You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现逻辑语句的同时替换?解决分步替换覆盖问题

逻辑语句同时替换的实现方案

问题描述

需要实现逻辑语句的符号替换功能,通过映射{B=¬(C), C=B}将语句(B → (C → B))转换为(¬(C) → (B → ¬(C)))。但采用分步替换(先替换B,再替换C)会导致已替换的内容被二次修改,输出错误结果(¬(B) → (B → ¬(B)))。

解决方案

核心思路是基于原始AST节点进行一次性替换,遍历每个节点时直接查询映射表完成替换,避免分步替换带来的干扰。修改各类的subs方法,使其接受一个字典类型的映射参数,而非单个目标-替换对。

修改后的完整代码

from dataclasses import dataclass

@dataclass(frozen=True)
class Symb: pass 

@dataclass(frozen=True)
class PrimConn(Symb): pass

@dataclass(frozen=True)
class Not(PrimConn):
    arg: Symb
    def __repr__(self):
        return f"¬({self.arg})"
    def subs(self, mapping: dict):
        # 递归处理子节点的替换
        return Not(self.arg.subs(mapping))

@dataclass(frozen=True)
class To(PrimConn):
    arg1: Symb
    arg2: Symb
    def __repr__(self):
        return f"({self.arg1} → {self.arg2})"
    def subs(self, mapping: dict):
        # 递归处理两个子节点的替换
        return To(
            self.arg1.subs(mapping),
            self.arg2.subs(mapping)
        )

@dataclass(frozen=True)
class StatLett(Symb):
    name: str
    def __repr__(self):
        return self.name
    def subs(self, mapping: dict):
        # 若当前符号在映射中,返回替换值;否则返回自身
        return mapping.get(self, self)
    
def main():
    b = StatLett("B") 
    c = StatLett("C")

    prop = To(b, To(c, b))
    print(prop)  # 输出: (B → (C → B))
    # 传入完整映射进行一次性替换
    prop = prop.subs({b: Not(c), c: b})
    print(prop)  # 输出: (¬(C) → (B → ¬(C)))

if __name__ == "__main__":
    main()

关键说明

  • StatLett.subs:直接检查当前符号是否在映射字典中,存在则返回对应的替换节点,否则返回自身。这保证了每个原始符号只被替换一次。
  • Not/To.subs:递归调用子节点的subs方法,确保整个AST树的所有节点都能被正确处理。
  • 一次性映射传入:通过{b: Not(c), c: b}将所有替换规则一次性传入,遍历AST时基于原始节点进行替换,避免分步替换导致的二次修改。

内容的提问来源于stack exchange,提问作者Jasper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 05:04:52