Exemplo n.º 1
0
    def _assert_some_negative_path_connected(self, path_var=None):
        path_var = self._negative_path_var if path_var is None else path_var

        start_left = [path_var(i, 1) for i in range(1, self.m + 1)]
        end_right = [path_var(i, self.n) for i in range(1, self.m + 1)]
        yield from constraint.at_most(start_left, 1)
        yield from constraint.at_most(end_right, 1)

        if self.n == 1:
            # covered by `_assert_negative_path_exists_if_function_false()`
            pass
        elif self.m == 1:
            for j in range(1, self.n):
                yield expr.Implies(path_var(1, j + 1), path_var(1, j)).to_cnf()
        else:
            for i in range(1, self.m + 1):
                column_offset = [
                    i_ for i_ in (i - 1, i, i + 1) if 1 <= i_ <= self.m
                ]
                for (j, j_off) in ((1, 2), (self.n, self.n - 1)):
                    elements = [path_var(i_, j_off) for i_ in column_offset]
                    equals_one = self._next_aux("equals_one")
                    yield from constraint.cardnet.equals(
                        elements, 1, equals_one)
                    yield expr.Implies(path_var(i, j), equals_one).to_cnf()

                for j in range(2, self.n):
                    elements = [
                        path_var(i_, j_)
                        for (i_, j_) in self._adjacent_8(i, j)
                    ]
                    equals_two = self._next_aux("equals_two")
                    yield from constraint.equals(elements, 2, equals_two)
                    yield expr.Implies(path_var(i, j), equals_two).to_cnf()
Exemplo n.º 2
0
    def _assert_some_path_connected(self, path_var=None):
        path_var = self._path_var if path_var is None else path_var

        start_at_top = [path_var(1, j) for j in range(1, self.n + 1)]
        end_at_bottom = [path_var(self.m, j) for j in range(1, self.n + 1)]
        yield from constraint.at_most(start_at_top, 1)
        yield from constraint.at_most(end_at_bottom, 1)

        if self.m == 1:
            # covered by `_assert_path_exists_if_function_true()`
            pass
        elif self.n == 1:
            for i in range(1, self.m):
                yield expr.Implies(path_var(i + 1, 1), path_var(i, 1)).to_cnf()
        else:
            for j in range(1, self.n + 1):
                yield expr.Implies(path_var(1, j), path_var(2, j)).to_cnf()
                yield expr.Implies(path_var(self.m, j),
                                   path_var(self.m - 1, j)).to_cnf()

            for i in range(2, self.m):
                for j in range(1, self.n + 1):
                    elements = [
                        path_var(i_, j_)
                        for (i_, j_) in self._adjacent_4(i, j)
                    ]
                    equals_two = self._next_aux("equals_two")
                    yield from constraint.equals(elements, 2, equals_two)
                    yield expr.Implies(path_var(i, j), equals_two).to_cnf()
Exemplo n.º 3
0
    def _assert_positive_path(self, switch_var=None, position_var=None):
        switch_var = self._active_switch if switch_var is None else switch_var
        position_var = self._position_reachable if position_var is None \
                       else position_var

        if self.m == 1 or self.n == 1:
            upper = self._upper_path_bound()
            for i in range(1, self.m + 1):
                for j in range(1, self.n + 1):
                    yield expr.Implies(position_var(i, j, upper),
                                       switch_var(i, j)).to_cnf()
            if self.n == 1:
                for i in range(1, self.m):
                    yield expr.Implies(position_var(i + 1, 1, upper),
                                       position_var(i, 1, upper)).to_cnf()
        else:
            for i in range(1, self.m + 1):
                for j in range(1, self.n + 1):
                    reachable = position_var(i, j, 0)
                    if i == 1: yield reachable
                    else: yield ~reachable

            for rnd in range(1, self._upper_path_bound() + 1):
                for i in range(1, self.m + 1):
                    for j in range(1, self.n + 1):
                        reachable = position_var(i, j, rnd)
                        elements = [position_var(i_, j_, rnd - 1) & \
                                    switch_var(i_, j_)
                                    for (i_, j_) in self._adjacent_4(i, j)]
                        elements.append(position_var(i, j, rnd - 1))
                        yield expr.Implies(reachable,
                                           expr.Or(*elements)).to_cnf()
def at_most_one(inputs, equivalent=None):
    assert inputs, "inputs must not be empty"
    count = next(_counter)

    def a(i):
        return expr.exprvar("sinz", (i, count))

    def clauses(variables):
        length = len(variables)
        (first, rest, last) = (variables[0], variables[1:-1], variables[-1])

        yield expr.Or(~first, a(1))
        yield expr.Or(~last, ~a(length - 1))

        for (i, x) in zip(range(2, length), rest):
            yield expr.Or(~x, a(i))
            yield expr.Or(~a(i - 1), a(i))
            yield expr.Or(~x, ~a(i - 1))

    if equivalent is None:
        yield from clauses(tuple(inputs))
    else:
        auxiliaries = list()
        for clause in clauses(tuple(inputs)):
            aux = expr.exprvar(("sinz", "eq"), next(_counter))
            yield expr.Implies(aux, clause).to_cnf()
            yield expr.Implies(clause, aux).to_cnf()
            auxiliaries.append(aux)
        constraint = expr.And(*auxiliaries)
        yield expr.Implies(constraint, equivalent).to_cnf()
        yield expr.Implies(equivalent, constraint).to_cnf()
