Ejemplo n.º 1
0
def rename_variables(let, u, aut):
    """Rename primed and unprimed occurrences of variables.

    @param let: `dict` that renames unprimed variable identifiers
    """
    let_primed = {stx.prime(k): stx.prime(v) for k, v in let.items()}
    let.update(let_primed)
    r = aut.let(let, u)
    support = aut.support(r)
    assert not support.intersection(let), support
    return r
Ejemplo n.º 2
0
def _primed_vars_per_quantifier(varlist):
    """Return `dict` that maps each player to set of primed vars.

    @return: `dict` that maps
          player name -> set of primed vars
    """
    assert 'env' in varlist, varlist
    assert 'sys' in varlist, varlist
    primed_vars = dict(
        env={stx.prime(var) for var in varlist['env']},
        sys={stx.prime(var) for var in varlist['sys']})
    return primed_vars
Ejemplo n.º 3
0
def _action_to_steps(aut, qinit):
    assert aut.action['sys'] != aut.false
    primed_vars = _primed_vars_per_quantifier(aut.varlist)
    vrs = set(aut.varlist['env']).union(aut.varlist['sys'])
    unprime_vars = {stx.prime(var): var for var in vrs}
    # fix an order for tupling
    keys = list(vrs)
    umap = dict()  # map assignments -> node numbers
    g = nx.DiGraph()
    queue, visited = _init_search(g, aut, umap, keys, qinit)
    g.initial_nodes = set(queue)
    varnames = set(keys)
    symbolic._assert_support_moore(aut.action['sys'], aut)
    # search
    while queue:
        node = queue.pop()
        values = g.nodes[node]
        log.debug('at node: {d}'.format(d=values))
        assert set(values) == varnames, (values, varnames)
        u = aut.action['env']
        u = aut.let(values, u)
        # apply Mealy controller function
        env_iter = aut.pick_iter(
            u, care_vars=primed_vars['env'])
        u = aut.action['sys']
        assert u != aut.false
        sys = aut.let(values, u)
        assert sys != aut.false
        for next_env in env_iter:
            log.debug('next_env: {r}'.format(r=next_env))
            # no effect if `aut.moore`
            u = aut.let(next_env, sys)
            u = aut.let(unprime_vars, u)
            env_values = {unprime_vars[var]: value
                          for var, value in next_env.items()}
            v = aut.let(env_values, visited)
            v, remain = _select_candidate_nodes(
                u, v, aut, visited=True)
            sys_values = aut.pick(
                v, care_vars=aut.varlist['sys'])
            d = dict(env_values)
            d.update(sys_values)
            # assert
            u = aut.let(d, visited)
            assert u == aut.true or u == aut.false
            assert remain == (u == aut.true), remain
            # find or add node
            if remain:
                next_node = _find_node(d, umap, keys)
            else:
                next_node = _add_new_node(d, g, queue, umap, keys)
                visited = _add_to_visited(d, visited, aut)
            g.add_edge(node, next_node)
            log.debug((
                'next env: {e}\n'
                'next sys: {s}\n').format(
                    e=env_values,
                    s=sys_values))
    return g
Ejemplo n.º 4
0
def _add_primed_bits(unprimed_bits):
    """Return list of ordered primed and unprimed bits."""
    bits = list()
    for bit in unprimed_bits:
        primed = stx.prime(bit)
        bits.append(bit)
        bits.append(primed)
    return bits
Ejemplo n.º 5
0
def _prime_bits_of_integers(ints, t):
    """Return bit priming for integers in `x`."""
    bit_rename = dict()
    for i in ints:
        bits = t.vars[i]['bitnames']
        d = {k: stx.prime(k) for k in bits}
        bit_rename.update(d)
    return bit_rename
Ejemplo n.º 6
0
def _add_primed_bits(unprimed_bits):
    """Return list of ordered primed and unprimed bits."""
    bits = list()
    for bit in unprimed_bits:
        primed = stx.prime(bit)
        bits.append(bit)
        bits.append(primed)
    return bits
