如何在没有冗余的情况下简洁地表达不等式的析取 answers/solutions
How to express a disjunction of inequalities compactly without redundant answers/solutions
考虑一下我的尝试:
dif_to_orto(A, B, C) :-
( dif(A, B)
; dif(A, C)
).
虽然从声明的角度来看这个定义很好,但它包含许多冗余。想到:
?- dif_to_orto(A, B, C), A = 1, B = 2, C = 2.
A = 1, B = 2, C = 2
; A = 1, B = 2, C = 2. % unexpected redundant solution
甚至在这种情况下也不行:
?- dif_to_orto(A, B, C), A = 1, B = 2, C = 3.
A = 1, B = 2, C = 3
; A = 1, B = 2, C = 3. % unexpected redundant solution
至少,这是一个没有冗余的案例...
?- dif_to_orto(A, B, C), A = 1, B = 2, C = 1.
A = 1, B = 2, C = 1
; false. % unexpected inefficient leftover choicepoint
...但是有一个浪费资源的剩余选择点。
很少有这种定义有效的情况:
?- dif_to_orto(A, B, C), A = 1, B = 1, C = 2.
A = 1, B = 1, C = 2.
此外,最一般的查询会产生两个答案,这对我来说听起来效率很低:
?- dif_to_orto(A, B, C).
dif:dif(A,B)
; dif:dif(A,C).
... 这也会产生以下冗余:
?- dif_to_orto(1, B, B).
dif:dif(1,B)
; dif:dif(1,B). % unexpected redundant answer
一个dif/2
就够了!
有没有办法避免所有这些冗余和低效率?
这是一个建议。据我所知,它不会创建选择点或冗余解决方案:
dif_to_orto(A, B, C) :-
when(?=(A,B),(A==B->dif(A,C);true)),
when(?=(A,C),(A==C->dif(A,B);true)).
对于每个析取,等待直到知道它是真还是假。一旦知道,检查它的真实性,如果为假,则 post 另一个析取。
扩展 dif/2 的定义:
dif_to_orto(A, B, C):-
when((?=(A,B), ?=(A, C)), (A \== B -> true ; A \== C)).
样本运行:
?- 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, B), ?=(A, C)), (A\==B->true;A\==C)).
此解决方案首先等待 3 个变量中的 2 个具有可比性,然后如果无法确定约束是否应该成功,则添加新约束:
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) )
)
)).
样本运行:
?- 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).
撤销支票:
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)
)).
这个怎么样:
dif_to_orto(A, B, C) :-
dif(A-A, B-C).
测试用例:
?- 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).
考虑一下我的尝试:
dif_to_orto(A, B, C) :-
( dif(A, B)
; dif(A, C)
).
虽然从声明的角度来看这个定义很好,但它包含许多冗余。想到:
?- dif_to_orto(A, B, C), A = 1, B = 2, C = 2.
A = 1, B = 2, C = 2
; A = 1, B = 2, C = 2. % unexpected redundant solution
甚至在这种情况下也不行:
?- dif_to_orto(A, B, C), A = 1, B = 2, C = 3.
A = 1, B = 2, C = 3
; A = 1, B = 2, C = 3. % unexpected redundant solution
至少,这是一个没有冗余的案例...
?- dif_to_orto(A, B, C), A = 1, B = 2, C = 1.
A = 1, B = 2, C = 1
; false. % unexpected inefficient leftover choicepoint
...但是有一个浪费资源的剩余选择点。
很少有这种定义有效的情况:
?- dif_to_orto(A, B, C), A = 1, B = 1, C = 2.
A = 1, B = 1, C = 2.
此外,最一般的查询会产生两个答案,这对我来说听起来效率很低:
?- dif_to_orto(A, B, C).
dif:dif(A,B)
; dif:dif(A,C).
... 这也会产生以下冗余:
?- dif_to_orto(1, B, B).
dif:dif(1,B)
; dif:dif(1,B). % unexpected redundant answer
一个dif/2
就够了!
有没有办法避免所有这些冗余和低效率?
这是一个建议。据我所知,它不会创建选择点或冗余解决方案:
dif_to_orto(A, B, C) :-
when(?=(A,B),(A==B->dif(A,C);true)),
when(?=(A,C),(A==C->dif(A,B);true)).
对于每个析取,等待直到知道它是真还是假。一旦知道,检查它的真实性,如果为假,则 post 另一个析取。
扩展 dif/2 的定义:
dif_to_orto(A, B, C):-
when((?=(A,B), ?=(A, C)), (A \== B -> true ; A \== C)).
样本运行:
?- 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, B), ?=(A, C)), (A\==B->true;A\==C)).
此解决方案首先等待 3 个变量中的 2 个具有可比性,然后如果无法确定约束是否应该成功,则添加新约束:
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) )
)
)).
样本运行:
?- 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).
撤销支票:
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)
)).
这个怎么样:
dif_to_orto(A, B, C) :-
dif(A-A, B-C).
测试用例:
?- 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).