Commit 7cb3ac9b authored by Allan Blanchard's avatar Allan Blanchard

Merge branch 'feature/wp/induction-tactic' into 'master'

[wp] induction tactic

See merge request frama-c/frama-c!2933
parents fdd2a762 c707d299
...@@ -1629,6 +1629,8 @@ src/plugins/wp/TacFilter.ml: CEA_WP ...@@ -1629,6 +1629,8 @@ src/plugins/wp/TacFilter.ml: CEA_WP
src/plugins/wp/TacFilter.mli: CEA_WP src/plugins/wp/TacFilter.mli: CEA_WP
src/plugins/wp/TacHavoc.ml: CEA_WP src/plugins/wp/TacHavoc.ml: CEA_WP
src/plugins/wp/TacHavoc.mli: CEA_WP src/plugins/wp/TacHavoc.mli: CEA_WP
src/plugins/wp/TacInduction.ml: CEA_WP
src/plugins/wp/TacInduction.mli: CEA_WP
src/plugins/wp/TacInstance.ml: CEA_WP src/plugins/wp/TacInstance.ml: CEA_WP
src/plugins/wp/TacInstance.mli: CEA_WP src/plugins/wp/TacInstance.mli: CEA_WP
src/plugins/wp/TacLemma.ml: CEA_WP src/plugins/wp/TacLemma.ml: CEA_WP
......
...@@ -142,7 +142,7 @@ val map_sequence : (pred -> pred) -> sequence -> sequence ...@@ -142,7 +142,7 @@ val map_sequence : (pred -> pred) -> sequence -> sequence
(** Rewrite all root predicates in sequence *) (** Rewrite all root predicates in sequence *)
val map_sequent : (pred -> pred) -> sequent -> sequent val map_sequent : (pred -> pred) -> sequent -> sequent
(** Rewrite all root predocates in hypotheses and goal *) (** Rewrite all root predicates in hypotheses and goal *)
val insert : ?at:int -> step -> sequent -> sequent val insert : ?at:int -> step -> sequent -> sequent
(** Insert a step in the sequent immediately [at] the specified position. (** Insert a step in the sequent immediately [at] the specified position.
......
...@@ -198,6 +198,7 @@ class mkcomposer ...@@ -198,6 +198,7 @@ class mkcomposer
Wutil.on filter (fun f -> wvalid <- f) ; Wutil.on filter (fun f -> wvalid <- f) ;
Wutil.on range (fun r -> ranged <- r) ; Wutil.on range (fun r -> ranged <- r) ;
ignore vmin ; ignore vmax ; ignore vmin ; ignore vmax ;
self#updated
end end
end end
......
...@@ -85,7 +85,7 @@ PLUGIN_CMO:= \ ...@@ -85,7 +85,7 @@ PLUGIN_CMO:= \
CfgCompiler StmtSemantics \ CfgCompiler StmtSemantics \
VCS script proof wpo wpReport \ VCS script proof wpo wpReport \
Footprint Tactical Strategy \ Footprint Tactical Strategy \
TacSplit TacChoice TacRange \ TacSplit TacChoice TacRange TacInduction \
TacArray TacCompound TacUnfold \ TacArray TacCompound TacUnfold \
TacHavoc TacInstance TacLemma \ TacHavoc TacInstance TacLemma \
TacFilter TacCut WpTac TacNormalForm \ TacFilter TacCut WpTac TacNormalForm \
......
(**************************************************************************)
(* *)
(* This file is part of WP plug-in of Frama-C. *)
(* *)
(* Copyright (C) 2007-2020 *)
(* CEA (Commissariat a l'energie atomique et aux energies *)
(* alternatives) *)
(* *)
(* you can redistribute it and/or modify it under the terms of the GNU *)
(* Lesser General Public License as published by the Free Software *)
(* Foundation, version 2.1. *)
(* *)
(* It is distributed in the hope that it will be useful, *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
(* GNU Lesser General Public License for more details. *)
(* *)
(* See the GNU Lesser General Public License version 2.1 *)
(* for more details (enclosed in the file licenses/LGPLv2.1). *)
(* *)
(**************************************************************************)
open Lang
type env = {
n : F.var ;
sigma : F.sigma ;
mutable hind : F.pred list ;
}
let rec strip env p =
match F.p_expr p with
| And ps -> F.p_all (strip env) ps
| _ ->
let p = F.p_subst env.sigma p in
if F.occursp env.n p then
( env.hind <- p :: env.hind ; F.p_true )
else p
let process value n0 seq =
(* Transfrom seq into: hyps => (forall n, goal) *)
let n = Lang.freshvar ~basename:"n" Qed.Logic.Int in
let i = Lang.freshvar ~basename:"i" Qed.Logic.Int in
let vn = F.e_var n in
let vi = F.e_var i in
let sigma = Lang.sigma () in
F.Subst.add sigma value vn ;
let env = { n ; sigma ; hind = [] } in
let hyps = Conditions.map_sequence (strip env) (fst seq) in
let goal_n = F.p_hyps env.hind @@ F.p_subst sigma (snd seq) in
let goal_i = F.p_subst_var n vi goal_n in
(* Base: n = n0 *)
let goal_base = F.p_imply (F.p_equal vn n0) goal_n in
(* Hind: n0 <= i < n *)
let goal_sup =
let hsup = [ F.p_leq n0 vi ; F.p_lt vi vn ] in
let hind = F.p_forall [i] (F.p_hyps hsup goal_i) in
F.p_hyps [F.p_lt n0 vn; hind] goal_n in
(* Hind: n < i <= n0 *)
let goal_inf =
let hinf = [ F.p_lt vn vi ; F.p_leq vi n0 ] in
let hind = F.p_forall [i] (F.p_hyps hinf goal_i) in
F.p_hyps [F.p_lt vn n0; hind] goal_n in
(* All Cases *)
List.map (fun (name,goal) -> name , (hyps,goal)) [
"Base" , goal_base ;
"Induction (sup)" , goal_sup ;
"Induction (inf)" , goal_inf ;
]
(* -------------------------------------------------------------------------- *)
(* --- Induction Tactical --- *)
(* -------------------------------------------------------------------------- *)
let vbase,pbase = Tactical.composer ~id:"base"
~title:"Base" ~descr:"Value of base case" ()
class induction =
object(self)
inherit Tactical.make
~id:"Wp.induction"
~title:"Induction"
~descr:"Proof by integer induction"
~params:[pbase]
method private get_base () =
match self#get_field vbase with
| Tactical.Compose(Code(t, _, _))
| Inside(_, t) when Lang.F.typeof t = Lang.t_int ->
Some t
| Compose(Cint i) ->
Some (Lang.F.e_bigint i)
| _ ->
None
method select feedback (s : Tactical.selection) =
begin match self#get_field vbase with
| Empty ->
self#set_field vbase (Tactical.int 0) ;
feedback#update_field vbase
| _ -> ()
end ;
let value = Tactical.selected s in
if F.is_int value then
match self#get_base () with
| Some base -> Applicable(process value base)
| None -> Not_configured
else Not_applicable
end
let tactical = Tactical.export (new induction)
(* -------------------------------------------------------------------------- *)
(**************************************************************************)
(* *)
(* This file is part of WP plug-in of Frama-C. *)
(* *)
(* Copyright (C) 2007-2020 *)
(* CEA (Commissariat a l'energie atomique et aux energies *)
(* alternatives) *)
(* *)
(* you can redistribute it and/or modify it under the terms of the GNU *)
(* Lesser General Public License as published by the Free Software *)
(* Foundation, version 2.1. *)
(* *)
(* It is distributed in the hope that it will be useful, *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
(* GNU Lesser General Public License for more details. *)
(* *)
(* See the GNU Lesser General Public License version 2.1 *)
(* for more details (enclosed in the file licenses/LGPLv2.1). *)
(* *)
(**************************************************************************)
(** Built-in Range Tactical (auto-registered) *)
open Tactical
val tactical : tactical
(**************************************************************************)
...@@ -251,26 +251,43 @@ c. Consolidating the Bench. ...@@ -251,26 +251,43 @@ c. Consolidating the Bench.
This mode replays the automated proofs and the interactive ones, re-running Alt-Ergo on every \textsf{WP} goals and every proof tactic sub-goals. The user scripts are never modified — this is a replay mode only. This mode replays the automated proofs and the interactive ones, re-running Alt-Ergo on every \textsf{WP} goals and every proof tactic sub-goals. The user scripts are never modified — this is a replay mode only.
\clearpage \subsection{Strategies}
\subsection{Available Tactics}
Strategies are heuristics that generate a prioritized bunch of tactics to be tried on the current goal.
Few built-in strategies are provided by the \textsf{WP} plug-in ; however, the user can extends the proof editor with
custom ones, as explained in section~\ref{wp-custom-tactics} below.
To run strategies, the interactive proof editor provide a single button \texttt{Strategies} in the tactic panel.
Configure the heuristics you want to include in your try, then click the button. The generated with highest priority is immediately applied. The proof summary now display \texttt{backtrack} buttons revealing proof nodes where alternative tactics are available. You can use those backtracking button to cycle over the generated tactics.
Of course, strategies are meant to be used multiple times, in sequence. Recall that strategies apply highest priority tactic first, on the current goal. When using strategies several times, you shall see several \texttt{backtrack}ing buttons in your proof script. You backtrack from any point at any time.
You shall also alternate strategies \emph{and} manually triggered tactics. Though, strategies are only used to
\emph{infer} or \emph{suggest} interesting tactics to the user. Once your are finished with your proved, only the tactics are saved in the script, not the strategies used to find them. Hence, replaying a script generated with strategies would not involve backtracking any more. The script will directly replay your chosen alternatives.
It is also possible to call strategies from the command line, with option \texttt{-wp-auto}. The strategies are tried up to some depth, and while a limited number of pending goals
remains unproved by \textsf{Qed} or the selected provers. More precisely:
\begin{description}
\item[\tt -wp-auto s,...] applies strategies \texttt{s,...} recursively to unproved goals.
\item[\tt -wp-auto-depth <$n$>] limit recursive application of strategies to depth $n$ (default is 5).
\item[\tt -wp-auto-width <$n$>] limit application of strategies when there is less than $n$ pending goals (default is 10).
\item[\tt -wp-auto-backtrack <$n$>] when the first tried strategies do not close a branch, allows for backtracking
on $n$ alternative strategies. Backtracking is performed on goals which are closed to the root proof obligation, hence
performing a kind of width-first search strategy, which tends to be more efficient in practice.
Backtracking is deactivated by default ($n=0$) and only used when \verb+-wp-auto+ is set.
\end{description}
The name of registered strategies is printed on console by using \texttt{-wp-auto '?'}. Custom strategies can be loaded by plug-ins, see below.
\newcommand{\TACTIC}[2]{#1\quad\quad\triangleright\quad\quad#2} \newcommand{\TACTIC}[2]{#1\quad\quad\triangleright\quad\quad#2}
\subsection{General Tactics}
\paragraph{Absurd} Contradict a Hypothesis\\ \paragraph{Absurd} Contradict a Hypothesis\\
The user can select a hypothesis $H$, and change the goal to $\neg H$: The user can select a hypothesis $H$, and change the goal to $\neg H$:
$$ \TACTIC{\Delta,H\models\,G}{\Delta\models\,\neg H} $$ $$ \TACTIC{\Delta,H\models\,G}{\Delta\models\,\neg H} $$
\paragraph{Array} Decompose array access-update patterns\\
The use select an expression $e\equiv a[k_1\mapsto v][k_2]$. Then:
$$ \TACTIC{\Delta\models\,G}{%
\begin{array}[t]{ll}
\Delta,\,k_1=k_2,\,e = v &\models G \\
\Delta,\,k_1\neq k_2,\,e = a[k_2] &\models G
\end{array}} $$
\paragraph{Choice} Select a Goal Alternative\\ \paragraph{Choice} Select a Goal Alternative\\
When the goal is a disjunction, the user select one alternative and discard the others: When the goal is a disjunction, the user select one alternative and discard the others:
$$ \TACTIC{\Delta\models\,\Gamma,G}{\Delta\models\,G} $$ $$ \TACTIC{\Delta\models\,\Gamma,G}{\Delta\models\,G} $$
...@@ -280,7 +297,6 @@ When the user select an equality between two records, it is decomposed field by ...@@ -280,7 +297,6 @@ When the user select an equality between two records, it is decomposed field by
$$ \TACTIC{ a = b }{ \bigwedge a.f_i = b.f_i } $$ $$ \TACTIC{ a = b }{ \bigwedge a.f_i = b.f_i } $$
\paragraph{Contrapose} Swap and Negate Hypothesis with Conclusion\\ \paragraph{Contrapose} Swap and Negate Hypothesis with Conclusion\\
The user select a hypothesis (typically, a negation) and swap it with the goal. The user select a hypothesis (typically, a negation) and swap it with the goal.
$$ \TACTIC{\Delta,H\models\,G}{\Delta,\neg G\models\,\neg H} $$ $$ \TACTIC{\Delta,H\models\,G}{\Delta,\neg G\models\,\neg H} $$
...@@ -303,14 +319,14 @@ $$\TACTIC{\Delta\models\,G}{% ...@@ -303,14 +319,14 @@ $$\TACTIC{\Delta\models\,G}{%
\Delta,\neg C \models G \Delta,\neg C \models G
\end{array}} $$ \end{array}} $$
\paragraph{Definition} Unfold predicate and logic function definition\\
The user simply select a term $f(e_1,\ldots,e_n)$ or a predicate $P(e_1,\ldots,e_n)$ which is replaced by its definition, when available.
\paragraph{Filter} Erase Hypotheses \\ \paragraph{Filter} Erase Hypotheses \\
The tactic is always applicable. It removes hypotheses from the goal on a variable used basis. When variables are compounds (record and arrays) a finer heuristics is used to detect which parts of the variable is relevant. A transitive closure of dependencies is also used. However, it is always possible that too many hypotheses are removed. The tactic is always applicable. It removes hypotheses from the goal on a variable used basis. When variables are compounds (record and arrays) a finer heuristics is used to detect which parts of the variable is relevant. A transitive closure of dependencies is also used. However, it is always possible that too many hypotheses are removed.
The tactic also have a variant where only hypotheses \emph{not relevant} to the goal are retained. This is useful to find absurd hypotheses that are completely disjoint from the goal. The tactic also have a variant where only hypotheses \emph{not relevant} to the goal are retained. This is useful to find absurd hypotheses that are completely disjoint from the goal.
\paragraph{Havoc} Go Through Assigns \\
This is a variant of the \texttt{Lemma} tactic dedicated to \texttt{Havoc} predicate generate by complex assigns clause. The user select an address, and if the address is not assigned by the \texttt{Havoc} clause, the memory at this address is unchanged.
\paragraph{Instance} Instantiate properties\\ \paragraph{Instance} Instantiate properties\\
The user selects a hypothesis with one or several $\forall$ quantifiers, or an $\exists$ quantified goal. Then, with the composer, the use choose to instantiate one or several of the quantified parameters. In case of $\forall$ quantifier over integer, a range of values can be instantiated instead. The user selects a hypothesis with one or several $\forall$ quantifiers, or an $\exists$ quantified goal. Then, with the composer, the use choose to instantiate one or several of the quantified parameters. In case of $\forall$ quantifier over integer, a range of values can be instantiated instead.
...@@ -323,22 +339,11 @@ $$\TACTIC{\Delta,\,\forall x\, P(x)\models G}{\Delta,P(n)\ldots P(m)\models G}$$ ...@@ -323,22 +339,11 @@ $$\TACTIC{\Delta,\,\forall x\, P(x)\models G}{\Delta,P(n)\ldots P(m)\models G}$$
When instantiating a goal with an expression $e$: When instantiating a goal with an expression $e$:
$$\TACTIC{\Delta\models \exists x\,G(x)}{\Delta\models G(e)}$$ $$\TACTIC{\Delta\models \exists x\,G(x)}{\Delta\models G(e)}$$
\paragraph{Lemma} Search \& Instantiate Lemma\\
The user start by selecting a term in the goal. Then, the search button in the tactic panel will display a list of lemma related to the term. Then, he can instantiate the parameters of the lemma, like with the Instance tactic.
\paragraph{Intuition} Decompose with Conjunctive/Disjunctive Normal Form\\ \paragraph{Intuition} Decompose with Conjunctive/Disjunctive Normal Form\\
The user can select a hypothesis or a goal with nested conjunctions and disjunctions. The tactics then computes the conjunctive or disjunctive normal form of the selection and split the goal accordingly. The user can select a hypothesis or a goal with nested conjunctions and disjunctions. The tactics then computes the conjunctive or disjunctive normal form of the selection and split the goal accordingly.
\paragraph{Range} Enumerate a range of values for an integer term\\ \paragraph{Lemma} Search \& Instantiate Lemma\\
The user select any integer expression $e$ in the proof, and a range of numerical values $a\ldots b$. The proof goes by case for each $e=a\ldots e=b$, plus the side cases $e<a$ and $e>b$: The user start by selecting a term in the goal. Then, the search button in the tactic panel will display a list of lemma related to the term. Then, he can instantiate the parameters of the lemma, like with the Instance tactic.
$$\TACTIC{\Delta\models\,G}{%
\begin{array}[t]{ll}
\Delta,e<a &\models G \\
\Delta,e=a &\models G \\
&\vdots \\
\Delta,e=b &\models G \\
\Delta,e>b &\models G
\end{array}} $$
\paragraph{Rewrite} Replace Terms\\ \paragraph{Rewrite} Replace Terms\\
This tactic uses an equality in a hypothesis to replace each occurrence of term by another one. This tactic uses an equality in a hypothesis to replace each occurrence of term by another one.
...@@ -348,9 +353,6 @@ The original equality hypothesis is removed from the goal. ...@@ -348,9 +353,6 @@ The original equality hypothesis is removed from the goal.
$$\TACTIC{\Delta,a=b\models\,G}{\Delta[a\leftarrow b]\models\,G[a\leftarrow b]}$$ $$\TACTIC{\Delta,a=b\models\,G}{\Delta[a\leftarrow b]\models\,G[a\leftarrow b]}$$
\paragraph{Separated} Expand Separation Cases\\
This tactic decompose a \texttt{separated}$(a,n,b,m)$ predicate into its four base cases: $a$ and $b$ have different bases, $a+n \leq b$, $b+m \leq a$, and $a[0..n-1]$ and $b[0..m-1]$ overlaps. The regions are separated in the first three cases, and not separated in the overlapping case. This is kind of normal disjunctive form of the separation clause.
\paragraph{Split} Decompose Logical Connectives and Conditionals\\ \paragraph{Split} Decompose Logical Connectives and Conditionals\\
This is the most versatile available tactic. It decompose merely any logical operator following the sequent calculus rules. Typically: This is the most versatile available tactic. It decompose merely any logical operator following the sequent calculus rules. Typically:
...@@ -376,7 +378,8 @@ When the user selects a arbitrary boolean expression $e$, the tactic is similar ...@@ -376,7 +378,8 @@ When the user selects a arbitrary boolean expression $e$, the tactic is similar
\Delta,\neg e\models G \Delta,\neg e\models G
\end{array}} \] \end{array}} \]
Finally, when the user select a arithmetic comparison over $a$ and $b$, the tactics makes a split over $a=b$, $a<b$ and $a>b$: Finally, when the user select a arithmetic comparison over $a$ and $b$,
the tactics makes a split over $a=b$, $a<b$ and $a>b$:
\[\TACTIC{\Delta\models\,G}{% \[\TACTIC{\Delta\models\,G}{%
\begin{array}[t]{ll} \begin{array}[t]{ll}
\Delta,a<b&\models G \\ \Delta,a<b&\models G \\
...@@ -384,49 +387,7 @@ Finally, when the user select a arithmetic comparison over $a$ and $b$, the tact ...@@ -384,49 +387,7 @@ Finally, when the user select a arithmetic comparison over $a$ and $b$, the tact
\Delta,a>b&\models G \Delta,a>b&\models G
\end{array}} \] \end{array}} \]
\paragraph{Definition} Unfold predicate and logic function definition\\ \subsection{Integers \& Bit-wised Tactics}
The user simply select a term $f(e_1,\ldots,e_n)$ or a predicate $P(e_1,\ldots,e_n)$ which is replaced by its definition, when available.
\paragraph{Bitwise} Decompose equalities over $N$-bits\\
The use selects an integer equality and a number of bits.
Providing the two members of the equality are in range $0..2^N-1$,
the equality is decomposed into $N$ bit-tests equalities:
\[\TACTIC{\Delta\models G}{%
\begin{array}[t]{rcl}
\Delta\phantom{)} &\models & 0 \leq a,b < 2^N \\
\sigma(\Delta) & \models & \sigma(G)
\end{array}
}\]
where $\sigma$ is the following subsitution:
\[ \sigma \equiv
\left[ a=b \quad \leftarrow
\bigwedge_{k\in 0..N-1} \mathtt{bit\_test}(a,k) = \mathtt{bit\_test}(b,k)
\right]
\]
The \lstinline{bit_test(a,b)} function is predefined in \textsf{WP} and is equivalent
to the \textsf{ACSL} expression \lstinline{(a & (1 << k)) != 0}. The
\textsf{Qed} engine has many simplification rules that applies to
such patterns, and the a tactic is good way to reason over bits.
\paragraph{Shift} Transform logical shifts into arithmetics\\
For positive integers, logical shifts such as \lstinline{a << k}
and \lstinline{a >> k} where \lstinline$k$ is a constant can be interpreted into a multiplication or a division by $2^k$.
When selecting a logical-shift, the tactic performs:
\[\TACTIC{\Delta\models G}{%
\begin{array}[t]{rcl}
\Delta\phantom{)} &\models& 0 \leq a \\
\sigma(\Delta) &\models& \sigma(G)
\end{array}
}\]
where:
\begin{tabular}[t]{ll}
$\sigma = [ \mathtt{lsl}(a,k) \leftarrow a * 2^k ]$ &
for left-shift, \\
$\sigma = [ \mathtt{lsr}(a,k) \leftarrow a / 2^k ]$ &
for right-shifts.
\end{tabular}
\paragraph{BitRange} Range of logical bitwise operators \\ \paragraph{BitRange} Range of logical bitwise operators \\
This tactical applies the two following lemmas to the current goal. This tactical applies the two following lemmas to the current goal.
...@@ -453,6 +414,28 @@ to apply the theorems. Such a strategy is \emph{not} complete in general. ...@@ -453,6 +414,28 @@ to apply the theorems. Such a strategy is \emph{not} complete in general.
Typically, $\mathtt{land}(x,y) < 38$ is true whenever both $x$ and $y$ are in range $0\ldots 31$, but this is also true Typically, $\mathtt{land}(x,y) < 38$ is true whenever both $x$ and $y$ are in range $0\ldots 31$, but this is also true
in other cases. in other cases.
\paragraph{Bitwise} Decompose equalities over $N$-bits\\
The use selects an integer equality and a number of bits.
Providing the two members of the equality are in range $0..2^N-1$,
the equality is decomposed into $N$ bit-tests equalities:
\[\TACTIC{\Delta\models G}{%
\begin{array}[t]{rcl}
\Delta\phantom{)} &\models & 0 \leq a,b < 2^N \\
\sigma(\Delta) & \models & \sigma(G)
\end{array}
}\]
where $\sigma$ is the following subsitution:
\[ \sigma \equiv
\left[ a=b \quad \leftarrow
\bigwedge_{k\in 0..N-1} \mathtt{bit\_test}(a,k) = \mathtt{bit\_test}(b,k)
\right]
\]
The \lstinline{bit_test(a,b)} function is predefined in \textsf{WP} and is equivalent
to the \textsf{ACSL} expression \lstinline{(a & (1 << k)) != 0}. The
\textsf{Qed} engine has many simplification rules that applies to
such patterns, and the a tactic is good way to reason over bits.
\paragraph{Congruence} Simplify Divisions and Products \\ \paragraph{Congruence} Simplify Divisions and Products \\
This tactic rewrites integer comparisons involving products and divisions. This tactic rewrites integer comparisons involving products and divisions.
The tactic applies one of the following theorems to the current goal. The tactic applies one of the following theorems to the current goal.
...@@ -470,8 +453,23 @@ n|k, n|k', & (k/n).a = (k'/n).b &\Longleftrightarrow& k.a = k'.b ...@@ -470,8 +453,23 @@ n|k, n|k', & (k/n).a = (k'/n).b &\Longleftrightarrow& k.a = k'.b
\end{array} \end{array}
\] \]
\paragraph{Induction} Start a proof by integer induction \\
The user select any integer expression $e$ in the proof and a base value $b$ (which defaults to
0). The tactic generates a proof by induction on $e$, that is, the base case
$e = b$ and then the cases $e < b$ and $b < e$. Formally, the initial goal
$\Delta_0\models\,G_0$ is first generalized into $\Delta,P(e)\models\,Q(e)$. The tactic
then proceed by (strong) induction over $n$ for
$G(n) \equiv P(n)\Longrightarrow\,Q(n)$:
\[\TACTIC{\Delta\models\,G(n)}{%
\begin{array}[t]{lll}
\Delta,\; \quad n = b & \models G(n) \\
\Delta,\; \forall i,\, b \leq i < n \Longrightarrow G(i) \; & \models G(n) \\
\Delta,\; \forall i,\, n < i \leq b \Longrightarrow G(i) \; & \models G(n)
\end{array}} \]
\paragraph{Overflow} Integer Conversions \\ \paragraph{Overflow} Integer Conversions \\
This tactic rewrites machine integer conversions by identify, This tactic rewrites machine integer conversions by identity,
providing the converted value is in available range. The tactic applies on expression providing the converted value is in available range. The tactic applies on expression
with pattern $\mathtt{to\_iota(e)}$ where \texttt{iota} is a a machine-integer name, with pattern $\mathtt{to\_iota(e)}$ where \texttt{iota} is a a machine-integer name,
\emph{eg.} \texttt{to\_uint32}. \emph{eg.} \texttt{to\_uint32}.
...@@ -485,33 +483,54 @@ with pattern $\mathtt{to\_iota(e)}$ where \texttt{iota} is a a machine-integer n ...@@ -485,33 +483,54 @@ with pattern $\mathtt{to\_iota(e)}$ where \texttt{iota} is a a machine-integer n
where $\sigma = [ \mathtt{to\_iota}(e) \mapsto e ]$ and $[a..b]$ is the range where $\sigma = [ \mathtt{to\_iota}(e) \mapsto e ]$ and $[a..b]$ is the range
of the \texttt{iota} integer domain. of the \texttt{iota} integer domain.
\subsection{Strategies} \paragraph{Range} Enumerate a range of values for an integer term\\
The user select any integer expression $e$ in the proof, and a range of numerical values $a\ldots b$. The proof goes by case for each $e=a\ldots e=b$, plus the side cases $e<a$ and $e>b$:
$$\TACTIC{\Delta\models\,G}{%
\begin{array}[t]{ll}
\Delta,e<a &\models G \\
\Delta,e=a &\models G \\
&\vdots \\
\Delta,e=b &\models G \\
\Delta,e>b &\models G
\end{array}} $$
Strategies are heuristics that generate a prioritized bunch of tactics to be tried on the current goal. \paragraph{Shift} Transform logical shifts into arithmetics\\
Few built-in strategies are provided by the \textsf{WP} plug-in ; however, the user can extends the proof editor with For positive integers, logical shifts such as \lstinline{a << k}
custom ones, as explained in section~\ref{wp-custom-tactics} below. and \lstinline{a >> k} where \lstinline$k$ is a constant can be interpreted into a multiplication or a division by $2^k$.
To run strategies, the interactive proof editor provide a single button \texttt{Strategies} in the tactic panel. When selecting a logical-shift, the tactic performs:
Configure the heuristics you want to include in your try, then click the button. The generated with highest priority is immediately applied. The proof summary now display \texttt{backtrack} buttons revealing proof nodes where alternative tactics are available. You can use those backtracking button to cycle over the generated tactics. \[\TACTIC{\Delta\models G}{%
\begin{array}[t]{rcl}
\Delta\phantom{)} &\models& 0 \leq a \\
\sigma(\Delta) &\models& \sigma(G)
\end{array}
}\]
where:
\begin{tabular}[t]{ll}
$\sigma = [ \mathtt{lsl}(a,k) \leftarrow a * 2^k ]$ &
for left-shift, \\
$\sigma = [ \mathtt{lsr}(a,k) \leftarrow a / 2^k ]$ &
for right-shifts.
\end{tabular}
Of course, strategies are meant to be used multiple times, in sequence. Recall that strategies apply highest priority tactic first, on the current goal. When using strategies several times, you shall see several \texttt{backtrack}ing buttons in your proof script. You backtrack from any point at any time. \subsection{Domain Specific Tactics}
You shall also alternate strategies \emph{and} manually triggered tactics. Though, strategies are only used to \paragraph{Array} Decompose array access-update patterns\\
\emph{infer} or \emph{suggest} interesting tactics to the user. Once your are finished with your proved, only the tactics are saved in the script, not the strategies used to find them. Hence, replaying a script generated with strategies would not involve backtracking any more. The script will directly replay your chosen alternatives. The use select an expression $e\equiv a[k_1\mapsto v][k_2]$. Then:
It is also possible to call strategies from the command line, with option \texttt{-wp-auto}. The strategies are tried up to some depth, and while a limited number of pending goals \[
remains unproved by \textsf{Qed} or the selected provers. More precisely: \TACTIC{\Delta\models\,G}{%
\begin{description} \begin{array}[t]{ll}
\item[\tt -wp-auto s,...] applies strategies \texttt{s,...} recursively to unproved goals. \Delta,\,k_1=k_2,\,e = v &\models G \\
\item[\tt -wp-auto-depth <$n$>] limit recursive application of strategies to depth $n$ (default is 5). \Delta,\,k_1\neq k_2,\,e = a[k_2] &\models G
\item[\tt -wp-auto-width <$n$>] limit application of strategies when there is less than $n$ pending goals (default is 10). \end{array}
\item[\tt -wp-auto-backtrack <$n$>] when the first tried strategies do not close a branch, allows for backtracking }\]
on $n$ alternative strategies. Backtracking is performed on goals which are closed to the root proof obligation, hence
performing a kind of width-first search strategy, which tends to be more efficient in practice.
Backtracking is deactivated by default ($n=0$) and only used when \verb+-wp-auto+ is set.
\end{description}
The name of registered strategies is printed on console by using \texttt{-wp-auto '?'}. Custom strategies can be loaded by plug-ins, see below. \paragraph{Havoc} Go Through Assigns \\
This is a variant of the \texttt{Lemma} tactic dedicated to \texttt{Havoc} predicate generate by complex assigns clause. The user select an address, and if the address is not assigned by the \texttt{Havoc} clause, the memory at this address is unchanged.
\paragraph{Separated} Expand Separation Cases\\
This tactic decompose a \texttt{separated}$(a,n,b,m)$ predicate into its four base cases: $a$ and $b$ have different bases, $a+n \leq b$, $b+m \leq a$, and $a[0..n-1]$ and $b[0..m-1]$ overlaps. The regions are separated in the first three cases, and not separated in the overlapping case. This is kind of normal disjunctive form of the separation clause.
\subsection{Custom Tactics and Strategies} \subsection{Custom Tactics and Strategies}
\label{wp-custom-tactics} \label{wp-custom-tactics}
......
/* run.config
DONTRUN:
*/
/* run.config_qualif
OPT: -wp-prover script,alt-ergo -wp-timeout 1
OPT: -wp-prover script,alt-ergo -wp-timeout 1
OPT: -wp-prover script,alt-ergo -wp-timeout 1
*/
// Script 0: induction on f(x) => success
// Script 1: induction on x => unsuccess
// Script 2: induction on y => unsuccess
/*@
axiomatic Inductive {
logic integer f(integer x);
predicate P(integer x, integer y);