summaryrefslogtreecommitdiff
path: root/Tutorial.v
diff options
context:
space:
mode:
Diffstat (limited to 'Tutorial.v')
-rw-r--r--Tutorial.v321
1 files changed, 321 insertions, 0 deletions
diff --git a/Tutorial.v b/Tutorial.v
new file mode 100644
index 0000000..84d40fc
--- /dev/null
+++ b/Tutorial.v
@@ -0,0 +1,321 @@
+(***************************************************************************)
+(* This is part of aac_tactics, it is distributed under the terms of the *)
+(* GNU Lesser General Public License version 3 *)
+(* (see file LICENSE for more details) *)
+(* *)
+(* Copyright 2009-2010: Thomas Braibant, Damien Pous. *)
+(***************************************************************************)
+
+(** * Examples about uses of the aac_rewrite library *)
+
+(*
+ Depending on your installation, either uncomment the following two
+ lines, or add them to your .coqrc files, replacing path_to_aac_tactics
+ with the correct path for your installation:
+
+ Add Rec LoadPath "path_to_aac_tactics".
+ Add ML Path "path_to_aac_tactics".
+*)
+Require Export AAC.
+Require Instances.
+
+(** ** Introductory examples *)
+
+(** First, we settle in the context of Z, and show an usage of our
+tactics: we rewrite an universally quantified hypothesis modulo
+associativity and commutativity. *)
+
+Section introduction.
+ Import ZArith.
+ Import Instances.Z.
+
+ Variables a b c : Z.
+ Hypothesis H: forall x, x + Zopp x = 0.
+ Goal a + b + c + Zopp (c + a) = b.
+ aac_rewrite H.
+ aac_reflexivity.
+ Qed.
+ Goal a + c+ Zopp (b + a + Zopp b) = c.
+ do 2 aac_rewrite H.
+ reflexivity.
+ Qed.
+
+ (** Notes:
+ - the tactic handles arbitrary function symbols like [Zopp] (as
+ long as they are proper morphisms);
+ - here, ring would have done the job.
+ *)
+
+End introduction.
+
+(** Second, we show how to exploit binomial identities to prove a goal
+about pythagorean triples, without breaking a sweat. By comparison,
+even if the goal and the hypothesis are both in normal form, making
+the rewrites using standard tools is difficult.
+*)
+
+Section binomials.
+
+ Import ZArith.
+ Import Instances.Z.
+
+ Notation "x ^2" := (x*x) (at level 40).
+ Notation "2 ⋅ x" := (x+x) (at level 41).
+ Lemma Hbin1: forall x y, (x+y)^2 = x^2 + y^2 + 2⋅x*y. Proof. intros; ring. Qed.
+ Lemma Hbin2: forall x y, x^2 + y^2 = (x+y)^2 + -(2⋅x*y). Proof. intros; ring. Qed.
+ Lemma Hopp : forall x, x + -x = 0. Proof Zplus_opp_r.
+
+ Variables a b c : Z.
+ Hypothesis H : c^2 + 2⋅(a+1)*b = (a+1+b)^2.
+ Goal a^2 + b^2 + 2⋅a + 1 = c^2.
+ aacu_rewrite <- Hbin1.
+ aac_rewrite Hbin2.
+ aac_rewrite <- H.
+ aac_rewrite Hopp.
+ aac_reflexivity.
+ Qed.
+
+ (** Note: after the [aac_rewrite <- H], one could use [ring] to close the proof.*)
+
+End binomials.
+
+(** ** Usage *)
+
+(** One can also work in an abstract context, with arbitrary
+ associative and commutative operators.
+
+ (Note that one can declare several operations of each kind;
+ however, to be able to use this plugin, one currently needs at least
+ one associative operator, and one associative-commutative
+ operator.) *)
+
+Section base.
+
+ Context {X} {R} {E: Equivalence R}
+ {plus} {zero}
+ {dot} {one}
+ {A: @Op_A X R dot one}
+ {AC: Op_AC R plus zero}.
+
+ Notation "x == y" := (R x y) (at level 70).
+ Notation "x * y" := (dot x y) (at level 40, left associativity).
+ Notation "1" := (one).
+ Notation "x + y" := (plus x y) (at level 50, left associativity).
+ Notation "0" := (zero).
+
+ (** In the very first example, [ring] would have solved the
+ goal. Here, since [dot] does not necessarily distribute over [plus],
+ it is not possible to rely on it. *)
+
+ Section reminder.
+ Hypothesis H : forall x, x * x == x.
+ Variables a b c : X.
+
+ Goal (a+b+c)*(c+a+b) == a+b+c.
+ aac_rewrite H.
+ aac_reflexivity.
+ Qed.
+
+ (** Note: the tactic starts by normalizing terms, so that trailing
+ units are always eliminated. *)
+
+ Goal ((a+b)+0+c)*((c+a)+b*1) == a+b+c.
+ aac_rewrite H.
+ aac_reflexivity.
+ Qed.
+ End reminder.
+
+ (** We can deal with "proper" morphisms of arbitrary arity (here [f],
+ or [Zopp] earlier), and rewrite under morphisms (here [g]). *)
+
+ Section morphisms.
+ Variable f : X -> X -> X.
+ Hypothesis Hf : Proper (R ==> R ==> R) f.
+ Variable g : X -> X.
+ Hypothesis Hg : Proper (R ==> R) g.
+
+ Variable a b: X.
+ Hypothesis H : forall x y, x+f (b+y) x == y+x.
+ Goal g ((f (a+b) a) + a) == g (a+a).
+ aac_rewrite H.
+ reflexivity.
+ Qed.
+ End morphisms.
+
+ (** ** Selecting what and where to rewrite *)
+
+ (** There are sometimes several possible rewriting. We now show how
+ to interact with the tactic to select the desired one. *)
+
+ Section occurrence.
+ Variable f : X -> X .
+ Variable a : X.
+ Hypothesis Hf : Proper (R ==> R) f.
+ Hypothesis H : forall x, x + x == x.
+
+ Goal f(a+a)+f(a+a) == f a.
+ (** In case there are several possible solutions, one can print
+ the different solutions using the [aac_instances] tactic (in
+ proofgeneral, look at buffer *coq* ): *)
+ aac_instances H.
+ (** the default choice is the smallest possible context (number
+ 0), but one can choose the desired context; *)
+ aac_rewrite H subterm 1.
+ (** now the goal is [f a + f a == f a], there is only one solution. *)
+ aac_rewrite H.
+ reflexivity.
+ Qed.
+
+ End occurrence.
+
+ Section subst.
+ Variables a b c d : X.
+ Hypothesis H: forall x y, a*x*y*b == a*(x+y)*b.
+ Hypothesis H': forall x, x + x == x.
+
+ Goal a*c*d*c*d*b == a*c*d*b.
+ (** Here, there is only one possible context, but several substitutions; *)
+ aac_instances H.
+ (** we can select them with the proper keyword. *)
+ aac_rewrite H subst 1.
+ aac_rewrite H'.
+ aac_reflexivity.
+ Qed.
+ End subst.
+
+ (** As expected, one can use both keyword together to select the
+ correct subterm and the correct substitution. *)
+
+ Section both.
+ Variables a b c d : X.
+ Hypothesis H: forall x y, a*x*y*b == a*(x+y)*b.
+ Hypothesis H': forall x, x + x == x.
+
+ Goal a*c*d*c*d*b*b == a*(c*d+b)*b.
+ aac_instances H.
+ aac_rewrite H subterm 1 subst 1.
+ aac_rewrite H.
+ aac_rewrite H'.
+ aac_reflexivity.
+ Qed.
+
+ End both.
+
+ (** We now turn on explaining the distinction between [aac_rewrite]
+ and [aacu_rewrite]: [aac_rewrite] rejects solutions in which
+ variables are instantiated by units, the companion tactic,
+ [aacu_rewrite] allows such solutions. *)
+
+ Section dealing_with_units.
+ Variables a b c: X.
+ Hypothesis H: forall x, a*x*a == x.
+ Goal a*a == 1.
+ (** Here, x must be instantiated with 1, hence no solutions; *)
+ aac_instances H.
+ (** while we get solutions with the "aacu" tactic. *)
+ aacu_instances H.
+ aacu_rewrite H.
+ reflexivity.
+ Qed.
+
+ (** We introduced this distinction because it allows us to rule
+ out dummy cases in common situations: *)
+
+ Hypothesis H': forall x y z, x*y + x*z == x*(y+z).
+ Goal a*b*c + a*c+ a*b == a*(c+b*(1+c)).
+ (** 6 solutions without units, *)
+ aac_instances H'.
+ (** more than 52 with units. *)
+ aacu_instances H'.
+ Abort.
+
+ End dealing_with_units.
+End base.
+
+(** ** Declaring instances *)
+
+(** One can use one's own operations: it suffices to declare them as
+ instances of our classes. (Note that these instances are already
+ declared in file [Instances.v].) *)
+
+Section Peano.
+ Require Import Arith.
+
+ Program Instance nat_plus : Op_AC eq plus O.
+ Solve All Obligations using firstorder.
+
+ Program Instance nat_dot : Op_AC eq mult 1.
+ Solve All Obligations using firstorder.
+
+
+ (** Caveat: we need at least an instance of an operator that is AC
+ and one that is A for a given relation. However, one can reuse an
+ AC operator as an A operator. *)
+
+ Definition default_a := AC_A nat_dot. Existing Instance default_a.
+End Peano.
+
+(** ** Caveats *)
+
+Section Peano'.
+ Import Instances.Peano.
+
+ (** 1. We have a special treatment for units, thus, [S x + x] does not
+ match [S 0], which is considered as a unit (one) of the mult
+ operation. *)
+
+ Section caveat_one.
+ Definition double_plus_one x := 2*x + 1.
+ Hypothesis H : forall x, S x + x = double_plus_one x.
+ Goal S O = double_plus_one O.
+ try aac_rewrite H. (** 0 solutions (normal since it would use 0 to instantiate x) *)
+ try aacu_rewrite H. (** 0 solutions (abnormal) *)
+ Abort.
+ End caveat_one.
+
+ (** 2. We cannot at the moment have two classes with the same
+ units: in the following example, [0] is understood as the unit of
+ [max] rather than as the unit of [plus]. *)
+
+ Section max.
+ Program Instance aac_max : Op_AC eq Max.max O := Build_Op_AC _ _ _ Max.max_assoc Max.max_comm.
+ Variable a : nat.
+ Goal 0 + a = a.
+ try aac_reflexivity.
+ Abort.
+ End max.
+End Peano'.
+
+(** 3. If some computations are possible in the goal or in the
+hypothesis, the inference mechanism we use will make the
+conversion. However, it seems that in most cases, these conversions
+can be done by hand using simpl rather than rewrite. *)
+
+Section Z.
+
+ (* The order of the following lines is important in order to get the right scope afterwards. *)
+ Import ZArith.
+ Open Scope Z_scope.
+ Opaque Zmult.
+
+ Hypothesis dot_ann_left :forall x, x * 0 = 0.
+ Hypothesis dot_ann_right :forall x, 0 * x = 0.
+
+ Goal forall a, a*0 = 0.
+ intros. aacu_rewrite dot_ann_left. reflexivity.
+ Qed.
+
+ (** Here the tactic fails, since the 0*a is converted to 0, and no
+ rewrite can occur (even though Zmult is opaque). *)
+ Goal forall a, 0*a = 0.
+ intros. try aacu_rewrite dot_ann_left.
+ Abort.
+
+ (** Here the tactic fails, since the 0*x is converted to 0 in the hypothesis. *)
+ Goal forall a, a*0 = 0.
+ intros. try aacu_rewrite dot_ann_right.
+ Abort.
+
+
+End Z.
+