some more thinking...

This commit is contained in:
2019-02-19 16:24:05 +01:00
parent f69d94d758
commit e5b16ae955
2 changed files with 30 additions and 9 deletions

View File

@@ -19,14 +19,34 @@
//! Price //! Price
//! - Per week : should restrict ingredients cost to a given amount //! - Per week : should restrict ingredients cost to a given amount
trait Rule { enum Status {
type State; Ok,
Violated,
}
fn check(&self, state: Self::State); trait Rule {
fn insights(&self, state: Self::State) -> Insight; type Key;
type Value;
fn status(&self, state: (Vec<&Self::Key>, Vec<&Self::Value>));
fn update(&self, idx: usize, value: Option<Self::Value>) -> Option<Filter>;
}; };
struct AllDifferentMeals; struct AllDifferentMeals;
impl Rule for AllDifferentMeals {
type State = Vec<Recipe>;
fn status(&self, _: Self::State) -> Status {
Status::Ok // Always enforced by update rule
}
fn update(&self, _: Self::State) -> Option<Filter> {
// Returns a filter excluding this value from domain.
// so that it is impossible to select the same meal twice.
None
}
}
struct FilterRecipeByMeals; // Essentially work on domain struct FilterRecipeByMeals; // Essentially work on domain
struct NutritionalByDayAverageReq; struct NutritionalByDayAverageReq;

View File

@@ -180,6 +180,8 @@ impl<'p, V: PartialEq, K: Eq + Hash + Clone> Problem<'p, V, K> {
/// a Clear to ensure the variable is unset before when leaving the branch. /// a Clear to ensure the variable is unset before when leaving the branch.
fn _push_updates(&self) -> Option<Vec<Assignment<'p,V>>> { fn _push_updates(&self) -> Option<Vec<Assignment<'p,V>>> {
if let Some(idx) = self._next_assign() { if let Some(idx) = self._next_assign() {
// TODO: Domain will filter possible values for us
// let values = self.domain.get(idx);
let domain_values = self.domains let domain_values = self.domains
.get(idx) .get(idx)
.expect("No domain for variable !"); .expect("No domain for variable !");
@@ -187,7 +189,6 @@ impl<'p, V: PartialEq, K: Eq + Hash + Clone> Problem<'p, V, K> {
assert!(!domain_values.is_empty()); assert!(!domain_values.is_empty());
// Push a clear assignment first, just before going up the stack. // Push a clear assignment first, just before going up the stack.
let mut updates = vec![Assignment::Clear(idx.clone())]; let mut updates = vec![Assignment::Clear(idx.clone())];
// TODO: should be able to filter domain values (inference, pertinence)
domain_values.iter().for_each(|value| { domain_values.iter().for_each(|value| {
updates.push( updates.push(
Assignment::Update(idx, *value) Assignment::Update(idx, *value)
@@ -233,14 +234,14 @@ impl<'p, V: PartialEq, K: Eq + Hash + Clone> Problem<'p, V, K> {
fn _assign(&mut self, idx: usize, value: Option<&'p V>) { fn _assign(&mut self, idx: usize, value: Option<&'p V>) {
self.variables[idx] = value; self.variables[idx] = value;
let var_key = &self.keys[idx]; let var_key = &self.keys[idx];
// TODO: manage dynamic filters on Domain
// let filters: Filter::Chain = self.constraints.iter_mut().map([...]).collect();
// self.domain.set_global(idx, filters);
self.constraints.iter_mut() self.constraints.iter_mut()
.for_each(|c| { .for_each(|c| {
c.update(&var_key, value); c.update(&var_key, value);
}); });
// Some thoughts: what if we used a stack of filters,
// for each variable, that is cleared, on every assign,
// and repopulated by aggregating update calls on constraints.
// Domain would then be filtered by ALL filters in these stacks.
} }
fn _solve(&mut self, limit: Option<usize>) -> Vec<Solution<'p, V, K>> { fn _solve(&mut self, limit: Option<usize>) -> Vec<Solution<'p, V, K>> {