def nne(expr):
    """
    converts the expression EXPR into negation normal form
    """
    #first get rid of all non standard
    #operators
    expr = PBA.std_expr(expr)

    #Then propagate the negation
    return PBA.nne(expr)
def cnf_list(expr):
    """
    returns a list representation of the recursive expression EXPR
    in the form of a dict where the clauses field is the actual list
    and Map is the mapping of variable names to numbers (in the form
    of a list of tuples)
    """

    #Get a var map, create a new one (in case the old one
    #is wrong) and apply the new map.
    m = PBA.get_var_map(expr)
    m = PBA.create_new_map(m)
    PBA.apply_map(expr, m)

    return {"Clauses": PBA.cnf_list(expr), "map": m}
def cnf_apply_sol(clauses, sol):
    """
    applys the solution SOL to CLAUSES (should return a 
    boolean value) SOL is a list of booleans where the variable
    name corresponds to the index of the list
    """
    return PBA.cnf_apply_sol(clauses, sol)
def poly_cnf(expr):
    """
    converts the expression EXPR into a polynomial sized
    cnf formula (adds variables and returned expression
    is still recursive, use cnf_list to
    convert to list representation)
    """
    repHash = {}
    return PBA.poly_cnf(expr, repHash)
def propagate(expr, tup):
    """
    Propagae the assignment TUP (string variable name, boolean value)
    through expression EXPR
    """
    expr = PBA.propagate(expr, tup)
    if type(expr) == bool:
        return PBB.mk_const_expr(expr)
    return expr
def exp_cnf(expr):
    """
    converts the expression EXPR into an expodentially
    large cnf expression (still recursive, use cnf_list to
    convert to list representation)
    """
    #Convert to nne
    expr = nne(expr)

    #distribute
    return PBA.exp_cnf(expr)
def rename_var(expr, tup):
    """
    given a tup (var1, var2) replaces var1 in expr with var2
    """
    cop_expr = copy.deepcopy(expr)
    return PBA.rename_var(cop_expr, tup)
def print_expr(expr):
    """
    prints a readable string representing the expression EXPR
    """
    return PBA.print_expr(expr)
def apply_sol_expr(expr, sol):
    """
    apply the solution SOL (DictType {string variable name : boolean value}
    to the expression EXPR
    """
    return PBA.apply_sol_expr(expr, sol)
def cnf_to_rec(clauses):
    """
    given a list form of an expression CLAUSES, return an equivalent
    recursive form
    """
    return PBA.cnf_to_rec(clauses)
def cnf_get_pure_literals(clauses):
    """
    returns a list of pure literals (variables appearing exclusively
    negated or non negated) in CLAUSES
    """
    return PBA.cnf_get_pure_literals(clauses)
def cnf_get_unit_clauses(clauses):
    """
    returns a list of literals appearing in unit clauses
    in CLAUSES
    """
    return PBA.cnf_get_unit_clauses(clauses)
def cnf_propagate(clauses, variable, truth_value):
    """
    propagates the assingment of VARIABLE to TRUTH_VALUE in
    CLAUSES
    """
    return PBA.cnf_propagate(clauses, variable, truth_value)
def get_vars(expr):
    return [x[0] for x in PBA.get_var_map(expr)]
def number_vars(expr):
    """
    returns the number of variables in expr
    """
    m = PBA.get_var_map(expr)
    return len(m)