예제 #1
0
def test_closed_system():
    c1 = aiger_bv.atom(1, 'c1', signed=False)
    a = aiger_bv.atom(1, 'a', signed=False)

    dyn = circ2mdp(chain(n=4, state_name='s', action='a'))
    dyn <<= (c1 & a).with_output('a').aigbv
    c1_coin = coin((1, 8), name='c1')
    dyn <<= c1_coin

    assert dyn.inputs == {'a'}
    assert dyn.outputs == {'s'}
    start = {'s_prev': (True, False, False, False, False)}
    end = {'s_prev': (False, True, False, False, False)}
    assert dyn.prob(start, {'a': (0, )}, end) == 0
    assert dyn.prob(start, {'a': (1, )}, end) == c1_coin.prob() == 1 / 8

    c2 = aiger_bv.atom(1, 'c2', signed=False)
    const_false = aiger_bv.atom(1, 0, signed=False)
    state = aiger_bv.atom(5, 's', signed=False)
    clip = state == 0b00001

    policy = circ2mdp(aiger_bv.ite(clip, const_false, c2).with_output('a'))
    policy <<= coin((1, 8), name='c2')

    sys = (policy >> dyn).feedback(inputs=['s'],
                                   outputs=['s'],
                                   latches=['s_prev2'],
                                   keep_outputs=True)
    assert sys.inputs == set()
    assert sys.outputs == {'s'}
예제 #2
0
def chain(n, state_name='x', action='a', start=None, clip=True, can_stay=True):
    if start is None:
        start = n // 2
    else:
        start -= 1

    start = encode_int(n, 1 << start, signed=False)

    x = atom(n, state_name, signed=False)
    a = atom(2, action, signed=False)

    backward, forward = a[0], a[1]
    x2 = ite(forward, x << 1, x >> 1)

    stay = atom(1, 1, signed=False)
    if clip:
        stay = (x2 == 0)
    if can_stay:
        stay |= ~(forward | backward)
    if clip or can_stay:
        x2 = ite(stay, x, x2)

    circ = x2.aigbv['o', {x2.output: state_name}]
    return circ.feedback(inputs=[state_name],
                         outputs=[state_name],
                         initials=[start],
                         keep_outputs=True)
예제 #3
0
def test_get_model():
    expr = atom(4, 'x') & atom(4, 'y') < 2
    f = sat_bv.SolverBVWrapper()
    f.add_expr(expr)

    model = f.get_model()
    assert len(model) == 2
    assert expr(model)
예제 #4
0
def gen_equiv_checks(aps: AtomicPreds) -> Iterable[BVExpr]:
    for t, ap in enumerate(aps):
        for name, val in ap.items():
            size = len(val)
            timed_name = f"{name}##time_{t + 1}"
            sym = BV.atom(size, timed_name, signed=False)
            sym_val = BV.atom(size, val, signed=False)

            yield sym == sym_val
예제 #5
0
def chain(n, state_name='x', action='H'):
    bits = n + 1
    start = encode_int(bits, 1, signed=False)

    x = atom(bits, state_name, signed=False)
    forward = atom(1, action, signed=False)

    x2 = ite(forward, x << 1, x)
    circ = x2.aigbv['o', {x2.output: state_name}]
    return circ.feedback(inputs=[state_name],
                         outputs=[state_name],
                         latches=[f"{state_name}_prev"],
                         initials=[start],
                         keep_outputs=True)
예제 #6
0
def test_mdp_readme():
    from aiger_bv import atom
    from aiger_coins import circ2mdp

    x = atom(3, 'x', signed=False)
    y = atom(3, 'y', signed=False)
    expr = (x & y).with_output('x&y')

    mdp1 = circ2mdp(expr)
    dist = aiger_coins.dist((0, 1, 2), name='y')

    mdp2 = dist >> mdp1

    assert mdp1.inputs == {'x', 'y'}
    assert mdp2.inputs == {'x'}

    mdp3 = mdp2 | circ2mdp(aiger_bv.identity_gate(3, 'z'))
    assert mdp3.inputs == {'x', 'z'}
    assert mdp3.outputs == {'x&y', 'z'}

    mdp4 = mdp3.feedback(inputs=['z'], outputs=['x&y'], keep_outputs=True)
    assert mdp4.inputs == {'x'}
    assert mdp4.outputs == {'x&y', 'z'}

    action = atom(1, 'action', signed=False)
    x_prev = atom(1, 'x_prev', signed=False)
    c = atom(1, 'c', signed=False)

    x_next = (x_prev & c & action).with_output('x_next')

    sys = circ2mdp(x_next).feedback(
        keep_outputs=True,
        inputs=['x_prev'],
        outputs=['x_next'],
        initials=[(True, )],
    )
    sys <<= coin((1, 2), name='c')
    assert sys.inputs == {'action'}
    assert sys.outputs == {'x_next'}

    sys_actions = 3 * [{'action': (True, )}]
    states = 3 * [{'x_next': (True, )}]

    actions = sys.encode_trc(sys_actions, states)
    assert not any(v['c'][0] for v in actions)

    sys_actions2, states2 = sys.decode_trc(actions)
    assert sys_actions2 == sys_actions
    assert states2 == states
예제 #7
0
def main():
    print("START")
    X = BV.atom(8, 'x', signed=False)
    Y = BV.atom(8, 'y', signed=False)
    APS = {       #            x-axis       y-axis
     'yellow': mask_test(0b1000_0001, 0b1000_0001, X, Y),
     'blue':   mask_test(0b0001_1000, 0b0011100, X, Y),
     'brown':   mask_test(0b0011_1100, 0b1000_0001, X, Y),
     'red':    mask_test(0b1000_0001, 0b0100_1100, X, Y) \
      | mask_test(0b0100_0010, 0b1100_1100, X, Y),
    }

    SENSOR = create_sensor(APS)

    print_map(SENSOR)
    print("SUCCESS")
