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