我的代码的最小更改将使其保持逻辑纯度?

发布于 2025-01-19 01:31:44 字数 1176 浏览 0 评论 0原文

我发布了下面的代码作为这个问题的答案用户“重复”回答并评论,这在逻辑上不纯粹和“如果您有兴趣对代码进行最小的更改以使其保持逻辑纯度,我建议发布一个关于此的新问题,我很乐意回答:)”。

% 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

桜花祭 2025-01-26 01:31:44

( - &gt;)/2(和朋友)的问题

考虑以下目标:

(member(1,D1) -> D1check = true ; D1check = false)

( - &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)

(member(1,D1), D1check = true ; non_member(1,D1), D1check = false)

我们应该如何实现non_member(x,xs) - 我们可以简单地写\++成员(x,xs)

不!为了保留逻辑纯度,我们最好不要以“否定为有限失败”为基础。

幸运的是,结合maplist/2dif/2在此处完成工作:

non_member(X,Xs) :-
   maplist(dif(X),Xs).

将所有作业放在一起,

所以我提出的最小更改:

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.

non_member(X,Xs) :- 
   maplist(dif(X),Xs).

minset_one(D1, D2, T) :-
   (member(1,D1), D1check = true ; non_member(1,D1), D1check = false),
   (member(1,D2), D2check = true ; non_member(1,D2), 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], X = U, U = 1, D2 = T, T = [1,V]
;  D1 = [1,Y,Z], X = V, V = 1, D2 = T, T = [U,1]
;  D1 = T, T = [1,Y,Z], X = 1, D2 = [U,V], dif(U,1), dif(V,1)
;  D1 = [X,1,Z], Y = U, U = 1, D2 = T, T = [1,V]
;  D1 = [X,1,Z], Y = V, V = 1, D2 = T, T = [U,1]
;  D1 = T, T = [X,1,Z], Y = 1, D2 = [U,V], dif(U,1), dif(V,1)
;  D1 = [X,Y,1], Z = U, U = 1, D2 = T, T = [1,V]
;  D1 = [X,Y,1], Z = V, V = 1, D2 = T, T = [U,1]
;  D1 = T, T = [X,Y,1], Z = 1, D2 = [U,V], dif(U,1), dif(V,1)
;  D1 = [X,Y,Z], D2 = T, T = [1,V], U = 1, dif(X,1), dif(Y,1), dif(Z,1)
;  D1 = [X,Y,Z], D2 = T, T = [U,1], V = 1, dif(X,1), dif(Y,1), dif(Z,1)
;  false.

更好:更好。当然,我看上去好像没有任何东西。

The Problem with (->)/2 (and friends)

Consider the following goal:

(member(1,D1) -> D1check = true ; D1check = false)

(->)/2 commits to the first answer of member(1,D1)—other answers are disregarded.

Can alternatives to (->)/2—like (*->)/2 (SWI, GNU) or if/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 of member(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):

(member(1,D1), D1check = true ; non_member(1,D1), D1check = false)

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 and dif/2 does the job here:

non_member(X,Xs) :-
   maplist(dif(X),Xs).

Putting it all together

So here's the minimum change I propose:

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.

non_member(X,Xs) :- 
   maplist(dif(X),Xs).

minset_one(D1, D2, T) :-
   (member(1,D1), D1check = true ; non_member(1,D1), D1check = false),
   (member(1,D2), D2check = true ; non_member(1,D2), D2check = false),
   length(D1, D1Len),
   length(D2, D2Len),
   minset_one_(D1check, D2check, D1, D2, D1Len, D2Len, T).

Running the sample query we now get:

?- D1 = [X,Y,Z], D2 = [U,V], minset_one(D1,D2,T).
   D1 = [1,Y,Z], X = U, U = 1, D2 = T, T = [1,V]
;  D1 = [1,Y,Z], X = V, V = 1, D2 = T, T = [U,1]
;  D1 = T, T = [1,Y,Z], X = 1, D2 = [U,V], dif(U,1), dif(V,1)
;  D1 = [X,1,Z], Y = U, U = 1, D2 = T, T = [1,V]
;  D1 = [X,1,Z], Y = V, V = 1, D2 = T, T = [U,1]
;  D1 = T, T = [X,1,Z], Y = 1, D2 = [U,V], dif(U,1), dif(V,1)
;  D1 = [X,Y,1], Z = U, U = 1, D2 = T, T = [1,V]
;  D1 = [X,Y,1], Z = V, V = 1, D2 = T, T = [U,1]
;  D1 = T, T = [X,Y,1], Z = 1, D2 = [U,V], dif(U,1), dif(V,1)
;  D1 = [X,Y,Z], D2 = T, T = [1,V], U = 1, dif(X,1), dif(Y,1), dif(Z,1)
;  D1 = [X,Y,Z], D2 = T, T = [U,1], V = 1, dif(X,1), dif(Y,1), dif(Z,1)
;  false.

Better. Sure looks to me like there's nothing missing.

一直在等你来 2025-01-26 01:31:44

我认为这将是:

add:

:- use_module(library(reif)).

...和替换:

    %(member(1, D1) -> D1check = true ; D1check = false),
    %(member(1, D2) -> D2check = true ; D2check = false),
    memberd_t(1, D1, D1check),
    memberd_t(1, D2, D2check),

成员和成员d_t之间的差异的示例:

?- member(X, [A, B, C]).
X = A ;
X = B ;
X = C.

?- memberd_t(X, [A, B, C], IsMember).
X = A,
IsMember = true ;
X = B,
IsMember = true,
dif(A,B) ;
X = C,
IsMember = true,
dif(A,C),
dif(B,C) ;
IsMember = false,
dif(A,X),
dif(B,X),
dif(C,X).

?- memberd_t(X, [A, B, C], IsMember), X = 5, A = 5, C = 5.
X = A, A = C, C = 5,
IsMember = true ;
false.

因此,成员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:

:- use_module(library(reif)).

... and replace:

    %(member(1, D1) -> D1check = true ; D1check = false),
    %(member(1, D2) -> D2check = true ; D2check = false),
    memberd_t(1, D1, D1check),
    memberd_t(1, D2, D2check),

Example of the difference between member and memberd_t:

?- member(X, [A, B, C]).
X = A ;
X = B ;
X = C.

?- memberd_t(X, [A, B, C], IsMember).
X = A,
IsMember = true ;
X = B,
IsMember = true,
dif(A,B) ;
X = C,
IsMember = true,
dif(A,C),
dif(B,C) ;
IsMember = false,
dif(A,X),
dif(B,X),
dif(C,X).

?- memberd_t(X, [A, B, C], IsMember), X = 5, A = 5, C = 5.
X = A, A = C, C = 5,
IsMember = true ;
false.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文