mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
simplify.
This commit is contained in:
parent
7cfc2f6a12
commit
4235933124
@ -244,11 +244,10 @@ pair<CheckResult, vector<string>> BooleanLPSolver::check(vector<Expression> cons
|
|||||||
// a cache.
|
// a cache.
|
||||||
// The current optimization is only for CDCL.
|
// The current optimization is only for CDCL.
|
||||||
lpSolvers.emplace_back(0, LPSolver{});
|
lpSolvers.emplace_back(0, LPSolver{});
|
||||||
lpSolvers.back().second.setState(lpState);
|
if (
|
||||||
|
lpSolvers.back().second.setState(lpState) == LPResult::Infeasible ||
|
||||||
//cout << "Boolean variables:" << joinHumanReadable(booleanVariables) << endl;
|
lpSolvers.back().second.check().first == LPResult::Infeasible
|
||||||
//cout << "Running LP solver on fixed constraints." << endl;
|
)
|
||||||
if (lpSolvers.back().second.check().first == LPResult::Infeasible)
|
|
||||||
{
|
{
|
||||||
cout << "----->>>>> unsatisfiable" << endl;
|
cout << "----->>>>> unsatisfiable" << endl;
|
||||||
return {CheckResult::UNSATISFIABLE, {}};
|
return {CheckResult::UNSATISFIABLE, {}};
|
||||||
|
@ -586,9 +586,8 @@ string SolvingState::toString() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<LPResult, variant<Model, ReasonSet>> SolvingStateSimplifier::simplify()
|
pair<LPResult, variant<map<size_t, rational>, ReasonSet>> SolvingStateSimplifier::simplify()
|
||||||
{
|
{
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
m_changed = false;
|
m_changed = false;
|
||||||
@ -605,7 +604,7 @@ pair<LPResult, variant<Model, ReasonSet>> SolvingStateSimplifier::simplify()
|
|||||||
}
|
}
|
||||||
while (m_changed);
|
while (m_changed);
|
||||||
|
|
||||||
return {LPResult::Unknown, move(m_model)};
|
return {LPResult::Unknown, move(m_fixedVariables)};
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<ReasonSet> SolvingStateSimplifier::removeFixedVariables()
|
optional<ReasonSet> SolvingStateSimplifier::removeFixedVariables()
|
||||||
@ -623,7 +622,8 @@ optional<ReasonSet> SolvingStateSimplifier::removeFixedVariables()
|
|||||||
if (upper != lower)
|
if (upper != lower)
|
||||||
continue;
|
continue;
|
||||||
set<size_t> reasons = bounds.lowerReasons + bounds.upperReasons;
|
set<size_t> reasons = bounds.lowerReasons + bounds.upperReasons;
|
||||||
m_model[m_state.variableNames.at(index)] = lower;
|
m_fixedVariables[index] = lower;
|
||||||
|
//cout << "Fixed " << m_state.variableNames.at(index) << " to " << ::toString(lower) << endl;
|
||||||
m_state.bounds[index] = {};
|
m_state.bounds[index] = {};
|
||||||
m_changed = true;
|
m_changed = true;
|
||||||
|
|
||||||
@ -723,7 +723,7 @@ void SolvingStateSimplifier::removeEmptyColumns()
|
|||||||
solAssert(!bounds.upper || bounds.upper >= 0);
|
solAssert(!bounds.upper || bounds.upper >= 0);
|
||||||
if (bounds.lower && bounds.upper)
|
if (bounds.lower && bounds.upper)
|
||||||
solAssert(*bounds.lower <= *bounds.upper);
|
solAssert(*bounds.lower <= *bounds.upper);
|
||||||
m_model[m_state.variableNames.at(i)] =
|
m_fixedVariables[i] =
|
||||||
bounds.upper ?
|
bounds.upper ?
|
||||||
*bounds.upper :
|
*bounds.upper :
|
||||||
*bounds.lower;
|
*bounds.lower;
|
||||||
@ -795,25 +795,22 @@ LPSolver::LPSolver(bool)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void LPSolver::setState(SolvingState _state)
|
LPResult LPSolver::setState(SolvingState _state)
|
||||||
{
|
{
|
||||||
//cout << "Set state:\n" << _state.toString() << endl;
|
//cout << "Set state:\n" << _state.toString() << endl;
|
||||||
m_state = move(_state);
|
m_state = move(_state);
|
||||||
m_subProblems.clear();
|
m_subProblems.clear();
|
||||||
|
|
||||||
normalizeRowLengths(m_state);
|
|
||||||
|
|
||||||
m_subProblemsPerVariable.resize(m_state.variableNames.size(), static_cast<size_t>(-1));
|
m_subProblemsPerVariable.resize(m_state.variableNames.size(), static_cast<size_t>(-1));
|
||||||
m_subProblemsPerConstraint.resize(m_state.constraints.size(), static_cast<size_t>(-1));
|
m_subProblemsPerConstraint.resize(m_state.constraints.size(), static_cast<size_t>(-1));
|
||||||
|
|
||||||
// TODO we should simplify, otherwise we get big problems with constanst that are used everywhere.
|
normalizeRowLengths(m_state);
|
||||||
|
auto&& [result, modelOrReasonSet] = SolvingStateSimplifier(m_state).simplify();
|
||||||
// TODO we could simplify, but then we need the option to answer 'infeasible' here.
|
if (result == LPResult::Infeasible)
|
||||||
// TODO assert that none of the constraints here have a reason set.
|
return result;
|
||||||
|
// We do not need to store reasons because at this point, we do not have any reasons yet.
|
||||||
// TODO if we eliminate variables, we should store their values and their reasons.
|
// We can add this and just need to store the reasons together with the variables.
|
||||||
// If new constraints come in, the eliminated variables have to be substituted.
|
m_fixedVariables = std::get<decltype(m_fixedVariables)>(modelOrReasonSet);
|
||||||
|
|
||||||
|
|
||||||
//cout << "Splitting..." << endl;
|
//cout << "Splitting..." << endl;
|
||||||
ProblemSplitter splitter(m_state);
|
ProblemSplitter splitter(m_state);
|
||||||
@ -833,15 +830,26 @@ void LPSolver::setState(SolvingState _state)
|
|||||||
//cout << m_subProblems.back()->state.toString() << endl;
|
//cout << m_subProblems.back()->state.toString() << endl;
|
||||||
}
|
}
|
||||||
//cout << "Done splitting." << endl;
|
//cout << "Done splitting." << endl;
|
||||||
|
return LPResult::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LPSolver::addConstraint(Constraint const& _constraint)
|
void LPSolver::addConstraint(Constraint _constraint)
|
||||||
{
|
{
|
||||||
//cout << "Adding constraint " << endl;
|
//cout << "Adding constraint " << endl;
|
||||||
set<size_t> touchedProblems;
|
set<size_t> touchedProblems;
|
||||||
for (auto const& [index, entry]: _constraint.data.enumerateTail())
|
for (auto const& [index, entry]: _constraint.data.enumerateTail())
|
||||||
if (entry && m_subProblemsPerVariable[index] != static_cast<size_t>(-1))
|
if (entry)
|
||||||
touchedProblems.emplace(m_subProblemsPerVariable[index]);
|
{
|
||||||
|
if (m_fixedVariables.count(index))
|
||||||
|
{
|
||||||
|
// This can directly lead to a conflict. We will check it later during the
|
||||||
|
// simplify run on the split problems.
|
||||||
|
_constraint.data[0] -= _constraint.data[index] * m_fixedVariables.at(index);
|
||||||
|
_constraint.data[index] = {};
|
||||||
|
}
|
||||||
|
else if (m_subProblemsPerVariable[index] != static_cast<size_t>(-1))
|
||||||
|
touchedProblems.emplace(m_subProblemsPerVariable[index]);
|
||||||
|
}
|
||||||
if (touchedProblems.empty())
|
if (touchedProblems.empty())
|
||||||
{
|
{
|
||||||
//cout << "Creating new sub problem." << endl;
|
//cout << "Creating new sub problem." << endl;
|
||||||
@ -861,15 +869,29 @@ pair<LPResult, variant<Model, ReasonSet>> LPSolver::check()
|
|||||||
//cout << "Checking" << endl;
|
//cout << "Checking" << endl;
|
||||||
for (auto&& [index, problem]: m_subProblems | ranges::views::enumerate)
|
for (auto&& [index, problem]: m_subProblems | ranges::views::enumerate)
|
||||||
{
|
{
|
||||||
if (!problem || !problem->dirty)
|
if (!problem)
|
||||||
|
continue;
|
||||||
|
if (!problem->dirty)
|
||||||
{
|
{
|
||||||
//cout << "not dirty" << endl;
|
solAssert(problem->result != LPResult::Infeasible);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cout << "Updating sub problem" << endl;
|
//cout << "Updating sub problem" << endl;
|
||||||
SolvingState state = stateFromSubProblem(index);
|
SolvingState state = stateFromSubProblem(index);
|
||||||
normalizeRowLengths(state);
|
normalizeRowLengths(state);
|
||||||
// TODO could also call simplify
|
|
||||||
|
// The simplify run is important because it detects conflicts
|
||||||
|
// due to fixed variables.
|
||||||
|
auto&& [result, modelOrReasonSet] = SolvingStateSimplifier(state).simplify();
|
||||||
|
if (result == LPResult::Infeasible)
|
||||||
|
{
|
||||||
|
problem->result = LPResult::Infeasible;
|
||||||
|
problem->model = {};
|
||||||
|
problem->dirty = false;
|
||||||
|
// TODO we could use the improved reason set above.
|
||||||
|
return {LPResult::Infeasible, reasonSetForSubProblem(*problem)};
|
||||||
|
}
|
||||||
//cout << state.toString() << endl;
|
//cout << state.toString() << endl;
|
||||||
|
|
||||||
if (auto conflict = boundsToConstraints(state))
|
if (auto conflict = boundsToConstraints(state))
|
||||||
|
@ -119,7 +119,7 @@ public:
|
|||||||
SolvingStateSimplifier(SolvingState& _state):
|
SolvingStateSimplifier(SolvingState& _state):
|
||||||
m_state(_state) {}
|
m_state(_state) {}
|
||||||
|
|
||||||
std::pair<LPResult, std::variant<Model, ReasonSet>> simplify();
|
std::pair<LPResult, std::variant<std::map<size_t, rational>, ReasonSet>> simplify();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Remove variables that have equal lower and upper bound.
|
/// Remove variables that have equal lower and upper bound.
|
||||||
@ -138,7 +138,7 @@ private:
|
|||||||
bool m_changed = false;
|
bool m_changed = false;
|
||||||
|
|
||||||
SolvingState& m_state;
|
SolvingState& m_state;
|
||||||
Model m_model;
|
std::map<size_t, rational> m_fixedVariables;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -180,8 +180,8 @@ class LPSolver
|
|||||||
public:
|
public:
|
||||||
explicit LPSolver(bool _supportModels = true);
|
explicit LPSolver(bool _supportModels = true);
|
||||||
|
|
||||||
void setState(SolvingState _state);
|
LPResult setState(SolvingState _state);
|
||||||
void addConstraint(Constraint const& _constraint);
|
void addConstraint(Constraint _constraint);
|
||||||
std::pair<LPResult, std::variant<Model, ReasonSet>> check();
|
std::pair<LPResult, std::variant<Model, ReasonSet>> check();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -202,6 +202,7 @@ private:
|
|||||||
SolvingState stateFromSubProblem(size_t _index) const;
|
SolvingState stateFromSubProblem(size_t _index) const;
|
||||||
ReasonSet reasonSetForSubProblem(SubProblem const& _subProblem);
|
ReasonSet reasonSetForSubProblem(SubProblem const& _subProblem);
|
||||||
|
|
||||||
|
std::map<size_t, rational> m_fixedVariables;
|
||||||
std::vector<std::optional<SubProblem>> m_subProblems;
|
std::vector<std::optional<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;
|
||||||
|
Loading…
Reference in New Issue
Block a user