Skip to content

Commit

Permalink
Merge branch 'master' into 0.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
daemontus committed Dec 19, 2023
2 parents 4454841 + 319ba29 commit 181b88e
Show file tree
Hide file tree
Showing 7 changed files with 485 additions and 33 deletions.
39 changes: 39 additions & 0 deletions src/bin/bench_reach_symbolic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use biodivine_lib_param_bn::biodivine_std::traits::Set;
use biodivine_lib_param_bn::symbolic_async_graph::reachability::Reachability;
use biodivine_lib_param_bn::symbolic_async_graph::SymbolicAsyncGraph;
use biodivine_lib_param_bn::BooleanNetwork;

fn main() {
let args = Vec::from_iter(std::env::args());
let path = &args[1];
let model = BooleanNetwork::try_from_file(path).unwrap();
let model = model.inline_inputs(true, true);

println!(
"Loaded model with {} variables and {} parameters.",
model.num_vars(),
model.num_parameters()
);

let stg = SymbolicAsyncGraph::new(&model).unwrap();

let mut count = 0;
let mut universe = stg.mk_unit_colored_vertices();
while !universe.is_empty() {
let reduced_stg = stg.restrict(&universe);
let mut component = universe.pick_vertex();
loop {
let update = Reachability::reach_bwd(&reduced_stg, &component);
let update = Reachability::reach_fwd(&reduced_stg, &update);
if update.is_subset(&component) {
break;
} else {
component = update;
}
}
println!("Found weak component: {}", component.approx_cardinality());
universe = universe.minus(&component);
count += 1;
}
println!("Total {count} components.")
}
39 changes: 39 additions & 0 deletions src/bin/bench_reach_symbolic_basic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use biodivine_lib_param_bn::biodivine_std::traits::Set;
use biodivine_lib_param_bn::symbolic_async_graph::reachability::Reachability;
use biodivine_lib_param_bn::symbolic_async_graph::SymbolicAsyncGraph;
use biodivine_lib_param_bn::BooleanNetwork;

fn main() {
let args = Vec::from_iter(std::env::args());
let path = &args[1];
let model = BooleanNetwork::try_from_file(path).unwrap();
let model = model.inline_inputs(true, true);

println!(
"Loaded model with {} variables and {} parameters.",
model.num_vars(),
model.num_parameters()
);

let stg = SymbolicAsyncGraph::new(&model).unwrap();

let mut count = 0;
let mut universe = stg.mk_unit_colored_vertices();
while !universe.is_empty() {
let reduced_stg = stg.restrict(&universe);
let mut component = universe.pick_vertex();
loop {
let update = Reachability::reach_bwd_basic(&reduced_stg, &component);
let update = Reachability::reach_fwd_basic(&reduced_stg, &update);
if update.is_subset(&component) {
break;
} else {
component = update;
}
}
println!("Found weak component: {}", component.approx_cardinality());
universe = universe.minus(&component);
count += 1;
}
println!("Total {count} components.")
}
8 changes: 7 additions & 1 deletion src/symbolic_async_graph/_impl_function_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ impl FunctionTable {
bdd_builder.make_variable(bdd_var_name.as_str())
})
.collect();
FunctionTable { arity, rows }
let name = name.to_string();
FunctionTable { arity, rows, name }
}

/// List the symbolic variables that appear in this function table.
Expand All @@ -25,6 +26,11 @@ impl FunctionTable {
pub fn symbolic_variables(&self) -> &Vec<BddVariable> {
&self.rows
}

/// True if this [FunctionTable] contains the provided [BddVariable].
pub fn contains(&self, var: BddVariable) -> bool {
self.rows.contains(&var)
}
}

/// Converts a `FunctionTable` into an iterator of `Vec<bool>` (function table row) and
Expand Down
37 changes: 13 additions & 24 deletions src/symbolic_async_graph/_impl_symbolic_async_graph_algorithm.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::biodivine_std::traits::Set;
use crate::symbolic_async_graph::reachability::Reachability;
use crate::symbolic_async_graph::{GraphColoredVertices, SymbolicAsyncGraph};
use crate::{ExtendedBoolean, Space, VariableId};

Expand All @@ -13,36 +14,14 @@ impl SymbolicAsyncGraph {
///
/// In other words, the result is the smallest forward-closed superset of `initial`.
pub fn reach_forward(&self, initial: &GraphColoredVertices) -> GraphColoredVertices {
let mut result = initial.clone();
'fwd: loop {
for var in self.variables().rev() {
let step = self.var_post_out(var, &result);
if !step.is_empty() {
result = result.union(&step);
continue 'fwd;
}
}

return result;
}
Reachability::reach_fwd(self, initial)
}

/// Compute the set of backward-reachable vertices from the given `initial` set.
///
/// In other words, the result is the smallest backward-closed superset of `initial`.
pub fn reach_backward(&self, initial: &GraphColoredVertices) -> GraphColoredVertices {
let mut result = initial.clone();
'bwd: loop {
for var in self.variables().rev() {
let step = self.var_pre_out(var, &result);
if !step.is_empty() {
result = result.union(&step);
continue 'bwd;
}
}

return result;
}
Reachability::reach_bwd(self, initial)
}

/// Compute the subset of `initial` vertices that can only reach other vertices within
Expand Down Expand Up @@ -139,6 +118,7 @@ impl SymbolicAsyncGraph {
#[cfg(test)]
mod tests {
use crate::biodivine_std::traits::Set;
use crate::symbolic_async_graph::reachability::Reachability;
use crate::symbolic_async_graph::SymbolicAsyncGraph;
use crate::ExtendedBoolean::Zero;
use crate::{BooleanNetwork, ExtendedBoolean, Space};
Expand All @@ -165,6 +145,8 @@ mod tests {
let pivot = stg.unit_colored_vertices().pick_vertex();
let fwd = stg.reach_forward(&pivot);
let bwd = stg.reach_backward(&pivot);
let fwd_basic = Reachability::reach_fwd_basic(&stg, &pivot);
let bwd_basic = Reachability::reach_bwd_basic(&stg, &pivot);
let scc = fwd.intersect(&bwd);

// Should contain all cases where pivot is in an attractor.
Expand All @@ -179,6 +161,13 @@ mod tests {
// For some reason, there is only a very small number of parameter valuations
// where this is not empty -- less than in the pivot in fact.
assert!(!repeller_basin.is_empty());

assert!(pivot.is_subset(&fwd));
assert!(pivot.is_subset(&bwd));
assert!(pivot.is_subset(&scc));

assert_eq!(fwd, fwd_basic);
assert_eq!(bwd, bwd_basic);
}

#[test]
Expand Down
Loading

0 comments on commit 181b88e

Please sign in to comment.