0

我试图编写一个可以理解用 C# 编写的学生程序的 prolog 代码。现在我被困在识别学生程序中的“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 中的事实/规则(我想,我不应该将其更改为 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)我认为我不能使用序言大于运算符,也Vd> 0不会Vd @> 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;

但同样,我需要帮助/想法如何在序言中将此代码表示为操作/规则/事实以实现目标。

非常感谢任何帮助。

非常感谢

4

2 回答 2

0

我猜您尝试使用以下布尔标识通过暗示对 if-then-else 进行建模:

A -> B == ~A v B.

与其使用蕴涵的连词,不如使用析取来在分支之间进行选择,并在控制流中使用合取更容易。但是您仍然需要通过否定排除以前的 if 条件。

举个例子:

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

您可以使用 CLP( * ) 对其进行建模。添加额外的变量以便变量不会被覆盖,但这在上面的小片段中不是问题。在 CLP( * ) 中,上面的代码片段变成了,为了简单起见,我使用 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.

再见

于 2012-10-25T06:22:03.237 回答
0

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

您似乎跳过了构建语法树的阶段,并且(手动?)代表程序的中间级别。

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

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

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

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),
   .....

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

编辑我认为一般问题无法解决,相当于图灵机的停机问题。对于手头的特殊情况,如果没有循环,我会在 AST 上使用抽象解释来解决问题。即计算有趣内容的解释器。

是否可行取决于您的目标程序的普遍性。您应该能够为每个条件点中涉及的每个变量划分整数域。事情变得迅速复杂......

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

于 2012-10-25T13:16:34.240 回答