GHOST
objective.hpp
Go to the documentation of this file.
1 /*
2  * GHOST (General meta-Heuristic Optimization Solving Tool) is a C++ framework
3  * designed to help developers to model and implement optimization problem
4  * solving. It contains a meta-heuristic solver aiming to solve any kind of
5  * combinatorial and optimization real-time problems represented by a CSP/COP/EF-CSP/EF-COP.
6  *
7  * First developed to solve game-related optimization problems, GHOST can be used for
8  * any kind of applications where solving combinatorial and optimization problems. In
9  * particular, it had been designed to be able to solve not-too-complex problem instances
10  * within some milliseconds, making it very suitable for highly reactive or embedded systems.
11  * Please visit https://github.com/richoux/GHOST for further information.
12  *
13  * Copyright (C) 2014-2023 Florian Richoux
14  *
15  * This file is part of GHOST.
16  * GHOST is free software: you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License as published
18  * by the Free Software Foundation, either version 3 of the License, or
19  * (at your option) any later version.
20 
21  * GHOST is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25 
26  * You should have received a copy of the GNU General Public License
27  * along with GHOST. If not, see http://www.gnu.org/licenses/.
28  */
29 
30 
31 #pragma once
32 
33 #include <algorithm>
34 #include <limits>
35 #include <vector>
36 #include <map>
37 #include <cmath> // for isnan
38 #include <exception>
39 
40 #include "variable.hpp"
41 #include "thirdparty/randutils.hpp"
42 
43 namespace ghost
44 {
45  namespace algorithms
46  {
47  class AdaptiveSearchValueHeuristic;
48  class AntidoteSearchValueHeuristic;
49  }
50 
61  class Objective
62  {
63  template<typename ModelBuilderType> friend class Solver;
64  friend class SearchUnit;
65  friend class ModelBuilder;
66 
67  friend class NullObjective;
68  friend class Minimize;
69  friend class Maximize;
70 
71  friend class algorithms::AdaptiveSearchValueHeuristic;
72  friend class algorithms::AntidoteSearchValueHeuristic;
73 
74  std::vector<Variable*> _variables; // Vector of raw pointers to variables needed to compute the objective function.
75  std::vector<int> _variables_index; // To know where are the constraint's variables in the global variable vector.
76  std::map<int,int> _variables_position; // To know where are global variables in the constraint's variables vector.
77  bool _is_optimization;
78  bool _is_maximization;
79  std::string _name; // Name of the objective object.
80 
81  struct nanException : std::exception
82  {
83  std::vector<Variable*> variables;
84  std::string message;
85 
86  nanException( const std::vector<Variable*>& variables ) : variables(variables)
87  {
88  message = "Objective required_cost returned a NaN value on variables (";
89  for( int i = 0; i < static_cast<int>( variables.size() ) - 1; ++i )
90  message += std::to_string( variables[i]->get_value() ) + ", ";
91  message += std::to_string( variables[ static_cast<int>( variables.size() ) - 1 ]->get_value() ) + ")\n";
92  }
93  const char* what() const noexcept { return message.c_str(); }
94  };
95 
96  struct variableOutOfTheScope : std::exception
97  {
98  std::string message;
99 
100  variableOutOfTheScope( int var_id, std::string name )
101  {
102  message = "Variable ID " + std::to_string( var_id ) + " is not in the scope of the Objective function " + name + ".\n";
103  }
104  const char* what() const noexcept { return message.c_str(); }
105  };
106 
107  Objective( const std::vector<int>& variables_index, bool is_maximization, const std::string& name );
108  Objective( const std::vector<Variable>& variables, bool is_maximization, const std::string& name );
109 
110  inline void update( int index, int new_value ) { conditional_update_data_structures( _variables, _variables_position[ index ], new_value ); }
111 
112  // Call required_cost() on Objective::_variables after making sure the cost does not give a nan, rise an exception otherwise.
113  double cost() const;
114 
115  // Call expert_heuristic_value on Objective::_variables.
116  inline int heuristic_value( int variable_index, const std::vector<int>& possible_values, randutils::mt19937_rng& rng ) const
117  { return expert_heuristic_value( _variables, _variables_position.at( variable_index ), possible_values, rng ); }
118 
119  // Call expert_heuristic_value_permutation on Objective::_variables.
120  inline int heuristic_value_permutation( int variable_index, const std::vector<int>& bad_variables, randutils::mt19937_rng& rng ) const
121  { return expert_heuristic_value_permutation( _variables, _variables_position.at( variable_index ), bad_variables, rng ); }
122 
123  // Call expert_postprocess on Objective::_variables.
124  inline double postprocess( double best_cost ) const
125  { return expert_postprocess( _variables, best_cost ); }
126 
127  protected:
145  virtual double required_cost( const std::vector<Variable*>& variables ) const = 0;
146 
162  virtual void conditional_update_data_structures( const std::vector<Variable*>& variables, int index, int new_value );
163 
189  virtual int expert_heuristic_value( const std::vector<Variable*>& variables,
190  int variable_index,
191  const std::vector<int>& possible_values,
192  randutils::mt19937_rng& rng ) const;
193 
214  virtual int expert_heuristic_value_permutation( const std::vector<Variable*>& variables,
215  int variable_index,
216  const std::vector<int>& bad_variables,
217  randutils::mt19937_rng& rng ) const;
218 
244  virtual double expert_postprocess( const std::vector<Variable*>& variables,
245  double best_cost ) const;
246 
247 
248  // No documentation on purpose.
249  inline void is_not_optimization() { _is_optimization = false; }
250 
251  public:
253  Objective( const Objective& other ) = default;
255  Objective( Objective&& other ) = default;
256 
258  Objective& operator=( const Objective& other ) = delete;
260  Objective& operator=( Objective&& other ) = delete;
261 
263  virtual ~Objective() = default;
264 
266  inline std::string get_name() const { return _name; }
267 
269  inline bool is_optimization() const { return _is_optimization; }
270 
275  inline bool is_maximization() const { return _is_maximization; }
276 
278  friend std::ostream& operator<<( std::ostream& os, const Objective& o )
279  {
280  return os << "Objective name: " << o._name
281  << "\n********";
282  }
283  };
284 
285  /*******************/
287  /*******************/
288  // NullObjective is used when no objective functions have been given to the solver (ie, for pure satisfaction runs).
289  class NullObjective : public Objective
290  {
291  public:
292  NullObjective() : Objective( std::vector<int>{0}, false, "nullObjective" )
293  {
294  this->is_not_optimization();
295  }
296 
297  private:
298  double required_cost( const std::vector<Variable*>& variables ) const override { return 0.0; }
299  };
300 
301  /**************/
303  /**************/
313  class Minimize : public Objective
314  {
315  public:
323  Minimize( const std::vector<int>& variables_index )
324  : Objective( variables_index, false, std::string( "Minimize" ) )
325  { }
326 
333  Minimize( const std::vector<Variable>& variables )
334  : Objective( variables, false, std::string( "Minimize" ) )
335  { }
336 
344  Minimize( const std::vector<int>& variables_index, const std::string& name )
345  : Objective( variables_index, false, name )
346  { }
347 
354  Minimize( const std::vector<Variable>& variables, const std::string& name )
355  : Objective( variables, false, name )
356  { }
357 
365  Minimize( const std::vector<int>& variables_index, const char* name )
366  : Objective( variables_index, false, std::string( name ) )
367  { }
368 
375  Minimize( const std::vector<Variable>& variables, const char* name )
376  : Objective( variables, false, std::string( name ) )
377  { }
378  };
379 
380  /**************/
382  /**************/
392  class Maximize : public Objective
393  {
394  public:
402  Maximize( const std::vector<int>& variables_index )
403  : Objective( variables_index, true, std::string( "Maximize" ) )
404  { }
405 
412  Maximize( const std::vector<Variable>& variables )
413  : Objective( variables, true, std::string( "Maximize" ) )
414  { }
415 
423  Maximize( const std::vector<int>& variables_index, const std::string& name )
424  : Objective( variables_index, true, name )
425  { }
426 
433  Maximize( const std::vector<Variable>& variables, const std::string& name )
434  : Objective( variables, true, name )
435  { }
436 
444  Maximize( const std::vector<int>& variables_index, const char* name )
445  : Objective( variables_index, true, std::string( name ) )
446  { }
447 
454  Maximize( const std::vector<Variable>& variables, const char* name )
455  : Objective( variables, true, std::string( name ) )
456  { }
457  };
458 }
Definition: objective.hpp:393
Maximize(const std::vector< Variable > &variables, const std::string &name)
Definition: objective.hpp:433
Maximize(const std::vector< int > &variables_index, const char *name)
Definition: objective.hpp:444
Maximize(const std::vector< int > &variables_index, const std::string &name)
Definition: objective.hpp:423
Maximize(const std::vector< Variable > &variables)
Definition: objective.hpp:412
Maximize(const std::vector< int > &variables_index)
Definition: objective.hpp:402
Maximize(const std::vector< Variable > &variables, const char *name)
Definition: objective.hpp:454
Definition: objective.hpp:314
Minimize(const std::vector< Variable > &variables, const char *name)
Definition: objective.hpp:375
Minimize(const std::vector< int > &variables_index, const char *name)
Definition: objective.hpp:365
Minimize(const std::vector< int > &variables_index, const std::string &name)
Definition: objective.hpp:344
Minimize(const std::vector< Variable > &variables, const std::string &name)
Definition: objective.hpp:354
Minimize(const std::vector< Variable > &variables)
Definition: objective.hpp:333
Minimize(const std::vector< int > &variables_index)
Definition: objective.hpp:323
Definition: model_builder.hpp:63
Definition: objective.hpp:62
friend class SearchUnit
Definition: objective.hpp:64
virtual void conditional_update_data_structures(const std::vector< Variable * > &variables, int index, int new_value)
Objective & operator=(Objective &&other)=delete
Move assignment operator disabled.
virtual int expert_heuristic_value_permutation(const std::vector< Variable * > &variables, int variable_index, const std::vector< int > &bad_variables, randutils::mt19937_rng &rng) const
std::string get_name() const
Inline accessor to get the name of the objective object.
Definition: objective.hpp:266
virtual double expert_postprocess(const std::vector< Variable * > &variables, double best_cost) const
Objective(const Objective &other)=default
Default copy contructor.
friend std::ostream & operator<<(std::ostream &os, const Objective &o)
To have a nicer stream of Objective.
Definition: objective.hpp:278
virtual double required_cost(const std::vector< Variable * > &variables) const =0
virtual int expert_heuristic_value(const std::vector< Variable * > &variables, int variable_index, const std::vector< int > &possible_values, randutils::mt19937_rng &rng) const
virtual ~Objective()=default
Default virtual destructor.
void is_not_optimization()
Definition: objective.hpp:249
Objective & operator=(const Objective &other)=delete
Copy assignment operator disabled.
bool is_optimization() const
Inline method returning if a user-defined objective function has been declared.
Definition: objective.hpp:269
Objective(Objective &&other)=default
Default move contructor.
bool is_maximization() const
Definition: objective.hpp:275
Definition: solver.hpp:110
Definition: auxiliary_data.hpp:38