Why does my prolog rule get stuck in infinite recursion - recursion

My code works for its intended purpose but always gets stuck in a loop at the end giving me an error saying "Stack limit exceeded." My code is below:
byCar(auckland,hamilton).
byCar(hamilton,raglan).
byCar(valmont,saarbruecken).
byCar(valmont,metz).
byTrain(metz,frankfurt).
byTrain(saarbruecken,frankfurt).
byTrain(metz,paris).
byTrain(saarbruecken,paris).
byPlane(frankfurt,bangkok).
byPlane(frankfurt,singapore).
byPlane(paris,losAngeles).
byPlane(bangkok,auckland).
byPlane(singapore,auckland).
byPlane(losAngeles,auckland).
travel(X,Y):- byCar(X,Y).
travel(X,Y):- byTrain(X,Y).
travel(X,Y):- byPlane(X,Y).
travel(X,Y):- travel(X,Z), travel(Z,Y).

When you call something like travel(metz, To), the last clause of travel/2 will call travel(metz, Z) with a new variable Z, which can then call travel(metz, Z2) with a new variable Z2, and so on.
This problem is called "left recursion": You have a recursive call that is equivalent to the original goal all the way "to the left" (i.e., at the beginning) of a clause. The solution is to "make some progress" before a recursive call. In this case, you can travel one hop before the recursion:
step(X, Y) :-
byCar(X, Y).
step(X, Y) :-
byTrain(X, Y).
step(X, Y) :-
byPlane(X, Y).
travel(X, Y) :-
step(X, Y).
travel(X, Z) :-
step(X, Y),
travel(Y, Z).
This now terminates:
?- travel(metz, To).
To = frankfurt ;
To = paris ;
To = bangkok ;
To = singapore ;
To = auckland ;
To = hamilton ;
To = raglan ;
To = auckland ;
To = hamilton ;
To = raglan ;
To = losAngeles ;
To = auckland ;
To = hamilton ;
To = raglan ;
false.
As pointed out in a comment by false, you can use a general predicate to capture this kind of closure: Definition of Reflexive Transitive Closure. Alternatively, some Prolog systems provide a feature called "tabling" which you can use to avoid this kind of problem: https://www.swi-prolog.org/pldoc/man?section=tabling-non-termination

Related

Prolog – How to recursively generate all combinations of two lists as a two-dimensional array

