我有来自两个不同来源的'if statements',它试图以不同的方式实现相同的条件。 'if语句'是C. 如果可能的话,我需要一个python脚本来决定条件对是否相等。 一个基本的例子:
source1:((op1 != v1) || ((op2 != v2) || (op3 != v3)))
source2:((op2 != v2) || (op1 != v1) || (op3 != v3))
当然,任何操作符都是允许的,函数调用,当然还有括号。
欢迎任何想法。
编辑1:函数调用没有副作用。
答案 0 :(得分:5)
这就是问题,问题可能(或可能不是)NP完全但除非这是在重要事物的内循环内(并且变量的数量很小),构建整个真值表< / em>的!这很容易做到。它明显增长为2 ^ n,但对于小n,这是完全可行的。与评论建议一样,我假设函数调用没有副作用,只需输出True
或False
。
我发布了一个模拟示例,可以解决您所说的问题,并根据需要进行调整。我依靠pythons解析器来处理表达式的评估。
import pyparsing as pypar
import itertools
def python_equiv(s):
return s.replace('||',' or ').replace('&&',' and ')
def substitute(s,truth_table, VARS):
for v,t in zip(VARS,truth_table):
s = s.replace(v,t)
return s
def check_statements(A1,A2):
VARS = set()
maths = pypar.oneOf("( ! = | & )")
keywords = pypar.oneOf("and or")
variable = pypar.Word(pypar.alphanums)
variable.setParseAction(lambda x: VARS.add(x[0]))
grammar = pypar.OneOrMore(maths | keywords | variable)
# Determine the variable names
grammar.parseString(A1)
grammar.parseString(A2)
A1 = python_equiv(A1)
A2 = python_equiv(A2)
bool_vals = map(str, [False,True])
for table in itertools.product(bool_vals,repeat=len(VARS)):
T1 = substitute(A1,table,VARS)
T2 = substitute(A2,table,VARS)
if eval(T1) != eval(T2):
print "FAIL AT ", table,
return False
print "Statements equiv:",
return True
# Original example
A1 = '''((op1 != v1) || ((op2 != v2) || (op3 != v3)))'''
A2 = '''((op2 != v2) || (op1 != v1) || (op3 != v3))'''
print check_statements(A1,A2)
# Example with a failure
A1 = '''((op1 != v1) || ((op2 != v2) || (op3 != v3)))'''
A2 = '''((op2 != v2) || (op1 != v1) && (op3 != v3))'''
print check_statements(A1,A2)
作为输出:
Statements equiv: True
FAIL AT ('False', 'False', 'False', 'False', 'False', 'True') False
答案 1 :(得分:2)
要做到这一点,您需要控制流anlaysis来确定这两个条件是否具有相同的控制依赖性(否则它们不会在相同的数据上下文中执行),完整的数据流分析包括C代码的分析点函数的副作用分析,跨函数调用从条件的根到表达式的叶子的反向能力,然后是一个考虑C语义的布尔等价匹配器(例如短路,溢出,... 。)
这远远超出了你从C解析器获得的东西。