Implement copy on write for sub problems.

This commit is contained in:
chriseth 2022-03-24 00:52:32 +01:00
parent b5aa534c43
commit 1b44668b34
2 changed files with 12 additions and 4 deletions

View File

@ -814,7 +814,7 @@ LPResult LPSolver::setState(SolvingState _state)
while (splitter) while (splitter)
{ {
auto&& [variables, constraints] = splitter.next(); auto&& [variables, constraints] = splitter.next();
SubProblem& problem = *m_subProblems.emplace_back(SubProblem()); SubProblem& problem = *m_subProblems.emplace_back(make_shared<SubProblem>());
solAssert(problem.dirty); solAssert(problem.dirty);
for (auto&& [i, included]: variables | ranges::views::enumerate) for (auto&& [i, included]: variables | ranges::views::enumerate)
if (included) if (included)
@ -854,13 +854,16 @@ void LPSolver::addConstraint(Constraint _constraint)
{ {
//cout << "Creating new sub problem." << endl; //cout << "Creating new sub problem." << endl;
// TODO we could find an empty spot for the pointer. // TODO we could find an empty spot for the pointer.
m_subProblems.emplace_back(SubProblem()); m_subProblems.emplace_back(make_shared<SubProblem>());
solAssert(m_subProblems.back()->dirty); solAssert(m_subProblems.back()->dirty);
touchedProblems.emplace(m_subProblems.size() - 1); touchedProblems.emplace(m_subProblems.size() - 1);
} }
for (size_t problemToErase: touchedProblems | ranges::views::tail | ranges::views::reverse) for (size_t problemToErase: touchedProblems | ranges::views::tail | ranges::views::reverse)
combineSubProblems(*touchedProblems.begin(), problemToErase); combineSubProblems(*touchedProblems.begin(), problemToErase);
addConstraintToSubProblem(*touchedProblems.begin(), _constraint); addConstraintToSubProblem(*touchedProblems.begin(), _constraint);
// cout << "subproblems: " << (
// m_subProblems | ranges::views::transform([&](auto&& p) { return !!p; })).size() <<
// " (total: " << m_subProblems.size() << endl;
//cout << "done" << endl; //cout << "done" << endl;
} }
@ -945,6 +948,9 @@ pair<LPResult, variant<Model, ReasonSet>> LPSolver::check()
void LPSolver::combineSubProblems(size_t _combineInto, size_t _combineFrom) void LPSolver::combineSubProblems(size_t _combineInto, size_t _combineFrom)
{ {
//cout << "Combining " << _combineInto << " <- " << _combineFrom << endl;
// TOOD creating a copy and setting dirty is on operation.
m_subProblems[_combineInto] = make_shared<SubProblem>(*m_subProblems[_combineInto]);
m_subProblems[_combineInto]->dirty = true; m_subProblems[_combineInto]->dirty = true;
for (size_t& item: m_subProblemsPerVariable) for (size_t& item: m_subProblemsPerVariable)
@ -960,7 +966,9 @@ void LPSolver::combineSubProblems(size_t _combineInto, size_t _combineFrom)
void LPSolver::addConstraintToSubProblem(size_t _subProblem, Constraint _constraint) void LPSolver::addConstraintToSubProblem(size_t _subProblem, Constraint _constraint)
{ {
m_subProblems[_subProblem] = make_shared<SubProblem>(*m_subProblems[_subProblem]);
SubProblem& problem = *m_subProblems[_subProblem]; SubProblem& problem = *m_subProblems[_subProblem];
problem.dirty = true;
for (auto const& [index, entry]: _constraint.data.enumerateTail()) for (auto const& [index, entry]: _constraint.data.enumerateTail())
if (entry) if (entry)
{ {
@ -968,7 +976,6 @@ void LPSolver::addConstraintToSubProblem(size_t _subProblem, Constraint _constra
m_subProblemsPerVariable[index] = _subProblem; m_subProblemsPerVariable[index] = _subProblem;
problem.variables.emplace(index); problem.variables.emplace(index);
} }
problem.dirty = true;
problem.removableConstraints.emplace_back(move(_constraint)); problem.removableConstraints.emplace_back(move(_constraint));
} }

View File

@ -210,7 +210,8 @@ private:
ReasonSet reasonSetForSubProblem(SubProblem const& _subProblem); ReasonSet reasonSetForSubProblem(SubProblem const& _subProblem);
std::map<size_t, rational> m_fixedVariables; std::map<size_t, rational> m_fixedVariables;
std::vector<std::optional<SubProblem>> m_subProblems; /// These use "copy on write".
std::vector<std::shared_ptr<SubProblem>> m_subProblems;
std::vector<size_t> m_subProblemsPerVariable; std::vector<size_t> m_subProblemsPerVariable;
std::vector<size_t> m_subProblemsPerConstraint; std::vector<size_t> m_subProblemsPerConstraint;
/// TODO also store the first infeasible subproblem? /// TODO also store the first infeasible subproblem?