Esempio n. 1
0
    def apply_to_backend_request(self,
                                 block: Block,
                                 level: Tuple[Factor, Union[SimpleLevel, DerivedLevel]],
                                 backend_request: BackendRequest
                                 ) -> None:
        sublists = self._build_variable_sublists(block, level, self.k)
        implications = []

        # Handle the regular cases (1 => 2 ^ ... ^ n ^ ~n+1)
        trim = len(sublists) if self.k > 1 else len(sublists) - 1
        for idx, l in enumerate(sublists[:trim]):
            if idx > 0:
                p_list = [Not(sublists[idx-1][0]), l[0]]
                p = And(p_list) if len(p_list) > 1 else p_list[0]
            else:
                p = l[0]

            if idx < len(sublists) - 1:
                q_list = cast(List[Any], l[1:]) + [Not(sublists[idx+1][-1])]
                q = And(q_list) if len(q_list) > 1 else q_list[0]
            else:
                q = And(l[1:]) if len(l[1:]) > 1 else l[self.k - 1]
            implications.append(If(p, q))

        # Handle the tail
        if len(sublists[-1]) > 1:
            tail = sublists[-1]
            tail.reverse()
            for idx in range(len(tail) - 1):
                implications.append(If(l[idx], l[idx + 1]))

        (cnf, new_fresh) = block.cnf_fn(And(implications), backend_request.fresh)

        backend_request.cnfs.append(cnf)
        backend_request.fresh = new_fresh
Esempio n. 2
0
def test_tseitin_rep_and():
    from sweetpea.logic import __tseitin_rep, _Cache

    clauses = []
    cache = _Cache(4)

    # Make sure return is correct, and value was cached.
    assert __tseitin_rep(And([1, 2, 3]), clauses, cache) == 4
    assert cache.get(str(And([1, 2, 3]))) == 4

    # Make sure equivalence clauses were added.
    assert Or([1, Not(4)]) in clauses
    assert Or([2, Not(4)]) in clauses
    assert Or([3, Not(4)]) in clauses
    assert Or([Not(1), Not(2), Not(3), 4]) in clauses

    # Don't duplicate clauses when the cache was already populated
    clauses = []
    cache = _Cache(4)

    # Prewarm the cache
    assert cache.get(str(And([1, 2, 3]))) == 4
    assert __tseitin_rep(And([1, 2, 3]), clauses, cache) == 4

    # Make sure no clauses were added
    assert clauses == []
Esempio n. 3
0
def test_derivation_with_general_window():
    block = fully_cross_block([color, text, congruent_bookend], [color, text],
                              [])
    # congruent bookend - yes
    d = Derivation(16, [[0, 2], [1, 3]], congruent_bookend)
    backend_request = BackendRequest(19)
    d.apply(block, backend_request)

    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            Iff(17, Or([And([1, 3]), And([2, 4])])),
            Iff(19, Or([And([13, 15]), And([14, 16])]))
        ]), 19)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]

    # congruent bookend - no
    d = Derivation(17, [[0, 3], [1, 2]], congruent_bookend)
    backend_request = BackendRequest(19)
    d.apply(block, backend_request)

    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            Iff(18, Or([And([1, 4]), And([2, 3])])),
            Iff(20, Or([And([13, 16]), And([14, 15])]))
        ]), 19)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]
Esempio n. 4
0
def test_eliminate_iff():
    from sweetpea.logic import __eliminate_iff

    # P <-> Q ==> (P v ~Q) ^ (~P v Q)
    assert __eliminate_iff(Iff(1, 2)) == And([Or([1, Not(2)]), Or([Not(1), 2])])

    assert __eliminate_iff(Iff(1, And([2, 3]))) == And([
        Or([1, Not(And([2, 3]))]),
        Or([Not(1), And([2, 3])])
    ])
Esempio n. 5
0
def test_forbid():
    f = Forbid(("color", "red"))
    backend_request = BackendRequest(0)
    f.apply(block, backend_request)
    assert backend_request.cnfs == [And([-1, -7, -13, -19])]

    f = Forbid(("congruent?", "con"))
    backend_request = BackendRequest(0)
    f.apply(block, backend_request)
    assert backend_request.cnfs == [And([-5, -11, -17, -23])]
