How to finish this simple proof involving booleans - boolean

This is my progress on an exercise from here: https://github.com/userhr/MIT-6.826-2017
(** **** Exercise: 2 stars (andb_true_elim2) *)
(** Prove the following claim, marking cases (and subcases) with
bullets when you use [destruct]. *)
Theorem andb_true_elim2 : forall b c : bool,
andb b c = true -> c = true.
Proof.
intros c.
(** Prove anything && false == false. *)
assert (forall x : bool, andb x false = false) as H.
destruct x.
-reflexivity.
-reflexivity.
(** Obviously true at this point since we have shown that no
matter what, andb b c will be false if one of them is
false. My idea is to use H to show that if it is to be
true, than both arguments must be true.
*)
Qed.
The reason why I felt it's necessary to show that (forall x : bool, andb x false = false) is because I can't figure out how to do the obvious proof by proving that (forall a b : bool, andb a b = true -> a = true, b = true)

Code snippet for this is
Theorem andb_true_elim2 : forall b c : bool,
andb b c = true -> c = true.
Proof.
intros b c H.
destruct c.
Case "c = true".
reflexivity.
Case "c = false".
rewrite <- H.
destruct b.
SCase "b = true".
reflexivity.
SCase "b = false".
reflexivity.
Qed.

Related

Coq's proof #Coq

I try to solve this proof but I don't find how to it.
I have two subgoals but I don't even know if it's correct.
Here the lemma that I trid to solve with this but I'm stuck :
2 subgoals
a, b : Nat
H : Equal (leB a b) True
______________________________________(1/2)
Equal match b with
| Z => False
| S m' => leB a m'
end (leB a b) / Equal (leB b (S a)) (leB a b)
______________________________________(2/2)
Equal (leB (S a) b) True / Equal (leB b (S a)) True
Inductive Bool : Type :=
True : Bool | False : Bool.
Definition Not(b : Bool) : Bool :=
Bool_rect (fun a => Bool)
False
True
b.
Lemma classic : forall b : Bool, Equal b (Not (Not b)).
Proof.
intro.
induction b.
simpl.
apply refl.
simpl.
apply refl.
Qed.
Definition Equal(T : Type)(x y : T) : Prop :=
forall P : T -> Prop, (P x) -> (P y).
Arguments Equal[T].
(* Avec certaines versions Arguments Equal[T] *)
Lemma refl : forall T : Type, forall x : T, Equal x x.
Proof.
intros.
unfold Equal.
intros.
assumption.
Qed.
Fixpoint leB n m : Bool :=
match n, m with
| Z, _ => True
| _, Z => False
| S n', S m' => leB n' m'
end.
First, don't introduce all variables in the beginning with intros. You will get a too weak induction hypothesis. Just introduce a.
Then in each branch, consider the different cases of b with the destruct tactic. It will simplify your goal and you can see if it is the left or the right side of goal that is true, and use your refl lemma to finish the goal.
The last case require that you use your induction hypothesis, and it is here that it is important that it holds for all b, not just one specific b.
Also, you didn't provide a definition for you Nat type, I guess it is something like this:
Inductive Nat := Z | S (n:Nat).
Here is a proof.
Lemma Linear : forall a b, (Equal (leB a b) True) \/ (Equal (leB b a) True).
Proof.
induction a.
- intros b. destruct b; simpl.
+ left. apply refl.
+ left. apply refl.
- intros b. destruct b; simpl.
+ right. apply refl.
+ destruct (IHa b) as [Hleft | Hright].
++ left. apply Hleft.
++ right. apply Hright.
Qed.
While it may not be as insightful, you can also use tactics that try these steps to get a shorter proof.
induction a; destruct b; firstorder.
will also prove your lemma.

Chaining definitions in coq

