def test_paper_example(self):

        solver = SimplexSolver()

        left = Variable('left')
        middle = Variable('middle')
        right = Variable('right')

        solver.add_constraint(middle == (left + right) / 2)
        solver.add_constraint(right == left + 10)
        solver.add_constraint(right <= 100)
        solver.add_constraint(left >= 0)

        # Check that all the required constraints are true:
        self.assertAlmostEqual((left.value + right.value) / 2, middle.value)
        self.assertAlmostEqual(right.value, left.value + 10)
        self.assertGreaterEqual(left.value, 0)
        self.assertLessEqual(right.value, 100)

        # Set the middle value to a stay
        middle.value = 45.0
        solver.add_stay(middle)

        # Check that all the required constraints are true:
        self.assertAlmostEqual((left.value + right.value) / 2, middle.value)
        self.assertAlmostEqual(right.value, left.value + 10)
        self.assertGreaterEqual(left.value, 0)
        self.assertLessEqual(right.value, 100)

        # But more than that - since we gave a position for middle, we know
        # where all the points should be.

        self.assertAlmostEqual(left.value, 40)
        self.assertAlmostEqual(middle.value, 45)
        self.assertAlmostEqual(right.value, 50)
Example #2
0
    def test_delete2(self):
        solver = SimplexSolver()
        x = Variable('x')
        y = Variable('y')

        solver.add_constraint(Constraint(x, Constraint.EQ, 100, WEAK))
        solver.add_constraint(Constraint(y, Constraint.EQ, 120, STRONG))
        c10 = Constraint(x, Constraint.LEQ, 10)
        c20 = Constraint(x, Constraint.LEQ, 20)
        solver.add_constraint(c10)
        solver.add_constraint(c20)
        self.assertAlmostEqual(x.value, 10)
        self.assertAlmostEqual(y.value, 120)

        solver.remove_constraint(c10)
        self.assertAlmostEqual(x.value, 20)
        self.assertAlmostEqual(y.value, 120)

        cxy = Constraint(x * 2, Constraint.EQ, y)
        solver.add_constraint(cxy)
        self.assertAlmostEqual(x.value, 20)
        self.assertAlmostEqual(y.value, 40)

        solver.remove_constraint(c20)
        self.assertAlmostEqual(x.value, 60)
        self.assertAlmostEqual(y.value, 120)

        solver.remove_constraint(cxy)
        self.assertAlmostEqual(x.value, 100)
        self.assertAlmostEqual(y.value, 120)
Example #3
0
    def test_strength(self):
        "Solvers should handle strengths correctly"
        solver = SimplexSolver()
        x = Variable(name='x', value=10)
        y = Variable(name='y', value=20)
        z = Variable(name='z', value=1)
        w = Variable(name='w', value=1)

        # Default weights.
        e0 = Constraint(x, Constraint.EQ, y)
        solver.add_stay(y)

        solver.add_constraint(e0)
        self.assertAlmostEqual(x.value, 20.0)
        self.assertAlmostEqual(y.value, 20.0)

        # Add a weak constraint.
        e1 = Constraint(x, Constraint.EQ, z, strength=WEAK)
        solver.add_stay(x)
        solver.add_constraint(e1)
        self.assertAlmostEqual(x.value, 20.0)
        self.assertAlmostEqual(z.value, 20.0)

        # Add a strong constraint.
        e2 = Constraint(z, Constraint.EQ, w, strength=STRONG)
        solver.add_stay(w)
        solver.add_constraint(e2)
        self.assertAlmostEqual(w.value, 1.0)
        self.assertAlmostEqual(z.value, 1.0)
