pydatalog-入门教程

举报
北纬30度 发表于 2021/06/29 19:18:51 2021/06/29
【摘要】 python pydatalog入门级操作

简介

Datalog是一种真正的声明性语言,源自Prolog。Datalog程序比Python等效程序短, Datalog语句可以以任何顺序指定。

pyDatalog可用于

  1. 模拟智能行为(用于游戏或专家系统),
  2. 查询复杂的相关信息集(例如,在数据集成或自然语言处理中),
  3. 执行递归算法(例如在分层数据结构上)

教程

首先 导入pyDatalog:

from pyDatalog import pyDatalog

变量和表达式

声明我们将使用的变量。它们必须是大写字母

pyDatalog.create_terms('X,Y')

变量出现在逻辑查询中,逻辑查询返回可打印结果

# give me all the X so that X is 1
print(X==1)
output:
X 
-
 1  

查询可以包含几个变量和几个条件(’&’ is read ‘and’)

# give me all the X and Y so that X is True and Y is False
print((X==True) & (Y==False))
output:
X    | Y     
-----|------ 
True | False  

每个等式周围的括号是必要的,以避免与(X==(True&Y)==False)混淆。

某些查询返回空结果:

# give me all the X so that X is 1
print(X==1)
output:
X 
-
 1 

除了数字和布尔值,变量还可以表示字符串。此外,查询可以包含python表达式:

# give me all the X and Y so that X is a name and Y is 'Hello ' followed by the first letter of X
print((X==raw_input('Please enter your name : ')) & (Y=='Hello ' + X[0]))
output:
Please enter your name : World 
X     | Y       
------|-------- 
World | Hello W  

变量还可以表示(嵌套)元组,这些元组可以参与表达式并被切片 (0-based)。

print((X==(1,2)+(3,)) & (Y==X[2]))
output:
X         | Y 
----------|-- 
(1, 2, 3) | 3  # give me all the X so that X is 1
print(X==1)
output:
X 
-
 1  

要在逻辑表达式中使用自己的函数,请在Python中定义它们,然后利用pyDatalog为它们创建逻辑术语:

def twice(a):
     return a+a
pyDatalog.create_terms('twice')
print((X==1) & (Y==twice(X))) 
output:
X | Y 
--|-- 
1 | 2 

pyDatalog变量可以传递给Python标准库中的函数:

# give me all the X and Y so that X is 2 and Y is the square root of X
import math
pyDatalog.create_terms('math')
print(X==2) & (Y==math.sqrt(X))
 
output:
X | Y             
--|-------------- 
2 | 1.41421356237  

循环

首先声明我们需要的变量: 可以使用.in()方法创建循环(稍后将看到还有其他方法可以创建循环):

from pyDatalog import pyDatalog
pyDatalog.create_terms('X,Y,Z')
# give me all the X so that X is in the range 0..4
print(X.in_((0,1,2,3,4)))
output:
X 
- 
0 
1 
3 
2 
4  # give me all the X so that X is 1
print(X==1)
output:
X 
-
 1  

该程序亦可实现循环

for x in range(5):
     print x
 
output:
0 
1 
2 
3 
4  

查询的结果是一组可能的解决方案,按随机顺序排列。每个解决方案对查询中的每个变量都有1个值。.data属性可以查看结果。

print(X.in_(range(5)).data)  
output:
[(0,), (1,), (2,), (3,), (4,)] 
print(X.in_(range(5)) == set([(0,), (1,), (2,), (3,), (4,)]))
output:
True 

在查询之后,变量包含其所有可能值的元组。可以使用以下方法访问它们:

print("Data : ",X.data) 
('Data : ', [1, 0, 4, 2, 3])
print("First value : ",  X.v())
('First value : ', 1)
# below, '>=' is a variable extraction operator

print("Extraction of first value of X: ", X.in_(range(5)) >= X)
('Extraction of first value of X: ', 2) 

“&”运算符可用于筛选结果。

# give me all X in range 0..4 that are below 2
print(X.in_(range(5)) & (X<2))
output:
X 
- 
1 
0 

循环可以很容易地嵌套。

# give me all X, Y and Z so that X and Y are in 0..4, Z is their sum, and Z is below 3
print(X.in_(range(5)) &
           Y.in_(range(5)) &
               (Z==X+Y) &
               (Z<3))
output:
X | Y | Z 
--|---|-- 
0 | 1 | 1 
1 | 1 | 2 
1 | 0 | 1 
0 | 2 | 2 
0 | 0 | 0 
2 | 0 | 2  

