How to access rule data in PROLOG - prolog

I have to determine whether two rectangles overlap or not, I can do this but I am struggling with figuring out how to grab my given data, and compare it to eachother to determine larger values.
%This is :what would be happening :
%separate(rectangle(0,10,10,0), rectangle(4,6,6,4))
separate(R1,R2) :-
%I Have to figure out how to take the values from R1 and R2 and compare
%them to one another.
.

It is called "pattern matching".
separated(R1, R2) :-
R1 = rectangle(A1, B1, C1, D1),
R2 = rectangle(A2, B2, C2, D2),
/* now just use your As and Bs */
and in many cases it is better to write straight away:
separated(rectangle(A1, B1, C1, D1), rectangle(A2, B2, C2, D2)) :-
/* now just use your As and Bs */

Related

Data structure traversal

Lets say I have package A version 1 and package A version 2, Will call them A1 and A2 respectively.
If I have a pool of packages: A1, A2, B1, B2, C1, C2, D1, D2
A1 depends on B1, will represent as (A1, (B1)).
Plus A1 depends on any version of package C "C1 or C2 satisfy A1", will represent as (A1, (C1, C2))
combining A1 deps together, then A1 data-structure becomes: (A1, (B1), (C1, C2))
Also B1 depends on D1: (B1, (D1))
A1 structure becomes: (A1, ((B1, (D1))), (C1, C2))
similarly A2 structure is (A2, ((B2, (D2))), (C1, C2))
My question is: How can I select best candidate of package A, where I can select based on a condition (for example, the condition is the package does not conflict with current installed packages).
by combining A1 and A2: ((A1, ((B1, (D1))), (C1, C2)), (A2, ((B2, (D2))), (C1, C2)))
How can I traverse this data structure
So start with A1, if doesn't conflict check B1, if doesn't conflict check D1, if doesn't conflict check (C1, C2), and take one only either C1 or C2.
With this I end up selecting (A1, B1, D1, C1).
In case if A1 or any of its deps did not meet the condition, (for example if B1 conflicts with installed packages), then drop A1 entirely and move to check A2. then end up with (A2, B2, D2, C1).
What kind of traversal would that be?
I have been reading about in-order, pre-order, post-order traversal, and wondering if I need to do something similar here.
Assuming you are asking traversal on a more generic problem rather than working on this instance, I don't think there exists such a traversal.
Note that in-order is only applicable to BINARY trees. Any other kind of tree does not have in-order traversal. If your generic problem has B1, B2, B3, then apparently there wouldn't be a binary tree representation.
One property about traversal, is that the tree has all the information inclusively in the itself. When you traverse over a tree you never worry about "external information". In your case, your tree is not complete in information - you need to depend on external information to see if there is a conflict. e.g. B1 is installed - this information is never in the tree.
You can use adjacency list to represent the data:
Suppose the packages are A1, A2, B1, B2, C1, C2.
And A1 depends on B1 and C2, A2 depends on B1 and C1 and C2.
The above data can be represented as
[A1] -> [B1, C2]
[A2] -> [B1, C1, C2]
Use Topological Sorting to get the order of dependencies

Prolog - create simple function

