Obliged to use Constraints in Prolog - prolog

I'm currently trying to solve this puzzle houses using only constraints provided by the clpfd prolog library, which means I cannot use backtracking!
Basically I want to find out which pairs of houses should be made in order to only have 2 distances between all the connections.
My input is a list of coordinates like this [[0,0],[0,3],[2,0],[3,0],[2,1],[3,1],[2,2],[3,3]] And a solution for it would be:
[
[[0,0],[0,3]],
[[2,0],[3,1]],
[[2,1],[3,0]],
[[2,2],[3,3]]
]
My current progress is this one:
connect(Houses):-
%There are only 2 distances and they're different
length(Distances, 2),
all_distinct(Distances),
%One connection per 2 houses (pairs) means half the number of houses as connections
length(Houses, NHouses),
NConnections #= NHouses // 2,
length(Connections, NConnections),
restrictDistances(Connections, Distances), %restrict every connection to have one of the two distances
%All the houses must be connected
append(Connections, ConnectedHouses),
ensureAllConnected(Houses, ConnectedHouses), %table
removeSymmetries(Connections), %avoid symmetries
%flatten list and labeling
append(ConnectedHouses, HousesCoordinates),
labeling([], HousesCoordinates),
write(Connections).
/*
All distances of all connections are one of the two distances
Distance is kept squared to keep it an integer i.e. dist(connection) = dist([[x1, y1], [x2, y2]]) = (x2-x1)^2 + (y2-y1)^2
*/
restrictDistances([], _).
restrictDistances([[[X1, Y1], [X2, Y2]]|Connections], Distances):-
DiffX #= X2 - X1,
DiffY #= Y2 - Y1,
Dis #= DiffX * DiffX + DiffY * DiffY,
% element(Idx, Distances, Dis), %element
member(Dis, Distances), %element
restrictDistances(Connections, Distances).
/*
Ensures all houses are connected
*/
ensureAllConnected([], _).
ensureAllConnected([H|Houses], ConnectedHouses):-
member(H, ConnectedHouses),
% element(_, ConnectedHouses, H),
ensureAllConnected(Houses, ConnectedHouses).
/*
Remove symmetries and connection permutations in final result
*/
removeSymmetries([_]).
removeSymmetries([[[X1, _], [X2, _]], [[X3, Y3], [X4, Y4]]|Connections]):-
X1 #=< X2,
X1 #=< X3,
X3 #=< X4,
removeSymmetries([[[X3, Y3], [X4, Y4]]|Connections]).
The worst part is that this code works, however the predicate member cannot be used because it uses backtracking... And yes, the predicate element exists, but I am unable to replace with it because if I replace first one the output is different, and if I replace the second one I get an instantiation error.

Strictly speaking, the problem is underspecified, because there are more than one kind of distance, e.g. Euclidean distance and Hamiltonian distance. Apparently, Euclidean distances are intended, otherwise you get multiple solutions for this instance.
For this puzzle, it is useful to think about what subtasks might be encoded with global constraints. Here are some hints:
You need to find a matching - that can be encoded with
assignment(Xs,Xs).
You can use table/2 to encode the (house,house,distance) relation.
You can use nvalue/2 to constrain
the number of distinct distances.
These are global constraints in SICStus Prolog.

Related

Pythagorean theorem for calculating distance between two points. Prolog

We all know that the Pythagorean theorem formula is: a2 + b2 = c2. I wanted to implement this formula, for calculating the distance between two points. This is my data of the coordinates of the cities (in km):
city(amsterdam, 121.813/487.362).
city(breda, 112.095/398.291).
city(eindhoven, 161.871/382.839).
city(groningen, 233.871/582.030).
city(haarlem, 103.690/488.416).
city(hertogenbosch, 149.225/412.119).
city(leeuwarden, 182.605/583.855).
city(maastricht, 176.830/318.793).
city(rotterdam, 92.548/437.734).
city(utrecht, 135.923/456.419).
city(zwolle, 203.252/503.130).
I implemented a program for this cause, but it doesn't seem to work:
estimate(State/NextState, Estimate) :-
city(State, X/Y),
city(NextState, X1/Y1),
X2 is X1 - X,
Y2 is Y1 - Y,
Estimate is X2^2 + Y2^2,
DifferentVar is sqrt(Estimate),
estimate(State/NextState, DifferentVar).
If a query something like this it returns false:
?- estimate(amsterdam/utrecht, X).
false.
?- estimate(utrecht/amsterdam, X).
false.
I also tried this, but it doesn't work:
estimate(State/NextState, Estimate) :-
city(State, X/Y),
city(NextState, X1/Y1),
Estimate is sqrt((X1 - X)^2 + sqrt(Y1 - Y)^2).
I have checked each 'subgoal' and I can't find the mistake or the wrong implementation. In my eyes it seems to me that each 'subgoal' has been reached, but it still returns false. I would really appreciate it if somebody could help me further!
The estimation rule should be:
estimate(State/NextState, Estimate) :-
city(State, X/Y),
city(NextState, X1/Y1),
X2 is X1 - X,
Y2 is Y1 - Y,
Estimate is sqrt(X2^2 + Y2^2).
Note that only the last line changed (and the next 2 lines were deleted).

