Optimizer.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef Optimizer_hh
00028 #define Optimizer_hh
00029
00030 #include "Input.h"
00031 #include "Params.h"
00032 #include "util/Exception.h"
00033
00034 #include <vector>
00035 #include <iostream>
00036
00037 #include <cmath>
00038
00039
00044 #define ROUND( x ) (x < 0 ? std::ceil( (x) - 0.5 ) : std::floor( (x) + 0.5 ))
00045
00046 const Params::Size_t EPSILON = 0.000001;
00047
00048
00049 class Optimizer;
00050 class BinSet;
00051
00056 static bool AlmostEqual( double u, double v )
00057 {
00058 return std::fabs( u - v ) <= EPSILON * std::fabs( u ) &&
00059 std::fabs( u - v ) <= EPSILON * std::fabs( v );
00060 }
00061
00062
00067 class Bin {
00068 public:
00072 Bin( Params::Size_t capacity ):
00073 m_sum_sizes( 0.0 ), m_capacity( capacity ) {}
00074
00078 Bin( const std::vector<const SizeName*>& sn )
00079 {
00080 for( unsigned i = 0; i < sn.size(); ++i ) AddItem( sn[i] );
00081 m_capacity = Used();
00082 }
00083
00087 unsigned Count() const { return m_items.size(); }
00088
00092 const SizeName* Item( int i ) const { return m_items[i]; }
00093
00097 std::vector<const SizeName*>& Items() { return m_items; }
00101 const std::vector<const SizeName*>& Items() const { return m_items; }
00102
00106 Params::Size_t Used() const { return m_sum_sizes; }
00107
00111 Params::Size_t Free() const { return Capacity() - Used(); }
00119 Params::Size_t Capacity() const { return m_capacity; }
00120
00124 void AddItem( const SizeName* i )
00125 {
00126
00127 m_items.push_back(i);
00128 m_sum_sizes += i->Size();
00129 }
00130
00134 void ReplaceItem( int i, const SizeName* item )
00135 {
00136 m_sum_sizes += ( item->Size() - m_items[i]->Size() );
00137 m_items[i] = item;
00138 }
00139
00143 void DelItem( int i )
00144 {
00145
00146 m_sum_sizes -= m_items[i]->Size();
00147 m_items.erase( m_items.begin() + i );
00148 }
00149
00153 void AddAllItems( Bin& b )
00154 {
00155 for( unsigned i = 0; i < b.Count(); ++i ) AddItem( b[i] );
00156 }
00157
00161 void DelAllItems() { m_items.clear(); m_sum_sizes = 0.0; }
00162
00166 const SizeName* operator[](int i) const { return m_items[i]; }
00167
00175 bool operator<( const Bin& bin ) const
00176 {
00177 if ( Free() < bin.Free() ) return true;
00178 if ( Free() == bin.Free() ) return Count() < bin.Count();
00179
00180 return false;
00181 }
00182
00192 bool operator==( const Bin& bin ) const
00193 {
00194 return ( AlmostEqual( bin.Free(), Free() ) && bin.Count() == Count() );
00195 }
00196
00200 std::vector<const SizeName*>::iterator begin() { return m_items.begin(); }
00204 std::vector<const SizeName*>::iterator end() { return m_items.end(); }
00205
00215 friend bool Intersect( Bin& a, std::vector<Bin>::iterator g1,
00216 std::vector<Bin>::iterator g2,
00217 std::vector<const SizeName*>& unassigned );
00218 private:
00219 std::vector<const SizeName*> m_items;
00220 Params::Size_t m_sum_sizes;
00221 Params::Size_t m_capacity;
00222 };
00223
00224
00229 class BinSet {
00230 public:
00234 Bin& operator[]( int i ) { return m_bins[i]; }
00238 const Bin& operator[]( int i ) const { return m_bins[i]; }
00239
00243 Bin& AddBin( Params::Size_t capacity )
00244 {
00245 m_bins.push_back( Bin( capacity ) );
00246 return m_bins.back();
00247 }
00251 Bin& AddBin(const Bin& b) { m_bins.push_back(b); return m_bins.back(); }
00252
00256 std::vector<Bin>::iterator begin() { return m_bins.begin(); }
00260 std::vector<Bin>::iterator end() { return m_bins.end(); }
00261
00265 void DelBin( int i ) { m_bins.erase( m_bins.begin() + i ); }
00269 void DelAllBins() { m_bins.clear(); }
00270
00274 unsigned int Count() const { return m_bins.size(); }
00275
00279 bool operator!=( const BinSet& bs ) const { return !( *this == bs ); }
00283 bool operator==( const BinSet& bs ) const
00284 {
00285 if( Count() != bs.Count() ) return false;
00286 std::vector<Bin>::const_iterator i = m_bins.begin(), j = bs.m_bins.begin();
00287
00288 while( i != m_bins.end() ) if( !(*i++ == *j++) ) return false;
00289
00290 return true;
00291 }
00292
00293 private:
00294 std::vector<Bin> m_bins;
00295 };
00296
00297
00302 class Optimizer {
00303 public:
00307 Optimizer( Input& i ): m_files( i.m_files ), m_params( i.m_params ),
00308 m_total_size( i.m_total_size ), m_solution( 0 )
00309 {
00310
00311
00312
00313
00314
00315
00316 if( !m_params.m_bins_theo )
00317 {
00318 const Params::Size_t div = m_total_size / m_params.m_target;
00319 if( div > ROUND( div ) && div - ROUND( div ) < EPSILON )
00320 m_params.m_bins_theo = static_cast<unsigned>( ROUND( div ) );
00321 else
00322 m_params.m_bins_theo = static_cast<unsigned>( ceil( div ) );
00323 }
00324
00325 if( m_params.m_verbose ) std::cout << "> Searching... "
00326 << std::flush << std::endl;
00327 }
00328
00332 virtual ~Optimizer() {};
00333
00334 private:
00338 Optimizer( const Optimizer& );
00342 Optimizer& operator=( const Optimizer& );
00343
00344 public:
00349 virtual void Evolve() = 0;
00356 void Output();
00361 friend std::ostream& operator<<( std::ostream&, const Optimizer& );
00362
00363 protected:
00367 virtual std::ostream& Write( std::ostream& s ) const
00368 {
00369 s << "> Target: " << m_params.PrettySize(m_params.m_target)
00370 << "\n> Input size: " << m_files.size()
00371 << "\n> Theoretical minimum number of bins: " << m_params.m_bins_theo
00372 << std::endl;
00373
00374 return s;
00375 }
00376
00377 protected:
00381 Params::Size_t Evaluate( const BinSet& bs ) const;
00382 std::vector<const SizeName*>& m_files;
00384 Params& m_params;
00385 const Params::Size_t m_total_size;
00386 protected:
00387 BinSet* m_solution;
00388 };
00389
00390
00391 inline std::ostream& operator<<( std::ostream& s, const Optimizer& optimizer )
00392 {
00393 return optimizer.Write( s );
00394 }
00395
00396
00397 #endif