用纯python实现的可嵌入prolog方言。使用sqlalchemy存储知识库以获得可伸缩性。
zamia-prolog的Python项目详细描述
#zamia prolog
用于zamia prolog(prolog方言)的可伸缩且可嵌入的编译器/解释器。通过sqlalchemy将其知识库存储在
数据库中,因此具有可伸缩性,即知识库不受可用ram数量的限制。
具有用于注册自定义内置项的接口,这些内置项可以在编译时(在
zamia prolog中称为指令)或运行时计算。
prolog核心基于chris meyers的http://openbookproject.net/py4fun/prolog/prolog3.html。
曼斯绝对是很重要的,现在克里斯的判读方式已经足够满足我的需要了。
我在这里的主要关注点是嵌入和语言特性-在撰写本文时,我正在尝试将一些命令式概念合并到zamia prolog中,例如可重分配变量和if/then/else构造。
请注意,这是一种prolog方言,可能永远不会符合任何prolog标准。相反,它很可能会偏离标准的prolog,并可能演变成我自己的基于逻辑的语言。
s
*具有完全回溯支持的可重分配变量
*具有完全回溯支持的assertz/retract(使用数据库覆盖)
*命令式语言结构,如if/then/else
*伪变量/-使db assertz/retractz更易于编码的谓词
ts
==
*注意*:可能不完整。
*python 2.7
*py nltools
*sqlalchemy
==usage
compile`hanoi1.pl`示例:
``python
from zamiaprolog.logicdb import logicdb
from zamiaprolog.parser import prologparser
db=logicdb(db_url)
parser=prologparser()
parser.compile_file('samples/hanoi1.pl','unittests',db)
```````
使用"body('move(3,left,right,center)')
rt=prologruntime(db)
solutions=rt.search(子句)
`````
输出:
`````
从左到右移动顶部磁盘
从左到中移动顶部磁盘
/>将顶部磁盘从中心向左移动
将顶部磁盘从中心向右移动
将顶部磁盘从左向右移动
````
从python访问prolog变量
--------
解决方案=rt.search(子句,{'x':numberliteral(3)}
```
>检查解决方案数:
``python
``打印len(解决方案)
```
``` ` `
``` ` ` `
` ` ` `
` ` ` ` `
` ` ` ` `
` ` ` ` ` ` ` `
` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `
o输出:
```
9
```
移动量=[[]
def记录移动量(g,rt):
全局记录移动量
pred=g.terms[g.inx]
args=pred.args
arg from=rt.prolog_eval(args[0],g.env)
arg to=rt.prolog_eval=rt.prolog_eval(args[1],g.env)
reco记录的移动量.附加((arg from,arg from,arg from,arg(到)
返回true
rt.register_builtin('record_move',record_move)
````
>现在,编译并运行"hanoi2.pl"示例:
``` python
parser.compile_file('samples/hanoi2.pl','unittests',db)
clause=parser.parse_line_clause_body('move(3,left,right,center)')
solutions=rt.search(clause)
`````
输出:
`````
从左到右移动顶部磁盘
从左到中移动顶部磁盘
k从右到中
从左到右移动顶盘
从中到左移动顶盘
从中到右移动顶盘
从左到右移动顶盘
``````
现在,检查记录的移动:
``python
打印长度(记录的移动)
打印重复(记录的移动)
```
输出:
```
7
[(谓词(左),谓词(右)),(谓词(左),谓词(中)),(谓词(右),谓词(中)),(谓词(左),谓词(右)),(谓词(中),谓词(左)),(谓词(中),谓词(左)),(谓词(中),谓词(右)),(谓词(左),谓词(右))]/>```
rt):
rt.u trace('called builtin custom_pred1',g)
args=pred.args
如果len(args)!=1:
raise prologruntimeerror('custom pred1:1 arg expected.')
arg var=rt.prolog_get_变量(args[0],g.env)
return truen每个prolog结果一个。在本例中,
我们生成4个绑定,每个绑定包含两个变量:
`` python
def multi-u binder(g,rt):
=2:
提升序言运行时错误(需要多个绑定器:2个参数)。
var廑y=rt.prolog廑u变量(args[1],g.env)
res[]
对于范围(2)中的x,x:
对于范围(2)中的y:
ly=numberinteral(y)
res.append({var_x:lx,var_y:ly})
return res
``````
,因此运行
``python
clause=self.parser.parse_Line_body('multi_binder(x,y)')
solutions=self.rt.search(clause)
```
`生成4个解决方案:
``
[{u'y':0,u'x':0},{u'y':1,u'x':0},{u'y':0,u'x':1},{u'y':1,u'x':1}
````
custom compiler directives
>
除了自定义内置,我们还可以在zamia prolog中使用自定义编译器指令。指令在编译时被求值,并且不会存储在数据库中。
下面是一个示例:首先,注册自定义指令:
``python
def\u自定义指令(模块名、子句、用户数据):
print"\u自定义指令已被调用。子句:%s user_data:%s"%(子句,user_data)
parser.register_directive('custom_directive','u custom_directive,none)
````
现在,编译一段使用该指令的prolog代码:
```python
parse_line_子句('custom_directive(abc,42,\'foo'.)。)
```
输出:
```
u已调用自定义指令。条款:自定义指令(ABC,42.0,"foo")。用户数据:无
[]
```
可重新分配的变量
——
>可以使用内置的特殊"集合"重新分配变量(`:=`):
````prolog
z:=23,z:=42
````
这带有完全的回溯支持。
pseudo variables/-predicates
----
这是对zamia prolog中的标准prolog语法的扩展,使"变量"设置和访问变得更容易:
```
c:user->;user(c,x)
c:user:name->;user(c,x,x),name(x,y)
self:name->;name(self,x)
self:label de->;label(self,de,x)
`````
c:user->;user(c,x)
c:user->;user(x,x,x)
c:user->;user(c,x)
c:user->;user(x,x)
self self:label de->;label(se),巴:foo:=42,z:=bar:foo
````
将导致数据库中的` z==42`和` foo(bar,42)`断言。
if/then/thethen/else/endif
prolog
或(and(foo(bar)、do1、do2)和(not(foo(bar)),do2,do3))
```
license
==
有关详细信息,请确保检查内部的
版权标题。
author
==
*guenter bartsch<;guenter@zamia.org>;
*chris meyers.
*heiko sch_fer<;heiko@schaefer.name>;
用于zamia prolog(prolog方言)的可伸缩且可嵌入的编译器/解释器。通过sqlalchemy将其知识库存储在
数据库中,因此具有可伸缩性,即知识库不受可用ram数量的限制。
zamia prolog中称为指令)或运行时计算。
prolog核心基于chris meyers的http://openbookproject.net/py4fun/prolog/prolog3.html。
曼斯绝对是很重要的,现在克里斯的判读方式已经足够满足我的需要了。
我在这里的主要关注点是嵌入和语言特性-在撰写本文时,我正在尝试将一些命令式概念合并到zamia prolog中,例如可重分配变量和if/then/else构造。
请注意,这是一种prolog方言,可能永远不会符合任何prolog标准。相反,它很可能会偏离标准的prolog,并可能演变成我自己的基于逻辑的语言。
s
*具有完全回溯支持的可重分配变量
*具有完全回溯支持的assertz/retract(使用数据库覆盖)
*命令式语言结构,如if/then/else
*伪变量/-使db assertz/retractz更易于编码的谓词
ts
==
*注意*:可能不完整。
*python 2.7
*py nltools
*sqlalchemy
==usage
compile`hanoi1.pl`示例:
``python
from zamiaprolog.logicdb import logicdb
from zamiaprolog.parser import prologparser
parser=prologparser()
parser.compile_file('samples/hanoi1.pl','unittests',db)
```````
使用"body('move(3,left,right,center)')
rt=prologruntime(db)
solutions=rt.search(子句)
`````
输出:
`````
从左到右移动顶部磁盘
从左到中移动顶部磁盘
/>将顶部磁盘从中心向左移动
将顶部磁盘从中心向右移动
将顶部磁盘从左向右移动
````
从python访问prolog变量
--------
解决方案=rt.search(子句,{'x':numberliteral(3)}
```
>检查解决方案数:
``python
``打印len(解决方案)
```
``` ` `
``` ` ` `
` ` ` `
` ` ` ` `
` ` ` ` `
` ` ` ` ` ` ` `
` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `
o输出:
```
9
```
移动量=[[]
def记录移动量(g,rt):
全局记录移动量
pred=g.terms[g.inx]
args=pred.args
arg from=rt.prolog_eval(args[0],g.env)
arg to=rt.prolog_eval=rt.prolog_eval(args[1],g.env)
reco记录的移动量.附加((arg from,arg from,arg from,arg(到)
返回true
rt.register_builtin('record_move',record_move)
````
>现在,编译并运行"hanoi2.pl"示例:
``` python
parser.compile_file('samples/hanoi2.pl','unittests',db)
clause=parser.parse_line_clause_body('move(3,left,right,center)')
solutions=rt.search(clause)
`````
输出:
`````
从左到右移动顶部磁盘
从左到中移动顶部磁盘
k从右到中
从左到右移动顶盘
从中到左移动顶盘
从中到右移动顶盘
从左到右移动顶盘
``````
现在,检查记录的移动:
``python
打印长度(记录的移动)
打印重复(记录的移动)
```
输出:
```
7
[(谓词(左),谓词(右)),(谓词(左),谓词(中)),(谓词(右),谓词(中)),(谓词(左),谓词(右)),(谓词(中),谓词(左)),(谓词(中),谓词(左)),(谓词(中),谓词(右)),(谓词(左),谓词(右))]/>```
rt):
rt.u trace('called builtin custom_pred1',g)
如果len(args)!=1:
raise prologruntimeerror('custom pred1:1 arg expected.')
arg var=rt.prolog_get_变量(args[0],g.env)
return truen每个prolog结果一个。在本例中,
我们生成4个绑定,每个绑定包含两个变量:
`` python
def multi-u binder(g,rt):
=2:
提升序言运行时错误(需要多个绑定器:2个参数)。
var廑y=rt.prolog廑u变量(args[1],g.env)
res[]
对于范围(2)中的x,x:
对于范围(2)中的y:
ly=numberinteral(y)
res.append({var_x:lx,var_y:ly})
return res
``````
,因此运行
``python
clause=self.parser.parse_Line_body('multi_binder(x,y)')
solutions=self.rt.search(clause)
```
`生成4个解决方案:
``
[{u'y':0,u'x':0},{u'y':1,u'x':0},{u'y':0,u'x':1},{u'y':1,u'x':1}
````
custom compiler directives
>
除了自定义内置,我们还可以在zamia prolog中使用自定义编译器指令。指令在编译时被求值,并且不会存储在数据库中。
下面是一个示例:首先,注册自定义指令:
``python
def\u自定义指令(模块名、子句、用户数据):
print"\u自定义指令已被调用。子句:%s user_data:%s"%(子句,user_data)
parser.register_directive('custom_directive','u custom_directive,none)
````
现在,编译一段使用该指令的prolog代码:
```python
parse_line_子句('custom_directive(abc,42,\'foo'.)。)
```
输出:
```
u已调用自定义指令。条款:自定义指令(ABC,42.0,"foo")。用户数据:无
[]
```
可重新分配的变量
——
>可以使用内置的特殊"集合"重新分配变量(`:=`):
````prolog
z:=23,z:=42
````
这带有完全的回溯支持。
pseudo variables/-predicates
----
这是对zamia prolog中的标准prolog语法的扩展,使"变量"设置和访问变得更容易:
```
c:user->;user(c,x)
c:user:name->;user(c,x,x),name(x,y)
self:name->;name(self,x)
self:label de->;label(self,de,x)
`````
c:user->;user(c,x)
c:user->;user(x,x,x)
c:user->;user(c,x)
c:user->;user(x,x)
self self:label de->;label(se),巴:foo:=42,z:=bar:foo
````
将导致数据库中的` z==42`和` foo(bar,42)`断言。
if/then/thethen/else/endif
prolog
或(and(foo(bar)、do1、do2)和(not(foo(bar)),do2,do3))
```
license
==
有关详细信息,请确保检查内部的
版权标题。
author
==
*guenter bartsch<;guenter@zamia.org>;
*chris meyers.
*heiko sch_fer<;heiko@schaefer.name>;