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

Add closure of conclusions of an interpretation and a NoGoodStore

This commit is contained in:
Stefan Ellmauthaler 2022-06-17 13:43:35 +02:00
parent 4eb54e79d9
commit 8059590fc0
Failed to extract signature

View File

@ -71,6 +71,7 @@ impl NoGood {
} }
/// Creates an updated [Vec<Term>], based on the given [&[Term]] and the [NoGood]. /// Creates an updated [Vec<Term>], based on the given [&[Term]] and the [NoGood].
/// The parameter _update_ is set to [`true`] if there has been an update and to [`false`] otherwise
pub fn update_term_vec(&self, term_vec: &[Term], update: &mut bool) -> Vec<Term> { pub fn update_term_vec(&self, term_vec: &[Term], update: &mut bool) -> Vec<Term> {
*update = false; *update = false;
term_vec.iter().enumerate().map(|(idx,val)|{ term_vec.iter().enumerate().map(|(idx,val)|{
@ -205,6 +206,7 @@ impl NoGoodStore {
} }
/// Draws a (Conclusion)[NoGood], based on the [NoGoodstore] and the given [NoGood]. /// Draws a (Conclusion)[NoGood], based on the [NoGoodstore] and the given [NoGood].
/// *Returns* [None] if there is a conflict
pub fn conclusions(&self, nogood: &NoGood) -> Option<NoGood> { pub fn conclusions(&self, nogood: &NoGood) -> Option<NoGood> {
let mut result = nogood.clone(); let mut result = nogood.clone();
self.store self.store
@ -236,6 +238,25 @@ impl NoGoodStore {
} }
Some(result) Some(result)
} }
/// Constructs the Closure of the conclusions drawn by the nogoods with respect to the given `interpretation`
pub(crate) fn conclusion_closure(&self, interpretation: &[Term]) -> ClosureResult {
let mut update = true;
let mut result = match self.conclusions(&interpretation.into()) {
Some(val) => val.update_term_vec(interpretation, &mut update),
None => return ClosureResult::Inconsistent,
};
if !update {
return ClosureResult::NoUpdate;
}
while update {
match self.conclusions(&result.as_slice().into()) {
Some(val) => result = val.update_term_vec(&result, &mut update),
None => return ClosureResult::Inconsistent,
}
}
ClosureResult::Update(result)
}
} }
/// Allows to define how costly the DuplicateElemination is done. /// Allows to define how costly the DuplicateElemination is done.
@ -249,6 +270,40 @@ pub enum DuplicateElemination {
Subsume, Subsume,
} }
/// If the closure had some issues, it is represented with this enum
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum ClosureResult {
Update(Vec<Term>),
NoUpdate,
Inconsistent,
}
impl ClosureResult {
pub fn is_update(&self) -> bool {
matches!(self, Self::Update(_))
}
pub fn is_no_update(&self) -> bool {
matches!(self, Self::NoUpdate)
}
pub fn is_inconsistent(&self) -> bool {
matches!(self, Self::Inconsistent)
}
}
impl TryInto<Vec<Term>> for ClosureResult {
type Error = &'static str;
fn try_into(self) -> Result<Vec<Term>, Self::Error> {
match self {
ClosureResult::Update(val) => Ok(val),
ClosureResult::NoUpdate => Err("No update occurred, use the old value instead"),
ClosureResult::Inconsistent => Err("Inconsistency occurred"),
}
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@ -585,4 +640,82 @@ mod test {
assert_eq!(ngs.conclusions(&interpr.as_slice().into()), None); assert_eq!(ngs.conclusions(&interpr.as_slice().into()), None);
} }
#[test]
fn conclusion_closure() {
let mut ngs = NoGoodStore::new(10);
ngs.add_ng([Term::BOT].as_slice().into());
ngs.add_ng(
[Term::TOP, Term::BOT, Term(33), Term::TOP]
.as_slice()
.into(),
);
ngs.add_ng(
[Term::TOP, Term::BOT, Term(33), Term(33), Term::BOT]
.as_slice()
.into(),
);
ngs.add_ng([Term::TOP, Term::TOP].as_slice().into());
let interpr: Vec<Term> = vec![
Term(123),
Term(233),
Term(345),
Term(456),
Term(567),
Term(678),
Term(789),
Term(899),
Term(999),
Term(1000),
];
let result = ngs.conclusion_closure(&interpr);
assert!(result.is_update());
let resultint: Vec<Term> = result.try_into().expect("just checked conversion");
assert_eq!(
resultint,
vec![
Term::TOP,
Term::BOT,
Term(345),
Term::BOT,
Term::TOP,
Term(678),
Term(789),
Term(899),
Term(999),
Term(1000)
]
);
let result_no_upd = ngs.conclusion_closure(&resultint);
assert!(result_no_upd.is_no_update());
assert_eq!(
<ClosureResult as TryInto<Vec<Term>>>::try_into(result_no_upd)
.expect_err("just checked that it is an error"),
"No update occurred, use the old value instead"
);
let inconsistent_interpr = vec![
Term::TOP,
Term::TOP,
Term::BOT,
Term::BOT,
Term(111),
Term(678),
Term(789),
Term(899),
Term(999),
Term(1000),
];
let result_inconsistent = ngs.conclusion_closure(&inconsistent_interpr);
assert!(result_inconsistent.is_inconsistent());
assert_eq!(
<ClosureResult as TryInto<Vec<Term>>>::try_into(result_inconsistent)
.expect_err("just checked that it is an error"),
"Inconsistency occurred"
);
}
} }