mirror of
https://github.com/ellmau/adf-obdd.git
synced 2025-12-19 09:29:36 +01:00
Feature/multiple heuristics (#48)
* Make two_val_model_counts_logic generic in heuristic * Update API and provide two different heuristics * Increment patch-version of lib and binary Co-authored-by: Maximilian Marx <mmarx@wh2.tu-dresden.de>
This commit is contained in:
parent
7e66d89d03
commit
6c116509c6
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -4,7 +4,7 @@ version = 3
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "adf_bdd"
|
name = "adf_bdd"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"biodivine-lib-bdd",
|
"biodivine-lib-bdd",
|
||||||
"derivative",
|
"derivative",
|
||||||
@ -21,7 +21,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "adf_bdd-solver"
|
name = "adf_bdd-solver"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adf_bdd",
|
"adf_bdd",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "adf_bdd-solver"
|
name = "adf_bdd-solver"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
authors = ["Stefan Ellmauthaler <stefan.ellmauthaler@tu-dresden.de>"]
|
authors = ["Stefan Ellmauthaler <stefan.ellmauthaler@tu-dresden.de>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "GPL-3.0-only"
|
license = "GPL-3.0-only"
|
||||||
|
|||||||
@ -105,9 +105,12 @@ struct App {
|
|||||||
/// Compute the stable models
|
/// Compute the stable models
|
||||||
#[clap(long = "stm")]
|
#[clap(long = "stm")]
|
||||||
stable: bool,
|
stable: bool,
|
||||||
/// Compute the stable models with the help of modelcounting
|
/// Compute the stable models with the help of modelcounting using heuristics a
|
||||||
#[clap(long = "stmc")]
|
#[clap(long = "stmca")]
|
||||||
stable_counting: bool,
|
stable_counting_a: bool,
|
||||||
|
/// Compute the stable models with the help of modelcounting using heuristics b
|
||||||
|
#[clap(long = "stmcb")]
|
||||||
|
stable_counting_b: bool,
|
||||||
/// Compute the stable models with a pre-filter (only hybrid lib-mode)
|
/// Compute the stable models with a pre-filter (only hybrid lib-mode)
|
||||||
#[clap(long = "stmpre")]
|
#[clap(long = "stmpre")]
|
||||||
stable_pre: bool,
|
stable_pre: bool,
|
||||||
@ -218,8 +221,14 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.stable_counting {
|
if self.stable_counting_a {
|
||||||
for model in naive_adf.stable_count_optimisation() {
|
for model in naive_adf.stable_count_optimisation_heu_a() {
|
||||||
|
print!("{}", printer.print_interpretation(&model));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.stable_counting_b {
|
||||||
|
for model in naive_adf.stable_count_optimisation_heu_b() {
|
||||||
print!("{}", printer.print_interpretation(&model));
|
print!("{}", printer.print_interpretation(&model));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "adf_bdd"
|
name = "adf_bdd"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
authors = ["Stefan Ellmauthaler <stefan.ellmauthaler@tu-dresden.de>"]
|
authors = ["Stefan Ellmauthaler <stefan.ellmauthaler@tu-dresden.de>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/ellmau/adf-obdd/"
|
repository = "https://github.com/ellmau/adf-obdd/"
|
||||||
|
|||||||
@ -351,14 +351,32 @@ impl Adf {
|
|||||||
|
|
||||||
/// Computes the stable models.
|
/// Computes the stable models.
|
||||||
/// Returns an iterator which contains all stable models.
|
/// Returns an iterator which contains all stable models.
|
||||||
/// This variant uses the computation of model and counter-model counts.
|
/// This variant uses the heuristic, which uses maximal var impact, minimal self-cyclye impact and the minimal amount of paths .
|
||||||
pub fn stable_count_optimisation<'a, 'c>(&'a mut self) -> impl Iterator<Item = Vec<Term>> + 'c
|
pub fn stable_count_optimisation_heu_a<'a, 'c>(
|
||||||
|
&'a mut self,
|
||||||
|
) -> impl Iterator<Item = Vec<Term>> + 'c
|
||||||
where
|
where
|
||||||
'a: 'c,
|
'a: 'c,
|
||||||
{
|
{
|
||||||
log::debug!("[Start] stable count optimisation");
|
log::debug!("[Start] stable count optimisation");
|
||||||
let grounded = self.grounded();
|
let grounded = self.grounded();
|
||||||
self.two_val_model_counts(&grounded)
|
self.two_val_model_counts(&grounded, Self::heu_max_imp_min_nacyc_impact_min_paths)
|
||||||
|
.into_iter()
|
||||||
|
.filter(|int| self.stability_check(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the stable models.
|
||||||
|
/// Returns an iterator which contains all stable models.
|
||||||
|
/// This variant uses the heuristic, which uses minimal number of paths and maximal variable-impact.
|
||||||
|
pub fn stable_count_optimisation_heu_b<'a, 'c>(
|
||||||
|
&'a mut self,
|
||||||
|
) -> impl Iterator<Item = Vec<Term>> + 'c
|
||||||
|
where
|
||||||
|
'a: 'c,
|
||||||
|
{
|
||||||
|
log::debug!("[Start] stable count optimisation");
|
||||||
|
let grounded = self.grounded();
|
||||||
|
self.two_val_model_counts(&grounded, Self::heu_min_paths_max_imp)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|int| self.stability_check(int))
|
.filter(|int| self.stability_check(int))
|
||||||
}
|
}
|
||||||
@ -387,11 +405,14 @@ impl Adf {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn two_val_model_counts(&mut self, interpr: &[Term]) -> Vec<Vec<Term>> {
|
fn two_val_model_counts<H>(&mut self, interpr: &[Term], heuristic: H) -> Vec<Vec<Term>>
|
||||||
self.two_val_model_counts_logic(interpr, &vec![Term::UND; interpr.len()], 0)
|
where
|
||||||
|
H: Fn(&Self, (Var, Term), (Var, Term), &[Term]) -> std::cmp::Ordering + Copy,
|
||||||
|
{
|
||||||
|
self.two_val_model_counts_logic(interpr, &vec![Term::UND; interpr.len()], 0, heuristic)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn heuristic1(
|
fn heu_max_imp_min_nacyc_impact_min_paths(
|
||||||
&self,
|
&self,
|
||||||
lhs: (Var, Term),
|
lhs: (Var, Term),
|
||||||
rhs: (Var, Term),
|
rhs: (Var, Term),
|
||||||
@ -417,19 +438,50 @@ impl Adf {
|
|||||||
value => value,
|
value => value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn two_val_model_counts_logic(
|
|
||||||
|
fn heu_min_paths_max_imp(
|
||||||
|
&self,
|
||||||
|
lhs: (Var, Term),
|
||||||
|
rhs: (Var, Term),
|
||||||
|
interpr: &[Term],
|
||||||
|
) -> std::cmp::Ordering {
|
||||||
|
match self
|
||||||
|
.bdd
|
||||||
|
.paths(lhs.1, true)
|
||||||
|
.minimum()
|
||||||
|
.cmp(&self.bdd.paths(rhs.1, true).minimum())
|
||||||
|
{
|
||||||
|
std::cmp::Ordering::Equal => self
|
||||||
|
.bdd
|
||||||
|
.var_impact(rhs.0, interpr)
|
||||||
|
.cmp(&self.bdd.var_impact(lhs.0, interpr)),
|
||||||
|
|
||||||
|
value => value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn two_val_model_counts_logic<H>(
|
||||||
&mut self,
|
&mut self,
|
||||||
interpr: &[Term],
|
interpr: &[Term],
|
||||||
will_be: &[Term],
|
will_be: &[Term],
|
||||||
depth: usize,
|
depth: usize,
|
||||||
) -> Vec<Vec<Term>> {
|
heuristic: H,
|
||||||
|
) -> Vec<Vec<Term>>
|
||||||
|
where
|
||||||
|
H: Fn(&Self, (Var, Term), (Var, Term), &[Term]) -> std::cmp::Ordering + Copy,
|
||||||
|
{
|
||||||
log::debug!("two_val_model_recursion_depth: {}/{}", depth, interpr.len());
|
log::debug!("two_val_model_recursion_depth: {}/{}", depth, interpr.len());
|
||||||
if let Some((idx, ac)) = interpr
|
if let Some((idx, ac)) = interpr
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|(idx, val)| !(val.is_truth_value() || will_be[*idx].is_truth_value()))
|
.filter(|(idx, val)| !(val.is_truth_value() || will_be[*idx].is_truth_value()))
|
||||||
.min_by(|(idx_a, val_a), (idx_b, val_b)| {
|
.min_by(|(idx_a, val_a), (idx_b, val_b)| {
|
||||||
self.heuristic1((Var(*idx_a), **val_a), (Var(*idx_b), **val_b), interpr)
|
heuristic(
|
||||||
|
self,
|
||||||
|
(Var(*idx_a), **val_a),
|
||||||
|
(Var(*idx_b), **val_b),
|
||||||
|
interpr,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
@ -473,6 +525,7 @@ impl Adf {
|
|||||||
&upd_int,
|
&upd_int,
|
||||||
will_be,
|
will_be,
|
||||||
depth + 1,
|
depth + 1,
|
||||||
|
heuristic,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -497,6 +550,7 @@ impl Adf {
|
|||||||
&upd_int,
|
&upd_int,
|
||||||
&must_be_new,
|
&must_be_new,
|
||||||
depth + 1,
|
depth + 1,
|
||||||
|
heuristic,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -785,7 +839,7 @@ mod test {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let mut adf = Adf::from_parser(&parser);
|
let mut adf = Adf::from_parser(&parser);
|
||||||
|
|
||||||
let mut stable = adf.stable_count_optimisation();
|
let mut stable = adf.stable_count_optimisation_heu_a();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stable.next(),
|
stable.next(),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
@ -801,7 +855,7 @@ mod test {
|
|||||||
let parser = AdfParser::default();
|
let parser = AdfParser::default();
|
||||||
parser.parse()("s(a).s(b).ac(a,neg(b)).ac(b,neg(a)).").unwrap();
|
parser.parse()("s(a).s(b).ac(a,neg(b)).ac(b,neg(a)).").unwrap();
|
||||||
let mut adf = Adf::from_parser(&parser);
|
let mut adf = Adf::from_parser(&parser);
|
||||||
let mut stable = adf.stable_count_optimisation();
|
let mut stable = adf.stable_count_optimisation_heu_a();
|
||||||
|
|
||||||
assert_eq!(stable.next(), Some(vec![Term::BOT, Term::TOP]));
|
assert_eq!(stable.next(), Some(vec![Term::BOT, Term::TOP]));
|
||||||
assert_eq!(stable.next(), Some(vec![Term::TOP, Term::BOT]));
|
assert_eq!(stable.next(), Some(vec![Term::TOP, Term::BOT]));
|
||||||
@ -812,14 +866,20 @@ mod test {
|
|||||||
let mut adf = Adf::from_parser(&parser);
|
let mut adf = Adf::from_parser(&parser);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
adf.stable_count_optimisation().collect::<Vec<_>>(),
|
adf.stable_count_optimisation_heu_a().collect::<Vec<_>>(),
|
||||||
|
vec![vec![Term::BOT, Term::BOT]]
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
adf.stable_count_optimisation_heu_b().collect::<Vec<_>>(),
|
||||||
vec![vec![Term::BOT, Term::BOT]]
|
vec![vec![Term::BOT, Term::BOT]]
|
||||||
);
|
);
|
||||||
|
|
||||||
let parser = AdfParser::default();
|
let parser = AdfParser::default();
|
||||||
parser.parse()("s(a).s(b).ac(a,neg(a)).ac(b,a).").unwrap();
|
parser.parse()("s(a).s(b).ac(a,neg(a)).ac(b,a).").unwrap();
|
||||||
let mut adf = Adf::from_parser(&parser);
|
let mut adf = Adf::from_parser(&parser);
|
||||||
assert_eq!(adf.stable_count_optimisation().next(), None);
|
assert_eq!(adf.stable_count_optimisation_heu_a().next(), None);
|
||||||
|
assert_eq!(adf.stable_count_optimisation_heu_b().next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user