Skip to content

[SMTChecker] Integration with CVC4#3840

Merged
axic merged 1 commit intodevelopfrom
smt_cvc4
Apr 17, 2018
Merged

[SMTChecker] Integration with CVC4#3840
axic merged 1 commit intodevelopfrom
smt_cvc4

Conversation

@leonardoalt
Copy link

Added CVC4 as an option for the SMT backend.
Z3 is still the default solver. CVC4 is only used when Z3 is not available.
The next step is writing the double solver that uses both and solves everything.

Copy link
Contributor

@axic axic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the interface selection is done as if (z3) use_z3 elseif (cvc4) use_cvc4 else use_file the cmake should be updated to reflect that.

e.g. no point displaying the warning if z3 is not found and no point checking for cvc4 if z3 is found.

@leonardoalt
Copy link
Author

This was done in preparation for the next step when we use both, in which case it makes sense to check for CVC4 even if Z3 is found.

@leonardoalt
Copy link
Author

leonardoalt commented Apr 7, 2018

@axic Committed a fix. Will squash after review is finished

@axic
Copy link
Contributor

axic commented Apr 9, 2018

The makefile changes look good.

return arguments[0];
}

CVC4::Type CVC4Interface::cvc4Sort(Sort _sort)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd name this toCVC4Sort.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, noticed this follows the naming convention from Z3. I may just do a name refactoring as a separate step on all three (z3, smt, cvc4).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the smt case?

Copy link
Contributor

@axic axic Apr 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(*)SMTLibInterface

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok now I remember ;)

return make_pair(result, values);
}

CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be a lot of copy paste from Z3, not sure how this could be shared between the two, but probably at least the arity map could be?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should have a validate() function on Expression which does the arity validation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, that could be shared. But same case with the rest, I mean, the goal of the function is exactly to translate from Solidity's internal SMT representation to Z3/CVC4

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was mostly wondering how could we improve this, but as part of this PR I would say the only thing to do is pull out the arity validation to the Expression class (and also check it in SMTLibInterface, which currently ignores it due to the flexible nature of S-expressions), that is a low hanging fruit.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok!

Copy link
Contributor

@axic axic Apr 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably bool valid() const is a good idea, which then can be part of an assertion (solAssert(_expr.isValid(), "") in the interfaces.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. I would also give as parameter the size of the arguments vector that the interface computed

}
}

pair<CheckResult, vector<string>> CVC4Interface::check(vector<Expression> const& _expressionsToEvaluate)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be a copy of Z3's too, but not sure how it can be refactored.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also not sure how this could be refactored. The structure is the same, and the changes are exactly what are actually different between Z3 and CVC4: results enums, methods to get models, etc

@leonardoalt leonardoalt force-pushed the smt_cvc4 branch 2 times, most recently from 5e573f0 to 970af2b Compare April 9, 2018 11:28

/// Checks whether this operator has a valid arity based on its name.
/// _arity is the arity of the operator in the solver.
bool isValid(unsigned _arity) const
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be only dependant on the internal state (m_arguments.size())?

Copy link
Author

@leonardoalt leonardoalt Apr 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is indirectly. Z3 and CVC4 interfaces use the _expr.arguments to build the correspondent vector of arguments. It should be the same in the end, it just checks one more thing this way

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it is better this way or to have two different assertions. I think this isValid would need to be local to the Expression class.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I'll make it two assertions then, to keep it safe

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I don't think we need the second assertion.

@axic
Copy link
Contributor

axic commented Apr 9, 2018

Also needs a changelog entry.

CVC4Interface::CVC4Interface():
m_solver(&m_context)
{
m_solver.setOption("produce-models", true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to just call reset here?

{
m_solver.assertFormula(toCVC4Expr(_expr));
}
catch (CVC4::TypeCheckingException &)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No space in front of &. Also should use const&.

@leonardoalt
Copy link
Author

Added Changelog entry and fixed review suggestions

@leonardoalt leonardoalt force-pushed the smt_cvc4 branch 2 times, most recently from 2aeec85 to f3ef945 Compare April 11, 2018 16:26
axic
axic previously approved these changes Apr 11, 2018
@axic
Copy link
Contributor

axic commented Apr 11, 2018

isValid had to be removed from smtlib, since its current version only checks for the "native operators". Both z3/cvc4 will try to replace constants and user functions before hitting isValid.

We may want to change that to only validate if the name is a native operator.

axic
axic previously approved these changes Apr 11, 2018
/// Checks whether this operator has a valid arity based on its name.
bool isValid() const
{
static std::map<std::string, unsigned> operatorsArity{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be const.

Expression& operator=(Expression const&) = default;
Expression& operator=(Expression&&) = default;

/// Checks whether this operator has a valid arity based on its name.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments suggests that the name of the function is not the best ;)

hasCorrectArity?

else if (n == "*")
return m_context.mkExpr(CVC4::kind::MULT, arguments[0], arguments[1]);
else if (n == "/")
return m_context.mkExpr(CVC4::kind::INTS_DIVISION_TOTAL, arguments[0], arguments[1]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember the rounding was weird for negative integers in z3, so I think we added a higher-level workaround for signed integers.

What happens at division by zero?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workaround was added in SMTChecker, right?

INTS_DIVISION_TOTAL returns 0 for division by 0.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, perfect!

@leonardoalt
Copy link
Author

@axic Good catch, SMTLib will return for constants before, but not for new functions.
We could have two functions in the SolverInterface, the one that was just introduced, and another one that does the same but is also fine with new functions. This way, Z3 and CVC4 can use the restricted version, since they know that at that point the expression should be a native operator.

@axic
Copy link
Contributor

axic commented Apr 17, 2018

@chriseth OK to merge now?

@leonardoalt can you rebase to ensure the changelog entry is in the right spot?

@chriseth
Copy link
Contributor

Ok to merge. We are basically still in the same mode, since we need to create the bugfix release, but let's try anyway.

@axic axic self-assigned this Apr 17, 2018
@axic
Copy link
Contributor

axic commented Apr 17, 2018

@chriseth rebased and applied changes, please review

void pop() override;

Expression newFunction(std::string _name, Sort _domain, Sort _codomain) override;
Expression newInteger(std::string _name) override;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should all use const& - don't they in the base class?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're also just string in the base class, where they're moved to the Expression

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry, I didn't see the move.

@axic axic merged commit f925747 into develop Apr 17, 2018
@axic axic deleted the smt_cvc4 branch April 17, 2018 13:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments