Here is my try at proving that Takeuchi function does terminate:
function moore :: "(int ⇒ int ⇒ int) ⇒ (int ⇒ int ⇒ int)" where
"moore x y z = ((if (x ≤ y) then 0 else 1) (max(x,y,z) - min(x,y,z)) (x - min(x,y,z)))"
fun tk :: "int ⇒ int ⇒ int ⇒ int" where
"tk x y z = ( if x ≤ y then y else tk (tk (x-1) y z) (tk (y-1) z x) (tk (z-1) x y) )"
there are several problems here. First I should return a triple in the function moore. Right now, the system is complaining with error:
Type unification failed: Clash of types "int" and "_ ⇒ _"
Type error in application: incompatible operand type
Operator: op ≤ x :: (int ⇒ int ⇒ int) ⇒ bool Operand: y :: int
Then, of course the termination proof does not succeed since I didn't apply the termination function above (the way to this should be similar to here).
How can I fix this?
First of all, your moore function currently does not return a triple but a function taking two ints and returning an int. For a triple, you would have to write int × int × int. Also, tuples are constructed as (x, y, z), not as x y z like you did.
Also, there is no reason to use fun (let alone function) to define the moore function, since it is not recursive. definition works fine. For tk, on the other hand, you will need to use function since there is no obvious lexicographic termination measure.
Also, functions returning triple are usually a bit ugly to handle in Isabelle; it makes more sense to define three individual functions. Putting all this together, you can then define your functions like this:
definition m1 where "m1 = (λ(x,y,z). if x ≤ y then 0 else 1)"
definition m2 where "m2 = (λ(x,y,z). nat (Max {x, y, z} - Min {x, y, z}))"
definition m3 where "m3 = (λ(x,y,z). nat (x - Min {x, y, z}))"
function tk :: "int ⇒ int ⇒ int ⇒ int" where
"tk x y z = ( if x ≤ y then y else tk (tk (x-1) y z) (tk (y-1) z x) (tk (z-1) x y))"
by auto
You can then easily prove a partial correctness theorem for the tk function using the partial induction rule tk.pinduct:
lemma tk_altdef:
assumes "tk_dom (x, y, z)"
shows "tk x y z = (if x ≤ y then y else if y ≤ z then z else x)"
using assms by (induction rule: tk.pinduct) (simp_all add: tk.psimps)
The tk_dom (x, y, z) assumption says that tk terminates on the values (x, y, z).
Now, if I read the paper you linked correctly, the template for the termination proof looks like this:
termination proof (relation "m1 <*mlex*> m2 <*mlex*> m3 <*mlex*> {}", goal_cases)
case 1
show "wf (m1 <*mlex*> m2 <*mlex*> m3 <*mlex*> {})"
by (auto intro: wf_mlex)
next
case (2 x y z)
thus ?case sorry
next
case (3 x y z)
thus ?case sorry
next
case (4 x y z)
thus ?case sorry
next
case (5 x y z)
thus ?case sorry
qed
In the last four cases here, you will have to do the actual work of showing that the measure decreases. The <*mlex*> operator combines several measures into a single lexicographic measure. The relevant rules for showing that something is in contained in that measure are mlex_less and mlex_le.
Related
I'm currently trying use Isabelle/HOL's reification tactic. I'm unable to use different interpretation functions below quantifiers/lambdas. The below MWE illustrates this. The important part is the definition of the form function, where the ter call occurs below the ∀. When trying to use the reify tactic I get an Cannot find the atoms equation error. I don't get this error for interpretation functions which only call themselves under quantifiers.
I can't really reformulate my problem to avoid this. Does anybody know how to get reify working for such cases?
theory MWE
imports
"HOL-Library.Reflection"
begin
datatype Ter = V nat | P Ter Ter
datatype Form = All0 Ter
fun ter :: "Ter ⇒ nat list ⇒ nat"
where "ter (V n) vs = vs ! n"
| "ter (P t1 t2) vs = ter t1 vs + ter t2 vs"
fun form :: "Form ⇒ nat list ⇒ bool"
where "form (All0 t) vs = (∀ v . ter t (v#vs) = 0)" (* use of different interpretation function below quantifier *)
(*
I would expect this to reify to:
form (All0 (P (V 0) (V 0))) []
instead I get an error :-(
*)
lemma "∀ n :: nat . n + n = 0"
apply (reify ter.simps form.simps)
(* proof (prove)
goal (1 subgoal):
1. ∀n. n + n = n + n
Cannot find the atoms equation *)
oops
(* As a side note: the following example in src/HOL/ex/Reflection_Examples.thy (line 448, Isabelle2022) seems to be broken? For me, the reify invocation
doesn't change the goal at all. It uses quantifiers too, but only calls the same interpretation function under quantifiers and also doesn't throw an error,
so at least for me this seems to be unrelated to my problem.
*)
(*
lemma " ∀x. ∃n. ((Suc n) * length (([(3::int) * x + f t * y - 9 + (- z)] # []) # xs) = length xs) ∧ m < 5*n - length (xs # [2,3,4,x*z + 8 - y]) ⟶ (∃p. ∀q. p ∧ q ⟶ r)"
apply (reify Irifm.simps Irnat_simps Irlist.simps Irint_simps)
oops
*)
end
I am trying to prove the following lemma (which is the meaning formula for the addition of two Binary numerals).
It goes like this :
lemma (in th2) addMeaningF_2: "∀m. m ≤ n ⟹ (m = (len x + len y) ⟹ (evalBinNum_1 (addBinNum x y) = plus (evalBinNum_1 x) (evalBinNum_1 y)))"
I am trying to perform strong induction. When I apply(induction n rule: less_induct) on the lemma, it throws an error.
exception THM 0 raised (line 755 of "drule.ML"):
infer_instantiate_types: type ?'a of variable ?a
cannot be unified with type 'b of term n
(⋀x. (⋀y. y < x ⟹ ?P y) ⟹ ?P x) ⟹ ?P ?a
Can anyone explain this?
Edit:
For more context
locale th2 = th1 +
fixes
plus :: "'a ⇒ 'a ⇒ 'a"
assumes
arith_1: "plus n zero = n"
and plus_suc: "plus n (suc m) = suc ( plus n m)"
len and evalBinNum_1 are both recursive functions
len gives us the length of a given binary numeral, while evalBinNum_1 evaluates binary numerals.
fun (in th2) evalBinNum_1 :: "BinNum ⇒ 'a"
where
"evalBinNum_1 Zero = zero"|
"evalBinNum_1 One = suc(zero)"|
"evalBinNum_1 (JoinZero x) = plus (evalBinNum_1 x) (evalBinNum_1 x)"|
"evalBinNum_1 (JoinOne x) = plus (plus (evalBinNum_1 x) (evalBinNum_1 x)) (suc zero)"
The problem is that Isabelle cannot infer the type of n (or the bound occurrence of m) when trying to use the induction rule less_induct. You might want to add a type annotation such as (n::nat) in your lemma. For the sake of generality, you might want to state that the type of n is an instance of the class wellorder, that is, (n::'a::wellorder). On another subject, I think there is a logical issue with your lemma statement: I guess you actually mean ∀m. m ≤ (n::nat) ⟶ ... ⟶ ... or, equivalently, ⋀m. m ≤ (n::nat) ⟹ ... ⟹ .... Finally, it would be good to know the context of your problem (e.g., there seems to be a locale th2 involved) for a more precise answer.
I have a beginner's question about Isabelle/HOL:
I want to prove the following lemma:
lemma
shows "{(x,y) . x ∈ {0..<n} ∧ y ∈ {0..<n} ∧ x = y} = {(x,x). x < n}"
But the proof state is:
proof (prove)
goal (1 subgoal):
1. {(x, y). x ∈ {0..<n} ∧ y ∈ {0..<n} ∧ x = y} = {(xa, x). x < n}
Why did the xa appear and how can I define the set the right (succinct) way?
The (x,y) in the set comprehension {(x,y). ....} is binding variable names. As you write {(x,x). x < n}, you bind two variables named x, where the second x shadows the first.
{(x,x). x < n} is just a nice syntax for a lambda term, actually. Internally, it translates to Collect (case_prod (λx. λx. x < n)). Looking at the term this way, the shadowing is more obvious.
To fix your problem, you have to explicitly express the information that the first and the second bound variable are to be identical, that is: {(x1,x2). x1 = x2 ∧ x1 < n}.
As a side note: The lemma you are trying to show is not true. (For example, n could be an int.) If you want n to be a nat, you have to make this explicit, for example by giving a type in your goal like this {(x,y). x ∈ {0..<(n::nat)} ∧ y ∈ {0..<n} ∧ x = y} = {(x1,x2). x1 = x2 ∧ x1 < n}.
Especially, if you are a beginner, I would strongly suggest to introduce free variables in lemma heads explicitly with the syntax lemma Name: fixes n :: ‹nat› assumes ‹...› shows ‹...›.
I need to generate a code calculating all values greater or equal to some value:
datatype ty = A | B | C
instantiation ty :: order
begin
fun less_ty where
"A < x = (x = C)"
| "B < x = (x = C)"
| "C < x = False"
definition "(x :: ty) ≤ y ≡ x = y ∨ x < y"
instance
apply intro_classes
apply (metis less_eq_ty_def less_ty.elims(2) ty.distinct(3) ty.distinct(5))
apply (simp add: less_eq_ty_def)
apply (metis less_eq_ty_def less_ty.elims(2))
using less_eq_ty_def less_ty.elims(2) by fastforce
end
instantiation ty :: enum
begin
definition [simp]: "enum_ty ≡ [A, B, C]"
definition [simp]: "enum_all_ty P ≡ P A ∧ P B ∧ P C"
definition [simp]: "enum_ex_ty P ≡ P A ∨ P B ∨ P C"
instance
apply intro_classes
apply auto
by (case_tac x, auto)+
end
lemma less_eq_code_predI [code_pred_intro]:
"Predicate_Compile.contains {z. x ≤ z} y ⟹ x ≤ y"
(* "Predicate_Compile.contains {z. z ≤ y} x ⟹ x ≤ y"*)
by (simp_all add: Predicate_Compile.contains_def)
code_pred [show_modes] less_eq
by (simp add: Predicate_Compile.containsI)
values "{x. A ≤ x}"
(* values "{x. x ≤ C}" *)
It works fine. But the theory looks over-complicated. Also I can't calculate values less or equal to some value. If one will uncoment the 2nd part of less_eq_code_predI lemma, then less_eq will have only one mode i => i => boolpos.
Is there a simpler and more generic approach?
Can less_eq support i => o => boolpos and o => i => boolpos at the same time?
Is it possible not to declare ty as an instance of enum class? I can declare a function returning a set of elements greater or equal to some element:
fun ge_values where
"ge_values A = {A, C}"
| "ge_values B = {B, C}"
| "ge_values C = {C}"
lemma ge_values_eq_less_eq_ty:
"{y. x ≤ y} = ge_values x"
by (cases x; auto simp add: dual_order.order_iff_strict)
This would allow me to remove enum and code_pred stuff. But in this case I will not be able to use this function in the definition of other predicates. How to replace (≤) by ge_values in the following definition?
inductive pred1 where
"x ≤ y ⟹ pred1 x y"
code_pred [show_modes] pred1 .
I need pred1 to have at least i => o => boolpos mode.
The predicate compiler has an option inductify that tries to convert functional definitions into inductive ones. It is somewhat experimental and does not work in every case, so use it with care. In the above example, the type classes make the whole situation a bit more complicated. Here's what I managed to get working:
case_of_simps less_ty_alt: less_ty.simps
definition less_ty' :: "ty ⇒ ty ⇒ bool" where "less_ty' = (<)"
declare less_ty_alt [folded less_ty'_def, code_pred_def]
code_pred [inductify, show_modes] "less_ty'" .
values "{x. less_ty' A x}"
The first line convertes the pattern-matching equations into one with a case expression on the right. It uses the command case_of_simps from HOL-Library.Simps_Case_Conv.
Unfortunately, the predicate compiler seems to have trouble with compiling type class operations. At least I could not get it to work.
So the second line introduces a new constant for (<) on ty.
The attribute code_pred_def tells the predicate compiler to use the given theorem (namely less_ty_alt with less_ty' instead of (<)) as the "defining equation".
code_pred with the inductify option looks at the equation for less_ty' declared by code_pred_def and derives an inductive definition out of that. inductify usually works well with case expressions, constructors and quantifiers. Everything beyond that is at your own risk.
Alternatively, you could also manually implement the enumeration similar to ge_values and register the connection between (<) and ge_values with the predicate compiler. See the setup block at the end of the Predicate_Compile theory in the distribution for an example with Predicate.contains. Note however that the predicate compiler works best with predicates and not with sets. So you'd have to write ge_values in the predicate monad Predicate.pred.
I am new to Isabelle and I am trying to define primitive recursive functions. I have tried out addition but I am having trouble with multiplication.
datatype nati = Zero | Suc nati
primrec add :: "nati ⇒ nati ⇒ nati" where
"add Zero n = n" |
"add (Suc m) n = Suc(add m n)"
primrec mult :: "nati ⇒ nati ⇒ nati" where
"mult Suc(Zero) n = n" |
"mult (Suc m) n = add((mult m n) m)"
I get the following error for the above code
Type unification failed: Clash of types "_ ⇒ _" and "nati"
Type error in application: operator not of function type
Operator: mult m n :: nati
Operand: m :: nati
Any ideas?
The problem is your mult function: It should look like this:
primrec mult :: "nati ⇒ nati ⇒ nati" where
"mult Zero n = Zero" |
"mult (Suc m) n = add (mult m n) m"
Function application in functional programming/Lambda calculus is the operation that binds strongest and it associates to the left: something like f x y means ‘f applied to x, and the result applied to y’ – or, equivalently due to Currying: the function f applied to the parameters x and y.
Therefore, something like mult Suc(Zero) n would be read as mult Suc Zero n, i.e. the function mult would have to be a function taking three parameters, namely Suc, Zero, and n. That gives you a type error. Similarly, add ((mult m n) m) does not work, since that is identical to add (mult m n m), which would mean that add is a function taking one parameter and mult is one taking three.
Lastly, if you fix all that, you will get another error saying you have a non-primitive pattern on the left-hand side of your mult function. You cannot pattern-match on something like Suc Zero since it is not a primitive pattern. You can do that if you use fun instead of primrec, but it is not what you want to do here: You want to instead handle the cases Zero and Suc (see my solution). In your definition, mult Zero n would even be undefined.