ocra-recipes
Doxygen documentation for the ocra-recipes repository
Constraint.h
Go to the documentation of this file.
1 
15 #ifndef _OCRABASE_CONSTRAINT_H_
16 #define _OCRABASE_CONSTRAINT_H_
17 
18 #ifdef WIN32
19 # pragma once
20 #endif
21 
22 
23 // includes
24 #include "ocra/optim/Variable.h"
25 #include "ocra/optim/Function.h"
27 #include <ocra/util/Macros.h>
28 #include <boost/static_assert.hpp>
29 #include <boost/type_traits/is_base_of.hpp>
30 
31 
32 //#include <sstream>
33 
39 namespace ocra
40 {
48  //never change this enum
50  {
51  CSTR_EQUAL_ZERO=0, //> \f$ f(x,t) = 0 \f$
52  CSTR_EQUAL_B, //> \f$ f(x,t) = b \f$
53  CSTR_LOWER_ZERO, //> \f$ f(x,t) \le 0 \f$
54  CSTR_LOWER_U, //> \f$ f(x,t) \le u \f$
55  CSTR_GREATER_ZERO, //> \f$ f(x,t) \ge 0 \f$
56  CSTR_GREATER_L, //> \f$ f(x,t) \ge l \f$
57  CSTR_LOWER_AND_GREATER //> \f$ l \le f(x,t) \le u \f$
58  };
59 
99  template<class T>
101  : public Constraint<typename T::functionType_t>
102  , public FunctionInterfaceMapping<Constraint<T> >
103  //TODO [mineur] ? Function could be put to T::functionType_t to verify
104  //that functionType_t is defined according to the inheritance tree of Function
105  {
106  DEFINE_CLASS_POINTER_TYPEDEFS(Constraint<T>);
107  private:
109 
113  Constraint& operator= (const Constraint&);
115 
116  public:
131  Constraint(T* function, bool equality, const VectorXd& v=VectorXd());
132 
149  Constraint(T* function, const VectorXd& l=VectorXd(), const VectorXd& u=VectorXd());
150 
152  inline operator const T& () {return static_cast<T&>(BaseConstraint::getFunction());}
153 
156  inline virtual T& getFunction(void) {return static_cast<T&>(BaseConstraint::getFunction());}
157  inline virtual const T& getFunction(void) const {return static_cast<const T&>(BaseConstraint::getFunction());}
159 
160  private:
161  typedef boost::is_base_of<Function, T> T_must_derived_from_Function;
162  BOOST_STATIC_ASSERT(T_must_derived_from_Function ::value);
163  };
164 
165 
166 
167 
168 
169 
170 
171 
172 
173  template<>
175  : public FunctionInterfaceMapping<Constraint<Function> >
176  , public SubjectBase<EVT_CSTR_CHANGE_BOUNDS_NUMBER>
177  {
178  // ------------------------ structures --------------------------------------
179  public:
180  /* The slack variable functionalities are disabled for now
181  class UpdatableSlackVariable: public ObserverSubject
182  {
183  private :
184  UpdatableSlackVariable();
185  UpdatableSlackVariable(UpdatableSlackVariable&);
186  public:
187  UpdatableSlackVariable(Function* f)
188  :_f(f)
189  {
190  std::stringstream s;
191  s << "_slack_";
192  s << cpt++;
193  _slack = new BaseVariable(s.str(), f->getDimension());
194  f->attach(*this);
195  }
196 
197  ~UpdatableSlackVariable()
198  {
199  delete _slack;
200  _f->completelyDetach(*this);
201  }
202 
203  virtual void updateSize(void);
204  inline Variable* getSlackVariable(void) {return _slack;}
205 
206  protected:
207  static int cpt;
208  BaseVariable* _slack;
209  Function* _f;
210  };*/
211 
212  // ------------------------ constructors ------------------------------------
213  private:
217  Constraint& operator= (const Constraint&);
219 
220  public:
223  Constraint(Function* function, bool equality, const VectorXd& v=VectorXd());
224  Constraint(Function* function, const VectorXd& l=VectorXd(), const VectorXd& u=VectorXd());
226 
227  // ------------------------ public interface --------------------------------
228  public:
231  inline virtual Function& getFunction() {return _function;}
232  inline virtual const Function& getFunction() const {return _function;}
234 
243  inline bool isRespected(int index=-1) const;
244 
247  inline bool isEquality() const;
248  inline bool isInequality() const;
250 
263  void setB(const VectorXd& b);
264 
275  void setL(const VectorXd& l);
276 
287  void setU(const VectorXd& u);
288 
301  void setLandU(const VectorXd& l, const VectorXd& u);
303 
306  eConstraintType getType() const;
311  const VectorXd& getB() const;
316  const VectorXd& getL() const;
321  const VectorXd& getU() const;
323 
329  void setViolationTolerance(double tol);
330  double getViolationTolerance() const;
332 
333  /* methods related to slack variable,
334  void makeSlacked();
335  void unmakeSlacked();
336  inline bool isSlacked() const;
337  inline Variable* getSlackVariable();
338  */
339 
340  // ------------------------ protected members -------------------------------
341  protected:
342  Function& _function; //< the function on which the constaint is built
343 
344  // ------------------------ private members ---------------------------------
345  private:
346  eConstraintType _type; //< true if this is an equality constraint
347  VectorXd _l; //< lower bound
348  VectorXd _u; //< upper bound, or equality value (b)
349  double _violation; //< accepted violation of the constraint
350  // UpdatableSlackVariable* _slack; //< possible slack variables
351 
352 
353  //TODO [mineur] : add a scaling factor : need Constraint to be an observer and have its own memory for results
354  };
355 
356 
357 
358 
359 
360  inline bool Constraint<Function>::isRespected(int index) const
361  {
362  if (index < 0)
363  {
364  switch (_type)
365  {
366  case CSTR_EQUAL_ZERO: return getValue().isZero(_violation); break;
367  case CSTR_EQUAL_B: return ((getValue().array()-_u.array()).abs() <= _violation).all(); break;
368  case CSTR_LOWER_ZERO: return (getValue().array() <= _violation).all(); break;
369  case CSTR_LOWER_U: return ((getValue().array()-_u.array()) <= _violation).all(); break;
370  case CSTR_GREATER_ZERO: return (getValue().array() >= -_violation).all(); break;
371  case CSTR_GREATER_L: return ((getValue().array()-_l.array()) >= -_violation).all(); break;
372  case CSTR_LOWER_AND_GREATER: return ((getValue().array()-_u.array()) <= _violation).all()
373  && ((getValue().array()-_l.array()) >= -_violation).all(); break;
374  default:
375  throw std::runtime_error("[Constraint<T>::isValid] invalid constraint type");
376  }
377  }
378  else
379  {
380  switch (_type)
381  {
382  case CSTR_EQUAL_ZERO: return fabs(getValue(index)) <= _violation; break;
383  case CSTR_EQUAL_B: return fabs(getValue(index)-_u[index]) <= _violation; break;
384  case CSTR_LOWER_ZERO: return getValue(index) <= _violation; break;
385  case CSTR_LOWER_U: return (getValue(index)-_u[index]) <= _violation; break;
386  case CSTR_GREATER_ZERO: return getValue(index) >= -_violation; break;
387  case CSTR_GREATER_L: return (getValue(index)-_l[index]) >= -_violation; break;
388  case CSTR_LOWER_AND_GREATER: return (getValue(index)-_u[index]) <= _violation
389  && (getValue(index)-_l[index]) >= -_violation; break;
390  default:
391  throw std::runtime_error("[Constraint<T>::isValid] invalid constraint type");
392  }
393  }
394  }
395 
397  {
398  return _type < CSTR_LOWER_ZERO;
399  }
400 
402  {
403  return _type >= CSTR_LOWER_ZERO;
404  }
405 
406  inline void Constraint<Function>::setB(const VectorXd& b)
407  {
408  ocra_assert(isEquality() && "You can change b only for an equality constraint");
409  if (b.size() > 0)
410  {
411  ocra_assert(b.size() == getDimension() && "b has not the size of the function");
412  _type = CSTR_EQUAL_B;
413  }
414  else
415  _type = CSTR_EQUAL_ZERO;
416  _u = b;
417  }
418 
419  inline void Constraint<Function>::setL(const VectorXd& l)
420  {
421  ocra_assert(isInequality() && "You can change l only for an inequality constraint");
422  if (l.size() > 0)
423  {
424  ocra_assert(l.size() == getDimension() && "l has not the size of the function");
425  ocra_assert(
426  (
427  _type == CSTR_GREATER_ZERO
428  || _type == CSTR_GREATER_L
429  || (_type == CSTR_LOWER_ZERO && (l.array()<0).all() )
430  || (_u.size() != 0 && (l.array()-_violation < _u.array()).all())
431  )
432  && "when there is a upper bound, it must be greater than l");
433  switch(_type)
434  {
435  case CSTR_LOWER_ZERO: _u = VectorXd::Zero(getDimension()); //no break here on purpose
436  case CSTR_LOWER_U: _type = CSTR_LOWER_AND_GREATER;
438  case CSTR_GREATER_ZERO: _type = CSTR_GREATER_L; break;
439  case CSTR_GREATER_L: /*nothing to do*/ break;
440  case CSTR_LOWER_AND_GREATER: /*nothing to do*/ break;
441  }
442  }
443  else
444  {
445  switch(_type)
446  {
447  case CSTR_LOWER_ZERO: /*nothing to do*/ break;
448  case CSTR_LOWER_U: /*nothing to do*/ break;
449  case CSTR_GREATER_ZERO: /*nothing to do*/ break;
450  case CSTR_GREATER_L: _type = CSTR_GREATER_ZERO; break;
451  case CSTR_LOWER_AND_GREATER: _type = CSTR_LOWER_U;
453  }
454  }
455  _l = l;
456  }
457 
458  inline void Constraint<Function>::setU(const VectorXd& u)
459  {
460  ocra_assert(isInequality() && "You can change u only for an inequality constraint");
461  if (u.size() > 0)
462  {
463  ocra_assert(u.size() == getDimension() && "u has not the size of the function");
464  ocra_assert(
465  (
466  _type == CSTR_LOWER_ZERO
467  || _type == CSTR_LOWER_U
468  || ( _type == CSTR_GREATER_ZERO && (u.array()>0).all() )
469  || (_l.size() != 0 && (_l.array()-_violation < u.array()).all())
470  )
471  && "when there is a lower bound, it must be lower than u");
472  switch(_type)
473  {
474  case CSTR_LOWER_ZERO: _type = CSTR_LOWER_U; break;
475  case CSTR_LOWER_U: /*nothing to do*/ break;
476  case CSTR_GREATER_ZERO: _l = VectorXd::Zero(getDimension()); //no break here on purpose
479  case CSTR_LOWER_AND_GREATER: /*nothing to do*/ break;
480  }
481  }
482  else
483  {
484  switch(_type)
485  {
486  case CSTR_LOWER_ZERO: /*nothing to do*/ break;
487  case CSTR_LOWER_U: _type = CSTR_LOWER_ZERO; break;
488  case CSTR_GREATER_ZERO: /*nothing to do*/ break;
489  case CSTR_GREATER_L: /*nothing to do*/ break;
492  }
493  }
494  _u = u;
495  }
496 
497  inline void Constraint<Function>::setLandU(const VectorXd& l, const VectorXd& u)
498  {
499  ocra_assert(isInequality() && "You can change l and u only for an inequality constraint");
500  if (l.size()>0)
501  {
502  ocra_assert(l.size() == getDimension() && "l has not the size of the function");
503  if (u.size() > 0)
504  {
505  ocra_assert(u.size() == getDimension() && "u has not the size of the function");
506  ocra_assert((l.array()-_violation < u.array()).all() && "l must be lower than u");
507  switch(_type)
508  {
509  case CSTR_LOWER_ZERO:
510  case CSTR_LOWER_U:
511  case CSTR_GREATER_ZERO:
514  case CSTR_LOWER_AND_GREATER: /*nothing to do*/ break;
515  }
516  _l = l;
517  _u = u;
518  }
519  else
520  {
521  // l is initialized
522  // u is not initialized (u.size() == 0)
523  setL(l);
524  setU(u);
525  }
526  }
527  else
528  {
529  ocra_assert( u.size()>0 && "l and u are not initialized, constraint is undefined");
530 
531  // l is not initialized (l.size() == 0)
532  // u is initialized
533  setU(u);
534  setL(l);
535  }
536  }
537 
539  {
540  return _type;
541  }
542 
543  inline const VectorXd& Constraint<Function>::getB() const
544  {
545  ocra_assert(isEquality() && "getB() can be called only on an equality constraint");
546  return _u;
547  }
548 
549  inline const VectorXd& Constraint<Function>::getL() const
550  {
551  ocra_assert(isInequality() && "getL() can be called only on an inequality constraint");
552  return _l;
553  }
554 
555  inline const VectorXd& Constraint<Function>::getU() const
556  {
557  ocra_assert(isInequality() && "getU() can be called only on an inequality constraint");
558  return _u;
559  }
560 
562  {
563  ocra_assert(tol>=0 && "tolerance must be a positive number");
564  _violation = tol;
565  }
566 
568  {
569  return _violation;
570  }
571 
572 
573 
574  //constructors
575  template<class T>
576  inline Constraint<T>::Constraint(T *function, bool equality, const VectorXd& v)
577  :Constraint<typename T::functionType_t>(function, equality, v)
578  {
579  //force T to inherit of Function
580  //TODO [mineur] ? could be put to T::functionType_t to verify
581  //that functionType_t is defined according to the inheritance tree of Function
582  }
583 
584  template<class T>
585  inline Constraint<T>::Constraint(T* function, const VectorXd& l, const VectorXd& u)
586  :Constraint<typename T::functionType_t>(function, l, u)
587  {
588  //force T to inherit of Function
589  //TODO [mineur] ? could be put to T::functionType_t to verify
590  //that functionType_t is defined according to the inheritance tree of Function
591  }
592 
593  inline Constraint<Function>::Constraint(Function *function, bool equality, const VectorXd& v)
594  :_function(*function)/*, _slack(NULL)*/, _u(v), _violation(1.e-7)
595  {
596  if (equality)
597  {
598  if (v.size() > 0)
599  {
600  ocra_assert(v.size() == getDimension() && "v has not the size of the function");
601  _type = CSTR_EQUAL_B;
602  }
603  else
604  _type = CSTR_EQUAL_ZERO;
605  }
606  else
607  {
608  if (v.size() > 0)
609  {
610  ocra_assert(v.size() == getDimension() && "v has not the size of the function");
611  _type = CSTR_LOWER_U;
612  }
613  else
614  _type = CSTR_LOWER_ZERO;
615  }
616  }
617 
618  inline Constraint<Function>::Constraint(Function* function, const VectorXd& l, const VectorXd& u)
619  :_function(*function)/*, _slack(NULL)*/, _l(l), _u(u), _violation(1.e-7)
620  {
621  if (l.size() > 0)
622  {
623  ocra_assert(l.size() == getDimension() && "l has not the size of the function");
624  if (u.size() > 0)
625  {
626  ocra_assert(_l.size() == _u.size() && "l and u don't have the same size");
627  ocra_assert((l.array()-_violation < u.array()).all() && "l must be lower than u");
628  if (l.isApprox(u))
629  _type = CSTR_EQUAL_B;
630  else
631  _type = CSTR_LOWER_AND_GREATER;
632  }
633  else
634  _type = CSTR_GREATER_L;
635  }
636  else
637  {
638  if (u.size() > 0)
639  {
640  ocra_assert(u.size() == getDimension() && "u has not the size of the function");
641  _type = CSTR_LOWER_U;
642  }
643  else
644  _type = CSTR_GREATER_ZERO;
645  }
646  }
647 /*
648  inline bool Constraint<Function>::isSlacked(void) const
649  {
650  return _slack != NULL;
651  }
652 
653  inline Variable* Constraint<Function>::getSlackVariable(void)
654  {
655  if (_slack != NULL)
656  return _slack->getSlackVariable();
657  else
658  return NULL;
659  }*/
660 }
661 
666 //#include "ocra/optim/LinearTask.h"
667 //#include "ocra/optim/SecondOrderLinearTask.h"
668 //#include "ocra/optim/QuadraticFunction.h"
669 
670 namespace ocra
671 {
677 // typedef Constraint<LinearTask> TaskConstraint;
678 // typedef Constraint<SecondOrderLinearTask> SecondOrderTaskConstraint;
679 // typedef Constraint<QuadraticFunction> QuadraticConstraint;
680 }
681 
682 #endif //_OCRABASE_CONSTRAINT_H_
683 
684 // cmake:sourcegroup=Constraint
Declaration file of the IdentityFunction class.
virtual Function & getFunction()
Definition: Constraint.h:231
Constraint< IdentityFunction > IdentityConstraint
Definition: Constraint.h:675
Constraint< LinearFunction > LinearConstraint
Definition: Constraint.h:673
Constraint< BoundFunction > BoundConstraint
Definition: Constraint.h:674
Declaration file of the FunctionInterfaceMapping struct.
Constraint< Function > GenericConstraint
Definition: Constraint.h:672
Optimization-based Robot Controller namespace. a library of classes to write and solve optimization p...
Function class.
Definition: Function.h:77
Constraint class.
Definition: Constraint.h:100
Declaration file of the LinearFunction class.
virtual T & getFunction(void)
Definition: Constraint.h:156
virtual const Function & getFunction() const
Definition: Constraint.h:232
Declaration file of the DiagonalLinearFunction class.
Declaration file of the Function class.
Declaration file of the BoundFunction class.
virtual const T & getFunction(void) const
Definition: Constraint.h:157
Constraint< DiagonalLinearFunction > DiagonalLinearConstraint
Definition: Constraint.h:676
#define ocra_assert(ocra_expression)
Definition: ocra_assert.h:45
Declaration file of the Variable class.
eConstraintType
Definition: Constraint.h:49