I'm following trough the software foundations books for working with Coq. I'm currently at the Tactics chapter and I'm stuck on the forall_exists_challenge.
I would like to negate the test predicate using negb but I receive the error The term "test" has type "X -> bool" while it is expected to have type "bool".
Fixpoint forallb {X : Type} (test : X -> bool) (l : list X) : bool :=
match l with
| [] => true
| h :: t => test h && forallb test t
end.
Example test_forallb_1 : forallb oddb [1;3;5;7;9] = true.
Proof. simpl. reflexivity. Qed.
Example test_forallb_2 : forallb negb [false;false] = true.
Proof. simpl. reflexivity. Qed.
Example test_forallb_3 : forallb evenb [0;2;4;5] = false.
Proof. simpl. reflexivity. Qed.
Example test_forallb_4 : forallb (eqb 5) [] = true.
Proof. simpl. reflexivity. Qed.
Fixpoint existsb {X : Type} (test : X -> bool) (l : list X) : bool :=
match l with
| [] => false
| h :: t => test h || forallb test t
end.
Example test_existsb_1 : existsb (eqb 5) [0;2;3;6] = false.
Proof. simpl. reflexivity. Qed.
Example test_existsb_2 : existsb (andb true) [true;true;false] = true.
Proof. simpl. reflexivity. Qed.
Example test_existsb_3 : existsb oddb [1;0;0;0;0;3] = true.
Proof. simpl. reflexivity. Qed.
Example test_existsb_4 : existsb evenb [] = false.
Proof. simpl. reflexivity. Qed.
Definition existsb' {X : Type} (test : X -> bool) (l : list X) : bool :=
negb (forallb (negb test) l).
Example test_existsb_1' : existsb' (eqb 5) [0;2;3;6] = false.
Proof. simpl. reflexivity. Qed.
Theorem existsb_existsb' : forall (X : Type) (test : X -> bool) (l : list X),
existsb test l = existsb' test l.
Proof. (* FILL IN HERE *) Admitted.
I expect I could be able to negate a predicate in some way but I can't seem to quite figure out how.
As the error message says, negb expects a single boolean, rather than a whole predicate. The simplest way to make a new predicate using negb would be something like fun x => negb (test x). Note that now (test x) actually does have type bool so it can be fed to negb.
Alternatively, you could make a notation for function composition (I don't think such a notation exists in the standard library, though I don't know about Software Foundations). For example, Notation "f 'o' g" := (fun x => f (g x)) (at level 20). (you might need to change the level to avoid conflicts with existing notations). Then you'd be able to do negb o test.
A third solution, if you expect to be negating predicates a lot and don't want to go as far as a function composition notation, would be to make a new function that negates a boolean predicate instead of negating a boolean. For example, Definition neg_pred {X: Type} (pred: X -> bool): X -> bool := fun x => negb (pred x).. Then you can simply use neg_pred test.

How would I prove that b = c if (andb b c = orb b c) in coq?