Ejemplo n.º 7
0
Archivo: fol.py Proyecto: johnyf/omega
def _prime_bits_of_integers(ints, t):
    """Return bit priming for integers in `x`."""
    bit_rename = dict()
    for i in ints:
        bits = t.vars[i]['bitnames']
        d = {k: stx.prime(k) for k in bits}
        bit_rename.update(d)
    return bit_rename
Ejemplo n.º 8
0
def prime(u, fol):
    """Prime state predicate `u`."""
    support = fol.support(u)
    # all identifiers are unprimed ?
    assert not any(stx.isprimed(name) for name in support), support
    # avoid priming constants
    # (no primed identifiers are declared for constants)
    vrs = {name for name in support if is_variable(name, fol)}
    let = {var: stx.prime(var) for var in vrs}
    return fol.let(let, u)
Ejemplo n.º 9
0
def prime(u, fol):
    """Prime state predicate `u`."""
    support = fol.support(u)
    # all identifiers are unprimed ?
    assert not any(stx.isprimed(name) for name in support), support
    # avoid priming constants
    # (no primed identifiers are declared for constants)
    vrs = {name for name in support if is_variable(name, fol)}
    let = {var: stx.prime(var) for var in vrs}
    return fol.let(let, u)
Ejemplo n.º 10
0
def _prime_and_order_table(t):
    """Return ordered table of primed and unprimed variables.

    The table maps each (integer or Boolean) variable to
    a `dict` of attributes (same as `t`).
    The attributes include `"bitnames"`.

    The following attributes are added:

      - level: index among ordered prime and unprimed integers
      - len: number of values the variable can take

    @param t: table of unprimed variables as `str`
    @type t: `dict`

    @rtype: `dict` from `str` to `dict`
    """
    ordvars = natsort.natsorted(t)
    dvars = dict()
    for i, var in enumerate(ordvars):
        d = t[var]
        j = 2 * i
        dtype = d['type']
        if dtype in ('int', 'saturating'):
            bits = list(d['bitnames'])
        elif dtype == 'bool':
            bits = [var]
        m = 2**len(bits)
        primed = stx.prime(var)
        pbits = [stx.prime(bit) for bit in bits]
        k = j + 1
        # copy attr
        dvars[var] = copy.deepcopy(d)
        dvars[primed] = copy.deepcopy(d)
        # update attr
        dvars[var].update(level=j, len=m, bitnames=bits)
        dvars[primed].update(level=k, len=m, bitnames=pbits)
    return dvars
Ejemplo n.º 11
0
def _prime_and_order_table(t):
    """Return ordered table of primed and unprimed variables.

    The table maps each (integer or Boolean) variable to
    a `dict` of attributes (same as `t`).
    The attributes include `"bitnames"`.

    The following attributes are added:

      - level: index among ordered prime and unprimed integers
      - len: number of values the variable can take

    @param t: table of unprimed variables as `str`
    @type t: `dict`

    @rtype: `dict` from `str` to `dict`
    """
    ordvars = natsort.natsorted(t)
    dvars = dict()
    for i, var in enumerate(ordvars):
        d = t[var]
        j = 2 * i
        dtype = d['type']
        if dtype in ('int', 'saturating'):
            bits = list(d['bitnames'])
        elif dtype == 'bool':
            bits = [var]
        m = 2**len(bits)
        primed = stx.prime(var)
        pbits = [stx.prime(bit) for bit in bits]
        k = j + 1
        # copy attr
        dvars[var] = copy.deepcopy(d)
        dvars[primed] = copy.deepcopy(d)
        # update attr
        dvars[var].update(level=j, len=m, bitnames=bits)
        dvars[primed].update(level=k, len=m, bitnames=pbits)
    return dvars