def at_least_one(inputs, equivalent=None):
    assert inputs, "inputs must not be empty"
    constraint = expr.Or(*inputs)
    if equivalent is None:
        yield constraint
    else:
        yield expr.Implies(equivalent, constraint).to_cnf()
        yield expr.Implies(constraint, equivalent).to_cnf()
Exemplo n.º 6
0
def at_most(inputs, p, equivalent=None):
    assert inputs, "inputs must not be empty"
    (variables, clauses) = Cardnet().cardnet(inputs, p)
    condition = ~variables[p]
    yield from clauses
    if equivalent is None:
        yield condition
    else:
        yield expr.Implies(equivalent, condition).to_cnf()
        yield expr.Implies(condition, equivalent).to_cnf()
Exemplo n.º 7
0
    def _assert_lattice_on_negative_path(self):
        def _set(i, j, inp):
            return self._literal_at_position_is(i, j, inp) & ~inp

        def _negated(i, j, inp):
            return self._literal_at_position_is(i, j, ~inp) & inp

        for i in range(1, self.m + 1):
            for j in range(1, self.n + 1):
                auxiliaries = list()
                for inp in self._inputs_plus():
                    aux = self._next_aux("on_neg_path")
                    on_neg_path = _set(i, j, inp) | _negated(i, j, inp)
                    auxiliaries.append(aux)
                    yield expr.Implies(aux, on_neg_path).to_cnf()
                yield expr.Implies(self._negative_path_var(i, j),
                                   expr.Or(*auxiliaries)).to_cnf()
Exemplo n.º 8
0
 def _assert_lattice_on_negative_path(self, assignment, path_var):
     for i in range(1, self.m + 1):
         for j in range(1, self.n + 1):
             elements = list(
                 self._literal_at_position_is(i, j, inp)
                 for inp in self._input_literals()
                 if inp.compose(assignment).simplify().is_zero())
             assert elements, "list of literal variables must not be empty"
             yield expr.Implies(path_var(i, j), expr.Or(*elements)).to_cnf()
Exemplo n.º 9
0
def convert_to_pyeda(term):
    """Converts a term object to a PyEDA expression.

	Args:
		term (Term): A term object.
	
	Returns:
		expr: The corresponding PyEDA expression.
	
	"""
    if term.operator is None:
        return expr.exprvar(escape_var_name(term.operands[0]), None)
    elif term.operator == "NEG":
        return expr.Not(convert_to_pyeda(term.operands[0]), simplify=False)
    elif term.operator == "AND":
        return expr.And(
            *[convert_to_pyeda(operand) for operand in term.operands],
            simplify=False)
    elif term.operator == "OR":
        return expr.Or(
            *[convert_to_pyeda(operand) for operand in term.operands],
            simplify=False)
    elif term.operator == "IMP":
        return expr.Implies(convert_to_pyeda(term.operands[0]),
                            convert_to_pyeda(term.operands[0]),
                            simplify=False)
    elif term.operator == "EQV":
        return expr.Equal(
            *[convert_to_pyeda(operand) for operand in term.operands],
            simplify=False)
    elif term.operator == "ADD":
        return expr.exprvar(
            "___ADD___".join([
                escape_var_name(operand.operands[0])
                for operand in term.operands
            ]), None)
Exemplo n.º 10
0
 def _assert_path_exists_if_function_false(self):
     elements = (self._active_switch(self.m, j) & \
                 self._position_reachable(self.m, j, self._upper_path_bound())
                 for j in range(1, self.n + 1))
     yield expr.Implies(~self.function, expr.Or(*elements)).to_cnf()
Exemplo n.º 11
0
 def _assert_negative_path_exists_if_function_true(self):
     elements = (self._inactive_switch(i, self.n) & \
                 self._position_unreachable(i, self.n, self._upper_path_bound())
                 for i in range(1, self.m + 1))
     yield expr.Implies(self.function, expr.Or(*elements)).to_cnf()
Exemplo n.º 12
0
 def _assert_path_exists_if_function_true(self):
     elements = (self._path_var(self.m, j) for j in range(1, self.n + 1))
     yield expr.Implies(self.function, expr.Or(*elements)).to_cnf()
Exemplo n.º 13
0
 def _assert_negative_path_exists_if_function_false(self):
     elements = (self._negative_path_var(i, self.n)
                 for i in range(1, self.m + 1))
     yield expr.Implies(~self.function, expr.Or(*elements)).to_cnf()