Set Nested Proofs Allowed. Require Import Compare.Open Scope string_scope. (* Lets us write strings literals as "x" *) Require Import List. Import ListNotations. Open Scope list_scope. (* Lets us write lists as [1; 2; 3] *) Require Import Arith.
We've seen how we can define some recursive functions in Coq, provided that it passes the termination checker. But what if we have a more complicated function? As an example, let's look at implementing merge sort for lists of natural numbers, using the standard ordering.
First, we need to define a function to merge two (already sorted lists). Normally, we'd write this as follows:
Definition nat_lte := Compare_dec.le_gt_dec.
Unfortunately, Coq will reject this because it's the case that xs is always getting smaller, nor the case that ys is always getting smaller. Of course, one of them is always getting smaller, so eventually, this will terminate. But in this case, we can hack around the problem by simply re-organizing the function as follows.
Fixpoint merge (xs:list nat) : list nat -> list nat :=
match xs with
| nil => fun ys => ys
| x::xs' =>
(fix inner_merge (ys:list nat) : list nat :=
match ys with
| nil => x::xs'
| y::ys' =>
if nat_lte x y then
x :: (merge xs' ys)
else
y :: (inner_merge ys')
end)
end.
We can write some examples to test that merge
works as expected.
Program Fixpoint merge' (xs ys:list nat) {measure (length xs + length ys)} : list nat := match xs, ys with | [], ys => ys | xs, [] => xs | x::xs', y::ys' => if nat_lte x y then x :: (merge' xs' ys) else y :: (merge' xs ys') (* Generates a proof obligation *) end.(* To show: length xs + length ys' < length xs + length ys *)y: nat
ys': list nat
x: nat
xs': list nat
merge': forall xs ys : list nat, Datatypes.length xs + Datatypes.length ys < Datatypes.length (x :: xs') + Datatypes.length (y :: ys') -> list nat
g: x > yDatatypes.length (x :: xs') + Datatypes.length ys' < Datatypes.length (x :: xs') + Datatypes.length (y :: ys')lia. Defined.y: nat
ys': list nat
x: nat
xs': list nat
merge': forall xs ys : list nat, Datatypes.length xs + Datatypes.length ys < Datatypes.length (x :: xs') + Datatypes.length (y :: ys') -> list nat
g: x > yS (Datatypes.length xs' + Datatypes.length ys') < S (Datatypes.length xs' + S (Datatypes.length ys'))
It is also interesting to examine the objects that are generated by this definition.
Now let's write a pair of helper functions, one that takes a list of list of naturals and merges consecutive elements, and another that transforms a list into a list of singleton lists.
Fixpoint merge_pairs (xs:list (list nat)) : list (list nat) := match xs with | h1::h2::t => (merge h1 h2) :: (merge_pairs t) | xs' => xs' end. Definition make_lists (xs:list nat) : list (list nat) := List.map (fun x => x::nil) xs.
Here are some examples to illustrate what these helper functions do.
Next we will prove an important lemma that relate the length of the list computed by merge_pairs
to the length of its argument. Note that we prove a conjunction to get a strong enough induction hypothesis. (As a fun exercise, try to prove just the first conjunct by induction and see where you get stuck.)
forall xs : list (list nat), (forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)) /\ (forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs))forall xs : list (list nat), (forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)) /\ (forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs))(forall h1 h2 : list nat, Datatypes.length (merge_pairs [h1; h2]) < Datatypes.length [h1; h2]) /\ (forall h : list nat, Datatypes.length (merge_pairs [h]) <= Datatypes.length [h])x: list nat
xs: list (list nat)
H1: forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)
H2: forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs)(forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: x :: xs)) < Datatypes.length (h1 :: h2 :: x :: xs)) /\ (forall h : list nat, Datatypes.length (merge_pairs (h :: x :: xs)) <= Datatypes.length (h :: x :: xs))(forall h1 h2 : list nat, Datatypes.length (merge_pairs [h1; h2]) < Datatypes.length [h1; h2]) /\ (forall h : list nat, Datatypes.length (merge_pairs [h]) <= Datatypes.length [h])split; lia.(list nat -> list nat -> 1 < 2) /\ (list nat -> 1 <= 1)x: list nat
xs: list (list nat)
H1: forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)
H2: forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs)(forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: x :: xs)) < Datatypes.length (h1 :: h2 :: x :: xs)) /\ (forall h : list nat, Datatypes.length (merge_pairs (h :: x :: xs)) <= Datatypes.length (h :: x :: xs))x: list nat
xs: list (list nat)
H1: forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)
H2: forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs)forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: x :: xs)) < Datatypes.length (h1 :: h2 :: x :: xs)x: list nat
xs: list (list nat)
H1: forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)
H2: forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs)forall h : list nat, Datatypes.length (merge_pairs (h :: x :: xs)) <= Datatypes.length (h :: x :: xs)x: list nat
xs: list (list nat)
H1: forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)
H2: forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs)forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: x :: xs)) < Datatypes.length (h1 :: h2 :: x :: xs)x: list nat
xs: list (list nat)
H1: forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)
H2: Datatypes.length (merge_pairs (x :: xs)) <= Datatypes.length (x :: xs)forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: x :: xs)) < Datatypes.length (h1 :: h2 :: x :: xs)lia.x: list nat
xs: list (list nat)
H1: list nat -> list nat -> S (Datatypes.length (merge_pairs xs)) < S (S (Datatypes.length xs))
H2: Datatypes.length match xs with | [] => x :: xs | h2 :: t => merge x h2 :: merge_pairs t end <= S (Datatypes.length xs)list nat -> list nat -> S (Datatypes.length match xs with | [] => x :: xs | h2 :: t => merge x h2 :: merge_pairs t end) < S (S (S (Datatypes.length xs)))x: list nat
xs: list (list nat)
H1: forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)
H2: forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs)forall h : list nat, Datatypes.length (merge_pairs (h :: x :: xs)) <= Datatypes.length (h :: x :: xs)x: list nat
xs: list (list nat)
H1: forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)
H2: forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs)
x': list natDatatypes.length (merge_pairs (x' :: x :: xs)) <= Datatypes.length (x' :: x :: xs)lia. Qed.x: list nat
xs: list (list nat)
x': list nat
H1: Datatypes.length (merge_pairs (x' :: x :: xs)) < Datatypes.length (x' :: x :: xs)
H2: forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs)Datatypes.length (merge_pairs (x' :: x :: xs)) <= Datatypes.length (x' :: x :: xs)
Next, we can prove a corollary that captures the case we will need to define merge sort.
forall (h1 h2 : list nat) (xs : list (list nat)), Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)forall (h1 h2 : list nat) (xs : list (list nat)), Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)h1, h2: list nat
xs: list (list nat)Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)h1, h2: list nat
xs: list (list nat)(forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)) /\ (forall h : list nat, Datatypes.length (merge_pairs (h :: xs)) <= Datatypes.length (h :: xs)) -> Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)apply H. Qed.h1, h2: list nat
xs: list (list nat)
H: forall h1 h2 : list nat, Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)Datatypes.length (merge_pairs (h1 :: h2 :: xs)) < Datatypes.length (h1 :: h2 :: xs)
Now we are ready to define our merge sort. We'll do it by iterating merge_pairs
until we have a singleton list.
Program Fixpoint merge_iter (xs: list (list nat)) { measure (length xs) } : list nat := match xs with | nil => nil | x::nil => x | x1::x2::xs' => merge_iter (merge_pairs (x1::x2::xs')) end.x1, x2: list nat
xs': list (list nat)
merge_iter: forall xs : list (list nat), Datatypes.length xs < Datatypes.length (x1 :: x2 :: xs') -> list natS (Datatypes.length (merge_pairs xs')) < Datatypes.length (x1 :: x2 :: xs')apply merge_pairs_length. Defined.x1, x2: list nat
xs': list (list nat)
merge_iter: forall xs : list (list nat), Datatypes.length xs < Datatypes.length (x1 :: x2 :: xs') -> list natS (Datatypes.length (merge_pairs xs')) < Datatypes.length (x1 :: x2 :: xs')
Note that we had to use merge_pairs_length
before Coq was willing to accept our recursive definition.
With these pieces in hand, we can finally define our merge_sort
function.
Definition merge_sort (xs:list nat) :=
merge_iter (make_lists xs).
Let's test that is is working as expected:
Axiom funext : forall {X Y: Type} (f g: X -> Y), (forall x, f x = g x) -> f = g. Inductive expr : Type := | Const : nat -> expr | Var : string -> expr | Plus : expr -> expr -> expr | Mult : expr -> expr -> expr | Minus : expr -> expr -> expr. Fixpoint eval (env : string -> nat) (e : expr) : nat := match e with | Const n => n | Var x => env x | Plus e1 e2 => eval env e1 + eval env e2 | Mult e1 e2 => eval env e1 * eval env e2 | Minus e1 e2 => eval env e1 - eval env e2 end.
A simple imperative programming language with While loops
Inductive stmt :=
| Assign : string -> expr -> stmt
| Seq : stmt -> stmt -> stmt
| If : expr -> stmt -> stmt -> stmt
| While : expr -> stmt -> stmt.
x, y: string{x = y} + {x <> y}destruct (String.eqb_spec x y); auto. Defined.x, y: string{x = y} + {x <> y}x, y: string(if string_eq x y then 0 else 1) = 1 -> (if string_eq y x then 1 else 0) = 0x, y: string(if string_eq x y then 0 else 1) = 1 -> (if string_eq y x then 1 else 0) = 0x, y: string
H: (if string_eq x y then 0 else 1) = 1(if string_eq y x then 1 else 0) = 0x, y: string
e: x = y
H: 0 = 1(if string_eq y x then 1 else 0) = 0x, y: string
n: x <> y
H: 1 = 1(if string_eq y x then 1 else 0) = 0discriminate.x, y: string
e: x = y
H: 0 = 1(if string_eq y x then 1 else 0) = 0x, y: string
n: x <> y
H: 1 = 1(if string_eq y x then 1 else 0) = 0x, y: string
n: x <> y
H: 1 = 1
e: y = x1 = 0x, y: string
n: x <> y
H: 1 = 1
n0: y <> x0 = 0congruence.x, y: string
n: x <> y
H: 1 = 1
e: y = x1 = 0reflexivity. Qed. Ltac simpeq := repeat match goal with | _ => congruence || (progress subst) | H : ?x = ?x |- _ => clear H | H : _ = _ |- _ => progress injection H as H end.x, y: string
n: x <> y
H: 1 = 1
n0: y <> x0 = 0
Shorter proof
Ltac string_cases := repeat (destruct string_eq; simpeq; simpl).x, y: string(if string_eq x y then 0 else 1) = 1 -> (if string_eq y x then 1 else 0) = 0string_cases. Qed.x, y: string(if string_eq x y then 0 else 1) = 1 -> (if string_eq y x then 1 else 0) = 0
Big-step semantics
Definition env := string -> nat. Inductive big_step : env -> stmt -> env -> Prop := | big_Assign env x e : big_step env (Assign x e) (fun var => if string_eq x var then eval env e else env var) | big_Seq env env' env'' s1 s2 : big_step env s1 env' -> big_step env' s2 env'' -> big_step env (Seq s1 s2) env'' | big_IfTrue env env' e s1 s2 : eval env e <> 0 -> big_step env s1 env' -> big_step env (If e s1 s2) env' | big_IfFalse env env' e s1 s2 : eval env e = 0 -> big_step env s2 env' -> big_step env (If e s1 s2) env' | big_WhileTrue env env' env'' e s : eval env e <> 0 -> big_step env s env' -> big_step env' (While e s) env'' -> big_step env (While e s) env'' | big_WhileFalse env e s : eval env e = 0 -> big_step env (While e s) env.
env: lec07_big_step.env
s: stmt
env1, env2: lec07_big_step.envbig_step env s env1 -> big_step env s env2 -> env1 = env2env: lec07_big_step.env
s: stmt
env1, env2: lec07_big_step.envbig_step env s env1 -> big_step env s env2 -> env1 = env2env: lec07_big_step.env
s: stmt
env1, env2: lec07_big_step.env
H1: big_step env s env1big_step env s env2 -> env1 = env2env: lec07_big_step.env
s: stmt
env1: lec07_big_step.env
H1: big_step env s env1forall env2 : lec07_big_step.env, big_step env s env2 -> env1 = env2env0: env
x: string
e: expr
env2: env
H2: big_step env0 (Assign x e) env2(fun var : string => if string_eq x var then eval env0 e else env0 var) = env2env0, env', env'': env
s1, s2: stmt
H1_: big_step env0 s1 env'
H1_0: big_step env' s2 env''
IHbig_step1: forall env2 : env, big_step env0 s1 env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' s2 env2 -> env'' = env2
env2: env
H2: big_step env0 (Seq s1 s2) env2env'' = env2env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e <> 0
H1: big_step env0 s1 env'
IHbig_step: forall env2 : env, big_step env0 s1 env2 -> env' = env2
env2: env
H2: big_step env0 (If e s1 s2) env2env' = env2env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e = 0
H1: big_step env0 s2 env'
IHbig_step: forall env2 : env, big_step env0 s2 env2 -> env' = env2
env2: env
H2: big_step env0 (If e s1 s2) env2env' = env2env0: string -> nat
env', env'': env
e: expr
s: stmt
H: eval env0 e <> 0
H1_: big_step env0 s env'
H1_0: big_step env' (While e s) env''
IHbig_step1: forall env2 : env, big_step env0 s env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' (While e s) env2 -> env'' = env2
env2: env
H2: big_step env0 (While e s) env2env'' = env2env0: string -> nat
e: expr
s: stmt
H: eval env0 e = 0
env2: env
H2: big_step env0 (While e s) env2env0 = env2env0: env
x: string
e: expr
env2: env
H2: big_step env0 (Assign x e) env2(fun var : string => if string_eq x var then eval env0 e else env0 var) = env2env0: env
x: string
e: expr
env2: env
H2: big_step env0 (Assign x e) env2
env1: env
x0: string
e0: expr
H: env1 = env0
H1: x0 = x
H3: e0 = e
H0: (fun var : string => if string_eq x var then eval env0 e else env0 var) = env2(fun var : string => if string_eq x var then eval env0 e else env0 var) = (fun var : string => if string_eq x var then eval env0 e else env0 var)env0: env
x: string
e: expr
env2, env1: env
x0: string
e0: expr
H: env1 = env0
H1: x0 = x
H3: e0 = e
H0: (fun var : string => if string_eq x var then eval env0 e else env0 var) = env2(fun var : string => if string_eq x var then eval env0 e else env0 var) = (fun var : string => if string_eq x var then eval env0 e else env0 var)reflexivity.env0: env
x: string
e: expr(fun var : string => if string_eq x var then eval env0 e else env0 var) = (fun var : string => if string_eq x var then eval env0 e else env0 var)env0, env', env'': env
s1, s2: stmt
H1_: big_step env0 s1 env'
H1_0: big_step env' s2 env''
IHbig_step1: forall env2 : env, big_step env0 s1 env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' s2 env2 -> env'' = env2
env2: env
H2: big_step env0 (Seq s1 s2) env2env'' = env2env0, env', env'': env
s1, s2: stmt
H1_: big_step env0 s1 env'
H1_0: big_step env' s2 env''
IHbig_step1: forall env2 : env, big_step env0 s1 env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' s2 env2 -> env'' = env2
env2: env
H2: big_step env0 (Seq s1 s2) env2
env1, env'0, env''0: env
s0, s3: stmt
H3: big_step env0 s1 env'0
H5: big_step env'0 s2 env2
H1: env1 = env0
H: s0 = s1
H0: s3 = s2
H4: env''0 = env2env'' = env2env0, env', env'': env
s1, s2: stmt
H1_: big_step env0 s1 env'
H1_0: big_step env' s2 env''
IHbig_step1: forall env2 : env, big_step env0 s1 env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' s2 env2 -> env'' = env2
env2, env1, env'0, env''0: env
s0, s3: stmt
H3: big_step env0 s1 env'0
H5: big_step env'0 s2 env2
H1: env1 = env0
H: s0 = s1
H0: s3 = s2
H4: env''0 = env2env'' = env2env0, env', env'': env
s1, s2: stmt
H1_: big_step env0 s1 env'
H1_0: big_step env' s2 env''
IHbig_step1: forall env2 : env, big_step env0 s1 env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' s2 env2 -> env'' = env2
env2, env'0: env
H3: big_step env0 s1 env'0
H5: big_step env'0 s2 env2env'' = env2env0, env', env'': env
s1, s2: stmt
H1_: big_step env0 s1 env'
H1_0: big_step env' s2 env''
IHbig_step1: forall env2 : env, big_step env0 s1 env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' s2 env2 -> env'' = env2
env2, env'0: env
H3: big_step env0 s1 env'0
H5: big_step env'0 s2 env2big_step env' s2 env2env0, env', env'': env
s1, s2: stmt
H1_: big_step env0 s1 env'
H1_0: big_step env' s2 env''
IHbig_step1: forall env2 : env, big_step env0 s1 env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' s2 env2 -> env'' = env2
env2, env'0: env
H3: env' = env'0
H5: big_step env'0 s2 env2big_step env' s2 env2apply H5.env0, env'': env
s1, s2: stmt
env'0: env
IHbig_step2: forall env2 : env, big_step env'0 s2 env2 -> env'' = env2
IHbig_step1: forall env2 : env, big_step env0 s1 env2 -> env'0 = env2
H1_0: big_step env'0 s2 env''
H1_: big_step env0 s1 env'0
env2: env
H5: big_step env'0 s2 env2big_step env'0 s2 env2env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e <> 0
H1: big_step env0 s1 env'
IHbig_step: forall env2 : env, big_step env0 s1 env2 -> env' = env2
env2: env
H2: big_step env0 (If e s1 s2) env2env' = env2env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e <> 0
H1: big_step env0 s1 env'
IHbig_step: forall env2 : env, big_step env0 s1 env2 -> env' = env2
env2: env
H7: eval env0 e <> 0
H8: big_step env0 s1 env2env' = env2env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e <> 0
H1: big_step env0 s1 env'
IHbig_step: forall env2 : env, big_step env0 s1 env2 -> env' = env2
env2: env
H7: eval env0 e = 0
H8: big_step env0 s2 env2env' = env2env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e <> 0
H1: big_step env0 s1 env'
IHbig_step: forall env2 : env, big_step env0 s1 env2 -> env' = env2
env2: env
H7: eval env0 e <> 0
H8: big_step env0 s1 env2env' = env2apply H8.env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e <> 0
H1: big_step env0 s1 env'
IHbig_step: forall env2 : env, big_step env0 s1 env2 -> env' = env2
env2: env
H7: eval env0 e <> 0
H8: big_step env0 s1 env2big_step env0 s1 env2congruence.env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e <> 0
H1: big_step env0 s1 env'
IHbig_step: forall env2 : env, big_step env0 s1 env2 -> env' = env2
env2: env
H7: eval env0 e = 0
H8: big_step env0 s2 env2env' = env2env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e = 0
H1: big_step env0 s2 env'
IHbig_step: forall env2 : env, big_step env0 s2 env2 -> env' = env2
env2: env
H2: big_step env0 (If e s1 s2) env2env' = env2env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e = 0
H1: big_step env0 s2 env'
IHbig_step: forall env2 : env, big_step env0 s2 env2 -> env' = env2
env2: env
H7: eval env0 e <> 0
H8: big_step env0 s1 env2env' = env2env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e = 0
H1: big_step env0 s2 env'
IHbig_step: forall env2 : env, big_step env0 s2 env2 -> env' = env2
env2: env
H7: eval env0 e = 0
H8: big_step env0 s2 env2env' = env2congruence.env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e = 0
H1: big_step env0 s2 env'
IHbig_step: forall env2 : env, big_step env0 s2 env2 -> env' = env2
env2: env
H7: eval env0 e <> 0
H8: big_step env0 s1 env2env' = env2env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e = 0
H1: big_step env0 s2 env'
IHbig_step: forall env2 : env, big_step env0 s2 env2 -> env' = env2
env2: env
H7: eval env0 e = 0
H8: big_step env0 s2 env2env' = env2apply H8.env0: string -> nat
env': env
e: expr
s1, s2: stmt
H: eval env0 e = 0
H1: big_step env0 s2 env'
IHbig_step: forall env2 : env, big_step env0 s2 env2 -> env' = env2
env2: env
H7: eval env0 e = 0
H8: big_step env0 s2 env2big_step env0 s2 env2env0: string -> nat
env', env'': env
e: expr
s: stmt
H: eval env0 e <> 0
H1_: big_step env0 s env'
H1_0: big_step env' (While e s) env''
IHbig_step1: forall env2 : env, big_step env0 s env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' (While e s) env2 -> env'' = env2
env2: env
H2: big_step env0 (While e s) env2env'' = env2env0: string -> nat
env', env'': env
e: expr
s: stmt
H: eval env0 e <> 0
H1_: big_step env0 s env'
H1_0: big_step env' (While e s) env''
IHbig_step1: forall env2 : env, big_step env0 s env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' (While e s) env2 -> env'' = env2
env2, env'0: env
H3: eval env0 e <> 0
H5: big_step env0 s env'0
H7: big_step env'0 (While e s) env2env'' = env2env', env'': env
e: expr
s: stmt
env2: env
H1_: big_step env2 s env'
H: eval env2 e <> 0
H1_0: big_step env' (While e s) env''
IHbig_step1: forall env3 : env, big_step env2 s env3 -> env' = env3
IHbig_step2: forall env2 : env, big_step env' (While e s) env2 -> env'' = env2
H5: eval env2 e = 0env'' = env2env0: string -> nat
env', env'': env
e: expr
s: stmt
H: eval env0 e <> 0
H1_: big_step env0 s env'
H1_0: big_step env' (While e s) env''
IHbig_step1: forall env2 : env, big_step env0 s env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' (While e s) env2 -> env'' = env2
env2, env'0: env
H3: eval env0 e <> 0
H5: big_step env0 s env'0
H7: big_step env'0 (While e s) env2env'' = env2env0: string -> nat
env', env'': env
e: expr
s: stmt
H: eval env0 e <> 0
H1_: big_step env0 s env'
H1_0: big_step env' (While e s) env''
IHbig_step1: forall env2 : env, big_step env0 s env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' (While e s) env2 -> env'' = env2
env2, env'0: env
H3: eval env0 e <> 0
H5: big_step env0 s env'0
H7: big_step env'0 (While e s) env2big_step env' (While e s) env2env0: string -> nat
env', env'': env
e: expr
s: stmt
H: eval env0 e <> 0
H1_: big_step env0 s env'
H1_0: big_step env' (While e s) env''
IHbig_step1: forall env2 : env, big_step env0 s env2 -> env' = env2
IHbig_step2: forall env2 : env, big_step env' (While e s) env2 -> env'' = env2
env2, env'0: env
H3: eval env0 e <> 0
H5: env' = env'0
H7: big_step env'0 (While e s) env2big_step env' (While e s) env2apply H7.env0: string -> nat
env'': env
e: expr
s: stmt
H: eval env0 e <> 0
env'0: env
IHbig_step2: forall env2 : env, big_step env'0 (While e s) env2 -> env'' = env2
IHbig_step1: forall env2 : env, big_step env0 s env2 -> env'0 = env2
H1_0: big_step env'0 (While e s) env''
H1_: big_step env0 s env'0
env2: env
H3: eval env0 e <> 0
H7: big_step env'0 (While e s) env2big_step env'0 (While e s) env2congruence.env', env'': env
e: expr
s: stmt
env2: env
H1_: big_step env2 s env'
H: eval env2 e <> 0
H1_0: big_step env' (While e s) env''
IHbig_step1: forall env3 : env, big_step env2 s env3 -> env' = env3
IHbig_step2: forall env2 : env, big_step env' (While e s) env2 -> env'' = env2
H5: eval env2 e = 0env'' = env2env0: string -> nat
e: expr
s: stmt
H: eval env0 e = 0
env2: env
H2: big_step env0 (While e s) env2env0 = env2env0: string -> nat
e: expr
s: stmt
H: eval env0 e = 0
env2, env': env
H3: eval env0 e <> 0
H5: big_step env0 s env'
H7: big_step env' (While e s) env2env0 = env2e: expr
s: stmt
env2: env
H, H5: eval env2 e = 0env2 = env2congruence.env0: string -> nat
e: expr
s: stmt
H: eval env0 e = 0
env2, env': env
H3: eval env0 e <> 0
H5: big_step env0 s env'
H7: big_step env' (While e s) env2env0 = env2reflexivity. Qed.e: expr
s: stmt
env2: env
H, H5: eval env2 e = 0env2 = env2
Shorter proof
Ltac inv H := inversion H; clear H; simpeq.env: lec07_big_step.env
s: stmt
env1, env2: lec07_big_step.envbig_step env s env1 -> big_step env s env2 -> env1 = env2env: lec07_big_step.env
s: stmt
env1, env2: lec07_big_step.envbig_step env s env1 -> big_step env s env2 -> env1 = env2env: lec07_big_step.env
s: stmt
env1, env2: lec07_big_step.env
H1: big_step env s env1big_step env s env2 -> env1 = env2induction H1; intros env2 H2; inv H2; auto; assert (env' = env'0) as ->; auto. Qed.env: lec07_big_step.env
s: stmt
env1: lec07_big_step.env
H1: big_step env s env1forall env2 : lec07_big_step.env, big_step env s env2 -> env1 = env2
Definition equiv (s1 s2 : stmt) : Prop := forall env env', big_step env s1 env' <-> big_step env s2 env'.s1, s2, s3: stmtequiv (Seq (Seq s1 s2) s3) (Seq s1 (Seq s2 s3))s1, s2, s3: stmtequiv (Seq (Seq s1 s2) s3) (Seq s1 (Seq s2 s3))s1, s2, s3: stmtforall env0 env' : env, big_step env0 (Seq (Seq s1 s2) s3) env' <-> big_step env0 (Seq s1 (Seq s2 s3)) env's1, s2, s3: stmt
env0, env': envbig_step env0 (Seq (Seq s1 s2) s3) env' <-> big_step env0 (Seq s1 (Seq s2 s3)) env's1, s2, s3: stmt
env0, env': env
H: big_step env0 (Seq (Seq s1 s2) s3) env'big_step env0 (Seq s1 (Seq s2 s3)) env's1, s2, s3: stmt
env0, env': env
H: big_step env0 (Seq s1 (Seq s2 s3)) env'big_step env0 (Seq (Seq s1 s2) s3) env's1, s2, s3: stmt
env0, env': env
H: big_step env0 (Seq (Seq s1 s2) s3) env'big_step env0 (Seq s1 (Seq s2 s3)) env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 (Seq s1 s2) env'0
H5: big_step env'0 s3 env'big_step env0 (Seq s1 (Seq s2 s3)) env's1, s2, s3: stmt
env0, env', env'0: env
H5: big_step env'0 s3 env'
env'1: env
H2: big_step env0 s1 env'1
H6: big_step env'1 s2 env'0big_step env0 (Seq s1 (Seq s2 s3)) env's1, s2, s3: stmt
env0, env', env'0: env
H5: big_step env'0 s3 env'
env'1: env
H2: big_step env0 s1 env'1
H6: big_step env'1 s2 env'0big_step env0 s1 ?env's1, s2, s3: stmt
env0, env', env'0: env
H5: big_step env'0 s3 env'
env'1: env
H2: big_step env0 s1 env'1
H6: big_step env'1 s2 env'0big_step ?env' (Seq s2 s3) env'apply H2.s1, s2, s3: stmt
env0, env', env'0: env
H5: big_step env'0 s3 env'
env'1: env
H2: big_step env0 s1 env'1
H6: big_step env'1 s2 env'0big_step env0 s1 ?env's1, s2, s3: stmt
env0, env', env'0: env
H5: big_step env'0 s3 env'
env'1: env
H2: big_step env0 s1 env'1
H6: big_step env'1 s2 env'0big_step env'1 (Seq s2 s3) env's1, s2, s3: stmt
env0, env', env'0: env
H5: big_step env'0 s3 env'
env'1: env
H2: big_step env0 s1 env'1
H6: big_step env'1 s2 env'0big_step env'1 s2 ?env's1, s2, s3: stmt
env0, env', env'0: env
H5: big_step env'0 s3 env'
env'1: env
H2: big_step env0 s1 env'1
H6: big_step env'1 s2 env'0big_step ?env' s3 env'apply H6.s1, s2, s3: stmt
env0, env', env'0: env
H5: big_step env'0 s3 env'
env'1: env
H2: big_step env0 s1 env'1
H6: big_step env'1 s2 env'0big_step env'1 s2 ?env'apply H5.s1, s2, s3: stmt
env0, env', env'0: env
H5: big_step env'0 s3 env'
env'1: env
H2: big_step env0 s1 env'1
H6: big_step env'1 s2 env'0big_step env'0 s3 env's1, s2, s3: stmt
env0, env': env
H: big_step env0 (Seq s1 (Seq s2 s3)) env'big_step env0 (Seq (Seq s1 s2) s3) env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
H5: big_step env'0 (Seq s2 s3) env'big_step env0 (Seq (Seq s1 s2) s3) env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
env'1: env
H2: big_step env'0 s2 env'1
H6: big_step env'1 s3 env'big_step env0 (Seq (Seq s1 s2) s3) env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
env'1: env
H2: big_step env'0 s2 env'1
H6: big_step env'1 s3 env'big_step env0 (Seq s1 s2) ?env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
env'1: env
H2: big_step env'0 s2 env'1
H6: big_step env'1 s3 env'big_step ?env' s3 env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
env'1: env
H2: big_step env'0 s2 env'1
H6: big_step env'1 s3 env'big_step env0 (Seq s1 s2) ?env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
env'1: env
H2: big_step env'0 s2 env'1
H6: big_step env'1 s3 env'big_step env0 s1 ?env'0s1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
env'1: env
H2: big_step env'0 s2 env'1
H6: big_step env'1 s3 env'big_step ?env'0 s2 ?env'apply H3.s1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
env'1: env
H2: big_step env'0 s2 env'1
H6: big_step env'1 s3 env'big_step env0 s1 ?env'0apply H2.s1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
env'1: env
H2: big_step env'0 s2 env'1
H6: big_step env'1 s3 env'big_step env'0 s2 ?env'apply H6. Qed.s1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
env'1: env
H2: big_step env'0 s2 env'1
H6: big_step env'1 s3 env'big_step env'1 s3 env'
Shorter proof
s1, s2, s3: stmtequiv (Seq (Seq s1 s2) s3) (Seq s1 (Seq s2 s3))s1, s2, s3: stmtequiv (Seq (Seq s1 s2) s3) (Seq s1 (Seq s2 s3))s1, s2, s3: stmtforall env0 env' : env, big_step env0 (Seq (Seq s1 s2) s3) env' <-> big_step env0 (Seq s1 (Seq s2 s3)) env's1, s2, s3: stmt
env0, env': envbig_step env0 (Seq (Seq s1 s2) s3) env' <-> big_step env0 (Seq s1 (Seq s2 s3)) env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 (Seq s1 s2) env'0
H5: big_step env'0 s3 env'big_step env0 (Seq s1 (Seq s2 s3)) env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
H5: big_step env'0 (Seq s2 s3) env'big_step env0 (Seq (Seq s1 s2) s3) env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 (Seq s1 s2) env'0
H5: big_step env'0 s3 env'big_step env0 (Seq s1 (Seq s2 s3)) env'eauto using big_step.s1, s2, s3: stmt
env0, env', env'0: env
H5: big_step env'0 s3 env'
env'1: env
H2: big_step env0 s1 env'1
H6: big_step env'1 s2 env'0big_step env0 (Seq s1 (Seq s2 s3)) env's1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
H5: big_step env'0 (Seq s2 s3) env'big_step env0 (Seq (Seq s1 s2) s3) env'eauto using big_step. Qed.s1, s2, s3: stmt
env0, env', env'0: env
H3: big_step env0 s1 env'0
env'1: env
H2: big_step env'0 s2 env'1
H6: big_step env'1 s3 env'big_step env0 (Seq (Seq s1 s2) s3) env'
Definition ex1 := Seq (Assign "x" (Plus (Var "x") (Var "x"))) (Assign "x" (Plus (Var "x") (Var "x"))).env, env': lec07_big_step.envbig_step env ex1 env' <-> (forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x))env, env': lec07_big_step.envbig_step env ex1 env' <-> (forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x))env, env': lec07_big_step.envbig_step env ex1 env' -> forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)env, env': lec07_big_step.env(forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)) -> big_step env ex1 env'env, env': lec07_big_step.envbig_step env ex1 env' -> forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)env, env': lec07_big_step.env
H: big_step env ex1 env'forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)env, env', env'0: lec07_big_step.env
H3: big_step env (Assign "x" (Plus (Var "x") (Var "x"))) env'0
H5: big_step env'0 (Assign "x" (Plus (Var "x") (Var "x"))) env'forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)env, env': lec07_big_step.env
H5: big_step (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Assign "x" (Plus (Var "x") (Var "x"))) env'forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)env: lec07_big_step.envforall x : string, (if string_eq "x" x then eval (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Plus (Var "x") (Var "x")) else if string_eq "x" x then eval env (Plus (Var "x") (Var "x")) else env x) = (if string_eq x "x" then 4 * env "x" else env x)env: lec07_big_step.env
x: string(if string_eq "x" x then eval (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Plus (Var "x") (Var "x")) else if string_eq "x" x then eval env (Plus (Var "x") (Var "x")) else env x) = (if string_eq x "x" then 4 * env "x" else env x)lia.env: lec07_big_step.envenv "x" + env "x" + (env "x" + env "x") = env "x" + (env "x" + (env "x" + (env "x" + 0)))env, env': lec07_big_step.env(forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)) -> big_step env ex1 env'env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)big_step env ex1 env'env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)(exists env'' : lec07_big_step.env, big_step env ex1 env'' /\ env'' = env') -> big_step env ex1 env'env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)exists env'' : lec07_big_step.env, big_step env ex1 env'' /\ env'' = env'env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)(exists env'' : lec07_big_step.env, big_step env ex1 env'' /\ env'' = env') -> big_step env ex1 env'env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)
env'': lec07_big_step.env
H1: big_step env ex1 env''
H2: env'' = env'big_step env ex1 env'auto.env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)
H1: big_step env ex1 env'big_step env ex1 env'env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)exists env'' : lec07_big_step.env, big_step env ex1 env'' /\ env'' = env'env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)big_step env ex1 ?env'' /\ ?env'' = env'env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)big_step env ex1 ?env''env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)?env'' = env'eauto using big_step.env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)big_step env ex1 ?env''env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)(fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "x" var0 then eval env (Plus (Var "x") (Var "x")) else env var0) (Plus (Var "x") (Var "x")) else (fun var0 : string => if string_eq "x" var0 then eval env (Plus (Var "x") (Var "x")) else env var0) var) = env'env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)forall x : string, (if string_eq "x" x then eval (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Plus (Var "x") (Var "x")) else if string_eq "x" x then eval env (Plus (Var "x") (Var "x")) else env x) = env' xenv, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)
x: string(if string_eq "x" x then eval (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Plus (Var "x") (Var "x")) else if string_eq "x" x then eval env (Plus (Var "x") (Var "x")) else env x) = env' xenv, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)
x: string(if string_eq "x" x then eval (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Plus (Var "x") (Var "x")) else if string_eq "x" x then eval env (Plus (Var "x") (Var "x")) else env x) = (if string_eq x "x" then 4 * env "x" else env x)lia. Qed. Ltac run_big_step := match goal with | [ |- big_step ?env ?s ?env' ] => let H1 := fresh "H" in let H2 := fresh "H" in cut (exists env'', big_step env s env'' /\ env'' = env'); [ intros [env'' [H1 H2]]; subst; auto | eexists; split; eauto using big_step ] end.env, env': lec07_big_step.env
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)env "x" + env "x" + (env "x" + env "x") = env "x" + (env "x" + (env "x" + (env "x" + 0)))env, env': string -> nat(forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)) -> big_step env ex1 env'env, env': string -> nat(forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)) -> big_step env ex1 env'env, env': string -> nat
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)big_step env ex1 env'env, env': string -> nat
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)(fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "x" var0 then eval env (Plus (Var "x") (Var "x")) else env var0) (Plus (Var "x") (Var "x")) else (fun var0 : string => if string_eq "x" var0 then eval env (Plus (Var "x") (Var "x")) else env var0) var) = env'env, env': string -> nat
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)forall x : string, (if string_eq "x" x then eval (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Plus (Var "x") (Var "x")) else if string_eq "x" x then eval env (Plus (Var "x") (Var "x")) else env x) = env' xenv, env': string -> nat
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)
x: string(if string_eq "x" x then eval (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Plus (Var "x") (Var "x")) else if string_eq "x" x then eval env (Plus (Var "x") (Var "x")) else env x) = env' xenv, env': string -> nat
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)
x: string(if string_eq "x" x then eval (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Plus (Var "x") (Var "x")) else if string_eq "x" x then eval env (Plus (Var "x") (Var "x")) else env x) = (if string_eq x "x" then 4 * env "x" else env x)lia. Qed. (* Invert big step but only do it when it produces a single subgoal. *) Ltac inv_big_step := match goal with | [ H : big_step _ _ _ |- _ ] => inv H end.env, env': string -> nat
H: forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)env "x" + env "x" + (env "x" + env "x") = env "x" + (env "x" + (env "x" + (env "x" + 0)))env, env': lec07_big_step.envbig_step env ex1 env' -> forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)env, env': lec07_big_step.envbig_step env ex1 env' -> forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)env, env': lec07_big_step.env
H: big_step env ex1 env'forall x : string, env' x = (if string_eq x "x" then 4 * env "x" else env x)env: lec07_big_step.envforall x : string, (if string_eq "x" x then eval (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Plus (Var "x") (Var "x")) else if string_eq "x" x then eval env (Plus (Var "x") (Var "x")) else env x) = (if string_eq x "x" then 4 * env "x" else env x)env: lec07_big_step.env
x: string(if string_eq "x" x then eval (fun var : string => if string_eq "x" var then eval env (Plus (Var "x") (Var "x")) else env var) (Plus (Var "x") (Var "x")) else if string_eq "x" x then eval env (Plus (Var "x") (Var "x")) else env x) = (if string_eq x "x" then 4 * env "x" else env x)lia. Qed.env: lec07_big_step.envenv "x" + env "x" + (env "x" + env "x") = env "x" + (env "x" + (env "x" + (env "x" + 0)))
Definition ex2 body := While (Const 1) body.env, env': lec07_big_step.env
body: stmt~ big_step env (ex2 body) env'env, env': lec07_big_step.env
body: stmt~ big_step env (ex2 body) env'env, env': lec07_big_step.env
body: stmt
H: big_step env (ex2 body) env'Falseenv, env': lec07_big_step.env
body, e: stmt
Heqe: e = ex2 body
H: big_step env e env'Falsebody: stmt
e: expr
s: stmt
Heqe: While e s = ex2 body
env0: string -> nat
H: eval env0 e = 0Falsebody: stmt
e: expr
s: stmt
Heqe: While e s = While (Const 1) body
env0: string -> nat
H: eval env0 e = 0Falsebody: stmt
e: expr
s: stmt
HH: e = Const 1
H0: s = body
env0: string -> nat
H: eval env0 e = 0Falsebody: stmt
env0: string -> nat
H: eval env0 (Const 1) = 0Falsediscriminate. Qed.body: stmt
env0: string -> nat
H: 1 = 0False
Definition ex3:= While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))).env, env': lec07_big_step.envbig_step env ex3 env' <-> env' "y" = env "y" + env "x" * env "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env x)env, env': lec07_big_step.envbig_step env ex3 env' <-> env' "y" = env "y" + env "x" * env "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env x)env, env': lec07_big_step.envbig_step env ex3 env' -> env' "y" = env "y" + env "x" * env "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env x)env, env': lec07_big_step.envenv' "y" = env "y" + env "x" * env "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env x) -> big_step env ex3 env'env, env': lec07_big_step.envbig_step env ex3 env' -> env' "y" = env "y" + env "x" * env "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env x)env, env': lec07_big_step.envbig_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env "y" + env "x" * env "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env x)env, env': lec07_big_step.env
x: nat
Heqx: x = env "x"big_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env "y" + x * env "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env x)x: natforall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)env0, env': env
Heqx: 0 = env0 "x"
H: big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' "y" = env0 "y" + 0 * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
H: big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' "y" = env0 "y" + S x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)env0, env': env
Heqx: 0 = env0 "x"
H: big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' "y" = env0 "y" + 0 * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)env0, env': env
Heqx: 0 = env0 "x"
env'0: env
H2: eval env0 (Var "x") <> 0
H4: big_step env0 (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))) env'0
H6: big_step env'0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' "y" = env0 "y" + 0 * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)env': env
Heqx: 0 = env' "x"
H4: eval env' (Var "x") = 0env' "y" = env' "y" + 0 * env' "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env' x)env0, env': env
Heqx: 0 = env0 "x"
env'0: env
H2: eval env0 (Var "x") <> 0
H4: big_step env0 (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))) env'0
H6: big_step env'0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' "y" = env0 "y" + 0 * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)simpeq.env0, env': env
Heqx: 0 = env0 "x"
env'0: env
H2: env0 "x" <> 0
H4: big_step env0 (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))) env'0
H6: big_step env'0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' "y" = env0 "y" + 0 /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)env': env
Heqx: 0 = env' "x"
H4: eval env' (Var "x") = 0env' "y" = env' "y" + 0 * env' "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env' x)env': env
Heqx: 0 = env' "x"
H4: env' "x" = 0env' "y" = env' "y" + 0 /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env' x)env': env
Heqx: 0 = env' "x"
H4: env' "x" = 0env' "y" = env' "y" + 0env': env
Heqx: 0 = env' "x"
H4: env' "x" = 0env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env' x)env': env
Heqx: 0 = env' "x"
H4: env' "x" = 0env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env' x)env': env
Heqx: 0 = env' "x"
H4: env' "x" = 0env' "x" = 0env': env
Heqx: 0 = env' "x"
H4: env' "x" = 0forall x : string, x <> "x" -> x <> "y" -> env' x = env' xlia.env': env
Heqx: 0 = env' "x"
H4: env' "x" = 0forall x : string, x <> "x" -> x <> "y" -> env' x = env' xx: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
H: big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' "y" = env0 "y" + S x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
env'0: env
H2: eval env0 (Var "x") <> 0
H4: big_step env0 (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))) env'0
H6: big_step env'0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' "y" = env0 "y" + S x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env': env
Heqx: S x = env' "x"
H4: eval env' (Var "x") = 0env' "y" = env' "y" + S x * env' "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env' x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
env'0: env
H2: eval env0 (Var "x") <> 0
H4: big_step env0 (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))) env'0
H6: big_step env'0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' "y" = env0 "y" + S x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
env'0: env
H2: eval env0 (Var "x") <> 0
H6: big_step env'0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env'1: env
H3: big_step env0 (Assign "y" (Plus (Var "y") (Var "z"))) env'1
H7: big_step env'1 (Assign "x" (Minus (Var "x") (Const 1))) env'0env' "y" = env0 "y" + S x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
env'0: env
H2: eval env0 (Var "x") <> 0
H6: big_step env'0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
H7: big_step (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Assign "x" (Minus (Var "x") (Const 1))) env'0env' "y" = env0 "y" + S x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
H2: eval env0 (Var "x") <> 0
H6: big_step (fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) (Minus (Var "x") (Const 1)) else if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' "y" = env0 "y" + S x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
H2: env0 "x" <> 0
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
H6: env' "y" = env0 "y" + env0 "z" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = (if string_eq "x" x then (if string_eq "y" "x" then env0 "y" + env0 "z" else env0 "x") - 1 else if string_eq "y" x then env0 "y" + env0 "z" else env0 x))env' "y" = env0 "y" + (env0 "z" + x * env0 "z") /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
H2: env0 "x" <> 0
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
H: env' "y" = env0 "y" + env0 "z" + x * env0 "z"
H0: env' "x" = 0
H1: forall x : string, x <> "x" -> x <> "y" -> env' x = (if string_eq "x" x then (if string_eq "y" "x" then env0 "y" + env0 "z" else env0 "x") - 1 else if string_eq "y" x then env0 "y" + env0 "z" else env0 x)env' "y" = env0 "y" + (env0 "z" + x * env0 "z") /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
H2: env0 "x" <> 0
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
H: env' "y" = env0 "y" + env0 "z" + x * env0 "z"
H0: env' "x" = 0
H1: forall x : string, x <> "x" -> x <> "y" -> env' x = (if string_eq "x" x then (if string_eq "y" "x" then env0 "y" + env0 "z" else env0 "x") - 1 else if string_eq "y" x then env0 "y" + env0 "z" else env0 x)env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
H2: env0 "x" <> 0
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
H: env' "y" = env0 "y" + env0 "z" + x * env0 "z"
H0: env' "x" = 0
H1: forall x : string, x <> "x" -> x <> "y" -> env' x = (if string_eq "x" x then (if string_eq "y" "x" then env0 "y" + env0 "z" else env0 "x") - 1 else if string_eq "y" x then env0 "y" + env0 "z" else env0 x)forall x : string, x <> "x" -> x <> "y" -> env' x = env0 xx: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
H2: env0 "x" <> 0
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
H: env' "y" = env0 "y" + env0 "z" + x * env0 "z"
H0: env' "x" = 0
H1: forall x : string, x <> "x" -> x <> "y" -> env' x = (if string_eq "x" x then (if string_eq "y" "x" then env0 "y" + env0 "z" else env0 "x") - 1 else if string_eq "y" x then env0 "y" + env0 "z" else env0 x)
x0: string
H3: x0 <> "x"
H4: x0 <> "y"env' x0 = env0 x0x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
H2: env0 "x" <> 0
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
H: env' "y" = env0 "y" + env0 "z" + x * env0 "z"
H0: env' "x" = 0
x0: string
H1: x0 <> "x" -> x0 <> "y" -> env' x0 = (if string_eq "x" x0 then (if string_eq "y" "x" then env0 "y" + env0 "z" else env0 "x") - 1 else if string_eq "y" x0 then env0 "y" + env0 "z" else env0 x0)
H3: x0 <> "x"
H4: x0 <> "y"env' x0 = env0 x0auto.x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env0, env': env
Heqx: S x = env0 "x"
H2: env0 "x" <> 0
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
H: env' "y" = env0 "y" + env0 "z" + x * env0 "z"
H0: env' "x" = 0
x0: string
n2: "x" <> x0
n3: "y" <> x0
H1: x0 <> "x" -> x0 <> "y" -> env' x0 = env0 x0
H3: x0 <> "x"
H4: x0 <> "y"env' x0 = env0 x0x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env': env
Heqx: S x = env' "x"
H4: eval env' (Var "x") = 0env' "y" = env' "y" + S x * env' "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env' x)simpeq.x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
env': env
Heqx: S x = env' "x"
H4: env' "x" = 0env' "y" = env' "y" + (env' "z" + x * env' "z") /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env' x)env, env': lec07_big_step.envenv' "y" = env "y" + env "x" * env "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env x) -> big_step env ex3 env'env, env': lec07_big_step.envenv' "y" = env "y" + env "x" * env "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env x) -> big_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env, env': lec07_big_step.env
x: nat
Heqx: x = env "x"env' "y" = env "y" + x * env "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env x) -> big_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: natforall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env0, env': env
Heqx: 0 = env0 "x"
H: env' "y" = env0 "y" + 0 * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: env' "y" = env0 "y" + S x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env0, env': env
Heqx: 0 = env0 "x"
H: env' "y" = env0 "y" + 0 * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env0, env': env
Heqx: 0 = env0 "x"
H: env' "y" = env0 "y" + 0 * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)env0 = env'env0, env': env
Heqx: 0 = env0 "x"
H: env' "y" = env0 "y" + 0 * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)forall x : string, env0 x = env' xenv0, env': env
Heqx: 0 = env0 "x"
H: env' "y" = env0 "y" + 0 * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)
x: stringenv0 x = env' xenv0, env': env
Heqx: 0 = env0 "x"
H1: env' "y" = env0 "y" + 0 * env0 "z"
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x
x: stringenv0 x = env' xenv0, env': env
Heqx: 0 = env0 "x"
H1: env' "y" = env0 "y" + 0 * env0 "z"
H2: env' "x" = 0
x: string
H3: x <> "x" -> x <> "y" -> env' x = env0 xenv0 x = env' xenv0, env': env
Heqx: 0 = env0 "x"
H1: env' "y" = env0 "y" + 0 * env0 "z"
H2: env' "x" = 0
x: string
H3: x <> "x" -> x <> "y" -> env' x = env0 x
n: x <> "x"env0 x = env' xenv0, env': env
Heqx: 0 = env0 "x"
H1: env' "y" = env0 "y" + 0 * env0 "z"
H2: env' "x" = 0
x: string
H3: x <> "x" -> x <> "y" -> env' x = env0 x
n: x <> "x"
n0: x <> "y"env0 x = env' xauto.env0, env': env
Heqx: 0 = env0 "x"
H1: env' "y" = env0 "y" + 0 * env0 "z"
H2: env' "x" = 0
x: string
H3: x <> "x" -> x <> "y" -> env' x = env0 x
n: x <> "x"
n0: x <> "y"env' x = env0 xx: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: env' "y" = env0 "y" + S x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x)big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + S x * env0 "z"
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 xbig_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 xbig_step env0 (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))) ?env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 xbig_step ?env' (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 xbig_step env0 (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))) ?env'reflexivity.x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x(fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) (Minus (Var "x") (Const 1)) else (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) var) = ?env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 xbig_step (fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) (Minus (Var "x") (Const 1)) else if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
n2: "y" <> "x"env' "y" = env0 "y" + env0 "z" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = (if string_eq "x" x then env0 "x" - 1 else if string_eq "y" x then env0 "y" + env0 "z" else env0 x))x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
n2: "y" <> "x"env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = (if string_eq "x" x then env0 "x" - 1 else if string_eq "y" x then env0 "y" + env0 "z" else env0 x))x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
n2: "y" <> "x"forall x : string, x <> "x" -> x <> "y" -> env' x = (if string_eq "x" x then env0 "x" - 1 else if string_eq "y" x then env0 "y" + env0 "z" else env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
H3: forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
n2: "y" <> "x"
x0: string
H: x0 <> "x"
H0: x0 <> "y"env' x0 = (if string_eq "x" x0 then env0 "x" - 1 else if string_eq "y" x0 then env0 "y" + env0 "z" else env0 x0)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
x0: string
H3: x0 <> "x" -> x0 <> "y" -> env' x0 = env0 x0
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
n2: "y" <> "x"
H: x0 <> "x"
H0: x0 <> "y"env' x0 = (if string_eq "x" x0 then env0 "x" - 1 else if string_eq "y" x0 then env0 "y" + env0 "z" else env0 x0)auto. Qed.x: nat
IHx: forall env0 env' : env, x = env0 "x" -> env' "y" = env0 "y" + x * env0 "z" /\ env' "x" = 0 /\ (forall x : string, x <> "x" -> x <> "y" -> env' x = env0 x) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H1: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
H2: env' "x" = 0
x0: string
H3: x0 <> "x" -> x0 <> "y" -> env' x0 = env0 x0
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
n2: "y" <> "x"
H: x0 <> "x"
H0: x0 <> "y"
n3: "x" <> x0
n4: "y" <> x0env' x0 = env0 x0
Shorter proof
env, env': lec07_big_step.envbig_step env ex3 env' <-> (forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env "y" + env "x" * env "z" else env x))env, env': lec07_big_step.envbig_step env ex3 env' <-> (forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env "y" + env "x" * env "z" else env x))env, env': lec07_big_step.envbig_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' <-> (forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env "y" + env "x" * env "z" else env x))env, env': lec07_big_step.envbig_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env "y" + env "x" * env "z" else env x)env, env': lec07_big_step.env(forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env "y" + env "x" * env "z" else env x)) -> big_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env, env': lec07_big_step.envbig_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env "y" + env "x" * env "z" else env x)env, env': lec07_big_step.env
x: nat
Heqx: x = env "x"big_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env "y" + x * env "z" else env x0)x: natforall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)env0, env': env
Heqx: 0 = env0 "x"
H: big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
x: stringenv' x = (if string_eq x "x" then 0 else if string_eq x "y" then env0 "y" + 0 * env0 "z" else env0 x)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
H: big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
x0: stringenv' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + S x * env0 "z" else env0 x0)env0, env': env
Heqx: 0 = env0 "x"
H: big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
x: stringenv' x = (if string_eq x "x" then 0 else if string_eq x "y" then env0 "y" + 0 * env0 "z" else env0 x)env': env
Heqx: 0 = env' "x"
x: string
H4: env' "x" = 0env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env' "y" + 0 else env' x)lia.env': env
Heqx: 0 = env' "x"
H4: env' "x" = 0
n: "y" <> "x"env' "y" = env' "y" + 0x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
H: big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
x0: stringenv' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + S x * env0 "z" else env0 x0)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
x0: string
env'0: env
H2: env0 "x" <> 0
H4: big_step env0 (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))) env'0
H6: big_step env'0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
x0: string
env'0: env
H2: env0 "x" <> 0
H6: big_step env'0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env'1: env
H3: big_step env0 (Assign "y" (Plus (Var "y") (Var "z"))) env'1
H7: big_step env'1 (Assign "x" (Minus (Var "x") (Const 1))) env'0env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
x0: string
env'0: env
H2: env0 "x" <> 0
H6: big_step env'0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
H7: big_step (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Assign "x" (Minus (Var "x") (Const 1))) env'0env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
x0: string
H2: env0 "x" <> 0
H6: big_step (fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) (Minus (Var "x") (Const 1)) else if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
x0: string
H2: env0 "x" <> 0
H6: env' ?x = (if string_eq ?x "x" then 0 else if string_eq ?x "y" then (if string_eq "x" "y" then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" "y" then eval env0 (Plus (Var "y") (Var "z")) else env0 "y") + x * (if string_eq "x" "z" then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" "z" then eval env0 (Plus (Var "y") (Var "z")) else env0 "z") else if string_eq "x" ?x then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" ?x then eval env0 (Plus (Var "y") (Var "z")) else env0 ?x)env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
x0: string
H2: env0 "x" <> 0
H6: big_step (fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) (Minus (Var "x") (Const 1)) else if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x = (if string_eq "x" "x" then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" "x" then eval env0 (Plus (Var "y") (Var "z")) else env0 "x")x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
x0: string
H2: env0 "x" <> 0
H6: env' ?x = (if string_eq ?x "x" then 0 else if string_eq ?x "y" then (if string_eq "x" "y" then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" "y" then eval env0 (Plus (Var "y") (Var "z")) else env0 "y") + x * (if string_eq "x" "z" then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" "z" then eval env0 (Plus (Var "y") (Var "z")) else env0 "z") else if string_eq "x" ?x then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" ?x then eval env0 (Plus (Var "y") (Var "z")) else env0 ?x)env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
x0: string
H2: env0 "x" <> 0
H6: env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then (if string_eq "x" "y" then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" "y" then eval env0 (Plus (Var "y") (Var "z")) else env0 "y") + x * (if string_eq "x" "z" then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" "z" then eval env0 (Plus (Var "y") (Var "z")) else env0 "z") else if string_eq "x" x0 then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" x0 then eval env0 (Plus (Var "y") (Var "z")) else env0 x0)(if string_eq x0 "x" then 0 else if string_eq x0 "y" then (if string_eq "x" "y" then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" "y" then eval env0 (Plus (Var "y") (Var "z")) else env0 "y") + x * (if string_eq "x" "z" then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" "z" then eval env0 (Plus (Var "y") (Var "z")) else env0 "z") else if string_eq "x" x0 then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" x0 then eval env0 (Plus (Var "y") (Var "z")) else env0 x0) = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)lia.x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
H2: env0 "x" <> 0
n: "y" <> "x"
n0: "x" <> "y"
n1: "x" <> "z"
n2: "y" <> "z"
H6: env' "y" = eval env0 (Plus (Var "y") (Var "z")) + x * env0 "z"env0 "y" + env0 "z" + x * env0 "z" = env0 "y" + (env0 "z" + x * env0 "z")x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
x0: string
H2: env0 "x" <> 0
H6: big_step (fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) (Minus (Var "x") (Const 1)) else if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x = (if string_eq "x" "x" then eval (fun var : string => if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (Minus (Var "x") (Const 1)) else if string_eq "y" "x" then eval env0 (Plus (Var "y") (Var "z")) else env0 "x")lia.x: nat
IHx: forall env0 env' : env, x = env0 "x" -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env' -> forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)
env0, env': env
Heqx: S x = env0 "x"
x0: string
H2: env0 "x" <> 0
H6: big_step (fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) (Minus (Var "x") (Const 1)) else if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
n: "y" <> "x"x = env0 "x" - 1env, env': lec07_big_step.env(forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env "y" + env "x" * env "z" else env x)) -> big_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env, env': lec07_big_step.env
x: nat
Heqx: x = env "x"(forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env "y" + x * env "z" else env x0)) -> big_step env (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: natforall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env0, env': env
Heqx: 0 = env0 "x"
H: forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env0 "y" + 0 * env0 "z" else env0 x)big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + S x * env0 "z" else env0 x0)big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env0, env': env
Heqx: 0 = env0 "x"
H: forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env0 "y" + 0 * env0 "z" else env0 x)big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'env0, env': env
Heqx: 0 = env0 "x"
H: forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env0 "y" + 0 * env0 "z" else env0 x)env0 = env'env0, env': env
Heqx: 0 = env0 "x"
H: forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env0 "y" + 0 * env0 "z" else env0 x)forall x : string, env0 x = env' xenv0, env': env
Heqx: 0 = env0 "x"
H: forall x : string, env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env0 "y" + 0 * env0 "z" else env0 x)
x: stringenv0 x = env' xenv0, env': env
Heqx: 0 = env0 "x"
x: string
H: env' x = (if string_eq x "x" then 0 else if string_eq x "y" then env0 "y" + 0 * env0 "z" else env0 x)env0 x = env' xlia.env0, env': env
Heqx: 0 = env0 "x"
n: "y" <> "x"
H: env' "y" = env0 "y" + 0 * env0 "z"env0 "y" = env' "y"x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + S x * env0 "z" else env0 x0)big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)big_step env0 (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))) ?env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)big_step ?env' (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)big_step env0 (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1)))) ?env'reflexivity.x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)(fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) (Minus (Var "x") (Const 1)) else (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) var) = ?env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)big_step (fun var : string => if string_eq "x" var then eval (fun var0 : string => if string_eq "y" var0 then eval env0 (Plus (Var "y") (Var "z")) else env0 var0) (Minus (Var "x") (Const 1)) else if string_eq "y" var then eval env0 (Plus (Var "y") (Var "z")) else env0 var) (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
n2: "y" <> "x"forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + env0 "z" + x * env0 "z" else if string_eq "x" x0 then env0 "x" - 1 else if string_eq "y" x0 then env0 "y" + env0 "z" else env0 x0)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
H: forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 x0)
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
n2: "y" <> "x"
y: stringenv' y = (if string_eq y "x" then 0 else if string_eq y "y" then env0 "y" + env0 "z" + x * env0 "z" else if string_eq "x" y then env0 "x" - 1 else if string_eq "y" y then env0 "y" + env0 "z" else env0 y)x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
y: string
H: env' y = (if string_eq y "x" then 0 else if string_eq y "y" then env0 "y" + (env0 "z" + x * env0 "z") else env0 y)
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
n2: "y" <> "x"env' y = (if string_eq y "x" then 0 else if string_eq y "y" then env0 "y" + env0 "z" + x * env0 "z" else if string_eq "x" y then env0 "x" - 1 else if string_eq "y" y then env0 "y" + env0 "z" else env0 y)lia. Qed.x: nat
IHx: forall env0 env' : env, x = env0 "x" -> (forall x0 : string, env' x0 = (if string_eq x0 "x" then 0 else if string_eq x0 "y" then env0 "y" + x * env0 "z" else env0 x0)) -> big_step env0 (While (Var "x") (Seq (Assign "y" (Plus (Var "y") (Var "z"))) (Assign "x" (Minus (Var "x") (Const 1))))) env'
env0, env': env
Heqx: S x = env0 "x"
n3: "y" <> "x"
H: env' "y" = env0 "y" + (env0 "z" + x * env0 "z")
n: "x" <> "y"
n0: "x" <> "z"
n1: "y" <> "z"
n2: "y" <> "x"env' "y" = env0 "y" + env0 "z" + x * env0 "z"