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'}
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)
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)
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
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)
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
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")
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)
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})
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
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
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)
def test_bdd_transform_smoke(): to_bdd(atom(3, 'x', signed=False) < 4)
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())
def test_solve(): expr = atom(4, 'x') & atom(4, 'y') < 2 model = sat_bv.solve(expr) assert len(model) == 2 assert expr(model)