Example #1
0
def simplify(expr):
    """
    Tries to simplify expressions very niavely.
    """
    expr = propagate(expr, (None, True))
    if type(expr) == bool:
        return PBB.mk_const_expr(expr)
    return expr
Example #2
0
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
Example #3
0
def _parse_ite(expr):
    """
    This method takes in any expression EXPR and parses it into
    a F, G, H expressions such that expr is the same as ite(F,G,H).
    This is possible because every boolean function can be represented
    in ite form. See Bryant's paper for formulas.
    """
    if expr["type"] == "const":
        v = expr["value"]
        return pbb.mk_const_expr(v), pbb.mk_const_expr(v), pbb.mk_const_expr(v)

    if expr["type"] == "var":
        return expr, pbb.mk_const_expr(True), pbb.mk_const_expr(False)

    if expr["type"] == "neg":
        return expr["expr"], pbb.mk_const_expr(False), pbb.mk_const_expr(True)

    if expr["type"] == "and":
        return expr["expr1"], expr["expr2"], pbb.mk_const_expr(False)

    if expr["type"] == "or":
        return expr["expr1"], pbb.mk_const_expr(True), expr["expr2"]

    if expr["type"] == "impl":
        return expr["expr1"], expr["expr2"], pbb.mk_const_expr(True)

    if expr["type"] == "xor":
        return expr["expr1"], pbb.mk_neg_expr(expr["expr2"]), expr["expr2"]

    if expr["type"] == "eqv":
        return expr["expr1"], expr["expr2"], pbb.mk_neg_expr(expr["expr2"])
Example #4
0
#Good example to demo PyBool. Step through with pdb, and print
#variables at each stage. For the recursive representations (expr and expr2)
#use Bool.print_expr(expr) for pretty printing. Uses very simple DIMACS
#file example_dimacs_files/lecture.cnf
if __name__ == "__main__":

    #Read and parse a dimacs file
    clauses = Bool.parse_dimacs("example_dimacs_files/lecture.cnf")
    clauses = clauses["clauses"]

    #convert dimacs form to recursive form
    expr = Bool.cnf_to_rec(clauses)

    #make a new formula that is the negation of previous
    expr = BoolB.mk_neg_expr(expr)

    expr2 = copy.deepcopy(expr)

    #Put in negation normal form
    expr = Bool.nne(expr)

    #now make a possibly exp. sized cnf
    expr = Bool.exp_cnf(expr)

    #with this expression we make a worst case
    #polynomial sized cnf
    expr2 = Bool.poly_cnf(expr2)

    #Now put the recursive formula back to list form
    clauses = Bool.cnf_list(expr2)
Example #5
0
def _parse_ite(expr):
    """
    This method takes in any expression EXPR and parses it into
    a F, G, H expressions such that expr is the same as ite(F,G,H).
    This is possible because every boolean function can be represented
    in ite form. See Bryant's paper for formulas.
    """
    if expr["type"] == "const":
        v = expr["value"]
        return pbb.mk_const_expr(v),pbb.mk_const_expr(v),pbb.mk_const_expr(v)

    if expr["type"] == "var":
        return expr, pbb.mk_const_expr(True), pbb.mk_const_expr(False)

    if expr["type"] == "neg":
        return expr["expr"], pbb.mk_const_expr(False), pbb.mk_const_expr(True)

    if expr["type"] == "and":
        return expr["expr1"], expr["expr2"], pbb.mk_const_expr(False)

    if expr["type"] == "or":
        return expr["expr1"], pbb.mk_const_expr(True), expr["expr2"]

    if expr["type"] == "impl":
        return expr["expr1"], expr["expr2"], pbb.mk_const_expr(True)

    if expr["type"] == "xor":
        return expr["expr1"], pbb.mk_neg_expr(expr["expr2"]), expr["expr2"]

    if expr["type"] == "eqv":
        return expr["expr1"], expr["expr2"], pbb.mk_neg_expr(expr["expr2"])
