Nlp 对称二元谓词的基本一阶逻辑推理失败

Nlp 对称二元谓词的基本一阶逻辑推理失败,nlp,artificial-intelligence,nltk,theorem-proving,first-order-logic,Nlp,Artificial Intelligence,Nltk,Theorem Proving,First Order Logic,超基本问题。我试图表达两个二进制谓词(父谓词和子谓词)之间的对称关系。但是,通过下面的陈述,我的决议证明者允许我证明任何事情。转换后的CNF表格对我来说是有意义的,就像通过决议证明一样,但这应该是一个明显的错误案例。我错过了什么 forall x,y (is-parent-of(x,y) <-> is-child-of(y,x)) 下面是分辨率验证程序的快速修复 导致验证程序不健全的问题是,当存在多个互补文本时,它无法正确实现解析规则。例如,给定子句{abc}和{-A-bd}二进

超基本问题。我试图表达两个二进制谓词(父谓词和子谓词)之间的对称关系。但是,通过下面的陈述,我的决议证明者允许我证明任何事情。转换后的CNF表格对我来说是有意义的,就像通过决议证明一样,但这应该是一个明显的错误案例。我错过了什么

forall x,y (is-parent-of(x,y) <-> is-child-of(y,x)) 

下面是分辨率验证程序的快速修复

导致验证程序不健全的问题是,当存在多个互补文本时,它无法正确实现解析规则。例如,给定子句
{abc}
{-A-bd}
二进制解析将产生子句
{A-acd}
{B-bcd}
。两者都将作为重言式被丢弃。而当前的NLTK实现将生成
{cd}

这可能是因为NLTK中的子句表示为列表,因此在一个子句中相同的文本可能出现多次。当应用于子句
{A A}
{-A-A}
时,此规则确实正确地生成空子句,但一般来说,此规则是不正确的

看来,如果我们保持从句不重复相同的文字,我们可以通过一些改变来恢复健全

首先定义一个删除相同文本的函数

下面是这样一个函数的简单实现

将nltk.inference.resolution导入为res
定义(第条):
"""
从子句中删除重复的文本
"""
重复项=[]
对于枚举中的i,c(第条):
如果我有两份:
持续
对于枚举中的j,d(子句[i+1:],start=i+1):
如果j一式两份:
持续
如果c==d:
重复。追加(j)
结果=[]
对于枚举中的i,c(第条):
如果不是我,请一式两份:
结果.追加(第[i]条)
返回res.子句(结果)
现在我们可以将此函数插入
nltk.interference.resolution
模块的一些函数中

def\u iterate\u first\u fix(第一、第二、绑定、使用、跳过、最终确定\u方法、调试):
"""
这种方法有助于通过“自我”的术语进行移动
"""
debug.line('unified(%s,%s)%s%%(第一个、第二个绑定))
如果不是len(第一个)或non len(第二个):#如果不能执行更多的递归
返回finalize_方法(第一个、第二个、绑定、已使用、跳过、调试)
其他:
#探索这个“自我”原子
result=res._iterate_second(第一、第二、绑定、使用、跳过、最终确定方法、调试+1)
#跳过这个可能的“自我”原子
Newskiped=(跳过[0]+[第一个[0]],跳过[1])
result+=res._iterate_first(第一[1:],第二,绑定,使用,新闻剪辑,finalize_方法,调试+1)
尝试:
newbindings,newused,unused=res._unified_术语(第一[0],第二[0],绑定,已使用)
#找到了统一,就沿着这条统一路线前进
#将跳过的和未使用的术语放回原处,以便以后统一。
newfirst=第一个[1::+跳过的[0]+未使用的[0]
newsecond=秒[1::+跳过的[1]+未使用的[1]
#当“\u unified\u term()”成功时,我们立即返回
结果+=\u简化(最终确定方法(newfirst、newsecond、newbindings、newused、([]、[])、debug))
除res.BindingException外:
通过
返回结果
res.\u iterate\u first=\u iterate\u first\u fix
同样地,更新res._迭代_秒

def\u iterate\u second\u修复(第一、第二、绑定、使用、跳过、最终确定\u方法、调试):
"""
此方法有助于通过“其他”术语进行移动
"""
debug.line('unified(%s,%s)%s%%(第一个、第二个绑定))
如果不是len(第一个)或non len(第二个):#如果不能执行更多的递归
返回finalize_方法(第一个、第二个、绑定、已使用、跳过、调试)
其他:
#跳过此可能的配对并移动到下一个配对
Newskiped=(跳过[0],跳过[1]+[第二个[0]])
result=res._iterate_second(第一,第二[1:],绑定,使用,新闻剪辑,finalize_方法,debug+1)
尝试:
newbindings,newused,unused=res._unified_术语(第一[0],第二[0],绑定,已使用)
#找到了统一,就沿着这条统一路线前进
#将跳过的和未使用的术语放回原处,以便以后统一。
newfirst=第一个[1::+跳过的[0]+未使用的[0]
newsecond=秒[1::+跳过的[1]+未使用的[1]
#当“\u unified\u term()”成功时,我们立即返回
结果+=\u简化(最终确定方法(newfirst、newsecond、newbindings、newused、([]、[])、debug))
除res.BindingException外:
#原子不能统一,
通过
返回结果
res._iterate_second=_iterate_second\u fix
最后,将我们的函数插入
clausify()
,以确保输入无重复

def子句化_简化(表达式):
"""
使变量分离、从句化和标准化。
"""
子句_list=[]
对于条款化决议(表达)中的条款:
for free in子句。free():
如果res.is_indvar(free.name):
newvar=res.VariableExpression(res.unique_variable())
子句=子句。替换(免费,新变量)
子句列表追加(_简化(子句))
返回子句列表
res.clausify=clausify\u简化
在应用这些更改后,验证人应运行标准测试,并正确处理
parentof/childof
关系

print res.ResolutionProver().prove(q, [s], verbose=True)
输出:

[1] {-foo(Bar)}                             A 
[2] {-parentof(z9,z10), childof(z10,z9)}    A 
[3] {parentof(z11,z12), -childof(z12,z11)}  A 
[4] {}                                      (2, 3) 

True
[1] {-foo(Bar)}                                  A 
[2] {-parentof(z144,z143), childof(z143,z144)}   A 
[3] {parentof(z146,z145), -childof(z145,z146)}   A 
[4] {childof(z145,z146), -childof(z145,z146)}    (2, 3) Tautology
[5] {-parentof(z146,z145), parentof(z146,z145)}  (2, 3) Tautology
[6] {childof(z145,z146), -childof(z145,z146)}    (2, 3) Tautology

False
更新:实现正确性并不是故事的结尾。更有效的解决方案是将用于存储
子句
类中的文本的容器替换为基于内置Python哈希ba的容器
[1] {-foo(Bar)}                                  A 
[2] {-parentof(z144,z143), childof(z143,z144)}   A 
[3] {parentof(z146,z145), -childof(z145,z146)}   A 
[4] {childof(z145,z146), -childof(z145,z146)}    (2, 3) Tautology
[5] {-parentof(z146,z145), parentof(z146,z145)}  (2, 3) Tautology
[6] {childof(z145,z146), -childof(z145,z146)}    (2, 3) Tautology

False