recursively define object positions like 'above' Prolog - recursion

I need to write a rule that recursively defines when an object is above another object, based on the objects in this picture
For example ?- above(scissors, clock). should return true
this is what I have so far
adjacent_left(clock, rocket).
adjacent_left(rocket, guitar).
adjacent_left(guitar, telephone).
on_top_of(paperclip, clock).
on_top_of(scissors, guitar).
adjacent_right(rocket, clock).
adjacent_right(guitar, rocket).
adjacent_right(telephone, guitar).
underneath(clock, paperclip).
underneath(guitar, scissors).
right_of(Obj1, Obj2):-
adjacent_right(Obj1, Obj2).
right_of(Obj1, Obj3):-
adjacent_right(Obj1, Obj2),
right_of(Obj2, Obj3).
above(Obj1, Obj2):-
on_top_of(Obj1, Obj2).
above(Obj1, Obj3):-
on_top_of(Obj1, Obj2),
above(Obj2, Obj3).

First I would define left_of/2 the same way you have defined right_of/2.
Then there are two cases in the image. The first you have: An object is above another object if it is on top of it.
The second case is object1 is above another object2 if object2 is on the same level as an object that object1 is above.
If you have more than two levels, then you need the third case which you already have: an object1 is above another object3 if object 1 is on top of an object2 that is above object3 .
There are two cases for an object to be on the same level. Either its left_of or right_of.
So:
adjacent_left(clock, rocket).
adjacent_left(rocket, guitar).
adjacent_left(guitar, telephone).
on_top_of(paperclip, clock).
on_top_of(scissors, guitar).
adjacent_right(rocket, clock).
adjacent_right(guitar, rocket).
adjacent_right(telephone, guitar).
underneath(clock, paperclip).
underneath(guitar, scissors).
right_of(Obj1, Obj2):-
adjacent_right(Obj1, Obj2).
right_of(Obj1, Obj3):-
adjacent_right(Obj1, Obj2),
right_of(Obj2, Obj3).
left_of(Obj1,Obj2):-
adjacent_left(Obj1,Obj2).
left_of(Obj1,Obj3):-
adjacent_left(Obj1,Obj2),
left_of(Obj2,Obj3).
same_level(Obj1,Obj2):-
left_of(Obj1,Obj2).
same_level(Obj1,Obj2):-
right_of(Obj1,Obj2).
above(Obj1, Obj2):-
on_top_of(Obj1, Obj2).
above(Obj1, Obj3):-
on_top_of(Obj1, Obj2),
above(Obj2, Obj3).
above(Obj1,Obj3):-
on_top_of(Obj1,Obj2),
same_level(Obj2,Obj3).
I would also recommend renaming predicates to go with the arguments. So above_below/2 instead of above/2 for example.

Firstly, it is useful to have your individual items listed in your fact database, as this allows for more straightforward construction of clauses (but this is just personal preference).
item(clock).
item(rocket).
item(guitar).
item(telephone).
item(scissors).
item(paperclip).
Then, I'd remove redundancy from some of your clauses
adjacent_left(clock, rocket).
adjacent_left(rocket, guitar).
adjacent_left(guitar, telephone).
on_top_of(paperclip, clock).
on_top_of(scissors, guitar).
adjacent_right(X, Y) :- adjacent_left(Y, X).
underneath(X, Y) :- on_top_of(Y, X).
left_of(X, Y) :- adjacent_left(X, Y), !.
left_of(X, Z) :- adjacent_left(X, Y), left_of(Y, Z).
right_of(X, Y) :- left_of(Y, X).
and define a helper predicate
siblings(X, Y) :- left_of(X, Y), !.
siblings(X, Y) :- left_of(Y, X).
Then the above relation is
above(X, Y) :- above(X, Y, []).
above(X, Y, Acc) :- on_top_of(X, Y), !.
above(X, Z, Acc) :- on_top_of(X, Y), above(Y, Z, Acc), !.
above(X, Z, Acc) :- item(Y), siblings(Y, Z), not(member(Y,Acc)), above(X, Y, [Z|Acc]), !.
The accumulator pattern is necessary to avoid a circular logic of "check if a is the sibling of b, then check if b is the sibling of a, etc etc ad infinitum).

