使用Sympy to_nnf转换布尔函数时调用eval()触发MemoryError问题
解决Sympy处理超大布尔函数时的MemoryError问题
你遇到的MemoryError核心原因是用eval()处理超长布尔函数字符串时的内存过载——eval在解析这类长字符串时,既要承载庞大的字符串本身,还要在内存中构建对应的抽象语法树,当符号数量极大时,内存开销直接触发溢出。而且eval本身还有安全风险,完全不适合处理这类动态生成的超长表达式。
下面给你两个更高效的解决方案:
方案一:用Sympy的parse_expr替代eval
Sympy专门提供了parse_expr函数来解析表达式字符串,它比eval更针对数学/布尔表达式优化,内存效率更高,也更安全。
举个实际例子:
from sympy import symbols, to_nnf, parse_expr # 假设有10000个符号(数量可任意调整) total_symbols = 10000 # 批量创建符号,比如x0, x1, ..., x9999 symbol_list = symbols(f'x0:{total_symbols}') # 假设你的布尔函数字符串是替换后的形式,比如"~(x0 & x1 & ... & x9999)" bool_func_str = "~(" + " & ".join([f'x{i}' for i in range(total_symbols)]) + ")" # 用parse_expr替代eval解析表达式 sympy_expr = parse_expr(bool_func_str) # 转换为否定范式 nnf_result = to_nnf(sympy_expr) # 查看结果(符号太多时可只看结构) print(nnf_result)
方案二:直接构建Sympy表达式(推荐)
如果能跳过生成字符串的环节,直接用Sympy的逻辑运算符(And、Not、Or等)构建表达式,完全避免字符串解析的内存开销,这是处理超大符号列表最高效的方式。
示例代码:
from sympy import symbols, to_nnf, And, Not total_symbols = 10000 symbol_list = symbols(f'x0:{total_symbols}') # 直接用And组合所有符号,再取Not,完全不用字符串 and_expression = And(*symbol_list) bool_expression = Not(and_expression) # 转换为否定范式 nnf_result = to_nnf(bool_expression) print(nnf_result)
额外提示
如果你的布尔函数是从外部读取的复杂字符串,建议先对字符串做语法分析,拆分出逻辑运算符和变量,再用Sympy的API逐个构建表达式节点,而不是生成超长的整体字符串再解析——这样能最大程度减少内存占用,同时避免eval带来的安全隐患。
内容的提问来源于stack exchange,提问作者digitaLink
相关产品推荐
相关产品推荐

