Canonical way to get a more specific lemma - isabelle

Say I have a lemma mylem: foo ?a = bar ?a, and I need to apply it on a goal that has two occurrences of foo, e.g. baz (foo (f p q)) (foo (g r s)), but only at one of these positions. I know of two ways of doing that without having to write out all of p,q..., which can be complex expressions.
Using apply (subst mylem) followed by an appropriate number (here, zero or one) of back commands.
Using apply (subst mylem[where a = 'foo x y', standard]), where x and y are unbound names.
The use of subst here is just for demonstration; I really do want to modify the lemma, e.g. to use it with rule when there are multiple possible matches that I’d like to disambiguate this way.
Both approaches look like bad style to me. Is there a nicer way of achieving that?

You can tell subst which occurrence it should replace: subst (i) mylem unfolds mylem at the i-th matching occurrence. This saves you the back steps. You can also list multiple positions as in subst (1 2) mylem. If you want to unfold mylem in premises, use subst (asm) (1 2) mylem.
In general, I do not know a way to achieve what you want inside an apply script. On the theory level, you can use lemmas with the for clause to generalise over locally introduced variables:
lemmas mylem' = mylem[where a="f x y"] for x y
Inside a structured proof, you can do it explicitly like this:
{ fix x y note mylem[where a="f x y"] }
note mylem' = this

Related

SMLNJ powerset function

I am trying to print the size of a list created from below power set function
fun add x ys = x :: ys;
fun powerset ([]) = [[]]
| powerset (x::xr) = powerset xr # map (add x) (powerset xr) ;
val it = [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]] : int list list;
I have the list size function
fun size xs = (foldr op+ 0 o map (fn x => 1)) xs;
I couldnt able to merge these two functions and get the result like
I need something like this:
[(0,[]),(1,[3]),(1,[2]),(2,[2,3]),(1,[1]),(2,[1,3]),(2,[1,2]),(3,[1,2,3])]
Could anyone please help me with this?
You can get the length of a list using the built-in List.length.
You seem to forget to mention that you have the constraint that you can only use higher-order functions. (I am guessing you have this constraint because others these days are asking how to write powerset functions with this constraint, and using foldr to count, like you do, seems a little constructed.)
Your example indicates that you are trying to count each list in a list of lists, and not just the length of one list. For that you'd want to map the counting function across your list of lists. But that'd just give you a list of lengths, and your desired output seems to be a list of tuples containing both the length and the actual list.
Here are some hints:
You might as well use foldl rather than foldr since addition is associative.
You don't need to first map (fn x => 1) - this adds an unnecessary iteration of the list. You're probably doing this because folding seems complicated and you only just managed to write foldr op+ 0. This is symptomatic of not having understood the first argument of fold.
Try, instead of op+, to write the fold expression using an anonymous function:
fun size L = foldl (fn (x, acc) => ...) 0 L
Compare this to op+ which, if written like an anonymous function, would look like:
fn (x, y) => x + y
Folding with op+ carries some very implicit uses of the + operator: You want to discard one operand (since not its value but its presence counts) and use the other one as an accumulating variable (which is better understood by calling it acc rather than y).
If you're unsure what I mean about accumulating variable, consider this recursive version of size:
fun size L =
let fun sizeHelper ([], acc) = acc
| sizeHelper (x::xs, acc) = sizeHelper (xs, 1+acc)
in sizeHelper (L, 0) end
Its helper function has an extra argument for carrying a result through recursive calls. This makes the function tail-recursive, and folding is one generalisation of this technique; the second argument to fold's helper function (given as an argument) is the accumulating variable. (The first argument to fold's helper function is a single argument rather than a list, unlike the explicitly recursive version of size above.)
Given your size function (aka List.length), you're only a third of the way, since
size [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]]
gives you 8 and not [(0,[]),(1,[3]),(1,[2]),(2,[2,3]),...)]
So you need to write another function that (a) applies size to each element, which would give you [0,1,1,2,...], and (b) somehow combine that with the input list [[],[3],[2],[2,3],...]. You could do that either in two steps using zip/map, or in one step using only foldr.
Try and write a foldr expression that does nothing to an input list L:
foldr (fn (x, acc) => ...) [] L
(Like with op+, doing op:: instead of writing an anonymous function would be cheating.)
Then think of each x as a list.

Define the notion of "pairs" using higher-order logic

