我对使用Natural Language ToolKit(NLTK)有疑问。我正在尝试创建一个应用程序,以便将自然语言问题翻译成它的逻辑表示,并查询数据库。
在nltk.sem.logic包下使用simplify()方法后得到的结果,得到以下表达式:
exists z2.(owner(fido, z2) & (z0 = z2))
但我需要的是简化它如下:
owner(fido, z0)
还有其他方法可以减少我想要的句子吗?
答案 0 :(得分:4)
在NLTK中,simplify()
执行beta缩减(according to the book),这不是您所需要的。当你应用某些策略时,你所要求的只能用定理证明。在这种情况下,你需要知道你期望得到什么,或者你知道可以应用什么样的公理来获得这样的结果。
NLTK中的定理证明器是Prover9,它提供了检查蕴涵关系的工具。基本上,您只能检查是否存在从表达式(前提)列表到目标表达式的步骤数量有限的证明。例如,在您的情况下,结果如下:
============================== PROOF =================================
% -------- Comments from original proof --------
% Proof 1 at 0.00 (+ 0.00) seconds.
% Length of proof is 8.
% Level of proof is 4.
% Maximum clause weight is 4.
% Given clauses 0.
1 (exists x (owner(fido,x) & y = x)) # label(non_clause). [assumption].
2 owner(fido,x) # label(non_clause) # label(goal). [goal].
3 owner(fido,f1(x)). [clausify(1)].
4 x = f1(x). [clausify(1)].
5 f1(x) = x. [copy(4),flip(a)].
6 -owner(fido,c1). [deny(2)].
7 owner(fido,x). [back_rewrite(3),rewrite([5(2)])].
8 $F. [resolve(7,a,6,a)].
============================== end of proof ==========================
在NLTK python中:
from nltk import Prover9
from nltk.sem import Expression
read_expr = Expression.fromstring
p1 = read_expr('exists z2.(owner(fido, z2) & (z0 = z2))')
c = read_expr('owner(fido, z0)')
result = Prover9().prove(c, [p1])
print(result)
# returns True
<强>更新强>
如果您坚持在python中使用可用工具,并且希望使用正则表达式手动检查此特定模式。你可以用正则表达式做这样的事情(我不赞成,但让我们尝试一下我讨厌的策略):
def my_nasty_tactic(exp):
parameter = re.findall(r'exists ([^.]*)\..*', exp)
if len(parameter) == 1:
parameter = parameter[0]
substitution = re.findall(r'&[ ]*\([ ]*([^ ]+)[ ]*=[ ]*'+parameter+r'[ ]*\)', exp)
if len(substitution) == 1:
substitution = substitution[0]
exp_abs = re.sub(r'exists(?= [^.]*\..*)', "\ ", exp)
exp_abs = re.sub(r'&[ ]*\([ ]*' + substitution + '[ ]*=[ ]*'+parameter+r'[ ]*\)', '', exp_abs)
return read_expr('(%s)(%s)' % (exp_abs, substitution)).simplify()
然后你可以像这样使用它:
my_nasty_tactic('exists z2.(owner(fido, z2) & (z0 = z2))')
# <ApplicationExpression owner(fido,z0)>