Sliding tile puzzle with varying tile size using logic programming

So I am trying to solve this Booth arrangement problem given here. It is basically a sliding tile puzzle where one (booth)tile has to reach a target spot and in the end all other (booths)tiles should be in their original location. Each tile/booth has a dimension and following are the input fact and relation descriptions:
One fact of the form room(W,H), which specifies the width W and
height H of the room (3 ≤ W, H ≤ 20).
One fact booths(B), which
specifies the number of booths (1 ≤ B ≤ 20).
A relation that consists
of facts of the form dimension(B, W, H), which specifies the width W
and height H of booth B.
A relation consisting of facts of the form
position(B, W, H), specifying the initial position (W, H) of booth B.
One fact target(B, W, H), specifying the destination (W, H) of the
target booth B.
An additional fact horizon(H) gives an upper bound on
the number of moves to be performed.
The program is supposed to read input facts from a file but I am just trying to do the solving so I have just copy pasted one possible input for now, and I have written some basic clauses:
room(3, 3).
booths(3).
dimension(1, 2, 1).
dimension(2, 2, 1).
dimension(3, 1, 1).
position(1, 0, 1).
position(2, 1, 2).
position(3, 0, 0).
target(3, 0, 2).
horizon(10).
xlim(X) :- room(X,_).
ylim(X) :- room(_,X).
sum(X,Y,Z) :- Z is X+Y .
do(position(B,X,Y),movedown,position(B,X,Z)) :- Y > 0 , sum(Y,-1,Z) .
do(position(B,X,Y),moveup,position(B,X,Z)) :- ylim(L), Y < L , sum(Y,1,Z) .
do(position(B,X,Y),moveleft,position(B,Z,Y)) :- X > 0 , sum(X,-1,Z) .
do(position(B,X,Y),moveright,position(B,Z,Y)) :- xlim(L), X < L, sum(X,1,Z) .
noverlap(B1,B2) :-
position(B1,X1,Y1),
position(B2,X2,Y2),
ends(Xe1,Ye1,B1),
ends(Xe2,Ye2,B2),
( Xe1 < X2 ;
Xe2 < X1 ;
Ye1 < Y2 ;
Ye2 < Y1 ).
ends(Xe,Ye,B) :-
dimension(B,W,H),
position(B,X,Y),
Xe is X+W-1,
Ye is Y+H-1.
between(X,Y,Z) :-
X > Y ,
X < Z .
validMove(M,B) :- do(position(B,X,Y),M,position(B,Xn,Yn)) .
I am new to Prolog and I am stuck on how to go from here, I have the no_overlap rule so I can test if a move is valid or not but I am not sure how with the current clauses that I have. My current clauses for moves do/3 probably needs some modification. Any pointers?.
You need to express the task in terms of relations between states of the puzzle. Your current clauses determine the validity of a single move, and can also generate possible moves.
However, that is not sufficient: You need to express more than just a single move and its effect on a single tile. You need to encode, in some way, the state of the whole puzzle, and also encode how a single move changes the state of the whole task.
For a start, I recommend you think about a relation like:
world0_move_world(W0, M, W) :- ...
and express the relation between a given "world" W0, a possible move M, and the resulting world W. This relation should be so general as to generate, on backtracking, each move M that is possible in W0. Ideally, it should even work if W0 is a free variable, and for this you may find clpfd useful: Constraints allow you to express arithmetic relations in a much more general way than you are currently using.
Once you have such a relation, the whole task is to find a sequence Ms of moves such that any initial world W0 is transformed to a desired state W.
Assuming you have implemented world0_move_world/3 as a building block, you can easily lift this to lists of moves as follows (using dcg):
moves(W0) --> { desired_world(W0) }.
moves(W0) --> [M], { world0_move_world(W0, M, W) }, moves(W).
You can then use iterative deepening to find a shortest sequence of moves that solves the puzzle:
?- length(Ms, _), initial_world(W0), phrase(moves(W0), Ms).

for-loop in prolog doesn't work