예제 #8
0
def dfa2aig(dfa: DFA):
    """
    Takes a dfa.DFA object and returns a tuple of:

    1. An aiger_bv.AIGBV circuit modeling the DFA's labeling and
       transitions.  This circuit has 1 input, output, and latch
       called "action", "output", and "state" respectively.

    2. A dictionary with at three entries, "inputs", "outputs", and
    "states".

      - Each entry of this dictionary is a bidict that maps one-hot
        encoded tuples, e.g. (True, False, False), to dfa inputs,
        outputs, states.

    3. An aiger_bv.AIGBV circuit which monitors is all inputs are
       valid, e.g., one_hot encoded.
    """
    in2bv, out2bv, state2bv = create_bv_maps(dfa)
    dfa_dict, _ = dfa2dict(dfa)

    action = aiger_bv.atom(len(dfa.inputs), 'action', signed=False)
    state = aiger_bv.atom(len(dfa.states()), 'state', signed=False)

    circ = out_circ(dfa_dict, state2bv, out2bv, state)
    circ |= transition_circ(dfa_dict, state2bv, in2bv, action, state)

    start = state2bv[dfa.start]

    circ = circ.loopback({
        "input": "state",
        "output": "next_state",
        "init": start,
        "keep_output": False,
    })

    relabels = {
        'inputs': in2bv.inv,
        'outputs': out2bv.inv,
        'states': state2bv.inv
    }

    return circ, relabels, valid_circ(action)
예제 #9
0
def test_seq_composition():
    x = BV.atom(4, 'x')
    y = BV.atom(4, 'y')

    circ1 = (x + 1).with_output('y').aigbv \
        | (x < 5).with_output('##valid').aigbv
    func1 = from_aigbv(circ1,)

    circ2 = (y - 1).with_output('z').aigbv \
        | (y > 2).with_output('##valid').aigbv
    func2 = from_aigbv(circ2,)

    func12 = func1 >> func2
    assert func12({'x': 4})[0] == {'z': 4}

    with pytest.raises(ValueError):
        func12({'x': 1})

    func12 = func2 << func1
    assert func12({'x': 4})[0] == {'z': 4}

    with pytest.raises(ValueError):
        func12({'x': 1})
예제 #10
0
def test_mdp_smoke():
    x = aiger_bv.identity_gate(2, 'x')
    y = aiger_bv.identity_gate(3, 'y')

    circ = x | y
    dist = aiger_coins.dist(((0, 3), (1, 3), (2, 3)), name='y')
    assert dist.expr.output == 'y'

    dyn = circ2mdp(circ, {'y': dist})
    assert dyn.inputs == {'x'}

    dyn2 = dist >> circ2mdp(circ)
    assert dyn2.inputs == {'x'}

    assert dyn2.aigbv.inputs == {'x'} | dist.inputs
    assert dyn2.aigbv.outputs == dyn2.outputs | {'##valid'}

    assert '##valid[0]' in dyn2.aig.outputs

    x = aiger_bv.atom(3, 'x', signed=False)
    y = aiger_bv.atom(3, 'y', signed=False)
    mdp = dist >> circ2mdp(x < y)
    assert mdp.inputs == {'x'}
    assert len(mdp.outputs) == 1
예제 #11
0
def dist(probs, name=None, keep_seperate=False):
    """Distribution generated by mutually exclusive coins.

    Encoded using the common denominator method.
    """
    is_coin = len(probs) == 1
    probs = _normalize_probs(probs)
    bots = [p.denominator for p in probs]
    lcm = reduce(utils.lcm, bots, 1)
    word_len = max(math.ceil(math.log2(lcm)), 1)
    weights = map(lambda p: p.numerator * (lcm // p.denominator), probs)

    bits = atom(word_len, name, signed=False)
    if name is not None:
        bits = bits.with_output(name)

    name = bits.output

    const_true = ~(bits @ 0)
    total, coins, max_val = 0, [], 2**word_len
    for i, weight in enumerate(weights):
        lb = const_true if total == 0 else (bits >= total)
        total += weight
        ub = const_true if total == max_val else (bits < total)
        coins.append(lb & ub)

    is_valid = const_true if lcm == max_val else bits < lcm

    if keep_seperate:
        return coins, is_valid

    coins = reduce(UnsignedBVExpr.concat, coins) \
        .with_output(name)

    _dist = Distribution(expr=coins, valid=is_valid)
    return _dist[0] if is_coin else _dist
예제 #12
0
def test_count_le(i):
    expr = atom(4, 'x', signed=False) < atom(4, i, signed=False)
    assert count(expr) == i
    assert count(expr, fraction=True) == i / (2**4)
예제 #13
0
def test_bdd_transform_smoke():
    to_bdd(atom(3, 'x', signed=False) < 4)
예제 #14
0
import aiger_ptltl as LTL
import funcy as fn
import termplotlib as tpl
from bidict import bidict
from blessings import Terminal


from mce.infer import spec_mle


# ================= World ========================

TERM = Terminal()


X = BV.atom(8, 'x', signed=False)
Y = BV.atom(8, 'y', signed=False)


def mask_test(xmask, ymask):
    return ((X & xmask) != 0) & ((Y & ymask) != 0)


APS = {
    'yellow': mask_test(0b1100_0000, 0b0000_0001),
    'red': mask_test(0b0011_1111, 0b1111_1111)
}


def create_sensor(aps):
    sensor = BV.aig2aigbv(A.empty())
예제 #15
0
def test_solve():
    expr = atom(4, 'x') & atom(4, 'y') < 2
    model = sat_bv.solve(expr)
    assert len(model) == 2
    assert expr(model)