如何显示的模式匹配的目标与几个自由变量在SWI-Prolog的从shell调用的结果?(How do

2019-07-30 17:19发布

让我们用下面的序言基地:

father(anakinSkywalker, princessLeia).
father(anakinSkywalker, lukeSkywalker).
saysOhNo(lukeSkywalker).

sdesciencelover问如何显示的模式匹配的目标结果的SWI,序言从shell调用,并得到一个答案的查询给人一种人工改造,isue写。

swipl -q -s kb.pl -t "father(anakinSkywalker,X), writeln(X), false"

结果:

princessLeia
lukeSkywalker

这工作得很好,当一个只与一个自由变量几个疑问,但手动将每个一个很乏味,如果我们希望与每个变量的名称正确的输出,其结果一起,它很快变得很烦人。 例如运行查询father(AVariable, Another) ,一个需要写:

swipl -q -s kb.pl -t "father(AVariable,Another), write('AVariable='), write(AVariable), write(', Another='), writeln(Another), false"

结果:

AVariable=anakinSkywalker, Another=princessLeia
AVariable=anakinSkywalker, Another=lukeSkywalker

我试图从管道给它的命令,但它不工作的伟大(当它已经写完的结果我无法检测,所以它只是挂起之后,并没有换行分隔的答案):

(echo "father(X,Y)."; while true; do echo ";"; done) | swipl -q -s kb.pl

结果:

X = anakinSkywalker,
Y = princessLeia X = anakinSkywalker,
Y = lukeSkywalker.

swipl hangs here, and needs to be stopped with Control-C.

我知道我可以使用sed脚本预先处理的查询,添加必要的代码来打印大写字母的变量,但它需要的工作有相当多的复杂的查询工作,例如在两个谓词必须满足:

father(X,Y), saysOhNo(Y).

要始终给出正确的结果,一个需要写序言解析器,这将是无用的工作,因为序言已经知道如何以交互方式做到这一点。

因此,这里是我的问题:有没有办法告诉GNU序言或SWI序言(或可以在Linux上轻松安装任何其他的免费版本)运行一些查询和打印结果,就像他们会以交互方式做,但不要求我输入(或复制粘贴)用手每个查询?

编辑:一种方法来存储一系列查询在一个文件中(无论是在kb.pl文件或辅助文件),并运行它们,可见其效果会更好。

Answer 1:

您可以使用命令行选项--query-goal在GNU。 像这样:

$ echo a| gprolog --query-goal 'X = 1 ; X =2'
GNU Prolog 1.4.1
By Daniel Diaz
Copyright (C) 1999-2012 Daniel Diaz
| ?- X = 1 ; X =2.

X = 1 ? a

X = 2

yes


Answer 2:

到目前为止,这里是我发现的方法:

gprolog

使用虚假的答案 ,我发现有一个必须在顶部添加一行kb.pl文件:

a(_) :- fail.

然后用./query.sh kb.pl "father(X,Y), saysOhNo(Y)"其中query.sh是:

#!/bin/sh
echo "a(fail)." | gprolog --query-goal "consult('$1'), $2"

当查询立即返回(即没有结果或一个结果和gprolog管理,以检测它是最后一个),这将运行查询consult('kb.pl'), actual_query. ,然后运行查询a(fail). 这将简单地打印的外来no在控制台上,这要归功于我们在文件的顶部添加了总是假的谓词。

gprolog问做什么(即多个结果,或一个结果和gprolog无法检测到它是最后一个),这将运行查询consult('kb.pl'), actual_query. ,读a它要求gprolog打印所有结果,然后它会运行查询(fail). 这将简单地打印的外来no在控制台上,因为这些都只是分组括号,所以查询等同于fail.

xsb

人们可以使用./query.sh kb.pl "father(X,Y), saysOhNo(Y)"其中query.sh是:

#!/bin/sh
(echo "consult('$1'), ${2%.}."; yes halt.) | xsb --noprompt --quietload --nobanner

xsb询问下一步该怎么做,如果用户键入一个非空字符串,然后enter ,将打印下一个结果,否则将停止搜索解决方案,以当前查询。 因此,在yes halt. 命令,我们类型的非空行无限流。 xsb将打印所有结果查询(每次读halt. ,所以它是一个非空字符串,它会在下一结果继续),并返回到它的提示。 接着,下面的halt. 它接收会告诉它退出。

swi-prolog

我还没有找到一个解决办法。

[言论]这一切会这么简单得多,如果人民建设序言实现真正想过用他们非交互,比如它可能与大多数其他语言。[/言论]



Answer 3:

你可能会发现你的问题的解决方案,但无论如何,在这里不用我的方法。 您可以随时递归到bagof内置谓词。 你可以看它做什么的文档,这样你会更多地了解它。

swipl -q -s starwars.pl -t "bagof(X, Y^father(X,Y), BagOfFathers), bagof(Y, X^father(X,Y), BagOfChildren), writeln(BagOfFathers), writeln(BagOfChildren)."
[anakinSkywalker,anakinSkywalker]
[princessLeia,lukeSkywalker]

您也可以处理它以后,只要你想映射或什么的,关系是1:1(不知道是否是说明它的正确的方式,但我希望你能得到它)



Answer 4:

您可以使用SWI-序言以下bash脚本:

#!/bin/sh

exec swipl -q  -f none -g "load_files([interface],[silent(true)])" \
         -t interface:get_args -- $*

这将加载该文件interface.pl并调用谓词get_args/0
得到命令行参数,你可以拨打:

current_prolog_flag(argv, Arguments)

当然,你可以改变谓词的名称/文件加载。
silent(true)参数抑制信息消息如介绍文字

编辑:您收到错误消息,因为你可能不具有interface.pl文件(既不是get_args / 0谓词)。 你将不得不更换interfacekb (或者无论你命名的文件)和interface:get_argskb:father(X,Y), saysOhNo(Y) 你的序言文件中使用的辅助谓词,如run(X,Y):- father(X,Y), saysOhNo(Y)其可以是有点儿清洁器)



文章来源: How do I show the results of pattern-matching goals with several free variables in SWI-Prolog from a shell invocation?