def test_term_rich_compare_operations(op, symbol): """Test using comparison on variables. """ v = Variable('foo') v2 = Variable('bar') t1 = Term(v, 10) t2 = Term(v2, 20) if symbol is not None: c = op(t1, t2 + 1) assert isinstance(c, Constraint) e = c.expression() t = e.terms() assert len(t) == 2 if t[0].variable() is not v: t = (t[1], t[0]) assert (t[0].variable() is v and t[0].coefficient() == 10 and t[1].variable() is v2 and t[1].coefficient() == -20) assert e.constant() == -1 assert c.op() == symbol and c.strength() == strength.required else: with pytest.raises(TypeError): op(t1, t2)
def test_handling_infeasible_constraints(): """Test that we properly handle infeasible constraints. We use the example of the cassowary paper to generate an infeasible situation after updating an edit variable which causes the solver to use the dual optimization. """ xm = Variable('xm') xl = Variable('xl') xr = Variable('xr') s = Solver() s.addEditVariable(xm, 'strong') s.addEditVariable(xl, 'weak') s.addEditVariable(xr, 'weak') s.addConstraint(2 * xm == xl + xr) s.addConstraint(xl + 20 <= xr) s.addConstraint(xl >= -10) s.addConstraint(xr <= 100) s.suggestValue(xm, 40) s.suggestValue(xr, 50) s.suggestValue(xl, 30) # First update causing a normal update. s.suggestValue(xm, 60) # Create an infeasible condition triggering a dual optimization s.suggestValue(xm, 90) s.updateVariables() assert xl.value() + xr.value() == 2 * xm.value() assert xl.value() == 80 assert xr.value() == 100
def test_variable_methods(): """Test the variable modification methods. """ v = Variable() assert v.name() == "" v.setName(u'γ') assert v.name() == 'γ' v.setName('foo') assert v.name() == 'foo' with pytest.raises(TypeError): v.setName(1) if sys.version_info >= (3, ): with pytest.raises(TypeError): v.setName(b'r') assert v.value() == 0.0 assert v.context() is None ctx = object() v.setContext(ctx) assert v.context() is ctx assert str(v) == 'foo' with pytest.raises(TypeError): Variable(1)
def test_suggesting_values_for_edit_variables(): """Test suggesting values in different situations. """ # Suggest value for an edit variable entering a weak equality s = Solver() v1 = Variable('foo') s.addEditVariable(v1, 'medium') s.addConstraint((v1 == 1) | 'weak') s.suggestValue(v1, 2) s.updateVariables() assert v1.value() == 2 # Suggest a value for an edit variable entering multiple solver rows s.reset() v1 = Variable('foo') v2 = Variable('bar') s = Solver() s.addEditVariable(v2, 'weak') s.addConstraint(v1 + v2 == 0) s.addConstraint((v2 <= -1)) s.addConstraint((v2 >= 0) | 'weak') s.suggestValue(v2, 0) s.updateVariables() assert v2.value() <= -1
def test_expression_rich_compare_operations(): """Test using comparison on variables. """ v = Variable('foo') v2 = Variable('bar') t1 = Term(v, 10) e1 = t1 + 5 e2 = v2 - 10 for op, symbol in ((operator.le, '<='), (operator.eq, '=='), (operator.ge, '>=')): c = op(e1, e2) assert isinstance(c, Constraint) e = c.expression() t = e.terms() assert len(t) == 2 if t[0].variable() is not v: t = (t[1], t[0]) assert (t[0].variable() is v and t[0].coefficient() == 10 and t[1].variable() is v2 and t[1].coefficient() == -1) assert e.constant() == 15 assert c.op() == symbol and c.strength() == strength.required for op in (operator.lt, operator.ne, operator.gt): with pytest.raises(TypeError): op(v, v2)
def test_expression_creation(): """Test the Term constructor. """ v = Variable('foo') v2 = Variable('bar') v3 = Variable('aux') e1 = Expression((v * 1, v2 * 2, v3 * 3)) e2 = Expression((v * 1, v2 * 2, v3 * 3), 10) for e, val in ((e1, 0), (e2, 10)): t = e.terms() assert (len(t) == 3 and t[0].variable() is v and t[0].coefficient() == 1 and t[1].variable() is v2 and t[1].coefficient() == 2 and t[2].variable() is v3 and t[2].coefficient() == 3) assert e.constant() == val assert str(e2) == '1 * foo + 2 * bar + 3 * aux + 10' with pytest.raises(TypeError) as excinfo: Expression((1, v2 * 2, v3 * 3)) assert 'Term' in excinfo.exconly() # ensure we test garbage collection. del e2 gc.collect()
def test_dumping_solver(capsys): """Test dumping the solver internal to stdout. """ v1 = Variable('foo') v2 = Variable('bar') s = Solver() s.addEditVariable(v2, 'weak') s.addConstraint(v1 + v2 == 0) s.addConstraint((v2 <= -1)) s.addConstraint((v2 >= 0) | 'weak') s.updateVariables() try: s.addConstraint((v2 >= 1)) except Exception: pass # Print the solver state s.dump() state = s.dumps() for header in ('Objective', 'Tableau', 'Infeasible', 'Variables', 'Edit Variables', 'Constraints'): assert header in state
def test_expression_rich_compare_operations(op, symbol): """Test using comparison on variables. """ v1 = Variable('foo') v2 = Variable('bar') t1 = Term(v1, 10) e1 = t1 + 5 e2 = v2 - 10 if symbol is not None: c = op(e1, e2) assert isinstance(c, Constraint) e = c.expression() t = e.terms() assert len(t) == 2 if t[0].variable() is not v1: t = (t[1], t[0]) assert (t[0].variable() is v1 and t[0].coefficient() == 10 and t[1].variable() is v2 and t[1].coefficient() == -1) assert e.constant() == 15 assert c.op() == symbol and c.strength() == strength.required else: with pytest.raises(TypeError) as excinfo: op(e1, e2) assert "kiwisolver.Expression" in excinfo.exconly()
def test_variable_arith_operators(): """Test the arithmetic operation on variables. """ v = Variable('foo') v2 = Variable('bar') neg = -v assert isinstance(neg, Term) assert neg.variable() is v and neg.coefficient() == -1 mul = v * 2.0 assert isinstance(mul, Term) assert mul.variable() is v and mul.coefficient() == 2 with pytest.raises(TypeError): v * v2 div = v / 2.0 assert isinstance(div, Term) assert div.variable() is v and div.coefficient() == 0.5 with pytest.raises(TypeError): v / v2 add = v + 2 assert isinstance(add, Expression) assert add.constant() == 2 terms = add.terms() assert (len(terms) == 1 and terms[0].variable() is v and terms[0].coefficient() == 1) add2 = v + v2 assert isinstance(add2, Expression) assert add2.constant() == 0 terms = add2.terms() assert (len(terms) == 2 and terms[0].variable() is v and terms[0].coefficient() == 1 and terms[1].variable() is v2 and terms[1].coefficient() == 1) sub = v - 2 assert isinstance(sub, Expression) assert sub.constant() == -2 terms = sub.terms() assert (len(terms) == 1 and terms[0].variable() is v and terms[0].coefficient() == 1) sub2 = v - v2 assert isinstance(sub2, Expression) assert sub2.constant() == 0 terms = sub2.terms() assert (len(terms) == 2 and terms[0].variable() is v and terms[0].coefficient() == 1 and terms[1].variable() is v2 and terms[1].coefficient() == -1) with pytest.raises(TypeError): v + ''
def test_basic_solver(): s = Solver() x0 = Variable('x0') x1 = Variable('x1') s.addConstraint(x0 >= 0) s.addConstraint(x1 >= 0) s.updateVariables() assert x0.value() == 0.0 assert x1.value() == 0.0
def terms(): """Terms for testing. """ v = Variable('foo') v2 = Variable('bar') t = Term(v, 10) t2 = Term(v2) return t, t2, v, v2
def expressions(): """Build expressions, terms and variables to test operations. """ v = Variable('foo') v2 = Variable('bar') t = Term(v, 10) t2 = Term(v2) e = t + 5 e2 = v2 - 10 return e, e2, t, t2, v, v2
def test_variable_mul(): """Test variable multiplications. """ v = Variable("foo") v2 = Variable('bar') for mul in (v * 2.0, 2 * v): assert isinstance(mul, Term) assert mul.variable() is v and mul.coefficient() == 2 with pytest.raises(TypeError): v * v2
def test_dumping_solver(capsys): """Test dumping the solver internal to stdout. """ v1 = Variable('foo') v2 = Variable('bar') s = Solver() s.addConstraint(v1 + v2 == 0) s.addConstraint(v1 == 10) s.addConstraint((v2 >= 0) | 'weak') s.updateVariables() s.dump()
def test_variable_division(): """Test variable divisions. """ v = Variable("foo") v2 = Variable('bar') div = v / 2.0 assert isinstance(div, Term) assert div.variable() is v and div.coefficient() == 0.5 with pytest.raises(TypeError): v / v2 with pytest.raises(ZeroDivisionError): v / 0
def test_managing_constraints(): """Test adding/removing constraints. """ s = Solver() v = Variable('foo') c1 = v >= 1 c2 = v <= 0 with pytest.raises(TypeError): s.hasConstraint(object()) with pytest.raises(TypeError): s.addConstraint(object()) with pytest.raises(TypeError): s.removeConstraint(object()) assert not s.hasConstraint(c1) s.addConstraint(c1) assert s.hasConstraint(c1) with pytest.raises(DuplicateConstraint): s.addConstraint(c1) with pytest.raises(UnknownConstraint): s.removeConstraint(c2) with pytest.raises(UnsatisfiableConstraint): s.addConstraint(c2) s.removeConstraint(c1) assert not s.hasConstraint(c1) s.addConstraint(c2) assert s.hasConstraint(c2) s.reset() assert not s.hasConstraint(c2)
def test_solver(): s = Solver() x0 = Variable('x0') x1 = Variable('x1') s.addConstraint(x0 >= 0) s.addConstraint(x1 >= 0) s.addConstraint(x1 == x0) s.updateVariables() assert x0.value() == 0.0 assert x1.value() == 0.0 with edit_context(s, [x1]): s.suggestValue(x1, 1.0) s.updateVariables() assert x0.value() == 1.0 assert x1.value() == 1.0
def test_constraint_repr(op): """Test the repr method of a constraint object. """ v = Variable('foo') c = Constraint(v + 1, op) assert op in repr(c)
def test_variable_neg(): """Test neg on a variable. """ v = Variable("foo") neg = -v assert isinstance(neg, Term) assert neg.variable() is v and neg.coefficient() == -1
def test_solver_creation(): """Test initializing a solver. """ s = Solver() assert isinstance(s, Solver) with pytest.raises(TypeError): Solver(Variable())
def test_expression_creation(): """Test the Term constructor. """ v = Variable('foo') v2 = Variable('bar') v3 = Variable('aux') e1 = Expression((v * 1, v2 * 2, v3 * 3)) e2 = Expression((v * 1, v2 * 2, v3 * 3), 10) for e, val in ((e1, 0), (e2, 10)): t = e.terms() assert (len(t) == 3 and t[0].variable() is v and t[0].coefficient() == 1 and t[1].variable() is v2 and t[1].coefficient() == 2 and t[2].variable() is v3 and t[2].coefficient() == 3) assert e.constant() == val assert str(e2) == '1 * foo + 2 * bar + 3 * aux + 10'
def test_variable_sub(): """Test variable substractions. """ v = Variable("foo") v2 = Variable('bar') for sub, diff in zip((v - 2, 2 - v), (-2, 2)): assert isinstance(sub, Expression) assert sub.constant() == diff terms = sub.terms() assert (len(terms) == 1 and terms[0].variable() is v and terms[0].coefficient() == -math.copysign(1, diff)) sub2 = v - v2 assert isinstance(sub2, Expression) assert sub2.constant() == 0 terms = sub2.terms() assert (len(terms) == 2 and terms[0].variable() is v and terms[0].coefficient() == 1 and terms[1].variable() is v2 and terms[1].coefficient() == -1)
def test_solving_with_strength(): """Test solving a system with unstatisfiable non-required constraint. """ v1 = Variable('foo') v2 = Variable('bar') s = Solver() s.addConstraint(v1 + v2 == 0) s.addConstraint(v1 == 10) s.addConstraint((v2 >= 0) | 'weak') s.updateVariables() assert v1.value() == 10 and v2.value() == -10 s.reset() s.addConstraint(v1 + v2 == 0) s.addConstraint((v1 >= 10) | 'medium') s.addConstraint((v2 == 2) | 'strong') s.updateVariables() assert v1.value() == -2 and v2.value() == 2
def __init__(self, spacing=6, **kwargs): """Create solver and basic grid parameters.""" self._next_cell = [0, 0] # row, col self._cells = {} self._grid_widgets = {} self.spacing = spacing self._n_added = 0 self._default_class = ViewBox # what to add when __getitem__ is used self._solver = Solver() self._need_solver_recreate = True # width and height of the Rect used to place child widgets self._var_w = Variable("w_rect") self._var_h = Variable("h_rect") self._width_grid = None self._height_grid = None # self._height_stay = None # self._width_stay = None Widget.__init__(self, **kwargs)
def test_constraint_or_operator(): """Test modifying a constraint strength using the | operator. """ v = Variable('foo') c = Constraint(v + 1, '==') for s in ('weak', 'medium', 'strong', 'required', strength.create(1, 1, 0)): c2 = c | s if isinstance(s, str): assert c2.strength() == getattr(strength, s) else: assert c2.strength() == s
def test_term_creation(): """Test the Term constructor. """ v = Variable('foo') t = Term(v) assert t.variable() is v assert t.coefficient() == 1 t = Term(v, 100) assert t.variable() is v assert t.coefficient() == 100 assert str(t) == '100 * foo'
def test_managing_edit_variable(): """Test adding/removing edit variables. """ s = Solver() v1 = Variable('foo') v2 = Variable('bar') with pytest.raises(TypeError): s.hasEditVariable(object()) with pytest.raises(TypeError): s.addEditVariable(object(), 'weak') with pytest.raises(TypeError): s.removeEditVariable(object()) with pytest.raises(TypeError): s.suggestValue(object(), 10) assert not s.hasEditVariable(v1) s.addEditVariable(v1, 'weak') assert s.hasEditVariable(v1) with pytest.raises(DuplicateEditVariable): s.addEditVariable(v1, 'medium') with pytest.raises(UnknownEditVariable): s.removeEditVariable(v2) s.removeEditVariable(v1) assert not s.hasEditVariable(v1) with pytest.raises(BadRequiredStrength): s.addEditVariable(v1, 'required') s.addEditVariable(v2, 'strong') assert s.hasEditVariable(v2) with pytest.raises(UnknownEditVariable): s.suggestValue(v1, 10) s.reset() assert not s.hasEditVariable(v2)
def test_managing_constraints(): """Test adding/removing constraints. """ s = Solver() v = Variable('foo') v2 = Variable('bar') c1 = v >= 1 c2 = v <= 0 c3 = ((v2 >= 1) and (v2 <= 0)) with pytest.raises(TypeError): s.hasConstraint(object()) with pytest.raises(TypeError): s.addConstraint(object()) with pytest.raises(TypeError): s.removeConstraint(object()) assert not s.hasConstraint(c1) s.addConstraint(c1) assert s.hasConstraint(c1) with pytest.raises(DuplicateConstraint): s.addConstraint(c1) with pytest.raises(UnknownConstraint): s.removeConstraint(c2) with pytest.raises(UnsatisfiableConstraint): s.addConstraint(c2) # XXX need to find how to get an invalid symbol from choose subject # with pytest.raises(UnsatisfiableConstraint): # s.addConstraint(c3) s.removeConstraint(c1) assert not s.hasConstraint(c1) s.addConstraint(c2) assert s.hasConstraint(c2) s.reset() assert not s.hasConstraint(c2)
def test_variable_addition(): """Test variable additions. """ v = Variable("foo") v2 = Variable('bar') for add in (v + 2, 2.0 + v): assert isinstance(add, Expression) assert add.constant() == 2 terms = add.terms() assert (len(terms) == 1 and terms[0].variable() is v and terms[0].coefficient() == 1) add2 = v + v2 assert isinstance(add2, Expression) assert add2.constant() == 0 terms = add2.terms() assert (len(terms) == 2 and terms[0].variable() is v and terms[0].coefficient() == 1 and terms[1].variable() is v2 and terms[1].coefficient() == 1) with pytest.raises(TypeError): v + ''
def test_solving_under_constrained_system(): """Test solving an under constrained system. """ s = Solver() v = Variable('foo') c = 2 * v + 1 >= 0 s.addEditVariable(v, 'weak') s.addConstraint(c) s.suggestValue(v, 10) s.updateVariables() assert c.expression().value() == 21 assert c.expression().terms()[0].value() == 20 assert c.expression().terms()[0].variable().value() == 10