Revising for a course on automated reasoning and I don't quite understand how to answer this question:
Show how the notion of pairs (x, y) can be defined in higher-order logic using a lambda abstraction. Define a function π1 that returns the first element of such a pair. Finally, show that π1(x, y) = x.
I've found similar questions on stackoverflow, but they're all to do with scheme, which I've never used. An explanation in English/relevant mathematical notation would be appreciated
Here you go
PAIR := λx. λy. λp. p x y
π1 := λp. p (λx. λy. x)
π2 := λp. p (λx. λy. y)
π1 (PAIR a b) => a
π2 (PAIR a b) => b
Check the wiki entry on Church encoding for some good examples, too
The main topic of this question is to understand how data can be represented as functions. When you're working with other paradigms , the normal way of thinking is "data = something that's stored in a variable" (could be an array, object, whatever structure you want).
But when we're in functional programming, we can also represent data as functions.
So let's say you want a function pair(x,y)
This is "pseudo" lisp language:
(function pair x y =
lambda(pick)
if pick = 1 return x
else return y )
That example, is showing a function that returns a lambda function which expects a parameter.
(function pi this-is-pair = this-is-pair 1)
this-is-pair should be constructed with a pair function, therefore, the parameter is a function which expects other parameter (pick).
And now, you can test what you need
(pi (pair x y ) ) should return x
I would highly recommend you to see this video about compound data. Most of the examples are made on lisp, but it's great to understand a concept like that.
Pairs or tuples describes Products Domain, is the union of all elements of the set A and all elements of the set B:
A × B = { (a, b) | a ∈ A, b ∈ B }
Here, A and B are diferent types, so if you for example are in a laguage program like C, Java, you can have pair like (String, Integer), (Char, Boolean), (Double, Double)
Now, the function π1, is just a function that takes a pair and returns the first element, this function is called in usually first, and that's how it looks like π1(x, y) = x, on the other hand you have second, doing the same thing but returning the second element:
fst(a, b) = a
snd(a, b) = b
When I studied the signature "Characteristics of the programming languages" in college our professor recommended this book, see the chapter Product Domain to understand well all this concepts.

Ordering a List of Pairs

