在 Prolog 中获取查询的具体答案时遇到问题

问题描述 投票:0回答:1

Prolog 似乎无法返回查询的某些特定答案。我在 SWI-Prolog 中编写了一段简短的代码,其中我尝试检查给定的二进制向量 C 是否可以由 生成矩阵 G 生成。所有计算均以模 2 进行。当我为二元向量

codeword/2
调用主谓词
[0,1,1]
时,它返回
true
,这是查询的正确答案:

codeword([0,1,1],[[1,1,1],[1,0,0]]).
true.

但是,当我在查询中调用谓词时

codeword([X,Y,Z],[[1,1,1],[1,0,0]]),X+Y+Z =:= 2.

它返回

false
,这显然是一个错误的答案,因为我们确实知道
[0,1,1]
实际上是一个代码字。换句话说,通过第一个查询,我们可以看到
[0,1,1]
确实是一个码字;但第二个查询表明该代码不包含权重为2的码字,这是不正确的。

这是 Prolog 中的正常行为吗?我们可以认为它是一个错误吗?

这是我写的:

addbinvecs([A],[B],[C]) :-
    (A = B -> C = 0; C = 1).
addbinvecs([H1|T1],[H2|T2],[H3|T3]) :-
    (H1 = H2 -> H3 = 0; H3 = 1),
    addbinvecs(T1,T2,T3).   
%%%
allzero([0]).
allzero([H|T]):-
    H = 0,
    allzero(T).
%%%
codeword(X,[_|_]) :- allzero(X).
codeword(C,[C|_]).
codeword(C,[_|Gt]):-
    codeword(C,Gt).
codeword(C,[Gh|Gt]):-
    addbinvecs(C,Gh,C1),
    codeword(C1,Gt).
prolog swi-prolog
1个回答
0
投票

在您的评论中加注星号:

我没有采用削减。

哦,是的,你做到了!您使用的 if-then-else 构造隐式地使用了剪切,从而对搜索空间进行了过多的修剪。但你自己怎么能看到呢?

首先,接受您的查询并删除额外的条件:

?- codeword([A,B,C],[[1,1,1],[1,0,0]]).
   A = 0, B = 0, C = 0
;  A = 1, B = 1, C = 1
;  A = 0, B = 0, C = 0
;  A = 1, B = 0, C = 0
;  A = 1, B = 1, C = 1
;  false, unexpected, incomplete.

因此,虽然这些答案都很好,但缺少进一步的答案。解决这个问题的一个简单方法是用它的纯版本替换这个 if-then-else 结构,称为

if_/3
:

:- use_module(library(reif)).

addbinvecs([A],[B],[C]) :-
   if_(A = B, C = 0, C = 1).
   % (A = B -> C = 0; C = 1).
addbinvecs([H1|T1],[H2|T2],[H3|T3]) :-
   if_(H1 = H2, H3 = 0, H3 = 1),
   % (H1 = H2 -> H3 = 0; H3 = 1),
   addbinvecs(T1,T2,T3).

?- codeword([A,B,C],[[1,1,1],[1,0,0]]).
   A = 0, B = 0, C = 0
;  A = 1, B = 1, C = 1
;  A = 0, B = 0, C = 0
;  A = 1, B = 0, C = 0
;  A = 1, B = 1, C = 1
;  B = 1, C = 1, dif:dif(A,1) % new
;  false.

(在SWI中,您需要安装库(reif),在Scryer或Trealla中它是预先安装的。)

现在包含您期望的解决方案,除了......它有点太笼统了。它不仅承认

A = 0, B = 1, C = 1
,而且还承认无数其他解决方案,例如

   true
;  false.

但是,这就是你一开始所描述的!要缩小范围,您必须声明所有变量都是二进制的。这对你来说应该不会太难。

© www.soinside.com 2019 - 2024. All rights reserved.