- Main Page
- Namespaces
- Classes
- Files

- Search for |

# eoVRP.h

    00001 /*
    00002  * Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2007
    00003  * (C) OPAC Team, LIFL, 2002-2007
    00004  *
    00005  * (c) Antonio LaTorre <atorre@fi.upm.es>, 2007
    00006  *
    00007  * This software is governed by the CeCILL license under French law and
    00008  * abiding by the rules of distribution of free software.  You can  use,
    00009  * modify and/ or redistribute the software under the terms of the CeCILL
    00010  * license as circulated by CEA, CNRS and INRIA at the following URL
    00011  * "http://www.cecill.info".
    00012  *
    00013  * As a counterpart to the access to the source code and  rights to copy,
    00014  * modify and redistribute granted by the license, users are provided only
    00015  * with a limited warranty  and the software's author,  the holder of the
    00016  * economic rights,  and the successive licensors  have only  limited liability.
    00017  *
    00018  * In this respect, the user's attention is drawn to the risks associated
    00019  * with loading,  using,  modifying and/or developing or reproducing the
    00020  * software by the user in light of its specific status of free software,
    00021  * that may mean  that it is complicated to manipulate,  and  that  also
    00022  * therefore means  that it is reserved for developers  and  experienced
    00023  * professionals having in-depth computer knowledge. Users are therefore
    00024  * encouraged to load and test the software's suitability as regards their
    00025  * requirements in conditions enabling the security of their systems and/or
    00026  * data to be ensured and,  more generally, to use and operate it in the
    00027  * same conditions as regards security.
    00028  * The fact that you are presently reading this means that you have had
    00029  * knowledge of the CeCILL license and that you accept its terms.
    00030  *
    00031  * ParadisEO WebSite : http://paradiseo.gforge.inria.fr
    00032  * Contact: paradiseo-help@lists.gforge.inria.fr
    00033  *
    00034  */
    00035
    00036 #ifndef _eoVRP_h
    00037 #define _eoVRP_h
    00038
    00039 // The base definition of eoVector
    00040 #include <eoVector.h>
    00041
    00042 // Utilities for the VRP-TW problem
    00043 #include "eoVRPUtils.h"
    00044
    00050 class eoVRP: public eoVector<eoMinimizingFitness, int> {
    00051
    00052 public:
    00053
    00058     eoVRP () : mLength (0.0) {
    00059
    00060     }
    00061
    00062
    00068     eoVRP (const eoVRP& _orig) {
    00069
    00070         operator= (_orig);
    00071
    00072     }
    00073
    00074
    00079     virtual ~eoVRP () {
    00080
    00081     }
    00082
    00083
    00090     eoVRP& operator= (const eoVRP& _orig) {
    00091
    00092         // Sanity check
    00093         if (&_orig != this) {
    00094
    00095             // Cleans both individual and decoding information
    00096             clean ();
    00097
    00098             // We call the assignment operator from the base class
    00099             eoVector<eoMinimizingFitness, int>::operator= (_orig);
    00100
    00101             // And then copy all our attributes
    00102             mRoutes  = _orig.mRoutes;
    00103             mLength  = _orig.mLength;
    00104
    00105         }
    00106
    00107         return *this;
    00108
    00109     }
    00110
    00111
    00117     virtual std::string className () const {
    00118
    00119         return "eoVRP";
    00120
    00121     }
    00122
    00123
    00129     void printOn (std::ostream& _os) const {
    00130
    00131         // First write the fitness
    00132         _os << std::endl;
    00133
    00134         // Then the individual itself using the base printing method
    00135         eoVector<eoMinimizingFitness, int>::printOn (_os);
    00136         _os << std::endl << std::endl;
    00137
    00138     }
    00139
    00140
    00146     void printAllOn (std::ostream& _os) const {
    00147
    00148         // Print the individual itself using the base printing method
    00149         eoVector<eoMinimizingFitness, int>::printOn (_os);
    00150         _os << std::endl << std::endl;
    00151
    00152         // Check if we have decoding information to print
    00153         if (decoded ()) {
    00154
    00155             // First, we print the decoded routes (stored in mRoutes)
    00156             _os << " => Routes: " << std::endl << std::endl;
    00157             printRoutes (_os);
    00158             _os << std::endl << std::endl;
    00159
    00160             if (this->invalid ())
    00161                 _os << " => Fitness: INVALID." << std::endl << std::endl;
    00162             else
    00163                 _os << " => Fitness: " << this->fitness () << std::endl << std::endl;
    00164
    00165         }
    00166         else
    00167             std::cerr << "Warning: 'printAllOn' called but the individual was not already decoded." << std::endl;
    00168
    00169     }
    00170
    00171
    00177     void readFrom (std::istream& _is) {
    00178
    00179         // Read the individual using the method from the base class
    00180         eoVector<eoMinimizingFitness, int>::readFrom (_is);
    00181
    00182     }
    00183
    00184
    00190     const Routes& routes () {
    00191
    00192         if (mRoutes.size () == 0)
    00193             std::cerr << "Warning: This individual has not been already decoded." << std::endl;
    00194
    00195         return mRoutes;
    00196
    00197     }
    00198
    00199
    00205     double length () {
    00206
    00207         return mLength;
    00208
    00209     }
    00210
    00211
    00217     void printRoutes (std::ostream& _os) const {
    00218
    00219         _os << "[";
    00220
    00221         for (unsigned i = 0; i < mRoutes.size (); i++) {
    00222
    00223             _os << "[";
    00224
    00225             printRoute (_os, i);
    00226
    00227             if (i == mRoutes.size () - 1)
    00228                 _os << "]";
    00229             else
    00230                 _os << "]," << std::endl;
    00231         }
    00232
    00233         _os << "]";
    00234
    00235     }
    00236
    00237
    00244     void printRoute (std::ostream& _os, unsigned _p) const {
    00245
    00246         _os << "[";
    00247
    00248         for (unsigned i = 0; i < mRoutes [_p].size (); i++) {
    00249
    00250             _os << mRoutes [_p][i];
    00251
    00252             if (i != mRoutes [_p].size () - 1)
    00253                 _os << ", ";
    00254
    00255         }
    00256
    00257         _os << "]";
    00258
    00259     }
    00260
    00261
    00267     bool clean () {
    00268
    00269         this->clear ();
    00270         mRoutes.clear ();
    00271         mLength = 0.0;
    00272
    00273         return true;
    00274
    00275     }
    00276
    00277
    00283     bool cleanRoutes () {
    00284
    00285         mRoutes.clear ();
    00286         mLength = 0.0;
    00287
    00288         return true;
    00289
    00290     }
    00291
    00292
    00298     bool decoded () const {
    00299
    00300         if (mRoutes.size () == 0)
    00301             return false;
    00302
    00303         return true;
    00304
    00305     }
    00306
    00307
    00313     bool encode (Routes& _routes) {
    00314
    00315         clean ();
    00316
    00317         for (unsigned i = 0; i < _routes.size (); i++) {
    00318
    00319             for (unsigned j = 0; j < _routes [i].size (); j++)
    00320                 this->push_back (_routes [i][j]);
    00321
    00322         }
    00323
    00324         return true;
    00325
    00326     }
    00327
    00328
    00334     double decode () {
    00335
    00336         bool routeStart = true;
    00337
    00338         double demand = 0.0, route_len = 0.0, time = 0.0;
    00339         double readyTime, dueTime, serviceTime;
    00340         double depotReadyTime, depotDueTime, depotServiceTime;
    00341
    00342         cleanRoutes ();
    00343
    00344         Route route;
    00345
    00346         eoVRPUtils::getTimeWindow (0, depotReadyTime, depotDueTime, depotServiceTime);
    00347
    00348         for (unsigned i = 0; i < this->size (); i++) {
    00349
    00350             if (routeStart) {
    00351
    00352                 demand = eoVRPUtils::clients [this->operator[] (i)].demand;
    00353                 route_len = eoVRPUtils::distance (0, this->operator[] (i));
    00354                 time = eoVRPUtils::distance (0, this->operator[] (i));
    00355
    00356                 // The capacity of the vehicle must NEVER be exceeded by the first client
    00357                 // (it would be an instance impossible to solve in that case)
    00358                 if (demand > VEHICLE_CAPACITY) {
    00359
    00360                     std::cerr << "This should never happen: " << std::endl;
    00361                     abort ();
    00362
    00363                 }
    00364
    00365                 // Check that its TW is not exceeded
    00366                 eoVRPUtils::getTimeWindow (this->operator[] (i), readyTime, dueTime, serviceTime);
    00367
    00368                 // Same thing as with capacity and first client, but now with the TW
    00369                 if (time > dueTime) {
    00370
    00371                     std::cerr << "This should never happen: " << std::endl;
    00372                     abort ();
    00373
    00374                 }
    00375                 else if (time < readyTime)
    00376                     time = readyTime;
    00377
    00378                 time += serviceTime;
    00379
    00380                 route.push_back (this->operator[] (i));
    00381
    00382                 routeStart = false;
    00383
    00384             }
    00385             else {
    00386
    00387                 time += eoVRPUtils::distance (this->operator[] (i - 1), this->operator[] (i));
    00388
    00389                 // Check that its TW is not exceeded
    00390                 eoVRPUtils::getTimeWindow (this->operator[] (i), readyTime, dueTime, serviceTime);
    00391
    00392                 if ((time > dueTime) || (time + serviceTime + eoVRPUtils::distance (this->operator[] (i), 0) > depotDueTime) ||
    00393                         (demand + eoVRPUtils::clients [this->operator[] (i)].demand > VEHICLE_CAPACITY)                             ) {
    00394
    00395                     route_len += eoVRPUtils::distance (this->operator[] (i - 1), 0);
    00396
    00397                     mLength += route_len;
    00398
    00399                     i--;
    00400                     routeStart = true;
    00401
    00402                     // A route should contain, at least, one client. This should never happen, anyway...
    00403                     if (route.size () == 0) {
    00404
    00405                         std::cerr << "Error: empty route detected while decoding. The wrong genome follows..." << std::endl;
    00406                         this->printOn (std::cerr);
    00407                         abort ();
    00408
    00409                     }
    00410
    00411                     mRoutes.push_back (route);
    00412                     route.clear ();
    00413
    00414                 }
    00415                 else {
    00416
    00417                     if (time < readyTime)
    00418                         time = readyTime;
    00419
    00420                     time += serviceTime;
    00421
    00422                     route_len += eoVRPUtils::distance (this->operator[] (i - 1), this->operator[] (i));
    00423                     demand += eoVRPUtils::clients [this->operator[] (i)].demand;
    00424
    00425                     route.push_back (this->operator[] (i));
    00426
    00427                 }
    00428
    00429             }
    00430
    00431         }
    00432
    00433         if (route.size () > 0) {
    00434
    00435             route_len += eoVRPUtils::distance (route [route.size () - 1], 0);
    00436
    00437             mLength += route_len;
    00438             mRoutes.push_back (route);
    00439             route.clear ();
    00440
    00441         }
    00442
    00443         return mLength;
    00444
    00445     }
    00446
    00447
    00448 private:
    00449
    00450     Routes mRoutes;
    00451     double mLength;
    00453 };
    00454
    00455 #endif