def _make_init(internal_init, win, aut): """Return initial conditions for implementation. Depending on `aut.qinit`, synthesize the initial condition `aut.env_init` using the winning states `win`. @param internal_init: initial condition for internal variables. """ qinit = aut.qinit # impl qinit = '\A \A' # we synthesize `env_init` below env_init = aut.init['env'] new_sys_init = aut.init['sys'] & internal_init & win # synthesize initial predicate if qinit in ('\A \A', '\A \E', '\E \E'): new_env_init = env_init & new_sys_init elif qinit == '\E \A': env_bound = aut.exist(aut.varlist['sys'], env_init) u = env_init & new_sys_init u |= ~ env_bound sys_bound = aut.forall(aut.varlist['env'], u) new_env_init = env_bound & sys_bound else: raise ValueError( 'unknown `qinit` value "{qinit}"'.format( qinit=qinit)) assert new_env_init != aut.false assert new_sys_init != aut.false assert is_state_predicate(new_env_init) assert is_state_predicate(new_sys_init) aut.init['impl_env'] = new_env_init aut.init['impl_sys'] = new_sys_init
def _make_init(internal_init, win, aut): """Return initial conditions for implementation. Depending on `aut.qinit`, synthesize the initial condition `aut.env_init` using the winning states `win`. @param internal_init: initial condition for internal variables. """ qinit = aut.qinit # impl qinit = '\A \A' # we synthesize `env_init` below env_init = aut.init['env'] new_sys_init = aut.init['sys'] & internal_init & win # synthesize initial predicate if qinit in ('\A \A', '\A \E', '\E \E'): new_env_init = env_init & new_sys_init elif qinit == '\E \A': env_bound = aut.exist(aut.varlist['sys'], env_init) u = env_init & new_sys_init u |= ~env_bound sys_bound = aut.forall(aut.varlist['env'], u) new_env_init = env_bound & sys_bound else: raise ValueError('unknown `qinit` value "{qinit}"'.format(qinit=qinit)) assert new_env_init != aut.false assert new_sys_init != aut.false assert is_state_predicate(new_env_init) assert is_state_predicate(new_sys_init) aut.init['impl_env'] = new_env_init aut.init['impl_sys'] = new_sys_init
def solve_rabin_game(aut, rank=1): """Return winning set and iterants for Rabin(1) game. @param aut: compiled game with <>[] & []<> winning @type aut: `temporal.Automaton` """ assert rank == 1, 'only rank 1 supported for now' assert aut.bdd.vars or not aut.vars, ( 'first call `Automaton.build`') # TODO: can these assertions be removed elegantly ? assert len(aut.win['<>[]']) > 0 assert len(aut.win['[]<>']) > 0 aut.build() z = aut.false zold = None zk = list() yki = list() xkijr = list() while z != zold: zold = z xijr = list() yi = list() for hold in aut.win['<>[]']: y, xjr = _cycle_inside(zold, hold, aut) z |= y xijr.append(xjr) yi.append(y) zk.append(z) yki.append(yi) xkijr.append(xijr) assert is_state_predicate(z), z.support return zk, yki, xkijr
def _assert_is_win(d): if isinstance(d, list): for u in d: assert prm.is_state_predicate(u), u return assert isinstance(d, dict), d for _, v in d.items(): _assert_is_win(v)
def test_is_state_predicate(): fol = setup() s = "x = -3 /\ ~ y" u = fol.add_expr(s) assert prm.is_state_predicate(u) assert not prm.is_primed_state_predicate(u, fol) assert not prm.is_proper_action(u) s = "x' = -3 /\ ~ y'" u = fol.add_expr(s) assert not prm.is_state_predicate(u) assert prm.is_primed_state_predicate(u, fol) assert not prm.is_proper_action(u) s = "x = -3 /\ ~ y'" u = fol.add_expr(s) assert not prm.is_state_predicate(u) assert not prm.is_primed_state_predicate(u, fol) assert prm.is_proper_action(u)
def trap(env_action, sys_action, safe, aut, unless=None): """Return subset of `safe` with contolled exit. @param unless: if `None`, then returned controlled invariant subset of `safe`. Otherwise, this defines an allowed set. @rtype: BDD node """ logger.info('++ cinv') assert is_state_predicate(safe), aut.support(safe) q = aut.true # if `unless is not None`, # then `q = safe` is wrong qold = None while q != qold: qold = q pre = step(env_action, sys_action, q, aut) q = safe & pre if unless is not None: q |= unless assert is_state_predicate(q), aut.support(q) logger.info('-- cinv') return q
def attractor(env_action, sys_action, target, aut, inside=None): """Return attractor for `target`. Keyword args as `step`. @param inside: remain in this set """ logger.info('++ attractor') assert is_state_predicate(target), aut.support(target) # ancestors q = target qold = None while q != qold: qold = q pred = step(env_action, sys_action, q, aut) q |= pred if inside is not None: q &= inside assert is_state_predicate(q), aut.support(q) logger.info('-- attractor') return q
def print_nodes(u, dvars, bdd, care_set=None, care_bits=None): """Enumerate first-order models of a set. A set of nodes is defined over unprimed variables. @param dvars: table of unprimed variables @type bdd: `BDD` """ assert scope.is_state_predicate(u), u.support if u == bdd.false: print('empty set') return if care_bits is not None: assert scope.support_issubset(u, care_bits, bdd), (support, care_bits) _print_enumeration(u, bdd, dvars, care_set, care_bits)
def _assert_invariant(components, aut, moore=True): """Assert invariant about `aut.varlists` and predicates. - varlists of `components` are disjoint - `aut.init` and `aut.win` contain state predicates If `moore=True`, then assert that `aut.action` are actions of `components`. """ varlists = {k: v for k, v in aut.varlist.items() if k in components} actions = {k: v for k, v in aut.actions.items() if k in components} assert prm.pairwise_disjoint(varlists), varlists for u in aut.init.values(): assert prm.is_state_predicate(u) _assert_is_win(aut.win) if not moore: return for component, action in actions.items(): assert prm.is_action_of_player(action, component, aut)
def do_it_yourself(): """Compute states *from* where we can reach a goal.""" aut, goal, action = spec() # Compute the least fixpoint, # so the states from where we can reach the `goal` # with one or more steps, or we are already there. vrs = aut.varlist['sys'] primed_vrs = stx.prime_vars(vrs) r = aut.false rold = None # for sure != r, thus at least one iteration assert r != rold while r != rold: rold = r # memo target = aut.replace_with_primed(vrs, r) pre = aut.exist(primed_vrs, action & target) r |= goal | pre assert prm.is_state_predicate(r) print_expr(r, aut)
def solve_streett_game(aut, rank=1): r"""Return winning set and iterants for Streett(1) game. The returned value takes into account actions and liveness, not initial conditions (i.e., it is the fixpoint before reasoning about initial conditions). Expects "env" and "sys" players. Writes: - `aut.varlist["env'"]` - `aut.varlist["sys'"]` @param aut: compiled game with <>[] \/ []<> winning @type aut: `temporal.Automaton` """ assert rank == 1, 'only rank 1 supported for now' assert aut.bdd.vars or not aut.vars, ( 'first call `Automaton.build`') assert len(aut.win['<>[]']) > 0 assert len(aut.win['[]<>']) > 0 env_action = aut.action['env'] sys_action = aut.action['sys'] aut.build() z = aut.true zold = None while z != zold: zold = z cox_z = fx.step(env_action, sys_action, z, aut) xijk = list() yij = list() for goal in aut.win['[]<>']: goal &= cox_z y, yj, xjk = _attractor_under_assumptions(goal, aut) z &= y xijk.append(xjk) yij.append(yj) assert is_state_predicate(z), z.support return z, yij, xijk
def _make_init(internal_init, win, aut): """Return initial conditions for implementation. Depending on `aut.qinit`, synthesize the initial condition `aut.init['impl']` using the winning states `win`. The cases are: - `\A \A`: `InternalInit` - `\E \E`: `InternalInit /\ Win /\ SysInit` - `\A \E`: - `plus_one is True`: ``` /\ SysInit /\ (EnvInit => Win) /\ InternalInit ``` - `plus_one is False`: ``` /\ EnvInit => (SysInit /\ Win) /\ InternalInit ``` - `\E \A`: - `plus_one is True`: ``` /\ \A EnvVars: SysInit /\ (EnvInit => Win) /\ InternalInit ``` - `plus_one is False`: ``` /\ \A EnvVars: EnvInit => (SysInit /\ Win) /\ InternalInit ``` where `InternalInit` is the initial condition for internal variables. @param internal_init: initial condition for internal variables. """ sys_init = aut.init['sys'] env_init = aut.init['env'] env_vars = aut.varlist['env'] qinit = aut.qinit plus_one = aut.plus_one # In `omega.games.enumeration` both of these reduce # to `sys_init & win` over those states that are # enumerated as initial, because only states that # satisfy `env_init` are enumerated--assuming # `env_init` is independent of sys vars. if plus_one: form = sys_init & (win | ~ env_init) else: form = (sys_init & win) | ~ env_init assert is_state_predicate(form) if qinit == '\A \A': # shared-state, env picks initial state init = aut.true elif qinit == '\E \E': # shared-state, sys picks initial state init = win & sys_init elif qinit == '\A \E': # disjoint-state init = form elif qinit == '\E \A': # disjoint-state init = aut.forall(env_vars, form) else: raise ValueError( 'unknown `qinit` value "{q}"'.format(q=qinit)) assert init != aut.false assert is_state_predicate(init) aut.init['impl'] = init & internal_init