3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-07 09:55:19 +00:00
z3/examples/python/tutorial/html/strategies-examples.htm
Nikolaj Bjorner e0a49dd556 html pages for z3 python tutorial
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2019-06-07 19:14:54 -07:00

351 lines
30 KiB
HTML

<html>
<head>
<title>Z3Py Strategies</title>
<link rel="StyleSheet" href="style.css" type="text/css">
</head>
<body>
<h1>Strategies</h1>
<p>
High-performance solvers, such as Z3, contain many tightly integrated, handcrafted heuristic
combinations of algorithmic proof methods. While these heuristic
combinations tend to be highly tuned for known classes of problems,
they may easily perform very badly on new classes of problems.
This issue is becoming increasingly pressing
as solvers begin to gain the attention of practitioners in diverse areas of science and engineering.
In many cases, changes to the solver heuristics can make a
tremendous difference.
</p>
<p>
In this tutorial we show how to create custom strategies using the basic building blocks
available in Z3. Z3Py and Z3 4.0 implement the ideas proposed in this <a target="_blank" href="http://research.microsoft.com/en-us/um/people/leonardo/strategy.pdf">article</a>.
</p>
<p>
Please send feedback, comments and/or corrections to <a href="mailto:leonardo@microsoft.com">leonardo@microsoft.com</a>.
Your comments are very valuable.
</p>
<h2>Introduction</h2>
<p>
Z3 implements a methodology for orchestrating reasoning
engines where "big" symbolic reasoning steps are represented as
functions known as <b>tactics</b>, and tactics are composed using
combinators known as <b>tacticals</b>. Tactics process sets of
formulas called <b>Goals</b>.
</p>
<p>
When a tactic is applied to some goal <tt>G</tt>, four different outcomes
are possible. The tactic succeeds in showing <tt>G</tt> to be satisfiable (i.e., feasible);
succeeds in showing <tt>G</tt> to be unsatisfiable (i.e., infeasible); produces a sequence of subgoals; or fails.
When reducing a goal <tt>G</tt> to a sequence of subgoals <tt>G1</tt>, ...,
<tt>Gn</tt>, we face the problem of model conversion.
A <b>model converter</b> construct a model for <tt>G</tt>
using a model for some subgoal <tt>Gi</tt>.
</p>
<p>In the following example, we create a goal <tt>g</tt> consisting of three formulas, and a tactic <tt>t</tt>
composed of two built-in tactics: <tt>simplify</tt> and <tt>solve-eqs</tt>. The tactic <tt>simplify</tt>
apply transformations equivalent to the ones found in the command <tt>simplify</tt>. The tactic <tt>solver-eqs</tt>
eliminate variables using Gaussian elimination. Actually, <tt>solve-eqs</tt> is not restricted only to linear arithmetic.
It can also eliminate arbitrary variables. Then, combinator <tt>Then</tt> applies <tt>simplify</tt> to the input goal
and <tt>solve-eqs</tt> to each subgoal produced by <tt>simplify</tt>. In this example, only one subgoal is produced.
</p>
<example pref="tactic.1"><html><body>
<div class="highlight"><pre><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">Reals</span><span class="p">(</span><span class="s">'x y'</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">Goal</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">,</span> <span class="n">y</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">,</span> <span class="n">x</span> <span class="o">==</span> <span class="n">y</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">print</span> <span class="n">g</span>
<span class="n">t1</span> <span class="o">=</span> <span class="n">Tactic</span><span class="p">(</span><span class="s">'simplify'</span><span class="p">)</span>
<span class="n">t2</span> <span class="o">=</span> <span class="n">Tactic</span><span class="p">(</span><span class="s">'solve-eqs'</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">Then</span><span class="p">(</span><span class="n">t1</span><span class="p">,</span> <span class="n">t2</span><span class="p">)</span>
<span class="k">print</span> <span class="n">t</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
</pre></div>
</body></html></example>
<p>In the example above, variable <tt>x</tt> is eliminated, and is not present the resultant goal.
</p>
<p>In Z3, we say a <b>clause</b> is any constraint of the form <tt>Or(f_1, ..., f_n)</tt>.
The tactic <tt>split-clause</tt> will select a clause <tt>Or(f_1, ..., f_n)</tt> in the input goal, and split it
<tt>n</tt> subgoals. One for each subformula <tt>f_i</tt>.
</p>
<example pref="tactic.2"><html><body>
<div class="highlight"><pre><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">Reals</span><span class="p">(</span><span class="s">'x y'</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">Goal</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Or</span><span class="p">(</span><span class="n">x</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">,</span> <span class="n">x</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">),</span> <span class="n">x</span> <span class="o">==</span> <span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">Tactic</span><span class="p">(</span><span class="s">'split-clause'</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">t</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">r</span><span class="p">:</span>
<span class="k">print</span> <span class="n">g</span>
</pre></div>
</body></html></example>
<h2>Tactics</h2>
<p>Z3 comes equipped with many built-in tactics.
The command <tt>describe_tactics()</tt> provides a short description of all built-in tactics.
</p>
<example pref="tactic.3"><html><body>
<div class="highlight"><pre><span class="n">describe_tactics</span><span class="p">()</span>
</pre></div>
</body></html></example>
<p>Z3Py comes equipped with the following tactic combinators (aka tacticals):
</p>
<ul>
<li> <tt>Then(t, s)</tt>
applies <tt>t</tt> to the input goal and <tt>s</tt>
to every subgoal produced by <tt>t</tt>.
</li>
<li> <tt>OrElse(t, s)</tt>
first applies <tt>t</tt> to the given goal,
if it fails then returns the result of <tt>s</tt> applied to the given goal.
</li>
<li> <tt>Repeat(t)</tt> Keep applying the given tactic until no subgoal is modified by it.
</li>
<li> <tt>Repeat(t, n)</tt> Keep applying the given tactic until no subgoal is modified by it, or
the number of iterations is greater than <tt>n</tt>.
</li>
<li> <tt>TryFor(t, ms)</tt> Apply tactic <tt>t</tt> to the input goal, if it does not return in
<tt>ms</tt> millisenconds, it fails.
</li>
<li> <tt>With(t, params)</tt> Apply the given tactic using the given parameters.
</li>
</ul>
<p>The following example demonstrate how to use these combinators.</p>
<example pref="tactic.4"><html><body>
<div class="highlight"><pre><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">=</span> <span class="n">Reals</span><span class="p">(</span><span class="s">'x y z'</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">Goal</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Or</span><span class="p">(</span><span class="n">x</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">1</span><span class="p">),</span>
<span class="n">Or</span><span class="p">(</span><span class="n">y</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="n">y</span> <span class="o">==</span> <span class="mi">1</span><span class="p">),</span>
<span class="n">Or</span><span class="p">(</span><span class="n">z</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="n">z</span> <span class="o">==</span> <span class="mi">1</span><span class="p">),</span>
<span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="o">+</span> <span class="n">z</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">)</span>
<span class="c"># Split all clauses"</span>
<span class="n">split_all</span> <span class="o">=</span> <span class="n">Repeat</span><span class="p">(</span><span class="n">OrElse</span><span class="p">(</span><span class="n">Tactic</span><span class="p">(</span><span class="s">'split-clause'</span><span class="p">),</span>
<span class="n">Tactic</span><span class="p">(</span><span class="s">'skip'</span><span class="p">)))</span>
<span class="k">print</span> <span class="n">split_all</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="n">split_at_most_2</span> <span class="o">=</span> <span class="n">Repeat</span><span class="p">(</span><span class="n">OrElse</span><span class="p">(</span><span class="n">Tactic</span><span class="p">(</span><span class="s">'split-clause'</span><span class="p">),</span>
<span class="n">Tactic</span><span class="p">(</span><span class="s">'skip'</span><span class="p">)),</span>
<span class="mi">1</span><span class="p">)</span>
<span class="k">print</span> <span class="n">split_at_most_2</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="c"># Split all clauses and solve equations</span>
<span class="n">split_solve</span> <span class="o">=</span> <span class="n">Then</span><span class="p">(</span><span class="n">Repeat</span><span class="p">(</span><span class="n">OrElse</span><span class="p">(</span><span class="n">Tactic</span><span class="p">(</span><span class="s">'split-clause'</span><span class="p">),</span>
<span class="n">Tactic</span><span class="p">(</span><span class="s">'skip'</span><span class="p">))),</span>
<span class="n">Tactic</span><span class="p">(</span><span class="s">'solve-eqs'</span><span class="p">))</span>
<span class="k">print</span> <span class="n">split_solve</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
</pre></div>
</body></html></example>
<p>In the tactic <tt>split_solver</tt>, the tactic <tt>solve-eqs</tt> discharges all but one goal.
Note that, this tactic generates one goal: the empty goal which is trivially satisfiable (i.e., feasible) </p>
<p>The list of subgoals can be easily traversed using the Python <tt>for</tt> statement.</p>
<example pref="tactic.5"><html><body>
<div class="highlight"><pre><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">=</span> <span class="n">Reals</span><span class="p">(</span><span class="s">'x y z'</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">Goal</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Or</span><span class="p">(</span><span class="n">x</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">1</span><span class="p">),</span>
<span class="n">Or</span><span class="p">(</span><span class="n">y</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="n">y</span> <span class="o">==</span> <span class="mi">1</span><span class="p">),</span>
<span class="n">Or</span><span class="p">(</span><span class="n">z</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="n">z</span> <span class="o">==</span> <span class="mi">1</span><span class="p">),</span>
<span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="o">+</span> <span class="n">z</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">)</span>
<span class="c"># Split all clauses"</span>
<span class="n">split_all</span> <span class="o">=</span> <span class="n">Repeat</span><span class="p">(</span><span class="n">OrElse</span><span class="p">(</span><span class="n">Tactic</span><span class="p">(</span><span class="s">'split-clause'</span><span class="p">),</span>
<span class="n">Tactic</span><span class="p">(</span><span class="s">'skip'</span><span class="p">)))</span>
<span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">split_all</span><span class="p">(</span><span class="n">g</span><span class="p">):</span>
<span class="k">print</span> <span class="n">s</span>
</pre></div>
</body></html></example>
<p>A tactic can be converted into a solver object using the method <tt>solver()</tt>.
If the tactic produces the empty goal, then the associated solver returns <tt>sat</tt>.
If the tactic produces a single goal containing <tt>False</tt>, then the solver returns <tt>unsat</tt>.
Otherwise, it returns <tt>unknown</tt>.
</p>
<example pref="tactic.6"><html><body>
<div class="highlight"><pre><span class="n">bv_solver</span> <span class="o">=</span> <span class="n">Then</span><span class="p">(</span><span class="s">'simplify'</span><span class="p">,</span>
<span class="s">'solve-eqs'</span><span class="p">,</span>
<span class="s">'bit-blast'</span><span class="p">,</span>
<span class="s">'sat'</span><span class="p">)</span><span class="o">.</span><span class="n">solver</span><span class="p">()</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">BitVecs</span><span class="p">(</span><span class="s">'x y'</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
<span class="n">solve_using</span><span class="p">(</span><span class="n">bv_solver</span><span class="p">,</span> <span class="n">x</span> <span class="o">|</span> <span class="n">y</span> <span class="o">==</span> <span class="mi">13</span><span class="p">,</span> <span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span>
</pre></div>
</body></html></example>
<p>In the example above, the tactic <tt>bv_solver</tt> implements a basic bit-vector solver using equation solving,
bit-blasting, and a propositional SAT solver. Note that, the command <tt>Tactic</tt> is suppressed.
All Z3Py combinators automatically invoke <tt>Tactic</tt> command if the argument is a string.
Finally, the command <tt>solve_using</tt> is a variant of the <tt>solve</tt> command where the first
argument specifies the solver to be used.
</p>
<p>In the following example, we use the solver API directly instead of the command <tt>solve_using</tt>.
We use the combinator <tt>With</tt> to configure our little solver. We also include the tactic <tt>aig</tt>
which tries to compress Boolean formulas using And-Inverted Graphs.
</p>
<example pref="tactic.7"><html><body>
<div class="highlight"><pre><span class="n">bv_solver</span> <span class="o">=</span> <span class="n">Then</span><span class="p">(</span><span class="n">With</span><span class="p">(</span><span class="s">'simplify'</span><span class="p">,</span> <span class="n">mul2concat</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span>
<span class="s">'solve-eqs'</span><span class="p">,</span>
<span class="s">'bit-blast'</span><span class="p">,</span>
<span class="s">'aig'</span><span class="p">,</span>
<span class="s">'sat'</span><span class="p">)</span><span class="o">.</span><span class="n">solver</span><span class="p">()</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">BitVecs</span><span class="p">(</span><span class="s">'x y'</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
<span class="n">bv_solver</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="mi">32</span> <span class="o">+</span> <span class="n">y</span> <span class="o">==</span> <span class="mi">13</span><span class="p">,</span> <span class="n">x</span> <span class="o">&amp;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">,</span> <span class="n">y</span> <span class="o">&gt;</span> <span class="o">-</span><span class="mi">100</span><span class="p">)</span>
<span class="k">print</span> <span class="n">bv_solver</span><span class="o">.</span><span class="n">check</span><span class="p">()</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">bv_solver</span><span class="o">.</span><span class="n">model</span><span class="p">()</span>
<span class="k">print</span> <span class="n">m</span>
<span class="k">print</span> <span class="n">x</span><span class="o">*</span><span class="mi">32</span> <span class="o">+</span> <span class="n">y</span><span class="p">,</span> <span class="s">"=="</span><span class="p">,</span> <span class="n">m</span><span class="o">.</span><span class="n">evaluate</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="mi">32</span> <span class="o">+</span> <span class="n">y</span><span class="p">)</span>
<span class="k">print</span> <span class="n">x</span> <span class="o">&amp;</span> <span class="n">y</span><span class="p">,</span> <span class="s">"=="</span><span class="p">,</span> <span class="n">m</span><span class="o">.</span><span class="n">evaluate</span><span class="p">(</span><span class="n">x</span> <span class="o">&amp;</span> <span class="n">y</span><span class="p">)</span>
</pre></div>
</body></html></example>
<p>The tactic <tt>smt</tt> wraps the main solver in Z3 as a tactic.</p>
<example pref="tactic.8"><html><body>
<div class="highlight"><pre><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">Ints</span><span class="p">(</span><span class="s">'x y'</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">Tactic</span><span class="p">(</span><span class="s">'smt'</span><span class="p">)</span><span class="o">.</span><span class="n">solver</span><span class="p">()</span>
<span class="n">s</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">print</span> <span class="n">s</span><span class="o">.</span><span class="n">check</span><span class="p">()</span>
<span class="k">print</span> <span class="n">s</span><span class="o">.</span><span class="n">model</span><span class="p">()</span>
</pre></div>
</body></html></example>
<p>Now, we show how to implement a solver for integer arithmetic using SAT. The solver is complete
only for problems where every variable has a lower and upper bound.
</p>
<example pref="tactic.9"><html><body>
<div class="highlight"><pre><span class="n">s</span> <span class="o">=</span> <span class="n">Then</span><span class="p">(</span><span class="n">With</span><span class="p">(</span><span class="s">'simplify'</span><span class="p">,</span> <span class="n">arith_lhs</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">som</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span>
<span class="s">'normalize-bounds'</span><span class="p">,</span> <span class="s">'lia2pb'</span><span class="p">,</span> <span class="s">'pb2bv'</span><span class="p">,</span>
<span class="s">'bit-blast'</span><span class="p">,</span> <span class="s">'sat'</span><span class="p">)</span><span class="o">.</span><span class="n">solver</span><span class="p">()</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">=</span> <span class="n">Ints</span><span class="p">(</span><span class="s">'x y z'</span><span class="p">)</span>
<span class="n">solve_using</span><span class="p">(</span><span class="n">s</span><span class="p">,</span>
<span class="n">x</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">,</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">,</span>
<span class="n">y</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">,</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">,</span>
<span class="n">z</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">,</span> <span class="n">z</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">,</span>
<span class="mi">3</span><span class="o">*</span><span class="n">y</span> <span class="o">+</span> <span class="mi">2</span><span class="o">*</span><span class="n">x</span> <span class="o">==</span> <span class="n">z</span><span class="p">)</span>
<span class="c"># It fails on the next example (it is unbounded)</span>
<span class="n">s</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>
<span class="n">solve_using</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">3</span><span class="o">*</span><span class="n">y</span> <span class="o">+</span> <span class="mi">2</span><span class="o">*</span><span class="n">x</span> <span class="o">==</span> <span class="n">z</span><span class="p">)</span>
</pre></div>
</body></html></example>
<p>
Tactics can be combined with solvers. For example, we can apply a tactic to a goal, produced a set of subgoals,
then select one of the subgoals and solve it using a solver. The next example demonstrates how to do that, and how to
use model converters to convert a model for a subgoal into a model for the original goal.
</p>
<example pref="tactic.10"><html><body>
<div class="highlight"><pre><span class="n">t</span> <span class="o">=</span> <span class="n">Then</span><span class="p">(</span><span class="s">'simplify'</span><span class="p">,</span>
<span class="s">'normalize-bounds'</span><span class="p">,</span>
<span class="s">'solve-eqs'</span><span class="p">)</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">=</span> <span class="n">Ints</span><span class="p">(</span><span class="s">'x y z'</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">Goal</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="mi">10</span><span class="p">,</span> <span class="n">y</span> <span class="o">==</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">3</span><span class="p">,</span> <span class="n">z</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">t</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="c"># r contains only one subgoal</span>
<span class="k">print</span> <span class="n">r</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">Solver</span><span class="p">()</span>
<span class="n">s</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">r</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">print</span> <span class="n">s</span><span class="o">.</span><span class="n">check</span><span class="p">()</span>
<span class="c"># Model for the subgoal</span>
<span class="k">print</span> <span class="n">s</span><span class="o">.</span><span class="n">model</span><span class="p">()</span>
<span class="c"># Model for the original goal</span>
<span class="k">print</span> <span class="n">r</span><span class="o">.</span><span class="n">convert_model</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">model</span><span class="p">())</span>
</pre></div>
</body></html></example>
<h2>Probes</h2>
<p>
<b>Probes</b> (aka formula measures) are evaluated over goals.
Boolean expressions over them can be built using relational operators and Boolean connectives.
The tactic <tt>FailIf(cond)</tt> fails if the given goal does not satisfy the condition <tt>cond</tt>.
Many numeric and Boolean measures are available in Z3Py. The command <tt>describe_probes()</tt> provides the list of
all built-in probes.
</p>
<example pref="probe.1"><html><body>
<div class="highlight"><pre><span class="n">describe_probes</span><span class="p">()</span>
</pre></div>
</body></html></example>
<p>In the following example, we build a simple tactic using <tt>FailIf</tt>. It also shows that a probe can be applied directly
to a goal.</p>
<example pref="probe.2"><html><body>
<div class="highlight"><pre><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">=</span> <span class="n">Reals</span><span class="p">(</span><span class="s">'x y z'</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">Goal</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="o">+</span> <span class="n">z</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">Probe</span><span class="p">(</span><span class="s">'num-consts'</span><span class="p">)</span>
<span class="k">print</span> <span class="s">"num-consts:"</span><span class="p">,</span> <span class="n">p</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">FailIf</span><span class="p">(</span><span class="n">p</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">t</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="k">except</span> <span class="n">Z3Exception</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"tactic failed"</span>
<span class="k">print</span> <span class="s">"trying again..."</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">Goal</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">print</span> <span class="n">t</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
</pre></div>
</body></html></example>
<p>Z3Py also provides the combinator (tactical) <tt>If(p, t1, t2)</tt> which is a shorthand for:</p>
<pre>OrElse(Then(FailIf(Not(p)), t1), t2)</pre>
<p>The combinator <tt>When(p, t)</tt> is a shorthand for:</p>
<pre>If(p, t, 'skip')</pre>
<p>The tactic <tt>skip</tt> just returns the input goal.
The following example demonstrates how to use the <tt>If</tt> combinator.</p>
<example pref="probe.3"><html><body>
<div class="highlight"><pre><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">=</span> <span class="n">Reals</span><span class="p">(</span><span class="s">'x y z'</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">Goal</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">y</span><span class="o">**</span><span class="mi">2</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">Probe</span><span class="p">(</span><span class="s">'num-consts'</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">If</span><span class="p">(</span><span class="n">p</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">,</span> <span class="s">'simplify'</span><span class="p">,</span> <span class="s">'factor'</span><span class="p">)</span>
<span class="k">print</span> <span class="n">t</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">Goal</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="o">+</span> <span class="n">z</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">y</span><span class="o">**</span><span class="mi">2</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">print</span> <span class="n">t</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
</pre></div>
</body></html></example>
</body>
</html>