# How to express a disjunction of inequalities compactly without redundant answers/solutions

dif_to_orto(A, B, C) :-
dif(A-A, B-C).


The test cases:

?- dif_to_orto(A, B, C), A = 1, B = 2, C = 2.
A = 1,
B = C, C = 2.

?- dif_to_orto(A, B, C), A = 1, B = 2, C = 3.
A = 1,
B = 2,
C = 3.

?- dif_to_orto(A, B, C), A = 1, B = 2, C = 1.
A = C, C = 1,
B = 2.

?- dif_to_orto(A, B, C), A = 1, B = 1, C = 2.
A = B, B = 1,
C = 2.

?- dif_to_orto(A, B, C).
dif(f(B, A), f(A, C)).

?- dif_to_orto(1, B, B).
dif(B, 1).


This solution first awaits for 2 of the 3 variables to be comparable, then if it cannot decide whether the constraint should succeed adds a new constraint:

dif_to_orto(A, B, C) :-
when((?=(A, B) ; ?=(A, C) ; ?=(B, C)),
(   ?=(A, B) ->
( A\==B ->  true ; dif(A, C) )
;
(
?=(A, C) ->
( A\==C -> true ; dif(A, B) )
;
( B\==C -> true ; dif(A, B) )
)
)).


Sample runs:

?- dif_to_orto(A, B, C), A = 1, B = 2, C = 2.
A = 1,
B = C, C = 2.

?- dif_to_orto(A, B, C), A = 1, B = 2, C = 3.
A = 1,
B = 2,
C = 3.

?- dif_to_orto(A, B, C), A = 1, B = 2, C = 1.
A = C, C = 1,
B = 2.

?- dif_to_orto(A, B, C).
when((?=(A, C);?=(B, C);?=(A, B)),  (?=(A, B)->(A\==B->true;dif(A, C));?=(A, C)->(A\==C->true;dif(A, B));B\==C->true;dif(A, B))).

?- dif_to_orto(1, 2, Z).
true.

?- dif_to_orto(1, B, B).
dif(B, 1).


Reversing the checks:

dif_to_orto(A, B, C) :-
when((?=(A, B) ; ?=(A, C) ; ?=(B, C)),
(
A==B -> dif(A, C)
;
((A==C ; B==C) -> dif(A, B) ; true)
)).


Here is one suggestion. As far as I can tell, it does not create choice points or redundant solutions:

dif_to_orto(A, B, C) :-
when(?=(A,B),(A==B->dif(A,C);true)),
when(?=(A,C),(A==C->dif(A,B);true)).


For each disjunct, wait until it is known to be true or false. Once known, check its truth and, if false, then post the other disjunct.