Esempio n. 6
0
def test_exclude():
    f = Exclude(color, get_level_from_name(color, "red"))
    backend_request = BackendRequest(0)
    f.apply(block, backend_request)
    assert backend_request.cnfs == [And([-1, -7, -13, -19])]

    f = Exclude(con_factor, get_level_from_name(con_factor, "con"))
    backend_request = BackendRequest(0)
    f.apply(block, backend_request)
    assert backend_request.cnfs == [And([-5, -11, -17, -23])]
Esempio n. 7
0
def test_distribute_ors_switching():
    from sweetpea.logic import __distribute_ors_switching

    # When lhs or rhs is a single variable, just distribute it.
    assert __distribute_ors_switching(Or([1, And([2, 3])]),
                                      4) == (And([Or([1, 2]),
                                                  Or([1, 3])]), 4)

    assert __distribute_ors_switching(Or([And([1, 2]), 3]),
                                      4) == (And([Or([1, 3]),
                                                  Or([2, 3])]), 4)

    # Should distribute over multiple individual variables
    assert __distribute_ors_switching(Or([1, 2, And([3, 4])]), 5) == (And(
        [Or([1, 2, 3]), Or([1, 2, 4])]), 5)

    # When both the lhs and rhs are more than just a single variable,
    # then introduce a switching variable to limit the formula growth.
    assert __distribute_ors_switching(Or([And([1, 2]),
                                          And([3, 4])]), 5) == (And([
                                              Or([1, Not(5)]),
                                              Or([2, Not(5)]),
                                              Or([3, 5]),
                                              Or([4, 5])
                                          ]), 6)
Esempio n. 8
0
    def apply(block: MultipleCrossBlock, backend_request: BackendRequest) -> None:
        # Treat each crossing seperately, and repeat the same process as fullycross
        for c in block.crossing:
            fresh = backend_request.fresh

            # Step 1: Get a list of the trials that are involved in the crossing.
            crossing_size = max(block.min_trials, block.crossing_size())
            crossing_trials = list(filter(lambda t: all(map(lambda f: f.applies_to_trial(t),
                                                            c)),
                                          range(1, block.trials_per_sample() + 1)))
            crossing_trials = crossing_trials[:crossing_size]

            # Step 2: For each trial, cross all levels of all factors in the crossing.
            crossing_factors = list(map(lambda t: (list(product(*[block.factor_variables_for_trial(f, t) for f in c]))), crossing_trials))

            # Step 3: For each trial, cross all levels of all design-only factors in the crossing.
            design_factors = cast(List[List[List[int]]], [])
            design_factors = list(map(lambda _: [], crossing_trials))
            for f in list(filter(lambda f: f not in c and not f.has_complex_window, block.design)):
                for i, t in enumerate(crossing_trials):
                    design_factors[i].append(block.factor_variables_for_trial(f, t))
            design_combinations = cast(List[List[Tuple[int, ...]]], [])
            design_combinations = list(map(lambda l: list(product(*l)), design_factors))

            # Step 4: For each trial, combine each of the crossing factors with all of the design-only factors.
            crossings = cast(List[List[List[Tuple[int, ...]]]], [])
            for i, t in enumerate(crossing_trials):
                crossings.append(list(map(lambda c: [c] + design_combinations[i], crossing_factors[i])))

            # Step 5: Remove crossings that are not possible.
            # From here on ignore all values other than the first in every list.
            crossings = block.filter_excluded_derived_levels(crossings)

            # Step 6: Allocate additional variables to represent each crossing.
            num_state_vars = list(map(lambda c: len(c), crossings))
            state_vars = list(range(fresh, fresh + sum(num_state_vars)))
            fresh += sum(num_state_vars)

            # Step 7: Associate each state variable with its crossing.
            flattened_crossings = list(chain.from_iterable(crossings))
            iffs = list(map(lambda n: Iff(state_vars[n], And([*flattened_crossings[n][0]])), range(len(state_vars))))

            # Step 8: Constrain each crossing to occur in only one trial.
            states = list(chunk(state_vars, block.crossing_size()))
            transposed = cast(List[List[int]], list(map(list, zip(*states))))

            # We Use n < 2 rather than n = 1 here because they may exclude some levels from the crossing.
            # This ensures that there won't be duplicates, while still allowing some to be missing.
            # backend_request.ll_requests += list(map(lambda l: LowLevelRequest("LT", 2, l), transposed))
            backend_request.ll_requests += list(map(lambda l: LowLevelRequest("GT", 0, l), transposed))

            (cnf, new_fresh) = block.cnf_fn(And(iffs), fresh)

            backend_request.cnfs.append(cnf)
            backend_request.fresh = new_fresh
