Inductive aexp' : Type :=
  | ANum : nat -> aexp'
  | APlus : aexp' -> aexp' -> aexp'
  | AMinus : aexp' -> aexp' -> aexp'
  | AMult : aexp' -> aexp' -> aexp'.Inductive aexp' : Type :=
  | ANum : nat -> aexp'
  | APlus : aexp' -> aexp' -> aexp'
  | AMinus : aexp' -> aexp' -> aexp'
  | AMult : aexp' -> aexp' -> aexp'.Inductive aexp' : Type :=
  | ANum : nat -> aexp'
  | APlus : aexp' -> aexp' -> aexp'
  | AMinus : aexp' -> aexp' -> aexp'
  | AMult : aexp' -> aexp' -> aexp'.Inductive aexp' : Type :=
  | ANum : nat -> aexp'
  | APlus : aexp' -> aexp' -> aexp'
  | AMinus : aexp' -> aexp' -> aexp'
  | AMult : aexp' -> aexp' -> aexp'.Inductive aexp' : Type :=
  | ANum : nat -> aexp'
  | APlus : aexp' -> aexp' -> aexp'
  | AMinus : aexp' -> aexp' -> aexp'
  | AMult : aexp' -> aexp' -> aexp'.Instance dec_eq_aex (x y : aexp') : Dec (x = y).(* AEC Reviewer example *)
Inductive aexpEq : aexp' -> aexp' -> Prop := 
 | ANumEq : forall n1 n2, n1 = n2 -> aexpEq (ANum n1) (ANum n2).(* AEC Reviewer example *)
Inductive aexpEq : aexp' -> aexp' -> Prop := 
 | ANumEq : forall n1 n2, n1 = n2 -> aexpEq (ANum n1) (ANum n2).Instance dec_aexpEq (x y : aexp') : Dec (aexpEq x y).Conjecture aexpEq_refl : forall x, aexpEq x x.Conjecture aexpEq_eq : forall x x', aexpEq x x' -> x = x'.(* End Reviwer example *)

Inductive bexp' : Type :=
  | BTrue : bexp'
  | BFalse : bexp'
  | BEq : aexp' -> aexp' -> bexp'
  | BLe : aexp' -> aexp' -> bexp'
  | BNot : bexp' -> bexp'
  | BAnd : bexp' -> bexp' -> bexp'.(* End Reviwer example *)

Inductive bexp' : Type :=
  | BTrue : bexp'
  | BFalse : bexp'
  | BEq : aexp' -> aexp' -> bexp'
  | BLe : aexp' -> aexp' -> bexp'
  | BNot : bexp' -> bexp'
  | BAnd : bexp' -> bexp' -> bexp'.(* End Reviwer example *)

Inductive bexp' : Type :=
  | BTrue : bexp'
  | BFalse : bexp'
  | BEq : aexp' -> aexp' -> bexp'
  | BLe : aexp' -> aexp' -> bexp'
  | BNot : bexp' -> bexp'
  | BAnd : bexp' -> bexp' -> bexp'.(* End Reviwer example *)

Inductive bexp' : Type :=
  | BTrue : bexp'
  | BFalse : bexp'
  | BEq : aexp' -> aexp' -> bexp'
  | BLe : aexp' -> aexp' -> bexp'
  | BNot : bexp' -> bexp'
  | BAnd : bexp' -> bexp' -> bexp'.(* End Reviwer example *)

Inductive bexp' : Type :=
  | BTrue : bexp'
  | BFalse : bexp'
  | BEq : aexp' -> aexp' -> bexp'
  | BLe : aexp' -> aexp' -> bexp'
  | BNot : bexp' -> bexp'
  | BAnd : bexp' -> bexp' -> bexp'.(* End Reviwer example *)

Inductive bexp' : Type :=
  | BTrue : bexp'
  | BFalse : bexp'
  | BEq : aexp' -> aexp' -> bexp'
  | BLe : aexp' -> aexp' -> bexp'
  | BNot : bexp' -> bexp'
  | BAnd : bexp' -> bexp' -> bexp'.(* End Reviwer example *)

Inductive bexp' : Type :=
  | BTrue : bexp'
  | BFalse : bexp'
  | BEq : aexp' -> aexp' -> bexp'
  | BLe : aexp' -> aexp' -> bexp'
  | BNot : bexp' -> bexp'
  | BAnd : bexp' -> bexp' -> bexp'.Instance dec_eq_bexp (x y : bexp') : Dec (x = y).Fixpoint aeval (a : aexp') : nat :=
  match a with
  | ANum n => n
  | APlus a1 a2 => (aeval a1) + (aeval a2)
  | AMinus a1 a2  => (aeval a1) - (aeval a2)
  | AMult a1 a2 => (aeval a1) * (aeval a2)
  end.Fixpoint beval (b : bexp') : bool :=
  match b with
  | BTrue       => true
  | BFalse      => false
  | BEq a1 a2   => beq_nat (aeval a1) (aeval a2)
  | BLe a1 a2   => leb (aeval a1) (aeval a2)
  | BNot b1     => negb (beval b1)
  | BAnd b1 b2  => andb (beval b1) (beval b2)
  end.Fixpoint optimize_0plus (a:aexp') : aexp' :=
  match a with
  | ANum n =>
      ANum n
  | APlus (ANum 0) e2 =>
      optimize_0plus e2
  | APlus e1 e2 =>
      APlus (optimize_0plus e1) (optimize_0plus e2)
  | AMinus e1 e2 =>
      AMinus (optimize_0plus e1) (optimize_0plus e2)
  | AMult e1 e2 =>
      AMult (optimize_0plus e1) (optimize_0plus e2)
  end.

Theorem optimize_0plus_sound: forall a, aeval (optimize_0plus a) = aeval a.