-
Notifications
You must be signed in to change notification settings - Fork 114
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
Iterator for a solver #221
Comments
I saw this and thought it was interesting so I gave a crack at it. Instead of creating an iterator over solutions, I created an iterator over models. Two things that made this tricky is that The following is what I came up with: struct Z3Iterator<'ctx> {
solver: Solver<'ctx>,
vars: Vec<Dynamic<'ctx>>,
}
impl<'ctx> Iterator for Z3Iterator<'ctx> {
type Item = Model<'ctx>;
fn next(&mut self) -> Option<Self::Item> {
if let SatResult::Sat = self.solver.check() {
let model = self.solver.get_model()?;
let negating_equations = self
.vars
.iter()
.map(|ast| ast._eq(&model.eval(ast, true).unwrap()).not())
.collect::<Vec<_>>();
let invalidate_model = Bool::or(
self.solver.get_context(),
&negating_equations.iter().collect::<Vec<_>>(),
);
self.solver.assert(&invalidate_model);
Some(model)
} else {
None
}
}
}
fn solver(target: i64) -> Vec<(i64, i64)> {
let cfg = Config::new();
let ctx = Context::new(&cfg);
let solver = Solver::new(&ctx);
let x = ast::Int::new_const(&ctx, "x");
let y = ast::Int::new_const(&ctx, "y");
let n = ast::Int::from_i64(&ctx, target);
let equals = ast::Int::add(&ctx, &[&x, &y])._eq(&n);
solver.assert(&x.lt(&n));
solver.assert(&y.lt(&n));
solver.assert(&equals);
let iterator = Z3Iterator {
solver,
vars: vec![Dynamic::from_ast(&x), Dynamic::from_ast(&y)],
};
let solutions = iterator
.into_iter()
.map(|model| {
let x_val = model.eval(&x, true).unwrap();
let y_val = model.eval(&y, true).unwrap();
(x_val.as_i64().unwrap(), y_val.as_i64().unwrap())
})
.collect();
return solutions;
}
fn main() {
for (x, y) in solver(10) {
println!("x={}, y={}", x, y)
}
} |
Hi, firstly, thank you very much for this libary - it's great!
I'm not sure if this is a generic rust question, or something specific to this library. I am trying to create an 'iterator' of solutions from z3, so that I can access the solutions 'lazily' and in a composable way (For example taking only the first n solutions with
.take(n)
). However, I can't figure out the ergonomics of it, and I'm not sure if it will even be possible to make the lifetimes work.Here is a version of what I would like to do which doesn't use iterators, and just returns a
Vec
of all the solutions:Here is an attempt to figure out what it 'might' look like. But I cannot arrange it to satisfy the lifetime checker:
Is this something that could be done using this library? If not, is there something we could add to make it possible? Thank you!
The text was updated successfully, but these errors were encountered: