How to make Isabelle use basic math rules? - isabelle

I'm trying to learn Isabelle:
theory test
imports Main
begin
datatype tree = Leaf | Node tree tree
fun nodes :: "tree ⇒ nat" where
"nodes Leaf = 1"|
"nodes (Node x y) = 1 + (nodes x) + (nodes y)"
fun explode :: "nat ⇒ tree ⇒ tree" where
"explode 0 t = t" |
"explode (Suc n) t = explode n (Node t t)"
theorem tree_count: "nodes (explode h l) = 2^h + 2^h * (nodes l) - 1"
apply(induction h arbitrary: l)
apply(auto simp add: numeral_eq_Suc)
done
end
However, the theorem is not solved:
Failed to finish proof:
goal (1 subgoal):
1. ⋀h l. (⋀l. nodes (explode h l) = Suc (Suc 0) ^ h + Suc (Suc 0) ^ h * nodes l - Suc 0) ⟹
Suc (Suc 0) ^ h + (Suc (Suc 0) ^ h + Suc (Suc 0) ^ h * (nodes l + nodes l)) - Suc 0 =
Suc (Suc 0) ^ h + Suc (Suc 0) ^ h + (Suc (Suc 0) ^ h + Suc (Suc 0) ^ h) * nodes l - Suc 0
If I'm not mistaken, Isabelle is just not applying x + x = 2*x and a + (b + c) = a + b + c. So I tried adding a lemma to use it with simp:
lemma a: "(x:nat) + x = 2*x"
But this fails with
Type unification failed: Clash of types "_ ⇒ _" and "_ set"
Type error in application: incompatible operand type
Operator: (∈) x :: ??'a set ⇒ bool
Operand: nat :: int ⇒ nat
I assume that it's just not possible to define the type of a variable in a lemma?
Now I could of course redifine the addition - but I guess that's not really best practice.
What would be the best way to solve the initial problem?

Some general approaches to find the right lemmas:
Use the theorem search, either via the query panel or in the text with find_theorems:
find_theorems ‹_ * (_ + _)›
find_theorems name: assoc "_ + _ + _"
find_theorems ‹2 * ?z = ?z + ?z›
Use sledgehammer.
Try the algebra_simps collection as suggested by waldelb (There are also ac_simps, algebra_split_simps, field_simps, and field_split_simps ).
Try to split it up into smaller steps. This helps the simp tool, because simplification can work on both sides of the equation and because you can guide it to the right intermediate steps. The example below is a bit too extreme, doing only one rewrite per step. In general, you can just add intermediary steps where the automatic ones fail.
theorem tree_count: ‹nodes (explode h l) = 2^h + 2^h * (nodes l) - 1›
proof (induction h arbitrary: l)
case 0
show ‹nodes (explode 0 l) = 2 ^ 0 + 2 ^ 0 * nodes l - 1›
by simp
next
case (Suc h)
have ‹nodes (explode (Suc h) l)
= nodes (explode h (Node l l))›
by (subst explode.simps, rule refl)
also have "... = 2 ^ h + 2 ^ h * nodes (Node l l) - 1"
by (subst Suc, rule refl)
also have "... = 2 ^ h + 2 ^ h * (1 + nodes l + nodes l) - 1"
by (subst nodes.simps, rule refl)
also have "... = 2 ^ h + 2 ^ h * (1 + (nodes l + nodes l)) - 1"
by (subst add.assoc, rule refl)
also have "... = 2 ^ h + 2 ^ h * (1 + (2 * nodes l)) - 1"
by (subst mult_2, rule refl)
also have "... = 2 ^ h + (2 ^ h * 1 + 2 ^ h * (2 * nodes l)) - 1"
by (subst distrib_left, rule refl)
also have "... = 2 ^ h + (2 ^ h * 1 + 2 ^ h * 2 * nodes l) - 1"
by (subst mult.assoc, rule refl)
also have "... = 2 ^ h + (2 ^ h * 1 + 2 ^ Suc h * nodes l) - 1"
by (subst power_Suc2, rule refl)
also have "... = (2 ^ h + 2 ^ h * 1) + 2 ^ Suc h * nodes l - 1"
by (subst add.assoc, rule refl)
also have "... = (2 ^ h + 2 ^ h) + 2 ^ Suc h * nodes l - 1"
by (subst mult_1_right, rule refl)
also have "... = 2 ^ h * 2 + 2 ^ Suc h * nodes l - 1"
by (subst mult_2_right, rule refl)
also have "... = 2 ^ Suc h + 2 ^ Suc h * nodes l - 1"
by (subst power_Suc2, rule refl)
finally show ?case .
qed