Ejemplo n.º 12
0
def add_primed_too(table):
    """Return table of primed and unprimed vars.

    Assert `table` contains only unprimed vars.
    Return new table with a primed variable for
    each unprimed variable in `table`,
    in addition to the unprimed variables.
    """
    t = dict()
    for var, d in table.items():
        assert not stx.isprimed(var)
        pvar = stx.prime(var)
        t[var] = dict(d)
        t[pvar] = dict(d)
    return t
Ejemplo n.º 13
0
def add_primed_too(table):
    """Return table of primed and unprimed vars.

    Assert `table` contains only unprimed vars.
    Return new table with a primed variable for
    each unprimed variable in `table`,
    in addition to the unprimed variables.
    """
    t = dict()
    for var, d in table.items():
        assert not stx.isprimed(var)
        pvar = stx.prime(var)
        t[var] = dict(d)
        t[pvar] = dict(d)
    return t
Ejemplo n.º 14
0
    def replace_with_primed(self, vrs, u):
        """Substitute primed for unprimed `vrs` in `u`.

        For example:

        ```
        u = aut.add_expr("x /\ y /\ z")
        vrs = ['x', 'y']
        v = aut.replace_with_primed(vrs, u)
        v_ = aut.add_expr("x' /\ y' /\ z")
        assert v == v_
        ```
        """
        let = {k: stx.prime(k) for k in vrs}
        return self.let(let, u)
Ejemplo n.º 15
0
    def prime_varlists(self, keys=None):
        """Map primed `keys` to lists of primed variables.

        For each `k in keys`, add `"{k}'".format(k=k)` to
        `self.varlist`, with value the `list` that results
        from priming the variables in `self.varlist[k]`.

        If `keys is None`, prime all unprimed variable lists.
        """
        if keys is None:
            keys = set(self.varlist)
        for k in keys:
            if stx.isprimed(k):
                continue
            pk = stx.prime(k)
            pvrs = stx.prime_vars(self.varlist[k])
            self.varlist[pk] = pvrs
Ejemplo n.º 16
0
    def prime_varlists(self, keys=None):
        """Map primed `keys` to lists of primed variables.

        For each `k in keys`, add `"{k}'".format(k=k)` to
        `self.varlist`, with value the `list` that results
        from priming the variables in `self.varlist[k]`.

        If `keys is None`, prime all unprimed variable lists.
        """
        if keys is None:
            keys = set(self.varlist)
        for k in keys:
            if stx.isprimed(k):
                continue
            pk = stx.prime(k)
            pvrs = stx.prime_vars(self.varlist[k])
            self.varlist[pk] = pvrs
Ejemplo n.º 17
0
    def replace_with_primed(self, vrs, u):
        r"""Substitute primed for unprimed `vrs` in `u`.

        For example:

        ```
        u = aut.add_expr("x /\ y /\ z")
        vrs = ['x', 'y']
        v = aut.replace_with_primed(vrs, u)
        v_ = aut.add_expr("x' /\ y' /\ z")
        assert v == v_
        ```

        Identifiers in `vrs` should be declared as variables.
        Identifiers declared as constants will raise errors.
        """
        let = {k: stx.prime(k) for k in vrs}
        return self.let(let, u)
Ejemplo n.º 18
0
    def replace_with_primed(self, vrs, u):
        r"""Substitute primed for unprimed `vrs` in `u`.

        For example:

        ```
        u = aut.add_expr("x /\ y /\ z")
        vrs = ['x', 'y']
        v = aut.replace_with_primed(vrs, u)
        v_ = aut.add_expr("x' /\ y' /\ z")
        assert v == v_
        ```

        Identifiers in `vrs` should be declared as variables.
        Identifiers declared as constants will raise errors.
        """
        let = {k: stx.prime(k) for k in vrs}
        return self.let(let, u)
