How to make a condition to end the query in prolog? - prolog

i'm new in prolog, so i have done a program which have a method to query something, but when i use it, it keeps yielding results even when it should end.
amigos(juanarjona,omarpacheco).
amigos(juanarjona,jasonancona).
amigos(juanarjona,jorgebolio).
amigos(juanarjona,gerardoadrian).
amigos(Amigo,Amigoslista):-!,amigos(Amigoslista,Amigo).
for example, when i execute
amigos(X,juanarjona).
it should give me just this answers:
X = omarpacheco ; X = jasonancona ; X = jorgebolio ; X = gerardoadrian
;
but what it really do is to repeat those answers without end like this
X = omarpacheco ; X = jasonancona ; X = jorgebolio ; X = gerardoadrian
; X = omarpacheco ; X = jasonancona ; X = jorgebolio ; X =
gerardoadrian . . . . . . . . . . . . (repeating)...........
so, that's why i'm recurring to you guys, i need to know how to establish a condition which do not let repeating the answers.
Sorry for my bad english by the way.
I Forgot to say that it must be with just one predicate in this case "amigos"

It's easy: Use two predicates instead of one!
The first predicate comprises facts only:
amigos(juanarjona, omarpacheco).
amigos(juanarjona, jasonancona).
amigos(juanarjona, jorgebolio).
amigos(juanarjona, gerardoadrian).
The second one—built on top of the first one—provides the symmetric closure1:
sym_amigos(X, Y) :- amigos(X, Y).
sym_amigos(X, Y) :- amigos(Y, X).
Sample query using SICStus Prolog 4.3.2:
| ?- sym_amigos(P, Q).
P = juanarjona, Q = omarpacheco ? ;
P = juanarjona, Q = jasonancona ? ;
P = juanarjona, Q = jorgebolio ? ;
P = juanarjona, Q = gerardoadrian ? ;
P = omarpacheco, Q = juanarjona ? ;
P = jasonancona, Q = juanarjona ? ;
P = jorgebolio, Q = juanarjona ? ;
P = gerardoadrian, Q = juanarjona ? ;
no
As your fact base gets larger and larger, looking at all the concrete answers gets tiresome... So, to check if sym_amigos/2 terminates universally, we can run a query like this one:
| ?- sym_amigos(P, Q), % looking for amigos ...
false. % ... we discard every candidate solution.
no % "no" means "terminates universally"
Above query can never yield any solution—after all, it is a conjunction with the goal false/0:
It can, however, tell us if the above goal terminates universally.
If Prolog returns no—it does2—we know that sym_amigos/2 terminates universally.
Footnote 1:
meta-predicate symm/2 covers the common idiom "symmetric closure".
Footnote 2: SWI-Prolog does not reply no but false instead.

Related

Predicate arithmetic combination (only + or -) to find a result from a list of numbers

I'm trying to achieve an old exercice from my school and i can't figure it out how to solve it. Here is the result expected :
bC([1,12,34,23,11],23,Res).
Res = 1+11-12+23
So bC/3 is supposed to find every combination of addition or substract operation (the third argument) from a list of number (the first argument) to match a result (the second argument).
I can't find a way to start resolving this... If someone could give me a clue about this problem, i would really appreciate it.
UPDATE: Some elements of the list can be left out.
As a hint: you can aim to construct all expressions by exhautively searching over the expression space. Since X - (Y - Z) is just X - Y + Z, this is good news, since we can restrict us to left recursive expressions, like:
makepm([], ExpI, ExpI).
makepm([H|T], ExpI, ExpO) :-
makepm(T, +(ExpI, H), ExpO).
makepm([H|T], ExpI, ExpO) :-
makepm(T, -(ExpI, H), ExpO).
If as first element we take 1, and we inject the rest of the list in the makepm/3, we get:
?- makepm([12,34,23,11], 1, F).
F = 1+12+34+23+11 ;
F = 1+12+34+23-11 ;
F = 1+12+34-23+11 ;
F = 1+12+34-23-11 ;
F = 1+12-34+23+11 ;
F = 1+12-34+23-11 ;
F = 1+12-34-23+11 ;
F = 1+12-34-23-11 ;
F = 1-12+34+23+11 ;
F = 1-12+34+23-11 ;
F = 1-12+34-23+11 ;
F = 1-12+34-23-11 ;
F = 1-12-34+23+11 ;
F = 1-12-34+23-11 ;
F = 1-12-34-23+11 ;
F = 1-12-34-23-11.
What still needs to be done: the question is not perfectly clear about the fact if numbers can be left out, if that is the case, then you should write a predicate that first selects a subset of numbers. Then we can exhaustively enumerate all expressions which we create with makepm/3, and then we need to verify, for example with the is/2 [swi-doc] predicate that the expression sums up to the requested value. If that is the case the predicate can succeed.

How to not repeat results in prolog language