Example #4
0
    def test_add_variable(self):
        o = Variable('o', 10)
        a = Expression(o, 20, 2)
        v = Variable('v', 20)

        self.assertEqual(len(a.terms), 1)
        self.assertAlmostEqual(a.terms.get(o), 20.0)

        # implicit coefficient of 1
        a.add_variable(v)
        self.assertEqual(len(a.terms), 2)
        self.assertAlmostEqual(a.terms.get(v), 1.0)

        # add again, with different coefficient
        a.add_variable(v, 2.0)
        self.assertEqual(len(a.terms), 2)
        self.assertAlmostEqual(a.terms.get(v), 3.0)

        # add again, with resulting 0 coefficient. should remove the term.
        a.add_variable(v, -3)
        self.assertEqual(len(a.terms), 1)
        self.assertIsNone(a.terms.get(v))

        # try adding the removed term back, with 0 coefficient
        a.add_variable(v, 0)
        self.assertEqual(len(a.terms), 1)
        self.assertIsNone(a.terms.get(v))
Example #5
0
    def test_coefficient_for(self):
        va = Variable('a', 10)
        vb = Variable('b', 20)
        a = Expression(va, 20, 2)

        self.assertEqual(a.coefficient_for(va), 20)
        self.assertEqual(a.coefficient_for(vb), 0)
Example #6
0
    def test_mul(self):
        x = Variable('x', 167)
        y = Variable('y', 42)

        # Multiply an expression by a constant
        self.assertExpressionEqual(Expression(x) * 2, '2.0*x[167.0]')
        self.assertExpressionEqual(3 * Expression(x), '3.0*x[167.0]')

        # Can't multiply an expression by a variable unless the expression is a constant
        with self.assertRaises(TypeError):
            y * Expression(x)
        with self.assertRaises(TypeError):
            Expression(x) * y
        self.assertExpressionEqual(x * Expression(constant=2), '2.0*x[167.0]')
        self.assertExpressionEqual(Expression(constant=3) * x, '3.0*x[167.0]')

        # Can't multiply an expression by an expression unless
        # one of the expressions is a constant.
        with self.assertRaises(TypeError):
            Expression(x) * Expression(y)
        with self.assertRaises(TypeError):
            Expression(x, 20, 2) * Expression(y, 10, 5)
        self.assertExpressionEqual(
            Expression(x, 20, 2) * Expression(constant=5),
            '10.0 + 100.0*x[167.0]')
        self.assertExpressionEqual(
            Expression(x, 20) * Expression(constant=5), '100.0*x[167.0]')
        self.assertExpressionEqual(
            Expression(constant=2) * Expression(y, 10, 5),
            '10.0 + 20.0*y[42.0]')
        self.assertExpressionEqual(
            Expression(constant=2) * Expression(y, 10), '20.0*y[42.0]')
Example #7
0
    def test_paper_example(self):

        solver = SimplexSolver()

        left = Variable('left')
        middle = Variable('middle')
        right = Variable('right')

        solver.add_constraint(middle == (left + right) / 2)
        solver.add_constraint(right == left + 10)
        solver.add_constraint(right <= 100)
        solver.add_constraint(left >= 0)

        # Check that all the required constraints are true:
        self.assertAlmostEqual((left.value + right.value) / 2, middle.value)
        self.assertAlmostEqual(right.value, left.value + 10)
        self.assertGreaterEqual(left.value, 0)
        self.assertLessEqual(right.value, 100)

        # Set the middle value to a stay
        middle.value = 45.0
        solver.add_stay(middle)

        # Check that all the required constraints are true:
        self.assertAlmostEqual((left.value + right.value) / 2, middle.value)
        self.assertAlmostEqual(right.value, left.value + 10)
        self.assertGreaterEqual(left.value, 0)
        self.assertLessEqual(right.value, 100)

        # But more than that - since we gave a position for middle, we know
        # where all the points should be.

        self.assertAlmostEqual(left.value, 40)
        self.assertAlmostEqual(middle.value, 45)
        self.assertAlmostEqual(right.value, 50)
Example #8
0
    def test_add_edit_var_required_after_suggestions(self):
        "Solver works with REQUIRED strength after many suggestions"
        solver = SimplexSolver()
        a = Variable(name='a')
        b = Variable(name='b')

        solver.add_stay(a, STRONG, 0)
        solver.add_constraint(Constraint(a, Constraint.EQ, b, REQUIRED))
        solver.resolve()

        self.assertEqual(b.value, 0)
        self.assertEqual(a.value, 0)

        solver.add_edit_var(a, REQUIRED)
        solver.begin_edit()
        solver.suggest_value(a, 2)
        solver.resolve()

        self.assertEqual(a.value, 2)
        self.assertEqual(b.value, 2)

        solver.suggest_value(a, 10)
        solver.resolve()

        self.assertEqual(a.value, 10)
        self.assertEqual(b.value, 10)
