Akkoy solver - prolog - prolog

i'm new to prolog and I want to solve the puzzle Akkoy with restrictions.
So far, i've been able to implement wich cells can be painted but i don't know how to force the white areas to have all the same area.
For now when solving the problem, prolog gives two answers, but I want only the first one.
Right Answer
Wrong Answer
akkoy_solver(Rows, Cols) :-
length(Rows, X),
length(Cols, Y),
make_grid(Grid, X, Y, Vars),
reset_timer,
solver(Rows, Cols, Grid),
label(Vars),
printAkkoy(Grid, Rows, Cols),
print_time,
statistics, nl.

Related

Prolog gives fail during searching for solution, when there is one

Hi guys :) I have encountered problem during programming in prolog. I have partial order defined as facts, and I have defined maximal and greatest element as predicates. We can think of partial order like greater or equal, so le(6,7) is something like 6 <= 7.
le(6,7).
le(4,4).
le(6,6).
le(5,6).
le(5,5).
le(4,5).
le(4,4).
maximal(X) :-
not((le(X,Z) , X\=Z)).
greatest(X) :-
not(le(X,_)).
minimal(X) :-
not((le(Z,X) , X\=Z)).
smallest(X) :-
not(le(_,X)).
When I have typed query like maximal(7) the prolog output is true, and when I ask prolog to find the solution like maximal(X) it gives mi fail. I am beginner prolog programmer, so sorry if the question is too trivial, but I couldn't find the solution on my own.
Prologs uses pre-defined steps to find the answer and negation is always tricky.
To make a long story short, to make the code easier to reason about most logic should be positive and negation applied to expressions where values of all variables are known.
Here is how you could make the code work.
le(6,7).
le(4,4).
le(6,6).
le(5,6).
le(5,5).
le(4,5).
le(4,4).
is_my_number(X) :- le(X, _).
is_my_number(X) :- le(_, X).
equal_or_not_le(X, Y) :- X = Y.
equal_or_not_le(X, Y) :- not(le(X, Y)).
maximal(X) :- is_my_number(X), forall(is_my_number(Y), equal_or_not_le(X, Y)).
Then query:
?- maximal(X).
X = 7 .
Good luck!

Prolog: Monkey and Banana, Two Boxes

Instructions: Modify the attached program so that in order for the monkey to reach the bananas, he has to stand on a smaller box, which he has placed on top of a bigger one. At the beginning of the program, the boxes should be in two different locations in the room. Display on the screen the activities of the monkey.
I've been reading through the textbook (Prolog Programming for Artificial Intelligence), and Prolog is definitely proving difficult to pick up. While the book goes over how to solve the problem if there is one box, it does not mention how to begin to tackle this problem if there is more than one box. Any guidance / suggestions would be greatly appreciated.
move(state(middle, onbox, middle, hasnot), grasp, state(middle, onbox, middle, has)).
move(state(Pos, onfloor, Pos, H), climb, state(Pos, onbox, Pos, H)).
move(state(P1, onfloor, P1, H), push(P1, P2), state(P2, onfloor, P2, H)).
move(state(P1, onfloor, P, H), walk(P1, P2), state(P2, onfloor, P, H)).
canget(state(_ ,_ ,_ , has)).
canget(state1) :-
move(State1, Move, State2),
canget(State2).
Question:
canget(state(atdoor, onfloor, atwindow, hasnot)). % (monkey's horizontal position, monkey's vertical position, position of the box, and whether or not the monkey has the banana).
Only thing I can think of is to add another field to every clause for the second box's position, e.g., state(horizontal pos, vertical pos, pos for box1, pos for box2, and banana status).
Your suggested solution is one way to solve this: You can indeed simply add one more argument to the term that represents the state.
However, let us aim for something more general: How would you go about this if there are not only one or two, but n boxes in the room? Further, let us suppose the boxes are of sizes S_1, ..., S_n (S_i not necessarily distinct), and can only be stacked when the box on top is smaller than the one on which it is placed.
I suggest the following representation to denote such states:
We will use a pair Pos-Size to denote the position and size of each box. This is just infix notation for the term -(Pos, Size), i.e., functor - and arity 2.
We will use a list of such pairs, i.e., [Pos1-Size1, Pos2-Size2, ..., Pos_n-Size_n] to represent all boxes.
When stacking boxes at the same position, we need to ensure that the boxes that are already located at the same position allow such stacking. I leave this is an exercise for you.
Further, canget/1 is not really that interesting, is it? What we actually care about is the list of moves that take us to the solution! Hence, we extend the predicate with one argument that actually lets us see all moves on the toplevel, and use a more speaking name to denote what we are actually describing:
moves(state(_ ,_ ,_ , has), []).
moves(State0, [Move|Moves]) :-
move(State0, Move, State),
moves(State, Moves).
Now we can use iterative deepening to find concrete solutions:
?- length(Ms, _), moves(State0, Ms).
where State0 is the initial state of the puzzle.
When you become more experienced with Prolog, you will increasingly use dcg notation to describe lists, in order to simplify the code. I leave this version here for you to study later:
moves(state(_ ,_ ,_ , has)) --> [].
moves(State0) --> [Move],
{ move(State0, Move, State) },
moves(State).
Usage example, again using iterative deepening to find a shortest solution:
?- length(Ms, _), phrase(moves(State0), Ms).
Have fun, and also try The Art of Prolog!

