2012-09-17 24 views
6

Ich versuche ein Programm zu erstellen, das mit Hilfe von sympy eine Menge von Variablen nimmt und einen symbolischen Logikausdruck über die Domäne dieser Variablen auswertet. Das Problem ist, dass ich Python nicht bekommen kann, um den Ausdruck auszuwerten, nachdem er die Wahrheitstabelle ausgespuckt hat.Wahrheitstabellen in Python mit Hilfe von sympy

Hier ist der Code:

from sympy import * 
from sympy.abc import p, q, r 

def get_vars(): 
    vars = [] 
     print "Please enter the number of variables to use in the equation" 
     numVars = int(raw_input()) 
    print "please enter each of the variables on a newline" 
     for i in xrange(numVars): 
     vars.append(raw_input()) 
    return vars 

def get_expr(): 
    print "Please enter the expression to use" 
    return str(raw_input()) 

def convert_to_expr(inputStr): 
    return eval(inputStr) 

def main(): 
    vars = get_vars() 
    expr = get_expr() 

    print("recieved input: " + str(vars) + " expr " + str(expr)) 

    print "Truth table for " + str(len(vars)) + "variable(s)" 
    for i in enumerate(truth_table(vars, expr)): 
     print i 

def fixed_table(numvars): 
    """ 
    Generate true/false permutations for the given number of variables. 
    So if numvars=2 
    Returns (not necessarily in this order): 
     True, True 
     True, False 
     False, False 
     False, True 
    """ 
    if numvars is 1: 
     yield [True] 
     yield [False] 
    else: 
     for i in fixed_table(numvars-1): 
      yield i + [True] 
      yield i + [False] 


def truth_table(vars, expr): 
    """ 
    Takes an array of variables, vars, and displays a truth table 
    for each possible value combination of vars. 
    """ 
    for cond in fixed_table(len(vars)): 
     values=dict(zip(vars,cond)) 
     yield cond + [eval(expr)] 

if __name__ == "__main__": 
    main() 

Wenn ich den folgenden, hier ist die Ausgabe:

Please enter the number of variables to use in the equation 
3 
please enter each of the variables on a newline 
p 
q 
r 
Please enter the expression to use 
p&q&r 
recieved input: ['p', 'q', 'r'] expr p&q&r 
Truth table for 3variable(s) 
(0, [True, True, True, And(p, q, r)]) 
(1, [True, True, False, And(p, q, r)]) 
(2, [True, False, True, And(p, q, r)]) 
(3, [True, False, False, And(p, q, r)]) 
(4, [False, True, True, And(p, q, r)]) 
(5, [False, True, False, And(p, q, r)]) 
(6, [False, False, True, And(p, q, r)]) 
(7, [False, False, False, And(p, q, r)]) 

Wenn einige Software zur Durchführung dieser Aufgabe existiert, ich habe wirklich darüber wissen möchten :-)

Vielen Dank im Voraus.

Antwort

7

Sie sind wirklich nah dran! Sobald Sie And(p, q, r) und Ihre Wahrheitstabellen haben, können Sie die subs Methode verwenden Ihre values dict in den Ausdruck schieben: dh

yield cond + [eval(expr).subs(values)] 

p&q&r 
recieved input: ['p', 'q', 'r'] expr p&q&r 
Truth table for 3variable(s) 
(0, [True, True, True, True]) 
(1, [True, True, False, False]) 
(2, [True, False, True, False]) 
(3, [True, False, False, False]) 
(4, [False, True, True, False]) 
(5, [False, True, False, False]) 
(6, [False, False, True, False]) 
(7, [False, False, False, False]) 

gibt Aber ich denke, es gibt einen einfacheren Weg zu mach das. Die sympify Funktion arbeitet bereits Ausdrücke von Zeichenketten zu erzeugen:

In [7]: expr = sympify("x & y | z") 

In [8]: expr 
Out[8]: Or(z, And(x, y)) 

und wir können die Variablen erhalten zu:

In [9]: expr.free_symbols 
Out[9]: set([x, z, y]) 

Plus itertools.product die Werte erzeugen kann (und cartes ist ein Alias ​​für sie in sympy) :

In [12]: cartes([False, True], repeat=3) 
Out[12]: <itertools.product at 0xa24889c> 

In [13]: list(cartes([False, True], repeat=3)) 
Out[13]: 
[(False, False, False), 
(False, False, True), 
(False, True, False), 
(False, True, True), 
(True, False, False), 
(True, False, True), 
(True, True, False), 
(True, True, True)] 

diese Kombination, die im Grunde nur sympify nutzt das bekommen Ausdruck und vermeiden eval, die sich im internen cartesianischen Produkt verwenden, und .subs() Hinzufügen Ihres values Wörterbuch verwenden, erhalten wir:

def explore(): 
    expr_string = raw_input("Enter an expression: ") 
    expr = sympify(expr_string) 
    variables = sorted(expr.free_symbols) 
    for truth_values in cartes([False, True], repeat=len(variables)): 
     values = dict(zip(variables, truth_values)) 
     print sorted(values.items()), expr.subs(values) 

die

In [22]: explore() 
Enter an expression: a & (b | c) 
[(a, False), (b, False), (c, False)] False 
[(a, False), (b, False), (c, True)] False 
[(a, False), (b, True), (c, False)] False 
[(a, False), (b, True), (c, True)] False 
[(a, True), (b, False), (c, False)] False 
[(a, True), (b, False), (c, True)] True 
[(a, True), (b, True), (c, False)] True 
[(a, True), (b, True), (c, True)] True 

Dies gibt kürzer als bei Ihnen, aber es nutzt genau dein Ansatz.

+0

Du bist großartig. Vielen Dank, das hat perfekt funktioniert !!! – alvonellos

Verwandte Themen