pyDatalog: python的逻辑编程引擎【四:从文件中加载和执行程序】

2019-10-30 19:10:14 浏览数 (1)

之前的教程中,所有的操作,包括定义数据等都是在python里面进行的。但是当我们处理庞大的知识库的时候,我们肯定不希望把所有的数据都写在一个py文件里,而是希望把它存在更通用的保存数据的文件格式/数据库里面,在需要的时候再让程序来读取就好了。

pyDatalog可以做到这些功能。下面是关于从文件中读取pyDatalog程序,我自己写的简单例子:

In [1]:

代码语言:javascript复制
from pyDatalog import pyDatalog

def run_program():
    # 创建一个简单的Datalog程序文件
    text0 = "factorial[N] = N*factorial[N-1]nfactorial[1] = 1"
    with open("sample_datalog_program.txt", 'w') as f:
        f.write(text0)
        
    file_in = open("sample_datalog_program.txt", 'r')
    mc = file_in.read()
    print(mc)
    pyDatalog.load(mc)
    file_in.close()
    print(pyDatalog.ask('factorial[3]==N'))         # 执行语句,注意这里不需要预先create_terms

if __name__ == "__main__":
    run_program()
代码语言:javascript复制
factorial[N] = N*factorial[N-1]
factorial[1] = 1
{(6,)}

这一部分功能,官网上称之为:

动态Datalog语句

因为一些应用可能需要动态创建和执行Datalog语句(比如实时),这时就可以使用这些指令。下面的例子给出了所有动态Datalog语句的接口:

In [2]:

代码语言:javascript复制
from pyDatalog.pyDatalog import assert_fact, retract_fact, load, ask
from pyDatalog import pyDatalog

# load(string): 从字符中加载Datalog语句
load("""
      parent('Kangxi', 'Yongzheng')
      parent('Yongzheng', 'Qianlong')
    ancestor(X,Y) <= parent(X,Y)
    ancestor(X,Y) <= parent(X,Z) & ancestor(Z,Y)
    """)
# assert_fact(string,不限量任意参数): 添加事实
assert_fact('parent', 'Qianlong','Jiaqing')
# 相当于 '  parent('Qianlong', 'Jiaqing') '

# ask: 通过字符串执行指令,并把answer作为元组返回
print(ask("ancestor('Kangxi',Y)")) 

# assert_fact(string,不限量任意参数): 删除事实
retract_fact('parent', 'Qianlong','Jiaqing')
# 相当于 '- parent('Qianlong', 'Jiaqing')
代码语言:javascript复制
print(ask("ancestor('Kangxi',Y)")) 
代码语言:javascript复制
{('Jiaqing',), ('Yongzheng',), ('Qianlong',)}
{('Yongzheng',), ('Qianlong',)}

有了这些操作,我们就可以想一些办法来处理更通用的数据格式了,比如说Excel表格(这里使用pandas的DataFrame演示一个简单例子):

In [3]:

代码语言:javascript复制
import pandas as pd
pyDatalog.clear()   #清空前面学到的事实
# 简单的表示关系的数据表
data = pd.DataFrame({"object":['Kangxi','Yongzheng','Qianlong'],
                     "relation":['parent','parent','parent'],
                     "subject":['Yongzheng','Qianlong','Jiaqing']})
print(data)
代码语言:javascript复制
      object relation    subject
0     Kangxi   parent  Yongzheng
1  Yongzheng   parent   Qianlong
2   Qianlong   parent    Jiaqing

In [4]:

代码语言:javascript复制
# 数据表转为Datalog语句
data_str = ""
for line_id,line in data.iterrows():
    obj,rela,subj = line["object"],line["relation"],line["subject"]
    data_str  = "  %s('%s','%s')n" % (rela,obj,subj)
print(data_str)
load(data_str)
代码语言:javascript复制
  parent('Kangxi','Yongzheng')
  parent('Yongzheng','Qianlong')
  parent('Qianlong','Jiaqing')

In [5]:

代码语言:javascript复制
# 规则与数据分离
rules = """
    ancestor(X,Y) <= parent(X,Y)
    ancestor(X,Y) <= parent(X,Z) & ancestor(Z,Y)
    """
load(rules)
print(ask("ancestor(X,Y)")) 
代码语言:javascript复制
{('Kangxi', 'Yongzheng'), ('Qianlong', 'Jiaqing'), ('Yongzheng', 'Jiaqing'), ('Yongzheng', 'Qianlong'), ('Kangxi', 'Jiaqing'), ('Kangxi', 'Qianlong')}

0 人点赞