Esempio n. 9
0
    def __apply_derivation(self, block: Block, backend_request: BackendRequest) -> None:
        trial_size = block.variables_per_trial()
        cross_size = block.trials_per_sample()

        iffs = []
        for n in range(cross_size):
            or_clause = Or(list(And(list(map(lambda x: x + (n * trial_size) + 1, l))) for l in self.dependent_idxs))
            iffs.append(Iff(self.derived_idx + (n * trial_size) + 1, or_clause))

        (cnf, new_fresh) = block.cnf_fn(And(iffs), backend_request.fresh)

        backend_request.cnfs.append(cnf)
        backend_request.fresh = new_fresh
Esempio n. 10
0
def test_to_cnf_tseitin():
    assert to_cnf_tseitin(Or([1, And([2, 3])]), 4) == (And([
        # 4 <=> (2 ^ 3)
        Or([Not(2), Not(3), 4]),
        Or([2, Not(4)]),
        Or([3, Not(4)]),

        # 5 <=> (1 v 4)
        Or([1, 4, Not(5)]),
        Or([Not(1), 5]),
        Or([Not(4), 5]),

        # Final clause
        5
    ]), 6)
def test_uniform_combinatoric_is_always_valid(filename):

    failures = []
    contents = None
    with open(filename, 'r') as f:
        contents = f.read()
        exec(contents, globals(), locals())

    if 'block' not in vars():
        pytest.fail(
            "File did not produce a variable named 'block', aborting. file={}".
            format(filename))

    # Build the CNF for this block
    build_cnf_result = build_cnf(vars()['block'])

    # Build the sampler
    enumerator = UCSolutionEnumerator(vars()['block'])

    # Generate some samples, make sure they're all SAT.
    sample_count = min(enumerator.solution_count(), 200)
    print("Checking that UC samples are SAT for {}, sample count={}".format(
        filename, sample_count))
    for s in range(sample_count):
        sample = enumerator.generate_solution_variables()
        if not cnf_is_satisfiable(build_cnf_result +
                                  CNF(cnf_to_json([And(sample)]))):
            failures.append("Found UNSAT solution! Solution={} File={}".format(
                sample, filename))

    if failures:
        pytest.fail(
            '{} failures occurred in SAT checks for UC sampler: {}'.format(
                len(failures), failures))
Esempio n. 12
0
def test_exclude_with_three_derived_levels():
    color_list = ["red", "green", "blue"]
    color = Factor("color", color_list)
    text = Factor("text", color_list)

    def count_diff(colors, texts):
        changes = 0
        if (colors[0] != colors[1]): changes += 1
        if (texts[0] != texts[1]): changes += 1
        return changes

    def make_k_diff_level(k):
        def k_diff(colors, texts):
            return count_diff(colors, texts) == k

        return DerivedLevel(str(k), Transition(k_diff, [color, text]))

    changed = Factor(
        "changed",
        [make_k_diff_level(0),
         make_k_diff_level(1),
         make_k_diff_level(2)])

    exclude_constraint = Exclude(changed, get_level_from_name(changed, "2"))

    design = [color, text, changed]
    crossing = [color, text]
    block = fully_cross_block(design, crossing, [exclude_constraint])

    backend_request = BackendRequest(0)
    exclude_constraint.apply(block, backend_request)
    assert backend_request.cnfs == [
        And([-57, -60, -63, -66, -69, -72, -75, -78])
    ]
Esempio n. 13
0
def test_apply_demorgan():
    from sweetpea.logic import __apply_demorgan

    # P ==> P, ~P ==> ~P
    assert __apply_demorgan(4) == 4
    assert __apply_demorgan(Not(4)) == Not(4)

    # ~~P ==> P
    assert __apply_demorgan(Not(Not(4))) == 4

    # ~(P v Q) ==> ~P ^ ~Q
    assert __apply_demorgan(Not(Or([1, 2]))) == And([Not(1), Not(2)])

    # ~(P ^ Q) ==> ~P v ~Q
    assert __apply_demorgan(Not(And([1, 2]))) == Or([Not(1), Not(2)])

    assert __apply_demorgan(Or([1, Not(And([2, 3]))])) == Or([1, Not(2), Not(3)])
