1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use biodivine_lib_param_bn::{BooleanNetwork, FnUpdate, VariableId};
use std::convert::TryFrom;
use std::io::Read;
fn main() {
let mut buffer = String::new();
std::io::stdin().read_to_string(&mut buffer).unwrap();
let mut model = BooleanNetwork::try_from(buffer.as_str()).unwrap();
for var in model.variables() {
flatten_update_function(&mut model, var);
}
println!("{}", model.to_bnet(false).unwrap());
}
fn flatten_update_function(network: &mut BooleanNetwork, variable: VariableId) {
if network.regulators(variable).is_empty() {
return;
}
let flattened = if let Some(function) = network.get_update_function(variable) {
let function = function.clone();
flatten_fn_update(network, &function)
} else {
let regulators = network.regulators(variable);
let name = format!("{}_", network.get_variable_name(variable));
explode_function(network, ®ulators, name)
};
network
.set_update_function(variable, Some(flattened))
.unwrap();
}
fn flatten_fn_update(network: &mut BooleanNetwork, update: &FnUpdate) -> FnUpdate {
match update {
FnUpdate::Const(value) => FnUpdate::Const(*value),
FnUpdate::Var(id) => FnUpdate::Var(*id),
FnUpdate::Not(update) => flatten_fn_update(network, update).negation(),
FnUpdate::Param(id, args) => {
let name = network.get_parameter(*id).get_name().clone();
explode_function(network, args, format!("{}_", name))
}
FnUpdate::Binary(op, left, right) => FnUpdate::Binary(
*op,
Box::new(flatten_fn_update(network, left)),
Box::new(flatten_fn_update(network, right)),
),
}
}
fn explode_function(
network: &mut BooleanNetwork,
regulators: &[VariableId],
name_prefix: String,
) -> FnUpdate {
if regulators.is_empty() {
let parameter = network.find_parameter(name_prefix.as_str());
let parameter =
parameter.unwrap_or_else(|| network.add_parameter(name_prefix.as_str(), 0).unwrap());
FnUpdate::Param(parameter, Vec::new())
} else {
let regulator = regulators[0];
let true_branch = explode_function(network, ®ulators[1..], format!("{}1", name_prefix));
let false_branch = explode_function(network, ®ulators[1..], format!("{}0", name_prefix));
let var = FnUpdate::Var(regulator);
var.clone()
.implies(true_branch)
.and(var.negation().implies(false_branch))
}
}