I'm trying to do a for loop in Prolog which doesn't work. The program should do following:
generate(N,[S,E],FinalSegments):-
segments([S,E],Initialsegments),
iterate_level(N,Initialsegments,FinalSegments).
When I'm calling generate(5,[(10,0),(-10,0)]) the first step is, that generate(5,[(10,0),(-10,0)],FinalSegments) is being called and this predicate generates 4 coordinates between the Startpoint (10,0) and the Endpoint (-10,0), and store those four ccordinates in the listFinalSegments. This is actually done correctly. In the next step the predicate iterate_level(N,Initialsegments,FinalSegments) is being called.
The predicate iterate_level(), takes the four coordinates from the last step as a list called Initialsegments:
Initialsegments:([[ (10, 0), (3.333333333333333, 0)],
[ (3.3333, 0), (-3.5527e-15, -5.7735)],
[ (-3.5527e-15, -5.77350), (-3.3333, 0)],
[(-3.3333, 0), (-10, 0)]])
And now iterate_level(5,Initialsegments,FinalSegments) should be a for-loop which should generate 16 coordinates after the first iteration, then 64 coordinates after the second iteration...
But here is my problem that this is not really working and I don't know what I'm still doing wrong.
It seem to me, when I'm looking at the trace, that
iterate_level(N,Ls,F):-
seq(0,N,Index),
next_level_segments(Index,Ls,F).
when next_level_segments(Index,Ls,F) is called within the for-loop, the list
Ls which should contain four times more coordinates after each iteration is not refreshed.(Maybe this is the problem).
When I call generate(3,[[(60,0),(-60,0)]],X). I get four times always the same 16 coordinates as a result but I should get 1024 different coordinates.
Maybe someone may have some time to have a look at this problem an give me some help.
Thanks
This is my implementation until now:
generate(N,[S,E],FinalSegments):-
segments([S,E],Initialsegments),
iterate_level(N,Initialsegments,FinalSegments).
generate(N,[],[]).
seq(From,_,From).
seq(From,To,X) :-
From<To,
Next is From+1,
seq(Next,To,X).
iterate_level(N,Ls,F):-
seq(0,N,Index),
next_level_segments(Index,Ls,F).
%fail.
iterate_level(Ls,F).
iterate_level([],[]).
segments([(Sx,Sy),(Ex,Ey)],Ls):-
X2 is Sx+(Ex-Sx)/3,
Y2 is Sy+(Ey-Sy)/3,
R1 is sqrt((X2-Sx)*(X2-Sx)+(Y2-Ey)*(Y2-Ey)),
Phi1 is atan((Y2-Sy)/(X2-Sx)),
X3 is X2 +R1*cos((Phi1-240)*pi/180),
Y3 is Y2 +R1*sin((Phi1+240)*pi/180),
X4 is X2+(X2-Sx),
Y4 is Y2+(Y2-Sy),
Ls=[
[(Sx,Sy),(X2,Y2)],
[(X2,Y2),(X3,Y3)],
[(X3,Y3),(X4,Y4)],
[(X4,Y4),(Ex,Ey)]
].
next_level_segments(N,[[(Sx,Sy),(Ex,Ey)]|E],[X|RLs]):-
segments([(Sx,Sy),(Ex,Ey)],X),
next_level_segments(N,E,RLs).
next_level_segments(N,[],[]).
So, first of all, Prolog doesn't do for-loops in the traditional sense - what you actually want to do is recurse over the list with an accumulator. This can be achieved as follows.
Firstly, generate(0, [[X|Y]|Z], [[X|Y]|Z]) :- !., which says "if I am trying to generate the 0th iteration of a list of lists, I have achieved my goal and I should succeed". This also cuts, as there is only ever going to be a single solution here.
generate(N, [[P1, P2]|Tail], Final) does the main body of the (outer) recursion. As long as this is a positive iteration (ie exclude negatives), we do_generate an iteration of coordinates, and recurse for another iteration (with iteration 0 succeeding as above).
do_generate([],[]). states that if we're trying to generate coordinates between an empty list, we're done for this level.
do_generate([Current|Rest], Interim) takes the first pair of coordinates and generates the set of four pairs of coordinates (using segments([(Sx,Sy),(Ex,Ey)],Ls) as before), then recurses onto the rest of the list of coordinates. Once we reach the above base-case, we append all the lists together from last to first to get the new set of coordinates. This is then unified with Interim, to send back to generate(N, [[P1, P2]|Tail], Final) for further recursion or unification with Final using the outer base-case.
As a caveat, in order to get output looking like input for the final base-case, the input is now required to be a list of lists of coordinate-pairs, not just a list of coordinate-pairs.
All put together, you get the following:
generate(0, [[X|Y]|Z], [[X|Y]|Z]) :- !.
generate(N, [[P1, P2]|Tail], Final) :-
N > 0,
do_generate([[P1, P2]|Tail], Interim),
N1 is N-1,
generate(N1, Interim, Final).
do_generate([], []).
do_generate([Current|Rest], Interim) :-
segments(Current, Segs),
do_generate(Rest, RestSegs),
append(Segs, RestSegs, Interim).
segments([(Sx,Sy), (Ex,Ey)], Ls) :-
X2 is Sx+(Ex-Sx)/3,
Y2 is Sy+(Ey-Sy)/3,
R1 is sqrt((X2-Sx)*(X2-Sx)+(Y2-Ey)*(Y2-Ey)),
Phi1 is atan((Y2-Sy)/(X2-Sx)),
X3 is X2+R1*cos((Phi1-240)*pi/180),
Y3 is Y2+R1*sin((Phi1+240)*pi/180),
X4 is X2+(X2-Sx),
Y4 is Y2+(Y2-Sy),
Ls=[[(Sx,Sy),(X2,Y2)],
[(X2,Y2),(X3,Y3)],
[(X3,Y3),(X4,Y4)],
[(X4,Y4),(Ex,Ey)]].

