1
0
mirror of https://github.com/ellmau/adf-obdd.git synced 2025-12-19 09:29:36 +01:00

changed structure, added basic functionality for formulae and statements (adf representation)

Signed-off-by: Stefan Ellmauthaler <stefan.ellmauthaler@tu-dresden.de>
This commit is contained in:
Stefan Ellmauthaler 2021-06-23 16:02:29 +02:00
parent 7d9e99b900
commit 40ea81b417
3 changed files with 146 additions and 4 deletions

141
src/adf.rs Normal file
View File

@ -0,0 +1,141 @@
use std::{
collections::HashMap,
num::ParseFloatError,
str::{self, FromStr},
};
use super::obdd::Bdd;
struct Statement {
label: String, // label of the statement
var: usize, // variable node in bdd
ac: Option<usize>, // node in bdd
}
impl Statement {
pub fn new(label: &str, var: usize) -> Self {
Statement {
label: String::from_str(label).unwrap(),
var: var,
ac: None,
}
}
pub fn add_ac(&mut self, ac: usize) {
self.ac = Some(ac);
}
}
struct Adf {
bdd: Bdd,
stmts: Vec<Statement>,
dict: HashMap<String, usize>, // label to pos in vec
}
impl Adf {
pub fn new() -> Self {
Adf {
bdd: Bdd::new(),
stmts: Vec::new(),
dict: HashMap::new(),
}
}
fn add_statement(&mut self, statement: &str) {
if self.dict.get(statement).is_none() {
let pos = self.stmts.len();
self.stmts
.push(Statement::new(statement, self.bdd.variable(pos).clone()));
self.dict.insert(self.stmts[pos].label.to_string(), pos);
}
}
fn parseformula(&mut self, ac: &str) -> usize {
if let Some(split) = ac.find(',') {
let (l, r) = ac.split_at(split);
let rterm = self.parseformula(&r[1..r.len() - 1]);
if ac.starts_with("and(") {
let lterm = self.parseformula(&l[4..]);
self.bdd.and(lterm, rterm)
} else if ac.starts_with("or(") {
let lterm = self.parseformula(&l[3..]);
self.bdd.or(lterm, rterm)
} else if ac.starts_with("iff(") {
let lterm = self.parseformula(&l[4..]);
let neglterm = self.bdd.not(lterm);
let negrterm = self.bdd.not(rterm);
let con1 = self.bdd.and(lterm, rterm);
let con2 = self.bdd.and(neglterm, negrterm);
self.bdd.or(con1, con2)
} else {
//if ac.starts_with("xor("){
let lterm = self.parseformula(&l[4..]);
let neglterm = self.bdd.not(lterm);
let negrterm = self.bdd.not(rterm);
let con1 = self.bdd.and(neglterm, rterm);
let con2 = self.bdd.and(lterm, negrterm);
self.bdd.or(con1, con2)
}
} else {
if ac.starts_with("neg(") {
let term = self.parseformula(&ac[4..ac.len() - 1]);
self.bdd.not(term)
} else if ac.eq("c(v)") {
self.bdd.constant(true)
} else if ac.eq("c(f)") {
self.bdd.constant(false)
} else {
match self.dict.get(ac) {
Some(it) => self.stmts[*it].var,
_ => unreachable!(),
}
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn add_statement() {
let mut adf = Adf::new();
adf.add_statement("A");
adf.add_statement("B");
adf.add_statement("A");
assert_eq!(adf.stmts.len(), 2);
adf.add_statement("C");
assert_eq!(adf.stmts.len(), 3);
}
#[test]
fn parseformula(){
let mut adf = Adf::new();
adf.add_statement("a");
adf.add_statement("b");
adf.add_statement("c");
assert_eq!(adf.parseformula("and(a,or(b,c))"),6);
assert_eq!(adf.parseformula("xor(a,b)"),11);
assert_eq!(adf.parseformula("or(c(f),b)"),3); // is b
}
#[test]
#[should_panic]
fn parseformula_panic(){
let mut adf = Adf::new();
adf.add_statement("a");
adf.add_statement("b");
adf.add_statement("c");
adf.parseformula("and(a,or(b,d))");
}
}

View File

@ -1 +1,2 @@
pub mod obdd;
pub mod obdd;
pub mod adf;

View File

@ -20,7 +20,7 @@ impl std::fmt::Display for BddNode {
}
}
struct Bdd {
pub (crate) struct Bdd {
nodes: Vec<BddNode>,
hash: HashMap<BddNode, Term>,
}
@ -67,11 +67,11 @@ impl Bdd {
}
}
fn variable(&mut self, var: usize) -> Term {
pub fn variable(&mut self, var: usize) -> Term {
self.create_node(var, BDD_BOT, BDD_TOP)
}
fn constant(&self, val: bool) -> Term {
pub fn constant(&self, val: bool) -> Term {
if val {
BDD_TOP
} else {