Ejemplo n.º 1
0
def select_states(primes, 
    num_state_samples=10000, 
    seed=0):

    n = len(primes)

    if 2**n <= num_state_samples:
        print ("using entire state space")
        states = set(itertools.product([0, 1], repeat=n))

    else:
        print ("sampling", 
                num_state_samples, 
                "states")
        states = set()
        np.random.seed(seed)

        while len(states) < num_state_samples:
            state = {n: (0 if n in ["Adenosine", "Dopamine", "Enkephalin",
                    "GABA", "Glutamate", "Serotonin", "Ach"]
                    else np.random.choice([0, 1]))
                    for n in primes}
            state = STGs.state2str(state)
            states.add(state)

    states = list(states)

    return states
Ejemplo n.º 2
0
def faithfulness_with_counterexample(Primes, Update, Trapspace):
	"""
	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 *Trapspace*.

	**arguments**:
		* *Primes*: prime implicants
		* *Update* (str): the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
		* *Trapspace* (str / dict): a subspace

	**returns**:
		* *Answer* (bool): whether *Trapspace* is faithful in the STG defined by *Primes* and *Update*
		* *CounterExample* (dict): a state that belongs to an attractor that does not oscillate in all free variables or *None* if no counterexample exists

	**example**::

		>>> mintspaces = PyBoolNet.AspSolver.trap_spaces(primes, "min")
		>>> x = mintspaces[0]
		>>> faithfulness(primes, x)
		True
	"""

	if type(Trapspace)==str:
		Trapspace=StateTransitionGraphs.str2subspace(Primes, Trapspace)

	# trivial case: steady state
	if len(Trapspace)==len(Primes):
		return True, None

	# percolation
	primes = PyBoolNet.PrimeImplicants.copy(Primes)
	PyBoolNet.PrimeImplicants.create_constants(primes, Constants=Trapspace)
	constants  = PyBoolNet.PrimeImplicants.percolate_and_remove_constants(primes)

	# trivial case: free variables fix due to percolation
	if len(constants)>len(Trapspace):
		counterex = find_attractor_state_by_randomwalk_and_ctl(primes, Update)
		attractor_state = PyBoolNet.Utility.Misc.merge_dicts([counterex, constants])

		return False, attractor_state

	# faithfulness
	spec = 'CTLSPEC AG(%s)'%PyBoolNet.TemporalLogic.EF_unsteady_states(primes)
	init = 'INIT TRUE'
	answer, counterex = PyBoolNet.ModelChecking.check_primes_with_counterexample(primes, Update, init, spec)

	# success
	if answer:
		return True, None

	# failure
	else:
		attractor_state = find_attractor_state_by_randomwalk_and_ctl(primes, Update, counterex[-1])
		attractor_state = PyBoolNet.Utility.Misc.merge_dicts([attractor_state, constants])

		return False, attractor_state
Ejemplo n.º 3
0
def build_STG_and_determine_attractors(
	primes, 
	states, 
	return_stg=False):
	print ("building partial STG to determine attractors for given initial conditions")

	# assume synchronous update scheme

	assert isinstance(states[0], str)

	stg = nx.DiGraph()

	attractors = []

	for i, state in enumerate(states):

		next_state = STGs.state2str(STGs.successor_synchronous(primes, state))

		while next_state not in stg:

			stg.add_edge(state, next_state)
			state = next_state
			next_state = STGs.state2str(STGs.successor_synchronous(primes, state))

		assert next_state in stg
		stg.add_edge(state, next_state) # connect new part of STG to existsing STG
				
		#cyclic attractor? use exising STG to determine attractor

		visited = [state]
		while next_state not in visited:
			visited.append(next_state)
			assert len(list(stg.neighbors(next_state))) == 1
			next_state = list(stg.neighbors(next_state))[0]

		idx = visited.index(next_state)
		attractor = visited[idx:]
		attractors.append(attractor)

	if return_stg:
		return stg, attractors
	else:
		return attractors
Ejemplo n.º 4
0
def univocality_with_counterexample(Primes, Update, Trapspace):
	"""
	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* (str): the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
		* *Trapspace* (str / dict): a subspace

	**returns**:
		* *Answer* (bool): whether *Trapspace* is univocal in the STG defined by *Primes* and *Update*
		* *CounterExample* (dict): two states that belong to different attractors or *None* if no counterexample exists

	**example**::

		>>> mintspaces = PyBoolNet.AspSolver.trap_spaces(primes, "min")
		>>> trapspace = mintrapspaces[0]
		>>> answer, counterex = univocality_with_counterexample(primes, trapspace, "asynchronous")
	"""

	if type(Trapspace)==str:
		Trapspace=StateTransitionGraphs.str2subspace(Primes, Trapspace)

	# percolation
	primes = PyBoolNet.PrimeImplicants.copy(Primes)
	PyBoolNet.PrimeImplicants.create_constants(primes, Constants=Trapspace)
	constants  = PyBoolNet.PrimeImplicants.percolate_and_remove_constants(primes)

	# trivial case: constants = unique steady state
	if primes == {}:
		return True, None

	# find attractor state
	attractor_state1 = find_attractor_state_by_randomwalk_and_ctl(primes, Update)

	# univocality
	spec = 'CTLSPEC ' + PyBoolNet.TemporalLogic.EF_oneof_subspaces(primes, [attractor_state1])
	init = 'INIT TRUE'
	answer, counterex = PyBoolNet.ModelChecking.check_primes_with_counterexample(primes, Update, init, spec)

	# success
	if answer:
		return True, None

	# failure
	else:
		attractor_state2 = find_attractor_state_by_randomwalk_and_ctl(primes, Update, counterex[-1])

		# need to add constants to get original states
		attractor_state2 = PyBoolNet.Utility.Misc.merge_dicts([attractor_state2,constants])
		attractor_state1 = PyBoolNet.Utility.Misc.merge_dicts([attractor_state1,constants])
		counterex = attractor_state1, attractor_state2

		return False, counterex
Ejemplo n.º 5
0
def compute_average_activation(primes, genes, attractors):

	counts = {gene: [] for gene in genes}

	for attractor in attractors:

		attractor_counts = {gene: 0 for gene in genes}
		attractor_period = len(attractor)

		for state in attractor:

			state_dict = STGs.state2dict(primes, state)

			for gene in genes:
				attractor_counts[gene] += state_dict[gene]

		for gene in genes:
			counts[gene].append(attractor_counts[gene] / \
				attractor_period)

	return counts
Ejemplo n.º 6
0
def select_states(primes, num_state_samples=10000, seed=0):

	n = len(primes)

	if 2**n <= num_state_samples:
		print ("using entire state space")
		states = set(itertools.product([0, 1], repeat=n))

	else:
		print ("sampling", 
				num_state_samples, 
				"states")
		states = set()
		np.random.seed(seed)

		while len(states) < num_state_samples:
			state = tuple(np.random.randint(2, size=n))
			states.add(state)

	states = list(map(lambda state: 
		STGs.state2str({p: s 
		for p, s in zip(primes, state)}), states))

	return states
