Dijkstra 守卫计数如何在 Prolog 中对执行进行排序

问题描述

我在 Dijsktras“if fi”中没有找到 Prolog cut,因为他 says“否则将选择具有真正保护的任意保护列表来执行。”。因此,他的构造不会选择第一个匹配项,就像 Prolog 剪切会做的那样:

if Cond1 -> Action11,..,Action1n1
[] Cond2 -> Action21,Action2n2
...
[] Condm -> Actionm1,Actionmn2
if

在“do od”构造中是否有 Prolog 切割,只要受保护列表的至少一个条件为真,它就会循环?或者在 Prolog 中实现它的其他方法,我假设循环可以转换为递归调用。那么我们如何在 Prolog 中对 q1,q2,q3,q4 进行排序:

do q1 > q2 -> q1,q2 := q2,q1
[] q2 > q3 -> q2,q3 := q3,q2
[] q3 > q4 -> q3,q4 := q4,q3
od

Prolog 程序对于输入 7,11,5,3 将有多少个非确定性执行路径(即 Prolog 解决方案)都提供相同的答案?

解决方法

如果我们假设没有守卫计算可以发散,我认为以下表达的计算与问题中的排序示例相同:

dgsort([A,B,C,D],R):-
  ( A > B -> X1 = [1]    ; X1 = [] ),( B > C -> X2 = [2|X1] ; X2 = X1 ),( C > D -> X3 = [3|X2] ; X3 = X2 ),(   X3 = [] -> R = [A,D]
  ;   random_member( X,X3),(  X =:= 1 -> dgsort([B,A,R)
      ;  X =:= 2 -> dgsort([A,R)
      ;  X =:= 3 -> dgsort([A,D,C],R) )).

评论:“一个任意带有true防护的防护列表将被选择执行”,其他所有列表都被删除,即被选中的 致力于,我一直认为。因此,如果我必须实现它,我会生成所有分支的守卫,以一定的超时间隔检查它们,一旦一个或多个成功,我就会随机选择其中一个,杀死所有其余的,然后继续赢家。即承诺它。无论如何,这是我的理解。 (或者也许超时也应该是随机的?)

我还认为 do-od 构造通过相同的机制选择了真正的守卫。即“至少一个”,我们不在乎哪个。如果我们假设所有守卫计算都终止,我们可以执行所有守卫计算,随机选择获胜者,然后继续其行动。上面的代码就是这样做的。


要找出我们需要将 random_member 更改为 member 的执行路径数,通过 findall 运行谓词并测量结果列表的长度:

dgsortn([A,D]
  ;   member( X,(  X =:= 1 -> dgsortn([B,R)
      ;  X =:= 2 -> dgsortn([A,R)
      ;  X =:= 3 -> dgsortn([A,R) )).

运行5次成功:

9 ?- dgsortn( [7,11,5,3],R).
R = [3,7,11] ;
R = [3,11].

我们还可以添加一个计数器来查看生成每个解决方案所采取的步骤数。

,

我认为你可以这样做:

<div class="shadow"></div>

执行:

do([Q1,Q2,Q3,Q4],[swap(Q1,Q2)|P],S) :-
    Q1 > Q2,do([Q2,Q1,P,S).

do([Q1,[swap(Q2,Q3)|P],S) :-
    Q2 > Q3,do([Q1,[swap(Q3,Q4)|P],S) :-
    Q3 > Q4,Q4,Q3],[],[Q1,Q4]) :- % termination state
    Q1 =< Q2,Q2 =< Q3,Q3 =< Q4.
,

我直接解决了计数问题并提出了这个解决方案。它的缺点是否定作为失败会重新评估条件。

sortloop([Q1,R) :- Q1 > Q2,sortloop([Q2,R).
sortloop([Q1,R) :- Q2 > Q3,sortloop([Q1,R) :- Q3 > Q4,Q4]) :- \+ Q1 > Q2,\+ Q2 > Q3,\+ Q3 > Q4.

但它显示有 5 个执行路径:

?- sortloop([7,11] ;
false.

但是我们可以改进条件只评估一次吗?我想到的是软剪切 (*->)/2,因为操作列表不会中止:

sortloop2([Q1,R) :-
  ((Q1 > Q2,sortloop2([Q2,R);
    Q2 > Q3,sortloop2([Q1,R);
    Q3 > Q4,R)) *-> true; R=[Q1,Q4]).

软切割解决方案给出了相同的结果:

?- sortloop2([7,11] ;
false.

但没有一个解决方案使用 Prolog 切割来替换 Dijkstra 守卫中条件和动作列表之间的箭头。情况有点复杂。

编辑 12.02.2021:
如果有人好奇这 5 条路径作为 DAG 的样子:

enter image description here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...