/build/buildd/coinor-ipopt-3.10.1/Ipopt/src/LinAlg/IpVector.hpp
Go to the documentation of this file.
00001 // Copyright (C) 2004, 2008 International Business Machines and others.
00002 // All Rights Reserved.
00003 // This code is published under the Eclipse Public License.
00004 //
00005 // $Id: IpVector.hpp 1861 2010-12-21 21:34:47Z andreasw $
00006 //
00007 // Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13
00008 
00009 #ifndef __IPVECTOR_HPP__
00010 #define __IPVECTOR_HPP__
00011 
00012 #include "IpTypes.hpp"
00013 #include "IpTaggedObject.hpp"
00014 #include "IpCachedResults.hpp"
00015 #include "IpSmartPtr.hpp"
00016 #include "IpJournalist.hpp"
00017 #include "IpException.hpp"
00018 
00019 #include <vector>
00020 
00021 namespace Ipopt
00022 {
00025   DECLARE_STD_EXCEPTION(UNIMPLEMENTED_LINALG_METHOD_CALLED);
00026 
00027   /* forward declarations */
00028   class VectorSpace;
00029 
00047   class Vector : public TaggedObject
00048   {
00049   public:
00055     Vector(const VectorSpace* owner_space);
00056 
00058     virtual ~Vector();
00060 
00062     Vector* MakeNew() const;
00063 
00065     Vector* MakeNewCopy() const;
00066 
00073     void Copy(const Vector& x);
00074 
00076     void Scal(Number alpha);
00077 
00079     void Axpy(Number alpha, const Vector &x);
00080 
00082     Number Dot(const Vector &x) const;
00083 
00085     Number Nrm2() const;
00086 
00088     Number Asum() const;
00089 
00091     Number Amax() const;
00093 
00100     void Set(Number alpha);
00101 
00103     void ElementWiseDivide(const Vector& x);
00104 
00106     void ElementWiseMultiply(const Vector& x);
00107 
00109     void ElementWiseMax(const Vector& x);
00110 
00112     void ElementWiseMin(const Vector& x);
00113 
00115     void ElementWiseReciprocal();
00116 
00118     void ElementWiseAbs();
00119 
00121     void ElementWiseSqrt();
00122 
00126     void ElementWiseSgn();
00127 
00129     void AddScalar(Number scalar);
00130 
00132     Number Max() const;
00133 
00135     Number Min() const;
00136 
00138     Number Sum() const;
00139 
00141     Number SumLogs() const;
00143 
00151     void AddOneVector(Number a, const Vector& v1, Number c);
00152 
00155     void AddTwoVectors(Number a, const Vector& v1,
00156                        Number b, const Vector& v2, Number c);
00160     Number FracToBound(const Vector& delta, Number tau) const;
00162     void AddVectorQuotient(Number a, const Vector& z, const Vector& s,
00163                            Number c);
00165 
00168     bool HasValidNumbers() const;
00169 
00173     Index Dim() const;
00174 
00176     SmartPtr<const VectorSpace> OwnerSpace() const;
00178 
00185     void Print(SmartPtr<const Journalist> jnlst,
00186                EJournalLevel level,
00187                EJournalCategory category,
00188                const std::string& name,
00189                Index indent=0,
00190                const std::string& prefix="") const;
00191     void Print(const Journalist& jnlst,
00192                EJournalLevel level,
00193                EJournalCategory category,
00194                const std::string& name,
00195                Index indent=0,
00196                const std::string& prefix="") const;
00198 
00199   protected:
00205     virtual void CopyImpl(const Vector& x)=0;
00206 
00208     virtual void ScalImpl(Number alpha)=0;
00209 
00211     virtual void AxpyImpl(Number alpha, const Vector &x)=0;
00212 
00214     virtual Number DotImpl(const Vector &x) const =0;
00215 
00217     virtual Number Nrm2Impl() const =0;
00218 
00220     virtual Number AsumImpl() const =0;
00221 
00223     virtual Number AmaxImpl() const =0;
00224 
00226     virtual void SetImpl(Number alpha)=0;
00227 
00229     virtual void ElementWiseDivideImpl(const Vector& x)=0;
00230 
00232     virtual void ElementWiseMultiplyImpl(const Vector& x)=0;
00233 
00235     virtual void ElementWiseMaxImpl(const Vector& x)=0;
00236 
00238     virtual void ElementWiseMinImpl(const Vector& x)=0;
00239 
00241     virtual void ElementWiseReciprocalImpl()=0;
00242 
00244     virtual void ElementWiseAbsImpl()=0;
00245 
00247     virtual void ElementWiseSqrtImpl()=0;
00248 
00250     virtual void ElementWiseSgnImpl()=0;
00251 
00253     virtual void AddScalarImpl(Number scalar)=0;
00254 
00256     virtual Number MaxImpl() const=0;
00257 
00259     virtual Number MinImpl() const=0;
00260 
00262     virtual Number SumImpl() const=0;
00263 
00265     virtual Number SumLogsImpl() const=0;
00266 
00269     virtual void AddTwoVectorsImpl(Number a, const Vector& v1,
00270                                    Number b, const Vector& v2, Number c);
00271 
00273     virtual Number FracToBoundImpl(const Vector& delta, Number tau) const;
00274 
00276     virtual void AddVectorQuotientImpl(Number a, const Vector& z,
00277                                        const Vector& s, Number c);
00278 
00282     virtual bool HasValidNumbersImpl() const;
00283 
00285     virtual void PrintImpl(const Journalist& jnlst,
00286                            EJournalLevel level,
00287                            EJournalCategory category,
00288                            const std::string& name,
00289                            Index indent,
00290                            const std::string& prefix) const =0;
00292 
00293   private:
00303     Vector();
00304 
00306     Vector(const Vector&);
00307 
00309     Vector& operator=(const Vector&);
00311 
00313     const SmartPtr<const VectorSpace> owner_space_;
00314 
00318     mutable CachedResults<Number> dot_cache_;
00319 
00320     mutable TaggedObject::Tag nrm2_cache_tag_;
00321     mutable Number cached_nrm2_;
00322 
00323     mutable TaggedObject::Tag asum_cache_tag_;
00324     mutable Number cached_asum_;
00325 
00326     mutable TaggedObject::Tag amax_cache_tag_;
00327     mutable Number cached_amax_;
00328 
00329     mutable TaggedObject::Tag max_cache_tag_;
00330     mutable Number cached_max_;
00331 
00332     mutable TaggedObject::Tag min_cache_tag_;
00333     mutable Number cached_min_;
00334 
00335     mutable TaggedObject::Tag sum_cache_tag_;
00336     mutable Number cached_sum_;
00337 
00338     mutable TaggedObject::Tag sumlogs_cache_tag_;
00339     mutable Number cached_sumlogs_;
00340 
00341     mutable TaggedObject::Tag valid_cache_tag_;
00342     mutable bool cached_valid_;
00343 
00344     //     AW: I removed this cache since it gets in the way for the
00345     //         quality function search
00346     //     /** Cache for FracToBound */
00347     //     mutable CachedResults<Number> frac_to_bound_cache_;
00349 
00350   };
00351 
00360   class VectorSpace : public ReferencedObject
00361   {
00362   public:
00368     VectorSpace(Index dim);
00369 
00371     virtual ~VectorSpace()
00372     {}
00374 
00378     virtual Vector* MakeNew() const=0;
00379 
00381     Index Dim() const
00382     {
00383       return dim_;
00384     }
00385 
00386   private:
00396     VectorSpace();
00397 
00399     VectorSpace(const VectorSpace&);
00400 
00402     VectorSpace& operator=(const VectorSpace&);
00404 
00406     const Index dim_;
00407   };
00408 
00409   /* inline methods */
00410   inline
00411   Vector::~Vector()
00412   {}
00413 
00414   inline
00415   Vector::Vector(const VectorSpace* owner_space)
00416       :
00417       TaggedObject(),
00418       owner_space_(owner_space),
00419       dot_cache_(10),
00420       nrm2_cache_tag_(0),
00421       asum_cache_tag_(0),
00422       amax_cache_tag_(0),
00423       max_cache_tag_(0),
00424       min_cache_tag_(0),
00425       sum_cache_tag_(0),
00426       sumlogs_cache_tag_(0),
00427       cached_valid_(0)
00428   {
00429     DBG_ASSERT(IsValid(owner_space_));
00430   }
00431 
00432   inline
00433   Vector* Vector::MakeNew() const
00434   {
00435     return owner_space_->MakeNew();
00436   }
00437 
00438   inline
00439   Vector* Vector::MakeNewCopy() const
00440   {
00441     // ToDo: We can probably copy also the cached values for Norms etc here
00442     Vector* copy = MakeNew();
00443     copy->Copy(*this);
00444     return copy;
00445   }
00446 
00447   inline
00448   void Vector::Copy(const Vector& x)
00449   {
00450     CopyImpl(x);
00451     ObjectChanged();
00452     // Also copy any cached scalar values from the original vector
00453     // ToDo: Check if that is too much overhead
00454     TaggedObject::Tag x_tag = x.GetTag();
00455     if (x_tag == x.nrm2_cache_tag_) {
00456       nrm2_cache_tag_ = GetTag();
00457       cached_nrm2_ = x.cached_nrm2_;
00458     }
00459     if (x_tag == x.asum_cache_tag_) {
00460       asum_cache_tag_ = GetTag();
00461       cached_asum_ = x.cached_asum_;
00462     }
00463     if (x_tag == x.amax_cache_tag_) {
00464       amax_cache_tag_ = GetTag();
00465       cached_amax_ = x.cached_amax_;
00466     }
00467     if (x_tag == x.max_cache_tag_) {
00468       max_cache_tag_ = GetTag();
00469       cached_max_ = x.cached_max_;
00470     }
00471     if (x_tag == x.min_cache_tag_) {
00472       min_cache_tag_ = GetTag();
00473       cached_min_ = x.cached_min_;
00474     }
00475     if (x_tag == x.sum_cache_tag_) {
00476       sum_cache_tag_ = GetTag();
00477       cached_sum_ = x.cached_sum_;
00478     }
00479     if (x_tag == x.sumlogs_cache_tag_) {
00480       sumlogs_cache_tag_ = GetTag();
00481       cached_sumlogs_ = x.cached_sumlogs_;
00482     }
00483   }
00484 
00485   inline
00486   void Vector::Axpy(Number alpha, const Vector &x)
00487   {
00488     AxpyImpl(alpha, x);
00489     ObjectChanged();
00490   }
00491 
00492   inline
00493   Number Vector::Dot(const Vector &x) const
00494   {
00495     // The current implementation of the caching doesn't allow to have
00496     // a dependency of something with itself.  Therefore, we use the
00497     // Nrm2 method if the dot product is to be taken with the vector
00498     // itself.  Might be more efficient anyway.
00499     if (this==&x) {
00500       Number nrm2 = Nrm2();
00501       return nrm2*nrm2;
00502     }
00503     Number retValue;
00504     if (!dot_cache_.GetCachedResult2Dep(retValue, this, &x)) {
00505       retValue = DotImpl(x);
00506       dot_cache_.AddCachedResult2Dep(retValue, this, &x);
00507     }
00508     return retValue;
00509   }
00510 
00511   inline
00512   Number Vector::Nrm2() const
00513   {
00514     if (nrm2_cache_tag_ != GetTag()) {
00515       cached_nrm2_ = Nrm2Impl();
00516       nrm2_cache_tag_ = GetTag();
00517     }
00518     return cached_nrm2_;
00519   }
00520 
00521   inline
00522   Number Vector::Asum() const
00523   {
00524     if (asum_cache_tag_ != GetTag()) {
00525       cached_asum_ = AsumImpl();
00526       asum_cache_tag_ = GetTag();
00527     }
00528     return cached_asum_;
00529   }
00530 
00531   inline
00532   Number Vector::Amax() const
00533   {
00534     if (amax_cache_tag_ != GetTag()) {
00535       cached_amax_ = AmaxImpl();
00536       amax_cache_tag_ = GetTag();
00537     }
00538     return cached_amax_;
00539   }
00540 
00541   inline
00542   Number Vector::Sum() const
00543   {
00544     if (sum_cache_tag_ != GetTag()) {
00545       cached_sum_ = SumImpl();
00546       sum_cache_tag_ = GetTag();
00547     }
00548     return cached_sum_;
00549   }
00550 
00551   inline
00552   Number Vector::SumLogs() const
00553   {
00554     if (sumlogs_cache_tag_ != GetTag()) {
00555       cached_sumlogs_ = SumLogsImpl();
00556       sumlogs_cache_tag_ = GetTag();
00557     }
00558     return cached_sumlogs_;
00559   }
00560 
00561   inline
00562   void Vector::ElementWiseSgn()
00563   {
00564     ElementWiseSgnImpl();
00565     ObjectChanged();
00566   }
00567 
00568   inline
00569   void Vector::Set(Number alpha)
00570   {
00571     // Could initialize caches here
00572     SetImpl(alpha);
00573     ObjectChanged();
00574   }
00575 
00576   inline
00577   void Vector::ElementWiseDivide(const Vector& x)
00578   {
00579     ElementWiseDivideImpl(x);
00580     ObjectChanged();
00581   }
00582 
00583   inline
00584   void Vector::ElementWiseMultiply(const Vector& x)
00585   {
00586     ElementWiseMultiplyImpl(x);
00587     ObjectChanged();
00588   }
00589 
00590   inline
00591   void Vector::ElementWiseReciprocal()
00592   {
00593     ElementWiseReciprocalImpl();
00594     ObjectChanged();
00595   }
00596 
00597   inline
00598   void Vector::ElementWiseMax(const Vector& x)
00599   {
00600     // Could initialize some caches here
00601     ElementWiseMaxImpl(x);
00602     ObjectChanged();
00603   }
00604 
00605   inline
00606   void Vector::ElementWiseMin(const Vector& x)
00607   {
00608     // Could initialize some caches here
00609     ElementWiseMinImpl(x);
00610     ObjectChanged();
00611   }
00612 
00613   inline
00614   void Vector::ElementWiseAbs()
00615   {
00616     // Could initialize some caches here
00617     ElementWiseAbsImpl();
00618     ObjectChanged();
00619   }
00620 
00621   inline
00622   void Vector::ElementWiseSqrt()
00623   {
00624     ElementWiseSqrtImpl();
00625     ObjectChanged();
00626   }
00627 
00628   inline
00629   void Vector::AddScalar(Number scalar)
00630   {
00631     // Could initialize some caches here
00632     AddScalarImpl(scalar);
00633     ObjectChanged();
00634   }
00635 
00636   inline
00637   Number Vector::Max() const
00638   {
00639     if (max_cache_tag_ != GetTag()) {
00640       cached_max_ = MaxImpl();
00641       max_cache_tag_ = GetTag();
00642     }
00643     return cached_max_;
00644   }
00645 
00646   inline
00647   Number Vector::Min() const
00648   {
00649     if (min_cache_tag_ != GetTag()) {
00650       cached_min_ = MinImpl();
00651       min_cache_tag_ = GetTag();
00652     }
00653     return cached_min_;
00654   }
00655 
00656   inline
00657   void Vector::AddOneVector(Number a, const Vector& v1, Number c)
00658   {
00659     AddTwoVectors(a, v1, 0., v1, c);
00660   }
00661 
00662   inline
00663   void Vector::AddTwoVectors(Number a, const Vector& v1,
00664                              Number b, const Vector& v2, Number c)
00665   {
00666     AddTwoVectorsImpl(a, v1, b, v2, c);
00667     ObjectChanged();
00668   }
00669 
00670   inline
00671   Number Vector::FracToBound(const Vector& delta, Number tau) const
00672   {
00673     /* AW: I avoid the caching here, since it leads to overhead in the
00674        quality function search.  Caches for this are in
00675        CalculatedQuantities.
00676     Number retValue;
00677     std::vector<const TaggedObject*> tdeps(1);
00678     tdeps[0] = &delta;
00679     std::vector<Number> sdeps(1);
00680     sdeps[0] = tau;
00681     if (!frac_to_bound_cache_.GetCachedResult(retValue, tdeps, sdeps)) {
00682       retValue = FracToBoundImpl(delta, tau);
00683       frac_to_bound_cache_.AddCachedResult(retValue, tdeps, sdeps);
00684     }
00685     return retValue;
00686     */
00687     return FracToBoundImpl(delta, tau);
00688   }
00689 
00690   inline
00691   void Vector::AddVectorQuotient(Number a, const Vector& z,
00692                                  const Vector& s, Number c)
00693   {
00694     AddVectorQuotientImpl(a, z, s, c);
00695     ObjectChanged();
00696   }
00697 
00698   inline
00699   bool Vector::HasValidNumbers() const
00700   {
00701     if (valid_cache_tag_ != GetTag()) {
00702       cached_valid_ = HasValidNumbersImpl();
00703       valid_cache_tag_ = GetTag();
00704     }
00705     return cached_valid_;
00706   }
00707 
00708   inline
00709   Index Vector::Dim() const
00710   {
00711     return owner_space_->Dim();
00712   }
00713 
00714   inline
00715   SmartPtr<const VectorSpace> Vector::OwnerSpace() const
00716   {
00717     return owner_space_;
00718   }
00719 
00720   inline
00721   VectorSpace::VectorSpace(Index dim)
00722       :
00723       dim_(dim)
00724   {}
00725 
00726 } // namespace Ipopt
00727 
00728 // Macro definitions for debugging vectors
00729 #if COIN_IPOPT_VERBOSITY == 0
00730 # define DBG_PRINT_VECTOR(__verbose_level, __vec_name, __vec)
00731 #else
00732 # define DBG_PRINT_VECTOR(__verbose_level, __vec_name, __vec) \
00733    if (dbg_jrnl.Verbosity() >= (__verbose_level)) { \
00734       if (dbg_jrnl.Jnlst()!=NULL) { \
00735         (__vec).Print(dbg_jrnl.Jnlst(), \
00736         J_ERROR, J_DBG, \
00737         __vec_name, \
00738         dbg_jrnl.IndentationLevel()*2, \
00739         "# "); \
00740       } \
00741    }
00742 #endif //if COIN_IPOPT_VERBOSITY == 0
00743 
00744 #endif