0

I cannot solve a Coq Theorem where I should use denotational semantics. If I go forward from this point I am always stucking in an endless loop.

What tactic should be used in this case? Where did I go wrong with this one? Should I start differently?

From Coq Require Import Strings.String
                        Arith.PeanoNat
                        Arith.Plus.

Definition Ident : Type := string.

Inductive AExp : Type :=
| ALit (n : nat)
| AVar (s : Ident)
| APlus (a1 a2 : AExp)
| ADup (n : AExp)
.

Definition State := Ident -> nat.

Definition empty : State := fun x => 0.

Definition aState : State := 
fun x =>
  match x with
  | "X"%string => 1
  | "Y"%string => 2
  | "Z"%string => 42
  | _ => 0
  end
.

Definition X:Ident := "X"%string.
Definition Y:Ident := "Y"%string.
Definition Z:Ident := "Z"%string.

Fixpoint val (a : AExp) (s : State) : nat :=
match a with
| ALit n => n
| AVar x => s x
| APlus a1 a2 => val a1 s + val a2 s
| ADup a => val a s + val a s
end.

Fixpoint aqb (a1 a2 : AExp) : bool :=
match a1, a2 with
| ALit n, ALit m => Nat.eqb n m
| AVar s, AVar x => String.eqb s x
| APlus a1 a2, APlus a1' a2' => aqb a1 a1' && aqb a2 a2'
| ADup a1, ADup a1' => aqb a1 a1'
| _, _ => false
end.

Fixpoint optmal (a : AExp) : AExp :=
match a with
| APlus a1 a2 => 
  if aqb a1 a2
  then ADup (optmal a1)
  else APlus (optmal a1) (optmal a2)
| ADup a0 => ADup (optmal a0)
| _ => a
end.

Theorem optmald :
  forall a s, val a s = val (optmal a) s.
Proof.
intros. unfold val. induction a.
* simpl. reflexivity.
* simpl. reflexivity.
* 

James Z
  • 12,209
  • 10
  • 24
  • 44
steve01
  • 1
  • 1

2 Answers2

0

First, instead of unfold val, it's better to rely on simpl after induction to simplify things, as that generally leads to goals that are easier to read.

Theorem optmald :
  forall a s, val a s = val (optmal a) s.
Proof.
intros. induction a; simpl.
* reflexivity.
* reflexivity.
* 

Now the goal looks like

val a1 s + val a2 s =
val (if aqb a1 a2 then ADup (optmal a1) else APlus (optmal a1) (optmal a2)) s

When there is an if (or a match) in the goal, one often good step is to destruct the scrutinee:

destruct (aqb a1 a2) eqn:Ea.
Li-yao Xia
  • 31,896
  • 2
  • 33
  • 56
  • Thank you! It indeed looks better, however now I always reach the following, where I am stucked again: `n + n0 = n + n` Do you might have any other suggestion? – steve01 Apr 03 '21 at 16:43
  • In the case where `aqb a1 a2` is true, you would expect that `a1` and `a2` evaluate to the same result. That's a separate lemma you can prove. – Li-yao Xia Apr 03 '21 at 17:06
  • Hi, thank you! Cannot it be proven in the same Theorem? I want to apply Ea in this case but does not let me. It should be logical. Isn't it? `Theorem optmald : forall a s, val a s = val (optmal a) s. Proof. intros. induction a. * simpl. reflexivity. * simpl. reflexivity. * simpl. destruct (aqb a1 a2) eqn:Ea. ** destruct a1. *** simpl. destruct a2. **** simpl in *.` Ea : (n =? n0) = true ______________________________________(1/1) n + n0 = n + n – steve01 Apr 03 '21 at 17:19
  • No, it's subtle but `(n =? n0) = true` and `n = n0` mean different things and the fact that they are logically equivalent is a fact that needs to be proved explicitly (otherwise, one might define `Nat.eqb` so that it is not true). The version for `Nat.eqb` is in the standard library (`Search Nat.eqb.`) but you will need to prove a similar lemma for `aqb` yourself to be able to "apply `Ea`". – Li-yao Xia Apr 03 '21 at 17:49
  • Hi, you are right! Those parts have been added as well, but still stucked in the loop. Please help, I just cannot figure out. I have added the next part in another answer. – steve01 Apr 03 '21 at 19:06
  • `apply aqb_eq in Ea.` or something like that. – Li-yao Xia Apr 04 '21 at 01:21
0

The theorem follows by induction on a. However, it is useful to first prove the lemma aeq_val first. It follows by induction on a1 and considering the cases of a2 and whether or not the branches of a1 and a2 are equal. All of the rewriteing can be handled automatically by congruence which is a tactic that can solve many goals that only require reasoning about equalities and reflexivity.

Lemma aeq_val : forall  a1 a2 s, aqb a1 a2 = true -> val (optmal a2) s = val (optmal a1) s.
  induction a1; destruct a2; simpl; try congruence; intros ? H.
  - apply eq_sym, EqNat.beq_nat_eq, eq_sym, H. 
  - apply eq_sym, f_equal, String.eqb_eq, H.
  - destruct (andb_prop _ _ H) as [H1 H2].
    apply aqb_eq in H1; apply aqb_eq in H2.
    destruct (aqb a2_1 a2_2) eqn:Hx;
      destruct (aqb a1_1 a1_2) eqn:Hy;
      congruence.
  - apply aqb_eq in H; congruence.
Qed.


Theorem optmald :
  forall a s, val a s = val (optmal a) s.
Proof.
  induction a; intros ?; simpl; auto.
  destruct (aqb a1 a2) eqn:H;
    rewrite IHa1, IHa2; auto;
      clear IHa1 IHa2.
  simpl; apply f_equal, aeq_val; auto.
Qed.  
larsr
  • 5,447
  • 19
  • 38