hyper_graph_optimization_problem_base.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement
4  *
5  * Copyright (c) 2020,
6  * TU Dortmund - Institute of Control Theory and Systems Engineering.
7  * All rights reserved.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  *
22  * Authors: Christoph Rösmann
23  *********************************************************************/
24 
26 
27 namespace corbo {
28 
30 {
31  assert(_graph.hasVertexSet());
32 
33  // Vertex set
35  if (vertices->isModified())
36  {
37  vertices->computeActiveVertices();
38  vertices->setModified(false); // avoid recomputation of active vertices
39  _dim_param = vertices->getParameterDimension();
40  vertices->computeVertexIndices();
41  }
42 }
43 
45 {
46  assert(_graph.hasEdgeSet());
47 
49  if (edges->isModified())
50  {
51  edges->getDimensions(_dim_non_lsq_obj, _dim_lsq_obj, _dim_eq, _dim_ineq);
52  edges->computeEdgeIndices();
53  edges->setModified(false);
54  }
55 }
56 
58 {
59  assert(_graph.hasEdgeSet());
60  assert(_graph.hasVertexSet());
61 
64 
65  _graph_precomputed = true;
66 }
67 
69 {
70  if (_graph.hasEdgeSet()) _graph.getEdgeSet()->clear();
71  _graph_precomputed = false;
72 
73  _dim_param = 0;
74  _dim_non_lsq_obj = 0;
75  _dim_lsq_obj = 0;
76  _dim_eq = 0;
77  _dim_ineq = 0;
78 }
79 
80 // implmements interface method
82 {
83  assert(_graph.hasEdgeSet());
85 
86  double value = 0;
87 
89  // Iterate plain objective edges
90  for (BaseEdge::Ptr& edge : edges->getObjectiveEdgesRef())
91  {
92  value += edge->computeSumOfValues();
93  }
94  // Iterate mixed edges
95  for (BaseMixedEdge::Ptr& edge : edges->getMixedEdgesRef())
96  {
97  // we consider only non-least squares objectives here
98  if (edge->isObjectiveLeastSquaresForm() || edge->getObjectiveDimension() == 0) continue;
99 
100  edge->precompute();
101  value += edge->computeSumOfObjectiveValues();
102  }
103  return value;
104 }
105 
107 {
108  assert(_graph.hasEdgeSet());
111  // Iterate plain objective edges
112  for (BaseEdge::Ptr& edge : edges->getLsqObjectiveEdgesRef())
113  {
114  edge->computeValues(values.segment(edge->getEdgeIdx(), edge->getDimension()));
115  }
116  // Iterate mixed edges
117  for (BaseMixedEdge::Ptr& edge : edges->getMixedEdgesRef())
118  {
119  // we consider only least squares objectives here
120  if (!edge->isObjectiveLeastSquaresForm() || edge->getObjectiveDimension() == 0) continue;
121 
122  edge->precompute();
123  edge->computeObjectiveValues(values.segment(edge->getEdgeObjectiveIdx(), edge->getObjectiveDimension()));
124  }
125 }
126 
128 {
129  assert(_graph.hasEdgeSet());
131 
132  double value = 0;
133 
135  // Iterate plain objective edges
136  for (BaseEdge::Ptr& edge : edges->getObjectiveEdgesRef())
137  {
138  PRINT_DEBUG_COND_ONCE(edge->isLeastSquaresForm(), "BaseHyperGraphOptimizationProblem::computeValueObjective(): "
139  << "least-squares edge found in non-lsq container");
140  value += edge->computeSumOfValues();
141  }
142  for (BaseEdge::Ptr& edge : edges->getLsqObjectiveEdgesRef())
143  {
144  PRINT_DEBUG_COND_ONCE(!edge->isLeastSquaresForm(), "BaseHyperGraphOptimizationProblem::computeValueObjective(): "
145  << "non-least-squares edge found in lsq container");
146  value += edge->computeSquaredNormOfValues();
147  }
148  // Iterate mixed edges
149  for (BaseMixedEdge::Ptr& edge : edges->getMixedEdgesRef())
150  {
151  if (edge->getObjectiveDimension() == 0) continue;
152 
153  edge->precompute();
154  if (edge->isObjectiveLeastSquaresForm())
155  value += edge->computeSquaredNormOfObjectiveValues();
156  else
157  value += edge->computeSumOfObjectiveValues();
158  }
159  return value;
160 }
161 
163 {
164  assert(_graph.hasEdgeSet());
167  // Iterate plain equality edges
168  for (BaseEdge::Ptr& edge : edges->getEqualityEdgesRef())
169  {
170  edge->computeValues(values.segment(edge->getEdgeIdx(), edge->getDimension()));
171  }
172  // Iterate mixed edges
173  for (BaseMixedEdge::Ptr& edge : edges->getMixedEdgesRef())
174  {
175  if (edge->getEqualityDimension() == 0) continue;
176 
177  edge->precompute();
178  edge->computeEqualityValues(values.segment(edge->getEdgeEqualityIdx(), edge->getEqualityDimension()));
179  }
180 }
181 
183 {
184  assert(_graph.hasEdgeSet());
187  // Iterate plain inequality edges
188  for (BaseEdge::Ptr& edge : edges->getInequalityEdgesRef())
189  {
190  edge->computeValues(values.segment(edge->getEdgeIdx(), edge->getDimension()));
191  }
192  // Iterate mixed edges
193  for (BaseMixedEdge::Ptr& edge : edges->getMixedEdgesRef())
194  {
195  if (edge->getInequalityDimension() == 0) continue;
196 
197  edge->precompute();
198  edge->computeInequalityValues(values.segment(edge->getEdgeInequalityIdx(), edge->getInequalityDimension()));
199  }
200 }
201 
204 {
205  assert(_graph.hasEdgeSet());
207 
209  // Iterate plain objective edges
210  non_lsq_obj_value = 0;
211  for (BaseEdge::Ptr& edge : edges->getObjectiveEdgesRef())
212  {
213  non_lsq_obj_value += edge->computeSumOfValues();
214  }
215  // Iterate lsq objective edges
216  for (BaseEdge::Ptr& edge : edges->getLsqObjectiveEdgesRef())
217  {
218  edge->computeValues(lsq_obj_values.segment(edge->getEdgeIdx(), edge->getDimension()));
219  }
220  // Iterate plain equality edges
221  for (BaseEdge::Ptr& edge : edges->getEqualityEdgesRef())
222  {
223  edge->computeValues(eq_values.segment(edge->getEdgeIdx(), edge->getDimension()));
224  }
225  // Iterate plain inequality edges
226  for (BaseEdge::Ptr& edge : edges->getInequalityEdgesRef())
227  {
228  edge->computeValues(ineq_values.segment(edge->getEdgeIdx(), edge->getDimension()));
229  }
230  // Iterate mixed edges
231  for (BaseMixedEdge::Ptr& edge : edges->getMixedEdgesRef())
232  {
233  edge->precompute();
234 
235  if (edge->isObjectiveLeastSquaresForm())
236  {
237  edge->computeObjectiveValues(lsq_obj_values.segment(edge->getEdgeObjectiveIdx(), edge->getObjectiveDimension()));
238  }
239  else
240  {
241  non_lsq_obj_value += edge->computeSumOfObjectiveValues();
242  }
243 
244  edge->computeEqualityValues(eq_values.segment(edge->getEdgeEqualityIdx(), edge->getEqualityDimension()));
245  edge->computeInequalityValues(ineq_values.segment(edge->getEdgeInequalityIdx(), edge->getInequalityDimension()));
246  }
247 }
248 
250 {
251  assert(_graph.hasVertexSet());
253 
254  int dim = 0;
255  // Iterate vertices
256  for (const VertexInterface* vertex : _graph.getVertexSet()->getActiveVertices())
257  {
258  dim += vertex->getNumberFiniteBounds(true); // only unfixed elements
259  }
260  return dim;
261 }
262 
264 {
265  assert(_graph.hasVertexSet());
267 
268  int dim = 0;
269  // Iterate vertices
270  for (const VertexInterface* vertex : _graph.getVertexSet()->getActiveVertices())
271  {
272  dim += vertex->getNumberFiniteLowerBounds(true); // only unfixed elements
273  dim += vertex->getNumberFiniteUpperBounds(true); // only unfixed elements
274  }
275  return dim;
276 }
277 
279 {
280  // we don't have any better strategy than default currently
281  computeValuesInequality(values);
282  for (int i = 0; i < values.size(); ++i)
283  {
284  if (values[i] < 0)
285  values[i] = 0;
286  else
287  values[i] *= weight;
288  }
289 }
290 
292 {
293  assert(_graph.hasVertexSet());
295 
296  int idx = 0;
297  for (const VertexInterface* vertex : _graph.getVertexSet()->getActiveVertices())
298  {
299  for (int i = 0; i < vertex->getDimension(); ++i)
300  {
301  if (vertex->isFixedComponent(i)) continue;
302 
303  if (vertex->hasFiniteLowerBound(i) || vertex->hasFiniteUpperBound(i))
304  {
305  if (vertex->getData()[i] < vertex->getLowerBounds()[i])
306  values[idx] = vertex->getLowerBounds()[i] - vertex->getData()[i];
307  else if (vertex->getData()[i] > vertex->getUpperBounds()[i])
308  values[idx] = vertex->getData()[i] - vertex->getUpperBounds()[i];
309  else
310  values[idx] = 0;
311  ++idx;
312  }
313  }
314  }
315 }
316 
318 {
319  assert(_graph.hasVertexSet());
321 
322  int idx = 0;
323  for (const VertexInterface* vertex : _graph.getVertexSet()->getActiveVertices())
324  {
325  for (int i = 0; i < vertex->getDimension(); ++i)
326  {
327  if (vertex->isFixedComponent(i)) continue;
328 
329  if (vertex->hasFiniteLowerBound(i) || vertex->hasFiniteUpperBound(i))
330  {
331  lb_minus_x[idx] = vertex->getLowerBounds()[i] - vertex->getData()[i];
332  ub_minus_x[idx] = vertex->getUpperBounds()[i] - vertex->getData()[i];
333  ++idx;
334  }
335  }
336  }
337 }
338 
340  Eigen::Ref<Eigen::VectorXd> ub_finite_bounds,
341  Eigen::Ref<Eigen::VectorXd> x_finite_bounds)
342 {
343  assert(_graph.hasVertexSet());
345 
346  int idx = 0;
347  for (const VertexInterface* vertex : _graph.getVertexSet()->getActiveVertices())
348  {
349  for (int i = 0; i < vertex->getDimension(); ++i)
350  {
351  if (vertex->isFixedComponent(i)) continue;
352 
353  if (vertex->hasFiniteLowerBound(i) || vertex->hasFiniteUpperBound(i))
354  {
355  lb_finite_bounds[idx] = vertex->getLowerBounds()[i];
356  ub_finite_bounds[idx] = vertex->getUpperBounds()[i];
357  x_finite_bounds[idx] = vertex->getData()[i];
358  ++idx;
359  }
360  }
361  }
362 }
363 
365 {
366  assert(_graph.hasVertexSet());
368  assert(jacobian.rows() == finiteCombinedBoundsDimension());
369  assert(jacobian.cols() == getParameterDimension());
370 
371  jacobian.setZero();
372 
373  int row_idx = 0;
374  for (const VertexInterface* vertex : _graph.getVertexSet()->getActiveVertices())
375  {
376  int vert_idx = vertex->getVertexIdx();
377  int free_idx = 0;
378  for (int i = 0; i < vertex->getDimension(); ++i)
379  {
380  if (vertex->isFixedComponent(i)) continue;
381 
382  if (vertex->hasFiniteLowerBound(i) || vertex->hasFiniteUpperBound(i))
383  {
384  if (vertex->getData()[i] < vertex->getLowerBounds()[i])
385  {
386  jacobian(row_idx, vert_idx + free_idx) = -weight;
387  }
388  else if (vertex->getData()[i] > vertex->getUpperBounds()[i])
389  {
390  jacobian(row_idx, vert_idx + free_idx) = weight;
391  }
392  ++row_idx;
393  }
394  ++free_idx;
395  }
396  }
397 }
398 
400 
403 {
404  assert(i_row.size() == computeSparseJacobianFiniteCombinedBoundsNNZ());
405  assert(j_col.size() == i_row.size());
406 
407  int row_idx = 0;
408  for (const VertexInterface* vertex : _graph.getVertexSet()->getActiveVertices())
409  {
410  int vert_idx = vertex->getVertexIdx();
411  int free_idx = 0;
412  for (int i = 0; i < vertex->getDimension(); ++i)
413  {
414  if (vertex->isFixedComponent(i)) continue;
415 
416  if (vertex->hasFiniteLowerBound(i) || vertex->hasFiniteUpperBound(i))
417  {
418  i_row[row_idx] = row_idx;
419  j_col[row_idx] = vert_idx + free_idx;
420  ++row_idx;
421  }
422  ++free_idx;
423  }
424  }
425 }
426 
428 {
429  assert(values.size() == computeSparseJacobianFiniteCombinedBoundsNNZ());
430 
431  int row_idx = 0;
432  for (const VertexInterface* vertex : _graph.getVertexSet()->getActiveVertices())
433  {
434  for (int i = 0; i < vertex->getDimension(); ++i)
435  {
436  if (vertex->isFixedComponent(i)) continue;
437 
438  if (vertex->hasFiniteLowerBound(i) || vertex->hasFiniteUpperBound(i))
439  {
440  if (vertex->getData()[i] < vertex->getLowerBounds()[i])
441  {
442  values(row_idx) = -weight;
443  }
444  else if (vertex->getData()[i] > vertex->getUpperBounds()[i])
445  {
446  values(row_idx) = weight;
447  }
448  else
449  {
450  values(row_idx) = 0.0;
451  }
452  ++row_idx;
453  }
454  }
455  }
456 }
457 
459 {
460  assert(_graph.hasVertexSet());
462  assert(jacobian.rows() == finiteCombinedBoundsDimension());
463  assert(jacobian.cols() == getParameterDimension());
464 
465  jacobian.setZero();
466 
467  int row_idx = 0;
468  for (const VertexInterface* vertex : _graph.getVertexSet()->getActiveVertices())
469  {
470  int vert_idx = vertex->getVertexIdx();
471  int free_idx = 0;
472  for (int i = 0; i < vertex->getDimension(); ++i)
473  {
474  if (vertex->isFixedComponent(i)) continue;
475 
476  if (vertex->hasFiniteLowerBound(i) || vertex->hasFiniteUpperBound(i))
477  {
478  jacobian(row_idx, vert_idx + free_idx) = 1;
479  ++row_idx;
480  }
481  ++free_idx;
482  }
483  }
484 }
485 
486 bool BaseHyperGraphOptimizationProblem::checkIfAllUnfixedParam(std::function<bool(double, int)> fun)
487 {
488  assert(_graph.hasVertexSet());
490 
491  int idx = 0;
492  for (const VertexInterface* vertex : _graph.getVertexSet()->getActiveVertices())
493  {
494  for (int i = 0; i < vertex->getDimension(); ++i)
495  {
496  if (vertex->isFixedComponent(i)) continue;
497 
498  if (vertex->hasFiniteLowerBound(i) || vertex->hasFiniteUpperBound(i))
499  {
500  if (!fun(vertex->getData()[i], idx)) return false;
501  ++idx;
502  }
503  }
504  }
505  return true;
506 }
507 
508 } // namespace corbo
OptimizationEdgeSet::Ptr getEdgeSet() const
Definition: hyper_graph.h:73
#define PRINT_DEBUG_COND_ONCE(cond, msg)
Print msg-stream only if cond == true, only once and only if project is compiled in Debug-mode...
Definition: console.h:77
void computeDenseJacobianFiniteCombinedBounds(Eigen::Ref< Eigen::MatrixXd > jacobian, double weight=1.0) override
Compute the Jacobian for finite combined bounds.
Generic interface class for vertices.
int getParameterDimension() override
Effictive dimension of the optimization parameter set (changeable, non-fixed part) ...
int finiteCombinedBoundsDimension() override
Dimension of the set of finite bounds (combined such that each ub and lb component define a single di...
void computeDistanceFiniteCombinedBounds(Eigen::Ref< Eigen::VectorXd > values) override
Compute the distance to finite bound values (combined lower and upper)
void computeValuesLsqObjective(Eigen::Ref< Eigen::VectorXd > values) override
Compute the objective function values f(x) for the current parameter set.
void computeValuesEquality(Eigen::Ref< Eigen::VectorXd > values) override
Compute the equality constraint values ceq(x) for the current parameter set.
void computeValuesActiveInequality(Eigen::Ref< Eigen::VectorXd > values, double weight=1.0) override
Compute the values of the active inequality constraints (elementwise max(0, c(x))) ...
void computeSparseJacobianFiniteCombinedBoundsValues(Eigen::Ref< Eigen::VectorXd > values, double weight=1.0) override
std::shared_ptr< OptimizationEdgeSet > Ptr
Definition: edge_set.h:77
std::shared_ptr< BaseMixedEdge > Ptr
void getParametersAndBoundsFinite(Eigen::Ref< Eigen::VectorXd > lb_finite_bounds, Eigen::Ref< Eigen::VectorXd > ub_finite_bounds, Eigen::Ref< Eigen::VectorXd > x_finite_bounds) override
Return bound and parameter vectors only for finite boudns.
void computeDenseJacobianFiniteCombinedBoundsIdentity(Eigen::Ref< Eigen::MatrixXd > jacobian) override
Compute the Jacobian for finite combined bounds.
std::shared_ptr< BaseEdge > Ptr
void computeLowerAndUpperBoundDiff(Eigen::Ref< Eigen::VectorXd > lb_minus_x, Eigen::Ref< Eigen::VectorXd > ub_minus_x) override
Compute the distance between parameters and bounds.
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:192
void computeValuesInequality(Eigen::Ref< Eigen::VectorXd > values) override
Compute the inequality constraint values c(x) for the current parameter set.
int finiteBoundsDimension() override
Dimension of the set of finite bounds (individual bounds ub and lb)
bool hasVertexSet() const
Definition: hyper_graph.h:71
std::shared_ptr< VertexSetInterface > Ptr
Definition: vertex_set.h:48
bool checkIfAllUnfixedParam(std::function< bool(double, int)> fun)
Check if a function taking the parameter value and unfixed-idx is true for all unfixed parameter valu...
void computeValues(double &non_lsq_obj_value, Eigen::Ref< Eigen::VectorXd > lsq_obj_values, Eigen::Ref< Eigen::VectorXd > eq_values, Eigen::Ref< Eigen::VectorXd > ineq_values) override
VertexSetInterface::Ptr getVertexSet() const
Definition: hyper_graph.h:74
void computeSparseJacobianFiniteCombinedBoundsStructure(Eigen::Ref< Eigen::VectorXi > i_row, Eigen::Ref< Eigen::VectorXi > j_col) override
bool hasEdgeSet() const
Definition: hyper_graph.h:70


control_box_rst
Author(s): Christoph Rösmann
autogenerated on Mon Feb 28 2022 22:06:54