pydatalog-入门教程
简介
Datalog是一种真正的声明性语言,源自Prolog。Datalog程序比Python等效程序短, Datalog语句可以以任何顺序指定。
pyDatalog可用于:
- 模拟智能行为(用于游戏或专家系统),
- 查询复杂的相关信息集(例如,在数据集成或自然语言处理中),
- 执行递归算法(例如在分层数据结构上)
教程
首先 导入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
- 点赞
- 收藏
- 关注作者
评论(0)