我的代码的最小更改将使其保持逻辑纯度?
我发布了下面的代码作为这个问题的答案和用户“重复”回答并评论,这在逻辑上不纯粹和“如果您有兴趣对代码进行最小的更改以使其保持逻辑纯度,我建议发布一个关于此的新问题,我很乐意回答:)”。
% minset_one(1 in D1, 1 in D2, D1, D2, D1Len, D2Len, T).
minset_one_(true, false, D1, _, _, _, D1).
minset_one_(false, true, _, D2, _, _, D2).
minset_one_(true, true, _, D2, D1Len, D2Len, D2) :- D1Len >= D2Len.
minset_one_(true, true, D1, _, D1Len, D2Len, D1) :- D1Len < D2Len.
minset_one(D1, D2, T) :-
(member(1, D1) -> D1check = true ; D1check = false),
(member(1, D2) -> D2check = true ; D2check = false),
length(D1, D1Len),
length(D2, D2Len),
minset_one_(D1check, D2check, D1, D2, D1Len, D2Len, T).
例如,
?- D1 = [X,Y,Z], D2 = [U,V], minset_one(D1,D2,T).
D1 = [1, Y, Z],
D2 = T, T = [1, V],
U = X, X = 1 ;
false
有更多可能的解决方案。 member(1, D1)
不会通过 [1, Y, Z]
回溯,然后通过 [X, 1, Z]
然后 [X,Y,1]
。
I posted the code below as an answer to this question and user "repeat" answered and commented that it's not logically pure and "if you are interested in a minimal change to your code that makes it preserve logical-purity, I suggest posting a new question about that. I'd be glad to answer it :)".
% minset_one(1 in D1, 1 in D2, D1, D2, D1Len, D2Len, T).
minset_one_(true, false, D1, _, _, _, D1).
minset_one_(false, true, _, D2, _, _, D2).
minset_one_(true, true, _, D2, D1Len, D2Len, D2) :- D1Len >= D2Len.
minset_one_(true, true, D1, _, D1Len, D2Len, D1) :- D1Len < D2Len.
minset_one(D1, D2, T) :-
(member(1, D1) -> D1check = true ; D1check = false),
(member(1, D2) -> D2check = true ; D2check = false),
length(D1, D1Len),
length(D2, D2Len),
minset_one_(D1check, D2check, D1, D2, D1Len, D2Len, T).
e.g.
?- D1 = [X,Y,Z], D2 = [U,V], minset_one(D1,D2,T).
D1 = [1, Y, Z],
D2 = T, T = [1, V],
U = X, X = 1 ;
false
there are more solutions possible. member(1, D1)
is not backtracking through [1, Y, Z]
, then [X, 1, Z]
then [X, Y, 1]
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
( - &gt;)/2
(和朋友)的问题考虑以下目标:
( - &gt;)/2
承诺成员的第一个答案(1,D1)
- 其他答案被忽略了。可以替代
( - &gt;)/2
- 例如(* - &gt;)/2
(swi,gnu)或if/3
(sicstus) - 在这里送我们吗?no 。这些 do 不忽略
成员(1,d1)
成功的替代答案,但他们不认为成员(1,d1)<的逻辑否定/code>也可以也成功了。
返回基础知识:“如果p则q else r“ =”(p∧q)∨(€p r)”
,那么让我们重写
(如果 - &gt; then; else; else)
as> (如果,则; not_if,else)
:我们应该如何实现
non_member(x,xs)
- 我们可以简单地写\++成员(x,xs)
?不!为了保留逻辑纯度,我们最好不要以“否定为有限失败”为基础。
幸运的是,结合
maplist/2
和dif/2
在此处完成工作:将所有作业放在一起,
所以我提出的最小更改:
运行示例查询我们现在得到:
更好:更好。当然,我看上去好像没有任何东西。
The Problem with
(->)/2
(and friends)Consider the following goal:
(->)/2
commits to the first answer ofmember(1,D1)
—other answers are disregarded.Can alternatives to
(->)/2
—like(*->)/2
(SWI, GNU) orif/3
(SICStus)—help us here?No. These do not ignore alternative answers to make
member(1,D1)
succeed, but they do not consider that the logical negation ofmember(1,D1)
could also have succeeded.Back to basics: "If P then Q else R" ≡ "(P ∧ Q) ∨ (¬P ∧ R)"
So let's rewrite
(If -> Then ; Else)
as(If, Then ; Not_If, Else)
:How should we implement
non_member(X,Xs)
—can we simply write\+ member(X,Xs)
?No! To preserve logical purity we better not build upon "negation as finite failure".
Luckily, combining
maplist/2
anddif/2
does the job here:Putting it all together
So here's the minimum change I propose:
Running the sample query we now get:
Better. Sure looks to me like there's nothing missing.
我认为这将是:
add:
...和替换:
成员和成员d_t之间的差异的示例:
因此,成员d_t本身正在添加dif/2约束。为了稍微帮助性能,它仅循环一次。
会员d_t的定义在eg https://github.com /meditans/reif/blob/master/prolog/reif.pl.l194 和 https://www.sw.swi-prolog.org/pack/pack/file_details/reif/reif/prolog/reif/reif.pl?show=src
I think it would be:
add:
... and replace:
Example of the difference between member and memberd_t:
So, memberd_t is itself adding the dif/2 constraints. To aid performance slightly, it loops through the list only once.
The definition of memberd_t is at e.g. https://github.com/meditans/reif/blob/master/prolog/reif.pl#L194 and https://www.swi-prolog.org/pack/file_details/reif/prolog/reif.pl?show=src