prolog - 使序言谓词具有确定性
问题描述
我写了一个谓词 ,shuffle/3
它生成两个列表的“洗牌”。当实例化第二个和第三个参数时,第一个参数变成一个列表,其中包含 Left 和 Right 的所有元素,其顺序与它们在 Left 和 Right 中出现的顺序相同。
例如:
?- shuffle(X, [1, 2], [3, 4]).
X = [1, 3, 2, 4] ;
X = [1, 3, 4, 2] ;
X = [1, 2, 3, 4] ;
X = [3, 4, 1, 2] ;
X = [3, 1, 2, 4] ;
X = [3, 1, 4, 2] ;
false.
这是我想出的实现它的代码:
shuffle([], [], []).
shuffle([H|R], [H|Left], Right) :- shuffle(R, Right, Left).
shuffle([H|R], Left, [H|Right]) :- shuffle(R, Right, Left).
这很好用,甚至可以为“最一般的查询”生成合理的结果,但它对于任何查询都不是确定性的,即使是所有参数都被完全实例化的查询:shuffle([1, 2, 3, 4], [1, 2], [3, 4])
.
我真正的问题是:有什么我可以做的,同时保持纯度(所以,没有削减),当所有参数都被完全实例化时,这使得这个谓词具有确定性?
当我在这里时,我是 Prolog 的新手,我想知道是否有人对我为什么要关心确定性提出建议。它对真正的序言程序很重要吗?
解决方案
不,没有办法在保持纯代码的同时使这个谓词具有确定性。要看到这一点,请考虑:
?- shuffle([1, 1], [1], [1]).
true
; true.
对此有两个答案。为什么?最好不要使用调试器来理解这一点,而是使用通用查询:
?- shuffle([X1, X2], [Y1], [Y2]).
X1 = Y1, X2 = Y2
; X1 = Y2, X2 = Y1.
所以在这里你可以看到论点之间的“真实”联系!现在我们的特定查询是这个更一般查询的一个实例。因此,没有办法删除这两个答案。
但是,您可以以纯方式使用 cut ,前提是对其进行保护以使结果始终是纯的。就像测试一样ground(shuffe(Xs, Ys, Zs))
,但所有这些都是临时性的。
再想一想,可能会有一个纯粹的、确定的答案,但前提是答案会以shuffle([X1, X2], [Y1], [Y2]).
某种方式改变。答案实际上应该是:
?- shuffledet([X1, X2], [Y1], [Y2]).
X1 = X2, X2 = Y1, Y1 = Y2 % all equal
; dif(X1, X2), X1 = Y1, X2 = Y2
; dif(X1, X2), X1 = Y2, X2 = Y1.
所以这可能是一种可能性......我会尽快给这个 500 赏金,但没有回应。我再次尝试另一个。
推荐阅读
- typescript - 安装后的 webpack 在加载打字稿时失败
- c++ - 如何在 gtest 中通过 CURL 测试 HTTPS 请求(SSL)?
- linux - gdb coredump - 调用函数或继续执行
- spring-boot - 寻找现在已弃用的 retryWhen 的替代方案
- solr - SolrJ addDateRangeFacet 和 addFacetPivotField
- python - 用于分发的 tensorflow-python 的更轻量级替代品
- javascript - NodeMailer 从数据库发送带有模板的 HTML 电子邮件
- r - 根据 r 中的因子水平指数对数据框进行排序
- reactjs - React Native 和 Firebase:我的组件正在无限循环中重新渲染
- java - 如何删除 Linked HashMap 中的重复项?