Example #9
0
    def test_operator_arguments_to_inequality(self):
        v1 = Variable(name='v1', value=10)
        v2 = Variable(name='v2', value=5)
        ieq = Constraint(v1, Constraint.GEQ, v2)
        self.assertExpressionEqual(ieq.expression, v1 - v2)

        ieq = Constraint(v1, Constraint.LEQ, v2)
        self.assertExpressionEqual(ieq.expression, v2 - v1)
Example #10
0
    def test_constructor_with_variable_operator_expression_args2(self):
        v = Variable(name='v', value=10)
        e = Expression(Variable(name='x', value=5), 2, 4)
        ieq = Constraint(e, Constraint.GEQ, v)
        self.assertExpressionEqual(ieq.expression, e - v)

        ieq = Constraint(e, Constraint.LEQ, v)
        self.assertExpressionEqual(ieq.expression, v - e)
Example #11
0
    def test_add_expression_variable(self):
        a = Expression(Variable('o', 10), 20, 2)
        v = Variable('v', 20)

        # should work just like add_variable
        a.add_expression(v, 2)
        self.assertEqual(len(a.terms), 2)
        self.assertEqual(a.terms.get(v), 2)
Example #12
0
    def test_change_subject(self):
        va = Variable('a', 10)
        vb = Variable('b', 5)
        e = Expression(va, 2, 5)

        e.change_subject(vb, va)
        self.assertEqual(e.constant, -2.5)
        self.assertIsNone(e.terms.get(va))
        self.assertEqual(e.terms.get(vb), 0.5)
Example #13
0
    def test_is_constant(self):
        e1 = Expression()
        e2 = Expression(constant=10)
        e3 = Expression(Variable('o', 10), 20)
        e4 = Expression(Variable('o', 10), 20, 2)

        self.assertTrue(e1.is_constant)
        self.assertTrue(e2.is_constant)
        self.assertFalse(e3.is_constant)
        self.assertFalse(e4.is_constant)
Example #14
0
    def test_stay(self):
        x = Variable('x', 5)
        y = Variable('y', 10)

        solver = SimplexSolver()
        solver.add_stay(x)
        solver.add_stay(y)

        self.assertAlmostEqual(x.value, 5)
        self.assertAlmostEqual(y.value, 10)
Example #15
0
    def test_simple(self):
        solver = SimplexSolver()

        x = Variable('x', 167)
        y = Variable('y', 2)
        eq = Constraint(x, Constraint.EQ, y)

        solver.add_constraint(eq)
        self.assertAlmostEqual(x.value, y.value)
        self.assertAlmostEqual(x.value, 0)
        self.assertAlmostEqual(y.value, 0)
Example #16
0
    def test_multiedit1(self):
        # This test stresses the edit session stack. begin_edit() starts a new
        # "edit variable group" and "end_edit" closes it, leaving only the
        # previously opened edit variables still active.
        x = Variable('x')
        y = Variable('y')
        w = Variable('w')
        h = Variable('h')
        solver = SimplexSolver()

        # Add some stays
        solver.add_stay(x)
        solver.add_stay(y)
        solver.add_stay(w)
        solver.add_stay(h)

        # start an editing session
        solver.add_edit_var(x)
        solver.add_edit_var(y)

        with solver.edit():
            solver.suggest_value(x, 10)
            solver.suggest_value(y, 20)

            # Force the system to resolve.
            solver.resolve()

            self.assertAlmostEqual(x.value, 10)
            self.assertAlmostEqual(y.value, 20)
            self.assertAlmostEqual(w.value, 0)
            self.assertAlmostEqual(h.value, 0)

            # Open a second set of variables for editing
            solver.add_edit_var(w)
            solver.add_edit_var(h)

            with solver.edit():
                solver.suggest_value(w, 30)
                solver.suggest_value(h, 40)

            # Close the second set...
            self.assertAlmostEqual(x.value, 10)
            self.assertAlmostEqual(y.value, 20)
            self.assertAlmostEqual(w.value, 30)
            self.assertAlmostEqual(h.value, 40)

            # Now make sure the first set can still be edited
            solver.suggest_value(x, 50)
            solver.suggest_value(y, 60)

        self.assertAlmostEqual(x.value, 50)
        self.assertAlmostEqual(y.value, 60)
        self.assertAlmostEqual(w.value, 30)
        self.assertAlmostEqual(h.value, 40)
