我试着编写一个能够理解用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> 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;
但同样,我需要帮助/想法如何在prolog中将此代码表示为实现目标的行动/规则/事实。
非常感谢任何帮助。
非常感谢
答案 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测试两个分支,传播值。但是,正如我所说,并不是那么容易......