Ejemplo n.º 19
0
def _partition_vars(bits, ubits, ebits):
    """Return primed and unprimed variable names.

    @param bits: `list` of variable names as `str`
    @param ubits: universally quantified variables
    @param ebits: existentially quantified variables

    @return: (prime, partition)
      - prime: `dict` that maps unprimed to primed variable names
      - partition: `dict(uvars=set, upvars=set,
                         evars=set, epvars=set)`
    """
    prime = {b: stx.prime(b) for b in bits}
    partition = dict(
        uvars=set(ubits),
        upvars={prime[b] for b in ubits},
        evars=set(ebits),
        epvars={prime[b] for b in ebits})
    return prime, partition
Ejemplo n.º 20
0
def _partition_vars(bits, ubits, ebits):
    """Return primed and unprimed variable names.

    @param bits: `list` of variable names as `str`
    @param ubits: universally quantified variables
    @param ebits: existentially quantified variables

    @return: (prime, partition)
      - prime: `dict` that maps unprimed to primed variable names
      - partition: `dict(uvars=set, upvars=set,
                         evars=set, epvars=set)`
    """
    prime = {b: stx.prime(b) for b in bits}
    partition = dict(uvars=set(ubits),
                     upvars={prime[b]
                             for b in ubits},
                     evars=set(ebits),
                     epvars={prime[b]
                             for b in ebits})
    return prime, partition
Ejemplo n.º 21
0
def is_primed_state_predicate(u, fol):
    """Return `True` if `u` depends only on primed variables.

    Only constant parameters (rigid variables) can appear
    unprimed in `u`. Any flexible variables in `u` should
    be primed.

    An identifier that is declared only unprimed is assumed
    to be a rigid variables. If a primed sibling is declared,
    then the identifier is assumed to be a flexible variable.
    """
    support = fol.support(u)
    primed = {name for name in support if stx.isprimed(name)}
    unprimed = support - primed
    any_flexible = False
    for name in unprimed:
        primed = stx.prime(name)
        if primed in fol.vars:
            any_flexible = True
            break
    return not any_flexible
Ejemplo n.º 22
0
def _sys_trans(g, nodevar, dvars):
    """Convert transition relation to safety formula."""
    logger.debug('modeling sys transitions in logic')
    sys_trans = list()
    for u in g:
        pre = _assign(nodevar, u, dvars)
        # no successors ?
        if not g.succ.get(u):
            logger.debug('node: {u} is deadend !'.format(u=u))
            sys_trans.append('({pre}) => False'.format(pre=pre))
            continue
        post = list()
        for u, v, d in g.edges(u, data=True):
            t = dict(d)
            t[stx.prime(nodevar)] = v
            r = _to_action(t, dvars)
            post.append(r)
        c = '({pre}) => ({post})'.format(pre=pre, post=stx.disj(post))
        sys_trans.append(c)
    s = stx.conj(sys_trans, sep='\n')
    return s
Ejemplo n.º 23
0
def _sys_trans(g, nodevar, dvars):
    """Convert transition relation to safety formula."""
    logger.debug('modeling sys transitions in logic')
    sys_trans = list()
    for u in g:
        pre = _assign(nodevar, u, dvars)
        # no successors ?
        if not g.succ.get(u):
            logger.debug('node: {u} is deadend !'.format(u=u))
            sys_trans.append('({pre}) => False'.format(pre=pre))
            continue
        post = list()
        for u, v, d in g.edges(u, data=True):
            t = dict(d)
            t[stx.prime(nodevar)] = v
            r = _to_action(t, dvars)
            post.append(r)
        c = '({pre}) => ({post})'.format(pre=pre, post=stx.disj(post))
        sys_trans.append(c)
    s = stx.conj(sys_trans, sep='\n')
    return s
Ejemplo n.º 24
0
    def _type_hints_to_formulas(self, vrs, action):
        r"""Return type constraint for `vrs` as `str`.

        If `action is False` then return type invariant `Inv`,
        else the action `Inv /\ Inv'`.
        """
        r = list()
        for var in vrs:
            hints = self.vars[var]
            if hints['type'] == 'bool':
                continue
            assert hints['type'] == 'int', hints
            a, b = hints['dom']
            s = r'({a} <= {var}) /\ ({var}  <= {b})'
            type_inv = s.format(a=a, b=b, var=var)
            r.append(type_inv)
            if not action:
                continue
            type_inv_primed = s.format(a=a, b=b, var=stx.prime(var))
            r.append(type_inv_primed)
        return stx.conj(r)
