예제 #1
0
def queens(n):

    solution = Robdd.true()

    # create the rule "there must be at least one queen at each line"
    for j in range(1, n + 1):
        line = Robdd.false()

        for i in range(1, n + 1):
            queen = Robdd.make_x(index_of(i, j))
            line = synth(line, Bdd.OR, queen)

        solution = synth(solution, Bdd.AND, line)

    # create a list of "NOT" expressions
    not_expressions = {}
    for j in range(1, n + 1):
        for i in range(1, n + 1):
            not_expressions[(i, j)] = Robdd.make_not_x(index_of(i, j))

    # create conditions for each position
    for j in range(1, n + 1):
        for i in range(1, n + 1):
            queen = queen_conditions(not_expressions, i, j, n)
            solution = synth(solution, Bdd.AND, queen)

    return solution
예제 #2
0
def queens(n):

    solution = Robdd.true()

    # create the rule "there must be at least one queen at each line"
    for j in range(1, n + 1):
        line = Robdd.false()

        for i in range(1, n + 1):
            queen = Robdd.make_x(index_of(i, j))
            line = synth(line, Bdd.OR, queen)

        solution = synth(solution, Bdd.AND, line)

    # create a list of "NOT" expressions
    not_expressions = {}
    for j in range(1, n + 1):
        for i in range(1, n + 1):
            not_expressions[(i, j)] = Robdd.make_not_x(index_of(i, j))

    # create conditions for each position
    for j in range(1, n + 1):
        for i in range(1, n + 1):
            queen = queen_conditions(not_expressions, i, j, n)
            solution = synth(solution, Bdd.AND, queen)
    
    return solution
예제 #3
0
def remove_interval_up(original, s):
    r = Robdd.false()
    for i, b in enumerate(s):
        if b == '0':
            current_var = Robdd.make_x(i)
            r = synth(r, Bdd.OR, current_var)

    return synth(original, Bdd.AND, r)
예제 #4
0
def blah():
    v = [
        '1000000000000001', '1100000000000011', '1010000000000101',
        '1000000110000001', '1000100000010001', '1001000000001001',
        '1000010000100001', '1000001001000001', '1111000000001111',
        '1010010110100101', '1001100110011001', '1100110000110101',
        '1010101001010101', '1100001111000011', '1111111111111111'
    ]
    #
    # '''
    # 1000010000100001
    # 1000000110000001
    # 1010000000000101
    # 1010010110100101
    # '''

    # print v[2]

    solution = None
    for __v__ in v:
        if solution is None:
            solution = add_restriction(__v__)
        else:
            solution = synth(solution, Bdd.OR, add_restriction(__v__))

    # solution = add_restriction(v[0])

    # for i in range(len(v)):
    #     if i in [0, 1, 13]:
    #         continue
    #     solution = synth(solution, Bdd.AND, add_negated(v[i]))

    # solution = remove_interval_down(solution, v[6])
    # solution = remove_interval_down(solution, v[2])
    # solution = remove_interval_down(solution, v[4])
    # solution = remove_interval_down(solution, v[5])
    #
    # solution = remove_interval_up(solution, v[1])

    # solution = Robdd.make_x(0)
    # solution = synth(solution, Bdd.OR, Robdd.make_not_x(0))
    # solution = synth(solution, Bdd.OR, Robdd.make_x(1))

    solution = Robdd.false()
    solution = synth(solution, Bdd.OR, Robdd.make_not_x(0))

    with open('/tmp/graph.dot', 'w') as fh:
        fh.write(solution.graphviz())

    return solution
예제 #5
0
def add_restriction(s):
    r = Robdd.true()
    for i, b in enumerate(s):
        # if i == 0:
        #     continue
        # if i >= 8 :
        #     continue

        if b == '1':
            current_var = Robdd.make_x(i)
        else:
            current_var = Robdd.make_not_x(i)

        r = synth(r, Bdd.AND, current_var)
    return r
예제 #6
0
def add_negated(s):
    r = Robdd.false()
    for i, b in enumerate(s):
        # if i == 0:
        #     continue
        # if i >= 8:
        #     continue

        if b == '0':
            current_var = Robdd.make_x(i)
        else:
            current_var = Robdd.make_not_x(i)

        r = synth(r, Bdd.OR, current_var)
    return r
