在swi-prolog中编写递归

时间:2012-09-16 07:59:33

标签: prolog

我已成功将PHP与Prolog连接,并设法查询驻留在knowledge_base.pl文件中的所需知识库,并设法通过php exec函数回显结果。

我在回复每次执行查询后返回的true / false值时遇到了问题(see previous question)所以我想出了一个我无法实现的解决方案。< / p>

假设我有一个简单的knowledge_base.pl文件,其中包含以下事实和规则:

girl(erin).
boy(john).

likes(erin, reading).
likes(john, reading).

hangs_out_with(erin, X) :-
    likes(X, reading),
    boy(X),
    writeln('Someone s got a new friend!!').

让我们说我想看看erin是否是女孩,如果是,请写下它是真的,否则写下它是假的。我将此添加到我的knowledge_base.pl文件中:

girl(erin) :-
        girl(erin)
     -> write('it is true')
     ;  write('it is not true'). 

当我输入查询时:?- girl(erin).我收到out of local stack错误。我搜索了网络,发现这是由于无限递归。

有人可以给我一个如何写的提示

girl(X) :-
    (    girl(X)
      -> write('it is true')
      ;  write('it is not true')).  
在Prolog中?提前谢谢。

作为新用户,我不允许发布图片。

SWI-Prolog的输出:

1 ?-hangs_out_with(erin,kosta).
false.

2 ?-hangs_out_with(erin,john).
Someone s got a new friend!!
true.

命令提示符的输出:

C:\(directory)>swipl -q -f knowledge_database.pl -g hangs_out_with(erin,kosta),halt.
1 ?-halt. (the halt is inputted by me.)
C:\(directory)>swipl -q -f knowledge_database.pl -g hangs_out_with(erin,john),halt.
Someone s got a new friend!!

第一个查询失败,第二个查询失败。正如您所看到的,prolog在查询执行后输出true / false但是当我在命令提示符中执行相同的查询时,true / false值不会被回显!!

3 个答案:

答案 0 :(得分:2)

我想你应该问

is_girl(X) :-
    girl(X) -> write('t is true') ; write('it is not true'). 

修改

你是说这种事吗?

is_type(Type, X) :-
    call(Type, X) -> writeln(yes); writeln(no).

答案 1 :(得分:1)

所以你通过在命令shell中执行Prolog查询并捕获和分析其输出来“将PHP连接到Prolog”。 http://www.swi-prolog.org/man/quickstart.html

  

“2.1.1.1在Unix上启动SWI-Prolog

     

默认情况下,SWI-Prolog安装为'swipl'。 SWI-Prolog本身及其实用程序的命令行参数使用标准的Unix手册页进行记录。“

请参阅有关“-q”开关的手册页。这也许是安静的“-q”吗? “-f”是什么意思(好吧,那可能是“文件”)?但解决方案是相同的 - 只需为新谓词使用不同的名称。

请注意,在您第一次尝试时,

C:>swipl -q -f knowledge_database.pl -g hangs_out_with(erin,kosta),halt.
1 ?-halt. (the halt is inputted by me.)

halt未执行,正是因为hangs_out_with(erin,kosta)失败了。逗号表示连词(“和”)。

您需要做的就是创建一个新的谓词来报告目标是真还是假,并且始终成功:

report_hangs_out_with(A,B):-
  hangs_out_with(A,B)- > writeln(['YES',A,B]) ; writeln('NO').

并改为使用

C:>swipl -q -f knowledge_database.pl -g report_hangs_out_with(erin,kosta),halt.

此外,Prolog回应“true”或“false”是其交互式会话的一部分。但是你用halt终止了它!


您发布了

编辑

1 ?-hangs_out_with(erin,kosta).
false.

因此,当您在交互式Prolog shell中运行该查询时,它会报告失败。 halt/0退出Prolog shell。当您使用通过命令行开关指定的目标运行它时,显然它不会报告失败的成功。就用户而言,这就是自然界的事实(例如编译器编写者)。用我向你展示的内容很容易解决。而且你自己也说它有效。对于可能失败或成功的每个谓词,定义另一个 报告谓词,就像我向您展示的那样。

这是一个示例脚本(在Windows中,但这是无关紧要的)。这应该清除你的疑虑:

C:\Program Files\pl\bin>plcon -q -g (writeln('****'),halt).
****                          // didn't say Yes, right??

C:\Program Files\pl\bin>plcon -q
1 ?- writeln('****'),halt.
****                          // didn't say Yes here either

C:\Program Files\pl\bin>plcon -q
1 ?- writeln('****').
****

Yes                           // does say Yes as part of interaction
2 ?- halt.

C:\Program Files\pl\bin>      

这就是它的样子。处理它。 :)或者写Jan并请他改变它。 :)

答案 2 :(得分:1)

girl(erin) :-
        girl(erin)
     -> write('it is true')
     ;  write('it is not true'). 

这有两个原因是错误的。 Prolog试图以最左边的文字解析身体。 所以它基本上是一个循环“是erin女孩?是的,如果erin是女孩。是erin女孩吗?......”

第二个原因是你混合了两种不同的东西。尽量将您的知识表示部分与您使用它的方式分开。 在Prolog中你只需说:

girl(erin)

然后查询

?- girl(erin)

Prolog只会说“是”。如果要打印它,可能最简单的方法是添加谓词。

  

check_and_print(X): - X,写(X),写(“是真”)。

您可能需要调用(X)而不是 X ,具体取决于您使用的实现。

我不确定命令提示符,我怀疑结果会以不同的方式返回。