Skip to content

Commit

Permalink
Adapt to updated lib-param-bn and lib-bdd.
Browse files Browse the repository at this point in the history
  • Loading branch information
daemontus committed Dec 14, 2020
1 parent a6eaa95 commit 5f89cf0
Show file tree
Hide file tree
Showing 18 changed files with 92 additions and 1,545 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ debug = true

[dependencies]
biodivine-lib-std = { git = "https://github.com/sybila/biodivine-lib-std.git" }
biodivine-lib-param-bn = { git = "https://github.com/sybila/biodivine-lib-param-bn.git", rev = "f9dd65e584f81debe9e17ea2c6a439070fdaf6a9" }
biodivine-lib-bdd = "0.1.0"
biodivine-lib-param-bn = { git = "https://github.com/sybila/biodivine-lib-param-bn.git", rev = "e42fc0b2dab8be4bca09e82d6fdd11768808c804" }
rocket = "0.4.6"
rayon = "1.5.0"
crossbeam = "0.8.0"
Expand Down
27 changes: 12 additions & 15 deletions src/bin/benchmark_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,28 @@ fn main() {
Ok(mut model) => {
// Check that basic properties match SBML model. But note that variables can be re-ordered...
let mut models_match =
model.graph().num_vars() == sbml_model.graph().num_vars();
if model.graph().num_vars() != sbml_model.graph().num_vars() {
model.num_vars() == sbml_model.num_vars();
if model.num_vars() != sbml_model.num_vars() {
eprintln!(
"{} != {}",
model.graph().num_vars(),
sbml_model.graph().num_vars()
model.num_vars(),
sbml_model.num_vars()
);
}
for v in model.graph().variable_ids() {
for v in model.variables() {
let regulators_in_model: HashSet<String> = model
.graph()
.regulators(v)
.into_iter()
.map(|r| model.graph().get_variable(r).get_name().clone())
.map(|r| model.get_variable_name(r).clone())
.collect();
let regulators_in_sbml_model: HashSet<String> = sbml_model
.graph()
.regulators(
sbml_model
.graph()
.find_variable(model.graph().get_variable(v).get_name())
sbml_model.as_graph()
.find_variable(model.get_variable_name(v))
.unwrap(),
)
.into_iter()
.map(|r| sbml_model.graph().get_variable(r).get_name().clone())
.map(|r| sbml_model.get_variable_name(r).clone())
.collect();
if regulators_in_model != regulators_in_sbml_model {
eprintln!(
Expand All @@ -105,7 +102,7 @@ fn main() {
}
// Check that all update functions are set (for non-parametrized model anyway).
let mut model_ok = true;
for v in model.graph().variable_ids() {
for v in model.variables() {
let function = model.get_update_function(v);
if function.is_none() {
model_ok = false;
Expand All @@ -128,11 +125,11 @@ fn main() {
let graph = SymbolicAsyncGraph::new(model);
match graph {
Ok(graph) => {
if graph.unit_colors().cardinality() != 1.0 {
if graph.unit_colors().approx_cardinality() != 1.0 {
errors += 1;
eprintln!(
"ERROR: Default model has {} colors in {}.",
graph.unit_colors().cardinality(),
graph.unit_colors().approx_cardinality(),
bench_dir.path().display()
);
}
Expand Down
15 changes: 5 additions & 10 deletions src/bin/experiment.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use biodivine_aeon_server::scc::algo_symbolic_components::{components, components_2};
use biodivine_aeon_server::scc::algo_symbolic_components::{components_2};
use biodivine_aeon_server::scc::{Classifier, ProgressTracker};
use biodivine_lib_param_bn::symbolic_async_graph::SymbolicAsyncGraph;
use biodivine_lib_param_bn::BooleanNetwork;
use std::convert::TryFrom;
use std::io::Read;
use std::sync::atomic::AtomicBool;
use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
Expand All @@ -17,22 +16,18 @@ fn main() {
.as_millis();

let model = BooleanNetwork::try_from(buffer.as_str()).unwrap();
let names: Vec<_> = model
.graph()
.variable_ids()
.map(|id| model.graph().get_variable(id).clone())
.collect();
let names: Vec<_> = model.variables().map(|id| model.get_variable_name(id)).collect();
println!("Model loaded...");
println!("{} variables: {:?}", model.graph().num_vars(), names);
println!("{} variables: {:?}", model.num_vars(), names);

let graph = SymbolicAsyncGraph::new(model).unwrap();

println!("Asynchronous graph ready...");
println!(
"Admissible parametrisations: {}",
graph.unit_colors().cardinality()
graph.unit_colors().approx_cardinality()
);
println!("State space: {}", graph.unit_vertices().cardinality());
println!("State space: {}", graph.unit_vertices().approx_cardinality());

let classifier = Classifier::new(&graph);
let progress = ProgressTracker::new(&graph);
Expand Down
57 changes: 24 additions & 33 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ use biodivine_lib_param_bn::{BooleanNetwork, FnUpdate};
use regex::Regex;
use std::convert::TryFrom;

mod test_main;

use biodivine_lib_param_bn::symbolic_async_graph::{GraphColors, SymbolicAsyncGraph};
use biodivine_lib_std::collections::bitvectors::{ArrayBitVector, BitVector};
use rocket::config::Environment;
Expand Down Expand Up @@ -95,25 +93,25 @@ fn check_update_function(data: Data) -> BackendResponse {
let graph = BooleanNetwork::try_from(model_string.as_str())
.and_then(|model| {
let mut max_size = 0;
for v in model.graph().variable_ids() {
for v in model.variables() {
if let Some(update_function) = model.get_update_function(v) {
max_size = max(max_size, max_parameter_cardinality(update_function));
} else {
max_size = max(max_size, model.graph().regulators(v).len())
max_size = max(max_size, model.regulators(v).len())
}
}
if max_size <= 4 {
println!(
"Start partial function analysis. {} variables and complexity {}.",
model.graph().num_vars(),
model.num_vars(),
max_size
);
SymbolicAsyncGraph::new(model)
} else {
Err("Function too large for on-the-fly analysis.".to_string())
}
})
.map(|g| g.unit_colors().cardinality());
.map(|g| g.unit_colors().approx_cardinality());
println!(
"Elapsed: {}, result {:?}",
start.elapsed().unwrap().as_millis(),
Expand Down Expand Up @@ -231,7 +229,7 @@ fn get_results() -> BackendResponse {
};
let lines: Vec<String> = data
.iter()
.map(|(c, p)| format!("{{\"sat_count\":{},\"phenotype\":{}}}", p.cardinality(), c))
.map(|(c, p)| format!("{{\"sat_count\":{},\"phenotype\":{}}}", p.approx_cardinality(), c))
.collect();

println!("Result {:?}", lines);
Expand Down Expand Up @@ -274,7 +272,7 @@ fn get_witness(class_str: String) -> BackendResponse {
if let Some(has_class) = try_get_class_params(classifier, &class) {
if let Some(class) = has_class {
if let Some(graph) = &cmp.graph {
let witness = graph.make_witness(&class);
let witness = graph.pick_witness(&class);
let layout = read_layout(cmp.input_model.as_str());
let mut model_string = format!("{}", witness); // convert back to aeon
model_string += "\n";
Expand Down Expand Up @@ -333,18 +331,15 @@ fn get_attractors(class_str: String) -> BackendResponse {
if let Some(has_class) = try_get_class_params(classifier, &class) {
if let Some(class) = has_class {
if let Some(graph) = &cmp.graph {
let witness_colour = class.pick_color(graph).unwrap();
let witness_network: BooleanNetwork = graph.make_witness(&class);
let witness_colour = class.pick_singleton();
let witness_network: BooleanNetwork = graph.pick_witness(&witness_colour);
let witness_graph =
SymbolicAsyncGraph::new(witness_network.clone()).unwrap();
let witness_str = witness_network.to_string();
let witness_attractors = classifier.attractors(&witness_colour, graph);
let witness_attractors = classifier.attractors(&witness_colour);
let variable_name_strings =
witness_network.graph().variable_ids().map(|id| {
format!(
"\"{}\"",
witness_network.graph().get_variable(id).get_name()
)
witness_network.variables().map(|id| {
format!("\"{}\"", witness_network.get_variable_name(id))
});

let mut all_attractors: Vec<(
Expand All @@ -361,40 +356,36 @@ fn get_attractors(class_str: String) -> BackendResponse {
println!(
"Attractor {:?} state count: {}",
behaviour,
attractor.cardinality()
attractor.approx_cardinality()
);
if attractor.cardinality() >= 2_000.0 {
return BackendResponse::err(&format!("Attractor has {} states. Visualisation size limit exceeded.", attractor.cardinality()));
if attractor.approx_cardinality() >= 2_000.0 {
return BackendResponse::err(&format!("Attractor has {} states. Visualisation size limit exceeded.", attractor.approx_cardinality()));
}
let mut attractor_graph: Vec<(ArrayBitVector, ArrayBitVector)> =
Vec::new();
let mut not_fixed_vars: HashSet<usize> = HashSet::new();
if *behaviour == Behaviour::Stability {
// This is a sink - no edges
assert_eq!(attractor.states(&graph).count(), 1);
let sink: ArrayBitVector =
attractor.states(&graph).next().unwrap();
assert_eq!(attractor.materialize().iter().count(), 1);
let sink: ArrayBitVector = attractor.materialize().iter().next().unwrap();
attractor_graph.push((sink.clone(), sink));
for i in 0..witness_network.graph().num_vars() {
for i in 0..witness_network.num_vars() {
// In sink, we mark everything as "not-fixed" because we want to just display it normally.
not_fixed_vars.insert(i);
}
} else {
for source in attractor.states(&graph) {
for source in attractor.materialize().iter() {
let source_set = witness_graph.vertex(&source);
let mut target_set = witness_graph.empty_vertices().clone();
for v in witness_graph.network().graph().variable_ids() {
let post = witness_graph.any_post(v, &source_set);
let mut target_set = witness_graph.mk_empty_vertices();
for v in witness_graph.network().variables() {
let post = witness_graph.var_post(v, &source_set);
if !post.is_empty() {
not_fixed_vars.insert(v.into());
target_set = target_set.union(&post);
}
}

for target in target_set
.state_projection(&witness_graph)
.states(&witness_graph)
{
for target in target_set.vertices().materialize().iter() {
attractor_graph.push((source.clone(), target));
}
}
Expand Down Expand Up @@ -548,7 +539,7 @@ fn start_computation(data: Data) -> BackendResponse {

// Now we can actually start the computation...
biodivine_aeon_server::scc::algo_symbolic_components::components(&graph, &progress, &*cancelled, |component| {
println!("Component {}", component.cardinality());
println!("Component {}", component.approx_cardinality());
classifier.add_component(component, &graph);
});

Expand Down Expand Up @@ -729,7 +720,7 @@ fn aeon_to_sbml_instantiated(data: Data) -> BackendResponse {
.and_then(|bn| SymbolicAsyncGraph::new(bn))
{
Ok(graph) => {
let witness = graph.make_witness(graph.unit_colors());
let witness = graph.pick_witness(graph.unit_colors());
let layout = read_layout(&aeon_string);
BackendResponse::ok(
&object! { "model" => witness.to_sbml(&layout) }.to_string(),
Expand Down
File renamed without changes.
37 changes: 17 additions & 20 deletions src/scc/impl_classifier.rs → src/scc/_impl_classifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,8 @@ impl Classifier {
pub fn attractors(
&self,
witness_colour: &GraphColors,
graph: &SymbolicAsyncGraph,
) -> Vec<(GraphVertices, Behaviour)> {
if witness_colour.cardinality() != 1.0 {
if witness_colour.approx_cardinality() != 1.0 {
eprintln!("WARNING: Computing attractor witnesses for non-singleton set. (This may be just a floating point error in large models).");
}
let mut result = Vec::new();
Expand All @@ -86,7 +85,7 @@ impl Classifier {
if attractor_states.is_empty() {
continue;
}
let attractor_states = attractor_states.state_projection(graph);
let attractor_states = attractor_states.vertices();
let attractor_behaviour = behaviour
.iter()
.find(|(_, c)| witness_colour.is_subset(c))
Expand All @@ -102,32 +101,32 @@ impl Classifier {
pub fn add_component(&self, component: GraphColoredVertices, graph: &SymbolicAsyncGraph) {
let mut component_classification = HashMap::new();
let without_sinks = self.filter_sinks(component.clone(), graph);
let not_sink_params = without_sinks.color_projection(graph);
let sink_params = component.color_projection(graph).minus(&not_sink_params);
let not_sink_params = without_sinks.colors();
let sink_params = component.colors().minus(&not_sink_params);
if !sink_params.is_empty() {
component_classification.insert(Behaviour::Stability, sink_params);
}
if !not_sink_params.is_empty() {
let mut disorder = graph.empty_colors().clone();
for variable in graph.network().graph().variable_ids() {
let found_first_successor = &graph.has_any_post(variable, &without_sinks);
for next_variable in graph.network().graph().variable_ids() {
let mut disorder = graph.mk_empty_colors();
for variable in graph.network().variables() {
let found_first_successor = &graph.var_can_post(variable, &without_sinks);
for next_variable in graph.network().variables() {
if next_variable == variable {
continue;
}
let found_second_successor =
&graph.has_any_post(next_variable, &found_first_successor);
disorder = disorder.union(&found_second_successor.color_projection(graph));
&graph.var_can_post(next_variable, &found_first_successor);
disorder = disorder.union(&found_second_successor.colors());
}
}
let cycle = without_sinks.color_projection(graph).minus(&disorder);
let cycle = without_sinks.colors().minus(&disorder);
if !cycle.is_empty() {
println!("Found cycle: {}", cycle.cardinality());
println!("Found cycle: {}", cycle.approx_cardinality());
component_classification.insert(Behaviour::Oscillation, cycle.clone());
self.push(Behaviour::Oscillation, cycle);
}
if !disorder.is_empty() {
println!("Found disorder: {}", disorder.cardinality());
println!("Found disorder: {}", disorder.approx_cardinality());
component_classification.insert(Behaviour::Disorder, disorder.clone());
self.push(Behaviour::Disorder, disorder);
}
Expand Down Expand Up @@ -172,7 +171,7 @@ impl Classifier {
pub fn print(&self) {
let classes = self.classes.lock().unwrap();
for (c, p) in &(*classes) {
println!("Class {:?}, cardinality: {}", c, p.cardinality());
println!("Class {:?}, cardinality: {}", c, p.approx_cardinality());
}
}

Expand All @@ -184,15 +183,13 @@ impl Classifier {
graph: &SymbolicAsyncGraph,
) -> GraphColoredVertices {
let mut is_not_sink = graph.empty_vertices().clone();
for variable in graph.network().graph().variable_ids() {
let has_successor = &graph.has_any_post(variable, &component);
for variable in graph.network().variables() {
let has_successor = &graph.var_can_post(variable, &component);
if !has_successor.is_empty() {
is_not_sink = is_not_sink.union(has_successor);
}
}
let is_sink = component
.color_projection(graph)
.minus(&is_not_sink.color_projection(graph));
let is_sink = component.colors().minus(&is_not_sink.colors());
if !is_sink.is_empty() {
self.push(Behaviour::Stability, is_sink);
}
Expand Down
Loading

0 comments on commit 5f89cf0

Please sign in to comment.