Prolog - programming a board game called Adugo - matrix

In the past few days I have tried doing the game Adugo in a prolog program, but Logic programming is a bit hard for me. I'm trying do it simple as possible, the initial matrix is :
[[1,1,1,0,0,0,0],
[1,1,1,0,0,0,0],
[1,1,2,0,0,0,0],
[1,1,1,0,0,0,0],
[1,1,1,0,0,0,0]]).
1 is for the dogs
2 is the jaguar
0 is nothing
The user will only control the dogs and the jaguar will be a bot.I have done this game in C++, but in Prolog I don't know how to do.

The game is quite fun. I have not yet completed the development,
but the basic idea is to use a predicate set_arg/4 to change the board
state. A predicate arg/3 is already found in the ISO core standard, it simply picks an argument from a compound. If it were not already predefined one could bootstrap via univ (=..)/2 as follows:
arg(K, C, A) :-
C =.. [_|L],
nth1(K, L, A).
Now the predicate set_arg/3 works similarly but its aim is not to access an argument, but instead to modify an argument. But since in Prolog terms are immutable, we simply return a new modified term and thus retain declarativity. It can be bootstrapped as follows:
set_arg(K, C, A, D) :-
C =.. [F|L],
nth1(K, L, _, H),
nth1(K, R, A, H),
D =.. [F|R].
Prolog implementors will not like such a bootstrapping, the univ (=..)/2 is notoriously a predicate that slows down the Prolog interpreter. In Jekejeke Prolog we have native support for a built-in set_arg/4 which makes it less a burden for the Prolog interpreter.
With set_arg/4 we can then implement the Adugo game moves relatively simple. Here is an example move, when a Jaguar (*) eats a Dog (o) by jumping over it. The link predicate represents the board topology including "streets":
move(S, K, *, T, K-I) :-
link(K, J, M),
arg(J, S, o),
N is M+1,
link(J, I, N),
arg(I, S, +),
set_arg(J, S, +, H),
set_arg(K, H, +, L),
set_arg(I, L, *, T).
Here is a screenshot of the midst of our game development. A game session can be started by the predicate game/2. The game/2 predicate cannot yet correctly detect an end of a game. But we are working on it:
Efficiency is not so bad. Since the Prolog interpreter allows just in time multi-argument indexing the move search via the link/3 topology database is quite fast. Other areas could be maybe improved, like a counter for the dogs and some alpha/beta pruning.

Related

How to properly express inequality in prolog?

TL;DR: sibling(a,X) succeeds with the answer X = a, but sibling(a,a) fails.
I have the following Prolog file:
children(a, c).
children(a, d).
children(b, c).
children(b, d).
sibling(X, Y) :-
X \== Y, A \== B,
children(X, A), children(X, B),
children(Y, A), children(Y, B).
It seems clear enough to me, two person are siblings if their parents are the same. Also, a person is not their own sibling.
But when I tried to run some queries on GNU Prolog, I get some strange results:
| ?- sibling(a, b).
true ? a
true
true
yes
This is the intended behavior. a and b are siblings. There are three results, which is a bit weird, but I assume Prolog is binding A = c, B = d and A = d, B = c.
| ?- sibling(a, a).
no
I think this means a and a are not siblings.
| ?- sibling(a, X).
X = a ? a
X = b
X = a
X = b
X = a
X = b
X = a
X = b
(15 ms) yes
This is where I got stuck: It says X = a, which means sibling(a,a) is true, but sibling(a,a) failed in the previous query!
I feel that I'm not understanding what \== actually does in Prolog.
What is happening, and how do I fix this?
TL;DR: Use prolog-dif—or iso_dif/2 (on iso-prolog conforming systems like gnu-prolog)!
Good question, +1!
In fact, it's a question I have asked myself, and the answer has to do with logical-purity: logical purity is a central aspect of what
makes Prolog as a language so special, as it enables you to:
describe—not prescribe
write code that is relational—not just functional
think in terms of problems / solutions—not the individual steps of the search process itself
operate on a higher level—not get lost in nitty-gritty details
Unlike many other programming languages, Prolog programs have both procedural semantics (defining the execution steps and their order) and declarative semantics (allowing you to state relations that should hold and let the Prolog processor find a proper way of execution by itself).
But, beware: Prolog has some features that, when used, ruin declarative semantics. To prevent this, try to structure your application into two parts: an impure shell for dealing with side-effects (input/output) and a logically pure base which comprises pure monotonic Prolog code.
Try moving the inequality to the end of the predicate. Maybe it gives you true because it's not instantiated already.
sibling(X,Y):- children(X, A), children(X, B),
children(Y, A), children(Y, B),
X \== Y, A \== B.

How to prevent Prolog from backtracking where it shouldn't

