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 test_biased_coin(k, m): f = Fraction(*sorted([k, m])) k, m = f.numerator, f.denominator for prob in [f, (k, m)]: k_expr, m_expr = coin((k, m), 'x') f2 = Fraction(count(k_expr), count(m_expr)) assert f == f2
def sys3(): mdp = sys1() mdp |= C.circ2mdp(BV.tee(1, {'c': ['c', 'c_next']})) coin = (~C.coin((1, 2), name='c')).with_output('c') mdp <<= coin delay = BV.aig2aigbv(aiger.delay(['c'], [True])) delay = C.circ2mdp(delay) return mdp >> delay
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 test_reweighted(): spec, sys = scenario_reactive() # Hack too re-weight coinl sys2 = C.coin((1, 4), 'c') >> C.MDP(sys.aigbv >> BV.sink(1, ['##valid'])) cspec2 = concretize(spec, sys2, 3) graph, root, _ = spec2graph(cspec2) assert nx.is_directed_acyclic_graph(graph) assert len(graph.nodes) == 12 assert len(graph.edges) == 20 for node in graph.nodes: assert graph.out_degree[node] <= 2
def test_smoke(): spec = PLTL.atom('a').historically() spec = BV.aig2aigbv(spec.aig) spec = C.circ2mdp(spec) spec <<= C.coin((1, 8), name='c') spec >>= C.circ2mdp(BV.sink(1, ['c'])) # HACK bdd, manager, order = to_bdd2(spec, horizon=3) assert bdd.dag_size == 4 for i in range(order.total_bits*order.horizon): t = order.time_step(i) var = manager.var_at_level(i) action, t2, _ = TIMED_INPUT_MATCHER.match(var).groups() assert t == int(t2) decision = action in spec.inputs assert decision == order.is_decision(i)
def test_find_env_input(): x, c = map(aiger_ptltl.atom, ('x', 'c')) sys = (x & c).historically().aig sys = circ2mdp(aiger_bv.aig2aigbv(sys)) sys <<= coin((1, 2), name='c') assert sys.inputs == {'x'} assert len(sys.outputs) == 1 out, *_ = sys.outputs start = end = sys.aigbv.latch2init action = {'x': (True, )} coins = sys.find_env_input(start, action, end) _, lmap = sys.aigbv(inputs={**action, **coins}) assert lmap == end
def test_find_coin_flips(): x, c = map(aiger_ptltl.atom, ('x', 'c')) sys = (x & c).historically().aig sys = circ2mdp(aiger_bv.aig2aigbv(sys)) sys <<= coin((1, 2), name='c') assert sys.inputs == {'x'} assert len(sys.outputs) == 1 out, *_ = sys.outputs sys_actions = 3 * [{'x': (True, )}] states = 3 * [{out: (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 test_biased_coin(k, m): f = Fraction(*sorted([k, m])) k, m = f.numerator, f.denominator for prob in [f, (k, m)]: assert coin((k, m), 'x').prob() == f
} def create_sensor(aps): sensor = BV.aig2aigbv(A.empty()) for name, ap in APS.items(): sensor |= ap.with_output(name).aigbv return sensor SENSOR = create_sensor(APS) DYN = GW.gridworld(8, start=(8, 8), compressed_inputs=True) SLIP = BV.atom(1, 'c', signed=False).repeat(2) & BV.atom(2, 'a', signed=False) SLIP = SLIP.with_output('a').aigbv DYN2 = C.coin((31, 32), 'c') >> C.circ2mdp(DYN << SLIP) def encode_state(x, y): x, y = [BV.encode_int(8, 1 << (v - 1), signed=False) for v in (x, y)] return {'x': tuple(x), 'y': tuple(y)} def ap_at_state(x, y, in_ascii=False): state = encode_state(x, y) obs = SENSOR(state)[0] if not in_ascii: return obs for k, code in {'yellow': 3, 'red': 1}.items():
def sys2(): mdp = sys1() mdp <<= C.coin((1, 8), name='c') mdp >>= C.circ2mdp(BV.sink(1, ['c'])) # HACK return mdp