Optimizer.h

Go to the documentation of this file.
00001 // ---------------------------------------------------------------------------
00002 // $Id: Optimizer.h 232 2008-08-15 18:19:35Z daaugusto $
00003 //
00004 //   Optimizer.h (created on Thu Nov 17 18:25:35 BRT 2005)
00005 // 
00006 //   Genetic Algorithm File Fitter (gaffitter)
00007 //
00008 //   Copyright (C) 2005-2008 Douglas A. Augusto
00009 // 
00010 // This file is part of gaffitter.
00011 // 
00012 // gaffitter is free software; you can redistribute it and/or modify it
00013 // under the terms of the GNU General Public License as published by the
00014 // Free Software Foundation; either version 3 of the License, or (at
00015 // your option) any later version.
00016 // 
00017 // gaffitter is distributed in the hope that it will be useful, but
00018 // WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 // General Public License for more details.
00021 // 
00022 // You should have received a copy of the GNU General Public License
00023 // along with gaffitter; if not, see <http://www.gnu.org/licenses/>.
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       //Assert (i->Size() <= Free());
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       //Assert(m_items[i]->Size() <= Used());
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       /* The correct way to calculate m_bin_theo. A problematic scenario
00311        * occurs, for instance, when the total size is 2000 and the bin
00312        * capacity (target) is 100, and unfortunately the division
00313        * 2000/100 is represented as 20.000001 rather than the exact
00314        * 20.0; so, ceil( 20.000001) is 21 instead of giving 20 as the
00315        * theoretical minimum number of bin. */
00316       if( !m_params.m_bins_theo ) // if not given calculate it!
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