rsmt2/solver.rs
1//! Wrapper around an SMT-LIB 2 compliant solver.
2//!
3//! The underlying solver runs in a separate process, communication goes through system pipes.
4
5use std::fs::File;
6use std::io::{BufReader, BufWriter, Read, Write};
7use std::process::{Child, ChildStdin, ChildStdout, Command, Stdio};
8
9use crate::{actlit::Actlit, parse::*, prelude::*, print::*};
10
11/// Promise for an asynchronous check-sat.
12pub struct FutureCheckSat {
13 _nothing: (),
14}
15fn future_check_sat() -> FutureCheckSat {
16 FutureCheckSat { _nothing: () }
17}
18
19/// Solver providing most of the SMT-LIB 2.5 commands.
20///
21/// Note the [`Self::tee`] function, which takes a file writer to which it will write
22/// everything sent to the solver.
23///
24/// # Check Success
25///
26/// By default, SMT-LIB 2 commands such as `declare-...`, `define-...`, `assert`, *etc.* are
27/// **silent** in the sense that, if successful, they do not cause the solver output anything. As a
28/// consequence, rmst2 does not check for errors after these commands are issued: since the command
29/// does not produce anything on success, how long should we wait for an error before deciding the
30/// command seems to have succeeded?
31///
32/// The problem is that when an error-producing command is issued, the actual error will only be
33/// seen by rsmt2 when it parses a result ---typically for a later `check-sat` or a `get-model`.
34/// This can be an issue when debugging, or when passing unchecked expressions or commands from
35/// downstream users.
36///
37/// ```rust
38/// # use rsmt2::Solver;
39/// let mut solver = Solver::default_z3(()).unwrap();
40/// // vvvvvvvvvvvvvvvvvvvvvv~~~~ probably gonna cause an error
41/// solver.assert(r#"(> "not an integer" 7)"#).unwrap();
42/// solver.assert("(= 0 1)").unwrap();
43/// solver.assert("(= 0 2)").unwrap();
44/// solver.assert("(= 0 3)").unwrap();
45/// solver.assert("(= 0 4)").unwrap();
46/// solver.assert("(= 0 5)").unwrap();
47/// // zero error so far
48/// let e = solver.check_sat().unwrap_err();
49/// # println!("{}", e);
50/// assert_eq!(
51/// &e.to_string(),
52/// "\
53/// solver error: \"line 3 column 25: \
54/// Sort mismatch at argument #1 for function (declare-fun > (Int Int) Bool) \
55/// supplied sort is String\"\
56/// ",
57/// );
58/// ```
59///
60/// SMT-LIB 2 has a `:print-success` option that forces all commands that do not produce a result
61/// to issue `success` on the solver's `stdout` when it's done handling them. This allows rsmt2 to
62/// notice and handle errors as soon as they happen, since it must check for `success` every time.
63///
64/// ```rust
65/// # use rsmt2::{Solver, SmtConf};
66/// let mut conf = SmtConf::default_z3();
67/// // activates `success`-printing
68/// conf.check_success();
69///
70/// let mut solver = Solver::new(conf, ()).unwrap();
71///
72/// // vvvvvvvvvvvvvvvvvvvvvv~~~~ probably gonna cause an error
73/// let res = solver.assert(r#"(> "not an integer" 7)"#);
74/// // did it?
75/// let e = res.unwrap_err();
76/// # println!("{}", e);
77/// assert_eq!(
78/// &e.to_string(),
79/// "\
80/// solver error: \"line 4 column 25: \
81/// Sort mismatch at argument #1 for function (declare-fun > (Int Int) Bool) \
82/// supplied sort is String\"\
83/// ",
84/// );
85/// solver.assert("(= 0 1)").unwrap();
86/// solver.assert("(= 0 2)").unwrap();
87/// solver.assert("(= 0 3)").unwrap();
88/// solver.assert("(= 0 4)").unwrap();
89/// solver.assert("(= 0 5)").unwrap();
90/// let is_sat = solver.check_sat().unwrap();
91/// ```
92///
93/// We can also activate `success`-checking at solver level.
94///
95/// ```rust
96/// # use rsmt2::{Solver};
97/// let mut solver = Solver::default_z3(()).unwrap();
98/// // activates `success` printing and checking.
99/// solver.print_success().unwrap();
100///
101/// // vvvvvvvvvvvvvvvvvvvvvv~~~~ probably gonna cause an error
102/// let res = solver.assert(r#"(> "not an integer" 7)"#);
103/// // did it?
104/// let e = res.unwrap_err();
105/// # println!("{}", e);
106/// assert_eq!(
107/// &e.to_string(),
108/// "\
109/// solver error: \"line 4 column 25: \
110/// Sort mismatch at argument #1 for function (declare-fun > (Int Int) Bool) \
111/// supplied sort is String\"\
112/// ",
113/// );
114/// ```
115///
116/// The downside is that rsmt2 will not parse `success` on all commands that do not produce
117/// results. This workflow is usually considered acceptable as parsing `success` is expected to be
118/// very, very cheap compared to whatever SMT check(s) the solver performs. This might not apply to
119/// users performing a lot of small, very fast checks; especially if you declare/define/assert a
120/// lot of things, as each declaration/definition/assertion causes to parse `success`.
121pub struct Solver<Parser> {
122 /// Solver configuration.
123 conf: SmtConf,
124 /// Actual solver process.
125 kid: Child,
126 /// Solver's stdin.
127 stdin: BufWriter<ChildStdin>,
128 /// Tee file writer.
129 tee: Option<BufWriter<File>>,
130 /// Parser on the solver's stdout.
131 smt_parser: RSmtParser,
132 /// User-defined parser.
133 parser: Parser,
134 /// Actlit counter.
135 actlit: usize,
136 /// If true, check for `success` every time.
137 check_success: bool,
138}
139
140impl<Parser> Write for Solver<Parser> {
141 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
142 if let Some(tee) = self.tee.as_mut() {
143 let _ = tee.write(buf);
144 }
145 self.stdin.write(buf)
146 }
147 fn flush(&mut self) -> ::std::io::Result<()> {
148 if let Some(tee) = self.tee.as_mut() {
149 let _ = tee.flush();
150 }
151 self.stdin.flush()
152 }
153}
154
155impl<Parser> Read for Solver<Parser> {
156 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
157 self.smt_parser.read(buf)
158 }
159}
160
161/// Writes something in both the solver and the tee-ed output.
162macro_rules! tee_write {
163 ($slf:expr, no_check |$w:ident| $($tail:tt)*) => ({
164 if let Some(ref mut $w) = $slf.tee {
165 $($tail)*;
166 writeln!($w)?;
167 $w.flush() ?
168 }
169 let $w = & mut $slf.stdin;
170 $($tail)*;
171 $w.flush()?;
172 });
173 ($slf:expr, |$w:ident| $($tail:tt)*) => ({
174 tee_write! { $slf, no_check |$w| $($tail)* }
175 if $slf.check_success {
176 $slf.check_success()?
177 }
178 });
179}
180
181impl<Parser> ::std::ops::Drop for Solver<Parser> {
182 fn drop(&mut self) {
183 let _ = self.kill();
184 ()
185 }
186}
187
188/// # Basic functions, not related to SMT-LIB.
189impl<Parser> Solver<Parser> {
190 /// Spawns the solver kid.
191 fn spawn(conf: &SmtConf) -> SmtRes<(Child, BufWriter<ChildStdin>, BufReader<ChildStdout>)> {
192 let mut kid = Command::new(
193 // Command.
194 conf.get_cmd(),
195 )
196 .args(
197 // Options.
198 conf.get_options(),
199 )
200 .stdin(Stdio::piped())
201 .stdout(Stdio::piped())
202 .stderr(Stdio::piped())
203 .spawn()
204 .chain_err::<_, ErrorKind>(|| {
205 format!(
206 "While spawning child process with {}",
207 conf.get_cmd().to_string()
208 )
209 .into()
210 })?;
211
212 let mut stdin_opt = None;
213 ::std::mem::swap(&mut stdin_opt, &mut kid.stdin);
214
215 let stdin = if let Some(inner) = stdin_opt {
216 BufWriter::new(inner)
217 } else {
218 bail!("could not retrieve solver's stdin")
219 };
220
221 let mut stdout_opt = None;
222 ::std::mem::swap(&mut stdout_opt, &mut kid.stdout);
223
224 let stdout = if let Some(inner) = stdout_opt {
225 BufReader::new(inner)
226 } else {
227 bail!("could not retrieve solver's stdout")
228 };
229
230 Ok((kid, stdin, stdout))
231 }
232
233 /// Constructor.
234 pub fn new(conf: SmtConf, parser: Parser) -> SmtRes<Self> {
235 // Constructing command and spawning kid.
236 let (kid, stdin, stdout) = Self::spawn(&conf)?;
237
238 let smt_parser = RSmtParser::new(stdout);
239
240 let tee = None;
241 let actlit = 0;
242
243 let mut slf = Solver {
244 kid,
245 stdin,
246 tee,
247 conf,
248 smt_parser,
249 parser,
250 actlit,
251 check_success: false,
252 };
253
254 if slf.conf.get_check_success() {
255 slf.print_success()?;
256 }
257 if slf.conf.get_models() {
258 slf.produce_models()?;
259 }
260 if slf.conf.get_unsat_cores() {
261 slf.produce_unsat_cores()?;
262 }
263
264 Ok(slf)
265 }
266
267 /// Creates a solver kid with the default z3 configuration.
268 ///
269 /// Mostly used in tests, same as `Self::new( SmtConf::z3(), parser )`.
270 pub fn z3(parser: Parser, cmd: impl Into<String>) -> SmtRes<Self> {
271 Self::new(SmtConf::z3(cmd), parser)
272 }
273 /// Creates a solver kid with the default cvc4 configuration.
274 ///
275 /// Mostly used in tests, same as `Self::new( SmtConf::z3(), parser )`.
276 pub fn cvc4(parser: Parser, cmd: impl Into<String>) -> SmtRes<Self> {
277 Self::new(SmtConf::cvc4(cmd), parser)
278 }
279 /// Creates a solver kid with the default yices 2 configuration.
280 ///
281 /// Mostly used in tests, same as `Self::new( SmtConf::yices_2(), parser )`.
282 pub fn yices_2(parser: Parser, cmd: impl Into<String>) -> SmtRes<Self> {
283 Self::new(SmtConf::yices_2(cmd), parser)
284 }
285
286 /// Creates a solver kid with the default z3 configuration and command.
287 ///
288 /// Mostly used in tests, same as `Self::new( SmtConf::default_z3(), parser )`.
289 ///
290 /// # Warning
291 ///
292 /// The command used to run a particular solver is up to the end-user. As such, it **does not
293 /// make sense** to use default commands for anything else than local testing. You should
294 /// explicitely pass the command to use with [`Self::z3`] instead.
295 pub fn default_z3(parser: Parser) -> SmtRes<Self> {
296 Self::new(SmtConf::default_z3(), parser)
297 }
298
299 /// Creates a solver kid with the default cvc4 configuration and
300 /// command.
301 ///
302 /// Mostly used in tests, same as `Self::new( SmtConf::default_z3(), parser )`.
303 ///
304 /// # Warning
305 ///
306 /// The command used to run a particular solver is up to the end-user. As such, it **does not
307 /// make sense** to use default commands for anything else than local testing. You should
308 /// explicitely pass the command to use with [`Self::cvc4`] instead.
309 pub fn default_cvc4(parser: Parser) -> SmtRes<Self> {
310 Self::new(SmtConf::default_cvc4(), parser)
311 }
312
313 /// Creates a solver kid with the default yices 2 configuration and
314 /// command.
315 ///
316 /// Mostly used in tests, same as `Self::new( SmtConf::default_yices_2(), parser )`.
317 ///
318 /// # Warning
319 ///
320 /// The command used to run a particular solver is up to the end-user. As such, it **does not
321 /// make sense** to use default commands for anything else than local testing. You should
322 /// explicitely pass the command to use with [`Self::yices_2`] instead.
323 pub fn default_yices_2(parser: Parser) -> SmtRes<Self> {
324 Self::new(SmtConf::default_yices_2(), parser)
325 }
326
327 /// Returns the configuration of the solver.
328 pub fn conf(&self) -> &SmtConf {
329 &self.conf
330 }
331
332 /// Forces the solver to write all communications to a file.
333 ///
334 /// - fails if the solver is already tee-ed;
335 /// - see also [`Self::path_tee`].
336 pub fn tee(&mut self, file: File) -> SmtRes<()> {
337 if self.tee.is_some() {
338 bail!("Trying to tee a solver that's already tee-ed")
339 }
340 let mut tee = BufWriter::with_capacity(1000, file);
341 write!(tee, "; Command:\n; > {}", self.conf.get_cmd())?;
342 for option in self.conf.get_options() {
343 write!(tee, " {}", option)?
344 }
345 writeln!(tee, "\n")?;
346 self.tee = Some(tee);
347 Ok(())
348 }
349
350 /// Forces the solver to write all communications to a file.
351 ///
352 /// - opens `file` with `create` and `write`;
353 /// - fails if the solver is already tee-ed;
354 /// - see also [`Self::tee`].
355 pub fn path_tee<P>(&mut self, path: P) -> SmtRes<()>
356 where
357 P: AsRef<::std::path::Path>,
358 {
359 use std::fs::OpenOptions;
360
361 let path: &::std::path::Path = path.as_ref();
362 let file = OpenOptions::new()
363 .create(true)
364 .write(true)
365 .truncate(true)
366 .open(path)
367 .chain_err(|| format!("while opening tee file `{}`", path.to_string_lossy()))?;
368 self.tee(file)
369 }
370
371 /// True if the solver is tee-ed.
372 pub fn is_teed(&self) -> bool {
373 self.tee.is_some()
374 }
375
376 /// Kills the solver kid.
377 ///
378 /// The windows version just prints `(exit)` on the kid's `stdin`. Anything else seems to cause
379 /// problems.
380 ///
381 /// This function is automatically called when the solver is dropped.
382 #[cfg(windows)]
383 pub fn kill(&mut self) -> SmtRes<()> {
384 let _ = writeln!(self.stdin, "(exit)");
385 let _ = self.stdin.flush();
386 let _ = self.kid.kill();
387 Ok(())
388 }
389 /// Kills the solver kid.
390 ///
391 /// The windows version just prints `(exit)` on the kid's `stdin`. Anything else seems to cause
392 /// problems.
393 ///
394 /// This function is automatically called when the solver is dropped.
395 #[cfg(not(windows))]
396 pub fn kill(&mut self) -> SmtRes<()> {
397 let _ = writeln!(self.stdin, "(exit)");
398 let _ = self.stdin.flush();
399 let _ = self.kid.kill();
400 let wait_time = std::time::Duration::from_millis(10);
401 for _ in 0..100 {
402 let join = self
403 .kid
404 .try_wait()
405 .chain_err(|| "waiting for child process to exit")?;
406 if join.is_some() {
407 return Ok(());
408 }
409 std::thread::sleep(wait_time);
410 }
411 bail!("failed to wait for child process to properly terminate")
412 }
413
414 /// Internal comment function.
415 #[inline]
416 fn cmt(file: &mut BufWriter<File>, blah: &str) -> SmtRes<()> {
417 for line in blah.lines() {
418 writeln!(file, "; {}", line)?
419 }
420 file.flush()?;
421 Ok(())
422 }
423
424 /// Prints a comment in the tee-ed file, if any.
425 #[inline]
426 pub fn comment_args(&mut self, args: std::fmt::Arguments) -> SmtRes<()> {
427 if let Some(ref mut file) = self.tee {
428 Self::cmt(file, &format!("{}", args))?
429 }
430 Ok(())
431 }
432
433 /// Prints a comment in the tee-ed file, if any (string version).
434 #[inline]
435 pub fn comment(&mut self, blah: &str) -> SmtRes<()> {
436 if let Some(ref mut file) = self.tee {
437 Self::cmt(file, blah)?
438 }
439 Ok(())
440 }
441}
442
443/// # Basic SMT-LIB parser-agnostic commands.
444impl<Parser> Solver<Parser> {
445 /// Activates print-success, see [here](Self#check-success).
446 #[inline]
447 pub fn print_success(&mut self) -> SmtRes<()> {
448 self.check_success = true;
449 self.set_option(":print-success", "true")
450 }
451 /// Parses a `success`, see [here](Self#check-success).
452 #[inline]
453 pub fn check_success(&mut self) -> SmtRes<()> {
454 self.smt_parser.success()
455 }
456 /// Activates unsat core production.
457 #[inline]
458 pub fn produce_unsat_cores(&mut self) -> SmtRes<()> {
459 self.set_option(":produce-unsat-cores", "true")
460 }
461 /// Activates model production.
462 #[inline]
463 pub fn produce_models(&mut self) -> SmtRes<()> {
464 self.set_option(":produce-models", "true")
465 }
466
467 /// Asserts an expression.
468 ///
469 /// # Examples
470 ///
471 /// ```rust
472 /// # use rsmt2::Solver;
473 /// let mut solver = Solver::default_z3(()).unwrap();
474 /// solver.assert("(= 0 1)").unwrap();
475 /// ```
476 #[inline]
477 pub fn assert(&mut self, expr: impl Expr2Smt) -> SmtRes<()> {
478 self.assert_with(expr, ())
479 }
480
481 /// Check-sat command, turns `unknown` results into errors.
482 ///
483 /// # See also
484 ///
485 /// - [`Self::print_check_sat`]
486 /// - [`Self::parse_check_sat`]
487 ///
488 /// If you want a more natural way to handle unknown results, see `parse_check_sat_or_unk`.
489 ///
490 /// # Examples
491 ///
492 /// ```rust
493 /// # use rsmt2::prelude::*;
494 /// let mut conf = SmtConf::default_z3();
495 /// conf.option("-t:10");
496 /// let mut solver = Solver::new(conf, ()).unwrap();
497 /// solver.declare_const("x", "Int").unwrap();
498 /// solver.declare_const("y", "Int").unwrap();
499 ///
500 /// solver.push(1).unwrap();
501 /// solver.assert("(= (+ x y) 0)").unwrap();
502 /// let maybe_sat = solver.check_sat().unwrap();
503 /// assert_eq! { maybe_sat, true }
504 /// solver.pop(1).unwrap();
505 ///
506 /// solver.assert("(= (+ (* x x y) (* y y x)) 7654321)").unwrap();
507 /// let sat_res = & solver.check_sat();
508 ///
509 /// match * sat_res {
510 /// Err(ref e) => match * e.kind() {
511 /// ::rsmt2::errors::ErrorKind::Unknown => (),
512 /// _ => panic!("expected unknown"),
513 /// },
514 /// Ok(res) => panic!("expected error: {:?}", res),
515 /// }
516 /// ```
517 pub fn check_sat(&mut self) -> SmtRes<bool> {
518 let future = self.print_check_sat()?;
519 self.parse_check_sat(future)
520 }
521
522 /// Check-sat command, turns `unknown` results in `None`.
523 ///
524 /// # See also
525 ///
526 /// - [`Self::parse_check_sat_or_unk`]
527 ///
528 /// # Examples
529 ///
530 /// ```rust
531 /// # use rsmt2::prelude::*;
532 /// let mut conf = SmtConf::default_z3();
533 /// conf.option("-t:10");
534 /// # let mut solver = Solver::new(conf, ()).unwrap();
535 /// solver.declare_const("x", "Int").unwrap();
536 /// solver.declare_const("y", "Int").unwrap();
537 ///
538 /// solver.push(1).unwrap();
539 /// solver.assert("(= (+ x y) 0)").unwrap();
540 /// let maybe_sat = solver.check_sat_or_unk().unwrap();
541 /// assert_eq! { maybe_sat, Some(true) }
542 /// solver.pop(1).unwrap();
543 ///
544 /// solver.assert("(= (+ (* x x y) (* y y x)) 7654321)").unwrap();
545 /// let maybe_sat = solver.check_sat_or_unk().unwrap();
546 /// // Unknown ~~~~~~~~~~~~~vvvv
547 /// assert_eq! { maybe_sat, None }
548 /// ```
549 pub fn check_sat_or_unk(&mut self) -> SmtRes<Option<bool>> {
550 let future = self.print_check_sat()?;
551 self.parse_check_sat_or_unk(future)
552 }
553
554 /// Resets the underlying solver. Restarts the kid process if no reset command is supported.
555 ///
556 /// # Examples
557 ///
558 /// ```rust
559 /// # use rsmt2::Solver;
560 /// let mut solver = Solver::default_z3(()).unwrap();
561 /// solver.assert("(= 0 1)").unwrap();
562 /// assert!(! solver.check_sat().unwrap());
563 /// solver.reset().unwrap();
564 /// assert!(solver.check_sat().unwrap());
565 /// ```
566 #[inline]
567 pub fn reset(&mut self) -> SmtRes<()> {
568 self.actlit = 0;
569 tee_write! {
570 self, |w| write_str(w, "(reset)\n") ?
571 }
572 Ok(())
573 }
574
575 /// Declares a new constant.
576 ///
577 /// # Examples
578 ///
579 /// ```rust
580 /// # use rsmt2::Solver;
581 /// let mut solver = Solver::default_z3(()).unwrap();
582 /// solver.declare_const("x", "Int").unwrap()
583 /// ```
584 #[inline]
585 pub fn declare_const(&mut self, symbol: impl Sym2Smt, out_sort: impl Sort2Smt) -> SmtRes<()> {
586 self.declare_const_with(symbol, out_sort, ())
587 }
588
589 /// Declares a new function symbol.
590 ///
591 /// ```rust
592 /// # use rsmt2::Solver;
593 /// let mut solver = Solver::default_z3(()).unwrap();
594 /// solver.declare_fun(
595 /// "my_symbol", & [ "Int", "Real", "Bool" ], "Bool"
596 /// ).unwrap()
597 /// ```
598 #[inline]
599 pub fn declare_fun<FunSym, Args, OutSort>(
600 &mut self,
601 symbol: FunSym,
602 args: Args,
603 out: OutSort,
604 ) -> SmtRes<()>
605 where
606 FunSym: Sym2Smt<()>,
607 OutSort: Sort2Smt,
608 Args: IntoIterator,
609 Args::Item: Sort2Smt,
610 {
611 self.declare_fun_with(symbol, args, out, ())
612 }
613
614 /// Defines a new constant function symbol.
615 ///
616 /// # Examples
617 ///
618 /// ```rust
619 /// # use rsmt2::Solver;
620 /// let mut solver = Solver::default_z3(()).unwrap();
621 /// solver.define_const(
622 /// "seven", "Int", "7"
623 /// ).unwrap()
624 /// ```
625 #[inline]
626 pub fn define_const(
627 &mut self,
628 symbol: impl Sym2Smt,
629 out: impl Sort2Smt,
630 body: impl Expr2Smt,
631 ) -> SmtRes<()> {
632 self.define_const_with(symbol, out, body, ())
633 }
634
635 /// Defines a new function symbol.
636 ///
637 /// # Examples
638 ///
639 /// ```rust
640 /// # use rsmt2::Solver;
641 /// let mut solver = Solver::default_z3(()).unwrap();
642 /// solver.define_fun(
643 /// "abs", & [ ("n", "Int") ], "Int", "(ite (< x 0) (- x) x)"
644 /// ).unwrap()
645 /// ```
646 #[inline]
647 pub fn define_fun<Args>(
648 &mut self,
649 symbol: impl Sym2Smt,
650 args: Args,
651 out: impl Sort2Smt,
652 body: impl Expr2Smt,
653 ) -> SmtRes<()>
654 where
655 Args: IntoIterator,
656 Args::Item: SymAndSort,
657 {
658 self.define_fun_with(symbol, args, out, body, ())
659 }
660
661 /// Pushes `n` layers on the assertion stack.
662 ///
663 /// - see also [`Self::pop`].
664 ///
665 /// Note that using [actlits][crate::actlit] is more efficient than push/pop, and is useable for
666 /// most push/pop use-cases.
667 ///
668 /// # Examples
669 ///
670 /// ```rust
671 /// # use rsmt2::Solver;
672 /// let mut solver = Solver::default_z3(()).unwrap();
673 /// solver.declare_const("x", "Int").unwrap();
674 /// solver.declare_const("y", "Int").unwrap();
675 /// solver.assert("(= x y)").unwrap();
676 /// let sat = solver.check_sat().unwrap();
677 /// assert!(sat);
678 ///
679 /// solver.push(1).unwrap();
680 /// solver.assert("(= x (+ x 1))").unwrap();
681 /// let sat = solver.check_sat().unwrap();
682 /// assert!(! sat);
683 /// solver.pop(1).unwrap();
684 ///
685 /// let sat = solver.check_sat().unwrap();
686 /// assert!(sat);
687 /// ```
688 #[inline]
689 pub fn push(&mut self, n: u8) -> SmtRes<()> {
690 tee_write! {
691 self, |w| writeln!(w, "(push {})", n) ?
692 }
693 Ok(())
694 }
695
696 /// Pops `n` layers off the assertion stack.
697 ///
698 /// - see also [`Self::push`].
699 ///
700 /// Note that using [actlits][crate::actlit] is more efficient than push/pop, and is useable for
701 /// most push/pop use-cases.
702 #[inline]
703 pub fn pop(&mut self, n: u8) -> SmtRes<()> {
704 tee_write! {
705 self, |w| writeln!(w, "(pop {})", n) ?
706 }
707 Ok(())
708 }
709
710 /// Check-sat assuming command, turns `unknown` results into errors.
711 ///
712 /// - see also [actlits][crate::actlit].
713 pub fn check_sat_assuming<Idents>(&mut self, idents: Idents) -> SmtRes<bool>
714 where
715 Idents: IntoIterator,
716 Idents::Item: Sym2Smt,
717 {
718 self.check_sat_assuming_with(idents, ())
719 }
720
721 /// Check-sat assuming command, turns `unknown` results into `None`.
722 ///
723 /// - see also [actlits][crate::actlit].
724 pub fn check_sat_assuming_or_unk<Ident, Idents>(
725 &mut self,
726 idents: Idents,
727 ) -> SmtRes<Option<bool>>
728 where
729 Idents: IntoIterator,
730 Idents::Item: Sym2Smt,
731 {
732 self.check_sat_assuming_or_unk_with(idents, ())
733 }
734
735 /// Sets the logic.
736 ///
737 /// # Examples
738 ///
739 /// ```rust
740 /// # use rsmt2::{SmtConf, Solver};
741 /// let mut solver = Solver::default_z3(()).unwrap();
742 /// solver.set_logic( ::rsmt2::Logic::QF_UF ).unwrap();
743 /// ```
744 #[inline]
745 pub fn set_logic(&mut self, logic: Logic) -> SmtRes<()> {
746 tee_write! {
747 self, |w| {
748 write_str(w, "(set-logic ")?;
749 logic.to_smt2(w, ())?;
750 write_str(w, ")\n") ?
751 }
752 }
753 Ok(())
754 }
755
756 /// Sets a custom logic.
757 ///
758 /// # Examples
759 ///
760 /// ```rust
761 /// # use rsmt2::{SmtConf, Solver};
762 /// let mut solver = Solver::default_z3(()).unwrap();
763 /// solver.set_custom_logic("QF_UFBV").unwrap();
764 /// ```
765 #[inline]
766 pub fn set_custom_logic(&mut self, logic: impl AsRef<str>) -> SmtRes<()> {
767 tee_write! {
768 self, |w| {
769 write_str(w, "(set-logic ")?;
770 write_str(w, logic.as_ref())?;
771 write_str(w, ")\n") ?
772 }
773 }
774 Ok(())
775 }
776
777 /// Defines a recursive function.
778 ///
779 /// # Examples
780 ///
781 /// ```rust
782 /// # use rsmt2::Solver;
783 /// let mut solver = Solver::default_z3(()).unwrap();
784 /// solver.define_fun_rec(
785 /// "abs", & [ ("n", "Int") ], "Int", "(ite (< x 0) (abs (- x)) x)"
786 /// ).unwrap()
787 /// ```
788 #[inline]
789 pub fn define_fun_rec<Args>(
790 &mut self,
791 symbol: impl Sym2Smt,
792 args: Args,
793 out: impl Sort2Smt,
794 body: impl Expr2Smt,
795 ) -> SmtRes<()>
796 where
797 Args: IntoIterator,
798 Args::Item: SymAndSort,
799 {
800 self.define_fun_rec_with(symbol, args, out, body, ())
801 }
802
803 /// Defines some (possibily mutually) recursive functions.
804 ///
805 /// # Examples
806 ///
807 /// ```rust
808 /// # use rsmt2::Solver;
809 /// let mut solver = Solver::default_z3(()).unwrap();
810 /// solver.define_funs_rec( & [
811 /// ("abs_1", [ ("n", "Int") ], "Int", "(ite (< x 0) (abs_2 (- x)) x)"),
812 /// ("abs_2", [ ("n", "Int") ], "Int", "(ite (< x 0) (abs_3 (- x)) x)"),
813 /// ("abs_3", [ ("n", "Int") ], "Int", "(ite (< x 0) (abs_1 (- x)) x)"),
814 /// ] ).unwrap()
815 /// ```
816 #[inline]
817 pub fn define_funs_rec<Defs>(&mut self, funs: Defs) -> SmtRes<()>
818 where
819 Defs: IntoIterator + Clone,
820 Defs::Item: FunDef,
821 {
822 self.define_funs_rec_with(funs, ())
823 }
824
825 /// Declares mutually recursive datatypes.
826 ///
827 /// A relatively recent version of z3 is recommended. Sort definition is a relatively expert
828 /// action, this function is a bit complex. The example below goes over how it works.
829 ///
830 /// # Examples
831 ///
832 /// ```rust
833 /// use rsmt2::print::{AdtDecl, AdtVariantField, AdtVariant};
834 ///
835 /// // Alright, so we're going to declare two mutually recursive sorts. It is easier to pack the
836 /// // sort-declaration data in custom types. If you want to declare a sort, you most likely
837 /// // already have a representation for it, so working on custom types is reasonable.
838 ///
839 /// // Notice that the `AdtDecl`, `AdtVariantField` and `AdtVariant` traits from `rsmt2::print::_`
840 /// // are in scope. This is what our custom types will need to generate to declare the sort.
841 ///
842 /// // We'll use static string slices for simplicity as `&str` implements all printing traits.
843 /// type Sym = &'static str;
844 /// type Sort = &'static str;
845 ///
846 /// // Let's start with the top-level sort type.
847 /// struct MySort {
848 /// // Name of the sort, for instance `List`.
849 /// sym: Sym,
850 /// // Symbol(s) for the type parameter(s), for instance `T` for `List<T>`. Must be a collection
851 /// // of known length, because rsmt2 needs to access the arity (number of type parameters).
852 /// args: Vec<Sym>,
853 /// // Body of the sort: its variants. For instance the `nil` and `cons` variants for `List<T>`.
854 /// variants: Vec<Variant>,
855 /// }
856 /// impl MySort {
857 /// // This thing build the actual definition expected by rsmt2. Its output is something that
858 /// // implements `AdtDecl` and can only live as long as the input ref to `self`.
859 /// fn as_decl<'me>(&'me self) -> impl AdtDecl + 'me {
860 /// // Check out rsmt2's documentation and you'll see that `AdtDecl` is already implemented for
861 /// // certain triplets.
862 /// (
863 /// // Symbol.
864 /// &self.sym,
865 /// // Sized collection of type-parameter symbols.
866 /// &self.args,
867 /// // Variant, collection of iterator over `impl AdtVariant` (see below).
868 /// self.variants.iter().map(Variant::as_decl),
869 /// )
870 /// }
871 ///
872 /// fn tree() -> Self {
873 /// Self {
874 /// sym: "Tree",
875 /// args: vec!["T"],
876 /// variants: vec![Variant::tree_leaf(), Variant::tree_node()],
877 /// }
878 /// }
879 /// }
880 ///
881 /// // Next up, variants. A variant is a symbol (*e.g.* `nil` or `cons` for `List<T>`) and some
882 /// // fields which describe the data stored in the variant.
883 /// struct Variant {
884 /// sym: Sym,
885 /// fields: Vec<Field>,
886 /// }
887 /// impl Variant {
888 /// // Variant declaration; again, `AdtVariant` is implemented for certain types of pairs.
889 /// fn as_decl<'me>(&'me self) -> impl AdtVariant + 'me {
890 /// (
891 /// // Symbol.
892 /// self.sym,
893 /// // Iterator over field declarations.
894 /// self.fields.iter().map(Field::as_decl),
895 /// )
896 /// }
897 ///
898 /// fn tree_leaf() -> Self {
899 /// Self {
900 /// sym: "leaf",
901 /// fields: vec![],
902 /// }
903 /// }
904 /// fn tree_node() -> Self {
905 /// Self {
906 /// sym: "node",
907 /// fields: vec![Field::tree_node_value(), Field::tree_node_children()],
908 /// }
909 /// }
910 /// }
911 ///
912 /// // A symbol and a sort: describes a piece of data in a variant with a symbol to retrieve it,
913 /// // *i.e.* the name of the field.
914 /// struct Field {
915 /// sym: Sym,
916 /// sort: Sort,
917 /// }
918 /// impl Field {
919 /// // As usual, `AdtVariantField` is implemented for certain pairs.
920 /// fn as_decl(&self) -> impl AdtVariantField {
921 /// (self.sym, self.sort)
922 /// }
923 ///
924 /// fn tree_node_value() -> Self {
925 /// Self {
926 /// sym: "value",
927 /// sort: "T",
928 /// }
929 /// }
930 /// fn tree_node_children() -> Self {
931 /// Self {
932 /// sym: "children",
933 /// sort: "(TreeList T)",
934 /// }
935 /// }
936 /// }
937 ///
938 /// let tree = MySort::tree();
939 ///
940 /// // Now this `tree` uses an non-existing `(TreeList T)` sort to store its children, let's declare
941 /// // it now.
942 ///
943 /// let nil = Variant {
944 /// sym: "nil",
945 /// fields: vec![],
946 /// };
947 /// let cons = Variant {
948 /// sym: "cons",
949 /// fields: vec![
950 /// Field {
951 /// sym: "car",
952 /// sort: "(Tree T)",
953 /// },
954 /// Field {
955 /// sym: "cdr",
956 /// sort: "(TreeList T)",
957 /// },
958 /// ],
959 /// };
960 /// let tree_list = MySort {
961 /// sym: "TreeList",
962 /// args: vec!["T"],
963 /// variants: vec![nil, cons],
964 /// };
965 ///
966 /// let mut solver = rsmt2::Solver::default_z3(()).unwrap();
967 ///
968 /// solver
969 /// // These sort are mutually recursive, `Solver::declare_datatypes` needs to declare them at the
970 /// // same time.
971 /// .declare_datatypes(&[tree.as_decl(), tree_list.as_decl()])
972 /// .unwrap();
973 ///
974 /// // That's it! Solver now knows these sorts and we can use them.
975 ///
976 /// solver.declare_const("t1", "(Tree Int)").unwrap();
977 /// solver.declare_const("t2", "(Tree Bool)").unwrap();
978 ///
979 /// solver.assert("(> (value t1) 20)").unwrap();
980 /// solver.assert("(not (is-leaf t2))").unwrap();
981 /// solver.assert("(not (value t2))").unwrap();
982 ///
983 /// let sat = solver.check_sat().unwrap();
984 /// assert!(sat);
985 /// ```
986 pub fn declare_datatypes<Defs>(&mut self, defs: Defs) -> SmtRes<()>
987 where
988 Defs: IntoIterator + Clone,
989 Defs::Item: AdtDecl,
990 {
991 tee_write! {
992 self, no_check |w| write!(w, "(declare-datatypes (") ?
993 }
994
995 for def in defs.clone() {
996 let sort_sym = def.adt_sym();
997 let arity = def.arity();
998 tee_write! {
999 self, no_check |w| {
1000 write!(w, " (")?;
1001 sort_sym.sym_to_smt2(w, ())?;
1002 write!(w, " {})", arity) ?
1003 }
1004 }
1005 }
1006
1007 tee_write! {
1008 self, no_check |w| write!(w, " ) (") ?
1009 }
1010
1011 for def in defs {
1012 let arity = def.arity();
1013 let args = def.adt_sort_args();
1014 let variants = def.adt_variants();
1015 tee_write! { self, |w| write!(w, " (")? };
1016 if arity > 0 {
1017 tee_write! { self, no_check |w| write!(w, "par (")? };
1018 for param in args {
1019 tee_write! { self, no_check |w| {
1020 write!(w, " ")?;
1021 param.sym_to_smt2(w, ())?;
1022 }}
1023 }
1024 tee_write! { self, no_check |w| write!(w, " ) (")? };
1025 }
1026
1027 for variant in variants {
1028 let sym = variant.sym();
1029 let mut fields = variant.fields();
1030 let first_field = fields.next();
1031
1032 tee_write! { self, no_check |w| write!(w, " ")? };
1033
1034 if first_field.is_some() {
1035 tee_write! { self, no_check |w| write!(w, "(")? };
1036 }
1037
1038 tee_write! { self, no_check |w| sym.sym_to_smt2(w, ())? };
1039
1040 if let Some(first) = first_field {
1041 for field in Some(first).into_iter().chain(fields) {
1042 let sym = field.field_sym();
1043 let sort = field.field_sort();
1044 tee_write! {
1045 self, no_check |w| {
1046 write!(w, " (")?;
1047 sym.sym_to_smt2(w, ())?;
1048 write!(w, " ")?;
1049 sort.sort_to_smt2(w)?;
1050 write!(w, ")")?;
1051 }
1052 }
1053 }
1054
1055 tee_write! { self, no_check |w| write!(w, ")")? };
1056 }
1057 }
1058
1059 tee_write! {
1060 self, no_check |w| {
1061 write!(w, " )")?;
1062
1063 if arity > 0 {
1064 write!(w, " )") ?
1065 }
1066 }
1067 }
1068 }
1069
1070 tee_write! {
1071 self, |w| writeln!(w, " ) )") ?
1072 }
1073
1074 Ok(())
1075 }
1076}
1077
1078/// # Basic SMT-LIB commands using the user's parser.
1079impl<Parser> Solver<Parser> {
1080 /// Get-model command.
1081 ///
1082 /// - See also [`Self::get_model_const`].
1083 ///
1084 /// # Examples
1085 ///
1086 /// ```rust
1087 /// use rsmt2::Solver;
1088 ///
1089 /// let mut solver = Solver::default_z3(()).unwrap();
1090 ///
1091 /// solver.declare_const("x", "Int").unwrap();
1092 /// solver.declare_const("y", "Int").unwrap();
1093 ///
1094 /// solver.assert("(= (+ x y) 0)").unwrap();
1095 ///
1096 /// let is_sat = solver.check_sat().unwrap();
1097 /// assert!(is_sat);
1098 /// let model = solver.get_model().unwrap();
1099 /// # println!("model: {:?}", model);
1100 ///
1101 /// let (mut x, mut y) = (None, None);
1102 /// // `x` and `y` are constants, *i.e.* functions taking no arguments. In general however,
1103 /// // `get_model` can yield functions. Hence the list of arguments
1104 /// // vvvv
1105 /// for (ident, args, sort, value) in model {
1106 /// assert!(args.is_empty());
1107 /// if ident == "x" {
1108 /// x = Some(isize::from_str_radix(&value, 10).expect("while parsing `x` value"))
1109 /// } else if ident == "y" {
1110 /// y = Some(isize::from_str_radix(&value, 10).expect("while parsing `y` value"))
1111 /// } else {
1112 /// panic!("unexpected ident `{}` in model", ident)
1113 /// }
1114 /// }
1115 ///
1116 /// let (x, y) = (x.expect("`x` not found in model"), y.expect("`y` not found in model"));
1117 /// assert_eq!(x + y, 0)
1118 /// ```
1119 pub fn get_model<Ident, Type, Value>(&mut self) -> SmtRes<Model<Ident, Type, Value>>
1120 where
1121 Parser: for<'p> IdentParser<Ident, Type, &'p mut RSmtParser>
1122 + for<'p> ModelParser<Ident, Type, Value, &'p mut RSmtParser>,
1123 {
1124 self.print_get_model()?;
1125 self.parse_get_model()
1126 }
1127
1128 /// Get-model command when all the symbols are nullary.
1129 ///
1130 /// - See also [`Self::get_model`].
1131 ///
1132 /// # Examples
1133 ///
1134 /// ```rust
1135 /// use rsmt2::Solver;
1136 ///
1137 /// let mut solver = Solver::default_z3(()).unwrap();
1138 ///
1139 /// solver.declare_const("x", "Int").unwrap();
1140 /// solver.declare_const("y", "Int").unwrap();
1141 ///
1142 /// solver.assert("(= (+ x y) 0)").unwrap();
1143 ///
1144 /// let is_sat = solver.check_sat().unwrap();
1145 /// assert!(is_sat);
1146 /// // We only have `x` and `y` which are constant symbols (functions with no arguments).
1147 /// // Using `get_model_const` instead of `get_model` will generate a model where symbols
1148 /// // have no arguments.
1149 /// let model = solver.get_model_const().unwrap();
1150 /// # println!("model: {:?}", model);
1151 ///
1152 /// let (mut x, mut y) = (None, None);
1153 /// // No list of arguments in the model, as opposed to models from `get_model`.
1154 /// // vvvvvvvvvvvvvvvvvv
1155 /// for (ident, sort, value) in model {
1156 /// if ident == "x" {
1157 /// x = Some(isize::from_str_radix(&value, 10).expect("while parsing `x` value"))
1158 /// } else if ident == "y" {
1159 /// y = Some(isize::from_str_radix(&value, 10).expect("while parsing `y` value"))
1160 /// } else {
1161 /// panic!("unexpected ident `{}` in model", ident)
1162 /// }
1163 /// }
1164 ///
1165 /// let (x, y) = (x.expect("`x` not found in model"), y.expect("`y` not found in model"));
1166 /// assert_eq!(x + y, 0)
1167 /// ```
1168 pub fn get_model_const<Ident, Type, Value>(&mut self) -> SmtRes<Vec<(Ident, Type, Value)>>
1169 where
1170 Parser: for<'p> IdentParser<Ident, Type, &'p mut RSmtParser>
1171 + for<'p> ModelParser<Ident, Type, Value, &'p mut RSmtParser>,
1172 {
1173 self.print_get_model()?;
1174 self.parse_get_model_const()
1175 }
1176
1177 /// Get-values command.
1178 ///
1179 /// - See also [`Self::get_values_with`].
1180 ///
1181 /// Notice that the input expression type and the output one have no reason
1182 /// to be the same.
1183 ///
1184 /// # Examples
1185 ///
1186 /// ```rust
1187 /// use rsmt2::Solver;
1188 ///
1189 /// let mut solver = Solver::default_z3(()).unwrap();
1190 ///
1191 /// solver.declare_const("x", "Int").unwrap();
1192 /// solver.declare_const("y", "Int").unwrap();
1193 ///
1194 /// solver.assert("(= (+ x y) 0)").unwrap();
1195 ///
1196 /// let is_sat = solver.check_sat().unwrap();
1197 /// assert!(is_sat);
1198 ///
1199 /// let vars = ["x", "y"];
1200 /// let values = solver.get_values(&vars).unwrap();
1201 /// # println!("values: {:?}", values);
1202 /// assert_eq!(vars.len(), values.len());
1203 ///
1204 /// let mut sum = 0;
1205 /// let mut values = values.into_iter();
1206 ///
1207 /// let (var, val) = values.next().unwrap();
1208 /// assert_eq!(var, "x");
1209 /// let val = isize::from_str_radix(&val, 10).expect("while parsing `x` value");
1210 /// sum += val;
1211 ///
1212 /// let (var, val) = values.next().unwrap();
1213 /// assert_eq!(var, "y");
1214 /// let val = isize::from_str_radix(&val, 10).expect("while parsing `y` value");
1215 /// sum += val;
1216 ///
1217 /// assert_eq!(values.next(), None);
1218 /// assert_eq!(sum, 0);
1219 /// ```
1220 pub fn get_values<Exprs, PExpr, PValue>(&mut self, exprs: Exprs) -> SmtRes<Vec<(PExpr, PValue)>>
1221 where
1222 Parser: for<'p> ExprParser<PExpr, (), &'p mut RSmtParser>
1223 + for<'p> ValueParser<PValue, &'p mut RSmtParser>,
1224 Exprs: IntoIterator,
1225 Exprs::Item: Expr2Smt,
1226 {
1227 self.get_values_with(exprs, ())
1228 .map_err(|e| self.conf.enrich_get_values_error(e))
1229 }
1230
1231 /// Get-values command.
1232 ///
1233 /// - See also [`Self::get_values`].
1234 ///
1235 /// Notice that the input expression type and the output one have no reason to be the same.
1236 pub fn get_values_with<Exprs, PExpr, PValue, Info>(
1237 &mut self,
1238 exprs: Exprs,
1239 info: Info,
1240 ) -> SmtRes<Vec<(PExpr, PValue)>>
1241 where
1242 Info: Copy,
1243 Parser: for<'p> ExprParser<PExpr, Info, &'p mut RSmtParser>
1244 + for<'p> ValueParser<PValue, &'p mut RSmtParser>,
1245 Exprs: IntoIterator,
1246 Exprs::Item: Expr2Smt<Info>,
1247 {
1248 self.print_get_values_with(exprs, info)?;
1249 self.parse_get_values_with(info)
1250 }
1251
1252 /// Get-unsat-core command.
1253 ///
1254 /// See also
1255 ///
1256 /// - [`NamedExpr`]: a convenient wrapper around any expression that gives it a name.
1257 ///
1258 /// # Examples
1259 ///
1260 /// ```rust
1261 /// use rsmt2::prelude::*;
1262 /// let mut conf = SmtConf::default_z3();
1263 /// conf.unsat_cores();
1264 /// # println!("unsat_cores: {}", conf.get_unsat_cores());
1265 ///
1266 /// let mut solver = Solver::new(conf, ()).unwrap();
1267 /// solver.declare_const("n", "Int").unwrap();
1268 /// solver.declare_const("m", "Int").unwrap();
1269 ///
1270 /// solver.assert("true").unwrap();
1271 ///
1272 /// let e_1 = "(> n 7)";
1273 /// let label_e_1 = "e_1";
1274 /// let named = NamedExpr::new(label_e_1, e_1);
1275 /// solver.assert(&named).unwrap();
1276 ///
1277 /// let e_2 = "(> m 0)";
1278 /// let label_e_2 = "e_2";
1279 /// let named = NamedExpr::new(label_e_2, e_2);
1280 /// solver.assert(&named).unwrap();
1281 ///
1282 /// let e_3 = "(< n 3)";
1283 /// let label_e_3 = "e_3";
1284 /// let named = NamedExpr::new(label_e_3, e_3);
1285 /// solver.assert(&named).unwrap();
1286 ///
1287 /// assert!(!solver.check_sat().unwrap());
1288 /// let core: Vec<String> = solver.get_unsat_core().unwrap();
1289 /// assert_eq!(core, vec![label_e_1, label_e_3]);
1290 /// ```
1291 pub fn get_unsat_core<Sym>(&mut self) -> SmtRes<Vec<Sym>>
1292 where
1293 Parser: for<'p> SymParser<Sym, &'p mut RSmtParser>,
1294 {
1295 self.print_get_unsat_core()?;
1296 self.parse_get_unsat_core()
1297 }
1298
1299 /// Get-interpolant command.
1300 ///
1301 /// - See [`Solver::get_interpolant_with`].
1302 pub fn get_interpolant<Expr>(
1303 &mut self,
1304 sym_1: impl Sym2Smt,
1305 sym_2: impl Sym2Smt,
1306 ) -> SmtRes<Expr>
1307 where
1308 Parser: for<'p> ExprParser<Expr, (), &'p mut RSmtParser>,
1309 {
1310 self.get_interpolant_with(sym_1, sym_2, ())
1311 }
1312
1313 /// Get-interpolant command.
1314 ///
1315 /// - See [Craig interpolation].
1316 /// - Only supported by recent versions of Z3.
1317 /// - This command is only legal after an `unsat` result.
1318 /// - The order of the two inputs symbols *matters*.
1319 ///
1320 /// Typically, you should assert two **named** formulas `f_1` and `f_2` (example
1321 /// [below](#examples)). Assuming you issue `check-sat` and get `unsat` (meaning `f_1 ⇒ ¬f_2`),
1322 /// then `get_interpolant(f_1, f_2)` produces a formula `I` such that
1323 /// - `f_1 ⇒ I`, *i.e.* `f_1 ∧ ¬I` is unsat,
1324 /// - `I ⇒ ¬f_2`, *i.e.* `I ∧ f_2` is unsat, and
1325 /// - `I` only mentions variables (constant symbols) that appear in both `f_1` and `f_2`.
1326 ///
1327 /// One way to think about interpolation is that `I` captures the reason for `f_1 ∧ f_2` being
1328 /// unsat from the *point of view of `f_1`*, in the sense that `I` does not contain variables
1329 /// that do not appear in `f_1`.
1330 ///
1331 /// # Examples
1332 ///
1333 /// ```rust
1334 /// use rsmt2::prelude::*;
1335 ///
1336 /// let mut solver = Solver::default_z3(()).unwrap();
1337 ///
1338 /// let (n, m) = ("n", "m");
1339 /// solver.declare_const(n, "Int").expect("declaring n");
1340 /// solver.declare_const(m, "Int").expect("declaring m");
1341 ///
1342 /// let f_1 = "(or (= (mod n 2) 0) (> n 42))";
1343 /// solver.assert(f_1.to_smt_named("f_1")).expect("assert f_1");
1344 ///
1345 /// let f_2 = "(and (< n m) (< m 9) (= (mod n 2) 1))";
1346 /// solver.assert(f_2.to_smt_named("f_2")).expect("assert f_2");
1347 ///
1348 /// let is_sat = solver.check_sat().unwrap();
1349 /// assert!(!is_sat);
1350 ///
1351 /// let interpolant: String = solver.get_interpolant("f_1", "f_2").unwrap();
1352 /// # println!("interpolant 1: {:?}", interpolant);
1353 /// assert_eq!(&interpolant, "(or (not (<= n 42)) (= (mod n 2) 0))");
1354 ///
1355 /// // Let's try again, but this time we switch the arguments of `get_interpolant`.
1356 /// let interpolant: String = solver.get_interpolant("f_2", "f_1").unwrap();
1357 /// # println!("interpolant 2: {:?}", interpolant);
1358 /// assert_eq!(&interpolant, "(and (= (mod (+ n 0) 2) 1) (<= n 7))");
1359 /// ```
1360 ///
1361 /// [Craig interpolation]: https://en.wikipedia.org/wiki/Craig_interpolation
1362 pub fn get_interpolant_with<Info, Expr>(
1363 &mut self,
1364 sym_1: impl Sym2Smt,
1365 sym_2: impl Sym2Smt,
1366 info: Info,
1367 ) -> SmtRes<Expr>
1368 where
1369 Parser: for<'p> ExprParser<Expr, Info, &'p mut RSmtParser>,
1370 {
1371 self.print_get_interpolant(sym_1, sym_2)?;
1372 let res = self.parse_get_interpolant(info);
1373 if res.is_err() && self.conf.style().is_z3() {
1374 res.chain_err(|| {
1375 format!(
1376 "`get-interpolant` is not legal for {} solvers",
1377 self.conf.style()
1378 )
1379 })
1380 .chain_err(|| format!("only Z3 supports `get-interpolant`"))
1381 } else {
1382 res
1383 }
1384 }
1385}
1386
1387/// # Actlit-Related Functions.
1388///
1389/// See the [`actlit` module][crate::actlit] for more details.
1390impl<Parser> Solver<Parser> {
1391 /// True if no actlits have been created since the last reset.
1392 ///
1393 /// See the [`actlit` module][crate::actlit] for more details.
1394 #[inline]
1395 fn has_actlits(&self) -> bool {
1396 self.actlit > 0
1397 }
1398
1399 /// Introduces a new actlit.
1400 ///
1401 /// See the [`actlit` module][crate::actlit] for more details.
1402 #[inline]
1403 pub fn get_actlit(&mut self) -> SmtRes<crate::actlit::Actlit> {
1404 let id = self.actlit;
1405 self.actlit += 1;
1406 let next_actlit = crate::actlit::Actlit::new(id);
1407 tee_write! {
1408 self, |w|
1409 write!(w, "(declare-fun ")?;
1410 next_actlit.write(w)?;
1411 writeln!(w, " () Bool)")?
1412 }
1413 Ok(next_actlit)
1414 }
1415
1416 /// Deactivates an activation literal, alias for `solver.set_actlit(actlit, false)`.
1417 ///
1418 /// See the [`actlit` module][crate::actlit] for more details.
1419 #[inline]
1420 pub fn de_actlit(&mut self, actlit: Actlit) -> SmtRes<()> {
1421 self.set_actlit(actlit, false)
1422 }
1423
1424 /// Forces the value of an actlit and consumes it.
1425 ///
1426 /// See the [`actlit` module][crate::actlit] for more details.
1427 #[inline]
1428 pub fn set_actlit(&mut self, actlit: Actlit, b: bool) -> SmtRes<()> {
1429 tee_write! {
1430 self, |w| {
1431 if b {
1432 write!(w, "(assert ") ?
1433 } else {
1434 write!(w, "(assert (not ") ?
1435 }
1436 actlit.write(w)?;
1437 if b {
1438 writeln!(w, ")") ?
1439 } else {
1440 writeln!(w, ") )") ?
1441 }
1442 }
1443 }
1444 ::std::mem::drop(actlit);
1445 Ok(())
1446 }
1447
1448 /// Asserts an expression without print information, guarded by an activation literal.
1449 ///
1450 /// See the [`actlit` module][crate::actlit] for more details.
1451 #[inline]
1452 pub fn assert_act(&mut self, actlit: &Actlit, expr: impl Expr2Smt) -> SmtRes<()> {
1453 self.assert_act_with(actlit, expr, ())
1454 }
1455
1456 /// Check-sat command with activation literals, turns `unknown` results into
1457 /// errors.
1458 pub fn check_sat_act<Actlits>(&mut self, actlits: Actlits) -> SmtRes<bool>
1459 where
1460 Actlits: IntoIterator,
1461 Actlits::Item: Sym2Smt,
1462 {
1463 let future = self.print_check_sat_act(actlits)?;
1464 self.parse_check_sat(future)
1465 }
1466
1467 /// Check-sat command with activation literals, turns `unknown` results in
1468 /// `None`.
1469 pub fn check_sat_act_or_unk<Actlits>(&mut self, actlits: Actlits) -> SmtRes<Option<bool>>
1470 where
1471 Actlits: IntoIterator,
1472 Actlits::Item: Sym2Smt,
1473 {
1474 let future = self.print_check_sat_act(actlits)?;
1475 self.parse_check_sat_or_unk(future)
1476 }
1477}
1478
1479/// # SMT-LIB asynchronous commands.
1480impl<Parser> Solver<Parser> {
1481 /// Prints a check-sat command.
1482 ///
1483 /// Allows to print the `check-sat` and get the result later, *e.g.* with
1484 /// [`Self::parse_check_sat`].
1485 ///
1486 /// # Examples
1487 ///
1488 /// ```rust
1489 /// use rsmt2::Solver;
1490 ///
1491 /// let mut solver = Solver::default_z3(()).unwrap();
1492 ///
1493 /// solver.declare_const("x", "Int").unwrap();
1494 /// solver.declare_const("y", "Int").unwrap();
1495 ///
1496 /// solver.assert("(= (+ x y) 0)").unwrap();
1497 ///
1498 /// let future = solver.print_check_sat().unwrap();
1499 /// // Do stuff while the solver works.
1500 /// let sat = solver.parse_check_sat(future).unwrap();
1501 /// assert!(sat);
1502 /// ```
1503 #[inline]
1504 pub fn print_check_sat(&mut self) -> SmtRes<FutureCheckSat> {
1505 tee_write! {
1506 self, no_check |w| write_str(w, "(check-sat)\n") ?
1507 }
1508 Ok(future_check_sat())
1509 }
1510
1511 /// Check-sat command, with actlits.
1512 ///
1513 /// See the [`actlit` module][crate::actlit] for more details.
1514 #[inline]
1515 pub fn print_check_sat_act<Actlits>(&mut self, actlits: Actlits) -> SmtRes<FutureCheckSat>
1516 where
1517 Actlits: IntoIterator,
1518 Actlits::Item: Sym2Smt,
1519 {
1520 match self.conf.get_check_sat_assuming() {
1521 Some(ref cmd) => {
1522 tee_write! {
1523 self, no_check |w| write!(w, "({} (", cmd) ?
1524 }
1525 for actlit in actlits {
1526 tee_write! {
1527 self, no_check |w| {
1528 write!(w, " ")?;
1529 actlit.sym_to_smt2(w, ()) ?
1530 }
1531 }
1532 }
1533 tee_write! {
1534 self, |w| write_str(w, ") )\n") ?
1535 }
1536 Ok(future_check_sat())
1537 }
1538 None => {
1539 let msg = format!("{} does not support check-sat-assuming", self.conf.desc());
1540 Err(msg.into())
1541 }
1542 }
1543 }
1544
1545 /// Parse the result of a check-sat, turns `unknown` results into errors.
1546 #[inline]
1547 pub fn parse_check_sat(&mut self, _: FutureCheckSat) -> SmtRes<bool> {
1548 if let Some(res) = self.smt_parser.check_sat()? {
1549 Ok(res)
1550 } else {
1551 Err(ErrorKind::Unknown.into())
1552 }
1553 }
1554
1555 /// Parse the result of a check-sat, turns `unknown` results into `None`.
1556 #[inline]
1557 pub fn parse_check_sat_or_unk(&mut self, _: FutureCheckSat) -> SmtRes<Option<bool>> {
1558 self.smt_parser.check_sat()
1559 }
1560
1561 /// Get-interpolant command.
1562 ///
1563 /// At the time of writing, only Z3 supports this command.
1564 #[inline]
1565 pub fn print_get_interpolant(
1566 &mut self,
1567 sym_1: impl Sym2Smt<()>,
1568 sym_2: impl Sym2Smt<()>,
1569 ) -> SmtRes<()> {
1570 tee_write! {
1571 self, no_check |w|
1572 write_str(w, "(get-interpolant ")?;
1573 sym_1.sym_to_smt2(w, ())?;
1574 write_str(w, " ")?;
1575 sym_2.sym_to_smt2(w, ())?;
1576 write_str(w, ")\n")?
1577 }
1578 Ok(())
1579 }
1580
1581 /// Get-model command.
1582 #[inline]
1583 fn print_get_model(&mut self) -> SmtRes<()> {
1584 tee_write! {
1585 self, no_check |w| write_str(w, "(get-model)\n") ?
1586 }
1587 Ok(())
1588 }
1589
1590 /// Get-assertions command.
1591 #[allow(dead_code)]
1592 fn print_get_assertions(&mut self) -> SmtRes<()> {
1593 tee_write! {
1594 self, no_check |w| write_str(w, "(get-assertions)\n") ?
1595 }
1596 Ok(())
1597 }
1598 /// Get-assignment command.
1599 #[allow(dead_code)]
1600 fn print_get_assignment(&mut self) -> SmtRes<()> {
1601 tee_write! {
1602 self, no_check |w| write_str(w, "(get-assignment)\n") ?
1603 }
1604 Ok(())
1605 }
1606 /// Get-unsat-assumptions command.
1607 #[allow(dead_code)]
1608 fn print_get_unsat_assumptions(&mut self) -> SmtRes<()> {
1609 tee_write! {
1610 self, no_check |w| write_str(w, "(get-unsat-assumptions)\n") ?
1611 }
1612 Ok(())
1613 }
1614 /// Get-proof command.
1615 #[allow(dead_code)]
1616 fn print_get_proof(&mut self) -> SmtRes<()> {
1617 tee_write! {
1618 self, no_check |w| write_str(w, "(get-proof)\n") ?
1619 }
1620 Ok(())
1621 }
1622 /// Get-unsat-core command.
1623 #[allow(dead_code)]
1624 fn print_get_unsat_core(&mut self) -> SmtRes<()> {
1625 tee_write! {
1626 self, no_check |w| write_str(w, "(get-unsat-core)\n") ?
1627 }
1628 Ok(())
1629 }
1630
1631 /// Get-values command.
1632 fn print_get_values_with<Exprs, Info>(&mut self, exprs: Exprs, info: Info) -> SmtRes<()>
1633 where
1634 Info: Copy,
1635 Exprs: IntoIterator,
1636 Exprs::Item: Expr2Smt<Info>,
1637 {
1638 tee_write! {
1639 self, no_check |w| write!(w, "(get-value (") ?
1640 }
1641 for e in exprs {
1642 tee_write! {
1643 self, no_check |w| {
1644 write_str(w, "\n ")?;
1645 e.expr_to_smt2(w, info) ?
1646 }
1647 }
1648 }
1649 tee_write! {
1650 self, no_check |w| write_str(w, "\n) )\n") ?
1651 }
1652 Ok(())
1653 }
1654
1655 /// Check-sat with assumptions command with unit info.
1656 pub fn print_check_sat_assuming<Idents>(&mut self, bool_vars: Idents) -> SmtRes<FutureCheckSat>
1657 where
1658 Idents: IntoIterator,
1659 Idents::Item: Sym2Smt,
1660 {
1661 self.print_check_sat_assuming_with(bool_vars, ())
1662 }
1663
1664 /// Check-sat with assumptions command.
1665 pub fn print_check_sat_assuming_with<Idents, Info>(
1666 &mut self,
1667 bool_vars: Idents,
1668 info: Info,
1669 ) -> SmtRes<FutureCheckSat>
1670 where
1671 Info: Copy,
1672 Idents: IntoIterator,
1673 Idents::Item: Sym2Smt<Info>,
1674 {
1675 match self.conf.get_check_sat_assuming() {
1676 Some(ref cmd) => {
1677 tee_write! {
1678 self, no_check |w| write!(w, "({} (\n ", cmd) ?
1679 }
1680 for sym in bool_vars {
1681 tee_write! {
1682 self, no_check |w| {
1683 write_str(w, " ")?;
1684 sym.sym_to_smt2(w, info) ?
1685 }
1686 }
1687 }
1688 tee_write! {
1689 self, no_check |w| write_str(w, "\n))\n") ?
1690 }
1691 Ok(future_check_sat())
1692 }
1693 None => {
1694 let msg = format!("{} does not support check-sat-assuming", self.conf.desc());
1695 Err(msg.into())
1696 }
1697 }
1698 }
1699
1700 /// Parse the result of a `get-model`.
1701 fn parse_get_model<Ident, Type, Value>(&mut self) -> SmtRes<Model<Ident, Type, Value>>
1702 where
1703 Parser: for<'p> IdentParser<Ident, Type, &'p mut RSmtParser>
1704 + for<'p> ModelParser<Ident, Type, Value, &'p mut RSmtParser>,
1705 {
1706 let has_actlits = self.has_actlits();
1707 let res = self.smt_parser.get_model(has_actlits, self.parser);
1708 if res.is_err() && !self.conf.get_models() {
1709 res.chain_err(|| {
1710 "\
1711 Note: model production is not active \
1712 for this SmtConf, see [`SmtConf::models`]\
1713 "
1714 })
1715 } else {
1716 res
1717 }
1718 }
1719
1720 /// Parses the result of a `get-unsat-core`.
1721 fn parse_get_unsat_core<Sym>(&mut self) -> SmtRes<Vec<Sym>>
1722 where
1723 Parser: for<'p> SymParser<Sym, &'p mut RSmtParser>,
1724 {
1725 self.smt_parser.get_unsat_core(self.parser)
1726 }
1727
1728 /// Parse the result of a `get-model` where all the symbols are nullary.
1729 fn parse_get_model_const<Ident, Type, Value>(&mut self) -> SmtRes<Vec<(Ident, Type, Value)>>
1730 where
1731 Parser: for<'p> IdentParser<Ident, Type, &'p mut RSmtParser>
1732 + for<'p> ModelParser<Ident, Type, Value, &'p mut RSmtParser>,
1733 {
1734 let has_actlits = self.has_actlits();
1735 let res = self.smt_parser.get_model_const(has_actlits, self.parser);
1736 if res.is_err() && !self.conf.get_models() {
1737 res.chain_err(|| {
1738 "\
1739 Note: model production is not active \
1740 for this SmtConf (`conf.models()`)\
1741 "
1742 })
1743 } else {
1744 res
1745 }
1746 }
1747
1748 /// Parse the result of a get-values.
1749 fn parse_get_values_with<Info, Expr, Val>(&mut self, info: Info) -> SmtRes<Vec<(Expr, Val)>>
1750 where
1751 Info: Copy,
1752 Parser: for<'p> ExprParser<Expr, Info, &'p mut RSmtParser>
1753 + for<'p> ValueParser<Val, &'p mut RSmtParser>,
1754 {
1755 let res = self.smt_parser.get_values(self.parser, info);
1756 if res.is_err() && !self.conf.get_models() {
1757 res.chain_err(|| {
1758 "Note: model production is not active \
1759 for this SmtConf (`conf.models()`)"
1760 })
1761 } else {
1762 res
1763 }
1764 }
1765
1766 /// Parses the result of a `get-interpolant`.
1767 fn parse_get_interpolant<Expr, Info>(&mut self, info: Info) -> SmtRes<Expr>
1768 where
1769 Parser: for<'p> ExprParser<Expr, Info, &'p mut RSmtParser>,
1770 {
1771 let mut res = self.smt_parser.get_interpolant(self.parser, info);
1772 if res.is_err() {
1773 if !self.conf.style().is_z3() {
1774 res = res.chain_err(|| {
1775 format!(
1776 "`{}` does not support interpolant production, only Z3 does",
1777 self.conf.style()
1778 )
1779 })
1780 } else if !self.conf.get_interpolants() {
1781 res = res.chain_err(|| format!("interpolant production is not active"))
1782 }
1783 }
1784 res
1785 }
1786}
1787
1788/// # Non-blocking commands.
1789impl<Parser: Send + 'static> Solver<Parser> {
1790 /// Asynchronous check-sat, see the [`asynch` module][crate::asynch] for details.
1791 ///
1792 /// This function is not `unsafe` in the sense that it **cannot** create undefined behavior.
1793 /// However, it is *unsafe* because the asynchronous check might end up running forever in the
1794 /// background, burning 100% CPU.
1795 pub unsafe fn async_check_sat_or_unk(&mut self) -> crate::asynch::CheckSatFuture<Parser> {
1796 crate::asynch::CheckSatFuture::new(self)
1797 }
1798}
1799
1800/// # Sort-related SMT-LIB commands.
1801impl<Parser> Solver<Parser> {
1802 /// Declares a new sort.
1803 ///
1804 /// # Examples
1805 ///
1806 /// ```rust
1807 /// # use rsmt2::Solver;
1808 /// let mut solver = Solver::default_z3(()).unwrap();
1809 /// solver.declare_sort("A", 0).unwrap();
1810 /// solver.declare_const("x", "A").unwrap();
1811 /// solver.declare_const("y", "A").unwrap();
1812 /// solver.declare_fun("f", & [ "A" ], "A").unwrap();
1813 /// solver.assert("(= (f (f x)) x)").unwrap();
1814 /// solver.assert("(= (f x) y)").unwrap();
1815 /// solver.assert("(not (= x y))").unwrap();
1816 /// let sat = solver.check_sat().unwrap();
1817 /// ```
1818 #[inline]
1819 pub fn declare_sort(&mut self, sort: impl Sort2Smt, arity: u8) -> SmtRes<()> {
1820 tee_write! {
1821 self, |w| {
1822 write_str(w, "(declare-sort ")?;
1823 sort.sort_to_smt2(w)?;
1824 writeln!(w, " {})", arity) ?
1825 }
1826 }
1827 Ok(())
1828 }
1829
1830 /// Defines a new sort.
1831 ///
1832 /// # Examples
1833 ///
1834 /// Note the use of [`Self::define_null_sort`] to avoid problems with empty arguments.
1835 ///
1836 /// ```rust
1837 /// # use rsmt2::Solver;
1838 /// let mut solver = Solver::default_z3(()).unwrap();
1839 /// solver.define_sort("MySet", & ["T"], "(Array T Bool)").unwrap();
1840 /// solver.define_null_sort("IList", "(List Int)").unwrap();
1841 /// solver.define_sort(
1842 /// "List-Set", & ["T"], "(Array (List T) Bool)"
1843 /// ).unwrap();
1844 /// solver.define_null_sort("I", "Int").unwrap();
1845 ///
1846 /// solver.declare_const("s1", "(MySet I)").unwrap();
1847 /// solver.declare_const("s2", "(List-Set Int)").unwrap();
1848 /// solver.declare_const("a", "I").unwrap();
1849 /// solver.declare_const("l", "IList").unwrap();
1850 ///
1851 /// solver.assert("(= (select s1 a) true)").unwrap();
1852 /// solver.assert("(= (select s2 l) false)").unwrap();
1853 /// let sat = solver.check_sat().unwrap();
1854 /// ```
1855 #[inline]
1856 pub fn define_sort<Args>(
1857 &mut self,
1858 sort_sym: impl Sym2Smt,
1859 args: Args,
1860 body: impl Sort2Smt,
1861 ) -> SmtRes<()>
1862 where
1863 Args: IntoIterator,
1864 Args::Item: Sort2Smt,
1865 {
1866 tee_write! {
1867 self, no_check |w| {
1868 write_str(w, "( define-sort ")?;
1869 sort_sym.sym_to_smt2(w, ())?;
1870 write_str(w, "\n ( ")?;
1871 }
1872 }
1873 for arg in args {
1874 tee_write! {
1875 self, no_check |w| {
1876 arg.sort_to_smt2(w)?;
1877 write_str(w, " ") ?
1878 }
1879 }
1880 }
1881 tee_write! {
1882 self, |w| {
1883 write_str(w, ")\n ")?;
1884 body.sort_to_smt2(w)?;
1885 write_str(w, "\n)\n") ?
1886 }
1887 }
1888 Ok(())
1889 }
1890
1891 /// Defines a new nullary sort.
1892 ///
1893 /// When using [`Self::define_sort`] with empty `args`, rust complains because it does not know
1894 /// what the `Arg` type parameter is. This function addresses this problem by not having
1895 /// arguments.
1896 #[inline]
1897 pub fn define_null_sort(&mut self, sym: impl Sym2Smt, body: impl Sort2Smt) -> SmtRes<()> {
1898 // Does not matter, just needs to implement `Sort2Smt`
1899 // vvvv
1900 self.define_sort(sym, None as Option<&str>, body)
1901 }
1902}
1903
1904/// # SMT-LIB commands vehiculating user information.
1905impl<Parser> Solver<Parser> {
1906 /// Declares a new constant.
1907 #[inline]
1908 pub fn declare_const_with<Info>(
1909 &mut self,
1910 symbol: impl Sym2Smt<Info>,
1911 out_sort: impl Sort2Smt,
1912 info: Info,
1913 ) -> SmtRes<()>
1914 where
1915 Info: Copy,
1916 {
1917 tee_write! {
1918 self, |w| {
1919 write_str(w, "(declare-const ")?;
1920 symbol.sym_to_smt2(w, info)?;
1921 write_str(w, " ")?;
1922 out_sort.sort_to_smt2(w)?;
1923 write_str(w, ")\n") ?
1924 }
1925 }
1926 Ok(())
1927 }
1928
1929 /// Declares a new function symbol.
1930 #[inline]
1931 pub fn declare_fun_with<Args, Info>(
1932 &mut self,
1933 symbol: impl Sym2Smt<Info>,
1934 args: Args,
1935 out: impl Sort2Smt,
1936 info: Info,
1937 ) -> SmtRes<()>
1938 where
1939 Info: Copy,
1940 Args: IntoIterator,
1941 Args::Item: Sort2Smt,
1942 {
1943 tee_write! {
1944 self, no_check |w| {
1945 write_str(w, "(declare-fun ")?;
1946 symbol.sym_to_smt2(w, info)?;
1947 write_str(w, " ( ") ?
1948 }
1949 }
1950 for arg in args {
1951 tee_write! {
1952 self, no_check |w| {
1953 arg.sort_to_smt2(w)?;
1954 write_str(w, " ") ?
1955 }
1956 }
1957 }
1958 tee_write! {
1959 self, |w| {
1960 write_str(w, ") ")?;
1961 out.sort_to_smt2(w)?;
1962 write_str(w, ")\n") ?
1963 }
1964 }
1965 Ok(())
1966 }
1967
1968 /// Defines a new constant.
1969 #[inline]
1970 pub fn define_const_with<Info>(
1971 &mut self,
1972 symbol: impl Sym2Smt<Info>,
1973 out_sort: impl Sort2Smt,
1974 body: impl Expr2Smt<Info>,
1975 info: Info,
1976 ) -> SmtRes<()>
1977 where
1978 Info: Copy,
1979 {
1980 tee_write! {
1981 self, |w| {
1982 write_str(w, "(define-const ")?;
1983 symbol.sym_to_smt2(w, info)?;
1984 write_str(w, " ")?;
1985 out_sort.sort_to_smt2(w)?;
1986 write_str(w, " ")?;
1987 body.expr_to_smt2(w, info)?;
1988 write_str(w, ")\n") ?
1989 }
1990 }
1991 Ok(())
1992 }
1993
1994 /// Defines a new function symbol.
1995 #[inline]
1996 pub fn define_fun_with<Args, Info>(
1997 &mut self,
1998 symbol: impl Sym2Smt<Info>,
1999 args: Args,
2000 out: impl Sort2Smt,
2001 body: impl Expr2Smt<Info>,
2002 info: Info,
2003 ) -> SmtRes<()>
2004 where
2005 Info: Copy,
2006 Args: IntoIterator,
2007 Args::Item: SymAndSort<Info>,
2008 {
2009 tee_write! {
2010 self, no_check |w| {
2011 write_str(w, "(define-fun ")?;
2012 symbol.sym_to_smt2(w, info)?;
2013 write_str(w, " ( ") ?
2014 }
2015 }
2016 for arg in args {
2017 let sym = arg.sym();
2018 let sort = arg.sort();
2019 tee_write! {
2020 self, no_check |w| {
2021 write_str(w, "(")?;
2022 sym.sym_to_smt2(w, info)?;
2023 write_str(w, " ")?;
2024 sort.sort_to_smt2(w)?;
2025 write_str(w, ") ") ?
2026 }
2027 }
2028 }
2029 tee_write! {
2030 self, |w| {
2031 write_str(w, ") ")?;
2032 out.sort_to_smt2(w)?;
2033 write_str(w, "\n ")?;
2034 body.expr_to_smt2(w, info)?;
2035 write_str(w, "\n)\n") ?
2036 }
2037 }
2038 Ok(())
2039 }
2040
2041 /// Defines some new (possibily mutually) recursive functions.
2042 pub fn define_funs_rec_with<Defs, Info>(&mut self, funs: Defs, info: Info) -> SmtRes<()>
2043 where
2044 Info: Copy,
2045 Defs: IntoIterator + Clone,
2046 Defs::Item: FunDef<Info>,
2047 {
2048 // Header.
2049 tee_write! {
2050 self, no_check |w| write_str(w, "(define-funs-rec (\n") ?
2051 }
2052
2053 // Signatures.
2054 for fun in funs.clone() {
2055 let sym = fun.fun_sym();
2056 let args = fun.args();
2057 let out = fun.out_sort();
2058
2059 tee_write! {
2060 self, no_check |w| {
2061 write_str(w, " (")?;
2062 sym.sym_to_smt2(w, info)?;
2063 write_str(w, " ( ") ?
2064 }
2065 }
2066
2067 for arg in args {
2068 tee_write! {
2069 self, no_check |w| {
2070 let sym = arg.sym();
2071 let sort = arg.sort();
2072 write_str(w, "(")?;
2073 sym.sym_to_smt2(w, info)?;
2074 write_str(w, " ")?;
2075 sort.sort_to_smt2(w)?;
2076 write_str(w, ") ") ?
2077 }
2078 }
2079 }
2080
2081 tee_write! {
2082 self, no_check |w| {
2083 write_str(w, ") ")?;
2084 out.sort_to_smt2(w)?;
2085 write_str(w, ")\n") ?
2086 }
2087 }
2088 }
2089 tee_write! {
2090 self, no_check |w| write_str(w, " ) (") ?
2091 }
2092
2093 // Bodies
2094 for fun in funs {
2095 let body = fun.body();
2096 tee_write! {
2097 self, no_check |w| {
2098 write_str(w, "\n ")?;
2099 body.expr_to_smt2(w, info) ?
2100 }
2101 }
2102 }
2103 tee_write! {
2104 self, |w| write_str(w, "\n )\n)\n") ?
2105 }
2106 Ok(())
2107 }
2108
2109 /// Defines a new recursive function.
2110 #[inline]
2111 pub fn define_fun_rec_with<Args, Info>(
2112 &mut self,
2113 symbol: impl Sym2Smt<Info>,
2114 args: Args,
2115 out: impl Sort2Smt,
2116 body: impl Expr2Smt<Info>,
2117 info: Info,
2118 ) -> SmtRes<()>
2119 where
2120 Info: Copy,
2121 Args: IntoIterator,
2122 Args::Item: SymAndSort<Info>,
2123 {
2124 // Header.
2125 tee_write! {
2126 self, no_check |w| write_str(w, "(define-fun-rec (\n") ?
2127 }
2128
2129 tee_write! {
2130 self, no_check |w| {
2131 // Signature.
2132 write_str(w, " (")?;
2133 symbol.sym_to_smt2(w, info)?;
2134 write_str(w, " ( ") ?
2135 }
2136 }
2137
2138 for arg in args {
2139 let sym = arg.sym();
2140 let sort = arg.sort();
2141 tee_write! {
2142 self, no_check |w| {
2143 write_str(w, "(")?;
2144 sym.sym_to_smt2(w, info)?;
2145 write_str(w, " ")?;
2146 sort.sort_to_smt2(w)?;
2147 write_str(w, ") ") ?
2148 }
2149 }
2150 }
2151
2152 tee_write! {
2153 self, |w| {
2154 write_str(w, ") ")?;
2155 out.sort_to_smt2(w)?;
2156 write_str(w, ")\n")?;
2157 write_str(w, " ) (")?;
2158
2159 // Body.
2160 write_str(w, "\n ")?;
2161 body.expr_to_smt2(w, info)?;
2162 write_str(w, "\n )\n)\n") ?
2163 }
2164 }
2165 Ok(())
2166 }
2167
2168 /// Asserts an expression with info, optional actlit and optional name.
2169 #[inline]
2170 pub fn full_assert<Act, Name, Info>(
2171 &mut self,
2172 actlit: Option<Act>,
2173 name: Option<Name>,
2174 expr: impl Expr2Smt<Info>,
2175 info: Info,
2176 ) -> SmtRes<()>
2177 where
2178 Info: Copy,
2179 Name: Sym2Smt,
2180 Act: Sym2Smt,
2181 {
2182 tee_write! {
2183 self, |w| {
2184 write_str(w, "(assert")?;
2185 if name.is_some() {
2186 write_str(w, " (!")?;
2187 }
2188 if let Some(actlit) = actlit.as_ref() {
2189 write_str(w, " (=> ")?;
2190 actlit.sym_to_smt2(w, ())?;
2191 }
2192 write_str(w, "\n ")?;
2193 expr.expr_to_smt2(w, info)?;
2194 write_str(w, "\n")?;
2195 if actlit.is_some() {
2196 write_str(w, ")")?;
2197 }
2198 if let Some(name) = name.as_ref() {
2199 write_str(w, " :named ")?;
2200 name.sym_to_smt2(w, ())?;
2201 write_str(w, ")")?;
2202 }
2203 write_str(w, ")\n")?;
2204 }
2205 }
2206 Ok(())
2207 }
2208
2209 /// Asserts an expression with an activation literal, a name and some print info.
2210 #[inline]
2211 pub fn named_assert_act_with<Info>(
2212 &mut self,
2213 actlit: &Actlit,
2214 name: impl Sym2Smt,
2215 expr: impl Expr2Smt<Info>,
2216 info: Info,
2217 ) -> SmtRes<()>
2218 where
2219 Info: Copy,
2220 {
2221 self.full_assert(Some(actlit), Some(name), expr, info)
2222 }
2223
2224 /// Asserts an expression with some print information, guarded by an activation literal.
2225 ///
2226 /// See the [`actlit` module][crate::actlit] for more details.
2227 #[inline]
2228 pub fn assert_act_with<Info>(
2229 &mut self,
2230 actlit: &Actlit,
2231 expr: impl Expr2Smt<Info>,
2232 info: Info,
2233 ) -> SmtRes<()>
2234 where
2235 Info: Copy,
2236 {
2237 let name: Option<&str> = None;
2238 self.full_assert(Some(actlit.as_ref()), name, expr, info)
2239 }
2240
2241 /// Asserts an expression with some print information.
2242 #[inline]
2243 pub fn assert_with<Info, Expr>(&mut self, expr: Expr, info: Info) -> SmtRes<()>
2244 where
2245 Info: Copy,
2246 Expr: Expr2Smt<Info>,
2247 {
2248 let name: Option<&str> = None;
2249 let act: Option<Actlit> = None;
2250 self.full_assert(act, name, expr, info)
2251 }
2252
2253 /// Asserts a named expression.
2254 #[inline]
2255 pub fn named_assert<Expr, Name>(&mut self, name: Name, expr: Expr) -> SmtRes<()>
2256 where
2257 Name: Sym2Smt,
2258 Expr: Expr2Smt,
2259 {
2260 let act: Option<Actlit> = None;
2261 self.full_assert(act, Some(name), expr, ())
2262 }
2263
2264 /// Asserts an expression with a name and some print info.
2265 #[inline]
2266 pub fn named_assert_with<Name, Info, Expr>(
2267 &mut self,
2268 name: Name,
2269 expr: Expr,
2270 info: Info,
2271 ) -> SmtRes<()>
2272 where
2273 Info: Copy,
2274 Expr: Expr2Smt<Info>,
2275 Name: Sym2Smt,
2276 {
2277 let act: Option<Actlit> = None;
2278 self.full_assert(act, Some(name), expr, info)
2279 }
2280
2281 /// Check-sat assuming command, turns `unknown` results into errors.
2282 pub fn check_sat_assuming_with<Info, Syms>(&mut self, idents: Syms, info: Info) -> SmtRes<bool>
2283 where
2284 Info: Copy,
2285 Syms: IntoIterator,
2286 Syms::Item: Sym2Smt<Info>,
2287 {
2288 let future = self.print_check_sat_assuming_with(idents, info)?;
2289 self.parse_check_sat(future)
2290 }
2291
2292 /// Check-sat assuming command, turns `unknown` results into `None`.
2293 pub fn check_sat_assuming_or_unk_with<Idents, Info>(
2294 &mut self,
2295 idents: Idents,
2296 info: Info,
2297 ) -> SmtRes<Option<bool>>
2298 where
2299 Info: Copy,
2300 Idents: IntoIterator,
2301 Idents::Item: Sym2Smt<Info>,
2302 {
2303 let future = self.print_check_sat_assuming_with(idents, info)?;
2304 self.parse_check_sat_or_unk(future)
2305 }
2306}
2307
2308/// # Other commands.
2309impl<Parser> Solver<Parser> {
2310 /// Set option command.
2311 #[inline]
2312 pub fn set_option<Value: ::std::fmt::Display>(
2313 &mut self,
2314 option: &str,
2315 value: Value,
2316 ) -> SmtRes<()> {
2317 match option {
2318 ":interactive_mode" => return Err("illegal set-option on interactive mode".into()),
2319 _ => (),
2320 };
2321 tee_write! {
2322 self, |w| writeln!(
2323 w, "(set-option {} {})", option, value
2324 ) ?
2325 }
2326 Ok(())
2327 }
2328
2329 /// Resets the assertions in the solver.
2330 #[inline]
2331 pub fn reset_assertions(&mut self) -> SmtRes<()> {
2332 tee_write! {
2333 self, |w| write_str(w, "(reset-assertions)\n") ?
2334 }
2335 Ok(())
2336 }
2337
2338 // // |===| Inspecting settings.
2339
2340 /// Get info command.
2341 #[inline]
2342 pub fn get_info(&mut self, flag: &str) -> SmtRes<()> {
2343 tee_write! {
2344 self, no_check |w| writeln!(w, "(get-info {})", flag) ?
2345 }
2346 Ok(())
2347 }
2348 /// Get option command.
2349 #[inline]
2350 pub fn get_option(&mut self, option: &str) -> SmtRes<()> {
2351 tee_write! {
2352 self, no_check |w| writeln!(w, "(get-option {})", option) ?
2353 }
2354 Ok(())
2355 }
2356
2357 // |===| Script information.
2358
2359 /// Set info command.
2360 #[inline]
2361 pub fn set_info(&mut self, attribute: &str) -> SmtRes<()> {
2362 tee_write! {
2363 self, |w| writeln!(w, "(set-info {})", attribute) ?
2364 }
2365 Ok(())
2366 }
2367 /// Echo command.
2368 #[inline]
2369 pub fn echo(&mut self, text: &str) -> SmtRes<()> {
2370 tee_write! {
2371 self, no_check |w| writeln!(w, "(echo \"{}\")", text) ?
2372 }
2373 Ok(())
2374 }
2375}