Ejemplo n.º 7
0
def run():

    RUN_ALL = 1

    if 0 or RUN_ALL:
        print("modifications of networks")

        bnet = """
        v1, 0
        v2, 1
        v3, v1&v2&v3&v4
        v4, v3 & (v1|v2)
        """
        primes = FEX.bnet2primes(bnet)

        constants = PIs.find_constants(primes)
        PIs.create_blinkers(primes, constants)

        print(FEX.primes2bnet(primes))

    if 0 or RUN_ALL:
        print("creates basin diagrams")
        primes = repo.get_primes("xiao_wnt5a")
        diagram = AB.commitment_diagram(primes, "asynchronous")
        print(diagram.order())
        print(diagram.nodes())
        print(diagram.node["4"]["formula"])
        print(diagram.node["4"]["size"])

        primes = repo.get_primes("arellano_rootstem")
        diagram = AB.commitment_diagram(primes, "asynchronous")
        AB.diagram2image(primes, diagram, "source/figure26.pdf")

        AB.diagram2aggregate_image(primes, diagram, "source/figure27.pdf")

    if 0 or RUN_ALL:
        print("creates interaction graphs for all repository networks:")
        s = []
        for x in repo.get_all_names():
            print(x)
            primes = repo.get_primes(x)
            igraph = IGs.create_image(primes, "source/%s_igraph.pdf" % x)

            s += [x]
            s += ["-" * len(x)]
            s += [".. figure:: %s_igraph.pdf" % x]
            s += ["   :scale: 60%"]
            s += ["   :align: center"]
            s += [""]
            s += ["   Interaction graph of %s." % x]
            s += [""]
            s += [""]

        print("\n".join(s))

    if 0 or RUN_ALL:
        print("model checking with accepting states")

        bnet = [
            "x0,   !x0&x1 | x2", "x1,   !x0 | x1 | x2", "x2,   x0&!x1 | x2"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        update = "asynchronous"
        init = "INIT !x1"
        spec = "CTLSPEC EF(AG(x0_STEADY))"

        answer, accepting = MC.check_primes_with_acceptingstates(
            primes, update, init, spec)
        for x in accepting.items():
            print(x)

        prop = accepting["INITACCEPTING"]
        init = "INIT %s" % prop
        spec = "CTLSPEC EF(STEADYSTATE)"
        print(MC.check_primes(primes, update, init, spec))

        for x in STGs.list_states_referenced_by_proposition(primes, prop):
            print(x)

    if 0 or RUN_ALL:
        print("primes from Python functions")

        f1 = lambda v2, v3, v4, v5: sum([v2, v3, v4, v5]) >= 2

        def f2(v1, v2, v3):
            if f1(v2, v3, 0, 0):
                return 0
            else:
                return sum([v1, v2, v3]) % 2

        f3 = lambda v4, v5: not (v4 or not f2(v4, v4, v5))
        f4 = lambda: 1
        f5 = lambda v5: v5

        funcs = {"v1": f1, "v2": f2, "v3": f3, "v4": f4, "v5": f5}
        primes = QMC.functions2primes(funcs)

        dnf = QMC.functions2mindnf(funcs)
        print(dnf["v1"])

    if 0 or RUN_ALL:
        print("figure01.pdf - basic interaction graph")

        bnet = "\n".join(["v1, v1|v3", "v2, 1", "v3, v1&!v2 | !v1&v2"])
        primes = FEX.bnet2primes(bnet)
        igraph = IGs.primes2igraph(primes)
        print(igraph.nodes())
        print(igraph.edges())
        print(igraph.edge["v3"]["v1"]["sign"])
        print(igraph.edge["v1"]["v3"]["sign"])

        IGs.igraph2image(igraph, "source/figure01.pdf")

    if 0 or RUN_ALL:
        print("graph, node and edge attributes")

        bnet = "\n".join(["v1, v2 & (!v1 | v3)", "v2, !v3", "v3, v2 | v1"])
        primes = FEX.bnet2primes(bnet)
        igraph = IGs.primes2igraph(primes)
        igraph.graph["node"]["shape"] = "circle"
        igraph.graph["node"]["color"] = "blue"
        igraph.node["v2"]["shape"] = "rpromoter"
        igraph.node["v2"]["color"] = "black"
        igraph.edge["v3"]["v1"]["arrowhead"] = "inv"
        igraph.edge["v3"]["v1"]["color"] = "red"
        igraph.graph["splines"] = "ortho"
        igraph.graph["label"] = "Example 3: Interaction graph with attributes"
        igraph.graph["rankdir"] = "LR"
        IGs.igraph2image(igraph, "source/figure02.pdf")

    if 0 or RUN_ALL:
        print("the interaction signs style")

        funcs = {
            "v1": lambda v1, v2, v3: v1 + v2 + v3 == 1,
            "v2": lambda v1: not v1,
            "v3": lambda v2: v2
        }
        primes = QMC.functions2primes(funcs)
        igraph = IGs.primes2igraph(primes)
        IGs.add_style_interactionsigns(igraph)
        igraph.graph["label"] = "Example 4: Signed interaction graph"
        igraph.graph["rankdir"] = "LR"
        IGs.igraph2image(igraph, "source/figure03.pdf")

    if 0 or RUN_ALL:
        print("styles for inputs, outputs and constants")

        bnet = [
            "v1, v1", "v2, v2", "v3, 1", "v4, v1 | v3", "v5, v4 & v2 | v6",
            "v6, 0", "v7, !v5", "v8, v7", "v9, v5 & v7"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        igraph = IGs.primes2igraph(primes)
        IGs.add_style_inputs(igraph)
        IGs.add_style_constants(igraph)
        IGs.add_style_outputs(igraph)
        igraph.graph[
            "label"] = "Example 5: Interaction graph with styles for inputs, outputs and constants"
        IGs.igraph2image(igraph, "source/figure04.pdf")

    if 0 or RUN_ALL:
        print("the SCC style")

        bnet = [
            "v1, v1", "v2, v3 & v5", "v3, v1", "v4, v1", "v5, 1", "v6, v7",
            "v7, v6 | v4", "v8, v6", "v9, v8", "v10, v7 & v11",
            "v11, v10 | v4", "v12, v10"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        igraph = IGs.primes2igraph(primes)
        IGs.add_style_sccs(igraph)
        igraph.graph["label"] = "Example 6: Interaction graph with SCC style"
        IGs.igraph2image(igraph, "source/figure05.pdf")

        igraph.graph["label"] = "Example 7: Interaction graph with SCC style"
        IGs.igraph2image(igraph, "source/figure06.pdf")

    if 0 or RUN_ALL:
        print("the subgraph style")

        bnet = [
            "v1, v7", "v2, v1 & v6", "v3, v2 | v7", "v4, v3", "v5, v1 | v4",
            "v6, v5", "v7, v6"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        igraph = IGs.primes2igraph(primes)
        subgraphs = [(["v2", "v6"], {}),
                     (["v1", "v4"], {
                         "label": "Genes",
                         "fillcolor": "lightblue"
                     })]
        IGs.add_style_subgraphs(igraph, subgraphs)
        igraph.graph[
            "label"] = "Example 8: Interaction graph with a subgraph style"
        IGs.igraph2image(igraph, "source/figure07.pdf")

    if 0 or RUN_ALL:
        print("the activities style and animations")

        bnet = [
            "v1, v7", "v2, v1 & v6", "v3, v2 | v7", "v4, v3", "v5, v1 | v4",
            "v6, v5", "v7, v6"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        igraph = IGs.primes2igraph(primes)
        activities = {"v2": 1, "v3": 0, "v4": 0}
        IGs.add_style_activities(igraph, activities)
        igraph.graph[
            "label"] = "Example 9: Interaction graph with a activities style"
        igraph.graph["rankdir"] = "LR"

        IGs.igraph2image(igraph, "source/figure08.pdf")

    if 0 or RUN_ALL:
        print("the default style")

        bnet = [
            "v1, v1", "v2, v3 & !v5", "v3, !v1", "v4, v1", "v5, 1", "v6, v7",
            "v7, v6 & !v4 | !v6 & v4", "v8, !v6", "v9, v8", "v10, v7 & !v11",
            "v11, v10 | v4", "v12, v10"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        igraph = IGs.primes2igraph(primes)
        IGs.add_style_default(igraph)
        IGs.igraph2image(igraph, "PyBoolNet-screenshot.jpg")
        igraph.graph[
            "label"] = "Example 10: Interaction graph with default style"
        IGs.igraph2image(igraph, "source/figure09.pdf")

    if 0 or RUN_ALL:
        print("Drawing the State Transition Graph - Asynchronous")

        bnet = "\n".join(["v1, v3", "v2, v1", "v3, v2"])
        primes = FEX.bnet2primes(bnet)
        update = "asynchronous"
        stg = STGs.primes2stg(primes, "asynchronous")
        print(repr(stg))
        print(stg.nodes()[0])
        print(networkx.has_path(stg, "100", "111"))
        stg.graph["label"] = "Example 11: The STG of a positive circuit"
        stg.graph["rankdir"] = "LR"
        STGs.stg2image(stg, "source/figure10.pdf")

        init = ["000", "111"]
        stg = STGs.primes2stg(primes, update, init)
        init = ["000", {"v1": 1, "v2": 1, "v3": 1}]
        stg = STGs.primes2stg(primes, update, init)
        init = lambda x: x["v1"] >= x["v2"]
        stg = STGs.primes2stg(primes, update, init)
        init = "--1"
        stg = STGs.primes2stg(primes, update, init)
        init = {"v3": 1}
        stg = STGs.primes2stg(primes, update, init)

    if 0 or RUN_ALL:
        print("Drawing the State Transition Graph - Synchronous")

        bnet = "\n".join(["v1, !v3", "v2, v1", "v3, v2"])
        primes = FEX.bnet2primes(bnet)
        stg = STGs.primes2stg(primes, "synchronous")
        stg.graph[
            "label"] = "Example 12: The synchronous STG of a negative circuit"
        stg.graph["rankdir"] = "LR"
        STGs.add_style_tendencies(stg)
        STGs.stg2image(stg, "source/figure11.pdf")

    if 0 or RUN_ALL:
        print("path style")

        bnet = "\n".join(["x, !x|y", "y, !x&!z|x&!y&z", "z, x|!y"])
        primes = FEX.bnet2primes(bnet)
        stg = STGs.primes2stg(primes, "asynchronous")
        stg.graph["label"] = "Example 13: STG with path style"

        path = ["011", "010", "110", "100", "000"]
        STGs.add_style_path(stg, path, "red")
        STGs.stg2image(stg, "source/figure12.pdf")

    if 0 or RUN_ALL:
        print("scc style for STGs")

        bnet = "\n".join(["x, !x|y", "y, x&!y|!z", "z, x&z|!y"])
        primes = FEX.bnet2primes(bnet)
        stg = STGs.primes2stg(primes, "asynchronous")
        stg.graph["label"] = "Example 14: STG with SCC style"
        STGs.add_style_sccs(stg)
        STGs.stg2image(stg, "source/figure13.pdf")

    if 0 or RUN_ALL:
        print("min trap spaces style")

        bnet = "\n".join(["x, !x|y&z", "y, x&!y|!z", "z, z|!y"])
        primes = FEX.bnet2primes(bnet)
        stg = STGs.primes2stg(primes, "asynchronous")
        stg.graph["label"] = "Example 15: STG with min trap spaces style"
        STGs.add_style_mintrapspaces(primes, stg)
        STGs.stg2image(stg, "source/figure14.pdf")

    if 0 or RUN_ALL:
        print("STG subspaces style")

        bnet = "\n".join(["x, !x|y&z", "y, x&!y|!z", "z, z|!y"])
        primes = FEX.bnet2primes(bnet)
        stg = STGs.primes2stg(primes, "asynchronous")
        stg.graph["label"] = "Example 16: STG with subspaces style"
        sub1 = ({"x": 0}, {"label": "x is zero"})
        sub2 = {"x": 1, "y": 0}
        subspaces = [sub1, sub2]
        STGs.add_style_subspaces(primes, stg, subspaces)

        STGs.stg2image(stg, "source/figure15.pdf")

    if 0 or RUN_ALL:
        print("STG default style")

        bnet = "\n".join(["x, !x|y&z", "y, x&!y|!z", "z, z|!y"])
        primes = FEX.bnet2primes(bnet)
        stg = STGs.primes2stg(primes, "asynchronous")
        stg.graph["label"] = "Example 17: STG with default style"
        STGs.add_style_default(primes, stg)

        STGs.stg2image(stg, "source/figure16.pdf")

    if 0 or RUN_ALL:
        print("model checking 1")

        bnet = [
            "Erk,  Erk & Mek | Mek & Raf", "Mek,  Erk | Mek & Raf",
            "Raf,  !Erk | !Raf"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        stg = STGs.primes2stg(primes, "asynchronous")
        stg.graph["label"] = "Example 18: STG of the Erk-Mek-Raf network"

        STGs.stg2image(stg, "source/figure17a.pdf")

        ## description not in the manual
        ts_basic = STGs.copy(stg)
        ts_basic.graph[
            "label"] = "Example 19: Basic transition system of Erk-Mek-Raf"
        ts_auxillary = STGs.copy(stg)
        ts_auxillary.graph[
            "label"] = "Example 20: Transition system of Erk-Mek-Raf with auxillary variables"
        for x in stg.nodes():
            x_dict = STGs.state2dict(primes, x)
            ap_basic = [name for name in sorted(x_dict) if x_dict[name]]
            ap_auxillary = list(ap_basic)
            outdegree = len(list(y for y in stg.successors(x) if y != x))

            suc = STGs.successor_synchronous(primes, x_dict)
            ap_auxillary += [
                name + "_STEADY" for name in sorted(x_dict)
                if suc[name] == x_dict[name]
            ]
            if not outdegree:
                ap_auxillary += ["STEADYSTATE"]
            ap_auxillary += ["SUCCESSORS=%i" % outdegree]

            ap_basic = pairs(ap_basic)
            ts_basic.node[x]["label"] = "{" + "\\n".join(ap_basic) + "}"

            ap_auxillary = pairs(ap_auxillary)
            ts_auxillary.node[x]["label"] = "{" + "\\n".join(
                ap_auxillary) + "}"

        STGs.stg2image(ts_basic, "source/figure17b.pdf")

        print("calling pdflatex, hope its installed")
        proc = subprocess.Popen(["pdflatex", "merge_figure17.tex"],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        out, err = proc.communicate()

        print("calling pdfcrop, hope its installed")
        proc = subprocess.Popen(["pdfcrop", "merge_figure17.pdf"],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        out, err = proc.communicate()
        shutil.copyfile("merge_figure17-crop.pdf", "source/figure17.pdf")

        STGs.stg2image(ts_auxillary, "source/figure18.pdf")

    if 0 or RUN_ALL:
        print("LTL queries")

        bnet = [
            "Erk,  Erk & Mek | Mek & Raf", "Mek,  Erk | Mek & Raf",
            "Raf,  !Erk | !Raf"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        init = "INIT TRUE"
        spec = "LTLSPEC F(Raf)"
        update = "asynchronous"
        print(MC.check_primes(primes, update, init, spec))

        init = "INIT Erk & SUCCESSORS<2"
        spec = "LTLSPEC G(F(Raf) & F(!Raf))"
        answer = MC.check_primes(primes, "asynchronous", init, spec)
        print(init, spec, "is", answer)

        init = "INIT Mek"
        spec = "LTLSPEC G(count(Erk_STEADY,Mek_STEADY,Raf_STEADY)>=2)"
        answer = MC.check_primes(primes, "asynchronous", init, spec)
        print(init, spec, "is", answer)

        print("#### Counterexamples ####")
        init = "INIT TRUE"
        spec = "LTLSPEC F(Raf & F(STEADYSTATE))"
        update = "asynchronous"
        answer, counterex = MC.check_primes_with_counterexample(
            primes, update, init, spec)
        print(answer)
        if counterex:
            print(" -> ".join(STGs.state2str(x) for x in counterex))

    if 0 or RUN_ALL:
        print("counterexample path style")

        bnet = [
            "Erk,  Erk & Mek | Mek & Raf", "Mek,  Erk | Mek & Raf",
            "Raf,  !Erk | !Raf"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        update = "asynchronous"

        init = "INIT TRUE"
        spec = "LTLSPEC F(Raf & F(STEADYSTATE))"
        answer, counterex = MC.check_primes_with_counterexample(
            primes, update, init, spec)
        if counterex:
            " -> ".join(STGs.state2str(x) for x in counterex)

        stg = STGs.primes2stg(primes, update)
        STGs.add_style_path(stg, counterex, "red")
        stg.graph["label"] = "Example 19: A LTL counterexample"
        STGs.stg2image(stg, "source/figure19.pdf")

        igraph = IGs.primes2igraph(primes)
        IGs.activities2animation(igraph, counterex, "counterexample.gif")

    if 0 or RUN_ALL:
        print("CTL examples")

        bnet = [
            "GrowthFactor,  0",
            "Proliferation, GrowthFactor | Proliferation & !DNAdamage",
            "DNAdamage,     !GrowthFactor & DNAdamage"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        update = "asynchronous"

        stg = STGs.primes2stg(primes, update)
        for x in stg.nodes():
            x_dict = STGs.state2dict(primes, x)
            if x_dict["GrowthFactor"]:
                stg.node[x]["style"] = "filled"
                stg.node[x]["fillcolor"] = "gray"
        sub = ({"Proliferation": 1}, {"label": "proliferation"})
        STGs.add_style_subspaces(primes, stg, [sub])
        stg.graph["label"] = "Example 20: STG of the Proliferation network"

        STGs.stg2image(stg, "source/figure20.pdf")

        init = "INIT GrowthFactor"
        spec = "LTLSPEC F(Proliferation)"
        answer, counterex = MC.check_primes_with_counterexample(
            primes, update, init, spec)
        print(init, spec, "is", answer)
        STGs.add_style_path(stg, counterex, "red")
        stg.graph["label"] = "Example 21: Counterexample"

        STGs.stg2image(stg, "source/figure21.pdf")

        spec = "CTLSPEC EF(Proliferation)"
        answer = MC.check_primes(primes, update, init, spec)
        print(init, spec, "is", answer)

    if 0 or RUN_ALL:
        bnet = [
            "GrowthFactor,  0",
            "Proliferation, GrowthFactor | Proliferation & !DNAdamage",
            "DNAdamage,     !GrowthFactor & DNAdamage"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        update = "asynchronous"

        init = "INIT !DNAdamage & GrowthFactor"
        c1 = "Proliferation"
        c2 = "DNAdamage_STEADY"
        spec = "CTLSPEC AG(EF(AG(%s | %s)))" % (c1, c2)
        answer = MC.check_primes(primes, update, init, spec)
        print(init, spec, "is", answer)

        init = "INIT Proliferation"
        condition = "STEADYSTATE"
        spec = "CTLSPEC AG(EF(AG(%s)))" % condition
        answer = MC.check_primes(primes, update, init, spec)
        print(init, spec, "is", answer)

        init = "INIT Proliferation"
        condition = "STEADYSTATE | (!Proliferation & DNAdamage)"
        spec = "CTLSPEC AG(EF(AG(%s)))" % condition
        answer = MC.check_primes(primes, update, init, spec)
        print(init, spec, "is", answer)

        init = "INIT Proliferation"
        spec = "CTLSPEC EX(Proliferation)"
        answer, counterex = MC.check_primes_with_counterexample(
            primes, update, init, spec)
        print(init, spec, "is", answer)
        print(counterex)
        for x in counterex:
            print(STGs.state2str(x))

        for x in STGs.successors_asynchronous(primes, "101"):
            print(x)

    if 0 or RUN_ALL:
        bnet = [
            "x0,   !x0&x1 | x2", "x1,   !x0 | x1 | x2", "x2,   x0&!x1 | x2"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)

        stg = STGs.primes2stg(primes, "asynchronous")
        attractor1 = (["010", "110"], {"label": "Attractor1"})
        attractor2 = (["111"], {"label": "Attractor2"})
        for x in stg.nodes():
            if x[1] == "0":
                stg.node[x]["style"] = "filled"
                stg.node[x]["fillcolor"] = "gray"

        stg.graph["label"] = "Example 22: Existential queries"
        STGs.stg2image(stg, "source/figure22.pdf")

        init = "INIT !x1"
        specQ1 = "CTLSPEC  EF(AG(x0_STEADY))"
        specQ2 = "CTLSPEC !EF(AG(x0_STEADY))"
        update = "asynchronous"
        Q1 = MC.check_primes(primes, update, init, specQ1)
        print(Q1)
        Q2 = not MC.check_primes(primes, update, init, specQ2)
        print(Q2)

        notQ2, counterex = MC.check_primes_with_counterexample(
            primes, update, init, specQ2)
        state = counterex[0]
        print(STGs.state2str(state))

        print(counterex)

    if 0 or RUN_ALL:

        bnet = ["x, !x | y | z", "y, !x&z | y&!z", "z, x&y | z"]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        tspaces = TS.trap_spaces(primes, "all")
        for x in tspaces:
            print(STGs.subspace2str(primes, x))

        print(", ".join(STGs.subspace2str(primes, x) for x in tspaces))

        stg = STGs.primes2stg(primes, "asynchronous")
        STGs.add_style_subspaces(primes, stg, tspaces)

        stg.graph["label"] = "Example 23: All trap spaces"
        STGs.stg2image(stg, "source/figure23.pdf")

        mintspaces = TS.trap_spaces(primes, "min")
        print("mintspaces",
              ", ".join(STGs.subspace2str(primes, x) for x in mintspaces))
        for x in mintspaces:
            sub = (x, {"fillcolor": "salmon"})
            STGs.add_style_subspaces(primes, stg, [sub])
        maxtspaces = TS.trap_spaces(primes, "max")
        print("maxtspaces",
              ", ".join(STGs.subspace2str(primes, x) for x in maxtspaces))
        for x in maxtspaces:
            if x in mintspaces:
                sub = (x, {"fillcolor": "lightyellow"})
                STGs.add_style_subspaces(primes, stg, [sub])
            else:
                sub = (x, {"fillcolor": "lightblue"})
                STGs.add_style_subspaces(primes, stg, [sub])
        stg.graph["label"] = "Example 24: Minimal and maximal trap spaces"

        STGs.stg2image(stg, "source/figure24.pdf")

    if 0 or RUN_ALL:
        bnet = ["v1, !v1 | v3", "v2, !v1 | v2&!v3", "v3, !v2"]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        stg = STGs.primes2stg(primes, "asynchronous")
        STGs.add_style_sccs(stg)
        steady, cyclic = AD.compute_attractors_tarjan(stg)

        stg.graph[
            "label"] = "Example 25: A network with a cyclic attractor and a steady state."
        STGs.stg2image(stg, "source/figure25.pdf")

        state = AD.find_attractor_state_by_randomwalk_and_ctl(
            primes, "asynchronous")
        print(STGs.state2str(state))

        update = "asynchronous"
        mintspaces = TS.trap_spaces(primes, "min")
        for x in mintspaces:
            answer_univocal = AD.univocality(primes, update, x)
            answer_faithful = AD.faithfulness(primes, update, x)
            print("min trap space:", STGs.subspace2str(primes, x))
            print("  is univocal:", answer_univocal)
            print("  is faithful:", answer_faithful)

        answer_complete, counterex = AD.completeness_naive(
            primes, update, mintspaces)
        print("min trap spaces are complete:", answer_complete)

    if False:

        bnet = [
            "v1, !v1&!v2&v3 | !v1&v2&!v3 | v1&!v2&!v3 | v1&v2&v3",
            "v2, !v1&!v2&!v3 | !v1&v2&v3 | v1&!v2&v3 | v1&v2&!v3",
            "v3, !v1&!v2&v3 | !v1&v2&!v3 | v1&!v2&!v3 | v1&v2&v3"
        ]
        bnet = "\n".join(bnet)
        primes = FEX.bnet2primes(bnet)
        mintspaces = TS.trap_spaces(primes, "min")
        stg = STGs.primes2stg(primes, "asynchronous")
        mintspaces = TS.trap_spaces(primes, "min")
        print([STGs.subspace2str(primes, x) for x in mintspaces])

        STGs.add_style_sccs(stg)
        STGs.add_style_subspaces(primes, stg, mintspaces)

        stg.graph[
            "label"] = "Example xx: An STG whose minimal trap space '---' is not complete"
        STGs.stg2image(stg, "source/figurexx.pdf")
Ejemplo n.º 8
0
def faithfulness_with_counterexample(Primes, Update, Trapspace):
    """
    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 *Trapspace*.
        
    **arguments**:
        * *Primes*: prime implicants
        * *Update* (str): the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
        * *Trapspace* (str / dict): a subspace

    **returns**:
        * *Answer* (bool): whether *Trapspace* is faithful in the STG defined by *Primes* and *Update*
        * *CounterExample* (dict): a state that belongs to an attractor that does not oscillate in all free variables or *None* if no counterexample exists

    **example**::

        >>> mintspaces = PyBoolNet.TrapSpaces.trap_spaces(primes, "min")
        >>> x = mintspaces[0]
        >>> faithfulness(primes, x)        
        True
    """

    if type(Trapspace) == str:
        Trapspace = StateTransitionGraphs.str2subspace(Primes, Trapspace)

    # trivial case: steady state
    if len(Trapspace) == len(Primes):
        return True, None

    # percolation
    primes = PyBoolNet.PrimeImplicants.copy(Primes)
    PyBoolNet.PrimeImplicants.create_constants(primes, Constants=Trapspace)
    constants = PyBoolNet.PrimeImplicants.percolate_and_remove_constants(
        primes)

    # trivial case: free variables fix due to percolation
    if len(constants) > len(Trapspace):
        counterex = find_attractor_state_by_randomwalk_and_ctl(primes, Update)
        attractor_state = PyBoolNet.Utility.Misc.merge_dicts(
            [counterex, constants])

        return False, attractor_state

    # faithfulness
    spec = 'CTLSPEC AG(%s)' % PyBoolNet.QueryPatterns.EF_unsteady_states(
        primes)
    init = 'INIT TRUE'
    answer, counterex = PyBoolNet.ModelChecking.check_primes_with_counterexample(
        primes, Update, init, spec)

    # success
    if answer:
        return True, None

    # failure
    else:
        attractor_state = find_attractor_state_by_randomwalk_and_ctl(
            primes, Update, counterex[-1])
        attractor_state = PyBoolNet.Utility.Misc.merge_dicts(
            [attractor_state, constants])

        return False, attractor_state
Ejemplo n.º 9
0
def univocality_with_counterexample(Primes, Update, Trapspace):
    """
    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* (str): the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
        * *Trapspace* (str / dict): a subspace
        
    **returns**:
        * *Answer* (bool): whether *Trapspace* is univocal in the STG defined by *Primes* and *Update*
        * *CounterExample* (dict): two states that belong to different attractors or *None* if no counterexample exists

    **example**::

        >>> mintspaces = PyBoolNet.TrapSpaces.trap_spaces(primes, "min")
        >>> trapspace = mintrapspaces[0]
        >>> answer, counterex = univocality_with_counterexample(primes, trapspace, "asynchronous")
    """

    if type(Trapspace) == str:
        Trapspace = StateTransitionGraphs.str2subspace(Primes, Trapspace)

    # percolation
    primes = PyBoolNet.PrimeImplicants.copy(Primes)
    PyBoolNet.PrimeImplicants.create_constants(primes, Constants=Trapspace)
    constants = PyBoolNet.PrimeImplicants.percolate_and_remove_constants(
        primes)

    # trivial case: constants = unique steady state
    if primes == {}:
        return True, None

    # find attractor state
    attractor_state1 = find_attractor_state_by_randomwalk_and_ctl(
        primes, Update)

    # univocality
    spec = 'CTLSPEC ' + PyBoolNet.QueryPatterns.EF_oneof_subspaces(
        primes, [attractor_state1])
    init = 'INIT TRUE'
    answer, counterex = PyBoolNet.ModelChecking.check_primes_with_counterexample(
        primes, Update, init, spec)

    # success
    if answer:
        return True, None

    # failure
    else:
        attractor_state2 = find_attractor_state_by_randomwalk_and_ctl(
            primes, Update, counterex[-1])

        # need to add constants to get original states
        attractor_state2 = PyBoolNet.Utility.Misc.merge_dicts(
            [attractor_state2, constants])
        attractor_state1 = PyBoolNet.Utility.Misc.merge_dicts(
            [attractor_state1, constants])
        counterex = attractor_state1, attractor_state2

        return False, counterex
Ejemplo n.º 10
0
def main():

    input_nodes = ["Adenosine", "Dopamine", "Enkephalin",
                    "GABA", "Glutamate", "Serotonin", "Ach"]

    primes = PyBoolNet.FileExchange.read_primes(
        "datasets/creb/network.json")

    # primary_attractor = pd.read_csv(
    #     "datasets/creb/primary_attractor.csv",
    #     index_col=0, header=None)
    # assert primary_attractor.shape[0] == len(primes)
    # for n in primary_attractor.index:
    #     assert n in primes, n
    
    # primary_attractor = [
    #     primary_attractor[col].to_dict()
    #     for col in primary_attractor.columns
    # ]
    # primary_attractor = [STGs.state2str(state)
    #     for state in primary_attractor]
    # primary_attractor = rotate_cyclic_attractor(
    #     primary_attractor)
    # assert min(primary_attractor) == primary_attractor[0]

    merge_depths = pd.read_csv("implisig_output/creb/pos_neg/merge_depths.csv", 
        index_col=0)["0"]
    depths = sorted(set(merge_depths.values), reverse=True)

    kernels = [
        ["AC2", "AC5", "Calmodulin", "M2R", "PKA"],
        ["CREB", "CaMKI", "Calmodulin", "Galphai", "PKA"],
        ["mGluR7", "PQtypeCaCh", "cAMP"], ["mGluR7", "cAMP", "Ca2plus"],
        # ["mGluR7", "PQtypeCaCh", "cAMP", "Calmodulin"], ["mGluR7", "cAMP", "Ca2plus", "Calmodulin"],
        # ["mGluR7", "PQtypeCaCh", ], ["mGluR7",  "Ca2plus"],
        # kernel 
            # for kernel_size in [1, 2, 3]
            # for kernel in itertools.combinations(
                # ["mGluR7", "cAMP", "Ca2plus"]
        #     # ["AC2", "AC5", "Calmodulin", "M2R", "PKA"] + ["NtypeCaCh", "PKC", "Ca2plus",] + ["CaMKII"], kernel_size)
        #     ["AC5",
        #         "PKA",
        #         "Gbetagamma",
        #         "DAG",
        #         "mGluR1",
        #         "PKC",
        #         "mGluR7",
        #         "PQtypeCaCh",
        #         "PDK1",
        #         "cAMP",
        #         "CaMKII",
        #         "AC1",
        #         "PIP3",
        #         "NtypeCaCh",
        #         "Calmodulin",
        #         "Ca2plus",
        #         "AC2",
        #         "PI3K",
                # "PLCbeta"]
                # , kernel_size)
            # ["NtypeCaCh", "PKC", "Ca2plus"] + ["CaMKII", "Calmodulin"], kernel_size)
            # merge_depths.index[merge_depths>=depths[2]], kernel_size)
        # ["NtypeCaCh", "PKC", "Ca2plus"], 
        # primes
    ] #+ [ list(merge_depths.index[merge_depths>=depth]) for depth in depths]
    # ]

    states = select_states(primes, 
        num_state_samples=10000)

    for state in states:
        state = STGs.state2dict(primes, state)
        assert not any([
            state[n] for n in input_nodes])

    attractors = build_STG_and_determine_attractors(
        primes, states, return_stg=False)
    
    attractors = map(rotate_cyclic_attractor, attractors)
    attractors = list(map(tuple, attractors))
    unique_attractors = set(attractors)

    for attractor in unique_attractors:
        for state in attractor:
            state = STGs.state2dict(primes, state)
            assert not any([
                state[n] for n in input_nodes])

    print ("number of unique attractors:",
        len(unique_attractors))

    stg = STGs.primes2stg(primes, 
        Update="synchronous", 
        InitialStates=states)

    basins = dict()
    for basin in sorted(nx.weakly_connected_components(stg),
            key=len, reverse=True):
        cycles = list(nx.simple_cycles(stg.subgraph(basin)))
        assert len(cycles) == 1
        attractor = tuple(cycles[0])
        attractor = rotate_cyclic_attractor(attractor)
        assert attractor in unique_attractors
        basins.update({attractor: basin})

    primary_attractor = max(basins, 
        key=lambda k: len(basins[k]))

    # primary_attractor = pd.DataFrame([pd.Series(STGs.state2dict(primes, state))
    #     for state in primary_attractor])
    
    # primary_attractor.to_csv("CREB_primary_attractor.csv")

    # raise SystemError

    print ("primary attractor basin proportion:", 
        len(basins[primary_attractor]) / len(stg))

    df = []

    for target_state in primary_attractor:
        target_state = STGs.state2dict(primes,
            target_state)
        d = {}
        for kernel in kernels:
            print ("processing kernel", kernel,)
            assert all([n in primes for n in kernel])

            primes_modified = PyBoolNet.PrimeImplicants.create_constants(
                primes,
                {n: target_state[n] for n in kernel},
                Copy=True)

            attractors_new = build_STG_and_determine_attractors(
                primes_modified, states, return_stg=False)
            attractors_new = map(rotate_cyclic_attractor,
                attractors_new)
            attractors_new = list(map(tuple, attractors_new))
            unique_attractors_new = set(attractors_new)

            print ("number of unique attractors:", 
                len(unique_attractors_new))
            if len(unique_attractors_new) == 1:

                for unique_attractor in unique_attractors_new:
                    assert min(unique_attractor) == unique_attractor[0]
                    print ("length of obtained attractor", len(unique_attractor))
                    if len(unique_attractor) == 1:
                        print ("checking primary basin membership")

                        attr = build_STG_and_determine_attractors(primes, unique_attractor)
                        assert len(attr) == 1
                        attr = rotate_cyclic_attractor(attr[0])
                        in_primary_basin = int(all([s1==s2 
                            for s1, s2 in zip(attr, primary_attractor)]))
                        print ("in primary basin:", in_primary_basin)
                        d.update({"_".join(kernel): in_primary_basin})
                    else:
                        d.update({"_".join(kernel): 0})
            else:
                d.update({"_".join(kernel): 0})

            print ()
        df.append(pd.Series(d, name=STGs.state2str(target_state)))

    df = pd.DataFrame(df)
    df.to_csv("CREB_kernels.csv", sep=",")
Ejemplo n.º 11
0
def faithfulness(Primes, Update, Trapspace):
	"""
	The model checking approach for deciding whether *Trapspace* is faithful,
	i.e., whether all free variables oscillate in all of the attractors contained in it,
	in the state transition graph defined by *Primes* and *Update*.
	The approach is described and discussed in :ref:`Klarner2015(a) <klarner2015trap>`.
	It is decided by a single CTL query of the pattern :ref:`EF_all_unsteady <EF_all_unsteady>`
	and the random-walk-approach of the function :ref:`random_walk <random_walk>`.

	.. note::
		In the (very unlikely) case that the random walk does not end in an attractor state an exception will be raised.

	.. note::
		Faithfulness depends on the update strategy, i.e.,
		a trapspace may be faithful in the synchronous STG but not faithful in the asynchronous STG or vice versa.

	.. note::
		A typical use case is to decide whether a minimal trap space is faithful.

	.. note::
		*Trapspace* is in fact not required to be a trap set, i.e., it may be an arbitrary subspace.
		If it is an arbitrary subspace then the involved variables are artificially fixed to be constant.

	**arguments**:
		* *Primes*: prime implicants
		* *Update* (str): the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
		* *Trapspace* (str / dict): a subspace

	**returns**:
		* *Answer* (bool): whether *Trapspace* is faithful in the STG defined by *Primes* and *Update*

	**example**::

		>>> mintspaces = PyBoolNet.AspSolver.trap_spaces(primes, "min")
		>>> x = mintspaces[0]
		>>> faithfulness(primes, x)
		True
	"""

	if type(Trapspace)==str:
		Trapspace=StateTransitionGraphs.str2subspace(Primes, Trapspace)

	# trivial case: steady state
	if len(Trapspace)==len(Primes):
		return True

	# percolation
	primes = PyBoolNet.PrimeImplicants.copy(Primes)
	PyBoolNet.PrimeImplicants.create_constants(primes, Constants=Trapspace)
	constants  = PyBoolNet.PrimeImplicants.percolate_and_remove_constants(primes)

	# trivial case: free variables fix due to percolation
	if len(constants)>len(Trapspace):
		return False

	# faithfulness
	spec = 'CTLSPEC AG(%s)'%PyBoolNet.TemporalLogic.EF_unsteady_states(primes)
	init = 'INIT TRUE'
	answer = PyBoolNet.ModelChecking.check_primes(primes, Update, init, spec)

	return answer
Ejemplo n.º 12
0
def univocality(Primes, Update, Trapspace):
	"""
	The model checking and random-walk-based method for deciding whether *Trapspace* is univocal,
	i.e., whether there is a unique attractor contained in it,
	in the state transition graph defined by *Primes* and *Update*.
	The approach is described and discussed in :ref:`Klarner2015(a) <klarner2015trap>`.
	The function performs two steps: first it searches for a state that belongs to an attractor inside of *Trapspace* using
	the random-walk-approach and the function :ref:`random_walk <random_walk>`,
	then it uses CTL model checking, specifically the pattern :ref:`AGEF_oneof_subspaces <AGEF_oneof_subspaces>`,
	to decide if the attractor is unique inside *Trapspace*.

	.. note::
		In the (very unlikely) case that the random walk does not end in an attractor state an exception will be raised.

	.. note::
		Univocality depends on the update strategy, i.e.,
		a trapspace may be univocal in the synchronous STG but not univocal in the asynchronous STG or vice versa.

	.. note::
		A typical use case is to decide whether a minimal trap space is univocal.

	.. note::
		*Trapspace* is in fact not required to be a trap set, i.e., it may be an arbitrary subspace.
		If it is an arbitrary subspace then the involved variables are artificially fixed to be constant.

	**arguments**:
		* *Primes*: prime implicants
		* *Update* (str): the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
		* *Trapspace* (str / dict): a subspace

	**returns**:
		* *Answer* (bool): whether *Trapspace* is univocal in the STG defined by *Primes* and *Update*

	**example**::

		>>> mintspaces = PyBoolNet.AspSolver.trap_spaces(primes, "min")
		>>> x = mintrapspaces[0]
		>>> univocality(primes, "asynchronous", x)
		True
	"""

	if type(Trapspace)==str:
		Trapspace=StateTransitionGraphs.str2subspace(Primes, Trapspace)

	# percolation
	primes = PyBoolNet.PrimeImplicants.copy(Primes)
	PyBoolNet.PrimeImplicants.create_constants(primes, Constants=Trapspace)
	PyBoolNet.PrimeImplicants.percolate_and_remove_constants(primes)

	# trivial case: unique steady state
	if primes == {}:
		return True

	# find attractor state
	attractor_state1 = find_attractor_state_by_randomwalk_and_ctl(primes, Update)

	# univocality
	spec = 'CTLSPEC ' + PyBoolNet.TemporalLogic.EF_oneof_subspaces(primes, [attractor_state1])
	init = 'INIT TRUE'
	answer = PyBoolNet.ModelChecking.check_primes(primes, Update, init, spec)

	return answer
Ejemplo n.º 13
0
def faithfulness(Primes, Update, Trapspace):
    """
    The model checking approach for deciding whether *Trapspace* is faithful,
    i.e., whether all free variables oscillate in all of the attractors contained in it,
    in the state transition graph defined by *Primes* and *Update*.
    The approach is described and discussed in :ref:`Klarner2015(a) <klarner2015trap>`.
    It is decided by a single CTL query of the pattern :ref:`EF_all_unsteady <EF_all_unsteady>`
    and the random-walk-approach of the function :ref:`random_walk <random_walk>`.

    .. note::
        In the (very unlikely) case that the random walk does not end in an attractor state an exception will be raised.

    .. note::
        Faithfulness depends on the update strategy, i.e.,
        a trapspace may be faithful in the synchronous STG but not faithful in the asynchronous STG or vice versa.

    .. note::
        A typical use case is to decide whether a minimal trap space is faithful.

    .. note::
        *Trapspace* is in fact not required to be a trap set, i.e., it may be an arbitrary subspace.
        If it is an arbitrary subspace then the involved variables are artificially fixed to be constant.

    **arguments**:
        * *Primes*: prime implicants
        * *Update* (str): the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
        * *Trapspace* (str / dict): a subspace

    **returns**:
        * *Answer* (bool): whether *Trapspace* is faithful in the STG defined by *Primes* and *Update*

    **example**::

        >>> mintspaces = PyBoolNet.AspSolver.trap_spaces(primes, "min")
        >>> x = mintspaces[0]
        >>> faithfulness(primes, x)
        True
    """

    if type(Trapspace) == str:
        Trapspace = StateTransitionGraphs.str2subspace(Primes, Trapspace)

    # trivial case: steady state
    if len(Trapspace) == len(Primes):
        return True

    # percolation
    primes = PyBoolNet.PrimeImplicants.copy(Primes)
    PyBoolNet.PrimeImplicants.create_constants(primes, Constants=Trapspace)
    constants = PyBoolNet.PrimeImplicants.percolate_and_remove_constants(
        primes)

    # trivial case: free variables fix due to percolation
    if len(constants) > len(Trapspace):
        return False

    # faithfulness
    spec = 'CTLSPEC AG(%s)' % PyBoolNet.TemporalLogic.EF_unsteady_states(
        primes)
    init = 'INIT TRUE'
    answer = PyBoolNet.ModelChecking.check_primes(primes, Update, init, spec)

    return answer
Ejemplo n.º 14
0
def univocality(Primes, Update, Trapspace):
    """
    The model checking and random-walk-based method for deciding whether *Trapspace* is univocal,
    i.e., whether there is a unique attractor contained in it,
    in the state transition graph defined by *Primes* and *Update*.
    The approach is described and discussed in :ref:`Klarner2015(a) <klarner2015trap>`.
    The function performs two steps: first it searches for a state that belongs to an attractor inside of *Trapspace* using
    the random-walk-approach and the function :ref:`random_walk <random_walk>`,
    then it uses CTL model checking, specifically the pattern :ref:`AGEF_oneof_subspaces <AGEF_oneof_subspaces>`,
    to decide if the attractor is unique inside *Trapspace*.

    .. note::
        In the (very unlikely) case that the random walk does not end in an attractor state an exception will be raised.

    .. note::
        Univocality depends on the update strategy, i.e.,
        a trapspace may be univocal in the synchronous STG but not univocal in the asynchronous STG or vice versa.

    .. note::
        A typical use case is to decide whether a minimal trap space is univocal.

    .. note::
        *Trapspace* is in fact not required to be a trap set, i.e., it may be an arbitrary subspace.
        If it is an arbitrary subspace then the involved variables are artificially fixed to be constant.

    **arguments**:
        * *Primes*: prime implicants
        * *Update* (str): the update strategy, one of *"asynchronous"*, *"synchronous"*, *"mixed"*
        * *Trapspace* (str / dict): a subspace

    **returns**:
        * *Answer* (bool): whether *Trapspace* is univocal in the STG defined by *Primes* and *Update*

    **example**::

        >>> mintspaces = PyBoolNet.AspSolver.trap_spaces(primes, "min")
        >>> x = mintrapspaces[0]
        >>> univocality(primes, "asynchronous", x)
        True
    """

    if type(Trapspace) == str:
        Trapspace = StateTransitionGraphs.str2subspace(Primes, Trapspace)

    # percolation
    primes = PyBoolNet.PrimeImplicants.copy(Primes)
    PyBoolNet.PrimeImplicants.create_constants(primes, Constants=Trapspace)
    PyBoolNet.PrimeImplicants.percolate_and_remove_constants(primes)

    # trivial case: unique steady state
    if primes == {}:
        return True

    # find attractor state
    attractor_state1 = find_attractor_state_by_randomwalk_and_ctl(
        primes, Update)

    # univocality
    spec = 'CTLSPEC ' + PyBoolNet.TemporalLogic.EF_oneof_subspaces(
        primes, [attractor_state1])
    init = 'INIT TRUE'
    answer = PyBoolNet.ModelChecking.check_primes(primes, Update, init, spec)

    return answer
Ejemplo n.º 15
0
def spit_out_graphs(variable_to_boolean_function, prefix_of_filename):
    """
    Plots the
    1) interaction graph
    2) asyncronous state transition graph
    3) The quotient graph with respect to the partition induced by the Boolean function.
    4) Qualitate and Boolean graph
    5) SCCs of these graphs
    """
    prime_implicants = QMC.functions2primes(variable_to_boolean_function)

    # Create the interaction graph
    igraph = IGs.primes2igraph(prime_implicants)

    if not function_is_monotonous(interaction_graph=igraph):
        raise ValueError("Error: This function is not monotonous.")

    # Only consider interaction graphs wihtout self loops
    if interaction_graph_has_self_loops(igraph):
        raise ValueError("This graph has a self loop.")

    # Construct the state transition graph
    state_transition_graph = STGs.primes2stg(prime_implicants, "asynchronous")

    # Get the quotient graph and plot it
    quotientGraph = computeQuotientGraph_fromFunction(state_transition_graph,
                                                      example.f)
    STGs.stg2image(quotientGraph,
                   prefix_of_filename + "_quotient_graph.pdf",
                   LayoutEngine="dot")

    # Convert the igraph into an adajacency matrix
    sign_matrix, number_to_nodes, nodes_to_number = graph_to_adj_matrix(igraph)

    # Get the QDE graph and the discrete QDE graph. Both are constructed in exactley the same way but have
    # different node sets.
    qde_graph = construct_qde_graph(sign_matrix, zero_one_representation=False)
    boolean_qde_graph = construct_qde_graph(sign_matrix,
                                            zero_one_representation=True)

    STGs.stg2image(qde_graph,
                   prefix_of_filename + "_complete_qde_graph.pdf",
                   LayoutEngine="dot")
    STGs.stg2image(boolean_qde_graph,
                   prefix_of_filename + "_complete_boolean_qde_graph.pdf",
                   LayoutEngine="dot")

    # Get the scc-graph of the QDE-graph
    sccs = nx.strongly_connected_components(boolean_qde_graph)
    scc_qde_graph = computeQuotientGraph_fromPartition(boolean_qde_graph, sccs)
    STGs.stg2image(scc_qde_graph,
                   prefix_of_filename + "_complete_scc_qde_graph.pdf")

    STGs.stg2image(state_transition_graph,
                   prefix_of_filename + "_stg.pdf",
                   LayoutEngine="dot")
    IGs.create_image(prime_implicants, prefix_of_filename + "_igraph.pdf")
Ejemplo n.º 16
0
def create_attractor_report(Primes, FnameTXT=None):
    """
    Creates an attractor report for the network defined by *Primes*.
    
    **arguments**:
        * *Primes*: prime implicants
        * *FnameTXT* (str): the name of the report file or *None*
    
    **returns**:
        * *FnameTXT* (str): *FnameTXT=None* or *None* if *FnameTXT* is given

    **example**::
         >>> create_attractor_report(primes, "report.txt")
    """

    mints = PyBoolNet.TrapSpaces.trap_spaces(Primes, "min")
    steady = sorted([x for x in mints if len(x) == len(Primes)])
    cyclic = sorted([x for x in mints if len(x) < len(Primes)])

    lines = ["", ""]
    lines += ["### Attractor Report"]
    lines += [
        " * created on %s using PyBoolNet, see https://github.com/hklarner/PyBoolNet"
        % datetime.date.today().strftime('%d. %b. %Y')
    ]
    lines += [""]

    lines += ["### Steady States"]
    if not steady:
        lines += [" * there are no steady states"]
    else:
        w = max([12, len(Primes)])
        lines += ["| " + "steady state".ljust(w) + " |"]
        lines += ["| " + w * "-" + " | "]

    for x in steady:
        lines += [
            "| " + StateTransitionGraphs.subspace2str(Primes, x).ljust(w) +
            " |"
        ]
    lines += [""]

    width = max([len(Primes), 14])
    spacer1 = lambda x: x.ljust(width)

    lines += ["### Asynchronous STG"]
    answer, counterex = completeness_iterative(Primes, "asynchronous")
    lines += [" * completeness: %s" % answer]

    if not cyclic:
        lines += [" * there are only steady states"]
    else:
        lines += [""]
        line = "| " + "trapspace".ljust(width) + " | univocal  | faithful  |"
        lines += [line]
        lines += ["| " + width * "-" + " | --------- | --------- |"]

    for x in cyclic:
        line = "| " + (
            "%s" % StateTransitionGraphs.subspace2str(Primes, x)).ljust(width)
        line += " | " + ("%s" %
                         univocal(Primes, "asynchronous", x)[0]).ljust(9)
        line += " | " + (
            "%s" % faithful(Primes, "asynchronous", x)[0]).ljust(9) + " |"
        lines += [line]
    lines += [""]

    lines += ["### Synchronous STG"]
    answer, counterex = completeness_iterative(Primes, "synchronous")
    lines += [" * completeness: %s" % answer]

    if not cyclic:
        lines += [" * there are only steady states"]
    else:
        lines += [""]
        line = "| " + "trapspace".ljust(width) + " | univocal  | faithful  |"
        lines += [line]
        lines += ["| " + width * "-" + " | --------- | --------- |"]

    for x in cyclic:
        line = "| " + (
            "%s" % StateTransitionGraphs.subspace2str(Primes, x)).ljust(width)
        line += " | " + ("%s" % univocal(Primes, "synchronous", x)[0]).ljust(9)
        line += " | " + ("%s" %
                         faithful(Primes, "synchronous", x)[0]).ljust(9) + " |"
        lines += [line]
    lines += [""]

    bnet = []
    for row in PyBoolNet.FileExchange.primes2bnet(Primes).split("\n"):
        t, f = row.split(",")
        bnet.append((t.strip(), f.strip()))

    t_width = max([7] + [len(x) for x, _ in bnet])
    f_width = max([7] + [len(x) for _, x in bnet])
    lines += ["### Network"]
    t, f = bnet.pop(0)
    lines += ["| " + t.ljust(t_width) + " | " + f.ljust(f_width) + " |"]
    lines += ["| " + t_width * "-" + " | " + f_width * "-" + " |"]
    for t, f in bnet:
        lines += ["| " + t.ljust(t_width) + " | " + f.ljust(f_width) + " |"]

    lines += ["", ""]

    if FnameTXT:
        with open(FnameTXT, "w") as f:
            f.writelines("\n".join(lines))
            print("created %s" % FnameTXT)
    else:
        return "\n".join(lines)