Prolog 初学者:如何为谓词中的每个变量设置唯一值
我有一个序言谓词:
Add( [A|B] , Answer ) :-
...
~ Add everything in the list to come up with answer
...
我现在想实现 AddUnique
,当我给它两次变量时,它将为列表中的所有内容返回唯一值除了。
以下是逻辑上等效的内容:
?- AddUnique([A, B, C], 10).
等效于: ?- Add([A, B, C], 10 ), A != B, B != C, A != C.
并且:
?- AddUnique([A, B, B], 10).
相当于: <代码>?- Add([A, B, B], 10), A != B.
另外:
?- AddUnique([A, B, B], 10).
不相当于: ?- Add([A, B, B], 10), A != B, B!=B.
如果 ?- AddUnique([A,B,C,D], 4).
被赋予它应该返回 false,因为它不能带有加到四的唯一正整数。
如果给出 ?- AddUnique([A,A,A,A], 4).
,则应返回 A=1
。
问题:如何在谓词内移动 A != B, B != C, A != C.
逻辑,而不执行类似 A ! = A ?
I have a prolog predicate:
Add( [A|B] , Answer ) :-
...
~ Add everything in the list to come up with answer
...
I would now like to implement AddUnique
that would return unique values for everything in the list except when I give it the variable twice.
Here are somethings that are logically equivalent:
?- AddUnique([A, B, C], 10).
is equivalent to: ?- Add([A, B, C], 10), A != B, B != C, A != C.
And:
?- AddUnique([A, B, B], 10).
is equivalent to: ?- Add([A, B, B], 10), A != B.
Also:
?- AddUnique([A, B, B], 10).
is NOT equivalent to: ?- Add([A, B, B], 10), A != B, B!=B.
If ?- AddUnique([A,B,C,D], 4).
is given it should return false since it cannot come with unique positive integers that add to four.
If ?- AddUnique([A,A,A,A], 4).
is given it should return A=1
.
Question: How can I move the A != B, B != C, A != C.
logic inside the predicate without doing something like this A != A
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Khm...你应该明白
doStuff(A,B,C,D)
和doStuff(A,A,B,B)
的意思。首先是将A
..D
值与适当的值统一起来,从而使doStuff/4
可以达到目标。第二个等于A=B, C=D, doStuff(A,B,C,D)
和doStuff(A,B,C,D), A=B, C =D
(但最后一个变体可能会导致回溯)。所以我希望您明白unique/1
不应该在doStuff/4
内部完成,因为它是外部限制。所以你应该使用 doStuff(A,B,C,D), unique([A,B,C,D]) 和 doStuff(A,A,B,B), unique ([A,B])。我想知道你怎么读
A is not B
...无论如何,您可以将
unique/1
定义为Khm... You should understand that
doStuff(A,B,C,D)
anddoStuff(A,A,B,B)
means. First is going to unify valuesA
..D
with appropriate values which makesdoStuff/4
reachable goal. And second is equal toA=B, C=D, doStuff(A,B,C,D)
anddoStuff(A,B,C,D), A=B, C=D
(but last variant probably will cause backtracking). So I hope you understand thatunique/1
shouldn't be done insidedoStuff/4
, because it's outside restriction. So you shoulad usedoStuff(A,B,C,D), unique([A,B,C,D])
anddoStuff(A,A,B,B), unique([A,B])
.I wonder how you read
A is not B
...Anyway you can define
unique/1
as根据您对 addUnique/2 谓词的描述,可以使用约束逻辑编程来实现解决方案。这与初学者的东西相去甚远,但无论如何我都会发布一个解释。
首先,可能值得查找约束逻辑编程是什么,以及如何使用实现(例如,SWI-PL clpfd)。基本上,约束逻辑编程(特别是有限域求解器)将允许您对输入列表上的变量指定以下约束:
addUnique/2
:总之,这些规范将允许底层约束求解器自动确定在给定上述约束的情况下变量可以同时采用哪些允许值,从而为您提供解决方案(可能有多个、一个或没有)。
下面是在 SWI-PROLOG(clpfd 求解器)中使用上述约束求解器的解决方案:
例如,运行此代码会给出:
;
枚举变量之间允许的绑定的下一个解决方案。请注意,A
和B
永远不会根据需要采用相同的值,但输入列表中的所有出现的总和将始终为6
。另一个查询:这里的结果是失败的,因为找不到单个整数可以绑定到
A
,当求和时,总计为4
,而:...如预期的那样。另外,您想尝试:
同样,这里的结果是失败,因为所有变量
A
、B
、C
和D< /code> 均被断言为不同,并且不能全部绑定到
1
。编辑 ps。 ony 也想尝试:
对上面的代码进行简单修改,确保在调用
ins
断言域时仅使用变量(而不是输入列表中的任何数字)。Given your description of the
addUnique/2
predicate, constraint logic programming can be used to implement a solution. This is far from beginner stuff, but I'll post an explanation anyway.Firstly, it might be worthwhile looking up what constraint logic programming is, and an how to use an implementation (e.g., SWI-PL clpfd). Basically, constraint logic programming (particularly the finite domain solver) will allow you to specify the following constraints over your variables on the input list to
addUnique/2
:Together, these specifications will allow the underlying constraint solver to automatically determine what permissible values the variables can simultaneously take on given the above constraints, giving you your solutions (there may be several, one, or none).
Here is a solution using the aforementioned constraint solver in SWI-PROLOG (the clpfd solver):
Running this code, e.g., gives you:
;
enumerates the next solution for permissible bindings between variables. Note thatA
andB
never take on the same value, as required, but all occurrences in the input list will always sum to6
. Another query:The result is failure here because no single integer could be found to bind to
A
that, when summed up, totaled4
, whereas:...as expected. Also, you wanted to try:
Again, the result is failure here because all the variables
A
,B
,C
andD
were all asserted to be different, and cannot all bind to1
.EDIT ps. ony also wanted to try:
A simple modification to the code above ensures that only variables are used when calling
ins
to assert domains (and not any numbers in the input list).这是我想出的解决方案。它只会将输入分配为小于 10 的数字,但效果很好!
This is the solution that I came up with. It will only assign the input to be numbers less than ten but works great for that!