예제 #1
0
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
예제 #2
0
    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,
        )
예제 #3
0
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)
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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)
예제 #7
0
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)
예제 #8
0
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
예제 #9
0
    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",
예제 #10
0
    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(),
예제 #11
0
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)