implemert strict comparisons

This commit is contained in:
chriseth 2022-05-12 10:22:32 +02:00
parent b76d3a6a0d
commit 074969b5d9
3 changed files with 56 additions and 1 deletions

View File

@ -342,7 +342,7 @@ void BooleanLPSolver::addLetBindings(Expression const& _let, map<string, size_t>
bool isBool = binding.arguments.at(0).sort->kind == Kind::Bool; bool isBool = binding.arguments.at(0).sort->kind == Kind::Bool;
Expression var = declareInternalVariable(isBool); Expression var = declareInternalVariable(isBool);
newBindings.insert({binding.name, state().variables.at(var.name)}); newBindings.insert({binding.name, state().variables.at(var.name)});
addAssertion(var == binding.arguments.at(0)); addAssertion(var == binding.arguments.at(0), _letBindings);
} }
for (auto&& [name, varIndex]: newBindings) for (auto&& [name, varIndex]: newBindings)
_letBindings.insert({name, varIndex}); _letBindings.insert({name, varIndex});
@ -429,6 +429,7 @@ Literal BooleanLPSolver::negate(Literal const& _lit)
} }
else else
{ {
// TODO We can only do this if we know it is an integer!
// X > b // X > b
// -x < -b // -x < -b
// -x <= -b - 1 // -x <= -b - 1

View File

@ -47,6 +47,56 @@ struct Constraint
bool operator==(Constraint const& _other) const; bool operator==(Constraint const& _other) const;
}; };
/**
* A two-dimensional rational number "a + b*delta" that can be used to perform strict comparisons:
* x > 0 is transformed into x >= 1*delta, where delta is assumed to be "small". Its value
* is never explicitly computed / set, it is just a symbolic parameter.
*/
class RationalWithDelta
{
public:
RationalWithDelta(rational _x): m_main(move(_x)) {}
static RationalWithDelta delta()
{
RationalWithDelta x(0);
x.m_delta = 1;
return x;
}
RationalWithDelta& operator+=(RationalWithDelta const& _other)
{
m_main += _other.m_main;
m_delta += _other.m_delta;
return *this;
}
RationalWithDelta& operator*=(rational const& _factor)
{
m_main *= _factor;
m_delta *= _factor;
return *this;
}
bool operator<=(RationalWithDelta const& _other)
{
return std::tie(m_main, m_delta) <= std::tie(_other.m_main, _other.m_delta);
}
bool operator<(RationalWithDelta const& _other)
{
return std::tie(m_main, m_delta) < std::tie(_other.m_main, _other.m_delta);
}
bool operator==(RationalWithDelta const& _other)
{
return std::tie(m_main, m_delta) == std::tie(_other.m_main, _other.m_delta);
}
bool operator!=(RationalWithDelta const& _other)
{
return std::tie(m_main, m_delta) != std::tie(_other.m_main, _other.m_delta);
}
private:
rational m_main;
rational m_delta;
};
/** /**
* State used when solving an LP problem. * State used when solving an LP problem.
*/ */

View File

@ -249,15 +249,19 @@ smtutil::Expression ReasoningBasedSimplifier::encodeEVMBuiltin(
); );
*/ */
case evmasm::Instruction::LT: case evmasm::Instruction::LT:
// TODO use x <= y - 1 directly?
return booleanValue(arguments.at(0) < arguments.at(1)); return booleanValue(arguments.at(0) < arguments.at(1));
case evmasm::Instruction::SLT: case evmasm::Instruction::SLT:
// TODO use x <= y - 1 directly?
return booleanValue( return booleanValue(
twosComplementToUpscaledUnsigned(arguments.at(0)) + smtutil::Expression(bigint(1) << 256) < twosComplementToUpscaledUnsigned(arguments.at(0)) + smtutil::Expression(bigint(1) << 256) <
twosComplementToUpscaledUnsigned(arguments.at(1)) + smtutil::Expression(bigint(1) << 256) twosComplementToUpscaledUnsigned(arguments.at(1)) + smtutil::Expression(bigint(1) << 256)
); );
case evmasm::Instruction::GT: case evmasm::Instruction::GT:
// TODO use x >= y + 1 directly!
return booleanValue(arguments.at(0) > arguments.at(1)); return booleanValue(arguments.at(0) > arguments.at(1));
case evmasm::Instruction::SGT: case evmasm::Instruction::SGT:
// TODO use x >= y + 1 directly!
return booleanValue( return booleanValue(
twosComplementToUpscaledUnsigned(arguments.at(0)) + smtutil::Expression(bigint(1) << 256) > twosComplementToUpscaledUnsigned(arguments.at(0)) + smtutil::Expression(bigint(1) << 256) >
twosComplementToUpscaledUnsigned(arguments.at(1)) + smtutil::Expression(bigint(1) << 256) twosComplementToUpscaledUnsigned(arguments.at(1)) + smtutil::Expression(bigint(1) << 256)