lambda calculus for functional programming - functional-programming

in lambda calculus (λ x. λ y. λ s. λ z. x s (y s z)) is used for addition of two Church numerals how can we explain this, is there any good resource the lambda calculus for functional programming ? your help is much appreciated

Actually λ f1. λ f2. λ s. λ z. (f1 s (f2 s z)) computes addition because it is in effect substituting (f2 s z), the number represented by f2, to the "zero" inside (f1 s z).
Example: Let's take two for f2, s s z in expanded form. f1 is one: s z. Replace that last z by f2 and you get s s s z, the expanded form for three.
This would be easier with a blackboard and hand-waving, sorry.

In lambda calculus, you code a datatype in terms of the operations it induces. For instance, a boolean is a just a choice function that takes in input two values a and b and either returns a or b:
true = \a,b.a false = \a,b.b
What is the use of a natural number? Its main computational purpose is to
provide a bound to iteration. So, we code a natural number as an operator
that takes in input a function f, a value x, and iterate the application
of f over x for n times:
n = \f,x.f(f(....(f x)...))
with n occurrences of f.
Now, if you want to iterate n + m times the function f starting from x
you must start iterating n times, that is (n f x), and then iterate for m
additional times, starting from the previous result, that is
m f (n f x)
Similarly, if you want to iterate n*m times you need to iterate m times
the operation of iterating n times f (like in two nested loops), that is
m (n f) x
The previous encoding of datatypes is more formally explained in terms
of constructors and corresponding eliminators (the so called
Bohm-Berarducci encoding).

Related

Map function in "Haskell like" language using folr

I'm trying to write a map function in a Haskell-like language. The operation I'm trying to use is a fold_right. So basically writing a map using foldr. However, I get a "parameter mismatch error".
Thank you.
map = lambda X. lambda Y.
lambda f: X -> Y.
lambda l: List X.
l [X] (
lambda hd:X.
lambda tl: List Y.
(cons[Y](f hd))(tl)
) (nil [Y]);
The first argument to l should be the type of the result of the fold (at least, that's my educated guess), the "motive". You want the end result to be a List Y, not an X, so you should say that:
map =
lambda X. lambda Y. lambda f: X -> Y. lambda l: List X.
l
[List Y]
(lambda x: X. lambda rec_xs: List Y. cons [Y] (f x) rec_xs)
(nil [Y]);
Maybe you got confused and wrote X because l is a List X? l already knows that it contains Xs; you don't need to point it out again. You just need to point out what you want get out (which could be X, but it isn't in this case).

Rewriting sine using simprocs in Isabelle

