diff --git a/Cargo.lock b/Cargo.lock index 7aba1060..52eb8cae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -280,7 +280,7 @@ dependencies = [ [[package]] name = "ddo" -version = "1.2.0" +version = "2.0.0" dependencies = [ "binary-heap-plus", "bit-set", diff --git a/ddo/Cargo.toml b/ddo/Cargo.toml index eb6920f0..7c28d230 100644 --- a/ddo/Cargo.toml +++ b/ddo/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ddo" -version = "1.2.0" +version = "2.0.0" authors = ["Xavier Gillard "] edition = "2021" description = "DDO a generic and efficient framework for MDD-based optimization." diff --git a/ddo/examples/alp/model.rs b/ddo/examples/alp/model.rs index e2e4b593..b01a460e 100644 --- a/ddo/examples/alp/model.rs +++ b/ddo/examples/alp/model.rs @@ -148,7 +148,7 @@ impl Problem for Alp { } } - fn transition_cost(&self, state: &Self::State, decision: ddo::Decision) -> isize { + fn transition_cost(&self, state: &Self::State, _: &Self::State, decision: ddo::Decision) -> isize { if decision.value == DUMMY { 0 } else { diff --git a/ddo/examples/golomb/main.rs b/ddo/examples/golomb/main.rs index 032a3405..b6dfa5b3 100644 --- a/ddo/examples/golomb/main.rs +++ b/ddo/examples/golomb/main.rs @@ -117,7 +117,7 @@ impl Problem for Golomb { } // compute the cost of the decision from the given state - fn transition_cost(&self, state: &Self::State, dec: Decision) -> isize { + fn transition_cost(&self, state: &Self::State, _: &Self::State, dec: Decision) -> isize { // distance between the new mark and the previous one -(dec.value - state.last_mark) // put a minus to turn objective into maximization (ddo requirement) } diff --git a/ddo/examples/knapsack/main.rs b/ddo/examples/knapsack/main.rs index 804b4968..a65aa464 100644 --- a/ddo/examples/knapsack/main.rs +++ b/ddo/examples/knapsack/main.rs @@ -111,7 +111,7 @@ impl Problem for Knapsack { } ret } - fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { + fn transition_cost(&self, _state: &Self::State, _: &Self::State, dec: Decision) -> isize { self.profit[dec.variable.id()] * dec.value } diff --git a/ddo/examples/lcs/model.rs b/ddo/examples/lcs/model.rs index da9bcd03..47a00fce 100644 --- a/ddo/examples/lcs/model.rs +++ b/ddo/examples/lcs/model.rs @@ -120,7 +120,7 @@ impl Problem for Lcs { LcsState { position } } - fn transition_cost(&self, _: &Self::State, decision: ddo::Decision) -> isize { + fn transition_cost(&self, _: &Self::State, _: &Self::State, decision: ddo::Decision) -> isize { match decision.value { GO_TO_END_OF_STRINGS => 0, _ => 1, diff --git a/ddo/examples/max2sat/model.rs b/ddo/examples/max2sat/model.rs index e4227fbb..d8684152 100644 --- a/ddo/examples/max2sat/model.rs +++ b/ddo/examples/max2sat/model.rs @@ -291,7 +291,7 @@ impl Problem for Max2Sat { ret } - fn transition_cost(&self, state: &State, d: Decision) -> isize { + fn transition_cost(&self, state: &State, _: &Self::State, d: Decision) -> isize { let k = d.variable; let vars = self.varset(state); if d.value == F { diff --git a/ddo/examples/mcp/model.rs b/ddo/examples/mcp/model.rs index e9177082..06891389 100644 --- a/ddo/examples/mcp/model.rs +++ b/ddo/examples/mcp/model.rs @@ -77,7 +77,7 @@ impl Problem for Mcp { McpState {depth: 1 + state.depth, benef: benefits} } - fn transition_cost(&self, state: &McpState, d: Decision) -> isize { + fn transition_cost(&self, state: &McpState, _: &Self::State, d: Decision) -> isize { match d.value { S => if state.depth == 0 { 0 } else { self.branch_on_s(state, d) }, T => if state.depth == 0 { 0 } else { self.branch_on_t(state, d) }, diff --git a/ddo/examples/misp/main.rs b/ddo/examples/misp/main.rs index bf49957a..1cb1d131 100644 --- a/ddo/examples/misp/main.rs +++ b/ddo/examples/misp/main.rs @@ -84,7 +84,7 @@ impl Problem for Misp { res } - fn transition_cost(&self, _: &Self::State, decision: Decision) -> isize { + fn transition_cost(&self, _: &Self::State, _: &Self::State, decision: Decision) -> isize { if decision.value == NO { 0 } else { diff --git a/ddo/examples/psp/model.rs b/ddo/examples/psp/model.rs index c7d4f9b8..daccdfd8 100644 --- a/ddo/examples/psp/model.rs +++ b/ddo/examples/psp/model.rs @@ -90,7 +90,7 @@ impl Problem for Psp { ret } - fn transition_cost(&self, state: &Self::State, decision: ddo::Decision) -> isize { + fn transition_cost(&self, state: &Self::State, _: &Self::State, decision: ddo::Decision) -> isize { if decision.value == IDLE { 0 } else { diff --git a/ddo/examples/sop/model.rs b/ddo/examples/sop/model.rs index d6d762ba..3edbd9e6 100644 --- a/ddo/examples/sop/model.rs +++ b/ddo/examples/sop/model.rs @@ -118,7 +118,7 @@ impl Problem for Sop { next } - fn transition_cost(&self, state: &SopState, d: Decision) -> isize { + fn transition_cost(&self, state: &SopState, _: &Self::State, d: Decision) -> isize { // Sop is a minimization problem but the solver works with a // maximization perspective. So we have to negate the cost. diff --git a/ddo/examples/srflp/model.rs b/ddo/examples/srflp/model.rs index ecb41351..bfb05693 100644 --- a/ddo/examples/srflp/model.rs +++ b/ddo/examples/srflp/model.rs @@ -129,7 +129,7 @@ impl Problem for Srflp { } } - fn transition_cost(&self, state: &SrflpState, d: Decision) -> isize { + fn transition_cost(&self, state: &SrflpState, _: &Self::State, d: Decision) -> isize { let d = d.value as usize; let mut cut = 0; diff --git a/ddo/examples/talentsched/model.rs b/ddo/examples/talentsched/model.rs index 56be9020..8b8dce11 100644 --- a/ddo/examples/talentsched/model.rs +++ b/ddo/examples/talentsched/model.rs @@ -110,7 +110,7 @@ impl Problem for TalentSched { ret } - fn transition_cost(&self, state: &Self::State, decision: ddo::Decision) -> isize { + fn transition_cost(&self, state: &Self::State, _: &Self::State, decision: ddo::Decision) -> isize { let scene = decision.value as usize; let pay = self.get_present(state).diff(self.actors[scene]); diff --git a/ddo/examples/tsptw/model.rs b/ddo/examples/tsptw/model.rs index 6f1720e5..5c3395f1 100644 --- a/ddo/examples/tsptw/model.rs +++ b/ddo/examples/tsptw/model.rs @@ -113,7 +113,7 @@ impl Problem for Tsptw { } } - fn transition_cost(&self, state: &TsptwState, d: Decision) -> isize { + fn transition_cost(&self, state: &TsptwState, _: &Self::State, d: Decision) -> isize { // Tsptw is a minimization problem but the solver works with a // maximization perspective. So we have to negate the min if we want to // yield a lower bound. diff --git a/ddo/examples/visualisation/main.rs b/ddo/examples/visualisation/main.rs index d62690b5..318202df 100644 --- a/ddo/examples/visualisation/main.rs +++ b/ddo/examples/visualisation/main.rs @@ -97,7 +97,7 @@ impl Problem for Knapsack { } ret } - fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { + fn transition_cost(&self, _state: &Self::State, _: &Self::State, dec: Decision) -> isize { self.profit[dec.variable.id()] as isize * dec.value } diff --git a/ddo/src/abstraction/dp.rs b/ddo/src/abstraction/dp.rs index 794a9ddb..f3b765eb 100644 --- a/ddo/src/abstraction/dp.rs +++ b/ddo/src/abstraction/dp.rs @@ -47,7 +47,7 @@ pub trait Problem { fn transition(&self, state: &Self::State, decision: Decision) -> Self::State; /// This method is an implementation of the transition cost function mentioned /// in the mathematical model of a DP formulation for some problem. - fn transition_cost(&self, state: &Self::State, decision: Decision) -> isize; + fn transition_cost(&self, source: &Self::State, dest: &Self::State, decision: Decision) -> isize; /// Any problem needs to be able to specify an ordering on the variables /// in order to decide which variable should be assigned next. This choice /// is an **heuristic** choice. The variable ordering does not need to be @@ -165,7 +165,7 @@ mod tests { fn transition(&self, _: &Self::State, _: Decision) -> Self::State { todo!() } - fn transition_cost(&self, _: &Self::State, _: Decision) -> isize { + fn transition_cost(&self, _: &Self::State, _: &Self::State, _: Decision) -> isize { todo!() } fn next_variable(&self, _: usize, _: &mut dyn Iterator) diff --git a/ddo/src/implementation/heuristics/cutoff.rs b/ddo/src/implementation/heuristics/cutoff.rs index bebe8470..a47eb2c8 100644 --- a/ddo/src/implementation/heuristics/cutoff.rs +++ b/ddo/src/implementation/heuristics/cutoff.rs @@ -73,7 +73,7 @@ use crate::Cutoff; /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, next_layer: &mut dyn Iterator) -> Option { @@ -212,7 +212,7 @@ impl Cutoff for NoCutoff { /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option { diff --git a/ddo/src/implementation/heuristics/width.rs b/ddo/src/implementation/heuristics/width.rs index 4abbc3c2..54290e50 100644 --- a/ddo/src/implementation/heuristics/width.rs +++ b/ddo/src/implementation/heuristics/width.rs @@ -84,7 +84,7 @@ use crate::{WidthHeuristic, SubProblem}; /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, next_layer: &mut dyn Iterator) -> Option { @@ -223,7 +223,7 @@ impl WidthHeuristic for FixedWidth { /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option { @@ -312,7 +312,7 @@ impl WidthHeuristic for FixedWidth { /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option { @@ -462,7 +462,7 @@ impl WidthHeuristic for NbUnassignedWidth { /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, next_layer: &mut dyn Iterator) -> Option { @@ -551,7 +551,7 @@ impl WidthHeuristic for NbUnassignedWidth { /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, next_layer: &mut dyn Iterator) -> Option { @@ -702,7 +702,7 @@ impl > WidthHeuristic for Times { /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option { @@ -791,7 +791,7 @@ impl > WidthHeuristic for Times { /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option { diff --git a/ddo/src/implementation/mdd/clean.rs b/ddo/src/implementation/mdd/clean.rs index 9b2fcb0b..44f0a1d3 100644 --- a/ddo/src/implementation/mdd/clean.rs +++ b/ddo/src/implementation/mdd/clean.rs @@ -727,7 +727,7 @@ where ) { let state = get!(node from_id, self).state.as_ref(); let next_state = Arc::new(problem.transition(state, decision)); - let cost = problem.transition_cost(state, decision); + let cost = problem.transition_cost(state, next_state.as_ref(), decision); match self.next_l.entry(next_state.clone()) { Entry::Vacant(e) => { @@ -2128,7 +2128,7 @@ mod test_default_mdd { } } - fn transition_cost(&self, _: &char, d: Decision) -> isize { + fn transition_cost(&self, _: &char, _: &Self::State, d: Decision) -> isize { d.value } } @@ -2567,7 +2567,7 @@ mod test_default_mdd { } } - fn transition_cost(&self, _: &Self::State, decision: crate::Decision) -> isize { + fn transition_cost(&self, _: &Self::State, _: &Self::State, decision: crate::Decision) -> isize { decision.value } @@ -2608,7 +2608,7 @@ mod test_default_mdd { } } - fn transition_cost(&self, _: &Self::State, decision: crate::Decision) -> isize { + fn transition_cost(&self, _: &Self::State, _: &Self::State, decision: crate::Decision) -> isize { decision.value } diff --git a/ddo/src/implementation/mdd/pooled.rs b/ddo/src/implementation/mdd/pooled.rs index fe0f0224..a9d48ac3 100644 --- a/ddo/src/implementation/mdd/pooled.rs +++ b/ddo/src/implementation/mdd/pooled.rs @@ -683,7 +683,7 @@ where ) { let state = get!(node from_id, self).state.as_ref(); let next_state = Arc::new(problem.transition(state, decision)); - let cost = problem.transition_cost(state, decision); + let cost = problem.transition_cost(state, next_state.as_ref(), decision); match self.pool.entry(next_state.clone()) { Entry::Vacant(e) => { @@ -2045,7 +2045,7 @@ mod test_default_mdd { } } - fn transition_cost(&self, _: &char, d: Decision) -> isize { + fn transition_cost(&self, _: &char, _: &Self::State, d: Decision) -> isize { d.value } } @@ -2423,7 +2423,7 @@ mod test_default_mdd { } } - fn transition_cost(&self, _: &Self::State, decision: crate::Decision) -> isize { + fn transition_cost(&self, _: &Self::State, _: &Self::State, decision: crate::Decision) -> isize { decision.value } @@ -2464,7 +2464,7 @@ mod test_default_mdd { } } - fn transition_cost(&self, _: &Self::State, decision: crate::Decision) -> isize { + fn transition_cost(&self, _: &Self::State, _: &Self::State, decision: crate::Decision) -> isize { decision.value } diff --git a/ddo/src/implementation/solver/parallel.rs b/ddo/src/implementation/solver/parallel.rs index 6bca12ad..5f1b303a 100644 --- a/ddo/src/implementation/solver/parallel.rs +++ b/ddo/src/implementation/solver/parallel.rs @@ -166,7 +166,7 @@ enum WorkLoad { /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option { @@ -1281,7 +1281,7 @@ mod test_solver { } ret } - fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { + fn transition_cost(&self, _state: &Self::State, _: &Self::State, dec: Decision) -> isize { self.profit[dec.variable.id()] as isize * dec.value } fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option { diff --git a/ddo/src/implementation/solver/sequential.rs b/ddo/src/implementation/solver/sequential.rs index efdc4029..deb56e77 100644 --- a/ddo/src/implementation/solver/sequential.rs +++ b/ddo/src/implementation/solver/sequential.rs @@ -81,7 +81,7 @@ enum WorkLoad { /// # } /// # ret /// # } -/// # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +/// # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { /// # self.profit[dec.variable.id()] as isize * dec.value /// # } /// # fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option { @@ -1035,7 +1035,7 @@ mod test_solver { } ret } - fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { + fn transition_cost(&self, _state: &Self::State, _: &Self::State, dec: Decision) -> isize { self.profit[dec.variable.id()] as isize * dec.value } fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option { diff --git a/ddo/src/lib.rs b/ddo/src/lib.rs index a851f4a3..04ec8fde 100644 --- a/ddo/src/lib.rs +++ b/ddo/src/lib.rs @@ -145,7 +145,7 @@ //! // This method is analogous to the transition function. But instead to returning //! // the next state when a decision is made, it returns the "cost", that is the //! // impact of making that decision on the objective function. -//! fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +//! fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { //! self.profit[dec.variable.id()] as isize * dec.value //! } //! // This method is used to determine the order in which the variables will be branched @@ -225,7 +225,7 @@ //! # } //! # ret //! # } -//! # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +//! # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { //! # self.profit[dec.variable.id()] as isize * dec.value //! # } //! # fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option { @@ -349,7 +349,7 @@ //! # } //! # ret //! # } -//! # fn transition_cost(&self, _state: &Self::State, dec: Decision) -> isize { +//! # fn transition_cost(&self, _state: &Self::State, _next: &Self::State, dec: Decision) -> isize { //! # self.profit[dec.variable.id()] as isize * dec.value //! # } //! # fn next_variable(&self, depth: usize, _: &mut dyn Iterator) -> Option {