예제 #7
0
def queen_conditions(not_x, i, j, n) :
    queen = Robdd.make_x(index_of(i, j))

    # creates the rule "none in the same column"
    a = Robdd.true()
    for y in range(1, n + 1) :
        if y == j : continue

        a_ = synth(queen, Bdd.IMPL, not_x[(i, y)])
        a  = synth(a, Bdd.AND, a_)

    # creates the rule "none in the same line"
    b = Robdd.true()
    for x in range(1, n + 1) :
        if x == i : continue

        b_ = synth(queen, Bdd.IMPL, not_x[(x, j)])
        b  = synth(b, Bdd.AND, b_)

    # creates the rule "none in the diagonals"
    c = Robdd.true()
    x = 1
    while (i - x) > 0 and (j - x) > 0 :
        c_ = synth(queen, Bdd.IMPL, not_x[(i - x, j - x)])
        c  = synth(c, Bdd.AND, c_)
        x += 1

    x = 1
    while (i + x) <= n and (j + x) <= n :
        c_ = synth(queen, Bdd.IMPL, not_x[(i + x, j + x)])
        c  = synth(c, Bdd.AND, c_)
        x += 1

    d = Robdd.true()
    x = 1
    while (i - x) > 0 and (j + x) <= n : 
        d_ = synth(queen, Bdd.IMPL, not_x[(i - x, j + x)])
        d  = synth(d, Bdd.AND, d_)
        x += 1

    x = 1
    while (i + x) <= n and (j - x) > 0 :

        d_ = synth(queen, Bdd.IMPL, not_x[(i + x, j - x)])
        d  = synth(d, Bdd.AND, d_)
        x += 1

    return synth(synth(a, Bdd.AND, b), Bdd.AND, synth(c, Bdd.AND, d))
예제 #8
0
def queen_conditions(not_x, i, j, n):
    queen = Robdd.make_x(index_of(i, j))

    # creates the rule "none in the same column"
    a = Robdd.true()
    for y in range(1, n + 1):
        if y == j: continue

        a_ = synth(queen, Bdd.IMPL, not_x[(i, y)])
        a = synth(a, Bdd.AND, a_)

    # creates the rule "none in the same line"
    b = Robdd.true()
    for x in range(1, n + 1):
        if x == i: continue

        b_ = synth(queen, Bdd.IMPL, not_x[(x, j)])
        b = synth(b, Bdd.AND, b_)

    # creates the rule "none in the diagonals"
    c = Robdd.true()
    x = 1
    while (i - x) > 0 and (j - x) > 0:
        c_ = synth(queen, Bdd.IMPL, not_x[(i - x, j - x)])
        c = synth(c, Bdd.AND, c_)
        x += 1

    x = 1
    while (i + x) <= n and (j + x) <= n:
        c_ = synth(queen, Bdd.IMPL, not_x[(i + x, j + x)])
        c = synth(c, Bdd.AND, c_)
        x += 1

    d = Robdd.true()
    x = 1
    while (i - x) > 0 and (j + x) <= n:
        d_ = synth(queen, Bdd.IMPL, not_x[(i - x, j + x)])
        d = synth(d, Bdd.AND, d_)
        x += 1

    x = 1
    while (i + x) <= n and (j - x) > 0:

        d_ = synth(queen, Bdd.IMPL, not_x[(i + x, j - x)])
        d = synth(d, Bdd.AND, d_)
        x += 1

    return synth(synth(a, Bdd.AND, b), Bdd.AND, synth(c, Bdd.AND, d))
예제 #9
0
    def synthesize(self):
        if self.expression_a == None or not isinstance(self.expression_a,
                                                       Robdd):
            raise "Expression A is not a Robdd object."

        if self.expression_b == None or not isinstance(self.expression_b,
                                                       Robdd):
            raise "Expression B is not a Robdd object."

        if self.operator not in [Bdd.AND, Bdd.OR, Bdd.IMPL, Bdd.BIIMPL]:
            raise "Invalid operator."

        self.result = Robdd()
        self.result.root = self._synth(self.expression_a.root,
                                       self.expression_b.root)

        return self.result
