Related
My input is two lists being l = [x1, x2, x3,...,xn] and k = [y1, y2, y3,...,yn]
I want a y = [(x1,y1),(x2,y2),(x3,y3)...(xn,yn)] output.
How can I apply recursion to my code? I could do it for the first item with
f = \l k. (cons (pair (head l) (head k)) empty) but I don't understand exactly how do I use recursion to create the other items.
The function "head" returns the first item of a list and the function "tail" returns a list without the first item.
Naturally it depends precisely on how you've implemented tuples, lists, etc. in Lambda Calculus. But assuming standard functional cons lists, and that both lists are the same length, and that you already have defined the following helpers, some of which you have already cited:
cons -- construct a list from a node and another list
empty -- the empty list
head -- retrieve the first node value of a list
tail -- retrieve all but the first node of a list
pair -- pair values into a tuple
isEmpty -- return `true` if a list is `empty`, `false` otherwise
true -- return the first argument
false -- return the second argument
Then we can recursively zip the lists as follows:
ZIP = λlk. isEmpty l -- "if the list is empty…"
empty -- "return an empty result. Else…"
(cons -- "return a new list, containing…"
(pair (head l) (head k)) -- "the zipped heads, and…"
(ZIP (tail l) (tail k))) -- "everything else zipped."
The problem of course is that the raw lambda calculus doesn't have recursion. You cannot refer to a function name within its own definition. The answer is to use a fixed-point combinator, e.g. the famous Y combinator.
ZIP = Y (λzlk. isEmpty l empty (cons (pair (head l) (head k)) (z (tail l) (tail k)))
The definition of Y is:
Y = λf.(λx.f(x x))(λx.f(x x))
Untangling how precisely this works is an impressive bit of mental gymnastics that is not quite in scope for this question, but using it is pretty simple. In general, if you have a desired (but illegal, in raw LC) recursive definition like this:
R = λ ??? . ??? R ???
You can instead write it as the totally legal, non-recursive definition:
R = Y (λr ??? . ??? r ???)
In other words, add a new parameter to your function which stands in for your recursive function, and use Y to wire up everything for you. That Y can invent recursion from scratch is extraordinary and the reason it is so famous.
Basically, I want to be able to check to see if at least one value in a list satisfies some predicate.
What I have so far:
need(x,y).
check_list(X,[H|T]) :-
need(H,X).
And so this works fine so long as I only have one value in the list. I'm not sure how to make it check the other values. When I try and use recursion I eventually find an element that satisfies the second predicate but it then goes back up the stack which will eventually cause it to be false.How can I make it 'break' essentially?
The backtracking you are seeing during recursion is Prolog attempting to find more ways for the predicate to succeed. This is a fundamental Prolog behavior and is what makes it useful. It seeks to find all of the solutions.
In your case, you only want to confirm one solution to the problem of, An element in the list that meets a specific criterion. For this, you could use a cut:
check_list(X, [H|_]) :-
need(X, H), !. % Don't backtrack after success
check_list(X, [_|T]) :-
check_list(X, T).
Or you could use once/1 which is specifically designed to handle cases where you only want a single solution:
check_list(X, [H|_]) :-
need(X, H).
check_list(X, [_|T]) :-
check_list(X, T).
check_list_once(X, L) :- once(check_list(X, L)).
Here is an example of what you can do.
I want to check is numbers are odd.
is_even(X) :-
X mod 2 =:= 0.
check_list(L, CL) :-
include(is_even, L, CL).
with result
?- check_list([1,2,3,4,5], L).
L = [2, 4].
?- check_list([1,3,5], L).
L = [].
You can use simple recursion:
need(x,y).
check_list(X,[H|T]) :-
( need(H,X) -> true;
check_list(X,T) ).
You can see in the examples below that this definition is deterministic:
?- check_list(y,[1,2,3]).
false.
?- check_list(y,[x,2,3]).
true.
?- check_list(y,[1,2,x]).
true.
?- check_list(Y,[1,2,x]).
Y = y.
?- check_list(Y,[1,2,3]).
false.
?- check_list(Y,[1,x,3]).
Y = y.
?- check_list(Y,[1,X,3]).
Y = y,
X = x.
?- check_list(Y,[1,2,3]), Y = x.
false.
?- check_list(Y,[1,2,3]), Y = y.
false.
?- check_list(Y,[1,2,3]).
false.
?- check_list(Y,[1,2,x]), Y = y.
Y = y.
Though if you want your queries to have uninstantiated variables e.g check_list(Y,[1,2,x]). and you add another fact need(x,z). Then:
?- check_list(Y,[1,2,x]).
Y = y.
Returns only one result and not Y = z. You could use if_/3 from library reif if you want a better definition of check_list/3.
I am trying to count a whole Europe population using this fucntion:
printEuropePopulation(A) :-
country(_, X, _, _),
printEuropePopulation(A+X),
true.
printEuropePopulation(A) :- write(A).
And program gives me
Out of local stack
when I call my func
printEuropePopulation(0)
Facts looks like:
country("Slovenia",20,2009,27300).
country("Finland",338,5238,35500).
country("France",549,60876,33800).
How can I fix it? Thanks in advance.
You cannot do this with a recursive predicate I think? It is easier to collect all the facts and then find the sum.
total_population(Total) :-
findall(P, country_population(_, P), Ps),
list_sum(Ps, Total).
In your definition you are taking the area it seems, but I take the population in thousands:
country_population(C, P) :- country(C, _, P, _).
If you want to find the sum you can do a recursive predicate because now you have all the population counts (the second argument?) in a list.
list_sum([], 0).
list_sum([X|Xs], Sum) :-
list_sum(Xs, S0),
Sum is S0 + X.
Now you can query it to find the sum of the second arguments of country
?- total_population(P).
P = 68123.
But if you are using SWI-Prolog you can also use one library which is called "aggregate" because you can use it to aggregate for example the sum:
?- aggregate_all(sum(P), country(_, _, P, _), Total_population).
Total_population = 68123.
I have written the following in Prolog (I am using version 7.4.0-rc1), trying to define a predicate insertPermutation/2 which is true if and only if both arguments are lists, one a permutation of the other.
delete(X,[X|T],T). % Base case, element equals head.
delete(X,[A|B],[A|C]) :- delete(X,B,C). % And/or repeat for the tail.
insert(X,Y,Z) :- delete(X,Z,Y). % Inserting is deletion in reverse.
insertPermutation([],[]). % Base case.
insertPermutation([H|T],P) :- insertPermutation(Q,T), insert(H,Q,P). % P permutation of T, H inserted.
I have already been made aware that delete is not a good name for the above helper predicate. We are required to write these predicates, and we cannot use the built-in predicates. This is why I wrote the above code in this way, and I chose the name I did (because I first wrote it to delete an element). It is true if and only if the third argument is a list, equal to the list in the second argument with the first instance of the first argument removed.
The insertPermutation predicate recursively tests if P equals a permutation of the tail of the first list, with the head added in any position in the permutation. This way it works to the base case of both being empty lists.
However, the permutation predicate does not behave the way I want it to. For instance, to the query
?- insertPermutation([1,2,2],[1,2,3]).
Prolog does not return false, but freezes. To the query
?- insertPermutation(X,[a,b,c]).
Prolog responds with
X = [a, b, c] ;
X = [b, a, c] ;
X = [c, a, b] ;
X = [a, c, b] ;
X = [b, c, a] ;
X = [c, b, a] ;
after which it freezes again. I see these problems are related, but not how. Can someone point out what case I am missing?
Edit: Two things, this is homework, and I need to solve this problem using an insert predicate. I wrote this one.
The answer is to change the last line
% P permutation of T, H inserted.
insertPermutation([H|T],P) :-
insertPermutation(Q,T),
insert(H,Q,P).
% P permutation of T, H inserted.
insertPermutation(P,[H|T]) :-
insertPermutation(Q,T),
insert(H,Q,P).
The use cases only needed to check if the first element is a permutation of the latter, not the other way around (or vice versa). Anti-climatic, but the answer to my problem.
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.