如何在Prolog中编写一种条件规划?

如何在Prolog中编写一种条件规划?,prolog,conditional,planning,clpfd,Prolog,Conditional,Planning,Clpfd,我试图编写一个prolog代码,可以理解用C#编写的学生程序。现在我被困在识别学生程序中“如果”语句的过程中。例如: 下面是我期望从学生那里得到的代码 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:-

我试图编写一个prolog代码,可以理解用C#编写的学生程序。现在我被困在识别学生程序中“如果”语句的过程中。例如: 下面是我期望从学生那里得到的代码

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事实和规则中表示上述学生代码,以发现目标在任何可能的条件下都得到满足

我试图将学生代码的第一部分更改为如下事实,但不知道如何在prolog中将学生的“如果”语句表示为事实/规则(我想,我不应该将其更改为prolog“如果”,对吗?)

另一个,在我的目标中,当我进行比较时,比如
gt(Vd,0)
我认为我不能使用prolog大于运算符,无论
Vd>0
还是
Vd@>0
都不会导致Vd中的值实际上是用户输入的某个值,但它表示为符号值(在本例中是:
val\u 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;

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

非常感谢您的帮助


非常感谢

我想你试图通过暗示,使用 以下布尔标识:

A -> B == ~A v B.
这比使用暗示连词更容易 使用析取在分支和连接之间进行选择 沿着控制流。但是你排除了以前的if条件 通过否定仍然是必要的

以你为例:

if (d>0)
   s = 2;
else if (d==0)
   s = 1;
else
   s = 0;
您可以使用CLP(*)对其进行建模。添加额外的变量,以便 变量不会被重写,但在 上面的小片段。在CLP(*)中,上述代码段变为 为了简单起见,am使用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
欢迎使用SWI Prolog(多线程,64位,版本6.3.0)
版权所有(C)1990年至2012年,阿姆斯特丹大学,阿姆斯特丹
?使用_模块(库(clpfd))。
?-[用户]。
如果(D,S):-
(D#>0,S#=2;
D#=<0,D#=0,S#=1;
D#=<0,D#=0,S#=0)
^D
在一个像样的CLP(*)系统中,您可以任意实例化或 在查询中约束D或S。我们已经有了一个例子 在中电(FD):

/*什么条件使结果S#=1*/
?-S#=1,即如果(D,S)。
S=1,
D=0。
/*什么结果给出了条件D#=1*/
?-D#=1,即如果(D,S)。
D=1,
S=2;
错误的
/*什么条件给出的结果S#=<1*/
?-S#=<1,如果(D,S)。
S=1,
D=0;
S=0,
D在inf-1.
/*什么结果给出了条件D#>=0*/
?-D#>=0,即如果(D,S)。
S=2,
D在1..sup中;
D=0,
S=1;
错误的

再见

通常,语言实现需要一个抽象语法树,在这里可以方便地指定实现我们可以表达的结构的语义操作

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

如果您坚持这样的中级表示,您可以使用递归术语(实际上是一个抽象树),比如
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测试两个分支,传播值。但是,正如我所说,这并不容易…

CLP这很有趣,但我认为一个新手可能真的很难理解它。这不是我的观点:我既不知道Budi Hartanto是否是一个新手,也没有统计数据表明CLP(*)特别难理解。CLP(*)应该更简单,因为它更具声明性。此外,如果没有一些CLP(*),则无法验证多少。如果您有int d=int.Parse(Console.ReadLine());然后数据可以是任意的,标准的Prolog穷举搜索实际上无法回答您的查询。你需要一些更具象征意义的东西,比如CLP(*)。嗨,饼干怪兽,谢谢你推荐的解决方案。问题是,在我的例子中,我永远不会知道d的值是多少,因为我永远不会运行学生代码。我只需要分析学生代码是否包含足够的计划(条件)来解决交给他的问题。因此,我永远不会知道D的值,在我的示例中,我只是简单地指定val_D作为变量D内容的符号表示。因此,在这种情况下,我的问题更像是检查学生的计划(代码)是否可以用来解决给他的问题。CLP(*)也不会赋值,除非在CLP(FD)中使用标签。但是像1..sup中的D这样的答案不是赋值,而是变量的域范围。但您需要多一点编码,并最终具体化约束,才能从CLP(*)rel获得更精确的响应
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
/* 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.
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),
   .....