Is induction required in this Isabelle proof? - isabelle

I'm trying to prove that generator functions produce certain, still very simple, patterns.
pattern_0_1 generates a list of alternating 0s and 1s. I've succeeded to prove that the first item is zero for any list whose length is greater than 0. Applying the same technique, however, failed to prove the 2nd element is always 1. My guess is induction is not at all required here. I'd appreciate any help on the right approach to complete the second lemma.
fun pattern_0_1 :: "nat ⇒ nat ⇒ nat list" where
"pattern_0_1 0 item = []" |
"pattern_0_1 len item = item # (pattern_0_1 (len - 1) (if item = 0 then 1 else 0))"
lemma item_0_is_0 : "lng ≥ 1 ⟹ pattern_0_1 lng 0 ! 0 = 0"
apply(induction lng)
apply(simp)
by auto
lemma item_1_is_1 : "lng ≥ 2 ⟹ pattern_0_1 lng 0 ! 1 = 1"
apply(induction lng)
apply(simp)
sorry

Induction is not required (it would be, would you show something about all even or all odd positions). Here, case analysis is enough, so that you get the cases 0, 1, and >= 2. So, your proof can be done via
apply(cases lng; cases "lng - 1"; auto)
where the first cases will be on being 0 or >= 1, and the second cases will distinguish between 1 and >= 2.

Related

Proof of a theorem using induction

Consider the statement: The last digit of n^5 is equal to the last digit of n. This is equivalent to saying n^ 5 mod 10 = n mod 1 . The proof for this is rather simple, the steps are
Proof 1
The last digit of n^5 can only be affected by the last digit n, as the first digit of any power n is only affected by the one digit of n. In this case, it becomes a matter of 'Prood by cases' where you only have to prove it for 0-9
0^5 = 0 , 1^5 = 1, 2^5 = 32 etc..
Alternatively,
Proof 2
This is also equvalent to saying, n^5−n is divisible by 10 . By induction:
if n=0, this is obviously true.
3.1) Assume correct for n
3.2)
(n+1)^5-(n+1) = n^5 + 5n^4 + 10n^3 + 10n^2 + 5n + 1 - (n+1) =n^5 - n + 10(n^3+n^2) +5n(n^3+1) is divisible by 10
This then has 3 subgoals.
3.3.1) Prove n^5 - n is divisble by 10, by induction
3.3.2) 10(n^3+n^2) is oobviously divisible by 10
3.3.3) prove that 5n(n^3+1) is divisible by 10. which is the same as showing n(n^3+1) is divisible by 2.
confusion
I have been attempting to complete this proof in Isabelle for weeks now. I have gone through the documentation and consulted colleagues, however, one way or another, no matter which way I frame the proof in Isabelle, I am unable to prove it.
For example, consider
theorem "(n::nat) ^ 5 mod 10 = n mod 10"
proof (induct n)
case 0
show "(0::nat)^5 mod 10 = 0 mod 10" by simp
next
case (Suc n)
hence"n^5 mod 10 = n mod 10" by assumption
have "Suc n = n+1" by simp
have "(n+1)^5-(n+1) = n^5+5*n^4+10*n^3+10*n^2+5*n+1-(n+1)"
also have "... = n^5+5*n^4+10*n^3+10*n^2+5*n+1-(n+1)"
also have "(Suc n)^5 mod 10 = (n+1)^5 mod 10"
thus "(Suc n)^5 mod 10 = (Suc n) mod 10" sorry
qed
This question is part of an assessed coursework exercise that is currently active at Imperial College London. I'd really appreciate it if folks could hold off answering this question until February or so, to give the students taking the course the opportunity to complete it themselves.
That said, if you have a question that is more specific than "I'm unable to prove it" (e.g. "What does this particular error message mean?"), I'd be delighted to help.

Coq:prove Prop implies arithmetic relations of natural number

I'm trying to prove the following Lemma in coq --
Lemma less_than_two_equivalent: forall x, less_than_two x = true -> x < 2.
based on the definition below.
Fixpoint less_than (a b:nat): bool:=
match a, b with
|0, 0 => false
|0, _ => true
|S a', 0 => false
|S a', S b' => less_than a' b'
end.
Fixpoint less_than_two (x:nat) : bool := if less_than x 2 then true else false.
Mathematically, there are only 2 cases, 0 or 1. And destructionshould be the hammer, but there won't be enough information about the S x for further reasoning.
Should I modify the less_than into inductive datatypes? If not, how to resolve it?
Let me begin by redefining less_than_two. First, it's not recursive, so there is no point in defining it as a Fixpoint. Next, if less_than x 2 then true else false is essentially the same thing as less_than x 2. And at this point I wouldn't bother with introducing a new definition, so your lemma becomes
Lemma less_than_two_equivalent x: less_than x 2 = true -> x < 2.
Proof.
do 2 (destruct x; auto); simpl.
destruct x; discriminate.
Qed.
I don't know what went wrong with your proof exactly, but you might have forgotten to destruct x one more time. When you see less_than x 0 = true -> S (S x) < 2 you can't still use discriminate to finish your goal, because evaluation is blocked on the variable -- less_than first pattern-matches on the a parameter and only then checks b. Destruction of x unblocks computation and lets Coq see that you have false = true as your premise, hence the goal becomes provable.
Note that this depends on the particular implementation of the comparison function. Had you chose this one
(* (!) the [struct] annotation is important here, as well as as
the order of the parameters [b, a] in the match expression *)
Fixpoint less_than' (a b : nat) {struct b} : bool :=
match b, a with
| 0, _ => false
| _, 0 => true
| S b', S a' => less_than' a' b'
end.
you would have a bit simpler proof (one less destruct):
Lemma less_than_two_equivalent x: less_than' x 2 = true -> x < 2.
Proof.
do 2 (destruct x; auto).
discriminate.
Qed.

