I was too optimistic about the native compare/3. It has also the
mirror anomaly. I find very quickly a violation of the mirror law:
/* SWI-Prolog 9.1.7 */
?- repeat, random_cyclic(A), random_cyclic(B),
compare(X,A,B), X = (<), \+ (compare(Y,B,A), Y = (>)).
A = s(A, A),
B = s(_S1, 1), % where
_S1 = s(_S1, s(1, _S1)),
X = (<) .
Its indeed a violation of this law:
It can be reproduced on the top-level:
/* SWI-Prolog 9.1.7 */
?- A = s(A, A),
B = s(_S1, 1), % where
_S1 = s(_S1, s(1, _S1)), compare(X,A,B), compare(Y,B,A).
%%% answer
X = Y, Y = (<).
This could explain why the native compare/3 has transitivity violations?
But where does the SWI-Prolog implementation make a decision,
which violates the mirror law?
Edit 05.04.2023
Interestingly Scryer-Prolog doesn’t have the mirror anomaly. I neverthless
found somewhere a transitivity violation, but the mirror anomaly seems not
to be there. So there is no guarantee if the mirror anomaly is fixed, that
the native compare/3 works correctly. But for the mirror anomaly here the
same in Scryer Prolog, it doesn’t yield anything:
/* Scryer-Prolog 0.9.1-218 */
?- repeat, random_cyclic(A), random_cyclic(B),
compare(X,A,B), X = (<), \+ (compare(Y,B,A), Y = (>)).
%%% runs and runs and runs
Was using the below fuzzer version. This fuzzer only generates ground
cyclic terms. So the mirror law is violated by two ground terms. Couldn’t
find a violation yet in Scryer-Prolog though.
fuzzer_20230405.p.log (1,7 KB)