Example #17
0
 def test_inconsistent4(self):
     solver = SimplexSolver()
     x = Variable('x')
     y = Variable('y')
     # x = 10
     solver.add_constraint(Constraint(x, Constraint.EQ, 10))
     # x = y
     solver.add_constraint(Constraint(x, Constraint.EQ, y))
     # y = 5. Should fail.
     with self.assertRaises(RequiredFailure):
         solver.add_constraint(Constraint(y, Constraint.EQ, 5))
Example #18
0
 def initialSetup(self, layer):
   self.solver = SimplexSolver()
   self.nodehash = {}
   for p in layer.paths:
     for n in p.nodes:
       nid = n.hash()
       self.nodehash[nid] = {
         "node": n,
         "xvar": Variable("x"+str(nid), n.position.x),
         "yvar": Variable("y"+str(nid), n.position.y),
         "affected": set()
       }
   self.setConstraintsFromHints(layer)
Example #19
0
    def test_casso1(self):
        solver = SimplexSolver()
        x = Variable('x')
        y = Variable('y')

        solver.add_constraint(Constraint(x, Constraint.LEQ, y))
        solver.add_constraint(Constraint(y, Constraint.EQ, x + 3))
        solver.add_constraint(Constraint(x, Constraint.EQ, 10, WEAK))
        solver.add_constraint(Constraint(y, Constraint.EQ, 10, WEAK))

        self.assertTrue(
            (approx_equal(x.value, 10) and approx_equal(y.value, 13))
            or (approx_equal(x.value, 7) and approx_equal(y.value, 10)))
Example #20
0
    def test_multiedit2(self):

        x = Variable('x')
        y = Variable('y')
        w = Variable('w')
        h = Variable('h')

        solver = SimplexSolver()
        solver.add_stay(x)
        solver.add_stay(y)
        solver.add_stay(w)
        solver.add_stay(h)
        solver.add_edit_var(x)
        solver.add_edit_var(y)

        solver.begin_edit()
        solver.suggest_value(x, 10)
        solver.suggest_value(y, 20)
        solver.resolve()
        solver.end_edit()

        self.assertAlmostEqual(x.value, 10)
        self.assertAlmostEqual(y.value, 20)
        self.assertAlmostEqual(w.value, 0)
        self.assertAlmostEqual(h.value, 0)

        solver.add_edit_var(w)
        solver.add_edit_var(h)

        solver.begin_edit()
        solver.suggest_value(w, 30)
        solver.suggest_value(h, 40)
        solver.end_edit()

        self.assertAlmostEqual(x.value, 10)
        self.assertAlmostEqual(y.value, 20)
        self.assertAlmostEqual(w.value, 30)
        self.assertAlmostEqual(h.value, 40)

        solver.add_edit_var(x)
        solver.add_edit_var(y)

        solver.begin_edit()
        solver.suggest_value(x, 50)
        solver.suggest_value(y, 60)
        solver.end_edit()

        self.assertAlmostEqual(x.value, 50)
        self.assertAlmostEqual(y.value, 60)
        self.assertAlmostEqual(w.value, 30)
        self.assertAlmostEqual(h.value, 40)
