Skip to content

Commit

Permalink
Merge pull request #122 from jcrozum/source-fast-forward
Browse files Browse the repository at this point in the history
Fast-forward source node expansion anywhere in the succession diagram
  • Loading branch information
daemontus authored Aug 23, 2024
2 parents b32bdd2 + b124b61 commit bafdf60
Showing 1 changed file with 43 additions and 46 deletions.
89 changes: 43 additions & 46 deletions biobalm/_sd_algorithms/expand_source_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import itertools as it
from typing import TYPE_CHECKING, cast

from biobalm.space_utils import percolate_network
from biobalm.types import BooleanSpace
from biobalm.interaction_graph_utils import source_nodes

Expand Down Expand Up @@ -35,49 +34,6 @@ def expand_source_blocks(
current_level: set[int] = set([root])
next_level: set[int] = set()

# This already accounts for constant percolation.
node_space = sd.node_data(root)["space"]

# find source nodes
perc_bn = percolate_network(sd.network, node_space)
sources = source_nodes(perc_bn)

if sd.config["debug"]:
print(f" > Computed source/input variable(s): {sources}")

# get source nodes combinations and expand root node
if len(sources) != 0 and optimize_source_nodes:
# If there are too many source nodes, this can generate an absurdly large SD.
# This would be a problem even without the SCC expansion, but we can just
# stop the whole thing faster because we know how many nodes it generates.
if 2 ** len(sources) > sd.config["max_motifs_per_node"]:
raise RuntimeError(
f"Exceeded the maximum amount of stable motifs per node ({sd.config['max_motifs_per_node']}; see `SuccessionDiagramConfiguration.max_motifs_per_node`)."
)
elif size_limit is not None and 2 ** len(sources) > size_limit:
# Cannot expand. Size limit would be exceeded.
return False
else:
if sd.config["debug"]:
print(
f" > Expanding {len(sources)} source node into {2 ** len(sources)} SD nodes."
)

bin_values_iter = it.product(range(2), repeat=len(sources))
for bin_values in bin_values_iter:
valuation = cast(BooleanSpace, dict(zip(sources, bin_values)))
sub_space = node_space | valuation

next_level.add(sd._ensure_node(root, sub_space)) # type: ignore

# This makes the root artificially "expanded". Also, there
# can be no attractors here because we are just fixing the source nodes.
sd.node_data(root)["expanded"] = True
sd.node_data(root)["attractor_seeds"] = []
sd.node_data(root)["attractor_sets"] = []
current_level = next_level
next_level = set()

bfs_depth = 0

while len(current_level) > 0:
Expand All @@ -97,6 +53,49 @@ def expand_source_blocks(
# Size limit reached.
return False

node_bn = sd.node_percolated_network(node, compute=True)
node_space = sd.node_data(node)["space"]

# Check for source nodes in the percolated network. We can "fast-forward" these the
# same way we would skip them in the root node.
sources = source_nodes(node_bn)
if len(sources) != 0 and optimize_source_nodes:
if sd.config["debug"]:
print(
f" > Found {len(sources)} source nodes in node {node}. Fast-forwarding instead of expansion."
)

# Check if size limits are exceeded.
expected_size = len(sd) + (2 ** len(sources))
if expected_size > sd.config["max_motifs_per_node"]:
raise RuntimeError(
f"Exceeded the maximum amount of stable motifs per node ({sd.config['max_motifs_per_node']}; see `SuccessionDiagramConfiguration.max_motifs_per_node`)."
)
elif size_limit is not None and expected_size > size_limit:
# Cannot expand. Size limit would be exceeded.
return False
else:
if sd.config["debug"]:
print(
f" > Fast-forwarding {len(sources)} source nodes into {2 ** len(sources)} SD nodes."
)

bin_values_iter = it.product(range(2), repeat=len(sources))
for bin_values in bin_values_iter:
valuation = cast(BooleanSpace, dict(zip(sources, bin_values)))
sub_space = node_space | valuation

next_level.add(sd._ensure_node(node, sub_space)) # type: ignore

# This makes the node artificially "expanded". Also, there
# can be no attractors here because we are just fixing the source nodes.
sd.node_data(node)["expanded"] = True
sd.node_data(node)["attractor_seeds"] = []
sd.node_data(node)["attractor_sets"] = []

# This node is done, more work will be done at the next level.
continue

# Compute successors as if this was a normal expansion procedure.
successors = sd.node_successors(node, compute=True)
# Sort successors to avoid non-determinism.
Expand All @@ -116,8 +115,6 @@ def expand_source_blocks(
next_level.add(successors[0])
continue

node_bn = sd.node_percolated_network(node, compute=True)

# Split successors into "blocks" based on the regulatory component
# of the variables fixed by the stable motif.

Expand Down

1 comment on commit bafdf60

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
biobalm
   _pint_reachability.py615018%24, 40–54, 69–93, 101–146
   control.py1141488%107, 119, 125, 129, 134, 143–159, 477, 480, 493
   interaction_graph_utils.py52688%11–13, 151–152, 222–223
   petri_net_translation.py1491292%22–26, 79, 136, 234, 308–309, 333–334, 343, 452
   space_utils.py1322085%26–28, 104–110, 133–139, 347–350, 414, 462
   succession_diagram.py3806483%6, 120, 210–215, 228, 275–282, 386–393, 410–411, 421, 427, 543, 630–636, 752, 755, 873–891, 923, 933, 936, 976, 983, 1034, 1052, 1174, 1360, 1371, 1379, 1422, 1434, 1439, 1445
   symbolic_utils.py32584%10, 39–44, 100, 128
   trappist_core.py1842388%14–18, 55, 57, 92, 215, 217, 219, 254–256, 276–282, 340, 342, 372, 420, 422
biobalm/_sd_algorithms
   expand_attractor_seeds.py60788%6, 28, 42, 109–114, 119
   expand_bfs.py28196%6
   expand_dfs.py30197%6
   expand_minimal_spaces.py40295%6, 37
   expand_source_SCCs.py1111686%11–13, 50, 69, 77, 82, 103, 112, 120, 131, 140, 143, 167, 179, 242–243
   expand_source_blocks.py1131587%10, 30, 42, 54, 64, 71, 76, 79, 138, 164, 173, 206, 216, 222, 231
   expand_to_target.py31390%6, 38, 43
biobalm/_sd_attractors
   attractor_candidates.py2659066%13–15, 26–27, 93, 101, 107–108, 130, 152, 187, 193–204, 223, 239–320, 325, 329, 335, 341, 356, 383, 388, 392, 398, 400–438, 511, 582–583, 684
   attractor_symbolic.py1141686%6–7, 75, 88–92, 103, 112, 144, 179, 191–193, 202, 230, 236
TOTAL198534583% 

Tests Skipped Failures Errors Time
359 0 💤 0 ❌ 0 🔥 55.321s ⏱️

Please sign in to comment.