icl_compare/3 below compares rational terms. So far, fuzzy test fails to find a counter example for transitivity. So I am posting the codes as I posted to do so.
The codes relies on ==/2 heavily, and I borrowed idea from @janW’s post using length of the initial cycle on the path of subterm series, which I saw vaguely a couple of years ago. It is appreciated if the code is tested by others. In fact, I’m in doubt.
% ?- icl_compare(C, a, b).
% ?- icl_compare(C, b, a).
% ?- X=(Y,0), Y=f(X,1), icl_compare(C, X, Y).
icl_compare(C, I, J):- icl_order(C, [0*0, I-J], []).
% icl: initial cycle length based ordering
icl_order(=, [], []):-!.
icl_order(C, [], [[_,_|Ps]|A]):-!, icl_order(C, Ps, A).
icl_order(C, [_, I-J|Ps], A):-
( I == J -> icl_order(C, Ps, A)
; \+ (compound(I), compound(J)) -> compare(C, I, J)
; compare_arity(D, I, J),
( D = (=) ->
initial_cycle_length(I-J, A, L*R, 1),
( nonvar(L), nonvar(R) ->
compare(E, L, R),
( E = (=) ->
A = [[_,_|Qs]|A0],
icl_order(C, Qs, A0)
; C = E
)
; I =.. [_|Is],
J =.. [_|Js],
zipper(Is, Js, Zip),
( var(L) -> L = 0
; true
),
( var(R) -> R = 0
; true
),
icl_order(C, Zip, [[L*R, I-J|Ps]|A])
)
; C = D
)
).
% ?- initial_cycle_length(a-b, [[0*0, a-b]], L*R, 1).
% ?- initial_cycle_length(a-b, [[0*0, a-c], [0*0, d-b]], L*R, 1).
initial_cycle_length(_, [], _, _):-!.
initial_cycle_length(_, _, L*R, _):- nonvar(L), nonvar(R), !.
initial_cycle_length(X-Y, Cs, L*R, K):-
Cs=[[L0*R0, A-B|_]|Cs0],
( nonvar(L) -> true
; L0>0 -> L = L0
; X == A -> L = K
; true
),
( nonvar(R) -> true
; R0>0 -> R = R0
; Y == B -> R = K
; true
),
K0 is K + 1,
initial_cycle_length(X-Y, Cs0, L*R, K0).
%
compare_arity(C, A, B):- functor(A, F, J),
functor(B, G, K),
compare(C, J/F, K/G).
% ?- zipper([a,b],[1,2], Z).
zipper([], [], []).
zipper([A|As], [B|Bs], [A-B|Cs]):-
zipper(As, Bs, Cs).