Ejemplo n.º 25
0
def _env_trans(g, nodevar, dvars, self_loops):
    """Convert environment transitions to safety formula.

    @type g: `networkx.MultiDigraph`
    @param nodevar: name of variable representing current node
    @type nodevar: `str`
    @type dvars: `dict`
    """
    env_trans = list()
    for u in g:
        pre = _assign(nodevar, u, dvars)
        # no successors ?
        if not g.succ.get(u):
            env_trans.append('{pre} => False'.format(pre=pre))
            if not self_loops:
                warnings.warn(
                    'Environment dead-end found.\n'
                    'If sys can force env to dead-end,\n'
                    'then GR(1) assumption becomes False,\n'
                    'and spec trivially True.')
            continue
        post = list()
        sys = list()
        for u, v, d in g.out_edges(u, data=True):
            # action
            t = dict(d)
            t[stx.prime(nodevar)] = v
            r = _to_action(t, dvars)
            post.append(r)
            # what sys vars ?
            t = {k: v for k, v in d.items()
                 if k not in g.env_vars}
            r = _to_action(t, dvars)
            sys.append(r)
        # avoid sys winning env by blocking all edges
        # post.append(stx.conj_neg(sys))
        env_trans.append('({pre}) => ({post})'.format(
            pre=pre, post=stx.disj(post)))
    s = stx.conj(env_trans, sep='\n')
    return s
Ejemplo n.º 26
0
    def _type_hints_to_formulas(self, vrs, action):
        r"""Return type constraint for `vrs` as `str`.

        If `action is  True` then return type invariant `Inv`,
        else the action `Inv /\ Inv'`.
        """
        r = list()
        for var in vrs:
            hints = self.vars[var]
            if hints['type'] == 'bool':
                continue
            assert hints['type'] == 'int', hints
            a, b = hints['dom']
            s = r'({a} <= {var}) /\ ({var}  <= {b})'
            type_inv = s.format(a=a, b=b, var=var)
            r.append(type_inv)
            if not action:
                continue
            type_inv_primed = s.format(
                a=a, b=b, var=stx.prime(var))
            r.append(type_inv_primed)
        return stx.conj(r)
Ejemplo n.º 27
0
def _env_trans(g, nodevar, dvars, self_loops):
    """Convert environment transitions to safety formula.

    @type g: `networkx.MultiDigraph`
    @param nodevar: name of variable representing current node
    @type nodevar: `str`
    @type dvars: `dict`
    """
    env_trans = list()
    for u in g:
        pre = _assign(nodevar, u, dvars)
        # no successors ?
        if not g.succ.get(u):
            env_trans.append('{pre} => False'.format(pre=pre))
            if not self_loops:
                warnings.warn('Environment dead-end found.\n'
                              'If sys can force env to dead-end,\n'
                              'then GR(1) assumption becomes False,\n'
                              'and spec trivially True.')
            continue
        post = list()
        sys = list()
        for u, v, d in g.out_edges(u, data=True):
            # action
            t = dict(d)
            t[stx.prime(nodevar)] = v
            r = _to_action(t, dvars)
            post.append(r)
            # what sys vars ?
            t = {k: v for k, v in d.items() if k not in g.env_vars}
            r = _to_action(t, dvars)
            sys.append(r)
        # avoid sys winning env by blocking all edges
        # post.append(stx.conj_neg(sys))
        env_trans.append('({pre}) => ({post})'.format(pre=pre,
                                                      post=stx.disj(post)))
    s = stx.conj(env_trans, sep='\n')
    return s