I'm trying to solve a CSP where I need to distribute cocktails over bartenders so that each bartender has at most one cocktail and all cocktails are given a bartender. I solved it by creating a list of clpfd variables,first giving them the full domain of all bartenders and then removing all bartenders that don't know how to make that cocktail.
My code works, but there is one problem: it's too slow. If I look in the profiler, remove_domain gets called 2000 times(for the input I'm giving my program), while it's Redo statistic is >100 000.
What do I need to change in one of these functions(or both) so that prolog doesn't need to backtrack?
produce_domains(_,_,[],[]) :- !.
produce_domains(Bartenders,NBartenders,[Cocktail|Cocktails],[Var|Vars]) :-
Var in 1..NBartenders,
remove_domain(Bartenders,NBartenders,Cocktail,Var),!,
produce_domains(Bartenders,NBartenders,Cocktails,Vars),!.
remove_domain([],0,_,_) :- !.
remove_domain([Bartender|Bartenders],NBartenders,Cocktail,Var) :-
(\+ member(Cocktail,Bartender) -> Var #\= NBartenders;!),!,
NNBartenders is NBartenders - 1,
remove_domain(Bartenders,NNBartenders,Cocktail,Var),!.
I have already read this related question, but I am using the latest Windows build of SWI-Prolog(5.10.5), so that shouldn't be the problem here.
You do not need so many !/0: Prolog can often tell that your predicates are deterministic.
Let me first offer the following version of your code. It uses names that are more relational, contains no !/0 and uses higher-order predicates to make the code shorter.
:- use_module(library(clpfd)).
bartenders_cocktails_variables(Bs, Cs, Vs) :-
length(Bs, LBs),
maplist(bartenders_cocktail_variable(Bs, LBs), Cs, Vs).
bartenders_cocktail_variable(Bs, N, C, V) :-
V in 1..N,
foldl(compatible_bartender(C,V), Bs, 1, _).
compatible_bartender(C, V, Cs, N0, N1) :-
( member(C, Cs) -> true
; V #\= N0
),
N1 #= N0 + 1.
Notice that I am counting upwards instead of downwards to enumerate the bartenders (which are just lists of cocktails they are able to mix), since this seems more natural. I was also able to omit a (\+)/1 by simply switching the branches of the if-then-else.
Example query, showing that the predicate is deterministic in this use case:
?- bartenders_cocktails_variables([[a,b],[a,b],[x,y]], [x,a,b], Vars).
Vars = [3, _G1098, _G1101],
_G1098 in 1..2,
_G1101 in 1..2.
We see: Cocktail x must be mixed by the third bartender etc.
I think this part of your program may not be responsible for the slow performance you are describing. Maybe other parts of your program are (unintentionally) not deterministic? Maybe try different labeling strategies or other constraints? We may be able to help you more if you post more context.

How to call a predicate from another predicate in Prolog?

So I just started Prolog and I was wondering two things:
1) Is there built in functions (or are they all called predicates?) for simple things like max of 2 numbers, or sine of a number, etc... If so, how do I access them?
2) How can I call a predicate from another one? I wrote two predicates called car and cdr. car returns the head of a list and cdr returns the list without the head. But now I want to call car on the cdr. Here are some examples for clarification:
car([3,4,5,5], H). would return H = 3
cdr([3,4,5,5],L). would return L = [4,5,5]
and what I am asking is how can I do this:
car(cdr[3,4,5,5]))
??
As others have pointed out, the predicates in Prolog are called that for a reason: they really aren't functions. Many newcomers to Prolog start out by trying to map the functionality they know in other languages over to Prolog and it generally fails. Prolog is a very different programming tool than most other languages. So it's a bit like using a variety of hammers for a long time, then having someone hand you a wrench, and you wonder why it doesn't make a good hammer.
In Prolog, predicates are a means of declaring relations between entities. If you say foo(a, b) it means there's a relationship between a and b called foo. You've probably seen the examples: knows(joe, jim). and knows(jim, sally). And you can define a relation, like:
remotely_acquainted(X, Y) :- knows(X, Z), knows(Z, Y), \+ knows(X, Y).
Or something like that.
A predicate does not return a value. It either succeeds or it fails. If you have a sequence of predicates separated by commas (an "and" relationship) and Prolog encounters a predicate that fails, it backs up (backtracks) to the nearest prior predicate which it can make succeed again with different instantiation of its arguments and moves forward again.
Just to add a little to the confusion, there are some predicates in Prolog designed specifically for the evaluation of arithmetic expressions. These act like functions, but they are special case. For example:
X is Y / gcd(Z, 4).
Here, gcd of Z and 4 is computed an its value returned, and then Y is divided by that value and the result is instantiated into X. There are a variety of other functions as well, such as max/2, sin/1, etc. You can look them up in the documentation.
Arithmetic comparative operators function this way as well (using =:=/2, >/2, </2, etc with numeric expressions). So if you say:
X < Y + Z
The Prolog will consider numerical evaluation of these arguments and then compare them.
So having said all that, Prolog does allow embedding of term structures. You could have something like:
car(cdr([1,2,3]))
as a term. Prolog will not interpret it. Interpretation is left up to the programmer. I could then create a predicate which defines an evaluation of such terms:
car([H|_], H).
cdr([_|T], T).
proc_list(car(X), Result) :-
proc_list(X, R1),
car(R1, Result), !.
proc_list(cdr(X), Result) :-
proc_list(X, R1),
cdr(R1, Result), !.
proc_list(X, X).
The cut in the above clauses prevents backtracking to proc_list(X, X) when I don't want it.
Then:
| ?- proc_list(car(cdr([1,2,3])), R).
R = 2
yes
| ?- proc_list(car(cdr(cdr([1,2,3]))), R).
R = 3
yes
| ?-
Note this is a simple case and I may not have captured all of the subtleties of doing a proper sequence of car and cdr. It can also be made more general using =.. and call, etc, instead of discrete terms car and cdr in the parameters. For example, a slightly more general proc_list might be:
proc_list(Term, Result) :-
Term =.. [Proc, X], % Assumes terms have just one argument
member(Proc, [car, cdr]), % True only on recognized terms
proc_list(X, R1), % Recursively process embedded term
ProcCall =.. [Proc, R1, Result], % Construct a calling term with Result
call(ProcCall), !.
proc_list(X, X).
This technique of processing a term does step away from relational behavior which Prolog is best at, and leans into functional behavior, but with an understand of how Prolog works.
Prolog has a really different attitude to computing...
You don't define functions, but relations among arguments. The most similar and well known language I'm aware of is SQL. Think of predicates as tables (or stored procedures, when some computation not predefined by database engine is required).
car([H|_],H).
cdr([_|T],T).
car_of_cdr(L, Car) :- cdr(L, Cdr), car(Cdr, Car).
but since lists' syntax is a core part of the language, a better definition could be
car_of_cdr([_,X|_], X).
Anyway, I think you should spend some time on some Prolog tutorial. SO info page has much more information...
:- use_module(support).
This means the module will use predicates written in other modules.
<module_name>:<predicate_name>(<atoms / Variables>).
This way you can call a predicate in another module.

