PySat:在CNF上使用Equals对象后执行Clausify异常如何解决?
PySat中基数约束与原子等价的正确实现方式
你遇到的问题根源是错误使用了Equals类——它无法直接接收CNF对象作为参数。Equals的设计目标是等价两个布尔表达式(如单个原子、逻辑组合表达式),而非已有的CNF子句集合。当你传入cnf2(ITotalizer生成的CNF实例)时,PySat内部会自动生成一个临时变量(比如输出中的12)来指代这个“未解析的CNF”,导致原基数约束的子句被完全忽略,只生成了临时变量与y的等价子句。
正确解决方案
要实现基数约束与原子y=4的真值等价,需先获取基数约束对应的顶层指示器文字(该文字为真当且仅当约束满足),再构造该文字与y的等价子句,最后合并所有子句:
方法1:使用CardEnc封装类(推荐)
from pysat.card import CardEnc from pysat.formula import CNF # 生成"lits=[1,2,3]最多1个为真"的基数约束,同时获取顶层指示器文字top_lit # top_lit为真 ↔ 基数约束满足 cnf_card, top_lit = CardEnc.atmost(lits=[1,2,3], bound=1, top_id=100).encode() print("基数约束子句:") print(cnf_card.clauses) # 构造top_lit与原子4的等价子句:等价于(top_lit ↔ 4) eq_clauses = [[-top_lit, 4], [-4, top_lit]] # 合并基数约束和等价子句,得到最终CNF cnf_final = CNF() cnf_final.extend(cnf_card.clauses) cnf_final.extend(eq_clauses) print("\n最终等价约束子句:") print(cnf_final.clauses)
方法2:直接使用ITotalizer类
如果需要直接使用ITotalizer,可以通过get_top()方法获取顶层指示器文字:
from pysat.card import ITotalizer from pysat.formula import CNF # 用ITotalizer构造最多1个为真的约束 totalizer = ITotalizer(lits=[1,2,3], ubound=1, top_id=100) cnf_card = totalizer.cnf top_lit = totalizer.get_top() # 获取顶层指示器文字 # 构造等价子句并合并 eq_clauses = [[-top_lit, 4], [-4, top_lit]] cnf_final = CNF() cnf_final.extend(cnf_card.clauses) cnf_final.extend(eq_clauses) print(cnf_final.clauses)
输出说明
运行后,最终的CNF会包含基数约束的所有原始子句,再加上[-top_lit,4]和[-4,top_lit]两个子句,确保基数约束与原子4的真值完全等价。
内容的提问来源于stack exchange,提问作者samarendra chandan bindu Dash
相关产品推荐
相关产品推荐

