示例#1
0
def faithfulness_with_counterexample(primes: dict, update: str,
                                     trap_space: dict) -> (bool, List[dict]):
    """
    Performs the same steps as :ref:`faithfulness` but also returns a counterexample which is *None* if it does not exist.
    A counterexample of a faithful test is a state that belongs to an attractor which has more fixed variables than there are in *trap_space*.

    **arguments**:
        * *primes*: prime implicants
        * *update*: the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
        * *trap_space*: a subspace

    **returns**:
        * *answer*: whether *trap_space* is faithful in the STG defined by *primes* and *update*
        * *counter_example*: a state that belongs to an attractor that does not oscillate in all free variables or *None* if no counterexample exists

    **example**::

        >>> mintspaces = compute_trap_spaces(primes, "min")
        >>> x = mintspaces[0]
        >>> faithfulness(primes, x)
        True
    """

    if len(trap_space) == len(primes):
        return True, None

    primes = percolate(primes=primes, add_constants=trap_space, copy=True)
    constants = find_constants(primes=primes)
    remove_all_constants(primes=primes)

    if len(constants) > len(trap_space):
        counterexample = find_attractor_state_by_randomwalk_and_ctl(
            primes=primes, update=update)
        attractor_state = merge_dicts(dicts=[counterexample, constants])

        return False, attractor_state

    spec = f"CTLSPEC AG({exists_finally_unsteady_components(names=list(primes))})"
    answer, counterexample = model_checking(primes=primes,
                                            update=update,
                                            initial_states="INIT TRUE",
                                            specification=spec,
                                            enable_counterexample=True)

    if answer:
        return True, None

    else:
        attractor_state = find_attractor_state_by_randomwalk_and_ctl(
            primes=primes, update=update, initial_state=counterexample[-1])
        attractor_state = merge_dicts(dicts=[attractor_state, constants])

        return False, attractor_state
示例#2
0
def univocality_with_counterexample(
        primes: dict, update: str,
        trap_space: Union[dict, str]) -> (bool, List[dict]):
    """
    Performs the same steps as :ref:`univocality` but also returns a counterexample which is *None* if it does not exist.
    A counterexample of a univocality test are two states that belong to different attractors.

    **arguments**:
        * *primes*: prime implicants
        * *update*: the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
        * *trap_space*: a subspace

    **returns**:
        * *answer*: whether *trap_space* is univocal in the STG defined by *primes* and *update*
        * *counter_example*: two states that belong to different attractors or *None* if no counterexample exists

    **example**::

        >>> mintspaces = compute_trap_spaces(primes, "min")
        >>> trapspace = mintrapspaces[0]
        >>> answer, counterex = univocality_with_counterexample(primes, trapspace, "asynchronous")
    """

    primes = percolate(primes=primes, add_constants=trap_space, copy=True)
    constants = find_constants(primes=primes)
    remove_all_constants(primes=primes)

    if primes == {}:
        return True, None

    attractor_state = find_attractor_state_by_randomwalk_and_ctl(primes=primes,
                                                                 update=update)
    spec = f"CTLSPEC {exists_finally_one_of_subspaces(primes=primes, subspaces=[attractor_state])}"
    init = "INIT TRUE"
    answer, counterexample = model_checking(primes=primes,
                                            update=update,
                                            initial_states=init,
                                            specification=spec,
                                            enable_counterexample=True)

    if answer:
        return True, None

    else:
        attractor_state2 = find_attractor_state_by_randomwalk_and_ctl(
            primes=primes, update=update, initial_state=counterexample[-1])
        attractor_state2 = merge_dicts(dicts=[attractor_state2, constants])
        attractor_state = merge_dicts(dicts=[attractor_state, constants])
        counterexample = attractor_state, attractor_state2

        return False, counterexample
示例#3
0
def intersection(*list_of_dicts):
    """
    each argument must be a list of subspaces (dicts)::

        >>> intersection([{"v1":1}], [{"v1":0}, {"v2":1, "v3":0}])
    """

    return [merge_dicts(dicts=x) for x in product(*list_of_dicts)]