Example #21
0
    def test_inconsistent3(self):
        solver = SimplexSolver()
        w = Variable('w')
        x = Variable('x')
        y = Variable('y')
        z = Variable('z')
        solver.add_constraint(Constraint(w, Constraint.GEQ, 10))
        solver.add_constraint(Constraint(x, Constraint.GEQ, w))
        solver.add_constraint(Constraint(y, Constraint.GEQ, x))
        solver.add_constraint(Constraint(z, Constraint.GEQ, y))
        solver.add_constraint(Constraint(z, Constraint.GEQ, 8))

        with self.assertRaises(RequiredFailure):
            solver.add_constraint(Constraint(z, Constraint.LEQ, 4))
Example #22
0
    def test_set_variable(self):
        va = Variable('a', 10)
        vb = Variable('b', 20)
        a = Expression(va, 20, 2)

        # set existing variable
        a.set_variable(va, 2)
        self.assertEqual(len(a.terms), 1)
        self.assertEqual(a.coefficient_for(va), 2)

        # set new variable
        a.set_variable(vb, 2)
        self.assertEqual(len(a.terms), 2)
        self.assertEqual(a.coefficient_for(vb), 2)
Example #23
0
    def test_leq_with_stay(self):
        # stay width
        # 100 <= right
        solver = SimplexSolver()

        x = Variable('x', 10)
        width = Variable('width', 10)
        right = x + width
        ieq = Constraint(100, Constraint.LEQ, right)

        solver.add_stay(width)
        solver.add_constraint(ieq)

        self.assertAlmostEqual(x.value, 90)
        self.assertAlmostEqual(width.value, 10)
Example #24
0
    def test_inconsistent2(self):
        solver = SimplexSolver()
        x = Variable('x')
        solver.add_constraint(Constraint(x, Constraint.GEQ, 10))

        with self.assertRaises(RequiredFailure):
            solver.add_constraint(Constraint(x, Constraint.LEQ, 5))
Example #25
0
    def test_delete1(self):
        solver = SimplexSolver()
        x = Variable('x')
        cbl = Constraint(x, Constraint.EQ, 100, WEAK)
        solver.add_constraint(cbl)

        c10 = Constraint(x, Constraint.LEQ, 10)
        c20 = Constraint(x, Constraint.LEQ, 20)
        solver.add_constraint(c10)
        solver.add_constraint(c20)
        self.assertAlmostEqual(x.value, 10)

        solver.remove_constraint(c10)
        self.assertAlmostEqual(x.value, 20)

        solver.remove_constraint(c20)
        self.assertAlmostEqual(x.value, 100)

        c10again = Constraint(x, Constraint.LEQ, 10)
        solver.add_constraint(c10)
        solver.add_constraint(c10again)
        self.assertAlmostEqual(x.value, 10)

        solver.remove_constraint(c10)
        self.assertAlmostEqual(x.value, 10)

        solver.remove_constraint(c10again)
        self.assertAlmostEqual(x.value, 100)
Example #26
0
    def test_expression_with_variable_and_operators(self):
        v = Variable(name='v', value=10)
        ieq = Constraint(v, Constraint.GEQ, 5)
        self.assertExpressionEqual(ieq.expression, v - 5)

        ieq = Constraint(v, Constraint.LEQ, 5)
        self.assertExpressionEqual(ieq.expression, 5 - v)
Example #27
0
    def test_variable_leq_constant(self):
        solver = SimplexSolver()

        x = Variable('x', 100)
        ieq = Constraint(x, Constraint.LEQ, 10)
        solver.add_constraint(ieq)

        self.assertAlmostEqual(x.value, 10)
Example #28
0
    def test_new_subject(self):
        v = Variable('v', 10)
        e = Expression(v, 2, 5)

        self.assertEqual(e.new_subject(v), 0.5)
        self.assertEqual(e.constant, -2.5)
        self.assertIsNone(e.terms.get(v))
        self.assertTrue(e.is_constant)
Example #29
0
    def test_full_expression(self):
        x = Variable('x', 167)

        expr = Expression(x, 2, 3)
        self.assertExpressionEqual(expr, '3.0 + 2.0*x[167.0]')
        self.assertAlmostEqual(expr.constant, 3.0)
        self.assertEqual(len(expr.terms), 1)
        self.assertAlmostEqual(expr.terms.get(x), 2.0)
