mirror of
https://github.com/ellmau/adf-obdd.git
synced 2025-12-19 09:29:36 +01:00
* Add NoGood and NoGoodStore (#65) * Update Flake to nix 22.05 * Add nogood-algorithm to the ADF * Add public api for the nogood-learner * Add direnv to gitignore * Avoid a Box, support custom heuristics functions * Add ng option with heu to binary * Introduce a new flag to handle big instances (modelcount vs adhoccount) Note that adhoccount without modelcount will not produce correct modelcounts if memoization is used * Add new heuristic * Add crossbeam-channel to represent an output-stream of stable models Uses a crossbeam-channel to fill a Queue, which can be used safely from outside the function. This rework is done to also allow ad-hoc output of results in a potentially multi-threaded setup. * Added documentation on this new feature on the module-page * Fix broken links in rust-doc * Update Readme for lib to reflect the new NoGood API * Add metadata to bin/Cargo.toml, add features * added a benchmark feature, to easily compile benchmark-releases * Fix facet count tests * Add multithread-safe functionality for the dictionary/ordering * Streamline a couple of API calls * Expose more structs and methods to the public API * Breaking some API (though nothing which is currently used in the binary) * Simple version of gh pages * Added more links and information to the landing page * Fix badges in the app-doc * Add two valued interpretation Parameterised the stable-nogood algorithm to allow a variable stability check function. * Refactor nogood-algorithm name * Update README.md and documentation (`docu` folder) `README.md` on the `/` level is now presenting the same information which is provided in `docs/index.md` * Update main - Update main functionality - Update naming * Fix cli-test * Update Version to 0.3.0 Due to braking API changes and reaching a milestone, the version is incremented to 0.3.0 (beta) * Update Documentation navigation (#81) * flake.lock: Update Flake lock file updates: • Updated input 'flake-utils': 'github:numtide/flake-utils/1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1' (2022-05-30) → 'github:numtide/flake-utils/7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249' (2022-07-04) • Updated input 'gitignoresrc': 'github:hercules-ci/gitignore.nix/bff2832ec341cf30acb3a4d3e2e7f1f7b590116a' (2022-03-05) → 'github:hercules-ci/gitignore.nix/f2ea0f8ff1bce948ccb6b893d15d5ea3efaf1364' (2022-07-21) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/8b538fcb329a7bc3d153962f17c509ee49166973' (2022-06-15) → 'github:NixOS/nixpkgs/e43cf1748462c81202a32b26294e9f8eefcc3462' (2022-08-01) • Updated input 'nixpkgs-unstable': 'github:NixOS/nixpkgs/b1957596ff1c7aa8c55c4512b7ad1c9672502e8e' (2022-06-15) → 'github:NixOS/nixpkgs/7b9be38c7250b22d829ab6effdee90d5e40c6e5c' (2022-07-30) • Updated input 'rust-overlay': 'github:oxalica/rust-overlay/9eea93067eff400846c36f57b7499df9ef428ba0' (2022-06-17) → 'github:oxalica/rust-overlay/9055cb4f33f062c0dd33aa7e3c89140da8f70057' (2022-08-02) * Add type alias for NoGood Add a type alias `Interpretation` for NoGood to reflect the duality where an Interpretation might become a NoGood. * Add documentation information about later revisions on VarContainer Co-authored-by: Maximilian Marx <mmarx@wh2.tu-dresden.de>
140 lines
4.9 KiB
Rust
140 lines
4.9 KiB
Rust
/*!
|
|
This module contains all the crate-wide defined heuristic functions.
|
|
In addition there is the public enum [Heuristic], which allows to set a heuristic function with the public API.
|
|
*/
|
|
use super::Adf;
|
|
use crate::datatypes::{Term, Var};
|
|
|
|
use strum::{EnumString, EnumVariantNames};
|
|
|
|
/// Return value for heuristics.
|
|
pub type RetVal = Option<(Var, Term)>;
|
|
/// Signature for heuristics functions.
|
|
pub type HeuristicFn = dyn Fn(&Adf, &[Term]) -> RetVal;
|
|
|
|
pub(crate) fn heu_simple(_adf: &Adf, interpr: &[Term]) -> Option<(Var, Term)> {
|
|
for (idx, term) in interpr.iter().enumerate() {
|
|
if !term.is_truth_value() {
|
|
return Some((Var(idx), Term::TOP));
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
pub(crate) fn heu_mc_minpaths_maxvarimp(adf: &Adf, interpr: &[Term]) -> Option<(Var, Term)> {
|
|
interpr
|
|
.iter()
|
|
.enumerate()
|
|
.filter(|(_var, term)| !term.is_truth_value())
|
|
.min_by(|(vara, &terma), (varb, &termb)| {
|
|
match adf
|
|
.bdd
|
|
.paths(terma, true)
|
|
.minimum()
|
|
.cmp(&adf.bdd.paths(termb, true).minimum())
|
|
{
|
|
std::cmp::Ordering::Equal => adf
|
|
.bdd
|
|
.passive_var_impact(Var::from(*vara), interpr)
|
|
.cmp(&adf.bdd.passive_var_impact(Var::from(*varb), interpr)),
|
|
value => value,
|
|
}
|
|
})
|
|
.map(|(var, term)| {
|
|
(
|
|
Var::from(var),
|
|
adf.bdd.paths(*term, true).more_models().into(),
|
|
)
|
|
})
|
|
}
|
|
|
|
pub(crate) fn heu_mc_maxvarimp_minpaths(adf: &Adf, interpr: &[Term]) -> Option<(Var, Term)> {
|
|
interpr
|
|
.iter()
|
|
.enumerate()
|
|
.filter(|(_var, term)| !term.is_truth_value())
|
|
.min_by(|(vara, &terma), (varb, &termb)| {
|
|
match adf
|
|
.bdd
|
|
.passive_var_impact(Var::from(*vara), interpr)
|
|
.cmp(&adf.bdd.passive_var_impact(Var::from(*varb), interpr))
|
|
{
|
|
std::cmp::Ordering::Equal => adf
|
|
.bdd
|
|
.paths(terma, true)
|
|
.minimum()
|
|
.cmp(&adf.bdd.paths(termb, true).minimum()),
|
|
|
|
value => value,
|
|
}
|
|
})
|
|
.map(|(var, term)| {
|
|
(
|
|
Var::from(var),
|
|
adf.bdd.paths(*term, true).more_models().into(),
|
|
)
|
|
})
|
|
}
|
|
|
|
/// Enumeration of all currently implemented heuristics.
|
|
/// It represents a public view on the crate-view implementations of heuristics.
|
|
#[derive(EnumString, EnumVariantNames, Copy, Clone)]
|
|
pub enum Heuristic<'a> {
|
|
/// Implementation of a simple heuristic.
|
|
/// This will just take the first not decided variable and maps it value to (`true`)[Term::TOP].
|
|
Simple,
|
|
/// Implementation of a heuristic, which which uses minimal number of [paths][crate::obdd::Bdd::paths] and maximal [variable-impact][crate::obdd::Bdd::passive_var_impact to identify the variable to be set.
|
|
/// As the value of the variable value with the maximal model-path is chosen.
|
|
MinModMinPathsMaxVarImp,
|
|
/// Implementation of a heuristic, which which uses maximal [variable-impact][crate::obdd::Bdd::passive_var_impact] and minimal number of [paths][crate::obdd::Bdd::paths] to identify the variable to be set.
|
|
/// As the value of the variable value with the maximal model-path is chosen.
|
|
MinModMaxVarImpMinPaths,
|
|
/// Allow passing in an externally-defined custom heuristic.
|
|
#[strum(disabled)]
|
|
Custom(&'a HeuristicFn),
|
|
}
|
|
|
|
impl Default for Heuristic<'_> {
|
|
fn default() -> Self {
|
|
Self::Simple
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Debug for Heuristic<'_> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Simple => write!(f, "Simple"),
|
|
Self::MinModMinPathsMaxVarImp => write!(f, "Maximal model-path count as value and minimum paths with maximal variable impact as variable choice"),
|
|
Self::MinModMaxVarImpMinPaths => write!(f, "Maximal model-path count as value and maximal variable impact with minimum paths as variable choice"),
|
|
Self::Custom(_) => f.debug_tuple("Custom function").finish(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Heuristic<'_> {
|
|
pub(crate) fn get_heuristic(&self) -> &(dyn Fn(&Adf, &[Term]) -> RetVal + '_) {
|
|
match self {
|
|
Heuristic::Simple => &heu_simple,
|
|
Heuristic::MinModMinPathsMaxVarImp => &heu_mc_minpaths_maxvarimp,
|
|
Heuristic::MinModMaxVarImpMinPaths => &heu_mc_maxvarimp_minpaths,
|
|
Self::Custom(f) => f,
|
|
}
|
|
}
|
|
}
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
use crate::datatypes::Term;
|
|
use crate::datatypes::Var;
|
|
|
|
#[test]
|
|
fn debug_out() {
|
|
dbg!(Heuristic::Simple);
|
|
dbg!(Heuristic::MinModMaxVarImpMinPaths);
|
|
dbg!(Heuristic::MinModMinPathsMaxVarImp);
|
|
dbg!(Heuristic::Custom(&|_adf: &Adf,
|
|
_int: &[Term]|
|
|
-> Option<(Var, Term)> { None }));
|
|
}
|
|
}
|