Esempio n. 1
0
def _init_from_ts(initial_nodes, nodevar, dvars, ignore_initial=False):
    """Return initial condition."""
    if ignore_initial:
        return list()
    if not initial_nodes:
        raise Exception('Transition system without initial states.')
    return [stx.disj(_assign(nodevar, u, dvars) for u in initial_nodes)]
Esempio n. 2
0
File: queens.py Progetto: johnyf/dd
def at_least_one_queen_per_row(n):
    """Return formula as `str`."""
    c = list()
    for i in range(n):
        xijs = [_var_str(i, j) for j in range(n)]
        s = disj(xijs)
        c.append(s)
    return conj(c)
Esempio n. 3
0
def at_least_one_queen_per_row(n):
    """Return formula as `str`."""
    c = list()
    for i in range(n):
        xijs = [_var_str(i, j) for j in range(n)]
        s = disj(xijs)
        c.append(s)
    return conj(c)
Esempio n. 4
0
def _init_from_ts(
        initial_nodes, nodevar,
        dvars, ignore_initial=False):
    """Return initial condition."""
    if ignore_initial:
        return list()
    if not initial_nodes:
        raise Exception('Transition system without initial states.')
    return [stx.disj(_assign(nodevar, u, dvars) for u in initial_nodes)]
Esempio n. 5
0
def dumps_cover(
        cover, f, care, fol,
        latex=False,
        show_dom=False,
        show_limits=False,
        comment=True):
    """Return disjunction of orthotopes in `cover`, one per line.

    @param latex: use `pf.sty` commands
    @param show_dom: if `care` implies type hints,
        then conjoin type hints (`fol.vars[var]['dom']`)
    @param show_limits: conjoin limits of  bitfield values
    @param comment: if `True`, then list support of `f`, `cover`

    @rtype: `str`
    """
    prm = lat.setup_aux_vars(f, care, fol)
    c = list()
    if show_limits:
        r = tyh._list_limits(prm.x_vars, fol.vars)
        c.extend(r)
    show_dom = show_dom and _care_implies_type_hints(f, care, fol)
    if show_dom:
        r = tyh._list_type_hints(prm.x_vars, fol.vars)
        c.extend(r)
    else:
        log.info(
            'type hints omitted')
    r = lat.list_expr(
        cover, prm, fol, use_dom=show_dom, latex=latex)
    s = stx.vertical_op(r, op='or', latex=latex, spacing=2)
    c.append(s)
    if care != fol.true:
        c.append('care expression')
    s = stx.vertical_op(c, op='and', latex=latex)
    f_vars = fol.support(f)
    care_vars = fol.support(care)
    s_comment = (
        '(* `f` depends on:  {f_vars} *)\n'
        '(* `care` depends on:  {care_vars} *)\n'
        '(* The minimal cover is: *)').format(
            f_vars=_comma_sorted(f_vars),
            care_vars=_comma_sorted(care_vars))
    if comment:
        s = '{comment}\n{s}'.format(comment=s_comment, s=s)
    # could add option to find minimal cover for care too
    # postcondition
    r = lat.list_expr(
        cover, prm, fol, use_dom=show_dom)
    r = stx.disj(r)
    g = fol.add_expr(r)
    # ensure that `g` equals `f` inside `care`
    # `g` can be arbitrary outside of `care`
    assert (g & care) == (f & care), r
    return s
Esempio n. 6
0
def mutex(v):
    """Return formula for at most one variable `True`.

    @param v: iterable of variables as `str`
    """
    v = set(v)
    c = list()
    for x in v:
        rest = disj(y for y in v if y != x)
        s = '{x} -> !({rest})'.format(x=x, rest=rest)
        c.append(s)
    return conj(c)
Esempio n. 7
0
def dumps_cover(
        cover, f, care, fol,
        latex=False,
        show_dom=False,
        show_limits=False):
    """Return disjunction of orthotopes in `cover`, one per line.

    @param latex: use `pf.sty` commands
    @param show_dom: if `care` implies type hints,
        then conjoin type hints (`fol.vars[var]['dom']`)
    @param show_limits: conjoin limits of  bitfield values

    @rtype: `str`
    """
    prm = lat.setup_aux_vars(f, care, fol)
    c = list()
    if show_limits:
        r = tyh._list_limits(prm.x_vars, fol.vars)
        c.extend(r)
    show_dom = show_dom and _care_implies_type_hints(f, care, fol)
    if show_dom:
        r = tyh._list_type_hints(prm.x_vars, fol.vars)
        c.extend(r)
    else:
        log.info(
            'type hints omitted (care does not imply them)')
    r = lat.list_expr(
        cover, prm, fol, use_dom=show_dom, latex=latex)
    s = stx.vertical_op(r, op='or', latex=latex)
    c.append(s)
    n_expr = len(r)
    if care != fol.true:
        c.append('care expression')
    s = stx.vertical_op(c, op='and', latex=latex)
    f_vars = fol.support(f)
    care_vars = fol.support(care)
    s = (
        '(* `f` depends on:  {f_vars} *)\n'
        '(* `care` depends on:  {care_vars} *)\n'
        '(* The minimal cover is: *)\n{s}').format(
            f_vars=_comma_sorted(f_vars),
            care_vars=_comma_sorted(care_vars),
            s=s)
    # could add option to find minimal cover for care too
    # postcondition
    r = lat.list_expr(
        cover, prm, fol, use_dom=show_dom)
    r = stx.disj(r)
    g = fol.add_expr(r)
    # ensure that `g` equals `f` inside `care`
    # `g` can be arbitrary outside of `care`
    assert (g & care) == (f & care), r
    return s