예제 #10
0
    def test_evaluate_should_return_true_for_x1(self):
        robdd = Robdd.false()
        v = robdd.make_x(0)
        robdd = synth(robdd, Bdd.OR, v)

        self.assertTrue(robdd.evaluate([1]))
        self.assertTrue(robdd.evaluate([1, 0]))
        self.assertTrue(robdd.evaluate([1, 1, 0, 1]))

        self.assertFalse(robdd.evaluate([0]))
        self.assertFalse(robdd.evaluate([0, 1]))
        self.assertFalse(robdd.evaluate([0, 1, 1, 1]))
예제 #11
0
파일: synthesis.py 프로젝트: ericvoid/robdd
    def synthesize(self):
        if self.expression_a == None or not isinstance(self.expression_a, Robdd):
            raise "Expression A is not a Robdd object."

        if self.expression_b == None or not isinstance(self.expression_b, Robdd):
            raise "Expression B is not a Robdd object."

        if self.operator not in [Bdd.AND, Bdd.OR, Bdd.IMPL, Bdd.BIIMPL]:
            raise "Invalid operator."

        self.result = Robdd()
        self.result.root = self._synth(self.expression_a.root, self.expression_b.root)

        return self.result
예제 #12
0
def negate_bdd(bdd):
    neg_bdd = synthesize(bdd, Bdd.AND, Robdd.true())
    for i in xrange(len(neg_bdd.items)):
        neg_bdd.items[i] = tuple(
            (neg_bdd.items[i][0], not neg_bdd.items[i][1]
             if neg_bdd.items[i][1] in (True, False) else neg_bdd.items[i][1],
             not neg_bdd.items[i][2]
             if neg_bdd.items[i][2] in (True, False) else neg_bdd.items[i][2]))

    # invert root, if root is a leaf
    if neg_bdd.root in (0, 1):
        neg_bdd.root ^= 1

    return neg_bdd
예제 #13
0
def negate_bdd(bdd):
    neg_bdd = synthesize(bdd, Bdd.AND, Robdd.true())
    for i in xrange(len(neg_bdd.items)):
        neg_bdd.items[i] = tuple((neg_bdd.items[i][0],
                                  not neg_bdd.items[i][1] if neg_bdd.items[i][1] in (True, False) else neg_bdd.items[i][
                                      1],
                                  not neg_bdd.items[i][2] if neg_bdd.items[i][2] in (True, False) else neg_bdd.items[i][
                                      2]))

    # invert root, if root is a leaf
    if neg_bdd.root in (0, 1):
        neg_bdd.root ^= 1

    return neg_bdd
def get_minimal_element(robdd: Robdd,
                        mapping_partition_to_boolean,
                        mapping_boolean_to_partition,
                        expected_value=1):
    bool_representation = robdd.get_random_solution(expected_value)
    if bool_representation is None:
        return None

    partition = Partition(
        mask=mapping_boolean_to_partition[tuple(bool_representation)].mask)

    while True:
        can_continue = False
        for partition_child in partition.subset_generator():
            boolean_representation = mapping_partition_to_boolean[
                partition_child.mask]
            if robdd.evaluate(boolean_representation) == expected_value:
                can_continue = True
                partition = partition_child

        if not can_continue:
            break

    return partition.mask
    def test_get_minimal_element_should_work2(self):
        robdd = Robdd.false()

        a = (1, 1, 1, 1)
        pa = Partition(mask=(0, 0, 0))

        b = (1, 1, 0, 0)
        pb = Partition(mask=(0, 0, 1))

        c = (1, 0, 1, 0)
        pc = Partition(mask=(0, 1, 0))

        d = (1, 0, 0, 1)
        pd = Partition(mask=(0, 1, 1))

        e = (1, 0, 0, 0)
        pe = Partition(mask=(0, 1, 2))

        robdd = synth(robdd, Bdd.OR, add_restriction(a))
        robdd = synth(robdd, Bdd.OR, add_restriction(b))
        robdd = synth(robdd, Bdd.OR, add_restriction(c))
        robdd = synth(robdd, Bdd.OR, add_restriction(d))

        mapping_partition_to_boolean = dict()
        mapping_partition_to_boolean[pa.mask] = a
        mapping_partition_to_boolean[pb.mask] = b
        mapping_partition_to_boolean[pc.mask] = c
        mapping_partition_to_boolean[pd.mask] = d
        mapping_partition_to_boolean[pe.mask] = e

        mapping_boolean_to_partition = dict()
        mapping_boolean_to_partition[a] = pa
        mapping_boolean_to_partition[b] = pb
        mapping_boolean_to_partition[c] = pc
        mapping_boolean_to_partition[d] = pd
        mapping_boolean_to_partition[e] = pe

        minimal_element = get_minimal_element(robdd, mapping_partition_to_boolean, mapping_boolean_to_partition)

        self.assertTrue(minimal_element == (0, 0, 1) or minimal_element == (0, 1, 0) or minimal_element == (0, 1, 1))
