Small algorithmic improvement of PartContraction::siblingPairFromRelatives

Use std::partial_sort for the non-exhaustive case. This is O(n) instead
of O(n*log(n)) in the size of the candidate list being sorted. (It
actually is O(n*log(k)), but k is constant 6 in the non-exhaustive
case).
This commit is contained in:
Geza Lore 2022-07-12 18:54:17 +01:00
parent 7e8bafd217
commit 87f1e06c41
1 changed files with 24 additions and 17 deletions

View File

@ -1541,25 +1541,32 @@ private:
if (shortestPrereqs.size() > PART_SIBLING_EDGE_LIMIT) break;
}
if (shortestPrereqs.empty()) return;
if (shortestPrereqs.size() <= 1) return;
std::sort(shortestPrereqs.begin(), shortestPrereqs.end(),
[way](const LogicMTask* ap, const LogicMTask* bp) {
const uint32_t aCp = ap->critPathCost(way) + ap->stepCost();
const uint32_t bCp = bp->critPathCost(way) + bp->stepCost();
if (aCp != bCp) return aCp < bCp;
return ap->id() < bp->id();
});
const auto cmp = [way](const LogicMTask* ap, const LogicMTask* bp) {
const uint32_t aCp = ap->critPathCost(way) + ap->stepCost();
const uint32_t bCp = bp->critPathCost(way) + bp->stepCost();
if (aCp != bCp) return aCp < bCp;
return ap->id() < bp->id();
};
// Don't make all NxN/2 possible pairs of prereqs, that's a lot
// to cart around. Just make a few pairs.
auto it = shortestPrereqs.cbegin();
for (unsigned i = 0; exhaustive || (i < 3); ++i) {
if (it == shortestPrereqs.cend()) break;
LogicMTask* const ap = *(it++);
if (it == shortestPrereqs.cend()) break;
LogicMTask* const bp = *(it++);
makeSiblingMC(ap, bp);
// Don't make all possible pairs of prereqs when not requested (non-exhaustive).
// Just make a few pairs.
constexpr size_t MAX_NONEXHAUSTIVE_PAIRS = 3;
size_t end; // End index of pairs to add to candidates (exclusive)
if (exhaustive || (shortestPrereqs.size() <= 2 * MAX_NONEXHAUSTIVE_PAIRS)) {
end = shortestPrereqs.size() & ~static_cast<size_t>(1); // Round down to even
std::sort(shortestPrereqs.begin(), shortestPrereqs.end(), cmp);
} else {
end = 2 * MAX_NONEXHAUSTIVE_PAIRS;
std::partial_sort(shortestPrereqs.begin(), shortestPrereqs.begin() + end,
shortestPrereqs.end(), cmp);
}
for (size_t i = 0; i < end; i += 2) {
makeSiblingMC(shortestPrereqs[i], shortestPrereqs[i + 1]);
}
}