Example #6
0
def _ite(bdd,F,G,H):
    """
    Main recursive method. Follows Bryants paper with a few
    added heuristics which are noted.
    """
    ####################
    #Possible Base Cases
    ####################
    #If G and H and constants:
    #
    #Base case if F is a variable or constant
    #Else Parse F into FGH form.

    #Switching the _ite_mk args, because they seem to be backwards!
    while (_is_const(G,True) and _is_const(H,False)) or (_is_const(H,True) and _is_const(G,False)) and (F["type"] == "neg" or F["type"] == "var"):
        if _is_const(G,True) and _is_const(H,False):
            if F["type"] == "var":
                return _ite_mk(bdd, F["name"][0] ,0,1)
            elif F["type"] == "const":
                return 1 if F["value"] else 0
            else:
                F,G,H = _parse_ite(F)

        elif _is_const(H,True) and _is_const(G,False):
            if F["type"] == "var":
                return _ite_mk(bdd, F["name"][0] ,1,0)
            elif F["type"] == "const":
                return 0 if F["value"] else 1
            else:
            #Fix applied Feb. 16, 2013 by Tyler Sorensen                
                F,G,H = _parse_ite(F)
                H = pbb.mk_neg_expr(H)
                G = pbb.mk_neg_expr(G)
            
    ####################
    #if H and G are equal and constant
    #Just return what H and G are (my heuristic)
    if _is_const(G, False) and _is_const(H, False):
        return 0

    elif _is_const(G,True) and _is_const(H,True):
        return 1

    ####################
    #Bug fix : forgot to check for these cases
    elif _is_const(F,False) and _is_const(H,True):
        return 1

    elif _is_const(F,False) and _is_const(H,False):
        return 0

    elif _is_const(F,True) and _is_const(G,False):
        return 0

    elif _is_const(F,True) and _is_const(G,True):
        return 1


    ####################
    #If F is a const, then we only have to consider
    #Either G or H. Base case if they're variable otherwise
    #parse them into F, G, H
    elif _is_const(F,True):
        if G["type"] == "var":
            return _ite_mk(bdd,G["name"][0],0,1)
        else:
            F,G,H = _parse_ite(G)

    elif _is_const(F,False):
        if H["type"] == "var":
            return _ite_mk(bdd, H["name"][0],0,1)
        else:
            F,G,H = _parse_ite(H)

    ####################
    #Find the top variable.
    v = top_variable(bdd, F,G,H)
    #create new expressions with variable propagated
    Fv, Gv, Hv = copy.deepcopy(F), copy.deepcopy(G), copy.deepcopy(H)
    Fv = pb.propagate(Fv, (v, True))
    Gv = pb.propagate(Gv, (v, True))
    Hv = pb.propagate(Hv, (v, True))

    Fnv = pb.propagate(F, (v, False))
    Gnv = pb.propagate(G, (v, False))
    Hnv = pb.propagate(H, (v, False))

    #Recursively find T (then) and E (else) nodes
    T = _ite(bdd, Fv, Gv, Hv)
    E = _ite(bdd, Fnv, Gnv, Hnv)

    #If they're the same, then we don't need to make a new
    #node
    #pdb.set_trace()
    if T == E:        
        return T
    
    #make a new node and return it
    R = _ite_mk(bdd,v,E,T)
    return R
