如何在Prolog中编写有条件的计划?

时间:2012-10-25 01:44:44

标签: prolog conditional planning clpfd

我试着编写一个能够理解用C#编写的学生程序的序言代码。现在我陷入了识别学生计划中“if”语句的过程中。例如: 以下是我对学生的期望代码。

int d = int.Parse(Console.ReadLine());  // value d is inputted by user
int s = 0;

if (d>0)
    s = 2;
else if (d==0)
    s = 1;
else
    s = 0;

我将此预期代码的目标定义为:

goal:- 
   hasVarName(Vid_s, s),
   hasVarName(Vid_d, d),
   hasVarValue(Vid_d, Vd),
   ((not(gt(Vd,0)); hasVarValue(Vid_s, 2)),           %eq: [Vd>0] -> [val_s = 2]
   ((gt(Vd,0); not(eq(Vd,0)); hasVarValue(Vid_s, 1)), %eq: [~(Vd>0)^(Vd=0)] -> [val_s = 1]
   ((gt(Vd,0); eq(Vd,0); hasVarValue(Vid_s, 0).       %eq: [~(Vd>0)^~(Vd=0)] -> [val_s = 0]

问题是如何在prolog事实和规则中代表上述学生代码,以发现目标对任何可能的条件都满意。

我试图改变学生代码的第一部分,使其成为如下事实,但实际上并不知道如何将学生的“if”陈述表示为prolog中的事实/规则(我想,我不应该改变)它是为了推广'如果',对吗?)

hasVarName(varID_d, d)
hasVarValue(varID_d, val_d)   %it is unknown, so I represent it as symbol 'val_d'

hasVarName(varID_s, s)
hasVarValue(varID_s, 0)

另一个,在我的目标中,当我进行比较时,例如gt(Vd,0)我认为我不能使用prolog大于运算符,Vd> 0Vd @> 0都不会导致Vd中的值实际上是用户输入的某个值,但它表示为符号值(在这种情况下它是:val_d)。

注意:使用上述目标,我认为如果将学生代码更改为以下代码,则会满足定义的目标。

int d = int.Parse(Console.ReadLine());  // value d is inputted by user
int s = 0;

if (d>0)
    s = 2;
else if (d==0)
    s = 1;

int d = int.Parse(Console.ReadLine());  // value d is inputted by user
int s = 10;           // any random initialization

if (d>0)
{
    int x = 2;       // unnecessary step, but still Ok.
    s = x;
}
else if (d==0)
    s = 1;
else
    s = 0;

但同样,我需要帮助/想法如何在prolog中将此代码表示为实现目标的行动/规则/事实。

非常感谢任何帮助。

非常感谢

2 个答案:

答案 0 :(得分:0)

我猜你试图通过暗示来模拟if-then-else,使用 以下布尔标识:

A -> B == ~A v B.

不是使用含义的连词,而是更容易 使用disjunction在分支和连接之间进行选择 沿着控制流程。但是你排除了以前的if条件 通过否定仍然是必要的。

举个例子:

if (d>0)
   s = 2;
else if (d==0)
   s = 1;
else
   s = 0;

您可以使用CLP(*)对其进行建模。添加额外的变量,以便 变量没有被覆盖,但这不是问题 小片上面的小片段。在CLP(*)中,上面的片段变成了,I 我使用CLP(FD)来简化:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.3.0)
Copyright (c) 1990-2012 University of Amsterdam, VU Amsterdam
?- use_module(library(clpfd)).
?- [user].
that_if(D, S) :-
   (D #> 0, S #= 2;
    D #=< 0, D #= 0, S #= 1;
    D #=< 0, D #\= 0, S #= 0)
^D

在一个体面的CLP(*)系统中,您可以任意实例化或 约束查询中的D或S.我们已经得到了例如 在CLP(FD)中:

/* What conditions give result S #= 1 ? */
?- S #= 1, that_if(D, S).
S = 1,
D = 0 .

/* What results give condition D #= 1 */
?- D #= 1, that_if(D, S).
D = 1,
S = 2 ;
false.

/* What conditions give a result S #=< 1 */
?- S #=< 1, that_if(D, S).
S = 1,
D = 0 ;
S = 0,
D in inf.. -1.

/* What results give a condition D #>= 0 */
?- D #>= 0, that_if(D, S).
S = 2,
D in 1..sup ;
D = 0,
S = 1 ;
false.

再见

答案 1 :(得分:0)

通常语言实现需要一个抽象语法树,可以方便地指定实现我们允许表达的构造的语义动作。

您似乎正在跳过构建语法树的阶段,(手工?)代表程序的中间级别。

如果您坚持使用这种中等级别的表示,您可以使用递归术语(实际上是一个抽象树),例如if(Condition, Then, Else),其中每个变量都是语法树。

否则,更实际的表示(通常应用于命令式语言),使用基本块的概念(没有跳转的指令序列)然后使用标签来描述执行流程。

结果是图表,程序的行为由该表示的“拓扑”决定。

goal:- 
   hasVarName(Vid_s, s),
   hasVarName(Vid_d, d),
   hasVarValue(Vid_d, Vd),

   %eq: [Vd>0] -> [val_s = 2]
   ((not(gt(Vd,0)); hasVarValue(Vid_s, 2), goto(label(0))),

   %eq: [~(Vd>0)^(Vd=0)] -> [val_s = 1]
   ((gt(Vd,0); not(eq(Vd,0)); hasVarValue(Vid_s, 1), goto(label(0))),

   %eq: [~(Vd>0)^~(Vd=0)] -> [val_s = 0]
   ((gt(Vd,0); eq(Vd,0); hasVarValue(Vid_s, 0)), % the goto is useless here...

   label(0),
   .....

请注意,我没有注意正确描述您的示例程序,只是放置了跳转来显示这种可能性......

编辑我认为一般问题无法解决,相当于图灵机的halting problem。对于手边的特定情况,没有循环,我会使用AST上的抽象解释来解决问题。即一个计算有趣内容的翻译。

如果可行,取决于目标计划的一般性。您应该能够为每个条件点中涉及的每个变量分区整数域。事情变得非常复杂......

具体而言,在IF THEN ELSE尝试对域进行分区的条件点。使用这种方法,让Prolog 执行 IF测试两个分支,传播值。但是,正如我所说,并不是那么容易......