2012-10-25 24 views
1

我试着编写一个可以理解用C#编写的学生程序的prolog代码。现在我被困在识别学生课程中'如果'陈述的过程中。例如: 以下是我期望学生的代码。如何在Prolog中编写一种有条件的规划?

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)我想我不能比运营商使用的序言时,既不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; 

但同样,我需要帮助/想法如何代码可以在序言为行动/规则/事实上,以满足目标来表示。

任何帮助真的很感激。

非常感谢

回答

0

我想你想的模型通过暗示IF-THEN-ELSE,使用 以下布尔身份:

A -> B == ~A v B. 

而不是使用含义的连词,它更容易 到沿着控制流使用分支在分支之间进行选择,并且连接 。但是,您通过否定排除之前的条件 仍然是必要的。

把你的例子:

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. 

再见

+0

CLP这很有趣,但我认为新手可能真的**很难弄清楚它。 – CapelliC

+0

不是我的观点:我也不知道Budi Hartanto是否是新手,也不知道CLP(*)特别困难的统计数据。 CLP(*)应该更简单,因为它更具说明性。 –

+0

此外,没有一些CLP(*)可以验证不多。如果你有int d = int.Parse(Console.ReadLine());那么数据可以是任意的,标准的Prolog穷举搜索实际上不会用于回答您的查询。你需要像CLP(*)这样更具象征意义的东西。 –

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的条件点,然后尝试分割域。使用这种方法,让Prolog 执行 IF测试两个分支,传播这些值。但是,正如我所说的,不是很容易...

+0

嗨Chac,谢谢你的建议解决方案。你能稍微解释一下你的建议吗?为了您的信息,这是我做的全部事情:我有一个C#程序,用于读取学生C#程序。在我的C#程序中,我拥有学生代码的AST。从这个AST中,我创建了prolog子句让prolog确定我为学生的任务设定的目标是否满意。所以,我的C#程序中已经准备好了AST,但是我不知道如何在序言中将它与我的目标联系起来。或者,也许我定义我的目标的方式不正确?谢谢 –