예제 #16
0
def main():
    #Parse the command line arguments provided at run time.
    parser = argparse.ArgumentParser(description='ROBDD')
    parser.add_argument('-b',
                        '--boolean_expr',
                        dest='expr_1',
                        metavar='B',
                        type=str,
                        nargs='?',
                        help='Provide a boolean expression')
    parser.add_argument('-b2',
                        '--boolean_expr2',
                        dest='expr_2',
                        metavar='B2',
                        type=str,
                        nargs='?',
                        help='Provide a boolean expression')
    parser.add_argument(
        '-a',
        '--apply',
        dest='apply_expr',
        metavar='A',
        type=str,
        nargs='?',
        help='Provide the operation to apply (And, Or, Equal, Implies)')
    parser.add_argument('-r',
                        '--restrict',
                        dest='restrict_expr',
                        metavar='R',
                        type=str,
                        nargs='?',
                        help='Provide the restriction "var,val"')
    parser.add_argument('-s',
                        '--sat',
                        dest='sat',
                        action='store_true',
                        help='Return SAT on ROBDD')

    # Parse the input arguments
    args = parser.parse_args()

    if args.expr_1 is not None:
        expression1 = str(expr(args.expr_1))
        print("Expression1: " + expression1)
        r1 = Robdd(find_large_var(expression1))
        r1.build(expression1)
        r1.print_graph("r1")

    if args.expr_2 is not None:
        expression2 = str(expr(args.expr_2))
        print("Expression2: " + expression2)
        r2 = Robdd(find_large_var(expression2))
        r2.build(expression2)
        r2.print_graph("r2")

    if args.apply_expr is not None:
        r3 = Robdd_apply(
            max(find_large_var(expression1), find_large_var(expression2)))
        r3.apply(convert_apply(args.apply_expr), r1, r2)
        r3.print_graph("r3_apply")

    if args.restrict_expr is not None:
        r4 = Robdd_restrict(r1)
        r4.restrict(int(args.restrict_expr.split(',')[0]),
                    int(args.restrict_expr.split(',')[1]))
        r4.print_graph('r4_restrict')

    if args.sat:
        r4 = Robdd_sat(r1)
        r4.print_SAT()
예제 #17
0
파일: synthesis.py 프로젝트: ericvoid/robdd
class Synthesis:
    def __init__(self):
        self.memo = {}

        self.operator = None
        self.expression_a = None
        self.expression_b = None

        self.result = None

    def synthesize(self):
        if self.expression_a == None or not isinstance(self.expression_a, Robdd):
            raise "Expression A is not a Robdd object."

        if self.expression_b == None or not isinstance(self.expression_b, Robdd):
            raise "Expression B is not a Robdd object."

        if self.operator not in [Bdd.AND, Bdd.OR, Bdd.IMPL, Bdd.BIIMPL]:
            raise "Invalid operator."

        self.result = Robdd()
        self.result.root = self._synth(self.expression_a.root, self.expression_b.root)

        return self.result

    def _synth(self, a_index, b_index):

        if (a_index, b_index) in self.memo:
            return self.memo[(a_index, b_index)]

        # print "_synth {}, {}".format(a_index, b_index)
        # print "   A is leaf:", self._is_leaf(a_index)
        # print "   B is leaf:", self._is_leaf(b_index)

        i_a, t_a, f_a = self.expression_a.items[a_index]
        i_b, t_b, f_b = self.expression_b.items[b_index]

        if self._is_leaf(a_index) and self._is_leaf(b_index):
            # print "   operating leaves"
            result = self._operate(a_index, b_index)

        elif i_a == i_b:
            # print "   operating nodes"
            result = self.result.insert(i_a, self._synth(t_a, t_b), self._synth(f_a, f_b))

        elif i_a < i_b:
            # print "   advancing A"
            result = self.result.insert(i_a, self._synth(t_a, b_index), self._synth(f_a, b_index))

        # elif i_a > i_b:
        else:
            # print "   advancing B"
            result = self.result.insert(i_b, self._synth(a_index, t_b), self._synth(a_index, f_b))

        self.memo[(a_index, b_index)] = result

        return result

    def _operate(self, a_index, b_index):
        a = self._index_to_bool(a_index)
        b = self._index_to_bool(b_index)

        if self.operator == Bdd.AND:
            return a and b

        if self.operator == Bdd.OR:
            return a or b

        if self.operator == Bdd.IMPL:
            return False if (a and not b) else True

        if self.operator == Bdd.BIIMPL:
            return a == b

        raise "Unknown operator."

    def _is_leaf(self, index):
        return index == 0 or index == 1

    def _index_to_bool(self, index):
        return index == 1
    def test_get_minimal_element_should_return_none_if_empty(self):
        robdd = Robdd.false()

        self.assertIsNone(get_minimal_element(robdd, dict(), dict()))
