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
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
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
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
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
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
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")
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
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
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=",")
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
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
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
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
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")
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)