Return SelectionResult from KnapsackSolver

Returns a std::optional<SelectionResult> from KnapsackSolver instead of
using out parameters for the inputs set and selected value.
This commit is contained in:
Andrew Chow
2020-11-16 15:36:47 -05:00
parent 60d2ca72e3
commit 0ef6184575
4 changed files with 134 additions and 114 deletions

View File

@@ -236,10 +236,9 @@ static void ApproximateBestSubset(const std::vector<OutputGroup>& groups, const
}
}
bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& groups, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet)
std::optional<SelectionResult> KnapsackSolver(std::vector<OutputGroup>& groups, const CAmount& nTargetValue)
{
setCoinsRet.clear();
nValueRet = 0;
SelectionResult result(nTargetValue);
// List of values less than target
std::optional<OutputGroup> lowest_larger;
@@ -250,9 +249,8 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
for (const OutputGroup& group : groups) {
if (group.GetSelectionAmount() == nTargetValue) {
util::insert(setCoinsRet, group.m_outputs);
nValueRet += group.m_value;
return true;
result.AddInput(group);
return result;
} else if (group.GetSelectionAmount() < nTargetValue + MIN_CHANGE) {
applicable_groups.push_back(group);
nTotalLower += group.GetSelectionAmount();
@@ -263,17 +261,15 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
if (nTotalLower == nTargetValue) {
for (const auto& group : applicable_groups) {
util::insert(setCoinsRet, group.m_outputs);
nValueRet += group.m_value;
result.AddInput(group);
}
return true;
return result;
}
if (nTotalLower < nTargetValue) {
if (!lowest_larger) return false;
util::insert(setCoinsRet, lowest_larger->m_outputs);
nValueRet += lowest_larger->m_value;
return true;
if (!lowest_larger) return std::nullopt;
result.AddInput(*lowest_larger);
return result;
}
// Solve subset sum by stochastic approximation
@@ -290,13 +286,11 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
// or the next bigger coin is closer), return the bigger coin
if (lowest_larger &&
((nBest != nTargetValue && nBest < nTargetValue + MIN_CHANGE) || lowest_larger->GetSelectionAmount() <= nBest)) {
util::insert(setCoinsRet, lowest_larger->m_outputs);
nValueRet += lowest_larger->m_value;
result.AddInput(*lowest_larger);
} else {
for (unsigned int i = 0; i < applicable_groups.size(); i++) {
if (vfBest[i]) {
util::insert(setCoinsRet, applicable_groups[i].m_outputs);
nValueRet += applicable_groups[i].m_value;
result.AddInput(applicable_groups[i]);
}
}
@@ -311,7 +305,7 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
}
}
return true;
return result;
}
/******************************************************************************