Related

Rewriting tail recursion prolog code into simple recursion

I'm quite new in prolog and I want to practice rewriting a tail-recursion code into a simple recursion to understand better the process, but I did not succeed in it. If anybody can help with it I would really appreciate it.
Note: Converting tail-recursive (tail-call) code to non tail-recursive code is not a wise thing to normally do in Prolog. This question is only for academic purposes of learning.
The code:
some_predicate(T,1,3,0,D),
%the tail has elements with ID and Numbers like [(1,3),(2,5),(4,3)])
%in the D I count steps if different conditions are fulfilled
%I would like to write something like: some_predicate(T,1,3,D) without the Acc
some_predicate(_, _, 1, D, D):-!.
some_predicate([], _, _, D, D):-!.
some_predicate([(UP,_)|_], ID, H, D, D):-
UP >= ID + H,
!.
some_predicate([(UP,UH)|T], _, H, D, RetD):-
H > UH,
TH is H - 1,
TD is D + 1,
some_predicate(T, UP, TH, TD, RetD),
!.
some_predicate([(UP,UH)|T], _, _,D, RetD):-
TD is D + 1,
some_predicate(T, UP, UH, TD, RetD),
!.
My attempt
some_predicate(_, _, 1,0):-!.
some_predicate([], _, _,0):-!.
some_predicate([(UP,_)|_], ID, H, 0):-
UP >= ID + H,
!.
some_predicate([(UP,UH)|Er], _, H, D):-
H > UH,
some_predicate(Er, UP, TH, TD),
H is TH - 1,
D is TD + 1,
!.
some_predicate([(UP,UH)|Er], _, _,D):-
some_predicate(Er, UP, UH, TD),
D is TD + 1,
!.
A comment in the question says that you would like to rewrite the code without an accumulator, but it doesn't use an accumulator. The general schema for predicates using a list accumulator would be something like this:
foo(X, Ys) :-
foo(X, [], Ys).
foo(X, Acc, Acc) :-
bar(X).
foo(X, Acc, Ys) :-
baz(X, Y, Z),
foo(Z, [Y | Acc], Ys).
The recursive call involving the list accumulator gets a bigger list than the accumulator was before. You add something to the accumulator before you pass it to the recursive call.
Your program instead uses the common pattern of "list iteration" (comments with a better name are welcome) in Prolog which does the opposite of recursion using an accumulator:
foo([], Y) :-
bar(Y).
foo([X | Xs], Y) :-
baz(X),
foo(Xs, Y).
(This uses similar names to the predicate before, but I'm not saying that they are equivalent.)
The list constructor [_ | _] is in the head of the clause, not in a recursive call. The list in the recursive call is smaller than the list in the head. You remove something from the list before you pass the tail to the recursive call.
This is therefore not an answer your question, just a hint that you need to start from the right place: Some predicate definition that really does use an accumulator list. The simplest interesting case is probably reversing a list.

Why does my prolog rule get stuck in infinite 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

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)).

replacing elements in atoms in Prolog

I'm writing a prolog predicate which replace an element with another in a given atom. The predicate I wrote is like this:
replace_var(Expr0, Var, Val, Expr) :-
Expr0 =.. Chars,
chars_replaced(Chars, Rs),
Expr =.. Rs.
chars_replaced(Chars, Rs) :-
maplist(rep, Chars, Rs).
rep(Var,Val).
rep(C, C) :- dif(C,var).
The result I want it to return is something like:
-?replace_var(hello, l, w, X).
X = hewwo.
The problem is about the rep() predicate. I don't know how to write it or how to pass the Val and Var to the predicate.
Please give me some suggestions. Thanks!
this is wrong
Expr0 =.. Chars
you need instead
atom_chars(Expr0, Chars)
and this one really puzzle me
rep(Var,Val).
rep(C, C) :- dif(C,var).
what do you mean, specially the second one ?
anyway, the whole could be
replace_var(Expr0, Var, Val, Expr) :-
atom_chars(Expr0, Cs),
maplist(rep(Var, Val), Cs, Ts),
atom_chars(Expr, Ts).
rep(C, T, C, T).
rep(_, _, C, C).
disclaimer: untested code

Resources