#ifndef SPARSEVECTORT_TCC #define SPARSEVECTORT_TCC #include #include #include #include #include #include #include "core/vector/SparseVectorT.h" namespace NICE { template SparseVectorT::SparseVectorT ( const std::map & mymap ):std::map ( mymap ) { //we assume that the last element specifies the maximal size :) if ( mymap.size() > 0 ) { typename std::map::const_reverse_iterator lastElem = mymap.rbegin(); dim = lastElem->first; } } template SparseVectorT::SparseVectorT ( I k, V v ) { this->insert ( std::pair ( k, v ) ); this->dim = k; } template SparseVectorT::SparseVectorT ( uint _dim ) : dim ( _dim ) { } template SparseVectorT::SparseVectorT ( const NICE::Vector &v, double tolerance ) { this->dim = v.size(); for ( uint i = 0; i < dim; i++ ) { if ( fabs ( v[i] ) > tolerance ) this->insert ( std::pair ( i, v[i] ) ); } } template void SparseVectorT::sub ( const SparseVectorT & v ) { for ( typename SparseVectorT::const_iterator v_it = v.begin(); v_it != v.end(); v_it++ ) ( *this ) [v_it->first] -= v_it->second; } template void SparseVectorT::add ( const SparseVectorT & v ) { this->add ( v, 1.0 ); } template void SparseVectorT::add ( const SparseVectorT & v, double lambda ) { for ( typename SparseVectorT::const_iterator v_it = v.begin(); v_it != v.end(); v_it++ ) ( *this ) [v_it->first] += v_it->second * lambda; } template void SparseVectorT::add ( V val ) { for ( typename SparseVectorT::iterator it = this->begin(); it != this->end(); it++ ) it->second += val; } template void SparseVectorT::divide ( const SparseVectorT & v ) { for ( typename SparseVectorT::iterator it = this->begin(); it != this->end(); ) { bool deleteEntry = false; typename SparseVectorT::const_iterator v_it = v.find ( it->first ); if ( v_it == v.end() ) { fthrow ( Exception, "Division by Zero !" ); } else { it->second /= v_it->second; if ( fabs ( it->second ) < 1e-20 ) deleteEntry = true; } if ( deleteEntry ) this->erase ( it++ ); else it++; } } template void SparseVectorT::divide ( V v ) { if ( fabs ( v ) < 1e-20 ) fthrow ( Exception, "Division by Zero !" ); for ( typename SparseVectorT::iterator it = this->begin(); it != this->end(); ) { bool deleteEntry = false; it->second /= v; if ( fabs ( it->second ) < 1e-20 ) deleteEntry = true; if ( deleteEntry ) this->erase ( it++ ); else it++; } } template void SparseVectorT::multiply ( const SparseVectorT & v ) { for ( typename SparseVectorT::iterator it = this->begin(); it != this->end(); ) { bool deleteEntry = false; typename SparseVectorT::const_iterator v_it = v.find ( it->first ); if ( v_it == v.end() ) deleteEntry = true; else { it->second *= v_it->second; if ( fabs ( it->second ) < 1e-20 ) deleteEntry = true; } if ( deleteEntry ) this->erase ( it++ ); else it++; } } template void SparseVectorT::multiply ( V val ) { for ( typename SparseVectorT::iterator it = this->begin(); it != this->end(); ) { it->second *= val; if ( fabs ( it->second ) < 1e-20 ) { this->erase ( it++ ); } else { it++; } } } template double SparseVectorT::innerProduct ( const SparseVectorT & v ) const { V prod = 0.0; typename SparseVectorT::const_iterator it1 = this->begin(); typename SparseVectorT::const_iterator it2 = v.begin(); while ( ( it1 != this->end() ) && ( it2 != v.end() ) ) { if ( it1->first == it2->first ) { prod += it1->second * it2->second; ++it1; ++it2; } else if ( it1->first < it2->first ) ++it1; else ++it2; } return prod; } template void SparseVectorT::restore ( std::istream & is, int format ) { I first; V second; if ( format == FORMAT_INDEX ) { std::string tag; is >> tag; if ( tag != "SVECTOR" ) { fthrow ( Exception, "Format error: starting tag is " << tag << " instead of SVECTOR" ); } is >> dim; I size; is >> size; for ( int i = 0; i < size; i++ ) { is >> first; is >> second; ( *this ) [first] = second; } is >> tag; if ( tag != "END" ) { fthrow ( Exception, "Format error: end tag is " << tag << " instead of END" ); } } else if ( format == FORMAT_INDEX_LINE ) { std::string line; std::getline ( is, line ); std::istringstream iss ( line, std::istringstream::in); while ( !iss.eof() ) { char c; if ( !( iss >> first) ) break; if ( !( iss >> c ) ) break; if ( !( iss >> second ) ) break; ( *this ) [first] = second; } // preserve dimension setting //dimension = -1; } else { fthrow(Exception, "Unknown format! (see SparseVectorT.h for details)"); } } template void SparseVectorT::store ( std::ostream & os, int format ) const { if ( format == FORMAT_INDEX ) { os << "SVECTOR "; os << dim << " " << this->size() << std::endl; for ( typename SparseVectorT::const_iterator it = this->begin(); it != this->end(); it++ ) { os << it->first << " " << it->second << " "; } os << "END" << std::endl; } else if ( format == FORMAT_INDEX_LINE ) { for ( typename SparseVectorT::const_iterator it = this->begin(); it != this->end(); it++ ) { if ( it != this->begin() ) os << " "; os << it->first << ":" << it->second; } os << std::endl; } else { fthrow(Exception, "Unknown format! (see SparseVectorT.h for details)"); } } template void SparseVectorT::clear () { std::map::clear(); } template V SparseVectorT::sum () const { V sumv = 0.0; for ( typename SparseVectorT::const_iterator it = this->begin(); it != this->end(); it++ ) sumv += it->second; return sumv; } template void SparseVectorT::normalize () { V sum = this->sum(); if ( fabs ( sum ) < 1e-20 ) { fprintf ( stderr, "WARNING: normalization failed !\n" ); for ( typename SparseVectorT::iterator it = this->begin(); it != this->end(); it++ ) it->second = 0.0; } else { for ( typename SparseVectorT::iterator it = this->begin(); it != this->end(); it++ ) it->second /= sum; } } template void SparseVectorT::normalize ( V minv, V maxv ) { typename SparseVectorT::iterator it = this->begin(); V oldmin = it->second; V oldmax = it->second; it++; for ( ; it != this->end(); it++ ) { oldmin = std::min ( oldmin, it->second ); oldmax = std::max ( oldmax, it->second ); } V diff = oldmax - oldmin; if ( diff == 0.0 ) { for ( it = this->begin(); it != this->end(); it++ ) { it->second = 0; } return; } for ( it = this->begin(); it != this->end(); it++ ) { it->second = ( ( ( it->second - oldmin ) / diff ) * ( maxv - minv ) ) + minv; } } template void SparseVectorT::addMap ( const std::map & v, double lambda ) { for ( std::map::const_iterator v_it = v.begin(); v_it != v.end(); v_it++ ) ( *this ) [(I)v_it->first] += (V)v_it->second * lambda; } template void SparseVectorT::addMap ( const std::map & v, double lambda ) { for ( std::map::const_iterator v_it = v.begin(); v_it != v.end(); v_it++ ) ( *this ) [(I)v_it->first] += (V)v_it->second * lambda; } template I SparseVectorT::maxElement () const { I maxindex = 0; V max = -std::numeric_limits::max(); for ( typename SparseVectorT::const_iterator it = this->begin(); it != this->end(); it++ ) { if ( it->second > max ) { maxindex = it->first; max = it->second; } } return maxindex; } template I SparseVectorT::maxElementExclusive ( I key ) const { I maxindex = ( key == 0 ) ? 1 : 0; double max = - std::numeric_limits::max(); for ( typename SparseVectorT::const_iterator it = this->begin(); it != this->end(); it++ ) { if ( ( it->first != key ) && ( it->second > max ) ) { maxindex = it->first; max = it->second; } } return maxindex; } template double SparseVectorT::entropy () const { double entropy = 0.0; double sum = 0.0; for ( typename SparseVectorT::const_iterator j = this->begin(); j != this->end(); j++ ) { if ( j->second <= 0.0 ) continue; entropy -= (double)j->second * log ( (double)j->second ); sum += (double)j->second; } entropy /= sum; entropy += log ( sum ); return entropy; } template void SparseVectorT::getSortedIndices ( std::vector & indizes ) const { typename std::vector< std::pair > tmp; for ( typename SparseVectorT::const_iterator i = this->begin(); i != this->end() ; i++ ) tmp.push_back ( std::pair ( i->second, i->first ) ); std::sort ( tmp.begin(), tmp.end() ); for (typename std::vector >::const_iterator j = tmp.begin(); j != tmp.end(); j++ ) indizes.push_back ( j->second ); } template V SparseVectorT::max () const { V max = - std::numeric_limits::max(); for ( typename SparseVectorT::const_iterator it = this->begin(); it != this->end(); it++ ) { if ( it->second > max ) max = it->second; } return max; } template V SparseVectorT::min () const { V min = std::numeric_limits::max(); for ( typename SparseVectorT::const_iterator it = this->begin(); it != this->end(); it++ ) { if ( it->second < min ) min = it->second; } return min; } template V SparseVectorT::get ( I i ) const { typename SparseVectorT::const_iterator it = this->find ( i ); if ( it == this->end() ) return 0.0; else return it->second; } template bool SparseVectorT::set ( I i , V newValue ) { typename SparseVectorT::iterator it = this->find ( i ); if ( it == this->end() ) { // behavior change (2/2/2012 by erik) if ( newValue > 1e-20 ) this->insert ( std::pair ( i, newValue ) ); //update our dimensions if ( i > dim ) //changed on 10-02-2012 by alex dim = i; return false; } else { it->second = newValue; return true; } } template void SparseVectorT::setDim ( uint _dim ) { this->dim = _dim; } template uint SparseVectorT::getDim() const { return this->dim; } template double SparseVectorT::minimumKernel ( const SparseVectorT & b ) const { V sum = 0.0; typename SparseVectorT::const_iterator i = this->begin(); typename SparseVectorT::const_iterator j = b.begin(); while ( ( i != this->end() ) && ( j != b.end() ) ) { I idx1 = i->first; I idx2 = j->first; if ( idx1 == idx2 ) { sum += std::min ( i->second, j->second ); i++; j++; } else if ( idx1 > idx2 ) { j++; } else { i++; } } return sum; } template I SparseVectorT::pickRandomSample() const { typedef typename std::vector< std::pair > CumSumType; CumSumType cumsum; // calculate the cumulative sum, also known // as the distribution function F typename SparseVectorT::const_iterator i = this->begin(); for ( ; i != this->end(); i++ ) { V value; if ( i == this->begin() ) value = i->second; else value = cumsum.rbegin()->first + i->second; cumsum.push_back( std::pair ( value, i->first ) ); } V sum = cumsum.rbegin()->first; // sample between 0 and sum V t = (V)(randDouble() * sum); // find the position to calculate F^{-1} // std::pair searchElement ( (V)t, (I)0 ); typename CumSumType::const_iterator j = std::lower_bound(cumsum.begin(), cumsum.end(), searchElement ); // return element index return j->second; } template void SparseVectorT::convertToVectorT(NICE::VectorT & v ) const { uint dimension ( this->getDim() ); if ( dimension == 0 ) { // if dimension is zero, it could either be the case that the sparse vector is empty, or that the dimension flag was not set properly. // thus, let's check out the largest dimension // could be removed later... only needed for backwards compatibility typename SparseVectorT::const_reverse_iterator svIt = this->rbegin(); uint dist (distance(this->begin(), this->end()) ); if ( dist > 0 ) dimension = svIt->first+1; //plus one, since this is the index, but we need the resulting size //we're not allowed here to set the dimension flag, since we want to have this method to be a const one } // is our sparse vector empty? if ( dimension == 0 ) { v.clear(); v.resize(0); return; } //resize the new VectorT v.resize(dimension); //set default values to zero v.set( (V) 0.0); //add the actual content typename SparseVectorT::const_iterator svIt = this->begin(); for ( ; svIt != this->end(); svIt++ ) { v[svIt->first] = svIt->second; } } } //namepspace NICE #endif