I have a function that uses 4 parameters, called tile . It is designed to work the following way :
tile(?E, ?S, ?W, ?N, ?ID)
I would like a getter function that given an ID, it returns the first 4 parameters: E, S, W and N.
I have tried something like:
coordonates(tile(E,S,W,N,L), (E,S,W,N)).
But it does not return the actual values, only true.
If I type tile(E, S, W, N, #1) in the terminal I get the desired result but I do not know what exactly is returned (a list maybe?).
Let's suppose our facts describing tile looks as follows:
tile(p1,p2,p3,p4,id1).
tile(q1,q2,q3,q4,id2).
tile(r1,r2,r3,r4,id3).
In this we have a finite number of facts. That can be checked by the most general query for tile:
?- tile(E,S,W,N,I).
E = p1,
S = p2,
W = p3,
N = p4,
I = id1 ; % <---- user input ; to continue
E = q1,
S = q2,
W = q3,
N = q4,
I = id2 ; % <---- user input ; to continue
E = r1,
S = r2,
W = r3,
N = r4,
I = id3. % <---- toplevel outputs . -- we're done
So in theory, we could define coordonates as follows:
coordonates(id1, t(p1, p2, p3, p4)).
coordonates(id2, t(q1, q2, q3, q4)).
coordonates(id3, t(r1, r2, r3, r4)).
which could be queried for id2 as follows:
?- coordonates(id2,X).
X = t(q1, q2, q3, q4).
I used the functor t to group the solution, to make clear that it is not the predicate tile we defined earlier. There's also a lot of repetition in this definition which is already a hint, that we can do better. What we are looking for is a rule which tells us how, given we have a answer for tile, we can describe coordonates. In logical terms, this is written as an implication of the form: goal1 ∧ ... ∧ goalN → head. which means "Suppose I know that goal1 to goalN is true, then I also know that head is true." In Prolog, this is written backwards:
head :-
goal1,
% ...
goalN.
Let's go back to our task: we know something about a tile and we want to describe how the projection looks like. This means, our code looks as follows:
coordonates( ... ) :-
% ...
tile(E,S,W,N,I).
The body tile(E,S,W,N,I) is the most general form we can write (see our query above) and can be read as "suppose I have any tile at coordinates E S W N with id I". Now we only need to fill in, how coordonates should look like. We know it has two arguments, because it relates the id with the four other elements. Lets give them names, say Id and Coords:
coordonates(Id, Coords) :-
% ...
tile(E,S,W,N,I).
Now we only need to find out how to relate E,S,E,N and I with Id and Coords. One is easy: Id is just I. The other one is also not too hard, we just need to group the coordinates into one term. We can pick an arbitrary one, but already above decided to take t, so we will stick with it:
coordonates(Id, Coords) :-
Id = I,
Coords = t(E,S,W,N),
tile(E,S,W,N,I).
This already works as we expect:
?- coordonates(X,Y).
X = id1,
Y = t(p1, p2, p3, p4) ;
X = id2,
Y = t(q1, q2, q3, q4) ;
X = id3,
Y = t(r1, r2, r3, r4).
Now we can make one observation: if two terms are equal, we can use one instead of the other. So instead of writing Id = I, we can just reuse Id. The same goes for Coords and t(E,S,W,N):
coordonates(I, t(E,S,W,N)) :-
tile(E,S,W,N,I).
It couldn't be much shorter :-)
You have to declare 'E, S, W and N' so that prolog can unify those parameters with the input when you make the query. Something like (In the most basic case):
tile(['cordE1','cordS1','cordW1','cordN1'],1).
tile(['cordE2','cordS2','cordW2','cordN2'],2).
tile(['cordE3','cordS3','cordW3','cordN3'],3).
Query:
?- tile(C,2).
C = [cordE2, cordS2, cordW2, cordN2].
?- tile(C,1).
C = [cordE1, cordS1, cordW1, cordN1].
?- tile(C,3).
C = [cordE3, cordS3, cordW3, cordN3].

efficient algorithm for describing this join?

I'm not sure how best to describe this without using sets:
Assume we have two distinct, finite sets A & B, and a set P which contains a subset of all the different pairs of A & B (it's a predicate join, basically).
for example:
P = { (a1, b1), (a1, b3), (a2, b1), (a2, b3), (a1, b2) }
I want to find a set C which contains contains the fewest (or close to) number of pairs (as,bs) of subsets of A & B, eg:
C = { ( {a1, a2}, {b1, b3} ), ( {a1}, {b2} ) }
such that for each (as,bs) in C, for each combination of a in as and b in bs, (a,b) is in P and each element of P appears once and only once in this 'expansion' of C.
i'm not exactly sure how to describe this, but it seems somewhat analagous to rectangle covering in computational geometry. maybe someone has seen something like this before?

Prolog - Checking 2x2 cells in a list of lists

Basically I am trying to implement a program in prolog that can solve a game called Yin Yang, independente of the size of the board.
The game is basically to paint every cell of the board of a specific color (either black or white) and all cells of same color are connected to each other, vertically or horizontally. I am representing this with a list of lists. Example initial->solution: https://i.gyazo.com/24a70d868934dfbf1540343e89d14c4b.png
However there is a rule I'm having trouble with: "No 2X2 group of cells can contain circles of a single color."
Any ideas how I can assure this doesn't happen using the clpfd library?
List representing board example:
[[0,0,0,0,0,0],
[0,0,0,1,0,0],
[0,0,1,1,2,0],
[0,2,0,0,2,2],
[1,0,2,0,1,0],
[0,1,0,0,0,1]]
I managed to do a variant of the problem :
get-elem(B, R, C, E) :- get-line(B, R, Row), get-line(Row, C, E).
get-line([R|_], 0, R).
get-line([_|A], N, R) :- get-line(A, M, R), N is M + 1.
twoXTwo(B, R, C) :- \+ (R1 is R+ 1, C1 is C+1,
get-elem(B, R, C, E1),
get-elem(B, R1, C, E2), E1 = E2,
get-elem(B, R, C1, E3), E2 = E3,
get-elem(B, R1, C1, E4), E3 = E4).
where I check the element at positions [(r+1,c), (r,c+1), (r+1,c+1)] are not the same element. I am also not sure what the numbers mean given you have either black (1) or white (0).
I solved the issue: This is the code I used for solving the problem described above.
twoByTwo([_],[_]).
twoByTwo([F1,S1|T1],[F2,S2|T2]):-
F1 + S1 + F2 + S2 #> 4,
F1 + S1 + F2 + S2 #< 8,
twoByTwo([S1|T1],[S2|T2]).
Basically twoByTwo receives a line of the board (in order) on each argument.
So basically this function is called recursively: twoByTwo(Line1,Line2), twoByTwo(Line2,Line3), etc.

Checking a square of numbers in Prolog

square([A1, A2, A3|_], [B1, B2, B3|_], [C1, C2, C3|_]):-
all_diff([A1, A2, A3, B1, B2, B3, C1, C2, C3]).
squares([[]|_]):- !.
squares([[A1,A2,A3|A4], [B1,B2,B3|B4], [C1,C2,C3|C4], [D1,D2,D3|D4], [E1,E2,E3|E4], [F1,F2,F3|F4], [G1,G2,G3|G4], [H1,H2,H3|H4], [I1,I2,I3|I4]]):-
square([[A1,A2,A3], [B1,B2,B3], [C1,C2,C3]]),
square([[D1,D2,D3], [E1,E2,E3], [F1,F2,F3]]),
square([[G1,G2,G3], [H1,H2,H3], [I1,I2,I3]]),
squares([A4, B4, C4, D4, E4, F4, G4, H4, I4]).
I'm getting a uncaught exception: error(existence_error(procedure,square/1),squares/1) - I'm new to Prolog so I'm not quite sure what this is saying (well, where it's saying it's going wrong).
This is inside a sudoku program, by the way.
squares iterates through the 3x3 squares of the sudoku puzzle starting with the top left, middle left, and bottom left - moving to the top middle, middle middle, bottom middle, and so on.
square checks the focus square - A1, A2, A3 are the first three values of the first row
B1, B2, B3 are the first three values of the second row, and so on. It assembles them into one array and checks to make sure they are all different.
on the lines
square([[A1,A2,A3], [B1,B2,B3], [C1,C2,C3]]),
square([[D1,D2,D3], [E1,E2,E3], [F1,F2,F3]]),
square([[G1,G2,G3], [H1,H2,H3], [I1,I2,I3]]),
you'll note that the type is ([[],[],[]]), however, the function, square is ([],[],[]).
Changing the lines to
square([A1,A2,A3], [B1,B2,B3], [C1,C2,C3]),
square([D1,D2,D3], [E1,E2,E3], [F1,F2,F3]),
square([G1,G2,G3], [H1,H2,H3], [I1,I2,I3]),
fixes the problem.

Resources