def test_sat_negative(self): solver = self.get_solver() solver.add(expr.And(*self.pos)) solver.add(expr.And(*(~p for p in self.pos))) solution = solver.solve() self.assertIsNone(solution)
def test_not_at_most_one(self): self.function = expr.And(self.pos, expr.exprvar("b"), ~expr.Or(*self.neg)) cardinality = constraint.at_most_one(self.function.support) sat = expr.And(self.function, *cardinality).to_cnf().satisfy_one() self.assertIsNone(sat)
def test_equals_one(self, function): cardinality_a = constraint.equals_one(function.support) sat_a = expr.And(function, *cardinality_a).to_cnf().satisfy_one() cardinality_b = constraint.equals(function.support, 1) sat_b = expr.And(function, *cardinality_b).to_cnf().satisfy_one() self.assertEqual(sat_a is None, sat_b is None)
def test_sat_positive(self): solver = self.get_solver() solver.add(expr.And(*self.pos)) solver.add(expr.And(*(~n for n in self.neg))) solution = solver.solve() expected = dict(it.chain(((p, True) for p in self.pos), ((n, False) for n in self.neg))) self.assertIsNotNone(solution) self.assertEqual(expected, solution)
def test_not_at_most_one_not_equivalent(self): self.function = expr.And(self.pos, expr.exprvar("b"), ~expr.Or(*self.neg)) at_most = expr.exprvar("at_most") cardinality = constraint.at_most_one(self.function.support, ~at_most) sat = expr.And(self.function, at_most, *cardinality).to_cnf().satisfy_one() self.assertIsNotNone(sat) self.assertEqual(sat.get(at_most), 1)
def test_at_least_one_not_equivalent(self, function): equivalent = expr.exprvar("equivalent") cardinality_a = constraint.at_least_one(function.support, ~equivalent) sat_a = expr.And(function, ~equivalent, *cardinality_a).to_cnf().satisfy_one() cardinality_b = constraint.at_least(function.support, 1, ~equivalent) sat_b = expr.And(function, ~equivalent, *cardinality_b).to_cnf().satisfy_one() self.assertEqual(sat_a is None, sat_b is None) if sat_a or sat_b: self.assertEqual(sat_a.get(equivalent), sat_b.get(equivalent))
def satisfies(spc, f): """ Return True if the spec (which must be BOTH) satisfies formula f. """ assert spc.spec_type == spec.ShapeSpecTypes.BOTH, "must pass in both type" spc_expr = spc.to_expr() return expr.And(spc_expr, f).satisfy_one() is not None
def expr_is_vacuous(f): """ Vacuous if every shape applies to this. """ return all( expr_is_satisfiable(expr.And(f, spc.to_expr())) for spc in spec.ShapeSpec.enumerate_both())
def test_at_least_one(self): cardinality = cardnet.at_least(self.function.support, 1) sat = expr.And(self.function, *cardinality).to_cnf().satisfy_one() self.assertIsNotNone(sat) solution = {x: sat.get(x) for x in self.pos} self.assertEqual(solution, {x: 1 for x in self.pos})
def test_qbf_negative(self): solver = self.get_solver() solver.forall(self.pos) solver.add(expr.And(*self.pos)) solution = solver.solve() self.assertIsNone(solution)
def test_at_most_one_zero(self): self.function = ~expr.Or(*self.neg) cardinality = constraint.at_most_one(self.function.support) sat = expr.And(self.function, *cardinality).to_cnf().satisfy_one() self.assertIsNotNone(sat)
def test_at_most_zero_small(self): (a, _b, _c) = self.pos self.function = a cardinality = cardnet.at_most(self.function.support, 0) sat = expr.And(self.function, *cardinality).to_cnf().satisfy_one() self.assertIsNone(sat)
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 __init__(self, *args, **kwargs): self.formula_dnf = self.formula.to_dnf() self.formula_onehot = onehot_f(self.formula) self.pos_assignments = [] self.neg_assignments = [] for spc in spec.ShapeSpec.enumerate_both(): if satisfies(spc, self.formula_onehot): self.pos_assignments.append(spc) else: self.neg_assignments.append(spc) self.disjunction = isinstance(self.formula, expr.OrOp) self.conjunction = isinstance(self.formula, expr.AndOp) # Get assignments by which part they satisfy self.left_assignments = [] self.right_assignments = [] self.both_assignments = [] self.neither_assignments = [] if self.conjunction or self.disjunction: left_formula, right_formula = self.formula.xs only_left = onehot_f( expr.And(left_formula, expr.Not(right_formula))) only_right = onehot_f( expr.And(right_formula, expr.Not(left_formula))) for spc in spec.ShapeSpec.enumerate_both(): if satisfies(spc, only_left): self.left_assignments.append(spc) elif satisfies(spc, only_right): self.right_assignments.append(spc) elif satisfies(spc, self.formula_onehot): # Both self.both_assignments.append(spc) else: self.neither_assignments.append(spc) if self.disjunction: assert set(self.neither_assignments) == set( self.neg_assignments) assert set(self.left_assignments + self.right_assignments + self.both_assignments) == set(self.pos_assignments) else: assert set(self.both_assignments) == set(self.pos_assignments) assert set(self.left_assignments + self.right_assignments + self.neither_assignments) == set( self.neg_assignments)
def test_sat_negative_assumption(self): solver = self.get_solver() solver.add(expr.And(*(~p for p in self.pos))) assumptions = {v: True for v in self.pos} solution = solver.solve(assumptions=assumptions) self.assertIsNone(solution)
def test_not_equals_higher(self): equals = expr.exprvar("equals") cardinality = cardnet.equals(self.function.support, len(self.pos) + 1, ~equals) sat = expr.And(self.function, equals, *cardinality).to_cnf().satisfy_one() self.assertIsNotNone(sat) self.assertEqual(sat.get(equals), 1)
def test_at_most_one_small(self): self.function = self.pos cardinality = constraint.at_most_one(self.function.support) sat = expr.And(self.function, *cardinality).to_cnf().satisfy_one() self.assertIsNotNone(sat) self.assertEqual(sat.get(self.pos), 1)
def test_not_at_most_is_not_equivalent(self): at_most = expr.exprvar("at_most") cardinality = cardnet.at_most(self.function.support, len(self.pos) - 1, ~at_most) sat = expr.And(self.function, at_most, *cardinality).to_cnf().satisfy_one() self.assertIsNotNone(sat) self.assertEqual(sat.get(at_most), 1)
def test_at_least_one_equivalent(self): at_least = expr.exprvar("at_least") cardinality = constraint.at_least_one(self.function.support, at_least) sat = expr.And(self.function, at_least, *cardinality).to_cnf().satisfy_one() self.assertIsNotNone(sat) self.assertEqual(sat.get(at_least), 1)
def test_equals_one_small(self): (a, _b, _c) = self.pos self.function = a cardinality = cardnet.equals(self.function.support, 1) sat = expr.And(self.function, *cardinality).to_cnf().satisfy_one() self.assertIsNotNone(sat) self.assertEqual(sat.get(a), 1)
def test_not_equals_one_not_equivalent(self): self.function = ~expr.Or(*self.neg) equals = expr.exprvar("equals") cardinality = constraint.equals_one(self.function.support, ~equals) sat = expr.And(self.function, equals, *cardinality).to_cnf().satisfy_one() self.assertIsNotNone(sat) self.assertEqual(sat.get(equals), 1)
def to_expr(self): if self.spec_type == ShapeSpecTypes.SHAPE: return shape.S2V[self.shape] elif self.spec_type == ShapeSpecTypes.COLOR: return color.C2V[self.color] else: return expr.And( color.C2V[self.color], shape.S2V[self.shape], )
def recurse(expression): if expression.ASTOP == "or": return expr.And(*(recurse(e) for e in expression.xs)) if expression.ASTOP == "and": return expr.Or(*(recurse(e) for e in expression.xs)) elif expression.ASTOP == "lit": return expression elif expression.is_one() or expression.is_zero(): return ~expression else: raise NotImplementedError(str(expression))
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)
def onehot_f(f): return expr.And(f, color.ONEHOT_VAR, shape.ONEHOT_VAR)
def _cover_to_expression(cover): inputs = (inp for (inp, outputs) in cover if outputs == (1, )) terms = (expr.And(*Function._vector_to_vars(v)) for v in inputs) return expr.Or(*terms)
def setUp(self): self.pos = tuple(expr.exprvar(p) for p in "abc") self.neg = tuple(expr.exprvar(p) for p in "uvwxyz") self.function = expr.And(*self.pos, ~expr.Or(*self.neg))
def test_at_most_lower(self): cardinality = cardnet.at_most(self.function.support, len(self.pos) - 1) sat = expr.And(self.function, *cardinality).to_cnf().satisfy_one() self.assertIsNone(sat)
def test_equals_higher(self): cardinality = cardnet.equals(self.function.support, len(self.pos) + 1) sat = expr.And(self.function, *cardinality).to_cnf().satisfy_one() self.assertIsNone(sat)
def test_at_most_zero(self): cardinality = cardnet.at_most(self.function.support, 0) sat = expr.And(self.function, *cardinality).to_cnf().satisfy_one() self.assertIsNone(sat)