Esempio n. 14
0
def test_to_cnf_switching():
    formula = Or([
        And([3, 4]),
        And([Not(2), Or([1, 5])])
    ])
    expected_cnf = And([
        Or([3, Not(6)]),
        Or([4, Not(6)]),
        Or([1, 5, 6]),
        Or([Not(2), 6])
    ])
    assert to_cnf_switching(formula, 6) == (expected_cnf, 7)

    formula = And([
        Iff(1, And([2, 3])),
        Iff(4, And([5, 6]))
    ])
    expected_cnf = And([
        Or([1, Not(2), Not(3)]),
        Or([Not(1), 2]),
        Or([Not(1), 3]),
        Or([4, Not(5), Not(6)]),
        Or([Not(4), 5]),
        Or([Not(4), 6])
    ])
    assert to_cnf_switching(formula, 7) == (expected_cnf, 7)
Esempio n. 15
0
def test_exclude_with_general_window():
    block = fully_cross_block([color, text, congruent_bookend], [color, text],
                              [])

    c = Exclude(congruent_bookend, get_level_from_name(congruent_bookend,
                                                       "yes"))
    backend_request = BackendRequest(0)
    c.apply(block, backend_request)
    assert backend_request.cnfs == [And([-17, -19])]
Esempio n. 16
0
def test_is_cnf_still_sat_should_respond_correctly():

    # Build the CNF on the server.
    cnf_result = build_cnf(block)

    # with open(path_to_cnf_files+'/test_is_cnf_still_sat_should_respond_correctly.cnf', 'w') as f:
    #     f.write(cnf_result.as_unigen_string())
    with open(
            path_to_cnf_files +
            '/test_is_cnf_still_sat_should_respond_correctly.cnf', 'r') as f:
        old_cnf = f.read()

    assert old_cnf == cnf_result.as_unigen_string()

    assert is_cnf_still_sat(block, [And([1, 3])])

    assert not is_cnf_still_sat(block, [And([7, 8])])
    assert not is_cnf_still_sat(block, [And([1, 7, 13])])
Esempio n. 17
0
def test_exclude_with_transition():
    block = fully_cross_block([color, text, color_repeats_factor],
                              [color, text], [])

    c = Exclude(color_repeats_factor,
                get_level_from_name(color_repeats_factor, "yes"))
    backend_request = BackendRequest(0)
    c.apply(block, backend_request)
    assert backend_request.cnfs == [And([-17, -19, -21])]
Esempio n. 18
0
    def apply_to_backend_request(self, block: Block, level: Tuple[Factor, Union[SimpleLevel, DerivedLevel]],
                                    backend_request: BackendRequest) -> None:

        # Request sublists for k+1 to allow us to determine the transition
        sublists = self._build_variable_sublists(block, level, self.k + 1)

        implications = []
        if sublists:
            # Starting corner case
            implications.append(If(sublists[0][0], And(sublists[0][1:-1])))
            for sublist in sublists:
                implications.append(If(And([Not(sublist[0]), sublist[1]]), And(sublist[2:])))
            # Ending corner case
            implications.append(If(sublists[-1][-1], And(sublists[-1][1:-1])))

        (cnf, new_fresh) = block.cnf_fn(And(implications), backend_request.fresh)

        backend_request.cnfs.append(cnf)
        backend_request.fresh = new_fresh
Esempio n. 19
0
    def __apply_derivation_with_complex_window(self, block: Block, backend_request: BackendRequest) -> None:
        trial_size = block.variables_per_trial()
        trial_count = block.trials_per_sample()
        iffs = []
        f = self.factor
        window = f.levels[0].window
        t = 0
        for n in range(trial_count):
            if not f.applies_to_trial(n + 1):
                continue

            num_levels = len(f.levels)
            get_trial_size = lambda x: trial_size if x < block.grid_variables() else len(block.decode_variable(x+1)[0].levels)
            or_clause = Or(list(And(list(map(lambda x: x + (t * window.stride * get_trial_size(x) + 1), l))) for l in self.dependent_idxs))
            iffs.append(Iff(self.derived_idx + (t * num_levels) + 1, or_clause))
            t += 1
        (cnf, new_fresh) = block.cnf_fn(And(iffs), backend_request.fresh)

        backend_request.cnfs.append(cnf)
        backend_request.fresh = new_fresh
