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