// Copyright (C) 2004, 2009 International Business Machines and others. // All Rights Reserved. // This code is published under the Eclipse Public License. // // Authors: Carl Laird, Andreas Waechter IBM 2004-08-13 #ifndef __IPDENSEVECTOR_HPP__ #define __IPDENSEVECTOR_HPP__ #include "IpUtils.hpp" #include "IpVector.hpp" #include namespace Ipopt { /* forward declarations */ class DenseVectorSpace; /** @name Exceptions */ ///@{ DECLARE_STD_EXCEPTION(METADATA_ERROR); ///@} /** Dense Vector Implementation. * * This is the default Vector class in Ipopt. * It stores vectors in contiguous Number arrays, unless * the vector has the same value in all entires. In the latter * case, we call the vector "homogeneous", and we store only the * values that is repeated in all elements. If you want to obtain * the values of vector, use the IsHomogeneous() method to find out * what status the vector is in, and then use either Values() const * or Scalar() const methods to get the values. To set the values * of a homogeneous method, use the Set method. To set the values * of a non-homogeneous vector, use the SetValues method, or use * the non-const Values method to get an array that you can * overwrite. In the latter case, storage is ensured. */ class IPOPTLIB_EXPORT DenseVector: public Vector { public: /**@name Constructors / Destructors */ ///@{ /** Default Constructor */ DenseVector( const DenseVectorSpace* owner_space ); /** Destructor */ virtual ~DenseVector(); ///@} /** @name Additional public methods not in Vector base class. */ ///@{ /** Create a new DenseVector from same VectorSpace */ SmartPtr MakeNewDenseVector() const; /** Set elements in the vector to the Number array x. */ void SetValues( const Number* x ); /** Obtain pointer to the internal Number array with vector * elements with the intention to change the vector data. * * @attention This does not produce a copy, and lifetime is not guaranteed!. */ inline Number* Values(); /** Obtain pointer to the internal Number array with vector * elements without the intention to change the vector data. * * @attention This does not produce a copy, and lifetime is not * guaranteed! * * @attention If this vector is currently homogeneous * (i.e. IsHomogeneous returns true), then you cannot * call this method. Instead, you need to use the Scalar() * method. */ inline const Number* Values() const; /** The same as the const version of Values, but we ensure that we * always return a valid array, even if IsHomogeneous returns * true. */ const Number* ExpandedValues() const; /** This is the same as Values, but we add it here so that * ExpandedValues can also be used for the non-const case. */ inline Number* ExpandedValues() { return Values(); } /** Indicates if the vector is homogeneous (i.e., all entries have * the value Scalar(). */ bool IsHomogeneous() const { return homogeneous_; } /** Scalar value of all entries in a homogeneous vector. */ Number Scalar() const { DBG_ASSERT(homogeneous_); return scalar_; } ///@} /** @name Modifying subranges of the vector. */ ///@{ /** Copy the data in x into the subrange of this vector starting * at position Pos in this vector. * * Position count starts at 0. */ void CopyToPos( Index Pos, const Vector& x ); /** Copy a subrange of x, starting at Pos, into the full data of * this vector. * * Position count starts at 0. */ void CopyFromPos( Index Pos, const Vector& x ); ///@} protected: /** @name Overloaded methods from Vector base class */ ///@{ virtual void CopyImpl( const Vector& x ); virtual void ScalImpl( Number alpha ); virtual void AxpyImpl( Number alpha, const Vector& x ); virtual Number DotImpl( const Vector& x ) const; virtual Number Nrm2Impl() const; virtual Number AsumImpl() const; virtual Number AmaxImpl() const; virtual void SetImpl( Number value ); virtual void ElementWiseDivideImpl( const Vector& x ); virtual void ElementWiseMultiplyImpl( const Vector& x ); virtual void ElementWiseSelectImpl( const Vector& x ); virtual void ElementWiseMaxImpl( const Vector& x ); virtual void ElementWiseMinImpl( const Vector& x ); virtual void ElementWiseReciprocalImpl(); virtual void ElementWiseAbsImpl(); virtual void ElementWiseSqrtImpl(); virtual void ElementWiseSgnImpl(); virtual void AddScalarImpl( Number scalar ); virtual Number MaxImpl() const; virtual Number MinImpl() const; virtual Number SumImpl() const; virtual Number SumLogsImpl() const; ///@} /** @name Implemented specialized functions */ ///@{ /** Add two vectors (a * v1 + b * v2). * * Result is stored in this vector. */ void AddTwoVectorsImpl( Number a, const Vector& v1, Number b, const Vector& v2, Number c ); /** Fraction to the boundary parameter. */ Number FracToBoundImpl( const Vector& delta, Number tau ) const; /** Add the quotient of two vectors, y = a * z/s + c * y. */ void AddVectorQuotientImpl( Number a, const Vector& z, const Vector& s, Number c ); ///@} /** @name Output methods */ ///@{ virtual void PrintImpl( const Journalist& jnlst, EJournalLevel level, EJournalCategory category, const std::string& name, Index indent, const std::string& prefix ) const { PrintImplOffset(jnlst, level, category, name, indent, prefix, 1); } /* Print the entire vector with padding, and start counting with an offset. */ void PrintImplOffset( const Journalist& jnlst, EJournalLevel level, EJournalCategory category, const std::string& name, Index indent, const std::string& prefix, Index offset ) const; ///@} friend class ParVector; private: /**@name Default Compiler Generated Methods * (Hidden to avoid implicit creation/calling). * These methods are not implemented and * we do not want the compiler to implement * them for us, so we declare them private * and do not define them. This ensures that * they will not be implicitly created/called. */ ///@{ /** Default Constructor */ DenseVector(); /** Copy Constructor */ DenseVector( const DenseVector& ); /** Default Assignment Operator */ void operator=( const DenseVector& ); ///@} /** Copy of the owner_space ptr as a DenseVectorSpace instead of a VectorSpace. */ const DenseVectorSpace* owner_space_; /** Dense Number array of vector values. */ Number* values_; /** Dense Number array pointer that is used for ExpandedValues */ mutable Number* expanded_values_; /** Get the internal values array, making sure that memory has been allocated. */ inline Number* values_allocated(); /** Flag for Initialization. * * This flag is false, if the data has not yet been initialized. */ bool initialized_; /** Flag indicating whether the vector is currently homogeneous * (that is, all elements have the same value). * * This flag is used to determine whether the elements of the vector * are stored in values_ or in scalar_. */ bool homogeneous_; /** Homogeneous value of all elements if the vector is currently homogeneous. */ Number scalar_; /** Auxiliary method for setting explicitly all elements in values_ to the * current scalar value. */ void set_values_from_scalar(); }; /** @name typedefs for the map variables that define meta data for the DenseVectorSpace */ ///@{ typedef std::map > StringMetaDataMapType; typedef std::map > IntegerMetaDataMapType; typedef std::map > NumericMetaDataMapType; ///@} /** This vectors space is the vector space for DenseVector. */ class IPOPTLIB_EXPORT DenseVectorSpace: public VectorSpace { public: /** @name Constructors/Destructors. */ ///@{ /** Constructor, requires dimension of all vector for this VectorSpace */ DenseVectorSpace( Index dim ) : VectorSpace(dim) { } /** Destructor */ ~DenseVectorSpace() { } ///@} /** Method for creating a new vector of this specific type. */ inline DenseVector* MakeNewDenseVector() const { return new DenseVector(this); } virtual Vector* MakeNew() const { return MakeNewDenseVector(); } /**@name Methods called by DenseVector for memory management. * * This could allow to have sophisticated memory management in the * VectorSpace. */ ///@{ /** Allocate internal storage for the DenseVector */ inline Number* AllocateInternalStorage() const; /** Deallocate internal storage for the DenseVector */ inline void FreeInternalStorage( Number* values ) const; ///@} /**@name Methods for dealing with meta data on the vector */ ///@{ /** Check if string meta exists for tag */ inline bool HasStringMetaData( const std::string& tag ) const; /** Check if Integer meta exists for tag */ inline bool HasIntegerMetaData( const std::string& tag ) const; /** Check if Numeric meta exists for tag */ inline bool HasNumericMetaData( const std::string& tag ) const; /** Get meta data of type std::string by tag */ inline const std::vector& GetStringMetaData( const std::string& tag ) const; /** Get meta data of type Index by tag */ inline const std::vector& GetIntegerMetaData( const std::string& tag ) const; /** Get meta data of type Number by tag */ inline const std::vector& GetNumericMetaData( const std::string& tag ) const; /** Set meta data of type std::string by tag */ inline void SetStringMetaData( const std::string& tag, const std::vector& meta_data ); /** Set meta data of type Index by tag */ inline void SetIntegerMetaData( const std::string& tag, const std::vector& meta_data ); /** Set meta data of type Number by tag */ inline void SetNumericMetaData( const std::string& tag, const std::vector& meta_data ); /** Get map of meta data of type Number */ inline const StringMetaDataMapType& GetStringMetaData() const; /** Get map of meta data of type Number */ inline const IntegerMetaDataMapType& GetIntegerMetaData() const; /** Get map of meta data of type Number */ inline const NumericMetaDataMapType& GetNumericMetaData() const; ///@} private: // variables to store vector meta data StringMetaDataMapType string_meta_data_; IntegerMetaDataMapType integer_meta_data_; NumericMetaDataMapType numeric_meta_data_; }; // inline functions inline Number* DenseVector::Values() { // Here we assume that every time someone requests this direct raw // pointer, the data is going to change and the Tag for this // vector has to be updated. if( initialized_ && homogeneous_ ) { // If currently the vector is a homogeneous vector, set all elements // explicitly to this value set_values_from_scalar(); } ObjectChanged(); initialized_ = true; homogeneous_ = false; values_allocated(); DBG_ASSERT(Dim() == 0 || values_ != NULL); return values_; } inline const Number* DenseVector::Values() const { DBG_ASSERT(initialized_ && (Dim() == 0 || values_)); return values_; } inline Number* DenseVector::values_allocated() { if( values_ == NULL ) { values_ = owner_space_->AllocateInternalStorage(); } return values_; } inline Number* DenseVectorSpace::AllocateInternalStorage() const { if( Dim() > 0 ) { return new Number[Dim()]; } else { return NULL; } } inline void DenseVectorSpace::FreeInternalStorage( Number* values ) const { delete[] values; } inline SmartPtr DenseVector::MakeNewDenseVector() const { return owner_space_->MakeNewDenseVector(); } inline bool DenseVectorSpace::HasStringMetaData( const std::string& tag ) const { StringMetaDataMapType::const_iterator iter; iter = string_meta_data_.find(tag); if( iter != string_meta_data_.end() ) { return true; } return false; } inline bool DenseVectorSpace::HasIntegerMetaData( const std::string& tag ) const { IntegerMetaDataMapType::const_iterator iter; iter = integer_meta_data_.find(tag); if( iter != integer_meta_data_.end() ) { return true; } return false; } inline bool DenseVectorSpace::HasNumericMetaData( const std::string& tag ) const { NumericMetaDataMapType::const_iterator iter; iter = numeric_meta_data_.find(tag); if( iter != numeric_meta_data_.end() ) { return true; } return false; } inline const std::vector& DenseVectorSpace::GetStringMetaData( const std::string& tag ) const { DBG_ASSERT(HasStringMetaData(tag)); StringMetaDataMapType::const_iterator iter; iter = string_meta_data_.find(tag); return iter->second; } inline const std::vector& DenseVectorSpace::GetIntegerMetaData( const std::string& tag ) const { DBG_ASSERT(HasIntegerMetaData(tag)); IntegerMetaDataMapType::const_iterator iter; iter = integer_meta_data_.find(tag); return iter->second; } inline const std::vector& DenseVectorSpace::GetNumericMetaData( const std::string& tag ) const { DBG_ASSERT(HasNumericMetaData(tag)); NumericMetaDataMapType::const_iterator iter; iter = numeric_meta_data_.find(tag); return iter->second; } inline void DenseVectorSpace::SetStringMetaData( const std::string& tag, const std::vector& meta_data ) { string_meta_data_[tag] = meta_data; } inline void DenseVectorSpace::SetIntegerMetaData( const std::string& tag, const std::vector& meta_data ) { integer_meta_data_[tag] = meta_data; } inline void DenseVectorSpace::SetNumericMetaData( const std::string& tag, const std::vector& meta_data ) { numeric_meta_data_[tag] = meta_data; } inline const StringMetaDataMapType& DenseVectorSpace::GetStringMetaData() const { return string_meta_data_; } inline const IntegerMetaDataMapType& DenseVectorSpace::GetIntegerMetaData() const { return integer_meta_data_; } inline const NumericMetaDataMapType& DenseVectorSpace::GetNumericMetaData() const { return numeric_meta_data_; } } // namespace Ipopt #endif