I tried to generate all the combinations of the elements in two lists.
For example, List([1,2,3],[1,2,3],L). should return L = [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
This is the code I wrote:
matrix(L1, L2, M, Res).
matrix([], L2, [], []).
matrix([H1|T1], L2, M, [M|Res]):- matrix(T1, L2, M_temp, Res), combo(L2, H1, [], M).
combo ([], _, Acc, Acc) :- !.
combo ([H2|T2], H_tmp, Acc, M) :- combo (T2, H_tmp, Acc, M_tmp), M = [[H_tmp,H2]|M_tmp].
but the result is: L = [[[1,1],[1,2],[1,3]],[[2,1],[2,2],[2,3]],[[3,1],[3,2],[3,3]]]
because I add the list as element instead of append each list element to Res. No success of implementing the the append.
append([1,2,3],[1,2,3],L).
append_lst([], L2, L2).
append_lst([H|T], L2, Res) :- append_lst(T, L2, Acc), Res = [H|Acc].
I think my approach is wrong.
Could you help me, please?
Well, Prolog doesn't have arrays: it just has lists. But, assuming your have two lists/sets, say
[1,2,3]
[a,b,c]
and want to generate a list containing the Cartesian product of the two sets:
[
[1,a], [1,b], [1,c],
[2,a], [2,b], [2,c],
[3,a], [3,b], [3,c],
]
The simplest way is to use findall/3 and member/2:
matrix( Xs, Ys, M ) :- findall( [X,Y] , ( member(X,Xs), member(Y,Ys) ) , M ).
And if you wanted to roll your own, it's not much more difficult. You might notice that we're using a helper predicate with an additional argument that will give us back the unbound tail of the list we're building, which gets closed when we run out of Xs.
Here's the code:
pairs( [] , _ , [] ) . % Once we exhausted the Xs, we're done.
pairs( [X|Xs] , Ys , Ps ) :- % But if we have an X, then...
pair(X,Ys,Ps, P0 ), % - pair that X with every Y, and
pairs(Xs,Ys,P0) % - and recurse down
. % Easy!
pair( _ , [] , Ps , Ps ) . % Once we've exhausted the Ys, we're done
pair( X , [Y|Ys] , [X:Y|Ps] , P0 ) :- % Otherwise, construct the X:Y pair, and
pair(X,Ys,Ps,P0) % - recurse down.
. % Even easier!

Checking descendants of a family tree in Prolog

How can I recursively check if X is the descendent of Y, using a recursive method descendent_of? The fact base consists of males and females, and father_of/mother_of statements.
/* Facts */
male(roy).
male(lee).
...
female(joy).
female(ana).
...
/* Rules */
grandmother_of(X, Z) :-
mother_of(X, Y),
(mother_of(Y, Z);
father_of(Y, Z)).
grandfather_of(X, Z) :-
father_of(X, Y),
(mother_of(Y, Z);
father_of(Y, Z)).
parent_of(X,Y) :-
mother_of(X,Y);father_of(X,Y).
descendent_of(X,Y) :-
*/ Recursive method here */
How do I set up the stopping condition? Also, how does recursion work in prolog if functions only return boolean values?
Any comments/suggestions are greatly appreciated.
If you look at descendant_of(X,Y) it should be true if X is descendant of Y. The truth value is than reursivly defined as follows:
I do here a little trick to achieve consistency with parent_of and introduce the predicate ancestor_of/2 as
descendent_of(X,Y) :- ancestor_of(Y,X)
Know X is ancestor of Y if either
X is parent of Y or
X is parent of Z and Z is descendant of Y
(1) is the base case of the recursion and (2) is the recursive definition.
Hint: You could also redefine the recursive case as: Z is descendant of Y and X is parent of Z (Keyword tail-recursion)
I've extended your facts to give some working data.
/* Facts */
male(roy).
male(lee).
female(joy).
female(ana).
parent_of(roy,joy).
parent_of(joy,ana).
parent_of(lee,ana).
Now we can build some rules. Let's start with grand_parent_of/2.
grand_parent_of(X,Z) :-
parent_of(X,Y),
parent_of(Y,Z).
This keeps the rules for grand_father_of/2 and grand_mother_of/2 rather simple.
grand_father_of(X,Y) :-
male(X),
grand_parent_of(X,Y).
grand_mother_of(X,Y) :-
female(X),
grand_parent_of(X,Y).
Now, every predicate so far the ancestor has been on the left and the descendent on the right, so to keep consistency, let's define ancestor_of/2 first, rather than descendent_of/2.
ancestor_of(X,Y) :-
parent_of(X,Y).
ancestor_of(X,Y) :-
parent_of(X,Z),
ancestor_of(Z,Y).
Note that the second predicate is recursive.
Now we can easily define descendent_of/2 simply in terms of ancestor_of/2.
descendent_of(X,Y) :-
ancestor_of(Y,X).
Here are the results of running the following query and asking prolog to keep giving me results.
?- descendent_of(X,Y).
X = joy,
Y = roy ;
X = ana,
Y = joy ;
X = ana,
Y = lee ;
X = ana,
Y = roy ;
false.

Lenses in Prolog via DCG, possible or not?

Was playing around with lenses in Prolog. Lenses are a kind of microscope that allow to zoom into a structure and do some reads or writes in a functional fashion. Basically my point of departure was the following modelling of setters and declarative getters in Prolog:
Getter: Just a <closure>,
called as call(<closure>, X, Y),
this will retrieve the value Y from X.
Declarative Setter: The same <closure> but used with a different arity,
called as call(<closure>, X, Y, Z), this will update the X by a new value Y giving a new Z.
I quickly arrived at a definition of a lens composition operator #, which can be used to combine two lenses into a new one, just based on their closures. An example and a definition is found in the appendix. But according to this article lenses can be made to be simply compositional.
In my opinion, when something is compositional it can be easily modelled via DCG. I can do this for the getter as follows, but I did not yet figure out a way to do it for the declarative setter as well:
/* Getter composition as DCG */
#(C1, C2) -->
call(C1),
call(C2).
How would I model the setter composition in DCG? Is this possible, maybe altering the intial assumptions of how the getters and declarative setters are modelled, so that the result is simply compositional?
Best Regards
Appendix:
Here is an example of some setters and getters:
/* getter */
back(bicycle(X, _), X).
front(bicycle(_, Y), Y).
circumference(wheel(X, _), X).
spokes(wheel(_, Y), Y).
/* setter */
back(bicycle(_, Y), X, bicycle(X, Y)).
front(bicycle(X, _), Y, bicycle(X, Y)).
circumference(wheel(_, Y), X, wheel(X, Y)).
spokes(wheel(X, _), Y, wheel(X, Y)).
Here is the modelling of the lens composition:
:- op(600, xfy, #).
/* getter composition */
#(C1, C2, X, Y) :-
call(C1, X, H),
call(C2, H, Y).
/* setter composition */
#(C1, C2, X, Y, Z) :-
call(C1, X, H),
call(C2, H, Y, J),
call(C1, X, J, Z).
Here is are some example runs:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.16)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
?- call(front#spokes, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
X = 16.
6 ?- call(back#circumference, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
X = 1330.
7 ?- call(front#circumference, bicycle(wheel(1330, 12), wheel(1440, 16)), 1420, X).
X = bicycle(wheel(1330, 12), wheel(1420, 16)).
There is a solution which has a further indirection, but which has also the potential to somehow precompile access paths. We view access paths again as closures, but this time they modify continuation functions. There are two types of continuation:
Getter Continuation:
- Transforms the value before returning it.
Declarative Setter Continuation:
- Transforms the value by an additional parameter before updating it.
An access path element now transforms the two continuations, to give a new continuation. The access path element transformation is compositional, whereby the inner access elements are first applied.
Some example continuations are given in the appendix, we can then model composition of access elements via DCG as follows. Note the order in the body of the DCG, this reflects aforementioned access elements order.
/* composition */
#(C1, C2) :-
call(C2),
call(C1).
Bye
Appendix:
Here are some transformer definitions:
/* transformer construction */
back(F, back(F)).
front(F, front(F)).
circumference(F, circumference(F)).
spokes(F, spokes(F)).
/* getter transformer */
back(F, bicycle(X, _), Y) :- call(F,X,Y).
front(F, bicycle(_, X), Y) :- call(F,X,Y).
circumference(F, wheel(X, _), Y) :- call(F,X,Y).
spokes(F, wheel(_, X), Y) :- call(F,X,Y).
/* setter transformer */
back(F, bicycle(X, Y), Z, bicycle(T, Y)) :- call(F,X,Z,T).
front(F, bicycle(X, Y), Z, bicycle(X, T)) :- call(F,Y,Z,T).
circumference(F, wheel(X, Y), Z, wheel(T, Y)) :- call(F,X,Z,T).
spokes(F, wheel(X, Y), Z, wheel(X, T)) :- call(F,Y,Z,T).
Here is the lens composition and some stop transformer:
:- op(600, xfy, #).
/* composition */
#(C1, C2, F, G) :-
call(C2, F, H),
call(C1, H, G).
/* stop getter */
id(X,X).
/* stop setter */
id(_,X,X).
here are some example runs:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.14-1-ga20f192)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
?- ['lens.pro'].
?- call(front#spokes, id, F), call(F, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
F = front(spokes(id)),
X = 16.
?- call(back#circumference, id, F), call(F, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
F = back(circumference(id)),
X = 1330.
?- call(front#circumference, id, F), call(F, bicycle(wheel(1330, 12), wheel(1440, 16)), 1420, X).
F = front(circumference(id)),
X = bicycle(wheel(1330, 12), wheel(1420, 16)).

Type issues with anonymous functions in Purescript

I am working through the Purescript By Example tutorial and I am having trouble getting types to line up using a fold left as such:
smallestFile' :: [Path] -> Maybe Path
smallestFile' (x : xs) = foldl(\acc i -> smallerFile(acc i) ) Just(x) xs // Error is on this line
smallerFile :: Maybe Path -> Path -> Maybe Path
smallerFile maybeA b = do
a <- maybeA
sa <- size a
sb <- size b
if sa > sb then return(b) else return(a)
The error I am receiving is on the fold left and is
Cannot unify Prim.Function u13116 with Data.Maybe.Maybe
I believe that the types line up, but I cannot make heads or tails of this error.
Also, is it possible to clean up the anonymous function syntax so that
foldl(\acc i -> smallerFile(acc i) ) Just(x) xs
becomes something like:
foldl smallerFile Just(x) xs
In PureScript, like Haskell, function application uses whitespace, and associates to the left, which means that f x y z parses as ((f x) y) z. You only need parentheses when terms need to be regrouped. It looks like you're trying to use parentheses for function application.
I suspect what you want to write is
foldl (\acc i -> smallerFile acc i) (Just x) xs
The argument to foldl is a function which takes two arguments acc and i and returns the application smallerFile acc i. This is equivalent to the double application (smallerFile acc) i. First we apply the argument acc, then the second argument i. The precedence rule for function application in the parser makes these equivalent.
Also, Just x needs to be parenthesized because what you wrote parses as
foldl (\acc i -> smallerFile (acc i)) Just x xs
which provides too many arguments to foldl.
Once you have the correct version, you can notice that \acc i -> smallerFile acc i is equivalent to \acc -> (\i -> (smallerFile acc) i). The inner function applies its argument i immediately, so we can simplify this to \acc -> smallerFile acc. Applying this simplification a second time, we get just smallerFile, so the code becomes:
foldl smallerFile (Just x) xs
so the only mistake in the end was the incorrect bracketing of Just x.

Recursion in prolog using append

I'm new in Prolog and I have some problem understanding how the recursion works.
The think I want to do is to create a list of numbers (to later draw a graphic).
So I have this code :
nbClassTest(0, _).
nbClassTest(X, L) :-
numberTestClass(A,X),
append([A], L, L),
X is X - 1,
nbClassTest(X, L).
But it keeps giving me 'false' as an answer and I don't understand why it doesn't fill the list. It should end if X reaches 0 right?
The numberTestClass(A,X), gives me a number (in the variable A) for some X as if it was a function.
You should build the list without appending, because it's rather inefficient.
This code could do:
nbClassTest(0, []).
nbClassTest(X, [A|R]) :-
numberTestClass(A, X),
X is X - 1,
nbClassTest(X, R).
or, if your system has between/3, you can use an 'all solutions' idiom:
nbClassTest(X, L) :-
findall(A, (between(1, X, N), numberTestClass(A, X)), R),
reverse(R, L).
the problem is that you use the same variable for the old and the new list. right now your first to append/3 creates a list of infinite length consisting of elements equal to the value of A.
?-append([42],L,L).
L = [42|L].
?- append([42],L,L), [A,B,C,D|E]=L.
L = [42|L],
A = B, B = C, C = D, D = 42,
E = [42|L].
then, if the next A is not the same with the previous A it will fail.
?- append([42],L,L), append([41],L,L).
false.
there is still on more issue with the code; your base case has an non-instantiated variable. you might want that but i believe that you actually want an empty list:
nbClassTest(0, []).
nbClassTest(X, L) :-
numberTestClass(A,X),
append([A], L, NL),
X is X - 1,
nbClassTest(X, NL).
last, append/3 is kinda inefficient so you might want to avoid it and build the list the other way around (or use difference lists)
It fails because you use append in wrong way
try
nbClassTest(0, _).
nbClassTest(X, L) :-
numberTestClass(A,X),
append([A], L, Nl),
X is X - 1,
nbClassTest(X, Nl).
append concatenate 2 lists so there is no such list which after adding to it element still will be same list.

Resources