Example #30
0
    def test_variable_equal_constant(self):
        solver = SimplexSolver()

        x = Variable('x', 10)
        eq = Constraint(100, Constraint.EQ, x)
        solver.add_constraint(eq)

        self.assertAlmostEqual(x.value, 100)
Example #31
0
    def test_clone(self):
        v = Variable('v', 10)
        expr = Expression(v, 20, 2)
        clone = expr.clone()

        self.assertEqual(clone.constant, expr.constant)
        self.assertEqual(len(clone.terms), len(expr.terms))
        self.assertEqual(clone.terms.get(v), 20)
    def test_buttons(self):
        "A test of a horizontal layout of two buttons on a screen."

        class Button(object):
            def __init__(self, identifier):
                self.left = Variable('left' + identifier, 0)
                self.width = Variable('width' + identifier, 0)

            def __repr__(self):
                return u'(%s:%s)' % (self.left.value, self.width.value)

        solver = SimplexSolver()

        b1 = Button('b1')
        b2 = Button('b2')
        left_limit = Variable('left', 0)
        right_limit = Variable('width', 0)

        left_limit.value = 0
        solver.add_stay(left_limit, REQUIRED)
        stay = solver.add_stay(right_limit, WEAK)

        # The two buttons are the same width
        solver.add_constraint(b1.width == b2.width)

        # b1 starts 50 from the left margin.
        solver.add_constraint(b1.left == left_limit + 50)

        # b2 ends 50 from the right margin
        solver.add_constraint(left_limit + right_limit == b2.left + b2.width + 50)

        # b2 starts at least 100 from the end of b1
        solver.add_constraint(b2.left >= (b1.left + b1.width + 100))

        # b1 has a minimum width of 87
        solver.add_constraint(b1.width >= 87)

        # b1's preferred width is 87
        solver.add_constraint(b1.width == 87, STRONG)

        # b2's minimum width is 113
        solver.add_constraint(b2.width >= 113)

        # b2's preferred width is 113
        solver.add_constraint(b2.width == 113, STRONG)

        # Without imposign a stay on the right, right_limit will be the minimum width for the layout
        self.assertAlmostEqual(b1.left.value, 50.0)
        self.assertAlmostEqual(b1.width.value, 113.0)
        self.assertAlmostEqual(b2.left.value, 263.0)
        self.assertAlmostEqual(b2.width.value, 113.0)
        self.assertAlmostEqual(right_limit.value, 426.0)

        # The window is 500 pixels wide.
        right_limit.value = 500
        stay = solver.add_stay(right_limit, REQUIRED)
        self.assertAlmostEqual(b1.left.value, 50.0)
        self.assertAlmostEqual(b1.width.value, 113.0)
        self.assertAlmostEqual(b2.left.value, 337.0)
        self.assertAlmostEqual(b2.width.value, 113.0)
        self.assertAlmostEqual(right_limit.value, 500.0)
        solver.remove_constraint(stay)

        # Expand to 700 pixels
        right_limit.value = 700
        stay = solver.add_stay(right_limit, REQUIRED)
        self.assertAlmostEqual(b1.left.value, 50.0)
        self.assertAlmostEqual(b1.width.value, 113.0)
        self.assertAlmostEqual(b2.left.value, 537.0)
        self.assertAlmostEqual(b2.width.value, 113.0)
        self.assertAlmostEqual(right_limit.value, 700.0)
        solver.remove_constraint(stay)

        # Contract to 600
        right_limit.value = 600
        stay = solver.add_stay(right_limit, REQUIRED)
        self.assertAlmostEqual(b1.left.value, 50.0)
        self.assertAlmostEqual(b1.width.value, 113.0)
        self.assertAlmostEqual(b2.left.value, 437.0)
        self.assertAlmostEqual(b2.width.value, 113.0)
        self.assertAlmostEqual(right_limit.value, 600.0)
        solver.remove_constraint(stay)