逻辑函数和字典

例如,我们将计算员工foo和bar的净工资。 请注意,逻辑函数名称,如工资,以小写开头。 函数为给定参数定义一个值。它类似于python字典。 可以查询函数。

from pyDatalog import pyDatalog
pyDatalog.create_terms('X,Y,Z, salary, tax_rate, tax_rate_for_salary_above, net_salary')
salary['foo'] = 60
salary['bar'] = 110
# give me all the X and Y so that the salary of X is Y
print(salary[X]==Y)
output:
X   | Y   
----|---- 
bar | 110 
foo | 60   
# python equivalent:
_salary = dict()  
_salary['foo'] = 60
_salary['bar'] = 110
print(_salary.items())
output:
[('foo', 60), ('bar', 110)] 

函数对于给定的参数只有一个值。

# foo now has a salary of 70
salary['foo'] = 70
print(salary['foo']==Y)
output:
Y  
-- 
70 
# Python equivalent
_salary['foo'] = 70
print('foo --> ' + str(_salary['foo']))
output:
foo --> 70   

函数也可以按值查询。

# give me all the X that have a salary of 110
print(salary[X]==110)
output:
X   
--- 
bar
# procedural equivalent in python
for i, j in _salary.items():
     if j==110:
         print i, '-->', j
output:
bar --> 110 

请注意,查询中存在隐式循环。 查询可以测试条件的否定。

print((salary[X]==Y) & ~(Y==110)) 
output:
X   | Y  
----|--- 
foo | 70 

现在让我们定义一个全球税率。我们将对函数参数使用“无”:

# the standard tax rate is 33%
+(tax_rate[None]==0.33)

函数可以在公式中调用:

# give me the net salary for all X
print((Z==salary[X]*(1-tax_rate[None]))) 
output:
X   | Z    
----|----- 
foo | 46.9 
bar | 73.7  # give me all the X so that X is 1
print(X==1)
output:
X 
-
 1 

在这种情况下,X受salary[X]的约束,因此可以计算表达式。

函数也可以由子句定义。以下是一个简单的例子:

# the net salary of X is Y if Y is the salary of X, reduced by the tax rate
net_salary[X] = salary[X]*(1-tax_rate[None])

# give me all the X and Y so that Y is the net salary of X
print(net_salary[X]==Y)
output:
X   | Y    
----|----- 
bar | 73.7 
foo | 46.9
# procedural equivalent in Python
for i,j in _salary.items():
     k = j*(1-0.33)
     print i, k
output:
foo 46.9 
bar 73.7  

同样,这样的函数可以按值查询

# give me the net salary of foo
print(net_salary['foo']==Y)
output:
Y    
---- 
46.9  
print(net_salary[Y]<50)
output:
 Y   
--- 
foo 

现在让我们定义一个累进税制度:默认税率为33%,但工资超过100的税率为50%。

# the tax rate for salaries above 0 is 33%, and above 100 is 50 %
(tax_rate_for_salary_above[X] == 0.33) <= (0 <= X)
(tax_rate_for_salary_above[X] == 0.50) <= (100 <= X)
print(tax_rate_for_salary_above[70]==Y)
output:
Y    
---- 
0.33  
print(tax_rate_for_salary_above[150]==Y)
output:
Y   
--- 
0.5

“<=”是上面语句中的重要标记:它被读取为“if”。 首先给出函数的最一般定义。搜索可能的答案时,pyDatalog从定义的最后一条规则开始,即更具体的规则,并在找到函数的有效答案后立即停止。因此,即使这两条规则似乎适用于150的工资,但第二条规则实际上是用来获得50%的工资 现在让我们重新定义净工资。在我们这样做之前,我们需要收回我们最初的定义:

# retract our previous definition of net_salary
del net_salary[X] 

以下是新的定义;

net_salary[X] = salary[X]*(1-tax_rate_for_salary_above[salary[X]])
# give me all X and Y so that Y is the net salary of X
print(net_salary[X]==Y)
output:
X | Y
----|-----
foo | 46.9
bar | 55.0

请注意,我们在上面使用了f[X]=<expr>,作为(f[X]==Y) <= (Y==expr)的较短表示法。 这种简短的符号,再加上函数可以按任何顺序定义的事实,使编写pyDatalog程序就像创建电子表格一样容易。

pyDatalog.create_terms('factorial, N')
factorial[N] = N*factorial[N-1]
factorial[1] = 1
print(factorial[3]==N)

output:
N 
- 
6
【版权声明】本文为华为云社区用户翻译文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容, 举报邮箱:cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。