algebra_simps is a list of common math rules. Adding it solves the problem:
apply(auto simp add: numeral_eq_Suc algebra_simps)

Related

Modular arithmetic proofs in agda

I'm trying to prove (n : ℕ) → ∃[ m ] n * n ≡ 3 * m + 2 → ⊥. Typically I would prove this by rewriting it in terms of congruence, and then splitting on each case. There doesn't seem to be a modular arithmetic module in agda-stdlib. How should I implement modular arithmetic or approach this kind of problem without modular arithmetic?
Edit: there has been discussion in the comments that is not quite precise enough to lead me to an answer, so in the hopes of clarifying what cannot fit in the word count I am dumping my various attempts at this problem, some of which inspired by things in the comments.
open Data.Nat.Divisibility.Core
open Data.Nat.Base
open Relation.Binary.Core
open Level using (0ℓ)
open Relation.Binary.PropositionalEquality
open Data.Empty
open Relation.Nullary
open Data.Product using (Σ; _,_; ∃; Σ-syntax; ∃-syntax)
open Relation.Binary.PropositionalEquality.≡-Reasoning
open Data.Nat.Solver
open +-*-Solver
data Z/3 : (n : ℕ) → Set where
Z/3₀ : (n : ℕ) → ∃[ m ] n ≡ 3 * m → Z/3 n
Z/3₁ : (n : ℕ) → ∃[ m ] n ≡ 3 * m + 1 → Z/3 n
Z/3₂ : (n : ℕ) → ∃[ m ] n ≡ 3 * m + 2 → Z/3 n
data _≋_ : Rel ℕ 0ℓ where
3∣|a-b| : ∀ {a b : ℕ} → 3 ∣ ∣ a - b ∣ → a ≋ b
q' : {a : ℕ} → (2 ≋ ((a + 3) * (a + 3))) → (∃[ a' ] 2 ≋ (a' * a'))
q' = {!!}
qq : (n : ℕ) → Z/3 (n * n)
qq zero = Z/3₀ zero (zero , refl)
qq (suc zero) = Z/3₁ 1 (zero , refl)
qq (suc (suc zero)) = Z/3₁ 4 (1 , refl)
qq (suc (suc (suc n))) = Z/3₁ ((3 + n) * (3 + n)) ({!!} , {!!})
q'' : (n : ℕ) → ∃[ m ] n * n ≡ 3 * m + 2 → ⊥
q'' zero (zero , ())
q'' zero (suc fst , ())
q'' (suc zero) (suc zero , ())
q'' (suc zero) (suc (suc fst) , ())
q'' (suc (suc zero)) (suc (suc (suc (suc zero))) , ())
q'' (suc (suc zero)) (suc (suc (suc (suc (suc fst)))) , ())
q'' (suc (suc (suc n))) (suc fst , snd) = q'' n ({!!} , {!!})
sq : {a : ℕ} → Z/3 a → Z/3 (a * a)
sq (Z/3₀ n (m , p)) = Z/3₀ (n * n) (3 * m * m , q) where
q =
begin
n * n
≡⟨ cong (λ e → e * n) p ⟩
(3 * m) * n
≡⟨ cong (λ e → (3 * m) * e) p ⟩
(3 * m) * (3 * m)
≡⟨ solve 1 (λ m' → (con 3 :* m') :* (con 3 :* m') := con 3 :* m' :* m' :+ (con 3 :* m' :* m' :+ (con 3 :* m' :* m' :+ con zero))) refl m ⟩
3 * m * m + (3 * m * m + (3 * m * m + zero))
∎
-- (3 * b + 1) * (3 * b + 1)
-- 9b^2 + 6b + 1
-- 3(3b^2 + 2b) +1
-- (3 * b + 2) * (3 * b + 2)
-- 9b^2 + 12b + 4
-- 3(3b^2+4b+1) + 1
sq (Z/3₁ n (m , p)) = Z/3₁ (n * n) (3 * m * m + 2 * m , q) where
q =
begin
n * n
≡⟨ cong (λ e → e * n) p ⟩
(3 * m + 1) * n
≡⟨ cong (λ e → (3 * m + 1) * e) p ⟩
(3 * m + 1) * (3 * m + 1)
≡⟨ solve 1 (λ m' → (con 3 :* m' :+ con 1) :* (con 3 :* m' :+ con 1) := (m' :+ (m' :+ (m' :+ con 0))) :* m' :+ (m' :+ (m' :+ con 0)) :+ ((m' :+ (m' :+ (m' :+ con 0))) :* m' :+ (m' :+ (m' :+ con 0)) :+ ((m' :+ (m' :+ (m' :+ con 0))) :* m' :+ (m' :+ (m' :+ con 0)) :+ con 0)) :+ con 1 ) refl m ⟩
(m + (m + (m + 0))) * m + (m + (m + 0)) + ((m + (m + (m + 0))) * m + (m + (m + 0)) + ((m + (m + (m + 0))) * m + (m + (m + 0)) + 0)) + 1
∎
sq (Z/3₂ n (m , p)) = Z/3₁ (n * n) (3 * m * m + 4 * m + 1 , {!!})
q : {a : ℕ} → ¬(2 ≋ (a * a))
q {zero} (3∣|a-b| (divides zero ()))
q {zero} (3∣|a-b| (divides (suc quotient) ()))
q {suc zero} (3∣|a-b| (divides zero ()))
q {suc zero} (3∣|a-b| (divides (suc quotient) ()))
q {suc (suc zero)} (3∣|a-b| (divides zero ()))
q {suc (suc zero)} (3∣|a-b| (divides (suc quotient) ()))
q {suc (suc (suc a))} (3∣|a-b| (divides (suc quotient) equality)) = {!!}
Building on Mark's proof outline:
module SOMod where
open import Data.Empty
open import Data.Nat
open import Data.Nat.Properties
open import Data.Nat.DivMod
open import Data.Product
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary.Negation
open ≡-Reasoning
lemma : ∀ m n → (n * n) % 3 ≢ (3 * m + 2) % 3
lemma m n p = contradiction ≡2 (≢2 n)
where
≡2 : ((n % 3) * (n % 3)) % 3 ≡ 2
≡2 = begin
((n % 3) * (n % 3)) % 3 ≡˘⟨ %-distribˡ-* n n 3 ⟩
(n * n) % 3 ≡⟨ p ⟩
(3 * m + 2) % 3 ≡⟨ cong (_% 3) (+-comm (3 * m) 2) ⟩
(2 + 3 * m) % 3 ≡⟨ cong (λ # → (2 + #) % 3) (*-comm 3 m) ⟩
(2 + m * 3) % 3 ≡⟨ [m+kn]%n≡m%n 2 m 3 ⟩
2 % 3 ≡⟨⟩
2 ∎
≢2 : ∀ n → ((n % 3) * (n % 3)) % 3 ≢ 2
≢2 zero = λ ()
≢2 (suc zero) = λ ()
≢2 (suc (suc zero)) = λ ()
≢2 (suc (suc (suc n))) = ≢2 n
proof : ∀ n → ∃[ m ] n * n ≡ 3 * m + 2 → ⊥
proof n (m , p) = contradiction (cong (_% 3) p) (lemma m n)

Why can't I simplify Σ {0} = 0 in Isabelle to make them equal?

I was going through chapter 5 (Isar) and I tried doing the structural induction proof for "Σ{0..n::nat} = n*(n+1) div 2" but it fails:
lemma "Σ{0..n::nat} = n*(n+1) div 2"
proof (induction n)
show "Σ{0..0::nat} = 0*(0+1) div 2" by simp
next
fix n
assume "Σ {0..n} = n * (n + 1) div 2"
thus "Σ {0..Suc n} = Suc n * (Suc n + 1) div 2" by simp
qed
it says:
show Σ {0..0} = 0 * (0 + 1) div 2
Successful attempt to solve goal by exported rule:
Σ {0..0} = 0 * (0 + 1) div 2
proof (state)
this:
Σ {0..0} = 0 * (0 + 1) div 2
goal (1 subgoal):
1. ⋀n. Σ {0..n} = n * (n + 1) div 2 ⟹ Σ {0..Suc n} = Suc n * (Suc n + 1) div 2
Failed to finish proof⌂:
goal (1 subgoal):
1. Σ {0} = 0
I don't know why. Sledgehammer didn't solve it either. I did try blast , auto etc but I knew they'd fail since sledgehammer has suggested those to me before but it was worth the try?
I tried doing the apply style to see what going on:
lemma "Σ{0..n::nat} = n*(n+1) div 2"
apply (induction n)
apply simp
apply simp
same error:
proof (prove)
goal (2 subgoals):
1. Σ {0} = 0
2. ⋀n. Σ {0..n} = n * (n + 1) div 2 ⟹ Σ {0..Suc n} = Suc n * (Suc n + 1) div 2
Failed to apply proof method⌂:
goal (2 subgoals):
1. Σ {0} = 0
2. ⋀n. Σ {0..n} = n * (n + 1) div 2 ⟹ Σ {0..Suc n} = Suc n * (Suc n + 1) div 2
why is this not working? Is there something wrong with my installation of Isabelle?
I also tried the proof on a file without anything and it also failed so it's not any of my earlier definitions (I assume with high probability).
Seems that going to the bottom right where I can manually insert symbols is a bad idea. It inserted the symbol sigma instead of Sum. I fixed it by doing \<Sum> (in reality I auto completed with tab). Proof works now:
lemma "∑{0..n::nat} = n*(n+1) div 2"
apply (induction n)
apply simp
by simp

Quadratic Formula in Isabelle?

I'm looking for a theory file which contains the quadratic formula:
and of course it would be helpful to know the name of the lemma too.
I've already found this paper:
http://www.inf.ed.ac.uk/publications/thesis/online/IM040231.pdf
and I can copy-paste the proof in that, but then I'll have to rewrite it (because it doesn't copy perfectly). It would be better to have something that works straight away: maybe if someone knows where the theory file that matches this paper can be found?
The paper you linked is very old and the proofs from it will not work without major changes.
Here's a short and simple proof of the theorem:
theory Scratch
imports Complex_Main
begin
lemma real_sqrt_unique':
"(x::real) ^ 2 = y ⟹ x = -sqrt y ∨ x = sqrt y"
using real_sqrt_unique[of x y] real_sqrt_unique[of "-x" y]
by (cases "x ≥ 0") simp_all
lemma quadratic_roots_formula:
fixes a b c x :: real
assumes "a ≠ 0"
defines "disc ≡ b^2 - 4 * a * c"
assumes "disc ≥ 0"
shows "a * x^2 + b * x + c = 0 ⟷ x ∈ {(-b - sqrt disc) / (2*a), (-b + sqrt disc) / (2*a)}"
proof -
from assms have "a * x^2 + b * x + c = 0 ⟷ 4 * a * (a * x^2 + b * x + c) = 0"
by simp
also have "4 * a * (a * x^2 + b * x + c) = (2 * a * x + b) ^ 2 - b^2 + 4 * a * c"
by (simp add: algebra_simps power2_eq_square)
also have "… = 0 ⟷ (2 * a * x + b) ^ 2 = disc" by (simp add: disc_def algebra_simps)
also from ‹disc ≥ 0› have "… ⟷ (2 * a * x + b) ∈ {-sqrt disc, sqrt disc}"
by (auto simp: real_sqrt_unique')
also have "… ⟷ x ∈ {(-b - sqrt disc) / (2*a), (-b + sqrt disc) / (2*a)}"
using assms by (auto simp: field_simps)
finally show ?thesis .
qed

In isabelle, why is this simplification lemma not being substituted?

I'm working through the Isabelle "Programming and Proving" tutorial, and am coming to Ex2.10, where you have to arrive at an equation discribing the number of nodes in an "exploded" tree.
The approach I've taken to this is to create separate expressions for the internal and leaf nodes in the tree, and am working on a proof for the number of internal nodes in the tree, as such:
lemma dddq: " a>0 ⟶ (nodes_noleaf (explode a b) = (ptser (a - 1) (2::nat)) + ((2 ^ a) * (nodes_noleaf b)))"
apply(induction a)
apply(simp)
apply(simp add:eeei eeed eeej eeek )
and this leaves the proof state as the following:
goal (1 subgoal):
1. ⋀a. 0 < a ⟶ nodes_noleaf (explode a b) = ptser (a - Suc 0) 2 + 2 ^ a * nodes_noleaf b ⟹
Suc (2 * nodes_noleaf (explode a b)) = ptser a 2 + 2 * 2 ^ a * nodes_noleaf b
Now, I also created (and successfully proved) a lemma that should replace the ptser a 2 + 2 * 2 ^ a * nodes_noleaf b with (Suc (2 * ((ptser (a - Suc 0) 2) + 2 ^ a * nodes_noleaf b)))), as such:
lemma eeek: "∀ a b . a>0 ⟶ (((ptser a 2) + 2 * 2 ^ a * nodes_noleaf b) = (Suc (2 * ((ptser (a - Suc 0) 2) + 2 ^ a * nodes_noleaf b))))"
apply(auto)
apply(simp add: ddddd)
done
However, adding this to the list of simplifications for the dddq does nothing, and I don't see the reason why.
Additional definitions..
fun nodes_noleaf:: "tree0 ⇒ nat" where
"nodes_noleaf Tip = 0"|
"nodes_noleaf (Node a b) = (add 1 (add (nodes_noleaf a) (nodes_noleaf b)))"
fun explode:: "nat ⇒ tree0 ⇒ tree0" where
"explode 0 t = t" |
"explode (Suc n) t = explode n (Node t t)"
fun ptser:: "nat ⇒ nat ⇒ nat" where
"ptser 0 b = b^0" |
"ptser a b = b^a + (ptser (a - 1) b)"
Your lemma eeek is a conditional rewrite rule, because it can only be applied when the simplifier can prove that a > 0 holds. In your goal state, however, you do not have the assumption a > 0. The 0 < a is a precondition to the induction hypothesis (--> binds stronger than ==>), which is why simp does not apply the induction hypothesis either.
Since the question does not contain all the definitions of your goal, it is hard to pinpoint the exact reason. Nevertheless, I suggest to drop the assumption a > 0 from dddq and prove a stronger statement.
A comment on style: Try to use the connectives !! and ==> of the natural deduction framework rather than explicit universal quantifiers and -->. The simplifier knows how to convert them back into !! and ==>, but other proof methods do not do this automatically. Thus, using !! and ==> will save you boilerplate proof steps later on.

Simplifier doesn't work with constants greater than 10?

Why does the Isabelle simplifier refuse to prove the following lemma?
lemma "n ≠ counter ⟹
n ≠ Suc counter ⟹
n ≠ Suc (Suc counter) ⟹
n ≠ counter + 3 ⟹
n ≠ counter + 4 ⟹
n ≠ counter + 5 ⟹
n ≠ counter + 6 ⟹
n ≠ counter + 7 ⟹
n ≠ counter + 8 ⟹
n ≠ counter + 9 ⟹
counter ≤ n ⟹ n < counter + 10 ⟹ False"
by simp
Although it proves a slightly smaller lemma
lemma "n ≠ counter ⟹
n ≠ Suc counter ⟹
n ≠ Suc (Suc counter) ⟹
n ≠ counter + 3 ⟹
n ≠ counter + 4 ⟹
n ≠ counter + 5 ⟹
n ≠ counter + 6 ⟹
n ≠ counter + 7 ⟹
n ≠ counter + 8 ⟹
counter ≤ n ⟹ n < counter + 9 ⟹ False"
by simp
It seems to me that the constant 10 is too large for the simplifier. Is there an option increasing the maximal processed constant or another workaround to prove the first lemma?
To answer for the workaround, you can use the "arith" or the "presburger" method:
lemma "n ≠ counter ⟹
n ≠ Suc counter ⟹
n ≠ Suc (Suc counter) ⟹
n ≠ counter + 3 ⟹
n ≠ counter + 4 ⟹
n ≠ counter + 5 ⟹
n ≠ counter + 6 ⟹
n ≠ counter + 7 ⟹
n ≠ counter + 8 ⟹
n ≠ counter + 9 ⟹
counter ≤ n ⟹ n < counter + 10 ⟹ False"
by presburger (* or by arith *)
arith also works but raises a warning (linarith failed) in this case, while this warning does not appear for the smaller lemma. There should be a correlation somewhere but I don't know exactly why the simp method fails though...
You could have discovered this by using the commands "try" or "try0" that try several provers and methods.
Thanks for the other answer for showing that arith can be used to prove the theorem, because arith is not one of the try0 methods.
By all appearances, this message from linarith_trace gives you the answer:
neq_limit exceeded (current value is 9), ignoring all inequalities
The value 10 comes into play not because you're using the constant 10, but because you're using 10 inequalities, as I show below. As usual, because I can't verify with someone what seems to be obvious (from looking at source files), I could be wrong.
I grepped on neq_limit in Isabelle2013-2/src and it shows up in two files. There's also an applicable example theory:
src/Provers/Arith/fast_lin_arith.ML
src/HOL/Tools/lin_arith.ML
src/HOL/ex/Arith_Examples.thy
Below, I quote from the files above, and I show, using [[simp_trace, linarith_trace]], whether I use apply(simp only:) or apply(arith), there's a lot of interaction between simp and various linear arithmetic methods.
I deleted my first answer. If anyone wants to see what I had to say about (simp only:), and other things about trying to track down things, you can click on edit somewhere below to see the old entries.
As shown below, whether I use apply(simp only:) or apply(arith), I get the neq_limit exceeded trace message above.
I speculate that the difference is between fast_lin_arith.ML and lin_arith.ML. In fast_lin_arith.ML, there is a check, at line 788, that's not in lin_arith.ML.
val split_neq = count is_neq (map (LA_Data.decomp ctxt) Hs') <= neq_limit
in
if split_neq then ()
else
trace_msg ctxt ("neq_limit exceeded (current value is " ^
This is related to a comment in that file:
(*the limit on the number of ~= allowed; because each ~= is split
into two cases, this can lead to an explosion*)
val neq_limit: int Config.T
In general, there's a lot of interaction between simp and the linear arithmetic automatic proof methods, as shown by a comment in Arith_Examples.thy.
The #{text arith} method combines them both, and tries other methods
(e.g.~#{text presburger}) as well. This is the one that you should use
in your proofs!
Now, I get rid of one not equal in your counter + 10 lemma (because it's redundant), which allows simp to prove it.
(*_SRC.0_*)
(*If we get rid of one inequality, and change the <= to <, it works.*)
lemma "(*n ≠ counter ==> *)
counter < n ==>
n ≠ Suc counter ==>
n ≠ Suc (Suc counter) ==>
n ≠ counter + 3 ==>
n ≠ counter + 4 ==>
n ≠ counter + 5 ==>
n ≠ counter + 6 ==>
n ≠ counter + 7 ==>
n ≠ counter + 8 ==>
n ≠ counter + 9 ==>
n < counter + 10 ==> False"
by(simp)
I show here that there's interaction between simp and a linear arithmetic tactic. (The comment in Arith_Examples.thy explains there are variations.)
(*_SRC.1_*)
lemma "
n ≠ counter ==>
n ≠ Suc counter ==>
n ≠ Suc (Suc counter) ==>
counter ≤ n ==>
n < counter + 3 ==> False"
using[[simp_trace, linarith_trace]]
(*Click "1000" at the bottom of the output panel to get it to finish.
The trace shows that `arith` is called very soon, but that there's also
a lot of simp rule rewriting, such as with the rule `Groups.add_ac_2`.*)
apply(simp only:)
done
I show that you get the same trace message about neq_limit with both apply(simp only:) and apply(arith), but one proof goes through, and one doesn't. Apparently, simp uses one form of a linear arithmetic tactic, and arith uses another.
(*_SRC.2_*)
lemma "n ≠ counter ==>
n ≠ Suc counter ==>
n ≠ Suc (Suc counter) ==>
n ≠ counter + 3 ==>
n ≠ counter + 4 ==>
n ≠ counter + 5 ==>
n ≠ counter + 6 ==>
n ≠ counter + 7 ==>
n ≠ counter + 8 ==>
n ≠ counter + 9 ==>
counter ≤ n ==>
n < counter + 10 ==> False"
using[[linarith_trace]]
apply(simp only:)
(*Gets the following error message, and it goes no further:
Trying to refute subgoal 1...
neq_limit exceeded (current value is 9), ignoring all inequalities
*)
oops
(*_SRC.3_*)
lemma "n ≠ counter ==>
n ≠ Suc counter ==>
n ≠ Suc (Suc counter) ==>
n ≠ counter + 3 ==>
n ≠ counter + 4 ==>
n ≠ counter + 5 ==>
n ≠ counter + 6 ==>
n ≠ counter + 7 ==>
n ≠ counter + 8 ==>
n ≠ counter + 9 ==>
counter ≤ n ==>
n < counter + 10 ==> False"
using[[simp_trace, linarith_trace]]
apply(arith)
(*Same complaint about "9", but the proof will go through if there's no trace:
Trying to refute subgoal 1...
neq_limit exceeded (current value is 9), ignoring all inequalities
*)
oops

Resources