Esempio n. 20
0
def test_cnf_to_json():
    assert cnf_to_json([And([1])]) == [[1]]

    assert cnf_to_json([And([Or([1])])]) == [[1]]
    assert cnf_to_json([And([Or([Not(5)])])]) == [[-5]]
    assert cnf_to_json([And([Or([1, 2, Not(4)])])]) == [[1, 2, -4]]

    assert cnf_to_json([And([Or([1, 4]), Or([5, -4, 2]), Or([-1, -5])])]) == [
        [1, 4],
        [5, -4, 2],
        [-1, -5]]

    assert cnf_to_json([And([
        Or([1, 3, Not(2)]),
        Or([1, 3, 5]),
        Or([1, 4, Not(2)]),
        Or([1, 4, 5]),
        Or([2, 3, 1, 5]),
        Or([2, 4, 1, 5])])]) == [
            [1, 3, -2],
            [1, 3, 5],
            [1, 4, -2],
            [1, 4, 5],
            [2, 3, 1, 5],
            [2, 4, 1, 5]]
Esempio n. 21
0
def test_derivation_with_three_level_transition():
    f = Factor("f", ["a", "b", "c"])
    f_transition = Factor("transition", [
        DerivedLevel("aa",
                     Transition(lambda c: c[0] == "a" and c[1] == "a", [f])),
        DerivedLevel("ab",
                     Transition(lambda c: c[0] == "a" and c[1] == "b", [f])),
        DerivedLevel("ac",
                     Transition(lambda c: c[0] == "a" and c[1] == "c", [f])),
        DerivedLevel("ba",
                     Transition(lambda c: c[0] == "b" and c[1] == "a", [f])),
        DerivedLevel("bb",
                     Transition(lambda c: c[0] == "b" and c[1] == "b", [f])),
        DerivedLevel("bc",
                     Transition(lambda c: c[0] == "b" and c[1] == "c", [f])),
        DerivedLevel("ca",
                     Transition(lambda c: c[0] == "c" and c[1] == "a", [f])),
        DerivedLevel("cb",
                     Transition(lambda c: c[0] == "c" and c[1] == "b", [f])),
        DerivedLevel("cc",
                     Transition(lambda c: c[0] == "c" and c[1] == "c", [f])),
    ])

    block = fully_cross_block([f, f_transition], [f], [])

    # a-a derivation
    d = Derivation(9, [[0, 3]], f_transition)
    backend_request = BackendRequest(28)
    d.apply(block, backend_request)

    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([Iff(10, Or([And([1, 4])])),
             Iff(19, Or([And([4, 7])]))]), 28)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]
Esempio n. 22
0
def test_exclude_with_reduced_crossing():
    color = Factor("color", ["red", "blue", "green"])
    text = Factor("text", ["red", "blue"])

    def illegal_stimulus(color, text):
        return color == "green" and text == "blue"

    def legal_stimulus(color, text):
        return not illegal_stimulus(color, text)

    stimulus_configuration = Factor("stimulus configuration", [
        DerivedLevel("legal", WithinTrial(legal_stimulus, [color, text])),
        DerivedLevel("illegal", WithinTrial(illegal_stimulus, [color, text]))
    ])

    c = Exclude(stimulus_configuration,
                get_level_from_name(stimulus_configuration, "illegal"))
    block = fully_cross_block([color, text, stimulus_configuration],
                              [color, text], [c],
                              require_complete_crossing=False)

    backend_request = BackendRequest(0)
    c.apply(block, backend_request)
    assert backend_request.cnfs == [And([-7, -14, -21, -28, -35])]