Esempio n. 8
0
File: queens.py Progetto: johnyf/dd
def mutex(v):
    """Return formula for at most one variable `True`.

    @param v: iterable of variables as `str`
    """
    v = set(v)
    c = list()
    for x in v:
        rest = disj(y for y in v if y != x)
        s = '{x} -> !({rest})'.format(x=x, rest=rest)
        c.append(s)
    return conj(c)
Esempio n. 9
0
def robots_example(fol):
    """Return cooperative winning set from ACC'16 example."""
    c = [
        '(x = 0) /\ (y = 4)', '(x = 0) /\ (y = 5)', '(x = 0) /\ (y = 2)',
        '(x = 0) /\ (y = 3)', '(x = 0) /\ (y = 6)', '(x = 0) /\ (y = 7)',
        '(x = 1) /\ (y = 0)', '(x = 1) /\ (y = 2)', '(x = 1) /\ (y = 4)',
        '(x = 1) /\ (y = 6)', '(x = 1) /\ (y = 5)', '(x = 1) /\ (y = 3)',
        '(x = 1) /\ (y = 7)', '(x = 2) /\ (y = 0)', '(x = 2) /\ (y = 1)',
        '(x = 2) /\ (y = 6)', '(x = 2) /\ (y = 7)', '(x = 3) /\ (y = 0)',
        '(x = 3) /\ (y = 2)', '(x = 3) /\ (y = 6)', '(x = 3) /\ (y = 1)',
        '(x = 3) /\ (y = 7)', '(x = 4) /\ (y = 0)', '(x = 4) /\ (y = 1)',
        '(x = 4) /\ (y = 2)', '(x = 4) /\ (y = 3)', '(x = 4) /\ (y = 6)',
        '(x = 4) /\ (y = 7)', '(x = 5) /\ (y = 0)', '(x = 5) /\ (y = 2)',
        '(x = 5) /\ (y = 4)', '(x = 5) /\ (y = 6)', '(x = 5) /\ (y = 1)',
        '(x = 5) /\ (y = 3)', '(x = 5) /\ (y = 7)'
    ]
    s = stx.disj(c)
    u = fol.add_expr(s)
    return u
Esempio n. 10
0
def test_orthotopes_using_robots_example():
    aut, prm = setup_aut(15, 15)
    p_vars = prm.p_vars
    # this predicate is constructed by `contract_maker`
    # for the robots example in ACC 2016
    f = robots_example(aut)
    prm.p_leq_q = lat.subseteq(prm._varmap, aut)
    prm.p_eq_q = lat.eq(prm._varmap, aut)
    u = lat.prime_implicants(f, prm, aut)
    support = aut.support(u)
    assert support == set(p_vars), (support, p_vars)
    n_primes = aut.count(u)
    k = aut.count(u)
    assert n_primes == k, (n_primes, k)
    log.info('{n} prime implicants'.format(n=n_primes))
    u = lat.essential_orthotopes(f, prm, aut)
    support = aut.support(u)
    assert support == set(p_vars), (support, p_vars)
    n_essential = aut.count(u)
    k = aut.count(u)
    assert n_essential == k, (n_essential, k)
    log.info('{n} essential prime implicants'.format(n=n_essential))
    assert n_essential == 7, n_essential
    # result: all primes are essential in this example
    #
    care = aut.true
    s = cov.dumps_cover(u, f, care, aut)
    log.info(s)
    log.info('BDD has {n} nodes'.format(n=len(aut.bdd)))
    # confirm that essential orthotopes cover exactly `f`
    c = lat.list_expr(u, prm, aut, simple=True)
    s = stx.disj(c)
    log.info(s)
    z = aut.add_expr(s)
    z = aut.exist(['a_x', 'b_x', 'a_y', 'b_y'], z)
    assert aut.support(z) == aut.support(f)
    assert z == f
    if plt is not None:
        _plot_orthotopes_for_robots_example(u, f, prm._px, xvars, aut)
    # pprint.pprint(aut.bdd.statistics())
    # pprint.pprint(aut.bdd.vars)
    log.info('{n} nodes in manager'.format(n=len(aut.bdd)))
