I want to make a definition in Isabelle which returns all the pairs of a map function.
I have the following definition in Z
\begin{schema}[X, Y, Z]
allPairs: (X \pfun (Y \rel Z)) \fun (Y \rel Z)
where
\<forall f: (X \<pfun (Y \rel Z)) #
allPairs f == \<bigcup{x:X | x \in \dom f # fx}
\end{schema}
Therefore I want to make a definition which takes an element of type
(X \<rightharpoonup> ((Y * Z) set))) or (X \<rightharpoonup> (Y \<rightharpoonup> Z)) in isabelle and return ((Y * Z) set) for both.
I have the following so far
definition allPairs ::
"('X \<rightharpoonup ('Y * 'Z) set) => ('Y * 'Z) set"
where
"allPairs f == ⋃{yz. yz ∈ ran f}"
Related
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 ‹...›.
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.
I wonder if there is a way to do something like this (x, y < 0, z)
with y < 0
There are three cases in my example y = 0, y < 0 and else.
I know how to implement this function with different approaches, but
I just like this way and want to know if this is possible in some way.
let rec f = function
| (x, 0, y) -> x
| (x, y < 0, z) -> f (x y z)
| (x, y, z) -> f (z y x)
Just that you know, I removed the complexity of the tuple in the recursive call, so the function has no purpose right now.
You can add a condition after a pattern using the when keyword. With that, you can do what you want like this:
let rec f = function
| (x, 0, y) -> x
| (x, y, z) when y < 0 -> f (x, y, z)
| (x, y, z) -> f (z, y, x)
This will cause infinite recursion because f (x, y, z) doesn't change anything about the arguments, but I assume that problem does not exist in your real code.
I created a function and helper function that find the number of repeating elements in a list, and what those elements.
let rec _encode l x =
match l with
| [] -> 0
| head::rest -> (if head = x then 1 else 0) + encode rest x
let encode l x = ((_encode l x), x)
In this case, I have to specify what that element is for it to search.
So this is a two part question. 1) How do I do it to return a list of tuples, with format (int * 'a) list, where int is the # of rep, and 'a is the element that is repeating.
2) How would I implement this using fold_right?
I was thinking something along the lines of:
let encode (l : 'a list) : (int * 'a) list = fold_right (fun (x,hd) lst ->
match x with
| [] -> 0
| hd :: rest -> if hd x then (x+1, hd) else (x, hd)) l []
Your attempt looks very confused:
It doesn't use lst, hd (the first one), or rest.
x is used as a list (match x with []) and a number (x+1).
The elements of x (list) are functions that return bools?? (... hd::rest -> ... if hd x)
The function sometimes returns a number (0) and sometimes a tuple ((x, hd)).
Here's how I'd do it:
let encode l =
let f x = function
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
in
fold_right f l []
Which is the same as:
let encode l =
let f x z = match z with
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
in
fold_right f l []
Which is the same as:
let encode l =
fold_right (fun x z ->
match z with
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
) l []
I am have some problems with recursion in Lazy Computations. I need calculation the square root by Newton Raphson method. I do not know how to apply a lazy evaluation. This is my code:
let next x z = ((x + z / x) / 2.);
let rec iterate f x =
List.Cons(x, (iterate f (f x)));
let rec within eps list =
let a = float (List.head list);
let b = float (List.head (List.tail list));
let rest = (List.tail (List.tail (list)));
if (abs(a - b) <= eps * abs(b))
then b
else within eps (List.tail (list));
let lazySqrt a0 eps z =
within eps (iterate (next z) a0);
let result2 = lazySqrt 10. Eps fvalue;
printfn "lazy approach";
printfn "result: %f" result2;
Of course, stack overflow exception.
You're using F# lists which has eager evaluation. In your example, you need lazy evaluation and decomposing lists, so F# PowerPack's LazyList is appropriate to use:
let next z x = (x + z / x) / 2.
let rec iterate f x =
LazyList.consDelayed x (fun () -> iterate f (f x))
let rec within eps list =
match list with
| LazyList.Cons(a, LazyList.Cons(b, rest)) when abs(a - b) <= eps * abs(b) -> b
| LazyList.Cons(a, res) -> within eps res
| LazyList.Nil -> failwith "Unexpected pattern"
let lazySqrt a0 eps z =
within eps (iterate (next z) a0)
let result2 = lazySqrt 10. Eps fvalue
printfn "lazy approach"
printfn "result: %f" result2
Notice that I use pattern matching which is more idiomatic than head and tail.
If you don't mind a slightly different approach, Seq.unfold is natural here:
let next z x = (x + z / x) / 2.
let lazySqrt a0 eps z =
a0
|> Seq.unfold (fun a ->
let b = next z a
if abs(a - b) <= eps * abs(b) then None else Some(a, b))
|> Seq.fold (fun _ x -> x) a0
If you need lazy computations, then you have to use appropriate tools. List is not lazy, it is computed to the end. Your iterate function never ends, so the entire code stack overflows in this function.
You may use Seq here.
Note: Seq.skip almost inevitably leads you to an O(N^2) complexity.
let next N x = ((x + N / x) / 2.);
let rec iterate f x = seq {
yield x
yield! iterate f (f x)
}
let rec within eps list =
let a = Seq.head list
let b = list |> Seq.skip 1 |> Seq.head
if (abs(a - b) <= eps * abs(b))
then b
else list |> Seq.skip 1 |> within eps
let lazySqrt a0 eps z =
within eps (iterate (next z) a0);
let result2 = lazySqrt 10. 0.0001 42.;
printfn "lazy approach";
printfn "result: %f" result2;
// 6.4807406986501
Yet another approach is to use LazyList from F# PowerPack. The code is available in this article. Copying it to my answer for sake of integrity:
open Microsoft.FSharp.Collections.LazyList
let next N (x:float) = (x + N/x) / 2.0
let rec repeat f a =
LazyList.consDelayed a (fun() -> repeat f (f a))
let rec within (eps : float) = function
| LazyList.Cons(a, LazyList.Cons(b, rest)) when (abs (a - b)) <= eps -> b
| x -> within eps (LazyList.tail x)
let newton_square a0 eps N = within eps (repeat (next N) a0)
printfn "%A" (newton_square 16.0 0.001 16.0)
Some minor notes:
Your next function is wrong;
The meaning of eps is relative accuracy while in most academic books I've seen an absolute accuracy. The difference between the two is whether or not it's measured against b, here: <= eps * abs(b). The code from FPish treats eps as an absolute accuracy.