Trouble displaying constraint values - SICStus clpfd

I am trying to solve a problem for a class that consists of this:
Fill the white cells on the each barrels side with different digits from 1 to 6. Digits cannot
repeat in every horizontal and vertical directions. Each number on the barrels top must
be equal to the sum or product of the four different digits in the barrel. All top numbers
are different and less than 91.
I can achieve the results fine, but I need to display the barrel's results and when I run my base case it shows this:
[_24087,18,60,17,_24343,72,_24471,_24535,14]
[1,2,3,4,5,6,3,4,5,6,1,2,2,5,1,3,6,4,4,6,2,5,3,1,5,1,6,2,4,3,6,3,4,1,2,5]
Result achieved in 0.015 sec.
Resumptions: 6197
Entailments: 1306
Prunings: 3520
Backtracks: 62
Constraints created: 107
The 1st list is the barrels and the 2nd list the Matrix calculated with labeling.
In order to calculate the barrels I use this on a rule:
getlist(Matrix,CounterX,CounterY,InnerSize,Value), % gets the barrel sublist
all_distinct(Value),
sum(Value, #=, SSet), % sum
prod(Value, VSet), % product
Set #= SSet #\/ Set #= VSet, % chooses one
Set #=< MaxValue,
insertinto(Set, List, NewList), % inserts into the barrel list
Since SICStus doesn't have a product calculation rule, I created this one:
prod([H|T], R) :-
prod(T, H, R).
prod([], R, R).
prod([H|T], V, R) :-
NV #= H * V,
prod(T, NV, R).
I don't understand where the problem actually lies.
In my prod rule -> It seems to unify correctly but seems not to when 1 is in the sublist.
How I unify the sum or prod -> Maybe that barrel can be a sum or prod and can't unify with Set correctly.

How I can add all the data in a knowledge base in Prolog?

I need help with this exercise of Prolog:
% items
items (cell).
items (labial).
items (control).
items (mirror).
% Weight of each item
weight (cell 2).
weight (labial, 3).
weight (control, 5).
weight (mirror, 10).
capacity (X, Y, Z, V) :-
weight (X C1), weight (Y, C2), weight (Z, C3), sum (C1, C2, C3, R), V> = R.
sum (X, Y, Z, K) :- K is X + Y + Z.
this program does is give me a combination of 3 items or less a given weight, eg capacity (X, Y, Z, 15).
result is, X: cell, Y: Lipstick, Z: mirror, X: control, Y: cell, Z: mirror. successively with all combinations where the sum of the 3 weight no higher input.
At the moment I am limited by the number of income variables manually, capacity (X, Y, Z, N. .......) I want that the combination with respect to number of items that are in the knowledge base, not manually enter the variables. How I can do that?
so would be ideal capacity (weight) and response.
the combination of items where the weight does not exceed
phone, lipstick, mirror.
control labial phone.
mirror, control, labilal .......
Sorry I do not speak English, I'm using google translator.
It looks like the structure that you are looking for is a list and you should look it up ([HD:TL] where TL is a list). The solution I provide below should show how to use lists to the desired effect although my solution allows duplicates and doesn't care about the order of the list. If this is for homework, you should be able to figure out how to fix that on your own once you know a little about lists.
Basically, the first predicate handles making long lists of items, HD is an item with weight X, and it looks for a predicate to define the tail (TL) list; the second handles the end of a list (TL is [] in the previous inductive step) and empty lists (because even empty lists need love too).
items(cell).
items(labial).
items(control).
items(mirror).
weight(cell,2).
weight(labial,3).
weight(control,5).
weight(mirror,10).
capacity(W, [HD|TL]) :- items(HD),weight(HD,X),W>0,capacity(W-X,TL).
capacity(W, []) :- W>=0.

Resources