Esempio n. 23
0
def test_fully_cross_with_transition_in_crossing():
    direction = Factor("direction", ["up", "down"])

    block = fully_cross_block([direction, color, color_repeats_factor],
                              [direction, color_repeats_factor], [])

    backend_request = BackendRequest(29)
    FullyCross.apply(block, backend_request)

    (expected_cnf, _) = to_cnf_tseitin(
        And([
            Iff(29, And([5, 21])),
            Iff(30, And([5, 22])),
            Iff(31, And([6, 21])),
            Iff(32, And([6, 22])),
            Iff(33, And([9, 23])),
            Iff(34, And([9, 24])),
            Iff(35, And([10, 23])),
            Iff(36, And([10, 24])),
            Iff(37, And([13, 25])),
            Iff(38, And([13, 26])),
            Iff(39, And([14, 25])),
            Iff(40, And([14, 26])),
            Iff(41, And([17, 27])),
            Iff(42, And([17, 28])),
            Iff(43, And([18, 27])),
            Iff(44, And([18, 28])),
        ]), 45)

    assert backend_request.fresh == 78
    assert backend_request.cnfs == [expected_cnf]
    assert backend_request.ll_requests == [
        LowLevelRequest("GT", 0, [29, 33, 37, 41]),
        LowLevelRequest("GT", 0, [30, 34, 38, 42]),
        LowLevelRequest("GT", 0, [31, 35, 39, 43]),
        LowLevelRequest("GT", 0, [32, 36, 40, 44])
    ]
Esempio n. 24
0
def test_to_cnf_naive():
    assert to_cnf_naive(1, 2) == (And([1]), 2)
    assert to_cnf_naive(And([1]), 2) == (And([1]), 2)
    assert to_cnf_naive(And([1, 2]), 3) == (And([1, 2]), 3)

    assert to_cnf_naive(Or([1, 2]), 3) == (And([Or([1, 2])]), 3)
    assert to_cnf_naive(Or([1, And([2, 3])]), 4) == (And([Or([1, 2]), Or([1, 3])]), 4)

    formula = And([
        Iff(1, And([2, 3])),
        Iff(4, And([5, 6]))
    ])
    expected_cnf = And([
        Or([1, Not(2), Not(3)]),
        Or([Not(1), 2]),
        Or([Not(1), 3]),
        Or([4, Not(5), Not(6)]),
        Or([Not(4), 5]),
        Or([Not(4), 6])
    ])
    assert to_cnf_switching(formula, 7) == (expected_cnf, 7)
Esempio n. 25
0
def test_derivation():
    # Congruent derivation
    d = Derivation(4, [[0, 2], [1, 3]], con_factor)
    backend_request = BackendRequest(24)
    d.apply(block, backend_request)

    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            Iff(5, Or([And([1, 3]), And([2, 4])])),
            Iff(11, Or([And([7, 9]), And([8, 10])])),
            Iff(17, Or([And([13, 15]), And([14, 16])])),
            Iff(23, Or([And([19, 21]), And([20, 22])]))
        ]), 24)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]

    # Incongruent derivation
    d = Derivation(5, [[0, 3], [1, 2]], con_factor)
    backend_request = BackendRequest(24)
    d.apply(block, backend_request)

    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            Iff(6, Or([And([1, 4]), And([2, 3])])),
            Iff(12, Or([And([7, 10]), And([8, 9])])),
            Iff(18, Or([And([13, 16]), And([14, 15])])),
            Iff(24, Or([And([19, 22]), And([20, 21])]))
        ]), 24)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]
Esempio n. 26
0
def test_distribute_ors_naive():
    from sweetpea.logic import __distribute_ors_naive

    # When f is int or Not, return it. (Not can only contain int, as we've
    # already applied DeMorgan's laws)
    assert __distribute_ors_naive(1) == 1
    assert __distribute_ors_naive(Not(1)) == Not(1)

    # When f in an Or, distribute the Or over the contained clauses.
    assert __distribute_ors_naive(Or([1, 2])) == And([Or([1, 2])])
    assert __distribute_ors_naive(Or([1, And([2, 3])])) == And([Or([1, 2]), Or([1, 3])])
    assert __distribute_ors_naive(Or([And([1, 2]), And([3, 4])])) == And([
        Or([1, 3]), Or([1, 4]), Or([2, 3]), Or([2, 4])
    ])

    # When f is an And, disitribute Ors over the contained clauses.
    assert __distribute_ors_naive(And([1, Not(2)])) == And([1, Not(2)])
    assert __distribute_ors_naive(And([1, Or([2, And([3, 4])])])) == And([
        Or([2, 3]), Or([2, 4]), 1
    ])