I want to implement a simproc capable of rewriting the argument of sin into a linear combination x + k * pi + k' * pi / 2 (where ideally k' = 0 or k' = 1) and then apply existing lemmas about additions of arguments in sines.
The steps could be as follows:
Pattern match the goal to extract the argument of sin(expr):
fun dest_sine t =
case t of
(#{term "(sin):: real ⇒ real"} $ t') => t'
| _ => raise TERM ("dest_sine", [t]) ;
Prove that for some x, k, k': expr = x + k*pi + k' * pi/2.
Use existing lemmas to rewrite to a simpler trigonometric function:
fun rewriter x k k' =
if (k mod 2 = 0 andalso k' = 0) then #{term "sin"} $ x
else if (k mod 2 = 0 andalso k' = 1) then #{term "cos"} $ x
else if (k mod 2 = 1 andalso k' = 0) then #{term "-sin"} $ x
else #{term "-cos"} $ x
I'm stuck at step two. The idea is to use algebra simplifications to obtain the x,k,k' where the theorem holds. I believe schematic goals should do this but I haven't ever used them.
My thoughts
Could I rather assume that the expression is of this form and let the simplifier find it so that the simproc can be triggered?
If I first start assuming the linear form x + k*pi + k' * pi/2 then:
Extract x,k,k' from this combination.
Apply rewriter and obtain the corresponding term to be rewritten two.
Apply in a sequence: rules dealing with + pi/2, rules dealing with + 2 pi
I would start easy and ignore the pi / 2 part for now.
You probably want to build a simproc that matches on anything of the form sin x. Then you want to write a conversion that takes that term x (which is assumed to be a sum of several terms) and brings it into the form a + of_int b * p.
A conversion is essentially a function of type cterm → thm which takes a cterm ct and returns a theorem of the form ct ≡ …, i.e. it's a form of deterministic rewriting (a conversion can also fail by throwing a CTERM exception, by convention). There are a lot of combinators for building and using these in Pure/conv.ML.
This is probably a bit fiddly. You essentially have to descend through the term and, for each atom (i.e. anything not of the form _ + _) you have to figure out whether it can be brought into the form of_int … * pi (e.g. again by writing a conversion that does this transformation – to make it easy you can omit this part so that your procedure only works if the terms are already in that form) and then group all the terms of the form of_int … * pi to the right and all the terms not of that form to the left using associativity and commutativity.
I would suggest this:
Define a function SIN_SIMPROC_ATOM x n = x + of_int n * pi
Write a conversion sin_atom_conv that rewrites of_int n * pi to SIN_SIMPROC_ATOM 0 n and everything else into SIN_SIMPROC_ATOM x 0
Write a conversion that descends through +, applies sin_atom_conv to every atom, and then applies some kind of combination rule like SIN_SIMPROC_ATOM x1 n1 + SIN_SIMPROC_ATOM x2 n2 = SIN_SIMPROC_ATOM (x1 + x2) (n1 + n2)
In the end, you have rewritten your entire form to the form sin (SIN_SIMPROC_ATOM x n), and then you can apply some suitable rule to that.
It's not quite clear to me how to best handle the parity of n. You could rewrite sin (SIN_SIMPROC_ATOM x n) = (-1) ^ nat ¦n¦ * sin x but I'm not sure if that's what the user really wants in most cases. It might make more sense to only do that if you can deduce the parity of n statically (e.g. by using the simplifier) and then directly simplify to sin x or -sin x.
The situation becomes even more complicated if you want to include halves of π. You can of course extend SIN_SIMPROC_ATOM by a second term for halves of π (and one for doubles of π as well to make it more uniform). Or you could ad all of them together so that you just have a single integer n that describes your multiples of π/2, and k multiples of π simply contribute 2k to that term. And then you have to figure out what n mod 4 is – possibly again with the simplifier or with some clever static method.

R - function input and optimization

I usually have trouble inputing functions in R but they are always simple functions that I manage to work it out. However now I have a very complicated problem at hand that requires functions that has unknowns, summation and a matrix. And I am clueless where to begin. (This is not my homework question, just trying to work out something using a different method, hoping it works)
So I want to input a function:
A=∑i=1 N exp ^ [ ∑j=1 M Matrix ij * unknownj ]
and then minimize the function:
B= log A - ∑j=1 M unknown j * C j
so my goal is to find the j unknown parameters that minimizes function B.
But this is very complicated. You do not have to give me an answer directly. You can use another example to answer my question indirectly. Any help/tips/guidance is appreciated.
Let's see if we can break the problem into smaller things:
Let's name some variables first:
Let Q be an matrix with N rows and M columns
Let x be a (column) vector of length M (for a moment, think it's not an "unknown")
Let C be a (column) vector of length M
Notice that both A and B will be "scalars" (or, in R parlance, 1x1 vectors).
Hint: In R, you can do matrix multiplication using the %*% operator. See Quick-R: Matrix algebra.
Working on function A
Q %*% x is the product inside the sum which is inside the exponential function, so:
A <- function (Q, x) {
y <- Q %*% x # This will be a (column) vector of length `N`
return(sum(exp(y)) # This will be a scalar (more precisely, a 1x1 vector)
}
Not so hard, is it?
Working on function B
B <- function(Q, C, x) {
y <- sum(x * C) # or, since both x and C are column vectors:
# y <- t(x) %*% C
a <- A(Q, x)
return(log(a) - y)
}
So, that's how you would input the functions.
As for the optimization, I suggest you take a look to the optimx package; you'll need to supply starting values for vector x.

From expensive search to Integer Programming or Constraint Programming?

Consider m by n matrices M, all of whose entries are 0 or 1. For a given M, the question is whether there exists a non zero vector v, all of whose entries are -1, 0 or 1 for which Mv = 0. For example,
[0 1 1 1]
M_1 = [1 0 1 1]
[1 1 0 1]
In this example, there is no such vector v.
[1 0 0 0]
M_2 = [0 1 0 0]
[0 0 1 0]
In this example, the vector (0,0,0,1) gives M_2v = 0.
Given an m and n, I would like to find if there exists such an M so that there is no non-zero v such that Mv = 0.
If m = 3 and n = 4 then the answer is yes as we can see above.
I am currently solving this problem by trying all different M and v which is very expensive.
However, is it possible to express the problem as an integer
programming problem or constraint programming problem so I can use an
existing software package, such as SCIP instead which might be more
efficient.
This question is probably more mathematical than progamming. I haven't found the final answer yet, but at least some ideas are here:
We can re-state the problem in the following way.
Problem A: Fix positive integers m and n. Let S be the set of n-dimensional vectors whose entries are 0 or 1. Does there exist any m by n matrix M whose entries are 0 or 1, such that, for any two different vectors v_1 and v_2 in S, the vectors Mv_1 and Mv_2 are different. (Or, you may say that, the matrix M, considered as an application from n-dimensional vectors to m-dimensional vectors, is injective on the set S.)
In brief: given the pair (m, n), does there exist such an injective M?
Problem A is equivalent to the original problem. Indeed, if Mv_1 = Mv_2 for two different v_1 and v_2 in S, then we have M(v_1 - v_2) = 0, and the vector v_1 - v_2 will have only 0, 1, - 1 as entries. The inverse is obviously also true.
Another reinterpretation is:
Problem B: Let m, n be a positive integer and S be the set of n-dimensional vectors whose entries are 0 and 1. Can we find m vectors r_1, ..., r_m in S, such that, for any pair of different vectors v_1 and v_2 in S, there exists an r_i, which satisfies <v_1, r_i> != <v_2, r_i>? Here <x, y> is the usual inner product.
In brief: can we choose m vectors in S to distinguish everyone in S by taking inner product with the chosen ones?
Problem B is equivalent to Problem A, because you can identify the matrix M with m vectors in S.
In the following, I will use both descriptions of the problem freely.
Let's call the pair (m, n) a "good pair" if the answer to Problem A (or B) is yes.
With the description of Problem B, it is clear that, for a given n, there is a minimal m such that (m, n) is a good pair. Let us write m(n) for this minimal m associated to n.
Similarly, for a given m, there is a maximal n such that (m, n) is good. This is because, if (m, n) is good, i.e. there is an injective M as stated in Problem A, then for any n' <= n, erasing any n - n' columns of M will give an injective M'. Let us write n(m) for this maximal n associated to m.
So the task becomes to calculate the functions m(n) and/or n(m).
We first prove several lemmas:
Lemma 1: We have m(n + k) <= m(n) + m(k).
Proof: If M is an m(n) by n injective matrix for the pair (m(n), n) and K is an m(k) by k injective matrix for the pair (m(k), k), then the (m(n) + n(k)) by (n + k) matrix
[M 0]
[0 K]
works for the pair (m(n) + 1, n + 1). To see this, let v_1 and v_2 be any pair of different (n + k)-dimensional vectors. We may cut both of them into two pieces: the first n entries, and the last k entries. If the first pieces of them are not equal, then they can be distinguished by one of the first m(n) rows of the above matrix; if the first pieces of them are equal, then the second pieces of them must be different, hence they can be distinguished by one of the last m(k) rows of the above matrix.
Remark: The sequence m(n) is thus a subadditive sequence.
A simple corollary:
Corollary 2: We have m(n + 1) <= m(n) + 1, hence m(n) <= n.
Proof: Take k = 1 in Lemma 1.
Note that, from other known values of m(n) you can get better upper bounds. For example, since we know that m(4) <= 3, we have m(4n) <= 3n. Anyway, these always give you O(n) upper bounds.
The next lemma gives you a lower bound.
Lemma 3: m(n) >= n / log2(n + 1).
Proof: Let T be the set of m(n)-dimensional vectors whose entries lie in {0, 1, ..., n}. Any m(n) by n matrix M gives a map from S to T, sending v to Mv.
Since there exists an M such that the above map is injective, then necessarily the size of the set T is at least the size of the set S. The size of T is (n + 1)^m, and the size of S is 2^n, thus we have:
(n + 1)^m(n) >= 2^n
or equivalently, m(n) >= n / log2(n + 1).
Back to programming
I have to say that I haven't figured out a good algorithm.
You might restate the problem as a Set Cover Problem, as follows:
Let U be the set of n dimensional vectors with entries 1, 0 or - 1, and let S be as above. Every vector w in S gives a subset C_w of U: C_w = {v in U: <w, v> != 0}. The question is then: can we find m vectors w such that the union of the subsets C_w is equal to U.
The general Set Cover Problem is NP complete, but in the above Wiki link there is an integer linear program formulation.
Anyway, this cannot take you much further than n = 10, I guess.
I'll keep editting this answer if I have further results.
i think using Boolean matrix multiplication will allow you to solve the Mv=0 problem with only 1's & 0's more efficiently. Using this method you should be able to solve without worrying about rank deficiencies due to the RHS equaling zero. Here is a link to documentation on some algorithms for using BMM:
http://theory.stanford.edu/~virgi/cs367/lecture2.pdf
If I understand the question, you are asking for a given m,n if there exists a Matrix M, (Linear Transformation), with a trivial kernal, that is Ker(M)={0}.
Recall that this is the same as the Nullspace of M being zero 0, Null(M)=0.
For the system Mv=0 the nullspace is {0} if the rank of the matrix M is equal to the dimension of v. So your question comes down to asking about the existence of a mxn matrix with rank dim(v)=m.
The problem in this form has been discussed here
Generate "random" matrix of certain rank over a fixed set of elements
You can also frame this question in terms of determinants because if M has determinant=0 then the nullspace is nontrivial. So you can think about this question in terms of constucting a matrix with entries in {-1,0,1} with a desired determinant.
I hope this helps.

Trouble with Curry functions (SML/NJ)

Often we are interested in computing f(i) i=m n∑ , the sum of function
values f(i) for i = m through n. Define ‘sigma f m n’ which computes
f(i) i=m n∑ . This is different from defining ‘sigma (f, m, n)’
I'm required to write a Curried version of this function. I'm have a bit of trouble understanding how this would actually work. I understand that a Curry function is something that takes in a function and produces a function. Would this be an example of a curry function?
fun myCurry f x = f(x)
As far as setting up my problem, would this be an acceptable start?
fun sigma f m n =
I haven't gotten any further, because I can't really grasp what i'm being asked to do.
A curried function is not, in fact, a function that takes in a function and produces another function. That is a higher order function.
A curried function is simply one that takes more than one argument and can be partially applied by only giving it one of its arguments.
For example, with your sigma question,
fun sigma (f,m,n) = ...
is not a curried function, as it takes only one argument (the tuple (f,m,n).)
fun sigma f m n = ...
, however, is a curried function, as it takes three arguments, and it is valid to say something like
val sigmasquare = sigma (fn x => x * x)
, partially applying sigma by giving it its first argument.
A simpler example would be
fun add (x,y) = x + y
This is a noncurried function. To evaluate it, you must give it its argument, which includes both x and y. add (3,5) will evaluate to 8, in this case.
fun add x y = x + y
is the curried version of this same function. This can be partially evaluated by just giving it x. For example, add 3 will evaluate to a function which will add three to its argument.
This is more clearly seen by looking at the previous examples as anonymous or lambda functions.
The first is equivalent to fn (x,y) => x + y, which clearly takes two ints and evaluates to an int.
The second is equivalent to fn x => fn y => x + y, which takes an int and evaluates to a function taking another int and evaluating to an int.
Thus, the type of the first is (int * int) -> int, while the type of the second is int -> int -> int.
Hopefully, this clears currying up somewhat.

Resources