Coq can't compute well-founded defined with Fix, but can if defined with Program Fixpoint

As an exercise to understand recursion by a well-founded relation I decided to implement the extended euclidean algorithm.
The extended euclidean algorithm works on integers, so I need some
well-founded relation on integers. I tried to use the relations in Zwf, but things didn't worked (I need to see more examples). I decided that would easier to map Z to nat with the Z.abs_nat function and then just use Nat.lt as relation. Our friend wf_inverse_image comes to help me. So here what I did:
Require Import ZArith Coq.ZArith.Znumtheory.
Require Import Wellfounded.
Definition fabs := (fun x => Z.abs_nat (Z.abs x)). (* (Z.abs x) is a involutive nice guy to help me in the future *)
Definition myR (x y : Z) := (fabs x < fabs y)%nat.
Definition lt_wf_on_Z := (wf_inverse_image Z nat lt fabs) lt_wf.
The extended euclidean algorithm goes like this:
Definition euclids_type (a : Z) := forall b : Z, Z * Z * Z.
Definition euclids_rec : (forall x : Z, (forall y : Z,(myR y x) -> euclids_type y) -> euclids_type x).
unfold myR, fabs.
refine (fun a rec b => if (Z_eq_dec a 0) then (b, 0, 1)
else let '(g, s, t) := rec (b mod a ) _ a
in (g, t - (b / a) * s, s)
).
apply Zabs_nat_lt. split. apply Z.abs_nonneg. apply Z.mod_bound_abs. assumption.
Defined.
Definition euclids := Fix lt_wf_on_Z _ euclids_rec.
Now let's see if it works:
Compute (euclids 240 46). (* Computation takes a long time and results in a huge term *)
I know that can happen if some definition is opaque, however all my definitions end with Defined.. Okey, something else is opaque, but what?
If is a library definition, then I don't think that would cool to just redefine it in my code.
It seems that my problem is related with this, this other and this too.
I decided to give Program Fixpoint a try, since I never used it. I was surprised to see that I could just copy and paste my program.
Program Fixpoint euclids' (a b: Z) {measure (Z.abs_nat (Z.abs a))} : Z * Z * Z :=
if Z.eq_dec a 0 then (b, 0, 1)
else let '(g, s, t) := euclids' (b mod a) a in
(g, t - (b / a) * s, s).
Next Obligation.
apply Zabs_nat_lt. split. apply Z.abs_nonneg. apply Z.mod_bound_abs. assumption.
Defined.
And even more surprise to see that works just fine:
Compute (euclids' 240 46). (* fast computation gives me (2, -9, 47): Z * Z * Z *)
What is opaque in euclids that is not in euclids' ?
And how to make euclids work?
Okey, something else is opaque, but what?
wf_inverse_image is opaque and so are the lemmas it relies on: Acc_lemma and Acc_inverse_image. If you make these three transparent euclids will compute.
The evidence of well-foundness is basically your parameter you do structural recursion on, so it must be transparent.
And how to make euclids work?
Fortunately, you don't have to roll your own transparent versions of the aforementioned standard definitions as there is well_founded_ltof lemma in Coq.Arith.Wf_nat which is already transparent so we can reuse it:
Lemma lt_wf_on_Z : well_founded myR.
Proof. exact (well_founded_ltof Z fabs). Defined.
That's it! After fixing lt_wf_on_Z the rest of your code just works.

How to analyze if-expressions in assumptions?

I'm trying to prove the following lemma:
lemma if_assumption: "(if a = 1 then 2 else 3) = 2 ⟹ a = 1"
apply (cases "a = 1")
apply simp_all
After simplification I get the following formula:
3 = 2 ⟹ a ≠ 1 ⟹ False
The result of if-expression equals 2 iff a equals 1. So, I guess that I can deduce this fact somehow.
How to prove this lemma?
Your statement is not correct as you wrote it down. Numbers in Isabelle are polymorphic by default (you can check that by hovering over the numbers while pressing Ctrl). There might be a number type for which 3 = 2 holds (e.g. the finite field {0,1,2}). In that case, a may not be equal to 1.
If instead you fix the number type:
lemma if_assumption: "(if a = 1 then 2 else 3) = (2::nat) ⟹ a = 1"
the proof script you wrote goes through. Or shorter:
apply (auto split: if_splits)
... which tells the system to split the if _ then _ else _ into two subgoals.

How can I prove this statement of big o notation?

How to prove this:
x^7 = O(x^10)
x^10 = O(x^7)?
I couldn't prove this statement.
Let's take a look at the definition of big-O notation.
f ∈ O(g) <=> (∃ x) (∃ c > 0) (∀ y > x) (|f(y)| <= c⋅|g(y)|)
The right hand side can be formulated "the quotient f/g is bounded for sufficiently large x".
So to prove that f ∈ O(g), look at the quotient, choose a (largish) x and try to find a bound.
For the first case, the quotient is
x⁷ / x¹⁰ = 1/x³
A bound for x ≥ 1 is obvious.
To refute f ∈ O(g), look at the quotient and prove that it assumes values of arbitrarily large modulus on each interval [x, ∞). Assume an arbitrary c > 0, and prove that for any x, there is an y > x with |f(y)/g(y)| > c.
That should give enough of a hint.
If not: x³ > c for x ≥ c+1.

Resources