I'm new to coq and I'm trying to prove this...
Theorem andb_eq_orb :
forall (b c : bool),
(andb b c = orb b c) -> (b = c).
Here is my proof, but I get stuck when I get to the goal (false = true -> false = true).
Proof.
intros b c.
induction c.
destruct b.
reflexivity.
simpl.
reflexivity.
I'm not sure how I would rewrite that expression so I can use reflexivity. But even if I do that, I'm not sure it will lead to the proof.
I was able to solve the prove if I started with the hypothesis b = c though. Namely...
Theorem andb_eq_orb_rev :
forall (b c : bool),
(b = c) -> (andb b c = orb b c).
Proof.
intros.
simpl.
rewrite H.
destruct c.
reflexivity.
reflexivity.
Qed.
But I can't figure out how to solve if I start with the hypothesis that has boolean functions.
You don't need induction, since bool is not a recursive data structure. Just go through the different cases for the values of b and c. Use destruct to do that. In two cases the hypothesis H will be of the type true = false, and you can finish the proof with inversion H. In the other two cases, the goal will be of the type true = true and it can be solved with reflexivity.
Theorem andb_eq_orb : forall b c, andb b c = orb b c -> b = c.
Proof. destruct b,c; intro H; inversion H; reflexivity. Qed.
You'll want to use the intro tactic. This will move false = true into your proof context as an assumption which you can then use to rewrite.
This might not be the most efficient way to do it.
At the step induction c. (where it's stuck):
______________________________________(1/2)
b && true = b || true -> b = true
______________________________________(2/2)
b && false = b || false -> b = false
You can use rewrite and basic theorems in [bool][1] to simplify terms such as b && true to b, and b || true to true.
This can reduce it to two "trivial" sub goals:
b : bool
______________________________________(1/2)
b = true -> b = true
______________________________________(2/2)
false = b -> b = false
This is almost trivial proof using assumption, except it is one symmetry away. You can try if symmetry will make them match using:
try (symmetry;assumption); try assumption.
(Someone who really knows Coq may enlighten me how to try this more succinctly)
Putting it together:
Require Import Bool.
Theorem andb_eq_orb : forall b c, andb b c = orb b c -> b = c.
Proof.
destruct c;
try (rewrite andb_true_r);
try (rewrite orb_true_r);
try (rewrite andb_false_r);
try (rewrite orb_false_r);
intro H;
try (symmetry;assumption); try assumption.
Qed.
A second approach is to brute-force it and using the "Truth table" method. This means you can break down all variables to their truth values, and simplify: destruct b, c; simpl.. This again gives four trivial implications, up to one symmetry to try:
4 subgoal
______________________________________(1/4)
true = true -> true = true
______________________________________(2/4)
false = true -> true = false
______________________________________(3/4)
false = true -> false = true
______________________________________(4/4)
false = false -> false = false
Putting it together:
Theorem andb_eq_orb1 : forall b c, andb b c = orb b c -> b = c.
Proof.
destruct b, c; simpl; intro; try (symmetry;assumption); try assumption.
Qed.
The first approach is more troublesome but it does not involve enumerating all truth table rows (I think).

Coq - I have to define a function that is only true if x and y are different, I also have to prove the definition

here is my attempt at defining diffb. diffb x y returns true, if x <> y and false otherwise.
Definition diffb (b c : bool) : bool :=
match b, c with
| true, false => true
| false, true => true
| false, false => false
| true, true => false
end.
I have attempted above to define diffb, though I'm not sure if it is correct :(, I also need to prove diffb:
Theorem diffb_correct : forall a b : bool,
a <> b <-> diffb a b = true.
Though I'm not sure what to do when diffb appears throughout my subgoals.
thanks
lucio
edit. Solved it :)
here it is
Definition diffb (b c : bool) : bool :=
match b, c with
| true, false => true
| false, true => true
| false, false => false
| true, true => false
end.
(* Now prove that your function satisfies the specification. *)
Theorem diffb_correct : forall a b : bool,
a <> b <-> diffb a b = true.
intro a.
destruct a.
intro b.
destruct b.
split.
intro c.
destruct c.
reflexivity.
intro d.
discriminate.
split.
intro e.
reflexivity.
intro f.
discriminate.
intro g.
destruct g.
split.
intro h.
reflexivity.
discriminate.
split.
intro i.
destruct i.
reflexivity.
discriminate.
Qed.
Your diffb function seems completely fine. Since it is defined by case analysis on its argument, your proof will have to follow the same path. Instead of a complete script, I'll give you two advices:
You might want to learn about the tactics case and destruct to perform the case analysis.
And have a look at unfold or simpl to replace diffb by its definition and simplify it after analysis.
Cheers,
V.

Coq: How to prove "a=b -> nat_compare a b = Eq."?

In an attempt to get a grasp what Coq is about, I ended up in a situation where I essentially need to prove that a=b -> nat_compare a b = Eq.
I can get a handy start by doing:
Coq < Theorem foo: forall (a:nat) (b:nat), a=b->nat_compare a b=Eq.
1 subgoal
============================
forall a b : nat, a = b -> nat_compare a b = Eq
foo < intros. rewrite H. destruct b.
which gives me:
2 subgoals
a : nat
H : a = 0
============================
nat_compare 0 0 = Eq
subgoal 2 is:
nat_compare (S b) (S b) = Eq
The first is trivial:
foo < simpl. reflexivity.
But the next goal stumps me:
1 subgoal
a : nat
b : nat
H : a = S b
============================
nat_compare (S b) (S b) = Eq
I can do
foo < rewrite <- H.
which gives:
1 subgoal
a : nat
b : nat
H : a = S b
============================
nat_compare a a = Eq
(I can also arrive to this exact point by simpl, which seems to make more sense.)
Now, with pen an paper, I'd just claim that here is my proof by induction..
Am I approaching this at all in a correct way? Where can I best learn how to do this properly?
I was able to prove this with
Theorem triv : forall a b, a = b -> nat_compare a b = Eq.
intros; subst; induction b; auto.
Qed.
The trick here is to leave the inductive hypothesis lying around. destruct is a weaker form of induction that doesn't give you an inductive hypothesis which you need for this proof.