Ejemplo n.º 28
0
 def replace_with_unprimed(self, vrs, u):
     """Substitute unprimed `vrs` for primed in `u`."""
     let = {stx.prime(k): k for k in vrs}
     return self.let(let, u)
Ejemplo n.º 29
0
def _prime_dict(d):
    """Return `dict` with primed keys and `dict` mapping to them."""
    p = dict((stx.prime(k), d[k]) for k in d)
    d2p = {k: stx.prime(k) for k in d}
    return p, d2p
Ejemplo n.º 30
0
def action_to_steps(aut, qinit='\A \A'):
    r"""Return enumerated graph with steps as edges.

    Only `aut.init['env']` considered.
    The predicate `aut.init['sys']` is ignored.

    `qinit` has different meaning that in `omega.games.gr1`.
    Nonetheless, for synthesized `aut.init['env']`,
    the meaning of `qinit` here yields the expected result.

    Enumeration is done based on `qinit`:

    - `'\A \A'`: pick all states that satisfy `aut.init['env']`
    - `'\E \E'`: pick one state that satisfies `aut.init['env']`
    - `'\A \E'`: for all states that satisfy `aut.init['env']`,
      pick a unique state for each env state `x`
    - `'\E \A'`: pick a sys state `u` and enumerate all
      states that satisfy `aut.init['env']` and `y = u`
    """
    assert aut.action['sys'] != aut.false
    primed_vars = _primed_vars_per_quantifier(aut.varlist)
    unprime_vars = {stx.prime(var): var for var in aut.vars
                    if not stx.isprimed(var)}
    # fix an order for tupling
    keys = list(k for k in aut.vars if not stx.isprimed(k))
    umap = dict()  # map assignments -> node numbers
    g = nx.DiGraph()
    queue, visited = _init_search(g, aut, umap, keys, qinit)
    g.initial_nodes = set(queue)
    varnames = set(keys)
    symbolic._assert_support_moore(aut.action['sys'], aut)
    # search
    while queue:
        node = queue.pop()
        values = g.node[node]
        log.debug('at node: {d}'.format(d=values))
        assert set(values) == varnames, (values, aut.vars)
        u = aut.action['env']
        u = aut.let(values, u)
        # apply Mealy controller function
        env_iter = aut.pick_iter(
            u, care_vars=primed_vars['env'])
        u = aut.action['sys']
        assert u != aut.false
        sys = aut.let(values, u)
        assert sys != aut.false
        for next_env in env_iter:
            log.debug('next_env: {r}'.format(r=next_env))
            # no effect if `aut.moore`
            u = aut.let(next_env, sys)
            u = aut.let(unprime_vars, u)
            env_values = {unprime_vars[var]: value
                          for var, value in next_env.items()}
            v = aut.let(env_values, visited)
            # prefer already visited nodes
            v &= u
            if v == aut.false:
                log.info('cannot remain in visited nodes')
                v = u
                remain = False
            else:
                remain = True
            assert v != aut.false
            sys_values = aut.pick(
                v, care_vars=aut.varlist['sys'])
            d = dict(env_values)
            d.update(sys_values)
            # assert
            u = aut.let(d, visited)
            assert u == aut.true or u == aut.false
            assert remain == (u == aut.true), remain
            # find or add node
            if remain:
                next_node = _find_node(d, umap, keys)
            else:
                next_node = _add_new_node(d, g, queue, umap, keys)
                visited = _add_to_visited(d, visited, aut)
            g.add_edge(node, next_node)
            log.debug((
                'next env: {e}\n'
                'next sys: {s}\n').format(
                    e=env_values,
                    s=sys_values))
    return g
Ejemplo n.º 31
0
 def replace_with_unprimed(self, vrs, u):
     """Substitute unprimed `vrs` for primed in `u`."""
     let = {stx.prime(k): k for k in vrs}
     return self.let(let, u)
Ejemplo n.º 32
0
def is_variable(name, fol):
    """Return `True` if `name` is declared as variable.

    The identifier `name` should be unprimed.
    """
    return stx.prime(name) in fol.vars
