Exemple #1
0
def is_equal(e1, e2):
    if isinstance(e1, aiger.AIG):
        assert len(e1.outputs) is 1
        e1 = aiger.BoolExpr(e1)
    if isinstance(e2, aiger.AIG):
        assert len(e2.outputs) is 1
        e2 = aiger.BoolExpr(e2)
    return is_valid(e1 == e2)
Exemple #2
0
def bmc_equiv(circ1, circ2, horizon, assume=None) -> Iterator[bool]:
    """
    Perform bounded model checking up to horizon to see if circ1 and
    circ2 are equivilent.
    """
    # Create distinguishing predicate.
    expr = BV.uatom(1, val=0)
    for o1 in circ1.outputs:
        o2 = f'{o1}##copy'
        size = circ1.omap[o1].size
        expr |= BV.uatom(size, o1) != BV.uatom(size, o2)
    expr.with_output('distinguished')

    monitor = ((circ1 | circ2) >> expr.aigbv).aig
    assert len(monitor.outputs) == 1

    # Make underlying aig lazy.
    monitor = monitor.lazy_aig

    # BMC loop
    for t in range(horizon):
        delta = horizon - t
        unrolled = monitor.unroll(delta, only_last_outputs=True)
        assert len(unrolled.outputs) == 1
        unrolled = aiger.BoolExpr(unrolled)

        if assume is not None:
            unrolled |= assume

        yield aiger_sat.is_sat(unrolled)
Exemple #3
0
def eliminate(e, variables, verbose=False):
    result_aig = _call_cadet(cmn.extract_aig(e),
                             variables,
                             projection=True,
                             verbose=verbose)
    if type(e) is aiger.BoolExpr:
        return aiger.BoolExpr(result_aig)
    return result_aig
Exemple #4
0
 def add_expr(self, expr):
     expr = aiger.BoolExpr(expr.aig)
     self.unsolved = True
     self.inputs |= expr.inputs
     cnf = aig2cnf(expr, fresh=self._id_pool)
     for clause in cnf.clauses:
         self.solver.add_clause(clause)
     self.sym_table.update(cnf.input2lit)
Exemple #5
0
def test_aig2cnf(circ, data):
    expr1 = aiger.BoolExpr(circ.unroll(1))
    cnf = aig2cnf(expr1)
    g = Glucose3()
    for c in cnf.clauses:
        g.add_clause(c)

    test_input = {i: data.draw(st.booleans()) for i in expr1.inputs}
    assumptions = []
    for name, val in test_input.items():
        if name not in cnf.input2lit:
            continue
        sym = cnf.input2lit[name]
        if not val:
            sym *= -1
        assumptions.append(sym)

    assert expr1(test_input) == g.solve(assumptions=assumptions)
Exemple #6
0
def to_bdd(circ_or_expr, output=None, manager=None, renamer=None, levels=None):
    if renamer is None:
        _count = 0

        def renamer(*_):
            nonlocal _count
            _count += 1
            return f"x{_count}"

    if not isinstance(circ_or_expr, aiger.BoolExpr):
        circ = aiger.to_aig(circ_or_expr, allow_lazy=True)
        assert len(circ.latches) == 0

        if output is None:
            assert len(circ.outputs) == 1
            output = fn.first(circ.outputs)

        expr = aiger.BoolExpr(circ)
    else:
        expr = circ_or_expr

    manager = BDD() if manager is None else manager
    input_refs_to_var = {
        ref: renamer(i, ref)
        for i, ref in enumerate(expr.inputs)
    }

    manager.declare(*input_refs_to_var.values())
    if levels is not None:
        assert set(manager.vars.keys()) <= set(levels.keys())
        levels = fn.project(levels, manager.vars.keys())
        levels = fn.walk_keys(input_refs_to_var.get, levels)

        manager.reorder(levels)
        manager.configure(reordering=False)

    def lift(obj):
        if isinstance(obj, bool):
            return manager.true if obj else manager.false
        return obj

    inputs = {i: manager.var(input_refs_to_var[i]) for i in expr.inputs}
    out = expr(inputs, lift=lift)
    return out, out.bdd, bidict(input_refs_to_var)
Exemple #7
0
def is_true_QBF(e, quantifiers):
    quantifiers = simplify_quantifier_prefix(quantifiers)
    aig = cmn.extract_aig(e)
    assert sum(map(len, fn.pluck(1, quantifiers))) == len(aig.inputs)
    if len(quantifiers) is 1:  # solve with SAT
        if quantifiers[0][0] is 'a':
            return is_valid(aig)
        else:
            assert quantifiers[0][0] is 'e'
            return is_satisfiable(aig)
    elif len(quantifiers) is 2:  # 2QBF
        true_return_code = CadetCodes.QBF_IS_TRUE.value
        if quantifiers[-1][0] is 'a':
            e = ~aiger.BoolExpr(aig)
            aig = e.aig
            true_return_code = CadetCodes.QBF_IS_FALSE.value
        return _call_cadet(aig, quantifiers[1][1]) == true_return_code
    else:
        raise NotImplementedError('Cannot handle general QBF at the moment')
Exemple #8
0
def are_equiv(expr1, expr2, *, engine=Glucose4):
    # Make sure they're expressions.
    assert len(expr1.aig.outputs) == len(expr2.aig.outputs) == 1
    expr1, expr2 = map(lambda e: aiger.BoolExpr(e.aig), (expr1, expr2))

    return is_valid(expr1 == expr2)
Exemple #9
0
def is_valid(e):
    e = ~aiger.BoolExpr(cmn.extract_aig(e))
    return not is_satisfiable(e)
def character(subset):
    if len(subset) == 0:
        return aiger.atom(False)

    return aiger.BoolExpr(aiger.parity_gate(subset))
Exemple #11
0
fullAig = andAig | PI1.aig | PI2.aig
fullAig = fullAig.feedback(['CI1'], ['PI1'])
fullAig = fullAig.feedback(['CI2'], ['PI2'])
#fullAig = andAig
#print(fullAig.loopback({"input": "b", "output": "a","init":True}))
print(fullAig)
exit()

in1, out1 = aiger.atoms('in1', 'out1')
in2, in3 = aiger.atoms('in2', 'in3')
expr1 = out1.with_output('out1')
expr2 = in2 & in3
aig1 = in1.aig | expr1.aig
aig2 = aig1.feedback(['in1'], ['out1'])
aig3 = aig2 | expr2.aig
expr4 = aiger.BoolExpr(aig3)
in4, in5 = aiger.atoms('in4', 'in5')
expr5 = in4 & expr4
print(expr5.aig)
exit()

outAtom = GraphSplitter.graphToAig(g, o)
print(outAtom)
exit()

w, x, y, z, o = aiger.atoms('w', 'x', 'y', 'z', 'o')
expr1 = x & y
expr2 = expr1.with_output('and1')
expr3 = z & w
expr4 = expr3.with_output('and2')
aig1 = expr2.aig | expr4.aig