Hi, I’m a Prolog learner, so my code can not be very efficient. I’m stuck on a little problem in Prolog which seems doable. Here is the problem :
I have two basis [i0,j0,k0] and [i1,j1,k1]. Then we have an orthogonal constraint between all elements of the same basis (i0 is orthogonal to j0, j0 is orthogonal to k0, and k0 is orthogonal to i0, and the same for the vectors of the second basis).
I would like to find the set of new orthogonal constraint to add between elements of the first basis and the second one such that the two basis are aligned/equal. Then it could be interesting to find the minimal number of constraints (which seems to be 3 when you think about it).
Here is my attempt:
:- dynamic ortho_constraint/2.
basis([i0,j0,k0]).
basis([i1,j1,k1]).
ortho(X,Y) :- ortho_constraint(X,Y); ortho_constraint(Y,X).
ortho(X,Y) :- basis(B), permutation(B,[X,Y,_]).
collin(X,Y) :-
dif(X,Y), % fail fast principle
basis(B1), basis(B2), dif(B1,B2),
permutation([E1,E2,X],B1), member(Y,B2),
ortho(E1,Y), ortho(E2,Y).
equal(B1,B2) :-
B1 = B2;
length(B1,3), length(B2,3),
maplist(collin, B1, B2).
In this code I defined basis/1 the predicate to define a base. Then ortho/2 is true when it exists a base B in which X and Y are vectors, or when it exists a dynamically added ortho_constraint/2 between the two vectors.
The first problem occurs in collin/2. It’s defined on the fact that two vectors X and Y are collinear iif it exists two different basis B1=[E1,E2,X] and B2=[_,_,Y] (possibly with a permutation) such that ortho(E1,Y) and ortho(E2,Y) are true.
When I query that, with some dynamic constraints added and that I want to get all X and Y such that collin(X,Y) is true, I get :
?- asserta(ortho_constraint(i1,k0)), asserta(ortho_constraint(j1,k0)), asserta(ortho_constraint(j1,i0)), collin(X,Y), retractall(ortho_constraint(_,_)).
X = j0,
Y = j1 ;
false.
But for instance :
?- asserta(ortho_constraint(i1,k0)), asserta(ortho_constraint(j1,k0)), asserta(ortho_constraint(j1,i0)), collin(k0,k1), retractall(ortho_constraint(_,_)).
false.
?- asserta(ortho_constraint(i1,k0)), asserta(ortho_constraint(j1,k0)), asserta(ortho_constraint(j1,i0)), collin(k1,k0), retractall(ortho_constraint(_,_)).
true .
collin/2 seems to depends on the order of the arguments even if I pay attention to not impose the basis in which X and Y belong, and we are not able to query all answers since {X=k1, Y=k0} should at least appear in the answers of collin(X,Y) …
Also, collin/2 has to be true between two vectors of two different basis if the two others vectors of the two different basis are already collinear (i0 // i1 and j0 // j1 => k0 // k1), but I am not able to express this rule without falling into an infinite recursion …
Can you help me to code a better version of collin/2 ?
At this point I will also be able to simplify equal/2 as when two vectors of two basis are collinear, it implies that the third vectors of the two basis are also collinear one to another ;).
Then I would like to formulate my query to answer my problem. The goal is to generate a list L of all possible pairs X-Y such that X is a member of B1 and Y is a member of B2, and then generate a powerset P from this list. This represents all the possible constraints we have to test in our problem. Then, for a list of constraint T in the powerset P, we define the constraints which are in T and we check that the two basis are equals, just before removing the dynamically added constraints.
powerset([], []).
powerset([_|T], P) :- powerset(T,P).
powerset([H|T], [H|P]) :- powerset(T,P).
solution(T,B1,B2) :-
basis(B1), basis(B2), dif(B1,B2),
findall(PS, (setof(X-Y, (member(X,B1), member(Y,B2)), L), powerset(L,PS)), P),
member(T,P), forall(member(X-Y,T), asserta(ortho_constraint(X,Y))),
equal(B1,B2), retractall(ortho_constraint(_,_)).
If you think that my query could be expressed in a simpler/clearer way, please notice me. I have 260 results and when I order them I have :
?- setof(Len-T, (solution(T, [i0,j0,k0],[i1,j1,k1]), length(T,Len)), Z), keysort(Z, S).
S = [
1-[j0-i1],
2-[i0-i1, j0-i1],
2-[i0-j1, k0-i1],
2-[i0-k1, j0-k1],
2-[j0-i1, k0-i1],
3-[i0-i1, i0-j1, k0-i1],
3-[i0-i1, i0-k1, j0-k1],
3-[i0-i1, j0-i1, k0-i1],
[...]
So some problems with lists of size 1 and 2 which are clearly not solutions of my problem, but the rest “seems” correct …
Thanks in advance
Teusner