So I have this data base in my prolog program about restaurants that have a name and the people working in it and the meals it serves :
restaurant(hardees,[abo_abdo,abo_ahmad,tahseen],[grilled_chicken,jambo_beef,grilled_cheese_sandwich,roast_beef]).
restaurant(subway,[eftikar,tahseen,samer],[potato_salad,chicken_rice,jambo_beef,srevice_dish]).
restaurant(mcDonalds,[amer,zaher,maher],[service_dish,beef_stew,potato_corn,grilled_chicken,roast_beef]).
restaurant(kfc,[mufeed,mazen,izdihar,maher],[mushroom_rice,service_dish,jambo_beef]).
and I want to know if there's a meal that's present in more than one restaurant.
I have this instruction (and there should only be one parameter for this instruction) :
multi_available(X):- restaurant(Y1,_,Z1),member(X,Z1),
restaurant(Y2,_,Z2),Y1 \= Y2 ,member(X,Z2).
and it's presenting these results :
multi_available(X).
X = grilled_chicken ;
X = jambo_beef ;
X = jambo_beef ;
X = roast_beef ;
X = jambo_beef ;
X = jambo_beef ;
X = service_dish ;
X = grilled_chicken ;
X = roast_beef ;
X = service_dish ;
X = jambo_beef ;
X = jambo_beef ;
How can I have my results without the repetition.
Thanks alot
The traditional way is to use setof/3 or findall/3 and sort/2. Both however result in first computing all answers and next you have a list of answers. You can turn that again to a satisfiable goal using member/2.
SWI-Prolog offers library(solution_sequences), which provides operators that are known from SQL, such as distinct/1,2, limit/2, offset/2, etc. Using that, you simply call
?- distinct(multi_available(X)).
which ensures that variant solutions are removed, gives the first answer as it becomes available and doesn't switch between answers and lists of them so you can easily create more complex queries.

Prolog - Allowing lists L iff #L > n in setof/3

likes(russel, wittgenstein).
likes(whitehead, wittgenstein).
likes(godel, wittgenstein).
likes(hardy, ramanujan).
likes(littlewood, ramanujan).
at_least_three_fans :-
setof(X, Z^(fact(X, idol), fact(Z, idol)), admirers).
I'd like to have print only Z : Z = wittgenstein, i.e., I'd like to have only the idols that have 3 or more admirers. The output to the predicate above:
?- at_least_three_fans.
idol = wittgenstein,
admirers = [godel, russell, whitehead].
idol = ramanujan,
admirers = [littlewood, hardy].
The following occurred to me:
at_least_three([_,_|_]).
But how am I to use it?
Thank you.

Prolog findall list of predicates

I've been searching but I can't find the right answer for my question.
The problem is:
a predicate
initial_estates([rb(1,1),rb(2,2),rb(3,5)]).
I want to use findall to get me a list of all the second term of rb's.
Like in this example [1,2,5]
Anyone can help
You can use lists:member/2 to interactively find all values of the pairs rb/2 in your list:
?- initial_estates(L),member(rb(X,Y),L).
L = [rb(1,1),rb(2,2),rb(3,5)],
X = Y = 1 ? ;
L = [rb(1,1),rb(2,2),rb(3,5)],
X = Y = 2 ? ;
L = [rb(1,1),rb(2,2),rb(3,5)],
X = 3,
Y = 5 ? ;
no
And based on that findall to get all second elements (Y) in one list (Res):
?- findall(Y,(initial_estates(L),member(rb(X,Y),L)),Res).
Res = [1,2,5]
Alternatively, you could also write a predicate, say rb_2nd/2, that describes the second argument to be the second element in the pair that is the first argument:
rb_2nd(rb(X,Y),Y).
And then use apply:maplist/3 to apply that relation to the list described by initial_estates/1:
?- initial_estates(L), maplist(rb_2nd,L,Res).
L = [rb(1,1),rb(2,2),rb(3,5)],
Res = [1,2,5]
I find the latter easier to read than the query using findall/3.

all possible routes between the Entry and the Exit

i need help to solve the maze path. Thanks in advance
link(a,b).
link(b,c).
link(c,d).
link(f,c).
link(b,e).
link(d,e).
link(e,f).
Write a predicate that defines a route between any two adjacent points (X and Y for example) based on the fact that there is a link between them and a recursive predicate that covers the more general case of a route between any two non-adjacent points (X and Z for example) by establishing for a fact that there is a link between X and a third point in the maze (say Y) and a route between Y and Z.
Two special rooms – one connected to “a” and called “Entry” and another one connected to “f” and called “Exit”. Add a set of facts to reflect the two new rooms. Using the predicates from task 1, write a predicate that finds all possible routes between the Entry and the Exit and creates a list of the visited rooms. Write another predicate that displays the list in the interactive console at the end of every iteration, or in other words every time the Exit is reached. Write a test plan that shows your anticipated results and the actual results. Evaluate this solution and identify any potential problems and the situations that may cause their occurrence.
The problem with this solution is looping.If I want to link(a,f) prolog says no.Is anything wrong with my predicate.
| ?- link(a,b).
link(b,c).
link(c,d).
link(f,c).
link(b,e).
link(d,e).
link(e,f).
route(X,Y):- link(X,Y).
route(X,Y):- link(X,Z), route(Z,Y).
yes
yes
yes
yes
yes
yes
yes
! ----------------------------------------
! Error 20 : Predicate Not Defined
! Goal : route(_31102,_31104) :- link(_31102,_31104)
Aborted
| ?- link(a,f).
no
| ?- route(X,Y).
X = a ,
Y = b ;
X = b ,
Y = c ;
X = c ,
Y = d ;
X = f ,
Y = c ;
X = b ,
Y = e ;
X = d ,
Y = e ;
X = e ,
Y = f ;
X = a ,
Y = c ;
X = a ,
Y = e ;
X = a ,
Y = d
;
X = a ,
Y = d
| ?- link(X,Z).
X = a ,
Z = b
| ?-
| ?- link(X,Z).
X = a ,
Z = b ;
X = b ,
Z = c ;
X = c ,
Z = d ;
X = f ,
Z = c ;
X = b ,
Z = e ;
X = d ,
Z = e ;
X = e ,
Z = f
connected_to( A,B) :-
closure0(link, A,B).
See this question for a definition of closure0/3.
Or, to use your new name:
route(A0,A) :-
link(A0,A1),
closure0(link, A1,A).

Resources