使用 Z3 Solver 在块世界模型中调试传递闭包

问题描述 投票:0回答:1

这是代码及其用途的扩展描述:

代码说明

此代码使用 Z3 求解器来模拟块世界的逻辑模型。积木世界是一个经典的人工智能规划领域,其中积木可以根据一定的规则和约束进行堆叠或操作。在该模型中,表示了四个块(A、B、C、D),并定义了它们之间的各种属性和关系来模拟块环境的状态。

该代码的主要目标是:

  1. 定义一个状态:它指定一个初始排列,其中

    D
    C
    上,
    C
    B
    上,
    B
    A
    上,
    A
    在桌子上。块
    A
    是绿色的,手是空的,块
    D
    是透明的(上面没有任何东西)。

  2. 建立条件和约束:它定义了要检查的条件:

    • 是否存在传递关系(传递闭包
      TC_On
      )允许从任何块到块
      A
      的路径。
    • 区块
      A
      是否已被收集。

    添加额外的约束来表示块世界中的规则,例如:

    • 一个区块不能同时位于两个区块上。
    • 如果一个块位于另一个块上,则它不是“在桌子上”。
    • 收集到的方块不能“清除”或“在桌子上”。
  3. 检查条件:代码根据定义的状态和约束验证

    proof_formulas
    中的每个条件。它使用 Z3 的
    Solver
    来确定在给定初始设置的情况下是否可以满足每个条件。

  4. 调试传递闭包问题:存在一个问题,传递闭包

    TC_On(x, A)
    预期为
    True
    ,但事实并非如此。该代码输出每个条件是否满足,有助于确定约束中是否存在冲突或
    TC_On
    的解释方式是否存在问题。

此设置允许测试块世界模型中的逻辑条件,并为验证自动推理系统中的规划约束提供基础。

from z3 import *

Block, (A, B, C, D) = EnumSort('Block', ('A', 'B', 'C', 'D'))
x, y, z = Consts("x y z", Block)

ontable=Function('ontable', Block, BoolSort())
clear=Function('clear', Block, BoolSort())
green=Function('green', Block, BoolSort())
collected=Function('collected', Block, BoolSort())
holding=Function('holding', Block, BoolSort())
handempty=Bool('handempty')
On = Function('On', Block, Block, BoolSort())
TC_On = TransitiveClosure(On)


state = And(
    clear(D), On(D, C), On(C, B), On(B, A), ontable(A), green(A), handempty
)

conditions=[
    TC_On(x,A),
    collected(A)
]

proof_formulas=[
    Exists([x], Implies(state, TC_On(x,A))),
    Implies(state, collected(A))
]

solver = Solver()

solver.add(state)

# solver.add()
solver.add(ForAll([x,y,z], Implies(And(On(y,x), On(z,x)), y==z)))
solver.add(ForAll([x,y,z], Implies(And(On(x,y), On(x,z)), y==z)))
solver.add(ForAll([x,y], And(On(x, y), Not(ontable(x)))))
solver.add(ForAll([x,y,z], Implies(And(On(x,y), On(y,z)), On(x,z))))#
solver.add(ForAll([x,y], And(On(y, x), Not(clear(x)))))

solver.add(ForAll([x], And(collected(x), Not(clear(x)))))
solver.add(ForAll([x], And(collected(x), Not(ontable(x)))))
solver.add(ForAll([x,y], And(On(y, x), Not(collected(x)))))
solver.add(ForAll([x,y], And(On(x, y), Not(collected(x)))))

print("For state: ", state)
print()

for (condition, proof_formula) in zip(conditions, proof_formulas):
    solver.push()
    solver.add(proof_formula)

    if solver.check() == sat:
        print("  satisfied :", condition)
        model = solver.model()
        try:
            print("   ", model.evaluate(condition))
        except Exception as e:
            print("    Error in model evaluate: ", e)
    else:
        print("  unsatisfied:", condition)

    solver.pop()
print()

为什么当我使用Z3求解器求传递闭包时答案不正确?应该是真的。

希望得到答复。

z3py planning transitive-closure
1个回答
0
投票

旁注:这看起来像是一个自动生成的 z3 程序,来自 chat-gpt 或类似程序。与往常一样,虽然该程序看起来和听起来都很合理,但它却充满了错误。堆栈溢出是为了帮助人们解决自己的编程问题,而不一定是调试 AI 输出。从 AI 输出开始是完全可以的,但是在将其转储到堆栈溢出之前,您需要对其进行处理。

为了让您开始,这是第一个有问题的约束:

solver.add(ForAll([x,y], And(On(x, y), Not(ontable(x)))))

这表示对于所有区块

x
y
x
必须位于
y
上;而且,
x
不能出现在桌子上。显然这是不能令人满意的。这里的约束是如果一个块位于另一个块之上,那么它就不能出现在桌子上。你应该这样写:

solver.add(ForAll([x,y], Implies(On(x, y), Not(ontable(x)))))

希望这能让您开始。但要强调的是,虽然从自动生成的脚本开始很好,但请不要在没有先自己研究的情况下逐字发布。自动生成的程序通常充满错误,直接将它们作为问题(或更糟糕的是答案!)发布在堆栈溢出上是不合适的。

© www.soinside.com 2019 - 2024. All rights reserved.