Ejemplo n.º 33
0
 def prime_vars(self, vrs):
     """Return `list` of primed variables from `vrs`."""
     return [stx.prime(var) for var in vrs]
Ejemplo n.º 34
0
def _prime_dict(d):
    """Return `dict` with primed keys and `dict` mapping to them."""
    p = dict((stx.prime(k), d[k]) for k in d)
    d2p = {k: stx.prime(k) for k in d}
    return p, d2p
Ejemplo n.º 35
0
def action_to_steps(aut, qinit='\A \A'):
    r"""Return enumerated graph with steps as edges.

    Only `aut.init['env']` considered.
    The predicate `aut.init['sys']` is ignored.

    `qinit` has different meaning that in `omega.games.gr1`.
    Nonetheless, for synthesized `aut.init['env']`,
    the meaning of `qinit` here yields the expected result.

    Enumeration is done based on `qinit`:

    - `'\A \A'`: pick all states that satisfy `aut.init['env']`
    - `'\E \E'`: pick one state that satisfies `aut.init['env']`
    - `'\A \E'`: for all states that satisfy `aut.init['env']`,
      pick a unique state for each env state `x`
    - `'\E \A'`: pick a sys state `u` and enumerate all
      states that satisfy `aut.init['env']` and `y = u`
    """
    assert aut.action['sys'] != aut.false
    primed_vars = _primed_vars_per_quantifier(aut.varlist)
    unprime_vars = {
        stx.prime(var): var
        for var in aut.vars if not stx.isprimed(var)
    }
    # fix an order for tupling
    keys = list(k for k in aut.vars if not stx.isprimed(k))
    umap = dict()  # map assignments -> node numbers
    g = nx.DiGraph()
    queue, visited = _init_search(g, aut, umap, keys, qinit)
    g.initial_nodes = set(queue)
    varnames = set(keys)
    symbolic._assert_support_moore(aut.action['sys'], aut)
    # search
    while queue:
        node = queue.pop()
        values = g.nodes[node]
        log.debug('at node: {d}'.format(d=values))
        assert set(values) == varnames, (values, aut.vars)
        u = aut.action['env']
        u = aut.let(values, u)
        # apply Mealy controller function
        env_iter = aut.pick_iter(u, care_vars=primed_vars['env'])
        u = aut.action['sys']
        assert u != aut.false
        sys = aut.let(values, u)
        assert sys != aut.false
        for next_env in env_iter:
            log.debug('next_env: {r}'.format(r=next_env))
            # no effect if `aut.moore`
            u = aut.let(next_env, sys)
            u = aut.let(unprime_vars, u)
            env_values = {
                unprime_vars[var]: value
                for var, value in next_env.items()
            }
            v = aut.let(env_values, visited)
            # prefer already visited nodes
            v &= u
            if v == aut.false:
                log.info('cannot remain in visited nodes')
                v = u
                remain = False
            else:
                remain = True
            assert v != aut.false
            sys_values = aut.pick(v, care_vars=aut.varlist['sys'])
            d = dict(env_values)
            d.update(sys_values)
            # assert
            u = aut.let(d, visited)
            assert u == aut.true or u == aut.false
            assert remain == (u == aut.true), remain
            # find or add node
            if remain:
                next_node = _find_node(d, umap, keys)
            else:
                next_node = _add_new_node(d, g, queue, umap, keys)
                visited = _add_to_visited(d, visited, aut)
            g.add_edge(node, next_node)
            log.debug(('next env: {e}\n'
                       'next sys: {s}\n').format(e=env_values, s=sys_values))
    return g
Ejemplo n.º 36
0
def is_variable(name, fol):
    """Return `True` if `name` is declared as variable.

    The identifier `name` should be unprimed.
    """
    return stx.prime(name) in fol.vars
