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:
parent
7d9e99b900
commit
40ea81b417
141
src/adf.rs
Normal file
141
src/adf.rs
Normal 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))");
|
||||
}
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
pub mod obdd;
|
||||
pub mod obdd;
|
||||
pub mod adf;
|
||||
@ -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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user