Can anyone give me a well-written implementation of how to order a list of pairs in scheme using a helper function (based on the value of the car of each of the pairs)? For example, '((3 2) (1 2) (8 4) (0 6)) should be ordered as '((0 6) (1 2) (3 2) (8 4)). This seems like such a simple thing to do, but for some reason I am drawing a blank.
Well, first of all you can use your favorite built-in sort routine, and specify it be sorting by car, e.g. in Common LISP
(sort ls #'< :key #'car)
if your Scheme lacks the ability to specify key, you can emulate this by a comparison procedure
(sort ls (lambda (a b) (< (car a) (car b))))
second, if you want to reimplement this, you could use the approach of mergesort: break up your list into monotone increasing portions, then merge them pairwise until there's only one left. In Haskell,
mergesortBy f xs
| null xs = []
| [s] <- until (null.tail) (pairwise (mergeBy f)) (breakup xs) = s
pairwise g (a:b:t) = g a b : pairwise g t
pairwise _ t = t
breakup xs = [[x] | x <- xs] -- a list of (a list of x) for x in xs
since the portions are monotone increasing (or at least non-decreasing), mergeBy can be easily implemented.
Of course, a "well-written" implementation will replace the rudimentary breakup shown here with an initial phase which will try to make longer chunks, preserving the non-decreasing and reversing the non-increasing chunks on the go (a Haskell example is here). pairwise and mergeBy (and perhaps even breakup) functions will have to be fused into one, to make the overall implementation more on-line, since Scheme is (usually) a strict (i.e. non-lazy) language. You could use explicit suspensions in the internal lists being merged, so that taking a few first elements off a sorted list is an O(n) operation.

Simple functions for SML/NJ

I was required to write a set of functions for problems in class. I think the way I wrote them was a bit more complicated than they needed to be. I had to implement all the functions myself, without using and pre-defined ones. I'd like to know if there are any quick any easy "one line" versions of these answers?
Sets can be represented as lists. The members of a set may appear in any order on the list, but there shouldn't be more than one
occurrence of an element on the list.
(a) Define dif(A, B) to
compute the set difference of A and B, A-B.
(b) Define cartesian(A,
B) to compute the Cartesian product of set A and set B, { (a, b) |
a∈A, b∈B }.
(c) Consider the mathematical-induction proof of the
following: If a set A has n elements, then the powerset of A has 2n
elements. Following the proof, define powerset(A) to compute the
powerset of set A, { B | B ⊆ A }.
(d) Define a function which, given
a set A and a natural number k, returns the set of all the subsets of
A of size k.
(* Takes in an element and a list and compares to see if element is in list*)
fun helperMem(x,[]) = false
| helperMem(x,n::y) =
if x=n then true
else helperMem(x,y);
(* Takes in two lists and gives back a single list containing unique elements of each*)
fun helperUnion([],y) = y
| helperUnion(a::x,y) =
if helperMem(a,y) then helperUnion(x,y)
else a::helperUnion(x,y);
(* Takes in an element and a list. Attaches new element to list or list of lists*)
fun helperAttach(a,[]) = []
helperAttach(a,b::y) = helperUnion([a],b)::helperAttach(a,y);
(* Problem 1-a *)
fun myDifference([],y) = []
| myDifference(a::x,y) =
if helper(a,y) then myDifference(x,y)
else a::myDifference(x,y);
(* Problem 1-b *)
fun myCartesian(xs, ys) =
let fun first(x,[]) = []
| first(x, y::ys) = (x,y)::first(x,ys)
fun second([], ys) = []
| second(x::xs, ys) = first(x, ys) # second(xs,ys)
in second(xs,ys)
end;
(* Problem 1-c *)
fun power([]) = [[]]
| power(a::y) = union(power(y),insert(a,power(y)));
I never got to problem 1-d, as these took me a while to get. Any suggestions on cutting these shorter? There was another problem that I didn't get, but I'd like to know how to solve it for future tests.
(staircase problem) You want to go up a staircase of n (>0) steps. At one time, you can go by one step, two steps, or three steps. But,
for example, if there is one step left to go, you can go only by one
step, not by two or three steps. How many different ways are there to
go up the staircase? Solve this problem with sml. (a) Solve it
recursively. (b) Solve it iteratively.
Any help on how to solve this?
Your set functions seem nice. I would not change anything principal about them except perhaps their formatting and naming:
fun member (x, []) = false
| member (x, y::ys) = x = y orelse member (x, ys)
fun dif ([], B) = []
| dif (a::A, B) = if member (a, B) then dif (A, B) else a::dif(A, B)
fun union ([], B) = B
| union (a::A, B) = if member (a, B) then union (A, B) else a::union(A, B)
(* Your cartesian looks nice as it is. Here is how you could do it using map: *)
local val concat = List.concat
val map = List.map
in fun cartesian (A, B) = concat (map (fn a => map (fn b => (a,b)) B) A) end
Your power is also very neat. If you call your function insert, it deserves a comment about inserting something into many lists. Perhaps insertEach or similar is a better name.
On your last task, since this is a counting problem, you don't need to generate the actual combinations of steps (e.g. as lists of steps), only count them. Using the recursive approach, try and write the base cases down as they are in the problem description.
I.e., make a function steps : int -> int where the number of ways to take 0, 1 and 2 steps are pre-calculated, but for n steps, n > 2, you know that there is a set of combinations of steps that begin with either 1, 2 or 3 steps plus the number combinations of taking n-1, n-2 and n-3 steps respectively.
Using the iterative approach, start from the bottom and use parameterised counting variables. (Sorry for the vague hint here.)

tail recursion sum, power, gcd in prolog?

how can I accomplish this:
Give a tail-recursive definition for each of the following predicates.
power(X,Y,Z): XY=Z.
gcd(X,Y,Z): The greatest common divisor of X and Y is Z.
sum(L,Sum): Sum is the sum of the elements in L.
so far I have done this but not sure if that's correct
power(_,0,1) :- !.
power(X,Y,Z) :- Y1 is Y - 1,power(X,Y1,Z1),Z is X * Z1.
sum(void,0).
sum(t(V,L,R),S) :- sum(L,S1),sum(R,S2), S is V + S1 + S2.
These are not tail recursive. You can write tail recursive variants by using an accumulator, see this answer.
Your sum is over a tree, which is unusual, normally one would use a list. In Prolog [] is the empty list and [X|R] is the pattern for a nonempty list with the head X and the tail R.

Resources