Turi Create  4.0
constraints-inl.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_CONSTRAINTS_H_
7 #define TURI_CONSTRAINTS_H_
8 
9 #include <string>
10 #include <core/data/flexible_type/flexible_type.hpp>
11 
12 // Eigen
13 #include <Eigen/Core>
14 #include <Eigen/SparseCore>
15 
16 // Optimizaiton
17 #include <ml/optimization/utils.hpp>
18 #include <ml/optimization/optimization_interface.hpp>
19 #include <ml/optimization/constraint_interface.hpp>
20 
21 // TODO: List of todo's for this file
22 //------------------------------------------------------------------------------
23 //
24 
25 namespace turi {
26 
27 namespace optimization {
28 
29 /**
30  * \ingroup group_optimization
31  * \addtogroup optimization_constraints Optimization Constraints
32  * \{
33  */
34 
35 
36 /**
37  * Interface for non-negative constriants.
38  * x >= 0
39  */
41 
42  protected:
43 
44  size_t variables; /**< # Variables in the problem */
45 
46  public:
47 
48 
49  /**
50  * Default constructor.
51  */
52  non_negative_orthant(const size_t& _variables){
53  variables = _variables;
54  }
55 
56  /**
57  * Default desctuctor. Do nothing.
58  */
60  }
61 
62 
63  /**
64  * Project a dense point into the constraint space.
65  * \param[in,out] point Point (Dense Vector)
66  *
67  * Given a convex set X, the projection operator is given by
68  * P(y) = \std::max(x, o)
69  *
70  */
71  inline void project(DenseVector &point) const {
72  DASSERT_EQ(variables, point.size());
73  point = point.cwiseMax(0);
74  }
75 
76  /**
77  * Project a block of a dense point into the constraint space.
78  *
79  * \param[in,out] point A block project the point.
80  * \param[in] block_start Start index of the block
81  * \param[in] block_size Size of the block
82  *
83  * Given a convex set X, the projection operator is given by
84  * P(y) = \std::max(x, o)
85  *
86  */
87  inline void project_block(DenseVector &point, const size_t block_start, const
88  size_t block_size) const {
89  DASSERT_LE(variables, block_start + block_size);
90  DASSERT_EQ(block_size, point.size());
91  point = point.cwiseMax(0);
92  }
93 
94  /**
95  * Boolean function to deterstd::mine if a dense point is present in a constraint
96  * space.
97  * \param[in] point Point which we are querying.
98  *
99  */
100  inline bool is_satisfied(const DenseVector &point) const {
101  DASSERT_EQ(variables, point.size());
102  for(size_t i=0; i < size_t(point.size()); i++){
103  if( point(i) <= -OPTIMIZATION_ZERO)
104  return false;
105  }
106  return true;
107  }
108 
109 
110  /**
111  * A measure of the first order optimality conditions.
112  *
113  * \param[in] point Point which we are querying.
114  * \param[in] gradient Gradient at that point for a given function
115  *
116  * Use the Cauchy point as a measure of optimality. See Pg 486 of
117  * Nocedal and Wright (Edition 2)
118  *
119  */
120  inline double first_order_optimality_conditions(const DenseVector &point,
121  const DenseVector& gradient) const{
122  DASSERT_TRUE(is_satisfied(point));
123  DenseVector proj_gradient = gradient;
124  for(size_t i=0; i < size_t(point.size()); i++){
125  if(point(i) <= OPTIMIZATION_ZERO){
126  proj_gradient(i) = std::min(0.0, gradient(i));
127  } else {
128  proj_gradient(i) = gradient(i);
129  }
130  }
131  return compute_residual(proj_gradient);
132  }
133 };
134 
135 
136 
137 /**
138  * Interface for box-constraints on variables.
139  * lb <= x <= ub
140  */
142 
143  protected:
144 
145  DenseVector lb; /**< # Upper bound */
146  DenseVector ub; /**< # Lower bound */
147  size_t variables; /**< # Variables in the problem */
148 
149  public:
150 
151 
152  /**
153  * Default constructor.
154  * \param[in] _variables Number of variables
155  * \param[in] _lb Lower bound
156  * \param[in] _ub Upper bound
157  */
158  box_constraints(const double& _lb, const double& _ub, const size_t&
159  _variables){
160  variables = _variables;
161  lb.resize(variables);
162  lb.setConstant(_lb);
163  ub.resize(variables);
164  ub.setConstant(_ub);
165  }
166 
167  /**
168  * Default constructor.
169  * \param[in] _variables Number of variables
170  * \param[in] _lb Lower bound
171  * \param[in] _ub Upper bound
172  */
173  box_constraints(const DenseVector& _lb, const
174  DenseVector& _ub){
175  variables = _lb.size();
176  DASSERT_EQ(variables, _ub.size());
177  lb = _lb;
178  ub = _ub;
179  }
180 
181  /**
182  * Default desctuctor. Do nothing.
183  */
185  }
186 
187 
188  /**
189  * Project a dense point into the constraint space.
190  * \param[in,out] point Point (Dense Vector)
191  *
192  * Given a convex set X, the projection operator is given by
193  * P(y) = \std::max(x, o)
194  *
195  */
196  inline void project(DenseVector &point) const {
197  DASSERT_EQ(variables, point.size());
198  for(size_t i=0; i < size_t(point.size()); i++){
199  point(i) = std::min(std::max(point(i), lb(i)), ub(i));
200  }
201  }
202 
203  /**
204  * Project a block of a dense point into the constraint space.
205  *
206  * \param[in,out] point A block project the point.
207  * \param[in] block_start Start index of the block
208  * \param[in] block_size Size of the block
209  *
210  * Given a convex set X, the projection operator is given by
211  * P(y) = \std::max(x, o)
212  *
213  */
214  inline void project_block(DenseVector &point, const size_t block_start, const
215  size_t block_size) const {
216  DASSERT_GE(variables, block_start + block_size);
217  DASSERT_EQ(block_size, point.size());
218  for(size_t i=0; i < block_size; i++){
219  point(i) = std::min(std::max(point(i),
220  lb(block_start + i)), ub(block_start + i));
221  }
222  }
223 
224  /**
225  * Boolean function to determine if a dense point is present in a constraint
226  * space.
227  * \param[in] point Point which we are querying.
228  *
229  */
230  inline bool is_satisfied(const DenseVector &point) const {
231  DASSERT_EQ(variables, point.size());
232  for(size_t i=0; i < size_t(point.size()); i++){
233  if( point(i) <= lb(i) - OPTIMIZATION_ZERO ||
234  point(i) >= ub(i) + OPTIMIZATION_ZERO)
235  return false;
236  }
237  return true;
238  }
239 
240 
241  /**
242  * A measure of the first order optimality conditions.
243  *
244  * \param[in] point Point which we are querying.
245  * \param[in] gradient Gradient at that point for a given function
246  *
247  * Use the Cauchy point as a measure of optimality. See Pg 486 of
248  * Nocedal and Wright (Edition 2)
249  *
250  */
251  inline double first_order_optimality_conditions(const DenseVector &point,
252  const DenseVector& gradient) const{
253  DASSERT_TRUE(is_satisfied(point));
254  DenseVector proj_gradient = gradient;
255  for(size_t i=0; i < size_t(point.size()); i++){
256  if(point(i) <= OPTIMIZATION_ZERO + lb(i)){
257  proj_gradient(i) = std::min(0.0, gradient(i));
258  } else if (point(i) >= ub(i) - OPTIMIZATION_ZERO){
259  proj_gradient(i) = std::max(0.0, gradient(i));
260  } else {
261  proj_gradient(i) = gradient(i);
262  }
263  }
264  return compute_residual(proj_gradient);
265  }
266 
267 
268 };
269 
270 
271 } // optimization
272 } // turicreate
273 
274 #endif
bool is_satisfied(const DenseVector &point) const
double first_order_optimality_conditions(const DenseVector &point, const DenseVector &gradient) const
const double OPTIMIZATION_ZERO
Optimization method zero.
non_negative_orthant(const size_t &_variables)
bool is_satisfied(const DenseVector &point) const
void project(DenseVector &point) const
double first_order_optimality_conditions(const DenseVector &point, const DenseVector &gradient) const
void project_block(DenseVector &point, const size_t block_start, const size_t block_size) const
double compute_residual(const DenseVector &gradient)
box_constraints(const double &_lb, const double &_ub, const size_t &_variables)
void project_block(DenseVector &point, const size_t block_start, const size_t block_size) const
void project(DenseVector &point) const
box_constraints(const DenseVector &_lb, const DenseVector &_ub)
#define DASSERT_TRUE(cond)
Definition: assertions.hpp:364