-
Notifications
You must be signed in to change notification settings - Fork 13
Add RecAddDefinition and AddDefinition #106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Marked as draft as the curent implementation doesn't work due to #93. |
"""Define a new SMT recursive function with the given function declaration. | ||
Replaces constants in `args` with bound variables. | ||
>>> fact = Function('fact', IntSort(), IntSort()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to Z3, a recursive function must be declared using RecFunction
instead of Function
. If you try to add a definition using RecAddDefinition
to a function declared with Function
, Z3 will trigger an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had an implementation of RecFunction
but it turned out exactly the same as Function
. The reason for this distinction in z3 is because they have Z3_mk_func_decl
and Z3_mk_rec_func_decl
, here I believe we just need mkConst
to declare a function, recursive or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could add RecFunction
to maintain compatibility, but do you think we should restrict the usage of RecAddDefinition
like z3 does?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have discussed this in the cvc5 team and the conclusion is:
- we should support the same functionality that z3 does, so to have a
RecFunction
method - we can also have extra functionality, so it's OK to support the case where we use
Function
@caioraposo @daniel-larraz I would be interested in picking this PR up because my project uses this functionality and I'm trying to add a cvc5 backend in addition to z3. However I've reviewed the code and I'm stumped on Caio's comment here: #108 (comment) Potential solutions I see: 1. I believe that #2 is closer to what Z3 does however, are there other parts of the cvc5 pythonic API that already do anything similar? |
This would simplify things here but would change the other cvc5 APIs as well. I'll push some changes shortly with a solution. |
@caioraposo Your current implementation (399bd09) doesn't seem to behave correctly. Consider the following example:
Z3 returns |
What about storing the recursive definition in the Context object associated with the function body, and adding the definition to the Solver as soon as it is created? |
This commit adds support for defining functions (recursive or not) through defineFun and defineFunRec from the base API.
@caioraposo @daniel-larraz You can find a working snippet for using the "configure solver on creation" strategy here: https://github.com/mercari/cel-smt/blob/8c6fbf987c309c22d1d0da25bec9a382e9dec8c3/src/cel_smt/backend.py#L23 Please let me know if you'd like me to create a separate PR, I'm happy to do so. |
Can you confirm this works if you define a function after creating a solver? For example: s = SolverFor("UFLIA")
fact = Function('fact', IntSort(), IntSort())
n = Int('n')
RecAddDefinition(fact, n, If(n == 0, 1, n * fact(n - 1)))
s.add(Not(fact(5) == 120))
print(s.check()) I don't know how I could test your code. |
I think you can open a PR or point to your working branch, just to make it easier to review and test. It's difficult to know just based on the snippet you provided. |
This commit adds support for defining functions (recursive or not) through defineFun and defineFunRec from the base API.