aboutsummaryrefslogtreecommitdiff
blob: 5e938a9e7549a7c9e88da90e21701251a77e26ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import pytest

from snakeoil.constraints import Problem

def any_of(**kwargs):
    return any(kwargs.values())

def all_of(**kwargs):
    return all(kwargs.values())

def test_readd_variables():
    p = Problem()
    p.add_variable((True, False), 'x', 'y')
    with pytest.raises(AssertionError, match="variable 'y' was already added"):
        p.add_variable((True, False), 'y', 'z')

def test_constraint_unknown_variable():
    p = Problem()
    p.add_variable((True, False), 'x', 'y')
    with pytest.raises(AssertionError, match="unknown variable 'z'"):
        p.add_constraint(any_of, ('y', 'z'))

def test_empty_problem():
    p = Problem()
    assert tuple(p) == ({}, )

def test_empty_constraints():
    p = Problem()
    p.add_variable((True, False), 'x', 'y')
    p.add_variable((True, ), 'z')
    assert len(tuple(p)) == 4

def test_domain_prefer_later():
    p = Problem()
    p.add_variable((False, True), 'x', 'y')
    p.add_constraint(any_of, ('x', 'y'))
    assert next(iter(p)) == {'x': True, 'y': True}

def test_constraint_single_variable():
    p = Problem()
    p.add_variable((True, False), 'x', 'y')
    p.add_constraint(lambda x: x, ('x', ))
    p.add_constraint(lambda y: not y, ('y', ))
    assert tuple(p) == ({'x': True, 'y': False}, )

def test_no_solution():
    p = Problem()
    p.add_variable((True, ), 'x')
    p.add_variable((True, False), 'y', 'z')
    p.add_constraint(lambda x, y: not x or y, ('x', 'y'))
    p.add_constraint(lambda y, z: not y or not z, ('y', 'z'))
    p.add_constraint(lambda x, z: not x or z, ('x', 'z'))
    assert not tuple(p)

def test_forward_check():
    p = Problem()
    p.add_variable(range(2, 10), 'x', 'y', 'z')
    p.add_constraint(lambda x, y: (x + y) % 2 == 0, ('x', 'y'))
    p.add_constraint(lambda x, y, z: (x * y * z) % 2 != 0, ('x', 'y', 'z'))
    p.add_constraint(lambda y, z: y < z, ('y', 'z'))
    p.add_constraint(lambda z, x: x ** 2 <= z, ('x', 'z'))
    assert tuple(p) == ({'x': 3, 'y': 7, 'z': 9}, {'x': 3, 'y': 5, 'z': 9}, {'x': 3, 'y': 3, 'z': 9})