164 lines
4.3 KiB
Python
164 lines
4.3 KiB
Python
# --------------------------------------------------------------------------------------
|
|
# Copyright (c) 2014-2022, Nucleic Development Team.
|
|
#
|
|
# Distributed under the terms of the Modified BSD License.
|
|
#
|
|
# The full license is in the file LICENSE, distributed with this software.
|
|
# --------------------------------------------------------------------------------------
|
|
import math
|
|
import operator
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
from kiwisolver import Constraint, Expression, Term, Variable, strength
|
|
|
|
|
|
def test_variable_methods() -> None:
|
|
"""Test the variable modification methods."""
|
|
v = Variable()
|
|
assert v.name() == ""
|
|
v.setName("Δ")
|
|
assert v.name() == "Δ"
|
|
v.setName("foo")
|
|
assert v.name() == "foo"
|
|
with pytest.raises(TypeError):
|
|
v.setName(1) # type: ignore
|
|
if sys.version_info >= (3,):
|
|
with pytest.raises(TypeError):
|
|
v.setName(b"r") # type: ignore
|
|
|
|
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) # type: ignore
|
|
|
|
|
|
def test_variable_neg() -> None:
|
|
"""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_variable_mul() -> None:
|
|
"""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 # type: ignore
|
|
|
|
|
|
def test_variable_division() -> None:
|
|
"""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 # type: ignore
|
|
|
|
with pytest.raises(ZeroDivisionError):
|
|
v / 0
|
|
|
|
|
|
def test_variable_addition() -> None:
|
|
"""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 + "" # type: ignore
|
|
|
|
|
|
def test_variable_sub() -> None:
|
|
"""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_variable_rich_compare_operations() -> None:
|
|
"""Test using comparison on variables."""
|
|
v = Variable("foo")
|
|
v2 = Variable("Δ")
|
|
|
|
for op, symbol in ((operator.le, "<="), (operator.eq, "=="), (operator.ge, ">=")):
|
|
c = op(v, v2 + 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() == 1
|
|
and t[1].variable() is v2
|
|
and t[1].coefficient() == -1
|
|
)
|
|
assert e.constant() == -1
|
|
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)
|