def test_to_js_smoke(): x, y = LTL.atom('x'), LTL.atom('y') expr1 = x.historically() \ .implies(y.once()) \ .with_output('sat') expr2 = x.once() \ .implies(y.historically()) \ .with_output('sat') exprs = [x, expr1, expr2, ~expr1, ~expr2, LTL.atom(True), LTL.atom(False)] with tempfile.TemporaryDirectory() as base: for expr in exprs: js_code = to_js(expr) js_code += 'var trc = [{"x": true, "y": true}, {"x": true, "y": false}]\n' # noqa: E501 js_code += 'console.log(JSON.stringify(spec_aig(trc)))' path = Path(base) / "test.js" with path.open('w') as f: f.write(js_code) js_result = check_output(['nodejs', str(path)], encoding='utf-8') result = json.loads(js_result) inputs = [{'x': True, 'y': True}, {'x': True, 'y': False}] assert expr.aig.simulate(inputs)[-1][0] == result
def unroll(self, horizon, *, init=True, omit_latches=True, only_last_outputs=False): hist_valid = LTL.atom(self.valid_id) \ .historically() \ .with_output(self.valid_id) monitor = BV.aig2aigbv(hist_valid.aig) circ = (self.circ >> monitor).unroll( horizon, init=init, omit_latches=omit_latches, only_last_outputs=only_last_outputs) if not only_last_outputs: times = range(1, horizon) circ >>= BV.sink(1, (f'{self.valid_id}##time_{t}' for t in times)) valid_id = f'{self.valid_id}##time_{horizon}' assert valid_id in circ.outputs input_encodings = timed_encodings(self.input_encodings, circ.inputs) output_encodings = timed_encodings(self.output_encodings, circ.outputs) return from_aigbv( circ=circ, input_encodings=input_encodings, output_encodings=output_encodings, valid_id=valid_id, )
def test_never_false_redemption(): spec = LTL.atom('x').historically() monitor = BV.aig2aigbv(spec.aig) assert len(monitor.latches) == 1 monitor = monitor['l', {fn.first(monitor.latches): 'z'}] # Environment can save you. x, y = BV.uatom(1, 'x'), BV.uatom(1, 'y') xy = (x | y).with_output('x') # env y can override x. dyn = C.pcirc(xy.aigbv) \ .randomize({'y': {0: 0.75, 1: 0.25}}) horizon = 3 model = from_pcirc(dyn, monitor, steps=horizon) coeff = np.log(2) # Special coeff to make LSE visit powers of 2. actor = improviser(model, coeff) v8 = coeff v7 = 0 v6 = coeff / 4 v5 = np.logaddexp(v6, coeff) v4 = (np.log(8) + v5) / 4 v3 = np.logaddexp(v4, v5) v2 = (3 * np.log(4) + v3) / 4 v1 = np.logaddexp(v2, v3) expected = sorted([v8, v7, v6, v5, v4, v3, v2, v1]) expected = fn.lmap(pytest.approx, expected) vals = sorted(list(actor.node2val.values())) assert all(x == y for x, y in zip(vals, expected)) def lprob(elems): return actor.prob(elems, log=True) assert lprob([]) == 0 assert lprob([1]) == pytest.approx(v3 - v1) for prefix in [[1], [1, 0, 1], [1, 1, 1], [1, 1, 1, 1, 1]]: for bit in [0, 1]: expected = pytest.approx(-np.log(4) + bit * np.log(3)) assert lprob(prefix + [bit]) - lprob(prefix) == expected ctrl = actor.policy() example = [] for env in [None, 0, 0]: example.append(ctrl.send(env)) assert -float('inf') < lprob(example) ctrl = actor.policy(observe_states=True) example = [] for env in [None, ({'x': 1}, None), ({'x': 1}, None)]: example.append(ctrl.send(env)) assert -float('inf') < lprob(example)
def test_never_false(): spec = LTL.atom('x').historically() monitor = BV.aig2aigbv(spec.aig) dyn = C.pcirc(BV.identity_gate(1, 'x')) horizon = 3 model = from_pcirc(dyn, monitor, steps=horizon) graph = model.graph() assert len(graph.nodes) == horizon + 2 assert len(graph.edges) == 2 * horizon
def test_never_false_redemption(): spec = LTL.atom('x').historically() monitor = BV.aig2aigbv(spec.aig) # Environment can save you. x, y = BV.uatom(1, 'x'), BV.uatom(1, 'y') xy = (x | y).with_output('x') # env y can override x. dyn = C.pcirc(xy.aigbv) \ .randomize({'y': {0: 0.4, 1: 0.6}}) horizon = 3 model = from_pcirc(dyn, monitor, steps=horizon) graph = model.graph() assert len(graph.nodes) == 2 * horizon + 2 assert len(graph.edges) == 4 * horizon
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_never_false1(): spec = LTL.atom('x').historically() monitor = BV.aig2aigbv(spec.aig) dyn = C.pcirc(BV.identity_gate(1, 'x')) horizon = 4 model = from_pcirc(dyn, monitor, steps=horizon) coeff = np.log(2) actor = model.improviser(rationality=coeff) expected = [ 0, coeff, np.log(1 + 2), np.log(3 + 2), np.log(7 + 2), np.log(15 + 2), ] # LSE visits powers of 2 for the special coeff. expected = fn.lmap(pytest.approx, expected) vals = sorted(list(actor.node2val.values())) assert all(x == y for x, y in zip(expected, vals)) expected = sorted([ np.log(9) - np.log(17), np.log(8) - np.log(17), ]) expected = fn.lmap(pytest.approx, expected) def lprob(elems): return actor.prob(elems, log=True) assert lprob([]) == 0 assert lprob([1]) == pytest.approx(np.log(9) - np.log(17)) assert lprob([1, 1]) == pytest.approx(np.log(5) - np.log(17)) assert lprob([1, 1, 1]) == pytest.approx(np.log(3) - np.log(17)) assert lprob([1, 1, 1, 1]) == pytest.approx(coeff - np.log(17)) # ----------- Fail on first state --------------------- base = np.log(8) - np.log(17) assert lprob([0]) == pytest.approx(base) # Uniform after failing. assert lprob([0, 1]) == pytest.approx(base - np.log(2)) assert lprob([0, 0]) == pytest.approx(base - np.log(2)) assert lprob([0, 0, 0]) == pytest.approx(base - np.log(4)) assert lprob([0, 0, 1]) == pytest.approx(base - np.log(4)) # ----------- Fail on second state --------------------- base = np.log(4) - np.log(17) assert lprob([1, 0]) == pytest.approx(base) assert lprob([1, 0, 0]) == pytest.approx(base - np.log(2)) assert lprob([1, 0, 1]) == pytest.approx(base - np.log(2)) assert lprob([1, 0, 0, 0]) == pytest.approx(base - np.log(4)) assert lprob([1, 1, 0, 1]) == pytest.approx(base - np.log(4)) with pytest.raises(ValueError): lprob([1, 1, 1, 1, 1, 1]) example = list(actor.sample()) assert -float('inf') < lprob(example) ctrl = actor.policy() example = [] for env in [None, 0, 0, 0]: example.append(ctrl.send(env)) assert -float('inf') < lprob(example) actor = model.improviser(psat=0.7) assert actor.sat_prob() == pytest.approx(0.7)
def valid_circ(action): hist_valid = PLTL.atom('valid').historically().with_output('valid') hist_valid = aiger_bv.aig2aigbv(hist_valid.aig) return is_1hot(action) >> hist_valid
observations = [ {k: v.index(True) + 1 for k, v in obs[0].items()} for obs in observations ] return [(obs['x'], obs['y']) for obs in observations] # ============== Specifications ==================== LAVA, RECHARGE = map(LTL.atom, ['red', 'yellow']) EVENTUALLY_RECHARGE = RECHARGE.once() AVOID_LAVA = (~LAVA).historically() CONST_TRUE = LTL.atom(True) SPECS = [ CONST_TRUE, AVOID_LAVA, EVENTUALLY_RECHARGE, AVOID_LAVA & EVENTUALLY_RECHARGE, ] SPEC_NAMES = [ "CONST_TRUE", "AVOID_LAVA", "EVENTUALLY_RECHARGE", "AVOID_LAVA & EVENTUALLY_RECHARGE",
return mdp 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 SPEC1 = PLTL.atom('a').historically() SPEC2 = PLTL.atom(True) SPEC3 = (PLTL.atom('a') == PLTL.atom('c')).historically() def gen_scenario(spec, sys): def scenario(negate=False): spec2 = ~spec if negate else spec return spec2, sys return scenario scenario1 = gen_scenario( spec=SPEC1, sys=sys1(),
import aiger_bv as BV import aiger_coins as C import aiger_ptltl as LTL from mce.equiv import equiv_states X = LTL.atom('x') Y = LTL.atom('y') SYS = C.circ2mdp(BV.aig2aigbv((X.once() | Y.once()).aig)) def test_equiv_states_smoke(): state = SYS._aigbv.latch2init for t in range(3): assert equiv_states(SYS, 3, t, state1=state, state2=state) state1 = SYS.aigbv({'x': (True, ), 'y': (False, )})[1] state2 = SYS.aigbv({'x': (False, ), 'y': (True, )})[1] assert state1 != state2 for t in range(3): assert equiv_states(SYS, 3, t, state1=state1, state2=state2)