Is there a way to use z3 to convert a formula to CNF (using Tseitsin-style encoding)? I am looking for something like the simplify
command, but guaranteeing that the returned formula is CNF.
2 Answers
You can use the apply
command for doing it. We can provide arbitrary tactics/strategies to this command. For more information about tactics and strategies in Z3 4.0, check the tutorial http://rise4fun.com/Z3/tutorial/strategies
The command (help-tactic)
can be used to display all available tactics in Z3 4.0 and their parameters. The programmatic is more convenient to use and flexible. Here is a tutorial based on the new Python API: http://rise4fun.com/Z3Py/tutorial/strategies.
The same capabilities are available in the .Net and C/C++ APIs.
The following script demonstrates how to convert a formula into CNF using this framework:

- 21,065
- 2
- 47
- 53
-
Great, thanks! That is exactly what I was loooking for. Just one more remark: Is there also a way to get z3 to tell me the function each of the new variables (k!0, k!1, ...) represents? Or do I have to "reverse engineer" that from the Tseitin-axioms? – Georg Jun 12 '12 at 14:19
-
No, we do not provide this information. However, Z3 produces a "model converter" for every preprocessing step. A model converter is a function that converts the model for the resultant formula, into a model for the original formula. For CNF conversion, the model converter is simple. It just removes the interpretation of the new variables `k!0`, `k!1`, ... Thus, it does not provide the information you want. – Leonardo de Moura Jun 13 '12 at 03:31
-
Ok, thanks a lot anyway. Reconstructing the function for the new variables from the Tseitin axioms seems to be fairly straightforward anyway. – Georg Jun 13 '12 at 05:35
-
2@LeonardodeMoura The last link is broken ;( – RexYuan Nov 13 '17 at 09:16
The example link @Leonardo provided is broken now. Found the code using wayback machine. Posting it here so future seekers may make use of it:
(declare-const x Int)
(declare-const y Int)
(declare-const z Int)
(assert (iff (> x 0) (> y 0)))
(assert (or (and (= x 0) (= y 0)) (and (= x 1) (= y 1)) (and (= x 2) (= y 2))))
(assert (if (> x 0) (= y x) (= y (- x 1))))
(assert (> z (if (> x 0) (- x) x)))
(apply (then (! simplify :elim-and true) elim-term-ite tseitin-cnf))
(echo "Trying again without using distributivity...")
(apply (then (! simplify :elim-and true) elim-term-ite (! tseitin-cnf :distributivity false)))

- 1,075
- 1
- 10
- 20