GHOST
Loading...
Searching...
No Matches
constraint.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-2025 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 <vector>
34#include <map>
35#include <utility>
36#include <iostream>
37#include <typeinfo>
38#include <functional>
39#include <cmath> // for isnan
40#include <exception>
41#include <string>
42
43#include "variable.hpp"
44
45namespace ghost
46{
47 namespace algorithms
48 {
49 class AdaptiveSearchErrorProjection;
50 class CulpritSearchErrorProjection;
51 }
52
63 {
64 friend class SearchUnit;
65 template<typename ModelBuilderType> friend class Solver;
66 friend class ModelBuilder;
67 friend class algorithms::AdaptiveSearchErrorProjection;
68 friend class algorithms::CulpritSearchErrorProjection;
69
70 std::vector<Variable*> _variables;
71 std::vector<int> _variables_index; // To know where are the constraint's variables in the global variable vector
72 std::map<int,int> _variables_position; // To know where are global variables in the constraint's variables vector
73
74 double _current_error; // Current error of the constraint.
75
76 int _id; // Unique ID integer
77 mutable bool _is_optional_delta_error_defined; // Boolean telling if optional_delta_error() is overrided or not.
78
79 struct nanException : std::exception
80 {
81 std::vector<Variable*> ptr_variables;
82 std::vector<Variable> variables;
83 std::string message;
84
85 nanException( const std::vector<Variable*>& ptr_variables ) : ptr_variables(ptr_variables)
86 {
87 message = "Constraint required_error returned a NaN value on variables (";
88 for( int i = 0; i < static_cast<int>( ptr_variables.size() ) - 1; ++i )
89 message += std::to_string( ptr_variables[i]->get_value() ) + ", ";
90 message += std::to_string( ptr_variables[ static_cast<int>( ptr_variables.size() ) - 1 ]->get_value() ) + ")\n";
91 }
92
93 nanException( const std::vector<Variable>& variables ) : variables(variables)
94 {
95 message = "Constraint optional_delta_error returned a NaN value on variables (";
96 for( int i = 0; i < static_cast<int>( variables.size() ) - 1; ++i )
97 message += std::to_string( variables[i].get_value() ) + ", ";
98 message += std::to_string( variables[ static_cast<int>( variables.size() ) - 1 ].get_value() ) + ")\n";
99 }
100
101 const char* what() const noexcept { return message.c_str(); }
102 };
103
104 struct negativeException : std::exception
105 {
106 std::vector<Variable*> ptr_variables;
107 std::vector<Variable> variables;
108 std::string message;
109
110 negativeException( const std::vector<Variable*>& ptr_variables ) : ptr_variables(ptr_variables)
111 {
112 message = "Constraint required_error returned a negative value on variables (";
113 for( int i = 0; i < static_cast<int>( ptr_variables.size() ) - 1; ++i )
114 message += std::to_string( ptr_variables[i]->get_value() ) + ", ";
115 message += std::to_string( ptr_variables[ static_cast<int>( ptr_variables.size() ) - 1 ]->get_value() ) + ")\n";
116 }
117
118 const char* what() const noexcept { return message.c_str(); }
119 };
120
121 struct deltaErrorNotDefinedException : std::exception
122 {
123 std::string message;
124
125 deltaErrorNotDefinedException()
126 {
127 message = "Constraint::optional_delta_error() has not been user-defined.\n";
128 }
129 const char* what() const noexcept { return message.c_str(); }
130 };
131
132 struct variableOutOfTheScope : std::exception
133 {
134 std::string message;
135
136 variableOutOfTheScope( int var_id, int ctr_id )
137 {
138 message = "Variable* ID " + std::to_string( var_id ) + " is not in the scope of Constraint ID " + std::to_string( ctr_id ) + ".\n";
139 }
140 const char* what() const noexcept { return message.c_str(); }
141 };
142
143 inline bool is_optional_delta_error_defined() { return _is_optional_delta_error_defined; }
144
145 // Call required_error() after getting sure the error does give a nan, rise an exception otherwise.
146 double error() const;
147
148 // Compute the delta error of the current assignment, giving a vector of variables index and their candidate values.
149 // Calling optional_delta_error after making the conversion of variables index.
150 // Getting sure the delta error does give a nan, rise an exception otherwise.
151 double delta_error( const std::vector<int>& variables_index, const std::vector<int>& candidate_values ) const;
152
153 // To simulate the error delta between the current configuration and the candidate configuration.
154 // This calls delta_error() if the user overrided it, otherwise it makes the simulation 'by hand' and calls error()
155 double simulate_delta( const std::vector<int>& variables_index, const std::vector<int>& candidate_values );
156
157 // Return ids of variable objects in _variables.
158 inline std::vector<int> get_variable_ids() const { return _variables_index; }
159
160 inline void update( int index, int new_value ) { conditional_update_data_structures( _variables, _variables_position[ index ], new_value ); }
161
162 protected:
202 virtual double required_error( const std::vector<Variable*>& variables ) const = 0;
203
241 virtual double optional_delta_error( const std::vector<Variable*>& variables, const std::vector<int>& indexes, const std::vector<int>& candidate_values ) const;
242
258 virtual void conditional_update_data_structures( const std::vector<Variable*>& variables, int index, int new_value );
259
265 inline double get_current_error() const { return _current_error; }
266
268 inline int get_id() const { return _id; }
269
270 public:
276 Constraint( const std::vector<int>& variables_index );
277
283 Constraint( const std::vector<Variable>& variables );
284
286 Constraint( const Constraint& other ) = default;
288 Constraint( Constraint&& other ) = default;
289
291 Constraint& operator=( const Constraint& other ) = delete;
293 Constraint& operator=( Constraint&& other ) = delete;
294
296 virtual ~Constraint() = default;
297
303 bool has_variable( int var_id ) const;
304
306 friend std::ostream& operator<<( std::ostream& os, const Constraint& c )
307 {
308 return os << "Constraint type: " << typeid(c).name()
309 << "\nId: " << c._id
310 << "\n########";
311 }
312 };
313
314 /**********************/
316 /**********************/
317 // PureOptimization is used when no constraints have been given to the solver (ie, for pure optimization runs).
319 {
320 double required_error( const std::vector<Variable*>& variables ) const
321 {
322 return 0.;
323 }
324
325 double optional_delta_error( const std::vector<Variable*>& variables, const std::vector<int>& indexes, const std::vector<int>& candidate_values ) const
326 {
327 return 0.;
328 }
329
330 public:
331 PureOptimization( const std::vector<Variable>& variables )
332 : Constraint( variables )
333 { }
334 };
335
336}
Definition constraint.hpp:63
Constraint(const Constraint &other)=default
Default copy contructor.
int get_id() const
Inline method to get the unique id of the Constraint object.
Definition constraint.hpp:268
friend class SearchUnit
Definition constraint.hpp:64
bool has_variable(int var_id) const
Constraint(const std::vector< int > &variables_index)
virtual void conditional_update_data_structures(const std::vector< Variable * > &variables, int index, int new_value)
virtual double optional_delta_error(const std::vector< Variable * > &variables, const std::vector< int > &indexes, const std::vector< int > &candidate_values) const
double get_current_error() const
Definition constraint.hpp:265
virtual double required_error(const std::vector< Variable * > &variables) const =0
Constraint(const std::vector< Variable > &variables)
Constraint & operator=(Constraint &&other)=delete
Move assignment operator disabled.
virtual ~Constraint()=default
Default virtual destructor.
friend std::ostream & operator<<(std::ostream &os, const Constraint &c)
To have a nicer stream of Constraint.
Definition constraint.hpp:306
Constraint(Constraint &&other)=default
Default move contructor.
Constraint & operator=(const Constraint &other)=delete
Copy assignment operator disabled.
Definition model_builder.hpp:63
Definition constraint.hpp:319
PureOptimization(const std::vector< Variable > &variables)
Definition constraint.hpp:331
Definition solver.hpp:119
Definition auxiliary_data.hpp:38