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.
Related
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.
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.
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.
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.
I have this complex iterations program I wrote in TI Basic to perform a basic iteration on a complex number and then give the magnitude of the result:
INPUT “SEED?”, C
INPUT “ITERATIONS?”, N
C→Z
For (I,1,N)
Z^2 + C → Z
DISP Z
DISP “MAGNITUDE”, sqrt ((real(Z)^2 + imag(Z)^2))
PAUSE
END
What I would like to do is make a Haskell version of this to wow my teacher in an assignment. I am still only learning and got this far:
fractal ::(RealFloat a) =>
(Complex a) -> (Integer a) -> [Complex a]
fractal c n | n == a = z : fractal (z^2 + c)
| otherwise = error "Finished"
What I don't know how to do is how to make it only iterate n times, so I wanted to have it count up a and then compare it to n to see if it had finished.
How would I go about this?
Newacct's answer shows the way:
fractal c n = take n $ iterate (\z -> z^2 + c) c
Iterate generates the infinite list of repeated applications.
Ex:
iterate (2*) 1 == [1, 2, 4, 8, 16, 32, ...]
Regarding the IO, you'll have to do some monadic computations.
import Data.Complex
import Control.Monad
fractal c n = take n $ iterate (\z -> z^2 + c) c
main :: IO ()
main = do
-- Print and read (you could even omit the type signatures here)
putStr "Seed: "
c <- readLn :: IO (Complex Double)
putStr "Number of iterations: "
n <- readLn :: IO Int
-- Working with each element the result list
forM_ (fractal c n) $ \current -> do
putStrLn $ show current
putStrLn $ "Magnitude: " ++ (show $ magnitude current)
Since Complex is convertible from and to strings by default, you can use readLn to read them from the console (format is Re :+ Im).
Edit: Just for fun, one could desugar the monadic syntax and type signatures which would compress the whole programm to this:
main =
(putStr "Seed: ") >> readLn >>= \c ->
(putStr "Number of iterations: ") >> readLn >>= \n ->
forM_ (take n $ iterate (\z -> z^2 + c) c) $ \current ->
putStrLn $ show current ++ "\nMagnitude: " ++ (show $ magnitude current)
Edit #2: Some Links related to plotting and Mandelbrot's sets.
Fractal plotter
Plotting with
Graphics.UI
Simplest solution
(ASCII-ART)
Well you can always generate an infinite list of results of repeated applications and take the first n of them using take. And the iterate function is useful for generating an infinite list of results of repeated applications.
If you'd like a list of values:
fractalList c n = fractalListHelper c c n
where
fractalListHelper z c 0 = []
fractalListHelper z c n = z : fractalListHelper (z^2 + c) c (n-1)
If you only care about the last result:
fractal c n = fractalHelper c c n
where
fractalHelper z c 0 = z
fractalHelper z c n = fractalHelper (z^2 + c) c (n-1)
Basically, in both cases you need a helper function to the counting and accumulation. Now I'm sure there's a better/less verbose way to do this, but I'm pretty much a Haskell newbie myself.
Edit: just for kicks, a foldr one-liner:
fractalFold c n = foldr (\c z -> z^2 + c) c (take n (repeat c))
(although, the (take n (repeat c)) thing seems kind of unnecessary, there has to be an even better way)