How do I define a binary operation on a set of numbers in prolog?

How do I define a binary operation on a list in prolog and then check its properties such as closure , associative, transitive , identity etc. ? I am new to prolog.. I don't know whether it is the place to ask but I tried and I didn't come across anything somewhere.
In Prolog you define predicates, i.e. relations among a symbol (called functor) and its arguments.
A predicate doesn't have a 'return value', just a 'truth value', depending of whether it can be evaluated WRT its arguments. Then your question it's not easy to answer.
Associativity, transitivity, identity, are of little help when it come down to speaking about predicates. The first and most common property we wish to evaluate is termination, because Prolog control flow it's a bit unusual and can easily lead to infinite recursion.
Anyway, the simpler binary relation on a list is member/2, that holds when its first argument it's an element of the second argument (the list).
member(X, [X|_]).
member(X, [_|T]) :- member(X,T).
I can't see any benefit in assessing that it's not associative, neither transitive (its arguments are of different types !).
Common operations like intersection, union, etc typically needs 3 arguments, where the last is the result of the operation performed between 2 lists.
Identity in Prolog (that is an implementation of first order logic) deserves a special role. Indeed, the usual programming symbol = used to assess identity, really performs a (potentially) complex operation, called unification. You can see from the (succint) documentation page that it's 'just' a matching between arbitrary terms.
You could do something like this:
% Define sets I want to try
set7([0,1,2,3,4,5,6]).
% Define operations
% Sum modulo 7
sum7(X, Y, R) :-
R is (X+Y) mod 7.
% Normal sum
nsum(X, Y, R) :-
R is X + Y.
% A given set is closed if there is not a single case which
% indicates that it is not closed
closed(S, Operator) :-
\+ n_closed(S, Operator, _), !.
% This predicate will succeed if it finds one pair of elements
% from S which, when operated upon, will give a result R which
% is outside of the set
n_closed(S, Operator, R) :-
member(X, S),
member(Y, S),
Operation =.. [Operator, X, Y, R],
Operation,
\+ member(R, S).
When you execute it, you get these results:
| ?- set7(S), closed(S, sum7).
(1 ms) yes
| ?- set7(S), closed(S, nsum).
no
I'm not convinced my closure check is optimal, but it gives some ideas for how to play with it.

Prolog: Related predicates with permuted arguments

Is there a way to declare the following in Prolog without being caught in an endless recursion?
left([X,Y], Z) :- left([Z,X], Y); left([Y,Z], X).
The semantics is that the list represents a vector given by two points and the second argument is a third point lying left of the vector.
A related question is, how one can declare the relation of "left" and "right" given by:
left([X,Y], Z) :- right([Y,X], Z).
without getting an endless recursion.
Unfortunately, you cannot do this directly in Prolog. You can express commutative relationships by introducing a predicate that enumerates the permutations for the fact, so for example:
left_of(A, B, C) :- left(A, B, C).
left_of(A, B, C) :- left(C, A, B).
left_of(A, B, C) :- left(B, C, A).
left(a, b, c).
Now the query should be
?- left_of(A, B, C).
Similarly, you should define right_of in terms of left.
Several things worth noting:
Keep the three arguments separate, as shown. It is good practice not to introduce unnecessary structures.
Prefer explicit clauses, instead of ;. It makes your code far more obvious. The ; is really easy to miss when reading the code; if you use it, put it at the beginning of the line, not in the middle somewhere or at the end
Prolog implementations that support tabling do not have this problem.

Resources