Esempio n. 27
0
def test_derivation_with_transition():
    block = fully_cross_block([color, text, color_repeats_factor],
                              [color, text], [])

    # Color repeats derivation
    d = Derivation(16, [[0, 4], [1, 5]], color_repeats_factor)
    backend_request = BackendRequest(23)
    d.apply(block, backend_request)

    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            Iff(17, Or([And([1, 5]), And([2, 6])])),
            Iff(19, Or([And([5, 9]), And([6, 10])])),
            Iff(21, Or([And([9, 13]), And([10, 14])]))
        ]), 23)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]

    # Color does not repeat derivation
    d = Derivation(17, [[0, 5], [1, 4]], color_repeats_factor)
    backend_request = BackendRequest(23)
    d.apply(block, backend_request)

    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            Iff(18, Or([And([1, 6]), And([2, 5])])),
            Iff(20, Or([And([5, 10]), And([6, 9])])),
            Iff(22, Or([And([9, 14]), And([10, 13])]))
        ]), 23)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]
Esempio n. 28
0
def test_derivation_with_multiple_transitions():
    block = fully_cross_block(
        [color, text, color_repeats_factor, text_repeats_factor],
        [color, text], [])

    # Text repeats derivation
    d = Derivation(22, [[2, 6], [3, 7]], text_repeats_factor)
    backend_request = BackendRequest(29)
    d.apply(block, backend_request)

    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            Iff(23, Or([And([3, 7]), And([4, 8])])),
            Iff(25, Or([And([7, 11]), And([8, 12])])),
            Iff(27, Or([And([11, 15]), And([12, 16])]))
        ]), 29)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]

    # Text does not repeat derivation
    d = Derivation(23, [[2, 7], [3, 6]], text_repeats_factor)
    backend_request = BackendRequest(29)
    d.apply(block, backend_request)

    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            Iff(24, Or([And([3, 8]), And([4, 7])])),
            Iff(26, Or([And([7, 12]), And([8, 11])])),
            Iff(28, Or([And([11, 16]), And([12, 15])]))
        ]), 29)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]
Esempio n. 29
0
def test_fully_cross_with_uncrossed_simple_factors():
    other = Factor('other', ['l1', 'l2'])
    block = fully_cross_block([color, text, other], [color, text], [])

    backend_request = BackendRequest(25)
    FullyCross.apply(block, backend_request)

    (expected_cnf, _) = to_cnf_tseitin(
        And([
            Iff(25, And([1, 3])),
            Iff(26, And([1, 4])),
            Iff(27, And([2, 3])),
            Iff(28, And([2, 4])),
            Iff(29, And([7, 9])),
            Iff(30, And([7, 10])),
            Iff(31, And([8, 9])),
            Iff(32, And([8, 10])),
            Iff(33, And([13, 15])),
            Iff(34, And([13, 16])),
            Iff(35, And([14, 15])),
            Iff(36, And([14, 16])),
            Iff(37, And([19, 21])),
            Iff(38, And([19, 22])),
            Iff(39, And([20, 21])),
            Iff(40, And([20, 22]))
        ]), 41)

    assert backend_request.fresh == 74
    assert backend_request.cnfs == [expected_cnf]
    assert backend_request.ll_requests == [
        LowLevelRequest("GT", 0, [25, 29, 33, 37]),
        LowLevelRequest("GT", 0, [26, 30, 34, 38]),
        LowLevelRequest("GT", 0, [27, 31, 35, 39]),
        LowLevelRequest("GT", 0, [28, 32, 36, 40])
    ]
Esempio n. 30
0
def test_exactlykinarow():
    backend_request = __run_kinarow(
        ExactlyKInARow(1, (color, get_level_from_name(color, "red"))))
    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            If(1, Not(7)),
            If(And([Not(1), 7]), Not(13)),
            If(And([Not(7), 13]), Not(19))
        ]), 25)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]

    backend_request = __run_kinarow(
        ExactlyKInARow(2, (color, get_level_from_name(color, "red"))))
    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            If(1, And([7, Not(13)])),
            If(And([Not(1), 7]), And([13, Not(19)])),
            If(And([Not(7), 13]), 19),
            If(19, 13)
        ]), 25)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]

    backend_request = __run_kinarow(
        ExactlyKInARow(3, (color, get_level_from_name(color, "red"))))
    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([
            If(1, And([7, 13, Not(19)])),
            If(And([Not(1), 7]), And([13, 19])),
            If(19, 13),
            If(13, 7)
        ]), 25)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]