def construct_diagram(): pool = Pool() pool.int_var("x", "y") b = Builder(pool) bounds = b.test("x", ">=", 0) & b.test("x", "<=", 8) & b.test("y", ">=", 1) & b.test("y", "<=", 10) return bounds * b.ite(b.test("x", ">=", "y"), b.terminal("2*x + 3*y"), b.terminal("3*x + 2*y"))
def test_printing(self): import json encoded = Pool.to_json(self.diagram.pool) representation = json.loads(encoded) reconstructed = Pool.from_json(encoded) re_encoded = Pool.to_json(reconstructed) new_representation = json.loads(re_encoded) self.assertEquals(representation, new_representation)
def test_inversion(self): pool = Pool() build = Builder(pool) build.vars("bool", "a", "b") build.vars("int", "x") test1 = build.test("a") test2 = build.test("b") test3 = build.test("x", "<=", 5) node3 = build.ite(test3, 1, 0) diagram = build.ite(test1, build.ite(test2, node3, 1), node3) self.assertTrue(is_ordered(diagram)) def inversion1(root_id): minus_one = pool.terminal("-1") return pool.apply(Multiplication, pool.apply(Summation, root_id, minus_one), minus_one) def transform(terminal_node, d): if terminal_node.expression == 1: return d.pool.zero_id elif terminal_node.expression == 0: return d.pool.one_id else: raise RuntimeError("Could not invert value {}".format(terminal_node.expression)) def inversion2(root_id): to_invert = pool.diagram(root_id) profile = WalkingProfile(diagram) return leaf_transform.transform_leaves(transform, to_invert) iterations = 1000 timer = Timer(precision=6) timer.start("Legacy inversion") for _ in range(iterations): inversion1(diagram.root_id) time_legacy = timer.stop() inverted1 = pool.diagram(inversion1(diagram.root_id)) timer.start("New inversion") for _ in range(iterations): inversion2(diagram.root_id) time_new = timer.stop() inverted2 = pool.diagram(inversion2(diagram.root_id)) for a in [True, False]: for b in [True, False]: for x in range(10): assignment = {"a": a, "b": b, "x": x} self.assertNotEqual(diagram.evaluate(assignment), inverted1.evaluate(assignment)) self.assertNotEqual(diagram.evaluate(assignment), inverted2.evaluate(assignment)) self.assertTrue(time_legacy > time_new, "New inversion ({}) not faster than legacy implementation ({})" .format(time_new, time_legacy))
def test_not(self): pool = Pool() pool.int_var("x") dd_true = Diagram(pool, pool.bool_test(LinearTest("x", ">="))) dd_false = Diagram(pool, pool.invert(dd_true.root_node.node_id)) for i in range(-5, 6): assignment = {"x": i} self.assertEqual((dd_true.evaluate(assignment) + 1) % 2, dd_false.evaluate(assignment))
def test_summation_one_var(self): pool = Pool() pool.add_var("x", "int") pool.add_var("y", "int") b = Builder(pool) bounds = b.test("x", ">=", 0) & b.test("x", "<=", 10) d = b.ite(bounds, b.terminal("x"), b.terminal(0)) d_const = Diagram(pool, SummationWalker(d, "x").walk()) self.assertEqual(55, d_const.evaluate({}))
def construct_diagram(): pool = Pool(empty=True) pool.int_var("x") x = pool.terminal("x") zero = pool.terminal("0") test1 = pool.internal(LinearTest("x - 5", "<="), x, zero) test2 = pool.internal(LinearTest("x + 1", ">="), test1, zero) test3 = pool.internal(LinearTest("x + 2", "<="), x, test2) root = pool.internal(LinearTest("x", ">="), test1, test3) return Diagram(pool, root)
def get_looping_diagram(): pool = Pool() pool.int_var("x") test = LinearTest("x", "<=", "2") zero = pool.terminal(0) one = pool.terminal(1) node1 = pool.internal(test, one, zero) node2 = pool.internal(test, node1, zero) diagram = pool.diagram(node2) return diagram
def setUp(self): pool = Pool() pool.int_var("x") pool.int_var("y") pool.int_var("z") b = Builder(pool) self.diagrams = [] d = b.ite(b.test("x", "<=", "y"), b.terminal(1), b.test("x", "<=", 2)) self.diagrams.append(({"x", "y"}, d)) d = b.terminal("x * 2 * y + 5 * z") self.diagrams.append(({"x", "y", "z"}, d)) d = b.ite(b.test("x", "<", "y"), b.terminal("z"), b.terminal("z * y")) self.diagrams.append(({"x", "y", "z"}, d))
def setUp(self): pool = Pool() pool.int_var("x") lb = Diagram(pool, pool.bool_test(LinearTest("x - 1", ">="))) ub = Diagram(pool, pool.bool_test(LinearTest("x - 10", "<="))) test = Diagram(pool, pool.bool_test(LinearTest("x - 5", "<="))) term_one = Diagram(pool, pool.terminal("x + 2")) term_two = Diagram(pool, pool.terminal("7 - 2 * (x - 5)")) b1 = lb & ub & test * term_one b2 = lb & ub & ~test * term_two self.diagram = b1 + b2
def setUp(self): pool = Pool() pool.int_var("x") lb = Diagram(pool, pool.bool_test(LinearTest("x - 1", ">="))) ub = Diagram(pool, pool.bool_test(LinearTest("x - 10", "<="))) test = Diagram(pool, pool.bool_test(LinearTest("x - 5", "<="))) redundant_test = Diagram(pool, pool.bool_test(LinearTest("x - 6", "<="))) term_one = Diagram(pool, pool.terminal("x + 2")) term_two = Diagram(pool, pool.terminal("7 - 2 * (x - 5)")) b1 = (lb & ub & test & redundant_test) * term_one b2 = (lb & ub & ~test & redundant_test) * term_two self.diagram = b1 + b2 self.exporter = Exporter(os.path.join(os.path.dirname(os.path.realpath(__file__)), "visual"), "reduce")
def build_diagram_2(): b = Builder(Pool()) b.ints("r", "c") lb, ub = 1, 10 bounds = b.limit("r", lb, ub) & b.limit("c", lb, ub) t1 = b.ite(b.test("r", "<=", 0), 2, 4) t2 = b.ite(b.test("c", ">=", 11), 3, 5) return bounds * (t1 + t2)
def test_summation_two_var_test(self): pool = Pool() pool.add_var("x", "int") pool.add_var("y", "int") b = Builder(pool) bounds = b.test("x", ">=", 0) & b.test("x", "<=", 1) bounds &= b.test("y", ">=", 1) & b.test("y", "<=", 3) two = b.test("x", ">=", "y") d = b.ite(bounds, b.ite(two, b.terminal("x"), b.terminal("10")), b.terminal(0)) summed = Diagram(pool, SummationWalker(d, "x").walk()) d_const = summed.reduce(["y"]) for y in range(-20, 20): s = 0 for x in range(-20, 20): s += d.evaluate({"x": x, "y": y}) self.assertEqual(s, d_const.evaluate({"y": y}))
def test_multiplication(self): pool = Pool() pool.int_var("x") two = pool.terminal("2") x = pool.terminal("x") test1 = pool.bool_test(LinearTest("x", ">=")) test2 = pool.apply(Multiplication, pool.bool_test(LinearTest("x - 5", "<=")), x) product = pool.apply(Multiplication, test1, test2) result = Diagram(pool, pool.apply(Multiplication, product, two)) for i in range(0, 10): evaluated = result.evaluate({"x": i}) if 0 <= i <= 5: self.assertEqual(2 * i, evaluated) else: self.assertEqual(0, evaluated)
def build_diagram_1(): b = Builder(Pool()) b.ints("r", "c") lb = 1 ub = 10 bounds = b.limit("r", lb, ub) & b.limit("c", lb, ub) diagonal = b.test("r", "<=", "c") & b.test("r", ">=", "c") block_1 = b.test("r", ">", lb + (ub - lb) / 2) & b.test("c", "<=", lb + (ub - lb) / 2) block_2 = b.test("r", "<=", lb + (ub - lb) / 2) & b.test("c", ">", lb + (ub - lb) / 2) return bounds * (diagonal * b.exp(6) + (block_1 | block_2))
def setUp(self): pool_file = "data/test_evaluate_1.txt" root_id = 1663 with open(pool_file, "r") as stream: json_input = stream.readline() exported_pool = Pool.from_json(json_input) self.diagram1 = exported_pool.diagram(root_id) self.vars1 = [('r_f0', 0, 1658), ('r_f1', 0, 964), ('c_f0', 0, 1658), ('c_f1', 0, 964)]
def test_invert_terminal(self): pool = Pool() self.assertEquals(pool.zero_id, pool.invert(pool.one_id)) self.assertEquals(pool.one_id, pool.invert(pool.zero_id)) try: pool.invert(pool.terminal(2)) self.assertTrue(False) except RuntimeError: self.assertTrue(True)
def setUp(self): pool = Pool() self.builder = Builder(pool) self.builder.ints("x", "y") b = self.builder limits = b.limit("x", 0, 20) & b.limit("y", 0, 20) rect1 = b.limit("x", 0, 10) & b.limit("y", 0, 10) rect2 = b.limit("x", 5, 20) & b.limit("y", 10, 20) self.diagram = rect1 * b.terminal("5") \ + rect2 * b.terminal("x + 2") \ + ~(rect1 | rect2) & limits * b.terminal("1") self.exporter = Exporter( os.path.join(os.path.dirname(os.path.realpath(__file__)), "visual"), "transform")
def build_example1(): # http://www.math.cornell.edu/~mec/Winter2009/RalucaRemus/Lecture3/lecture3.html pool = Pool() build = Builder(pool) variables = [("i", 1, 4)] for var in variables: name = var[0] build.ints("r_{}".format(name), "c_{}".format(name), name) limits = build.limit("r_i", 1, 4) & build.limit("c_i", 1, 4) column1 = (build.limit("c_i", 1, 1) & build.limit("r_i", 2, 4)) * build.exp("1/3") column2 = (build.limit("c_i", 2, 2) & build.limit("r_i", 3, 4)) * build.exp("1/2") column3 = (build.limit("c_i", 3, 3) & build.limit("r_i", 1, 1)) * build.exp("1") column4 = (build.limit("c_i", 4, 4) & (build.limit("r_i", 1, 1) | build.limit("r_i", 3, 3))) * build.exp("1/2") diagram = limits * (column1 + column2 + column3 + column4) return diagram, variables
def test_leaf_transform_simple_test(self): pool = Pool() pool.int_var("x") test1 = pool.bool_test(LinearTest("x", ">=")) leaf_transform.transform_leaves(lambda t, d: d.pool.terminal(2), pool.diagram(test1))
from __future__ import print_function import itertools from png import Writer from pyxadd.build import Builder from pyxadd.diagram import Pool, Diagram from pyxadd.matrix.matrix import assignments from pyxadd.reduce import SmtReduce, LinearReduction from pyxadd.view import export pool = Pool() pool.add_var("x", "int") pool.add_var("xs", "int") pool.add_var("y", "int") pool.add_var("ys", "int") b = Builder(pool) # TODO needs control over interleaving class RedGreenBlueDiagrams(object): def __init__(self, red, green, blue): self.diagrams = (red, green, blue) @staticmethod def all(diagram): return RedGreenBlueDiagrams(diagram, diagram, diagram) def _binary(self, op, other): if isinstance(other, RedGreenBlueDiagrams):
def test_leaf_transform_leaf_node(self): pool = Pool() diagram = pool.diagram(pool.one_id) leaf_transform.transform_leaves(lambda t, d: d.pool.terminal(2), diagram)
def test_leaf_walking_leaf_node(self): pool = Pool() diagram = pool.diagram(pool.one_id) walk.walk_leaves(lambda p, n: True, diagram)
def setUp(self): pool = Pool() pool.int_var("x") self.test1 = pool.bool_test(LinearTest("x", ">=")) self.test2 = pool.bool_test(LinearTest("x + 2", ">")) self.test3 = pool.bool_test(LinearTest("x + 1", "<=")) self.test4 = pool.bool_test(LinearTest("x - 5", "<=")) self.x = pool.terminal("x") p1 = pool.apply(Multiplication, self.test1, self.test4) p2 = pool.apply(Multiplication, pool.invert(self.test1), self.test2) p3 = pool.apply( Multiplication, pool.apply( Multiplication, pool.apply(Multiplication, pool.invert(self.test1), pool.invert(self.test2)), self.test3), self.test4) result = pool.apply(Summation, pool.apply(Summation, p1, p2), p3) result = pool.apply(Multiplication, result, self.x) self.diagram = Diagram(pool, result)
def setUp(self): pool = Pool() pool.int_var("x") self.test1 = pool.bool_test(LinearTest("x", ">=")) self.test2 = pool.bool_test(LinearTest("x + 2", ">")) self.test3 = pool.bool_test(LinearTest("x + 1", "<=")) self.test4 = pool.bool_test(LinearTest("x - 5", "<=")) self.x = pool.terminal("x") p1 = pool.apply(Multiplication, self.test1, self.test4) p2 = pool.apply(Multiplication, pool.invert(self.test1), self.test2) p3 = pool.apply(Multiplication, pool.apply(Multiplication, pool.apply(Multiplication, pool.invert(self.test1), pool.invert(self.test2)), self.test3), self.test4) result = pool.apply(Summation, pool.apply(Summation, p1, p2), p3) result = pool.apply(Multiplication, result, self.x) self.diagram = Diagram(pool, result)
from pyxadd.build import Builder from pyxadd.diagram import Pool from pyxadd.view import export pool = Pool() b = Builder(pool) b.ints("r", "c") xadd_1 = b.terminal("5 + r * c") export(xadd_1, "visual/examples/xadd_1.dot") xadd_2 = b.limit("r", 1, 2) & b.limit("c", 1, 2) * xadd_1 export(xadd_2, "visual/examples/xadd_2.dot")
def test_inversion(self): pool = Pool() build = Builder(pool) build.vars("bool", "a", "b") build.vars("int", "x") test1 = build.test("a") test2 = build.test("b") test3 = build.test("x", "<=", 5) node3 = build.ite(test3, 1, 0) diagram = build.ite(test1, build.ite(test2, node3, 1), node3) self.assertTrue(is_ordered(diagram)) def inversion1(root_id): minus_one = pool.terminal("-1") return pool.apply(Multiplication, pool.apply(Summation, root_id, minus_one), minus_one) def transform(terminal_node, d): if terminal_node.expression == 1: return d.pool.zero_id elif terminal_node.expression == 0: return d.pool.one_id else: raise RuntimeError("Could not invert value {}".format( terminal_node.expression)) def inversion2(root_id): to_invert = pool.diagram(root_id) profile = WalkingProfile(diagram) return leaf_transform.transform_leaves(transform, to_invert) iterations = 1000 timer = Timer(precision=6) timer.start("Legacy inversion") for _ in range(iterations): inversion1(diagram.root_id) time_legacy = timer.stop() inverted1 = pool.diagram(inversion1(diagram.root_id)) timer.start("New inversion") for _ in range(iterations): inversion2(diagram.root_id) time_new = timer.stop() inverted2 = pool.diagram(inversion2(diagram.root_id)) for a in [True, False]: for b in [True, False]: for x in range(10): assignment = {"a": a, "b": b, "x": x} self.assertNotEqual(diagram.evaluate(assignment), inverted1.evaluate(assignment)) self.assertNotEqual(diagram.evaluate(assignment), inverted2.evaluate(assignment)) self.assertTrue( time_legacy > time_new, "New inversion ({}) not faster than legacy implementation ({})". format(time_new, time_legacy))
def __init__(self, pool=None): if pool is None: pool = Pool() assert isinstance(pool, Pool) self._pool = pool
def build_diagram1(): pool = Pool() b = Builder(pool) b.ints("x") return b.ite(b.test("x", "<=", 3), b.ite(b.test("x", "<=", 2), b.exp(1), b.exp("2*x")), b.exp(1))
def test_multiplication(self): pool = Pool() pool.int_var("x1", "x2") x_two = Diagram(pool, pool.terminal("x2")) two = Diagram(pool, pool.terminal("2")) three = Diagram(pool, pool.terminal("3")) four = Diagram(pool, pool.terminal("4")) test11 = Diagram(pool, pool.bool_test(LinearTest("x1", ">="))) test12 = Diagram(pool, pool.bool_test(LinearTest("x1 - 1", "<="))) test13 = Diagram(pool, pool.bool_test(LinearTest("x1 - 3", ">"))) test21 = Diagram(pool, pool.bool_test(LinearTest("x2", ">="))) test22 = Diagram(pool, pool.bool_test(LinearTest("x2", ">"))) test23 = Diagram(pool, pool.bool_test(LinearTest("x2 - 1", ">"))) test24 = Diagram(pool, pool.bool_test(LinearTest("x2 - 2", ">"))) x_twos = test12 * ~test23 * x_two twos = test12 * test23 * two threes = ~test12 * ~test22 * three fours = ~test12 * test22 * four unlimited = x_twos + twos + threes + fours restricted = unlimited * test11 * ~test13 * test21 * ~test24 vector = test21 * ~test24 * Diagram(pool, pool.terminal("x2 + 1")) result = Diagram(pool, matrix_multiply(pool, restricted.root_node.node_id, vector.root_node.node_id, ["x2"])) for x1 in range(0, 4): self.assertEqual(8 if x1 < 2 else 23, result.evaluate({"x1": x1}))
def get_unordered_diagram(): pool = Pool() pool.int_var("x") test1 = LinearTest("x", "<=", "2") test2 = LinearTest("x", "<=", "3") zero = pool.terminal(0) one = pool.terminal(1) pool.internal(test1, one, zero) pool.internal(test2, one, zero) # test2 => test1 => 1 node1 = pool.internal(test1, one, zero) node2 = pool.internal(test2, node1, zero) diagram = pool.diagram(node2) return diagram