IpVector.hpp
Go to the documentation of this file.
1 // Copyright (C) 2004, 2008 International Business Machines and others.
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // $Id: IpVector.hpp 1861 2010-12-21 21:34:47Z andreasw $
6 //
7 // Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
8 
9 #ifndef __IPVECTOR_HPP__
10 #define __IPVECTOR_HPP__
11 
12 #include "IpTypes.hpp"
13 #include "IpTaggedObject.hpp"
14 #include "IpCachedResults.hpp"
15 #include "IpSmartPtr.hpp"
16 #include "IpJournalist.hpp"
17 #include "IpException.hpp"
18 
19 #include <vector>
20 
21 namespace Ipopt
22 {
25  DECLARE_STD_EXCEPTION(UNIMPLEMENTED_LINALG_METHOD_CALLED);
26 
27  /* forward declarations */
28  class VectorSpace;
29 
47  class Vector : public TaggedObject
48  {
49  public:
55  Vector(const VectorSpace* owner_space);
56 
58  virtual ~Vector();
60 
62  Vector* MakeNew() const;
63 
65  Vector* MakeNewCopy() const;
66 
73  void Copy(const Vector& x);
74 
76  void Scal(Number alpha);
77 
79  void Axpy(Number alpha, const Vector &x);
80 
82  Number Dot(const Vector &x) const;
83 
85  Number Nrm2() const;
86 
88  Number Asum() const;
89 
91  Number Amax() const;
93 
100  void Set(Number alpha);
101 
103  void ElementWiseDivide(const Vector& x);
104 
106  void ElementWiseMultiply(const Vector& x);
107 
109  void ElementWiseMax(const Vector& x);
110 
112  void ElementWiseMin(const Vector& x);
113 
115  void ElementWiseReciprocal();
116 
118  void ElementWiseAbs();
119 
121  void ElementWiseSqrt();
122 
126  void ElementWiseSgn();
127 
129  void AddScalar(Number scalar);
130 
132  Number Max() const;
133 
135  Number Min() const;
136 
138  Number Sum() const;
139 
141  Number SumLogs() const;
143 
151  void AddOneVector(Number a, const Vector& v1, Number c);
152 
155  void AddTwoVectors(Number a, const Vector& v1,
156  Number b, const Vector& v2, Number c);
160  Number FracToBound(const Vector& delta, Number tau) const;
162  void AddVectorQuotient(Number a, const Vector& z, const Vector& s,
163  Number c);
165 
168  bool HasValidNumbers() const;
169 
173  Index Dim() const;
174 
178 
186  EJournalLevel level,
187  EJournalCategory category,
188  const std::string& name,
189  Index indent=0,
190  const std::string& prefix="") const;
191  void Print(const Journalist& jnlst,
192  EJournalLevel level,
193  EJournalCategory category,
194  const std::string& name,
195  Index indent=0,
196  const std::string& prefix="") const;
198 
199  protected:
205  virtual void CopyImpl(const Vector& x)=0;
206 
208  virtual void ScalImpl(Number alpha)=0;
209 
211  virtual void AxpyImpl(Number alpha, const Vector &x)=0;
212 
214  virtual Number DotImpl(const Vector &x) const =0;
215 
217  virtual Number Nrm2Impl() const =0;
218 
220  virtual Number AsumImpl() const =0;
221 
223  virtual Number AmaxImpl() const =0;
224 
226  virtual void SetImpl(Number alpha)=0;
227 
229  virtual void ElementWiseDivideImpl(const Vector& x)=0;
230 
232  virtual void ElementWiseMultiplyImpl(const Vector& x)=0;
233 
235  virtual void ElementWiseMaxImpl(const Vector& x)=0;
236 
238  virtual void ElementWiseMinImpl(const Vector& x)=0;
239 
241  virtual void ElementWiseReciprocalImpl()=0;
242 
244  virtual void ElementWiseAbsImpl()=0;
245 
247  virtual void ElementWiseSqrtImpl()=0;
248 
250  virtual void ElementWiseSgnImpl()=0;
251 
253  virtual void AddScalarImpl(Number scalar)=0;
254 
256  virtual Number MaxImpl() const=0;
257 
259  virtual Number MinImpl() const=0;
260 
262  virtual Number SumImpl() const=0;
263 
265  virtual Number SumLogsImpl() const=0;
266 
269  virtual void AddTwoVectorsImpl(Number a, const Vector& v1,
270  Number b, const Vector& v2, Number c);
271 
273  virtual Number FracToBoundImpl(const Vector& delta, Number tau) const;
274 
276  virtual void AddVectorQuotientImpl(Number a, const Vector& z,
277  const Vector& s, Number c);
278 
282  virtual bool HasValidNumbersImpl() const;
283 
285  virtual void PrintImpl(const Journalist& jnlst,
286  EJournalLevel level,
287  EJournalCategory category,
288  const std::string& name,
289  Index indent,
290  const std::string& prefix) const =0;
292 
293  private:
303  Vector();
304 
306  Vector(const Vector&);
307 
309  Vector& operator=(const Vector&);
311 
314 
319 
322 
325 
328 
331 
334 
337 
340 
342  mutable bool cached_valid_;
343 
344  // AW: I removed this cache since it gets in the way for the
345  // quality function search
346  // /** Cache for FracToBound */
347  // mutable CachedResults<Number> frac_to_bound_cache_;
349 
350  };
351 
361  {
362  public:
368  VectorSpace(Index dim);
369 
371  virtual ~VectorSpace()
372  {}
374 
378  virtual Vector* MakeNew() const=0;
379 
381  Index Dim() const
382  {
383  return dim_;
384  }
385 
386  private:
396  VectorSpace();
397 
399  VectorSpace(const VectorSpace&);
400 
404 
406  const Index dim_;
407  };
408 
409  /* inline methods */
410  inline
412  {}
413 
414  inline
415  Vector::Vector(const VectorSpace* owner_space)
416  :
417  TaggedObject(),
418  owner_space_(owner_space),
419  dot_cache_(10),
420  nrm2_cache_tag_(0),
421  asum_cache_tag_(0),
422  amax_cache_tag_(0),
423  max_cache_tag_(0),
424  min_cache_tag_(0),
425  sum_cache_tag_(0),
426  sumlogs_cache_tag_(0),
427  cached_valid_(0)
428  {
430  }
431 
432  inline
434  {
435  return owner_space_->MakeNew();
436  }
437 
438  inline
440  {
441  // ToDo: We can probably copy also the cached values for Norms etc here
442  Vector* copy = MakeNew();
443  copy->Copy(*this);
444  return copy;
445  }
446 
447  inline
448  void Vector::Copy(const Vector& x)
449  {
450  CopyImpl(x);
451  ObjectChanged();
452  // Also copy any cached scalar values from the original vector
453  // ToDo: Check if that is too much overhead
454  TaggedObject::Tag x_tag = x.GetTag();
455  if (x_tag == x.nrm2_cache_tag_) {
458  }
459  if (x_tag == x.asum_cache_tag_) {
462  }
463  if (x_tag == x.amax_cache_tag_) {
466  }
467  if (x_tag == x.max_cache_tag_) {
470  }
471  if (x_tag == x.min_cache_tag_) {
474  }
475  if (x_tag == x.sum_cache_tag_) {
478  }
479  if (x_tag == x.sumlogs_cache_tag_) {
482  }
483  }
484 
485  inline
486  void Vector::Axpy(Number alpha, const Vector &x)
487  {
488  AxpyImpl(alpha, x);
489  ObjectChanged();
490  }
491 
492  inline
493  Number Vector::Dot(const Vector &x) const
494  {
495  // The current implementation of the caching doesn't allow to have
496  // a dependency of something with itself. Therefore, we use the
497  // Nrm2 method if the dot product is to be taken with the vector
498  // itself. Might be more efficient anyway.
499  if (this==&x) {
500  Number nrm2 = Nrm2();
501  return nrm2*nrm2;
502  }
503  Number retValue;
504  if (!dot_cache_.GetCachedResult2Dep(retValue, this, &x)) {
505  retValue = DotImpl(x);
506  dot_cache_.AddCachedResult2Dep(retValue, this, &x);
507  }
508  return retValue;
509  }
510 
511  inline
513  {
514  if (nrm2_cache_tag_ != GetTag()) {
517  }
518  return cached_nrm2_;
519  }
520 
521  inline
523  {
524  if (asum_cache_tag_ != GetTag()) {
527  }
528  return cached_asum_;
529  }
530 
531  inline
533  {
534  if (amax_cache_tag_ != GetTag()) {
537  }
538  return cached_amax_;
539  }
540 
541  inline
543  {
544  if (sum_cache_tag_ != GetTag()) {
545  cached_sum_ = SumImpl();
547  }
548  return cached_sum_;
549  }
550 
551  inline
553  {
554  if (sumlogs_cache_tag_ != GetTag()) {
557  }
558  return cached_sumlogs_;
559  }
560 
561  inline
563  {
565  ObjectChanged();
566  }
567 
568  inline
569  void Vector::Set(Number alpha)
570  {
571  // Could initialize caches here
572  SetImpl(alpha);
573  ObjectChanged();
574  }
575 
576  inline
578  {
580  ObjectChanged();
581  }
582 
583  inline
585  {
587  ObjectChanged();
588  }
589 
590  inline
592  {
594  ObjectChanged();
595  }
596 
597  inline
599  {
600  // Could initialize some caches here
602  ObjectChanged();
603  }
604 
605  inline
607  {
608  // Could initialize some caches here
610  ObjectChanged();
611  }
612 
613  inline
615  {
616  // Could initialize some caches here
618  ObjectChanged();
619  }
620 
621  inline
623  {
625  ObjectChanged();
626  }
627 
628  inline
630  {
631  // Could initialize some caches here
632  AddScalarImpl(scalar);
633  ObjectChanged();
634  }
635 
636  inline
638  {
639  if (max_cache_tag_ != GetTag()) {
640  cached_max_ = MaxImpl();
642  }
643  return cached_max_;
644  }
645 
646  inline
648  {
649  if (min_cache_tag_ != GetTag()) {
650  cached_min_ = MinImpl();
652  }
653  return cached_min_;
654  }
655 
656  inline
657  void Vector::AddOneVector(Number a, const Vector& v1, Number c)
658  {
659  AddTwoVectors(a, v1, 0., v1, c);
660  }
661 
662  inline
664  Number b, const Vector& v2, Number c)
665  {
666  AddTwoVectorsImpl(a, v1, b, v2, c);
667  ObjectChanged();
668  }
669 
670  inline
671  Number Vector::FracToBound(const Vector& delta, Number tau) const
672  {
673  /* AW: I avoid the caching here, since it leads to overhead in the
674  quality function search. Caches for this are in
675  CalculatedQuantities.
676  Number retValue;
677  std::vector<const TaggedObject*> tdeps(1);
678  tdeps[0] = &delta;
679  std::vector<Number> sdeps(1);
680  sdeps[0] = tau;
681  if (!frac_to_bound_cache_.GetCachedResult(retValue, tdeps, sdeps)) {
682  retValue = FracToBoundImpl(delta, tau);
683  frac_to_bound_cache_.AddCachedResult(retValue, tdeps, sdeps);
684  }
685  return retValue;
686  */
687  return FracToBoundImpl(delta, tau);
688  }
689 
690  inline
692  const Vector& s, Number c)
693  {
694  AddVectorQuotientImpl(a, z, s, c);
695  ObjectChanged();
696  }
697 
698  inline
700  {
701  if (valid_cache_tag_ != GetTag()) {
704  }
705  return cached_valid_;
706  }
707 
708  inline
710  {
711  return owner_space_->Dim();
712  }
713 
714  inline
716  {
717  return owner_space_;
718  }
719 
720  inline
722  :
723  dim_(dim)
724  {}
725 
726 } // namespace Ipopt
727 
728 // Macro definitions for debugging vectors
729 #if COIN_IPOPT_VERBOSITY == 0
730 # define DBG_PRINT_VECTOR(__verbose_level, __vec_name, __vec)
731 #else
732 # define DBG_PRINT_VECTOR(__verbose_level, __vec_name, __vec) \
733  if (dbg_jrnl.Verbosity() >= (__verbose_level)) { \
734  if (dbg_jrnl.Jnlst()!=NULL) { \
735  (__vec).Print(dbg_jrnl.Jnlst(), \
736  J_ERROR, J_DBG, \
737  __vec_name, \
738  dbg_jrnl.IndentationLevel()*2, \
739  "# "); \
740  } \
741  }
742 #endif //if COIN_IPOPT_VERBOSITY == 0
743 
744 #endif