Write a Prolog program to model a gorilla moving across a grid

I have done very little programming in Prolog and find it quite difficult so far.
I was given the question: A gorilla moves along an 8x8 grid and can only move right or up. it has to remain within the grid and must finish at (8,8) starting at any arbitrary location.
Write a move predicate that describes all the possible moves.
My attempt:
move(X,Y,X+1,Y).
move(X,Y,X,Y+1).
Write a path predicate that uses the move predicate to determine the path thte robot shuld take.
My attempt:
path('right'):-
move(X,Y,X+1,Y).
path('up'):-
move(X,Y,X,Y+1).
Write prolog predicates that model blockages at (1,2), (4,2), and (4,1).
So far, from what I have found it seems I need to set up a list that would give all possible positions.
I have written a list of the possible positions but do not understand how to implement it:
[(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),
(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(2,8),
(3,1),(3,2),(3,3),(3,4),(3,5),(3,6),(3,7),(3,8),
(4,1),(4,2),(4,3),(4,4),(4,5),(4,6),(4,7),(4,8),
(5,1),(5,2),(5,3),(5,4),(5,5),(5,6),(5,7),(5,8),
(6,1),(6,2),(6,3),(6,4),(6,5),(6,6),(6,7),(6,8),
(7,1),(7,2),(7,3),(7,4),(7,5),(7,6),(7,7),(7,8),
(8,1),(8,2),(8,3),(8,4),(8,5),(8,6),(8,7),(8,8)]
This seems like it would be a simple program but I cannot seem to grasp the concepts or at least put them all together into a workable program.
Any help in direction would be greatly appreciated.
There are quite some issues with your code. Let's go through it one at a time.
1. Possible positions
Although your list of possible positions is OK, I wouldn't hard-code it like that. It's very easy to do a check if a position is on the grid:
grid_position(X, Y) :-
X >= 1,
X =< 8,
Y >= 1,
Y =< 8.
Do note that this can only be used to verify a given position. If you want to be able to generate all possible positions, you can use in/2 from library(clpfd).
2. Allowed positions
If there is no simple logic as above for positions that are blocked, there is no other way than to enumerate them yourself.
blocked(1, 2).
blocked(4, 2).
blocked(4, 1).
Using this, we can determine which are the allowed positions for our gorilla: any position that is on the grid, but is not blocked.
allowed_position(X, Y) :-
grid_position(X, Y),
\+blocked(X, Y).
3. move
The main problem here is that writing X+1 in the head of the clause doesn't do what you think it does. To evaluate arithmetic expressions, you need to use the is predicate.
Additionally, I would only allow a move if the next location is allowed. Since the gorilla is already at the current location, I don't include a check to see if this location is actually allowed.
move(X, Y, X2, Y) :-
X2 is X + 1,
allowed_position(X2, Y).
move(X, Y, X, Y2) :-
Y2 is Y + 1,
allowed_position(X, Y2).
4. path
Here's how I interpret the requirement: given a start position, return the list of moves used to reach the end position.
To do this, we're going to need 3 arguments: the X and Y positions, and the output. The output here will be a list of positions rather than a list of moves, I'll leave it up to you to change that if needed.
So what makes up our path? Well, first you make one move, and then you find the rest of the path from the next position.
path(X, Y, [(X,Y)|Ps]) :-
move(X, Y, X2, Y2),
path(X1, Y1, Ps).
Of course we have to make sure this ends at the target position, so for base case we can use:
path(8, 8, (8, 8)).
You may also want to verify that the initial position is an allowed position, which I have left out.
Combine everything, and you get output such as below.
?- path(5,6,L).
L = [(5,6),(6,6),(7,6),(8,6),(8,7)|(8,8)] ? ;
L = [(5,6),(6,6),(7,6),(7,7),(8,7)|(8,8)] ? ;
L = [(5,6),(6,6),(7,6),(7,7),(7,8)|(8,8)] ? ;
...
This may not be exactly what you're looking for, but I hope it helps you well on the way.
So you might want to say where you are moving while you're doing that. So I'll suggest a predicate move/3 like this:
% move(From_Position, To_Position, Direction).
move((X,Y),(X,Y1), up) :-
grid(G),
member((X,Y1),G),
Y1 is Y + 1.
move((X,Y),(X1,Y), rigth):-
grid(G),
member((X1,Y),G),
X1 is X + 1.
The grid calls are there to ensure that you'll always stay on the grid. you also could use a smarter predicate in_grid and avoid the member call (which is quite time consuming).
grid([(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),
(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(2,8),
(3,1),(3,2),(3,3),(3,4),(3,5),(3,6),(3,7),(3,8),
(4,1),(4,2),(4,3),(4,4),(4,5),(4,6),(4,7),(4,8),
(5,1),(5,2),(5,3),(5,4),(5,5),(5,6),(5,7),(5,8),
(6,1),(6,2),(6,3),(6,4),(6,5),(6,6),(6,7),(6,8),
(7,1),(7,2),(7,3),(7,4),(7,5),(7,6),(7,7),(7,8),
(8,1),(8,2),(8,3),(8,4),(8,5),(8,6),(8,7),(8,8)]).
A path should probably be a list of directions:
path((8,8), []).
path(Position, [Direction| Before]):-
\+ Position = (8,8),
move(Position, NewPosition, Direction),
path(NewPosition,Before).
To Accumulate, you can use bagof or setof
all_paths(Position,Paths):-
setof(Path,path(Position,Path),Paths).

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.

Probabilistic Clause Choice

Its been a long time since I used Prolog in earnest, but I can't find any reference to this by googling, or in the texts I have. This may be a failure of terminology, so apologies if I massacre that.
If I have a program that could have multiple solutions:
likes(mary, joe).
likes(bob, joe).
:- likes(X, joe)
Is there a simple built-in way to have the solver run matching predicates in random order, and therefore give results in a random order (or, equivalently, have the first solution be random)?
Obviously you can get as sophisticated as you like with the word random. I'm thinking of some uniform random sampling from the set of valid predicates at each step of the solver. Something more complex like a uniform random sampling over valid solutions is also fine. The issue is general.
I can probably build a program to do this, using a random number generator, and meta-programming. But I want to check if I'm missing something simple.
Linear selection of matching clauses is an important part of Prolog algorithm (or better SLD resolution) . And each match is a candidate solution. I think you cannot expect Prolog as such to randomize clauses order for you.
I would elaborate on mat' answer:
:- meta_predicate randomize_preds(0).
randomize_preds(C) :-
findall(C, retract(C), Cs),
random_permutation(Cs, Rs),
maplist(assertz, Rs).
:- dynamic likes/2.
likes(alice, joe).
likes(bob, joe).
likes(charlie, joe).
likes(dan, joe).
test:
3 ?- randomize_preds(likes(_,_)),findall(X,likes(X,joe),L).
L = [bob, alice, charlie, dan].
4 ?- randomize_preds(likes(_,_)),findall(X,likes(X,joe),L).
L = [alice, bob, dan, charlie].
Randomizing the solutions is easiest in this case, because you only have finitely many and can thus collect them easily:
?- findall(X, likes(X, joe), Ps0), random_permutation(Ps0, Ps), member(P, Ps).
This gives you all people P that like joe, one by one, in a random order.

Resources