Skip to content

Commit

Permalink
expand source scc in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
troonmel committed Nov 7, 2023
1 parent 369aea2 commit 32285e8
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 0 deletions.
177 changes: 177 additions & 0 deletions nfvsmotifs/_sd_algorithms/expand_source_SCCs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import sys

sys.path.append(".")

from biodivine_aeon import BooleanNetwork

import nfvsmotifs
import networkx as nx
import itertools as it
from nfvsmotifs.interaction_graph_utils import infer_signed_interaction_graph, _digraph_to_regulatory_graph
from nfvsmotifs.space_utils import percolate_space, percolate_network
from nfvsmotifs.SuccessionDiagram import SuccessionDiagram
from networkx import DiGraph
from nfvsmotifs.petri_net_translation import extract_variable_names, network_to_petrinet

def expand_source_SCCs(sd: SuccessionDiagram, size_limit: int | None = None) -> bool:
"""
See `SuccessionDiagram.expand_minimal_spaces` for documentation.
"""

root = sd.root()

seen = set([root])

# percolate constant nodes
perc_space, _ = percolate_space(sd.network, {}, strict_percolation=False)
perc_bn = percolate_network(sd.network, perc_space)

# find source nodes
source_nodes = find_source_nodes(perc_bn)

# get the initial subspaces that constitute the first depth
initial_sub_spaces:list[dict[str,int]] = []
if len(source_nodes) == 0:
initial_sub_spaces.append(perc_space)
else:
# get source nodes combinations
bin_values_list = it.product(range(2), repeat=len(source_nodes))
for bin_values in bin_values_list:
source_comb = dict(zip(source_nodes, bin_values))

sub_space = source_comb
sub_space.update(perc_space)
initial_sub_spaces.append(sub_space)


def perc_and_remove_constants_from_bn(bn:BooleanNetwork, space: dict[str, int]) -> BooleanNetwork:
"""
Take a BooleanNetwork and percolate given space.
Then remove constant nodes with rules
A* = (A | !A)
B* = (B & !B)
and return a clean BooleanNetwork with no constant nodes.
TODO: if possible, delete constant nodes from the BooleanNetwork directly,
without converting into bnet and back.
"""

perc_space, _ = percolate_space(bn, space, strict_percolation=False)
perc_bn = percolate_network(bn, perc_space)

perc_bnet = perc_bn.to_bnet()

# remove constant nodes from the bnet
clean_bnet = ""
for line in perc_bnet.split("\n"):
if line.strip() == "":
continue
node = line.split(",")[0]
function = line.split(",")[1].strip()
if function == "("+node+" | !"+node+")":
continue
elif function == "("+node+" & !"+node+")":
continue
else:
clean_bnet += line + "\n"

clean_bn = BooleanNetwork.from_bnet(clean_bnet)

return clean_bn


def find_source_nodes(network: BooleanNetwork | DiGraph) -> list[str]:

if isinstance(network, BooleanNetwork):
bn = network
petri_net = network_to_petrinet(network)
else:
bn = None
petri_net = network

assert isinstance(petri_net, DiGraph)

if bn is None:
variables = extract_variable_names(petri_net)
else:
variables = [bn.get_variable_name(v) for v in bn.variables()]

# Source node is a node that has no transitions in the PN encoding
# (i.e. it's value cannot change).
source_set = set(variables)
for _, change_var in petri_net.nodes(data="change"): # type: ignore
if change_var in source_set:
source_set.remove(change_var) # type: ignore[reportUnknownArgumentType] # noqa
source_nodes: list[str] = sorted(source_set)

return source_nodes

# di = infer_signed_interaction_graph(perc_bn)

# scc_list = [x for x in nx.strongly_connected_components(di)]

# source_scc_list = []
# for scc in scc_list:
# source = True
# for node in scc:
# for reg in di.predecessors(node):
# if reg not in scc:
# source = False
# break
# if not source:
# break
# if source:
# source_scc_list.append(scc)

# print(source_scc_list)

# print(perc_bnet)

# est_size = 1
# est_depth = 0
# est_min = 1

# for source_scc in source_scc_list:
# print("source_scc:", source_scc)
# scc_bnet = "targets,factors\n"
# for line in perc_bnet.split("\n"):
# for node in source_scc:
# if line.startswith(node+","):
# scc_bnet += line + "\n"

# scc_bn = BooleanNetwork.from_bnet(scc_bnet)

# print(scc_bn.to_bnet())
# scc_bn = scc_bn.infer_regulatory_graph()

# for var in scc_bn.implicit_parameters():
# scc_bn.set_update_function(var, "true")

# scc_bn = scc_bn.infer_regulatory_graph()


# # Compute the succession diagram.
# sd = SuccessionDiagram(scc_bn)
# fully_expanded = sd.expand_bfs(bfs_level_limit=DEPTH_LIMIT, size_limit=NODE_LIMIT)
# assert fully_expanded

# print(f"SD size, {len(sd)}")
# print(f"SD depth, {sd.depth()} ")
# print(f"minimal trapspaces, {len(sd.minimal_trap_spaces())}")

# est_size *= len(sd)
# est_depth += sd.depth()
# est_min *= len(sd.minimal_trap_spaces())

# print(f"{est_size=}")
# print(f"{est_depth=}")
# print(f"{est_min=}")

# log = open(LOG_LOCATION, "a")
# log.write(sys.argv[1].split("/")[-1] + ",") # model name
# log.write(str(bn.num_vars()) + ",") # network size
# log.write(str(len(source_scc_list)) + ",") # number of source_scc
# log.write(str(len(scc_list)) + ",") # number of scc
# log.write(str(est_size) + ",") # estimated SD size
# log.write(str(est_depth) + ",") # estimated SD depth
# log.write(str(est_min) + "\n") # estimated number of attractors
9 changes: 9 additions & 0 deletions nfvsmotifs/_sd_algorithms/test.bnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
targets,factors
constant1_1, (constant1_1 | !constant1_1)
constant1_0, (constant1_0 & !constant1_0)
constant2_1, true
constant2_0, false
source, source
oscillator, !oscillator
source_after_perc, source_after_perc & constant1_1
after_perc_0, after_perc_0 & constant1_0
25 changes: 25 additions & 0 deletions nfvsmotifs/_sd_algorithms/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from expand_source_SCCs import *


bn = BooleanNetwork.from_file("nfvsmotifs/_sd_algorithms/test.bnet")

source_nodes = find_source_nodes(bn)

print(source_nodes)

perc_space, _ = percolate_space(bn, {}, strict_percolation=False)
perc_bn = percolate_network(bn, perc_space)

source_nodes = find_source_nodes(perc_bn)

print(source_nodes)

bin_values_list = it.product(range(2), repeat=len(source_nodes))
for bin_values in bin_values_list:
source_comb = dict(zip(source_nodes, bin_values))
print(source_comb)

sub_space = source_comb
sub_space.update(perc_space)

print(sub_space)

0 comments on commit 32285e8

Please sign in to comment.