Example #7
0
def _ite(bdd, F, G, H):
    """
    Main recursive method. Follows Bryants paper with a few
    added heuristics which are noted.
    """
    ####################
    #Possible Base Cases
    ####################
    #If G and H and constants:
    #
    #Base case if F is a variable or constant
    #Else Parse F into FGH form.

    #Switching the _ite_mk args, because they seem to be backwards!
    while (_is_const(G, True)
           and _is_const(H, False)) or (_is_const(H, True) and _is_const(
               G, False)) and (F["type"] == "neg" or F["type"] == "var"):
        if _is_const(G, True) and _is_const(H, False):
            if F["type"] == "var":
                return _ite_mk(bdd, F["name"][0], 0, 1)
            elif F["type"] == "const":
                return 1 if F["value"] else 0
            else:
                F, G, H = _parse_ite(F)

        elif _is_const(H, True) and _is_const(G, False):
            if F["type"] == "var":
                return _ite_mk(bdd, F["name"][0], 1, 0)
            elif F["type"] == "const":
                return 0 if F["value"] else 1
            else:
                #Fix applied Feb. 16, 2013 by Tyler Sorensen
                F, G, H = _parse_ite(F)
                H = pbb.mk_neg_expr(H)
                G = pbb.mk_neg_expr(G)

    ####################
    #if H and G are equal and constant
    #Just return what H and G are (my heuristic)
    if _is_const(G, False) and _is_const(H, False):
        return 0

    elif _is_const(G, True) and _is_const(H, True):
        return 1

    ####################
    #Bug fix : forgot to check for these cases
    elif _is_const(F, False) and _is_const(H, True):
        return 1

    elif _is_const(F, False) and _is_const(H, False):
        return 0

    elif _is_const(F, True) and _is_const(G, False):
        return 0

    elif _is_const(F, True) and _is_const(G, True):
        return 1

    ####################
    #If F is a const, then we only have to consider
    #Either G or H. Base case if they're variable otherwise
    #parse them into F, G, H
    elif _is_const(F, True):
        if G["type"] == "var":
            return _ite_mk(bdd, G["name"][0], 0, 1)
        else:
            F, G, H = _parse_ite(G)

    elif _is_const(F, False):
        if H["type"] == "var":
            return _ite_mk(bdd, H["name"][0], 0, 1)
        else:
            F, G, H = _parse_ite(H)

    ####################
    #Find the top variable.
    v = top_variable(bdd, F, G, H)
    #create new expressions with variable propagated
    Fv, Gv, Hv = copy.deepcopy(F), copy.deepcopy(G), copy.deepcopy(H)
    Fv = pb.propagate(Fv, (v, True))
    Gv = pb.propagate(Gv, (v, True))
    Hv = pb.propagate(Hv, (v, True))

    Fnv = pb.propagate(F, (v, False))
    Gnv = pb.propagate(G, (v, False))
    Hnv = pb.propagate(H, (v, False))

    #Recursively find T (then) and E (else) nodes
    T = _ite(bdd, Fv, Gv, Hv)
    E = _ite(bdd, Fnv, Gnv, Hnv)

    #If they're the same, then we don't need to make a new
    #node
    #pdb.set_trace()
    if T == E:
        return T

    #make a new node and return it
    R = _ite_mk(bdd, v, E, T)
    return R
def simplify(expr):
    expr = propagate(expr, (None, True))
    if type(expr) == bool:
        return PBB.mk_const_expr(expr)
    return expr
Example #9
0
#Good example to demo PyBool. Step through with pdb, and print
#variables at each stage. For the recursive representations (expr and expr2)
#use Bool.print_expr(expr) for pretty printing. Uses very simple DIMACS
#file example_dimacs_files/lecture.cnf
if __name__ == "__main__":

    #Read and parse a dimacs file
    clauses = Bool.parse_dimacs("example_dimacs_files/lecture.cnf")
    clauses = clauses["clauses"]

    #convert dimacs form to recursive form
    expr = Bool.cnf_to_rec(clauses)

    #make a new formula that is the negation of previous
    expr = BoolB.mk_neg_expr(expr)

    expr2 = copy.deepcopy(expr)

    #Put in negation normal form
    expr = Bool.nne(expr)

    #now make a possibly exp. sized cnf
    expr = Bool.exp_cnf(expr)
    
    #with this expression we make a worst case
    #polynomial sized cnf
    expr2 = Bool.poly_cnf(expr2)

    #Now put the recursive formula back to list form
    clauses = Bool.cnf_list(expr2)