Esempio n. 11
0
def implicants_intersect(prm, fol):
    """Return `ab \cap uv # \emptyset`.

    Equivalent to

    \E x:  /\ x \in concretization(ab)
           /\ x \in concretization(uv)

    The representation of orthotopes as products of
    intervals allows for a direct construction that
    avoids quantification over `x`.
    """
    # disjoint intervals in at least one dimension
    s = stx.disj('''
           ({b} < {u})
        \/ ({v} < {a})
        '''.format(a=a, b=b, u=u, v=v)
                 for (a, b), (u, v) in prm._varmap.items())
    r = fol.add_expr(s)
    return ~r
Esempio n. 12
0
def implicants_intersect(prm, fol):
    """Return `ab \cap uv # \emptyset`.

    Equivalent to

    \E x:  /\ x \in concretization(ab)
           /\ x \in concretization(uv)

    The representation of orthotopes as products of
    intervals allows for a direct construction that
    avoids quantification over `x`.
    """
    # disjoint intervals in at least one dimension
    s = stx.disj('''
           ({b} < {u})
        \/ ({v} < {a})
        '''.format(a=a, b=b, u=u, v=v)
            for (a, b), (u, v) in prm._varmap.items())
    r = fol.add_expr(s)
    return ~ r
Esempio n. 13
0
def robots_example(fol):
    """Return cooperative winning set from ACC'16 example."""
    c = [
        '(x = 0) /\ (y = 4)',
        '(x = 0) /\ (y = 5)',
        '(x = 0) /\ (y = 2)',
        '(x = 0) /\ (y = 3)',
        '(x = 0) /\ (y = 6)',
        '(x = 0) /\ (y = 7)',
        '(x = 1) /\ (y = 0)',
        '(x = 1) /\ (y = 2)',
        '(x = 1) /\ (y = 4)',
        '(x = 1) /\ (y = 6)',
        '(x = 1) /\ (y = 5)',
        '(x = 1) /\ (y = 3)',
        '(x = 1) /\ (y = 7)',
        '(x = 2) /\ (y = 0)',
        '(x = 2) /\ (y = 1)',
        '(x = 2) /\ (y = 6)',
        '(x = 2) /\ (y = 7)',
        '(x = 3) /\ (y = 0)',
        '(x = 3) /\ (y = 2)',
        '(x = 3) /\ (y = 6)',
        '(x = 3) /\ (y = 1)',
        '(x = 3) /\ (y = 7)',
        '(x = 4) /\ (y = 0)',
        '(x = 4) /\ (y = 1)',
        '(x = 4) /\ (y = 2)',
        '(x = 4) /\ (y = 3)',
        '(x = 4) /\ (y = 6)',
        '(x = 4) /\ (y = 7)',
        '(x = 5) /\ (y = 0)',
        '(x = 5) /\ (y = 2)',
        '(x = 5) /\ (y = 4)',
        '(x = 5) /\ (y = 6)',
        '(x = 5) /\ (y = 1)',
        '(x = 5) /\ (y = 3)',
        '(x = 5) /\ (y = 7)']
    s = stx.disj(c)
    u = fol.add_expr(s)
    return u
Esempio n. 14
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
Esempio n. 15
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
Esempio n. 16
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
Esempio n. 17
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
Esempio n. 18
0
def _env_trans_from_sys_ts(g, nodevar, dvars):
    """Return safety assumption to prevent env from blocking sys."""
    denv = {k: v for k, v in dvars.items() if k in g.env_vars}
    env_trans = list()
    for u in g:
        # no successor states ?
        if not g.succ.get(u):
            continue
        # collect possible next env actions
        c = set()
        for u, w, d in g.edges(u, data=True):
            t = _to_action(d, denv)
            if not t:
                continue
            c.add(t)
        # no next env actions ?
        if not c:
            continue
        post = stx.disj(c)
        pre = _assign(nodevar, u, dvars)
        env_trans.append('(({pre}) => ({post}))'.format(pre=pre, post=post))
    s = stx.conj(env_trans, sep='\n')
    return s
Esempio n. 19
0
def _env_trans_from_sys_ts(g, nodevar, dvars):
    """Return safety assumption to prevent env from blocking sys."""
    denv = {k: v for k, v in dvars.items() if k in g.env_vars}
    env_trans = list()
    for u in g:
        # no successor states ?
        if not g.succ.get(u):
            continue
        # collect possible next env actions
        c = set()
        for u, w, d in g.edges(u, data=True):
            t = _to_action(d, denv)
            if not t:
                continue
            c.add(t)
        # no next env actions ?
        if not c:
            continue
        post = stx.disj(c)
        pre = _assign(nodevar, u, dvars)
        env_trans.append('(({pre}) => ({post}))'.format(
            pre=pre, post=post))
    s = stx.conj(env_trans, sep='\n')
    return s