Boolean Fomulas + CNF
This commit is contained in:
290
rsprocess/src/boolean.rs
Normal file
290
rsprocess/src/boolean.rs
Normal file
@ -0,0 +1,290 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::element::IdType;
|
||||
use crate::translator::{Formatter, PrintableWithTranslator};
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum BooleanFunction {
|
||||
#[default]
|
||||
False,
|
||||
True,
|
||||
Not(Box<BooleanFunction>),
|
||||
Variable(IdType),
|
||||
And(Box<BooleanFunction>, Box<BooleanFunction>),
|
||||
Or(Box<BooleanFunction>, Box<BooleanFunction>),
|
||||
}
|
||||
|
||||
impl PrintableWithTranslator for BooleanFunction {
|
||||
fn print(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter,
|
||||
translator: &crate::translator::Translator,
|
||||
) -> std::fmt::Result {
|
||||
use BooleanFunction::*;
|
||||
match self {
|
||||
| False => write!(f, "False"),
|
||||
| True => write!(f, "True"),
|
||||
| Not(next) =>
|
||||
write!(f, "Not({})", Formatter::from(translator, &**next)),
|
||||
| Variable(x) => write!(f, "{})", Formatter::from(translator, x)),
|
||||
| And(next1, next2) => write!(
|
||||
f,
|
||||
"And({}, {})",
|
||||
Formatter::from(translator, &**next1),
|
||||
Formatter::from(translator, &**next2)
|
||||
),
|
||||
| Or(next1, next2) => write!(
|
||||
f,
|
||||
"Or({}, {})",
|
||||
Formatter::from(translator, &**next1),
|
||||
Formatter::from(translator, &**next2)
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize,
|
||||
)]
|
||||
pub enum CNFLiteral {
|
||||
#[default]
|
||||
False,
|
||||
True,
|
||||
Variable {
|
||||
positive: bool,
|
||||
variable: IdType,
|
||||
},
|
||||
}
|
||||
|
||||
impl std::ops::Not for CNFLiteral {
|
||||
type Output = CNFLiteral;
|
||||
|
||||
fn not(self) -> Self::Output {
|
||||
match self {
|
||||
| Self::False => Self::True,
|
||||
| Self::True => Self::False,
|
||||
| Self::Variable { positive, variable } => Self::Variable {
|
||||
positive: !positive,
|
||||
variable,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CNFLiteral {
|
||||
pub fn evaluate(&self, assignments: &BTreeMap<IdType, bool>) -> bool {
|
||||
match self {
|
||||
| Self::False => false,
|
||||
| Self::True => true,
|
||||
| Self::Variable { positive, variable } =>
|
||||
if *positive {
|
||||
*assignments.get(variable).unwrap_or(&false)
|
||||
} else {
|
||||
!*assignments.get(variable).unwrap_or(&false)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PrintableWithTranslator for CNFLiteral {
|
||||
fn print(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter,
|
||||
translator: &crate::translator::Translator,
|
||||
) -> std::fmt::Result {
|
||||
use CNFLiteral::*;
|
||||
match self {
|
||||
| False => write!(f, "F"),
|
||||
| True => write!(f, "T"),
|
||||
| Variable { positive, variable } =>
|
||||
if *positive {
|
||||
write!(f, "{}", Formatter::from(translator, variable))
|
||||
} else {
|
||||
write!(f, "-{}", Formatter::from(translator, variable))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
// first vec is And, second in Or
|
||||
pub struct CNFBooleanFunction {
|
||||
pub formula: Vec<Vec<CNFLiteral>>,
|
||||
}
|
||||
|
||||
impl PrintableWithTranslator for CNFBooleanFunction {
|
||||
fn print(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter,
|
||||
translator: &crate::translator::Translator,
|
||||
) -> std::fmt::Result {
|
||||
let mut it = self.formula.iter().peekable();
|
||||
while let Some(or_formula) = it.next() {
|
||||
let mut or_it = or_formula.iter().peekable();
|
||||
write!(f, "(")?;
|
||||
while let Some(or) = or_it.next() {
|
||||
if or_it.peek().is_none() {
|
||||
write!(f, "{}", Formatter::from(translator, or))?;
|
||||
} else {
|
||||
write!(f, "{} v ", Formatter::from(translator, or))?;
|
||||
}
|
||||
}
|
||||
if it.peek().is_none() {
|
||||
write!(f, ")")?;
|
||||
} else {
|
||||
writeln!(f, ") ^")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BooleanFunction> for CNFBooleanFunction {
|
||||
fn from(source: BooleanFunction) -> Self {
|
||||
fn morgan(source: CNFBooleanFunction) -> CNFBooleanFunction {
|
||||
let temp: Vec<Vec<_>> = source
|
||||
.formula
|
||||
.into_iter()
|
||||
.map(|f| f.into_iter().map(|l| !l).collect())
|
||||
.collect();
|
||||
|
||||
let lenghts: Vec<usize> = temp.iter().map(|f| f.len()).collect();
|
||||
let mut position = vec![0; temp.len()];
|
||||
|
||||
let add_one = |position: &mut Vec<usize>| -> bool {
|
||||
let mut location: usize = 0;
|
||||
loop {
|
||||
if location >= position.len() {
|
||||
return true;
|
||||
}
|
||||
position[location] += 1;
|
||||
if position[location] >= lenghts[location] {
|
||||
position[location] = 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
location += 1;
|
||||
}
|
||||
};
|
||||
|
||||
let mut ret_val = vec![];
|
||||
loop {
|
||||
ret_val.push(
|
||||
position
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(pos, p)| temp[pos][*p])
|
||||
.collect(),
|
||||
);
|
||||
|
||||
if add_one(&mut position) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CNFBooleanFunction { formula: ret_val }
|
||||
}
|
||||
|
||||
fn helper_normalize(source: BooleanFunction) -> CNFBooleanFunction {
|
||||
match &source {
|
||||
| BooleanFunction::False => CNFBooleanFunction {
|
||||
formula: vec![vec![CNFLiteral::False]],
|
||||
},
|
||||
| BooleanFunction::True => CNFBooleanFunction {
|
||||
formula: vec![vec![CNFLiteral::True]],
|
||||
},
|
||||
| BooleanFunction::Variable(v) => CNFBooleanFunction {
|
||||
formula: vec![vec![CNFLiteral::Variable {
|
||||
positive: true,
|
||||
variable: *v,
|
||||
}]],
|
||||
},
|
||||
| BooleanFunction::And(n1, n2) => {
|
||||
let n1 = helper_normalize(*n1.clone());
|
||||
let n2 = helper_normalize(*n2.clone());
|
||||
|
||||
CNFBooleanFunction {
|
||||
formula: n1
|
||||
.formula
|
||||
.into_iter()
|
||||
.chain(n2.formula)
|
||||
.collect(),
|
||||
}
|
||||
},
|
||||
| BooleanFunction::Or(n1, n2) => {
|
||||
let n1 = helper_normalize(*n1.clone());
|
||||
let n2 = helper_normalize(*n2.clone());
|
||||
|
||||
let mut formulas = vec![];
|
||||
for formula1 in n1.formula {
|
||||
for formula2 in &n2.formula {
|
||||
formulas.push(
|
||||
formula1
|
||||
.iter()
|
||||
.chain(formula2.iter())
|
||||
.cloned()
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
}
|
||||
CNFBooleanFunction { formula: formulas }
|
||||
},
|
||||
| BooleanFunction::Not(n) => {
|
||||
if let BooleanFunction::Not(n) = &**n {
|
||||
helper_normalize(*n.clone())
|
||||
} else {
|
||||
morgan(helper_normalize(*n.clone()))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
helper_normalize(source)
|
||||
}
|
||||
}
|
||||
|
||||
impl CNFBooleanFunction {
|
||||
pub fn evaluate(&self, assignments: &BTreeMap<IdType, bool>) -> bool {
|
||||
self.formula
|
||||
.iter()
|
||||
.all(|or_f| or_f.iter().any(|l| l.evaluate(assignments)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct BooleanNetwork {
|
||||
initial_state: BTreeMap<IdType, bool>,
|
||||
update_rules: BTreeMap<IdType, BooleanFunction>,
|
||||
}
|
||||
|
||||
impl PrintableWithTranslator for BooleanNetwork {
|
||||
fn print(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter,
|
||||
translator: &crate::translator::Translator,
|
||||
) -> std::fmt::Result {
|
||||
write!(f, "Initial State: ")?;
|
||||
let mut it = self.initial_state.iter().peekable();
|
||||
while let Some((x, b)) = it.next() {
|
||||
write!(f, "({} -> {})", Formatter::from(translator, x), b)?;
|
||||
if it.peek().is_some() {
|
||||
write!(f, ",")?;
|
||||
}
|
||||
write!(f, " ")?;
|
||||
}
|
||||
|
||||
writeln!(f)?;
|
||||
writeln!(f, "Update Rules:")?;
|
||||
|
||||
for (x, bf) in self.update_rules.iter() {
|
||||
write!(
|
||||
f,
|
||||
"\t{} -> {}",
|
||||
Formatter::from(translator, x),
|
||||
Formatter::from(translator, bf)
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
420
rsprocess/src/boolean_test.rs
Normal file
420
rsprocess/src/boolean_test.rs
Normal file
@ -0,0 +1,420 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::boolean::{BooleanFunction, CNFBooleanFunction, CNFLiteral};
|
||||
use crate::element::IdType;
|
||||
|
||||
macro_rules! cnfl {
|
||||
($i:ident) => {
|
||||
CNFLiteral::$i
|
||||
};
|
||||
($p:literal, $i:literal) => {
|
||||
CNFLiteral::Variable {
|
||||
positive: $p,
|
||||
variable: $i,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! boolean {
|
||||
(False) => (BooleanFunction::False);
|
||||
(True) => (BooleanFunction::True);
|
||||
(Variable($i:literal)) => (BooleanFunction::Variable($i));
|
||||
(Not($($tail:tt)+)) => (BooleanFunction::Not(Box::new(boolean!($($tail)*))));
|
||||
(And(($($tail1:tt)+ ), ($($tail2:tt)+ ))) => (
|
||||
BooleanFunction::And(
|
||||
Box::new(boolean!($($tail1)+)),
|
||||
Box::new(boolean!($($tail2)+))
|
||||
)
|
||||
);
|
||||
(Or(($($tail1:tt)+ ), ($($tail2:tt)+ ))) => (
|
||||
BooleanFunction::Or(
|
||||
Box::new(boolean!($($tail1)+)),
|
||||
Box::new(boolean!($($tail2)+))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_1() {
|
||||
let bf = boolean!(False);
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(False)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_2() {
|
||||
let bf = boolean!(True);
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_3() {
|
||||
let bf = boolean!(Variable(1));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(true, 1)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_4() {
|
||||
let bf = boolean!(Not(True));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(False)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_5() {
|
||||
let bf = boolean!(Not(False));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_6() {
|
||||
let bf = boolean!(Not(False));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_7() {
|
||||
let bf = boolean!(Not(Not(False)));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(False)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_8() {
|
||||
let bf = boolean!(Not(Not(True)));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_9() {
|
||||
let bf = boolean!(Not(Variable(0)));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(false, 0)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_10() {
|
||||
let bf = boolean!(Not(Not(Variable(0))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(true, 0)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_11() {
|
||||
let bf = boolean!(And((True), (True)));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True)], [cnfl!(True)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_12() {
|
||||
let bf = boolean!(And((True), (False)));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True)], [cnfl!(False)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_13() {
|
||||
let bf = boolean!(And((Variable(0)), (False)));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(true, 0)], [cnfl!(False)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_14() {
|
||||
let bf = boolean!(And((Not(Variable(0))), (False)));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(false, 0)], [cnfl!(False)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_15() {
|
||||
let bf = boolean!(And((Not(Variable(0))), (Not(Not(Variable(1))))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(false, 0)], [cnfl!(true, 1)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_16() {
|
||||
let bf = boolean!(And((And((True), (True))), (Not(Not(Variable(1))))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True)], [cnfl!(True)], [cnfl!(
|
||||
true, 1
|
||||
)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_17() {
|
||||
let bf = boolean!(Not(And((False), (False))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True), cnfl!(True)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_18() {
|
||||
let bf = boolean!(Not(And((False), (True))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True), cnfl!(False)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_19() {
|
||||
let bf = boolean!(Not(And((False), (Not(True)))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True), cnfl!(True)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_20() {
|
||||
let bf = boolean!(Not(And((Variable(0)), (Not(True)))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(false, 0), cnfl!(True)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_21() {
|
||||
let bf = boolean!(Not(And((Variable(0)), (Not(And((True), (False)))))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(false, 0), cnfl!(True)], [
|
||||
cnfl!(false, 0),
|
||||
cnfl!(False)
|
||||
]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_22() {
|
||||
let bf = boolean!(And(
|
||||
(Or((Variable(0)), (Or((Not(Variable(1))), (Variable(2)))))),
|
||||
(Or((Not(Variable(3))), (Or((Variable(4)), (Variable(5))))))
|
||||
));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [
|
||||
[cnfl!(true, 0), cnfl!(false, 1), cnfl!(true, 2)],
|
||||
[cnfl!(false, 3), cnfl!(true, 4), cnfl!(true, 5)]
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_23() {
|
||||
let bf = boolean!(And((Or((Variable(0)), (Variable(1)))), (Variable(2))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [vec![cnfl!(true, 0), cnfl!(true, 1)], vec![
|
||||
cnfl!(true, 2)
|
||||
]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_24() {
|
||||
let bf = boolean!(Or((Variable(0)), (Variable(1))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(true, 0), cnfl!(true, 1)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_25() {
|
||||
let bf = boolean!(Or((Variable(0)), (Or((Variable(1)), (Variable(2))))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[
|
||||
cnfl!(true, 0),
|
||||
cnfl!(true, 1),
|
||||
cnfl!(true, 2)
|
||||
]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_26() {
|
||||
let bf = boolean!(Or(
|
||||
(Variable(0)),
|
||||
(Or((Variable(1)), (Or((Variable(2)), (Variable(3))))))
|
||||
));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[
|
||||
cnfl!(true, 0),
|
||||
cnfl!(true, 1),
|
||||
cnfl!(true, 2),
|
||||
cnfl!(true, 3)
|
||||
]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_27() {
|
||||
let bf = boolean!(Or(
|
||||
(Variable(0)),
|
||||
(Or(
|
||||
(Or((Variable(1)), (Variable(2)))),
|
||||
(Or((Variable(3)), (Variable(4))))
|
||||
))
|
||||
));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[
|
||||
cnfl!(true, 0),
|
||||
cnfl!(true, 1),
|
||||
cnfl!(true, 2),
|
||||
cnfl!(true, 3),
|
||||
cnfl!(true, 4)
|
||||
]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_28() {
|
||||
let bf = boolean!(Or((Not(Variable(0))), (Variable(1))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(false, 0), cnfl!(true, 1)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_29() {
|
||||
let bf = boolean!(Or((Not(Variable(0))), (Not(Not(Variable(1))))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(false, 0), cnfl!(true, 1)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_30() {
|
||||
let bf = boolean!(Not(Or((False), (False))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True)], [cnfl!(True)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_31() {
|
||||
let bf = boolean!(Not(Or((False), (True))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
assert_eq!(cnf.formula, [[cnfl!(True)], [cnfl!(False)]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_32() {
|
||||
let bf = boolean!(Not(Or((Variable(0)), (Not(Or((True), (False)))))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
let assignments = BTreeMap::from([(0, false)]);
|
||||
|
||||
assert!(cnf.evaluate(&assignments));
|
||||
|
||||
let assignments = BTreeMap::from([(0, true)]);
|
||||
|
||||
assert!(!cnf.evaluate(&assignments));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_33() {
|
||||
let bf = boolean!(Not(Or((Variable(0)), (Not(And((True), (False)))))));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
let assignments = BTreeMap::from([(0, false)]);
|
||||
|
||||
assert!(!cnf.evaluate(&assignments));
|
||||
|
||||
let assignments = BTreeMap::from([(0, true)]);
|
||||
|
||||
assert!(!cnf.evaluate(&assignments));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_34() {
|
||||
let bf = boolean!(Or(
|
||||
(And((Variable(0)), (Variable(1)))),
|
||||
(Or(
|
||||
(Or((Variable(2)), (Not(Variable(3))))),
|
||||
(Not(And((And((Variable(4)), (Not(Variable(5))))), (Variable(6)))))
|
||||
))
|
||||
));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
let assignments: Vec<BTreeMap<IdType, bool>> = (0_u32..128)
|
||||
.map(|p| {
|
||||
BTreeMap::from_iter(
|
||||
(0..8)
|
||||
.map(|pos| (pos, p >> pos & 1 == 1))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let correct_results = [
|
||||
true, true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, false, false, false, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true,
|
||||
];
|
||||
|
||||
for (assignment, res) in assignments.iter().zip(correct_results) {
|
||||
assert_eq!(cnf.evaluate(assignment), res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_35() {
|
||||
let bf = boolean!(Or(
|
||||
(And(
|
||||
(And(
|
||||
(Or((Variable(0)), (Or((Variable(1)), (Variable(2)))))),
|
||||
(Or((And((Variable(0)), (Not(Variable(1))))), (Variable(2))))
|
||||
)),
|
||||
(Not(Variable(2)))
|
||||
)),
|
||||
(And((Variable(2)), (Not(Or((Variable(0)), (Variable(1)))))))
|
||||
));
|
||||
let cnf: CNFBooleanFunction = bf.into();
|
||||
|
||||
let assignments: Vec<BTreeMap<IdType, bool>> = (0_u32..8)
|
||||
.map(|p| {
|
||||
BTreeMap::from_iter(
|
||||
(0..3)
|
||||
.map(|pos| (pos, p >> pos & 1 == 1))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let correct_results =
|
||||
[false, true, false, false, true, false, false, false];
|
||||
|
||||
for (assignment, res) in assignments.iter().zip(correct_results) {
|
||||
assert_eq!(cnf.evaluate(assignment), res);
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,8 @@ pub mod set;
|
||||
pub mod system;
|
||||
pub mod trace;
|
||||
|
||||
pub mod boolean;
|
||||
|
||||
pub mod dot;
|
||||
pub mod frequency;
|
||||
pub mod graph;
|
||||
@ -28,3 +30,6 @@ mod set_test;
|
||||
|
||||
#[cfg(test)]
|
||||
mod trace_test;
|
||||
|
||||
#[cfg(test)]
|
||||
mod boolean_test;
|
||||
|
||||
@ -220,6 +220,14 @@ impl From<Vec<IdType>> for Set {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<IdType> for Set {
|
||||
fn from_iter<T: IntoIterator<Item = IdType>>(iter: T) -> Self {
|
||||
Self {
|
||||
identifiers: iter.into_iter().collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Set {
|
||||
/// Converts set to positive set. All elements with the same state.
|
||||
pub fn to_positive_set(&self, state: IdState) -> PositiveSet {
|
||||
@ -775,3 +783,9 @@ impl PositiveSet {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PositiveSet> for Set {
|
||||
fn from(value: PositiveSet) -> Self {
|
||||
value.positives().iter().map(|el| *el.0).collect::<_>()
|
||||
}
|
||||
}
|
||||
|
||||
@ -742,11 +742,12 @@ impl System {
|
||||
self.context_elements.lock().unwrap().clone()
|
||||
}
|
||||
|
||||
|
||||
pub fn to_single_products(&self) -> Self {
|
||||
let mut new_sys = Self::default();
|
||||
new_sys.precomputed_context_elements(self.direct_get_context_elements());
|
||||
new_sys.precomputed_product_elements(self.direct_get_product_elements());
|
||||
new_sys
|
||||
.precomputed_context_elements(self.direct_get_context_elements());
|
||||
new_sys
|
||||
.precomputed_product_elements(self.direct_get_product_elements());
|
||||
|
||||
new_sys.delta = Arc::clone(&self.delta);
|
||||
new_sys.available_entities = self.available_entities.clone();
|
||||
@ -755,9 +756,11 @@ impl System {
|
||||
let mut new_reactions = vec![];
|
||||
for r in self.reaction_rules.iter() {
|
||||
for el in r.products.iter() {
|
||||
new_reactions.push(Reaction::from(r.reactants.clone(),
|
||||
r.inhibitors.clone(),
|
||||
[*el].into()))
|
||||
new_reactions.push(Reaction::from(
|
||||
r.reactants.clone(),
|
||||
r.inhibitors.clone(),
|
||||
[*el].into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
Arc::new(new_reactions)
|
||||
|
||||
@ -11,7 +11,7 @@ use crate::translator::Translator;
|
||||
fn slice_atoi() {
|
||||
let mut translator = Translator::new();
|
||||
|
||||
let reactions = vec![
|
||||
let reactions = [
|
||||
(
|
||||
vec!["tgfbr", "stat3", "il6r"],
|
||||
vec!["tbet", "gata3", "foxp3"],
|
||||
@ -161,7 +161,7 @@ fn slice_positive_atoi() {
|
||||
let mut translator = Translator::new();
|
||||
|
||||
let reactions = {
|
||||
let reactions = vec![
|
||||
let reactions = [
|
||||
(
|
||||
vec!["tgfbr", "stat3", "il6r"],
|
||||
vec!["tbet", "gata3", "foxp3"],
|
||||
|
||||
Reference in New Issue
Block a user