예제 #19
0
 def test_evaluate_should_always_return_false(self):
     robdd = Robdd.false()
     self.assertFalse(robdd.evaluate([0]))
     self.assertFalse(robdd.evaluate([1]))
     self.assertFalse(robdd.evaluate([0, 0]))
     self.assertFalse(robdd.evaluate([0, 1, 1, 0]))
예제 #20
0
class Synthesis:
    def __init__(self):
        self.memo = {}

        self.operator = None
        self.expression_a = None
        self.expression_b = None

        self.result = None

    def synthesize(self):
        if self.expression_a == None or not isinstance(self.expression_a,
                                                       Robdd):
            raise "Expression A is not a Robdd object."

        if self.expression_b == None or not isinstance(self.expression_b,
                                                       Robdd):
            raise "Expression B is not a Robdd object."

        if self.operator not in [Bdd.AND, Bdd.OR, Bdd.IMPL, Bdd.BIIMPL]:
            raise "Invalid operator."

        self.result = Robdd()
        self.result.root = self._synth(self.expression_a.root,
                                       self.expression_b.root)

        return self.result

    def _synth(self, a_index, b_index):

        if (a_index, b_index) in self.memo:
            return self.memo[(a_index, b_index)]

        # print "_synth {}, {}".format(a_index, b_index)
        # print "   A is leaf:", self._is_leaf(a_index)
        # print "   B is leaf:", self._is_leaf(b_index)

        i_a, t_a, f_a = self.expression_a.items[a_index]
        i_b, t_b, f_b = self.expression_b.items[b_index]

        if self._is_leaf(a_index) and self._is_leaf(b_index):
            # print "   operating leaves"
            result = self._operate(a_index, b_index)

        elif i_a == i_b:
            # print "   operating nodes"
            result = self.result.insert(i_a, self._synth(t_a, t_b),
                                        self._synth(f_a, f_b))

        elif i_a < i_b:
            # print "   advancing A"
            result = self.result.insert(i_a, self._synth(t_a, b_index),
                                        self._synth(f_a, b_index))

        # elif i_a > i_b:
        else:
            # print "   advancing B"
            result = self.result.insert(i_b, self._synth(a_index, t_b),
                                        self._synth(a_index, f_b))

        self.memo[(a_index, b_index)] = result

        return result

    def _operate(self, a_index, b_index):
        a = self._index_to_bool(a_index)
        b = self._index_to_bool(b_index)

        if self.operator == Bdd.AND:
            return a and b

        if self.operator == Bdd.OR:
            return a or b

        if self.operator == Bdd.IMPL:
            return False if (a and not b) else True

        if self.operator == Bdd.BIIMPL:
            return a == b

        raise "Unknown operator."

    def _is_leaf(self, index):
        return index == 0 or index == 1

    def _index_to_bool(self, index):
        return index == 1
예제 #21
0
 def test_evaluate_should_always_return_true(self):
     robdd = Robdd.true()
     self.assertTrue(robdd.evaluate([0]))
     self.assertTrue(robdd.evaluate([1]))
     self.assertTrue(robdd.evaluate([0, 0]))
     self.assertTrue(robdd.evaluate([0, 1, 1, 0]))