Ejemplo n.º 37
0
def hide_vars_from_sys(vrs, inv, sys_player, aut):
    """Return new `sys_player` action, after hiding `vrs`.

    The variables `vrs` to be hidden are already selected.
    So this function is suitable for generating the component
    specifications after the parametric analysis has been
    completed.
    """
    turn_type = aut.vars[TURN]['type']
    turn_p = stx.prime(TURN)
    assert turn_type == 'int', turn_type
    turn_dom = aut.vars[TURN]['dom']
    # extract full-info actions from assembly action
    action = sym.conj_actions_of(aut.players, aut)
    inv_p = aut.replace_with_primed(aut.vars_of_all_players, inv)
    assembly_next = inv & inv_p & action
    others = set(aut.players)
    others.remove(sys_player)
    # notice the symmetry
    sys_vars = aut.vars_of_players([sys_player])
    sys_vars_p = aut.prime_vars(sys_vars)
    env_vars = aut.vars_of_players(others)
    env_vars_p = aut.prime_vars(env_vars)
    extracted_sys_next = aut.exist(env_vars_p, assembly_next)
    extracted_env_next = aut.exist(sys_vars_p, assembly_next)
    # decompile `SysStep`
    k = aut.players[sys_player]
    kp = increment_turn(k, turn_dom)
    u = aut.let({TURN: k}, extracted_sys_next)
    inv_proj = aut.let({TURN: k}, inv)
    v = aut.let({turn_p: kp}, inv_p)
    inv_p_proj = aut.exist(env_vars_p, v)
    care = inv_proj & inv_p_proj
    s = sym.dumps_expr(u, aut, care=care)
    print('ExtractedSysStep ==')
    print(s)
    # hide variables from `SysNext`
    sys_next = extracted_sys_next
    u = sys_next | ~inv
    u = aut.forall(vrs, u)
    inv_h = aut.exist(vrs, inv)
    simpler_sys_next = u & inv_h
    # hide variables from `EnvNext`
    env_next = extracted_env_next
    u = env_next & inv
    vrs_p = aut.prime_vars(vrs)
    qvars = set(vrs).union(vrs_p)
    simpler_env_next = aut.exist(qvars, u)
    # decompile `inv_h`
    s = sym.dumps_expr(inv_h, aut, use_types=True)
    print('InvH == \E h:  Inv <=>')
    print(s)
    # decompile `SimplerSysNext`
    k = aut.players[sys_player]
    u = aut.let({TURN: k}, simpler_sys_next)
    inv_h_p = aut.replace_with_primed(aut.vars_of_all_players, inv_h)
    inv_h_p = aut.exist(env_vars_p, inv_h_p)
    assert stx.prime(TURN) not in aut.support(inv_h_p)
    inv_h_proj = aut.let({TURN: k}, inv_h)
    care = inv_h_proj & inv_h_p
    s = sym.dumps_expr(u, aut, care=inv_h, use_types=True)
    print('SimplerSysNext ==')
    print(s)
    # decompile `SimplerEnvNext`
    inv_h_p = aut.replace_with_primed(aut.vars_of_all_players, inv_h)
    inv_h_p = aut.exist(sys_vars_p, inv_h_p)
    for player, k in aut.players.items():
        if player == sys_player:
            continue
        if k is None:
            print('Scheduler skipped (plays concurrently)')
            continue
        inv_h_proj = aut.let({TURN: k}, inv_h)
        s = sym.dumps_expr(inv_h_proj, aut, use_types=True)
        print('InvH{player} == '.format(player=player))
        print(s)
        # use (known) scheduler action as care set
        kp = increment_turn(k, turn_dom)
        scheduler_action = {TURN: k, turn_p: kp}
        u = aut.let(scheduler_action, simpler_env_next)
        inv_h_p_proj = aut.let({turn_p: kp}, inv_h_p)
        care = inv_h_proj & inv_h_p_proj
        s = sym.dumps_expr(u, aut, care=inv_h, use_types=True)
        print('Simpler{player}Next == '.format(player=player))
        print(s)