ddo/common.rs
1// Copyright 2020 Xavier Gillard
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of
4// this software and associated documentation files (the "Software"), to deal in
5// the Software without restriction, including without limitation the rights to
6// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7// the Software, and to permit persons to whom the Software is furnished to do so,
8// subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20//! This module defines the most basic data types that are used throughout all
21//! the code of our library (both at the abstraction and implementation levels).
22//! These are also the types your client library is likely to work with.
23
24use std::sync::Arc;
25
26// ----------------------------------------------------------------------------
27// --- VARIABLE ---------------------------------------------------------------
28// ----------------------------------------------------------------------------
29/// This type denotes a variable from the optimization problem at hand.
30/// In this case, each variable is assumed to be identified with an integer
31/// ranging from 0 until `problem.nb_vars()`
32#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
33pub struct Variable(pub usize);
34impl Variable {
35 #[inline]
36 /// This function returns the id (numeric value) of the variable.
37 ///
38 /// # Examples:
39 /// ```
40 /// # use ddo::Variable;
41 /// assert_eq!(0, Variable(0).id());
42 /// assert_eq!(1, Variable(1).id());
43 /// assert_eq!(2, Variable(2).id());
44 /// assert_eq!(3, Variable(3).id());
45 /// ```
46 pub fn id(self) -> usize {
47 self.0
48 }
49}
50
51// ----------------------------------------------------------------------------
52// --- DECISION ---------------------------------------------------------------
53// ----------------------------------------------------------------------------
54/// This denotes a decision that was made during the search. It affects a given
55/// `value` to the specified `variable`. Any given `Decision` should be
56/// understood as ```[[ variable = value ]]````
57#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
58pub struct Decision {
59 pub variable : Variable,
60 pub value : isize
61}
62
63
64// ----------------------------------------------------------------------------
65// --- SUBPROBLEM -------------------------------------------------------------
66// ----------------------------------------------------------------------------
67/// A subproblem is a residual problem that must be solved in order to complete the
68/// resolution of the original problem which had been defined.
69///
70/// # Note:
71/// Sub-problems are automatically instantiated from nodes in the exact cut-sets
72/// of relaxed decision diagrams. If you are only discovering the API, rest
73/// assured.. you don't need to implement any subproblem yourself.
74#[derive(Debug, Clone, PartialEq, Eq)]
75pub struct SubProblem<T> {
76 /// The root state of this sub problem
77 pub state: Arc<T>,
78 /// The root value of this sub problem
79 pub value: isize,
80 /// The path to traverse to reach this subproblem from the root
81 /// of the original problem
82 pub path: Vec<Decision>,
83 /// An upper bound on the objective reachable in this subproblem
84 pub ub: isize,
85 /// The depth of the subproblem with respect to the root problem
86 pub depth: usize,
87}
88
89// ----------------------------------------------------------------------------
90// --- THRESHOLD --------------------------------------------------------------
91// ----------------------------------------------------------------------------
92/// A threshold is a value that can be stored during the execution of a branch
93/// and bound algorithm. It is associated with a single exact state and is used
94/// to determine whether a new node with the same state is worth exploring.
95#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
96pub struct Threshold {
97 /// The value of the threshold
98 pub value: isize,
99 /// Whether a node with the given value has already been explored
100 pub explored: bool,
101}
102
103// ----------------------------------------------------------------------------
104// --- Results ----------------------------------------------------------------
105// ----------------------------------------------------------------------------
106/// A reason explaining why the mdd stopped developing
107#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
108pub enum Reason {
109 /// It stopped because the configured cutoff criterion was met
110 CutoffOccurred
111}
112
113/// The outcome of an mdd development
114#[derive(Debug, Clone)]
115pub struct Completion {
116 /// is the given solution exact (proved optimal for the given [sub-]problem)?
117 /// or is it an approximation ?
118 pub is_exact: bool,
119 /// if present the value of the best solution derived from this mdd
120 pub best_value: Option<isize>,
121}
122
123
124// ############################################################################
125// #### TESTS #################################################################
126// ############################################################################
127
128#[cfg(test)]
129mod test_var {
130 use crate::Variable;
131
132 #[test]
133 fn test_var_id() {
134 assert_eq!(0, Variable(0).id());
135 assert_eq!(1, Variable(1).id());
136 assert_eq!(2, Variable(2).id());
137 assert_eq!(3, Variable(3).id());
138 }
139}