def _cartesian_product_of_diagrams(diagrams, factor, edge_data):
    result = networkx.DiGraph()
    nodes = [x.nodes(data=True) for x in diagrams]

    for product in itertools.product(*nodes):
        data = {
            "size":
            functools.reduce(operator.mul, [x["size"]
                                            for _, x in product]) * factor,
            "formula":
            " & ".join(f"({x['formula']})" for _, x in product)
        }

        attractors = [x["attractors"] for _, x in product]
        attractors = list(itertools.product(*attractors))
        attractors = [merge_dicts(x) for x in attractors]
        data["attractors"] = attractors

        node = tuple(x for x, _ in product)

        result.add_node(node)
        for key, value in data.items():
            result.nodes[node][key] = value

    for source in result.nodes():
        for s, diagram in zip(source, diagrams):
            factor = result.nodes[source]["size"] / diagram.nodes[s]["size"]
            for _, t, data in diagram.out_edges(s, data=True):

                data = {}
                basic_formula = [
                    "(%s)" % g.nodes[x]["formula"]
                    for x, g in zip(source, diagrams) if not g == diagram
                ]
                data["EX_size"] = factor * diagram.adj[s][t]["EX_size"]
                formula = basic_formula + [
                    f"({diagram.adj[s][t]['EX_formula']})"
                ]
                data["EX_formula"] = " & ".join(formula)

                if edge_data:
                    data["EF_size"] = factor * diagram.adj[s][t]["EF_size"]
                    formula = basic_formula + [
                        f"({diagram.adj[s][t]['EF_formula']})"
                    ]
                    data["EF_formula"] = " & ".join(formula)

                target = tuple(x if g != diagram else t
                               for x, g in zip(source, diagrams))

                result.add_edge(source, target)
                for key, value in data.items():
                    result.edges[source, target][key] = value

    result = networkx.convert_node_labels_to_integers(result)

    return result
示例#5
0
def iterative_completeness_algorithm(
        primes: dict,
        update: str,
        compute_counterexample: bool,
        max_output: int = 1000) -> Union[Tuple[bool, Optional[dict]], bool]:
    """
    The iterative algorithm for deciding whether the minimal trap spaces are complete.
    The function is implemented by line-by-line following of the pseudo code algorithm given in
    "Approximating attractors of Boolean networks by iterative CTL model checking", Klarner and Siebert 2015.

    **arguments**:
        * *primes*: prime implicants
        * *update*: the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
        * *compute_counterexample*: whether to compute a counterexample

    **returns**:
        * *answer*: whether *subspaces* is complete in the STG defined by *primes* and *update*,
        * *counterexample*: a state that can not reach one of the minimal trap spaces of *primes* or *None* if no counterexample exists

    **example**::

        >>> answer, counterexample = completeness_with_counterexample(primes, "asynchronous")
        >>> answer
        False
        >>> state2str(counterexample)
        10010111101010100001100001011011111111
    """

    primes = percolate(primes=primes, copy=True)
    constants_global = find_constants(primes=primes)
    remove_all_constants(primes=primes)

    min_trap_spaces = compute_trap_spaces(primes=primes,
                                          type_="min",
                                          max_output=max_output)
    if min_trap_spaces == [{}]:
        if compute_counterexample:
            return True, None
        else:
            return True

    current_set = [({}, set([]))]
    while current_set:
        p, w = current_set.pop()
        primes_reduced = copy_primes(primes=primes)
        create_constants(primes=primes_reduced, constants=p)
        igraph = primes2igraph(primes=primes_reduced)

        cgraph = digraph2condensationgraph(digraph=igraph)
        cgraph_dash = cgraph.copy()

        for U in cgraph.nodes():
            if set(U).issubset(set(w)):
                cgraph_dash.remove_node(U)

        w_dash = w.copy()
        refinement = []
        top_layer = [
            U for U in cgraph_dash.nodes() if cgraph_dash.in_degree(U) == 0
        ]

        for U in top_layer:
            u_dash = find_ancestors(igraph, U)

            primes_restricted = copy_primes(primes_reduced)
            remove_all_variables_except(primes=primes_restricted, names=u_dash)

            q = compute_trap_spaces(primes=primes_restricted,
                                    type_="min",
                                    max_output=max_output)

            phi = exists_finally_one_of_subspaces(primes=primes_restricted,
                                                  subspaces=q)

            init = "INIT TRUE"
            spec = f"CTLSPEC {phi}"

            if compute_counterexample:
                answer, counterexample = model_checking(
                    primes=primes_restricted,
                    update=update,
                    initial_states=init,
                    specification=spec,
                    enable_counterexample=True)
                if not answer:
                    downstream = [x for x in igraph if x not in U]
                    arbitrary_state = random_state(downstream)
                    top_layer_state = counterexample[-1]
                    counterexample = merge_dicts([
                        constants_global, p, top_layer_state, arbitrary_state
                    ])

                    return False, counterexample
            else:
                answer = model_checking(primes=primes_restricted,
                                        update=update,
                                        initial_states=init,
                                        specification=spec)
                if not answer:
                    return False

            refinement += intersection([p], q)
            w_dash.update(u_dash)

        for q in intersection(refinement):
            q_tilde = find_constants(
                primes=percolate(primes=primes, add_constants=q, copy=True))

            if q_tilde not in min_trap_spaces:
                current_set.append((q_tilde, w_dash))

    if compute_counterexample:
        return True, None
    else:
        return True