I have two predicates:
foo(Y,X)
bar(Y,Z)
After running foo, How can I run bar with all possibilities of Y ?
example:
foo(Y, key) % all possibilities of Y => chat
% faq
% about
% search
How can I run bar with these all possibilities ?
bar(chat, Z)
bar(faq, Z)
bar(about, Z)
bar(serach, Z)
And then store all the results of Z in a list Zs?
foo/2 and bar/2 are already in join, and after each run of foo/2 bar/2 will be tried.
Maybe you are looking for forall(foo(Y,X), bar(Y,Z)), that run all possibilities of foo/2, and then bar/2. I.e. is required that bar/2 doesn't fail.
To understand the behaviour of forall/2, as well as other all solutions builtins, like setof/3, can be useful test with very simple builtins, with well known behaviour:
?- forall(member(X,[f,o,o]),(member(Y,[b,a,r]),writeln(X-Y))).
f-b
o-b
o-b
true.
You can see that the complete solution search of forall applies to its first argument, not the second.
HTH
allZs(X, Zs) :-
setof(Y, foo(Y, X), Ys),
maplist(bar, Ys, Zs).
related SWI-Prolog man pages: Finding all Solutions to a Goal and library apply
Note: usually in Prolog the convention is to put intput arguments before output ones - in your first predicate that'd mean foo(X, Y) instead of foo(Y, X). Plus here it'd outline the transitivity: foo(X, Y), bar(Y, Z)..
I think you want something like this:
barOnList([], []).
barOnList([Y|Ys], [Z|Zs]) :- bar(Y, Z), barOnList(Ys, Zs).
Related
As title stated above, how to make this possible?
For example:
**Facts:**
parent(child, parent).
parent(child, parent2).
parent(child2, parent).
parent(child2, parent2).
**Rules:**
childof(X,Y) :- parent(Y, X).
number_of_child(X,Y):- X has Y number of child
How should I implement the number_of_child rules?
My expected answer is Y will show 2 (since there are child and child2) or something like that.
Thank you.
You should learn about setof/3, bagof/3 and findall/3. They are general prolog predicates to find all solutions.
If you want something swi-prolog specific just to count the solutions then you can use aggregate_all.
num_children(X, N) :- aggregate_all(count, child_of(X, _Y), N).
https://www.swi-prolog.org/FAQ/SingletonVar.html
I am working through Seven Languages in Seven Weeks, but there is something I don't understand about prolog. I have the following program (based on their wallace and grommit program):
/* teams.pl */
onTeam(a, aTeam).
onTeam(b, aTeam).
onTeam(b, superTeam).
onTeam(c, superTeam).
teamMate(X, Y) :- \+(X = Y), onTeam(X, Z), onTeam(Y, Z).
and load it like this
?- ['teams.pl'].
true.
but it doesn't give me any solutions to the following
?- teamMate(a, X).
false.
it can solve simpler stuff (which is shown in the book):
?- onTeam(b, X).
X = aTeam ;
X = superTeam.
and there are solutions:
?- teamMate(a, b).
true ;
false.
What am I missing? I have tried with both gnu prolog and swipl.
...AND THERE IS MORE...
when you move the "can't be your own teammate" restriction to then end:
/* teams.pl */
onTeam(a, aTeam).
onTeam(b, aTeam).
onTeam(b, superTeam).
onTeam(c, superTeam).
teamMate(X, Y) :- onTeam(X, Z), onTeam(Y, Z), \+(X = Y).
it gives me the solutions I would expect:
?- ['teams.pl'].
true.
?- teamMate(a, X).
X = b.
?- teamMate(b, X).
X = a ;
X = c.
What gives?
You have made a very good observation! In fact, the situation is even worse, because even the most general query fails:
?- teamMate(X, Y).
false.
Declaratively, this means "there are no solutions whatsoever", which is obviously wrong and not how we expect relations to behave: If there are solutions, then more general queries must not fail.
The reason you get this strange and logically incorrect behaviour is that (\+)/1 is only sound if its arguments are sufficiently instantiated.
To express disequality of terms in a more general way, which works correctly no matter if the arguments are instantiated or not, use dif/2, or, if your Prolog system does not provide it, the safe approximation iso_dif/2 which you can find in the prolog-dif tag.
For example, in your case (note_that_I_am_using_underscores_for_readability instead of tuckingTheNamesTogetherWhichMakesThemHarderToRead):
team_mate(X, Y) :- dif(X, Y), on_team(X, Z), on_team(Y, Z).
Your query now works exactly as expected:
?- team_mate(a, X).
X = b.
The most general query of course also works correctly:
?- team_mate(X, Y).
X = a,
Y = b ;
X = b,
Y = a ;
X = b,
Y = c ;
etc.
Thus, using dif/2 to express disequality preserves logical-purity of your relations: The system now no longer simply says false even though there are solutions. Instead, you get the answer you expect! Note that, in contrast to before, this also works no matter where you place the call!
The answer by mat gives you some high-level considerations and a solution. My answer is a more about the underlying reasons, which might or might not be interesting to you.
(By the way, while learning Prolog, I asked pretty much the same question and got a very similar answer by the same user. Great.)
The proof tree
You have a question:
Are two players team mates?
To get an answer from Prolog, you formulate a query:
?- team_mate(X, Y).
where both X and Y can be free variables or bound.
Based on your database of predicates (facts and rules), Prolog tries to find a proof and gives you solutions. Prolog searches for a proof by doing a depth-first traversal of a proof tree.
In your first implementation, \+ (X = Y) comes before anything else, so it at the root node of the tree, and will be evaluated before the following goals. And if either X or Y is a free variable, X = Y must succeed, which means that \+ (X = Y) must fail. So the query must fail.
On the other hand, if either X or Y is a free variable, dif(X, Y) will succeed, but a later attempt to unify them with each other must fail. At that point, Prolog will have to look for a proof down another branch of the proof tree, if there are any left.
(With the proof tree in mind, try to figure out a way of implementing dif/2: do you think it is possible without either a) adding some kind of state to the arguments of dif/2 or b) changing the resolution strategy?)
And finally, if you put \+ (X = Y) at the very end, and take care that both X and Y are ground by the time it is evaluated, then the unification becomes more like a simple comparison, and it can fail, so that the negation can succeed.
Consider the following:
link(step1, step2) .
link(step2, step3) .
link(step3, step4) .
goal(X) :- \+ link(X, _) .
I would like goal functor to represent a step that is not at the beginning of a link.
But when I try :
| ?- goal(X).
no
(instead of telling me that step4 is a solution)
The following, however, does evaluate to yes:
goal(step4).
I'm guessing that's because I'm asking prolog to find what it can't find (sigh…)
Any way I can do this?
The trouble comes with Prolog not knowing what your universe of valid values of X could be. In this particular example, you could do it by defining what a valid step is:
valid_step(X) :- link(X, _) ; link(_, X).
This would then help you tell goal what to choose from for the "universe of valid steps":
goal(X) :- valid_step(X), \+ link(X, _).
Yielding:
| ?- goal(X).
X = step4
yes
| ?-
Or, if more specifically, you really mean to find X which is present as a destination link but not a source link:
goal(X) :- link(_, X), \+ link(X, _).
It depends upon the big picture of what your facts are, what they mean, and what the semantics of goal really are.
Perhaps a more suitable way to define valid steps, if the link relation isn't what logically definesto what a valid step is, would be to make valid_step a set of facts, instead of the predicate I show above:
valid_step(step1).
valid_step(step2).
valid_step(step3).
valid_step(step4).
valid_step(step5).
So this is a simple, completely independent definition of what a valid step is, and can be used by other relations (predicates) that need this information.
It may be tempting to do:
valid_steps([step1,step2,step3,step4,step5]).
And then:
goal(X) :- valid_steps(Valid), member(X, Valid), \+ link(X, _).
But I believe the list of discrete facts is preferable.
How to implement rule1 that succeeds iff rule2 returns two or more results?
rule1(X) :-
rule2(X, _).
How can I count the results, and then set a minimum for when to succeed?
How can I count the results, and then set a minimum for when it's true?
It is not clear what you mean by results. So I will make some guesses. A result might be:
A solution. For example, the goal member(X,[1,2,1]) has two solutions. Not three. In this case consider using either setof/3 or a similar predicate. In any case, you should first understand setof/3 before addressing the problem you have.
An answer. The goal member(X,[1,2,1]) has three answers. The goal member(X,[Y,Z]) has two answers, but infinitely many solutions.
So if you want to ensure that there are at least a certain number of answers, define:
at_least(Goal, N) :-
\+ \+ call_nth(Goal, N).
with call_nth/2 defined in another SO-answer.
Note that the other SO-answers are not correct: They either do not terminate or produce unexpected instantiations.
you can use library(aggregate) to count solutions
:- use_module(library(aggregate)).
% it's useful to declare this for modularization
:- meta_predicate at_least(0, +).
at_least(Predicate, Minimum) :-
aggregate_all(count, Predicate, N),
N >= Minimum.
example:
?- at_least(member(_,[1,2,3]),3).
true.
?- at_least(member(_,[1,2,3]),4).
false.
edit here is a more efficient way, using SWI-Prolog facilities for global variables
at_least(P, N) :-
nb_setval(at_least, 0),
P,
nb_getval(at_least, C),
S is C + 1,
( S >= N, ! ; nb_setval(at_least, S), fail ).
with this definition, P is called just N times. (I introduce a service predicate m/2 that displays what it returns)
m(X, L) :- member(X, L), writeln(x:X).
?- at_least(m(X,[1,2,3]),2).
x:1
x:2
X = 2.
edit accounting for #false comment, I tried
?- call_nth(m(X,[1,2,3]),2).
x:1
x:2
X = 2 ;
x:3
false.
with call_nth from here.
From the practical point of view, I think nb_setval (vs nb_setarg) suffers the usual tradeoffs between global and local variables. I.e. for some task could be handly to know what's the limit hit to accept the condition. If this is not required, nb_setarg it's more clean.
Bottom line: the better way to do would clearly be using call_nth, with the 'trick' of double negation solving the undue variable instantiation.
I'm writing a text adventure game in Prolog, and I am printing out room exits. I have code that does:
exits_from(Room) :-
connected(Room, X),
write(X), write(' ').
where connected/2 is:
connected(X, Y) :- path(X, Y).
connected(X, Y) :- path(Y, X).
and path is:
path(room, hallway).
path(hallway, foyer).
and so on.
When I am printing the exits for a room though, it gets the first, then wants a ';' to say that I want another solution. Is there anyway to force a predicate to compute the result entirely, so that the player wouldn't have to keep asking for more exits?
one way is to do something like
print_all_solutions :-
solution(Sol),
write(Sol),
fail. % this causes backtracking
print_all_solutions. % succed
another is to use special predicate forall, like follows:
forall(solution(Sol), write(Sol))