complete vcrptw package with an AUTHORS file + the sources at least
git-svn-id: svn://scm.gforge.inria.fr/svnroot/paradiseo@835 331e1502-861f-0410-8da2-ba01fb791d7f
This commit is contained in:
parent
328b5cc66e
commit
7d6038307e
9 changed files with 2255 additions and 0 deletions
3
contribution/trunk/combinatorial/routing/vrptw/AUTHORS
Normal file
3
contribution/trunk/combinatorial/routing/vrptw/AUTHORS
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
Antonio LaTorre atorre[at]fi.upm.es
|
||||
Thomas Legrand paradiseo-help[at]lists.gforge.inria.fr
|
||||
455
contribution/trunk/combinatorial/routing/vrptw/src/eoVRP.h
Normal file
455
contribution/trunk/combinatorial/routing/vrptw/src/eoVRP.h
Normal file
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2007
|
||||
* (C) OPAC Team, LIFL, 2002-2007
|
||||
*
|
||||
* (c) Antonio LaTorre <atorre@fi.upm.es>, 2007
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*
|
||||
* ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
* Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _eoVRP_h
|
||||
#define _eoVRP_h
|
||||
|
||||
// The base definition of eoVector
|
||||
#include <eoVector.h>
|
||||
|
||||
// Utilities for the VRP-TW problem
|
||||
#include "eoVRPUtils.h"
|
||||
|
||||
/**
|
||||
* \class eoVRP eoVRP.h
|
||||
* \brief Defines the getoype used to solve the VRP-TW problem.
|
||||
*/
|
||||
|
||||
class eoVRP: public eoVector<eoMinimizingFitness, int> {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Default constructor: initializes variables to safe values.
|
||||
*/
|
||||
|
||||
eoVRP () : mLength (0.0) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Copy contructor: creates a new individual from a given one.
|
||||
* \param _orig The individual used to create the new one.
|
||||
*/
|
||||
|
||||
eoVRP (const eoVRP& _orig) {
|
||||
|
||||
operator= (_orig);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Default destructor: nothing to do here.
|
||||
*/
|
||||
|
||||
virtual ~eoVRP () {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Performs a copy from the invidual passed as argument.
|
||||
* \param _orig The individual to copy from.
|
||||
* \return A reference to this.
|
||||
*/
|
||||
|
||||
eoVRP& operator= (const eoVRP& _orig) {
|
||||
|
||||
// Sanity check
|
||||
if (&_orig != this) {
|
||||
|
||||
// Cleans both individual and decoding information
|
||||
clean ();
|
||||
|
||||
// We call the assignment operator from the base class
|
||||
eoVector<eoMinimizingFitness, int>::operator= (_orig);
|
||||
|
||||
// And then copy all our attributes
|
||||
mRoutes = _orig.mRoutes;
|
||||
mLength = _orig.mLength;
|
||||
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns a string containing the name of the class.
|
||||
* \return The string containing the name of the class.
|
||||
*/
|
||||
|
||||
virtual std::string className () const {
|
||||
|
||||
return "eoVRP";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Prints the individual to a given stream.
|
||||
* \param _os The stream to print to.
|
||||
*/
|
||||
|
||||
void printOn (std::ostream& _os) const {
|
||||
|
||||
// First write the fitness
|
||||
_os << std::endl;
|
||||
|
||||
// Then the individual itself using the base printing method
|
||||
eoVector<eoMinimizingFitness, int>::printOn (_os);
|
||||
_os << std::endl << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Prints a detailed version of the individual (decoding information, unsatisfied contraints, etc.) to a given stream.
|
||||
* \param _os The stream to print to.
|
||||
*/
|
||||
|
||||
void printAllOn (std::ostream& _os) const {
|
||||
|
||||
// Print the individual itself using the base printing method
|
||||
eoVector<eoMinimizingFitness, int>::printOn (_os);
|
||||
_os << std::endl << std::endl;
|
||||
|
||||
// Check if we have decoding information to print
|
||||
if (decoded ()) {
|
||||
|
||||
// First, we print the decoded routes (stored in mRoutes)
|
||||
_os << " => Routes: " << std::endl << std::endl;
|
||||
printRoutes (_os);
|
||||
_os << std::endl << std::endl;
|
||||
|
||||
if (this->invalid ())
|
||||
_os << " => Fitness: INVALID." << std::endl << std::endl;
|
||||
else
|
||||
_os << " => Fitness: " << this->fitness () << std::endl << std::endl;
|
||||
|
||||
}
|
||||
else
|
||||
std::cerr << "Warning: 'printAllOn' called but the individual was not already decoded." << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Reads an individual from a given stream.
|
||||
* \param _is The stream to read from.
|
||||
*/
|
||||
|
||||
void readFrom (std::istream& _is) {
|
||||
|
||||
// Read the individual using the method from the base class
|
||||
eoVector<eoMinimizingFitness, int>::readFrom (_is);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns a reference to the decoded individual.
|
||||
* \return A reference to the decoded individual.
|
||||
*/
|
||||
|
||||
const Routes& routes () {
|
||||
|
||||
if (mRoutes.size () == 0)
|
||||
std::cerr << "Warning: This individual has not been already decoded." << std::endl;
|
||||
|
||||
return mRoutes;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns the total cost (length) of traveling all the routes.
|
||||
* \return The total cost (length) of traveling all the routes.
|
||||
*/
|
||||
|
||||
double length () {
|
||||
|
||||
return mLength;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Aux. method to print a structure of routes.
|
||||
* \param _os The stream to print to.
|
||||
*/
|
||||
|
||||
void printRoutes (std::ostream& _os) const {
|
||||
|
||||
_os << "[";
|
||||
|
||||
for (unsigned i = 0; i < mRoutes.size (); i++) {
|
||||
|
||||
_os << "[";
|
||||
|
||||
printRoute (_os, i);
|
||||
|
||||
if (i == mRoutes.size () - 1)
|
||||
_os << "]";
|
||||
else
|
||||
_os << "]," << std::endl;
|
||||
}
|
||||
|
||||
_os << "]";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Aux. method to print only one route.
|
||||
* \param _os The stream to print to.
|
||||
* \param _p The route to print.
|
||||
*/
|
||||
|
||||
void printRoute (std::ostream& _os, unsigned _p) const {
|
||||
|
||||
_os << "[";
|
||||
|
||||
for (unsigned i = 0; i < mRoutes [_p].size (); i++) {
|
||||
|
||||
_os << mRoutes [_p][i];
|
||||
|
||||
if (i != mRoutes [_p].size () - 1)
|
||||
_os << ", ";
|
||||
|
||||
}
|
||||
|
||||
_os << "]";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Cleans the individual (the vector of clients and also the decoding information).
|
||||
* \return True if the operation finishes correctly. False otherwise.
|
||||
*/
|
||||
|
||||
bool clean () {
|
||||
|
||||
this->clear ();
|
||||
mRoutes.clear ();
|
||||
mLength = 0.0;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Invalidates the decoding information (usually after crossover or mutation).
|
||||
* \return True if the operation finishes correctly. False otherwise.
|
||||
*/
|
||||
|
||||
bool cleanRoutes () {
|
||||
|
||||
mRoutes.clear ();
|
||||
mLength = 0.0;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Has this individual been decoded?
|
||||
* \return True if has decoding information. False otherwise.
|
||||
*/
|
||||
|
||||
bool decoded () const {
|
||||
|
||||
if (mRoutes.size () == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encodes an individual from a set of routes (usually used within crossover).
|
||||
* \return True if the operation finishes correctly. False otherwise.
|
||||
*/
|
||||
|
||||
bool encode (Routes& _routes) {
|
||||
|
||||
clean ();
|
||||
|
||||
for (unsigned i = 0; i < _routes.size (); i++) {
|
||||
|
||||
for (unsigned j = 0; j < _routes [i].size (); j++)
|
||||
this->push_back (_routes [i][j]);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decodes an individual in a set of routes and calculates its cost (length) of traveling.
|
||||
* \return The cost (length) of traveling the set of routes.
|
||||
*/
|
||||
|
||||
double decode () {
|
||||
|
||||
bool routeStart = true;
|
||||
|
||||
double demand = 0.0, route_len = 0.0, time = 0.0;
|
||||
double readyTime, dueTime, serviceTime;
|
||||
double depotReadyTime, depotDueTime, depotServiceTime;
|
||||
|
||||
cleanRoutes ();
|
||||
|
||||
Route route;
|
||||
|
||||
eoVRPUtils::getTimeWindow (0, depotReadyTime, depotDueTime, depotServiceTime);
|
||||
|
||||
for (unsigned i = 0; i < this->size (); i++) {
|
||||
|
||||
if (routeStart) {
|
||||
|
||||
demand = eoVRPUtils::clients [this->operator[] (i)].demand;
|
||||
route_len = eoVRPUtils::distance (0, this->operator[] (i));
|
||||
time = eoVRPUtils::distance (0, this->operator[] (i));
|
||||
|
||||
// The capacity of the vehicle must NEVER be exceeded by the first client
|
||||
// (it would be an instance impossible to solve in that case)
|
||||
if (demand > VEHICLE_CAPACITY) {
|
||||
|
||||
std::cerr << "This should never happen: " << std::endl;
|
||||
abort ();
|
||||
|
||||
}
|
||||
|
||||
// Check that its TW is not exceeded
|
||||
eoVRPUtils::getTimeWindow (this->operator[] (i), readyTime, dueTime, serviceTime);
|
||||
|
||||
// Same thing as with capacity and first client, but now with the TW
|
||||
if (time > dueTime) {
|
||||
|
||||
std::cerr << "This should never happen: " << std::endl;
|
||||
abort ();
|
||||
|
||||
}
|
||||
else if (time < readyTime)
|
||||
time = readyTime;
|
||||
|
||||
time += serviceTime;
|
||||
|
||||
route.push_back (this->operator[] (i));
|
||||
|
||||
routeStart = false;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
time += eoVRPUtils::distance (this->operator[] (i - 1), this->operator[] (i));
|
||||
|
||||
// Check that its TW is not exceeded
|
||||
eoVRPUtils::getTimeWindow (this->operator[] (i), readyTime, dueTime, serviceTime);
|
||||
|
||||
if ((time > dueTime) || (time + serviceTime + eoVRPUtils::distance (this->operator[] (i), 0) > depotDueTime) ||
|
||||
(demand + eoVRPUtils::clients [this->operator[] (i)].demand > VEHICLE_CAPACITY) ) {
|
||||
|
||||
route_len += eoVRPUtils::distance (this->operator[] (i - 1), 0);
|
||||
|
||||
mLength += route_len;
|
||||
|
||||
i--;
|
||||
routeStart = true;
|
||||
|
||||
// A route should contain, at least, one client. This should never happen, anyway...
|
||||
if (route.size () == 0) {
|
||||
|
||||
std::cerr << "Error: empty route detected while decoding. The wrong genome follows..." << std::endl;
|
||||
this->printOn (std::cerr);
|
||||
abort ();
|
||||
|
||||
}
|
||||
|
||||
mRoutes.push_back (route);
|
||||
route.clear ();
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
if (time < readyTime)
|
||||
time = readyTime;
|
||||
|
||||
time += serviceTime;
|
||||
|
||||
route_len += eoVRPUtils::distance (this->operator[] (i - 1), this->operator[] (i));
|
||||
demand += eoVRPUtils::clients [this->operator[] (i)].demand;
|
||||
|
||||
route.push_back (this->operator[] (i));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (route.size () > 0) {
|
||||
|
||||
route_len += eoVRPUtils::distance (route [route.size () - 1], 0);
|
||||
|
||||
mLength += route_len;
|
||||
mRoutes.push_back (route);
|
||||
route.clear ();
|
||||
|
||||
}
|
||||
|
||||
return mLength;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Routes mRoutes; /**< A set of routes containing the decoding information of the individual. */
|
||||
double mLength; /**< Cached cost (length) of traveling the set of routes defined by the individual. */
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2007
|
||||
* (C) OPAC Team, LIFL, 2002-2007
|
||||
*
|
||||
* (c) Antonio LaTorre <atorre@fi.upm.es>, 2007
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*
|
||||
* ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
* Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _eoVRPEvalFunc_h
|
||||
#define _eoVRPEvalFunc_h
|
||||
|
||||
// General includes
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
|
||||
// The base definition of eoEvalFunc
|
||||
#include "eoEvalFunc.h"
|
||||
|
||||
// Utilities for the VRP-TW problem
|
||||
#include "eoVRPUtils.h"
|
||||
|
||||
/**
|
||||
* \class eoVRPEvalFunc eoVRPEvalFunc.h
|
||||
* \brief Evaluates an individual of type eoVRP.
|
||||
*/
|
||||
|
||||
class eoVRPEvalFunc : public eoEvalFunc<eoVRP> {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Constructor: nothing to do here.
|
||||
*/
|
||||
|
||||
eoVRPEvalFunc () {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Computes the (penalized) fitness
|
||||
* \param _eo The individual to be evaluated.
|
||||
*/
|
||||
|
||||
void operator () (eoVRP& _eo) {
|
||||
|
||||
double fit = 0.0;
|
||||
|
||||
if (_eo.decoded ()) {
|
||||
|
||||
if (_eo.invalid ()) {
|
||||
|
||||
std::cerr << "Warning: invalid individual presents decoding information." << std::endl;
|
||||
fit = _eo.decode ();
|
||||
|
||||
}
|
||||
else
|
||||
fit = _eo.length ();
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
if (!_eo.invalid ()) {
|
||||
|
||||
std::cerr << "Warning: valid individual does not present decoding information." << std::endl;
|
||||
std::cerr << " Proceeding to decode..." << std::endl;
|
||||
|
||||
}
|
||||
|
||||
fit = _eo.decode ();
|
||||
|
||||
}
|
||||
|
||||
_eo.fitness (fit);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
606
contribution/trunk/combinatorial/routing/vrptw/src/eoVRPInit.h
Normal file
606
contribution/trunk/combinatorial/routing/vrptw/src/eoVRPInit.h
Normal file
|
|
@ -0,0 +1,606 @@
|
|||
/*
|
||||
* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2007
|
||||
* (C) OPAC Team, LIFL, 2002-2007
|
||||
*
|
||||
* (c) Antonio LaTorre <atorre@fi.upm.es>, 2007
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*
|
||||
* ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
* Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _eoVRPInit_h
|
||||
#define _eoVRPInit_h
|
||||
|
||||
// The base definition of eoInit
|
||||
#include <eoInit.h>
|
||||
|
||||
// Utilities for the VRP-TW problem
|
||||
#include "eoVRPUtils.h"
|
||||
|
||||
/**
|
||||
* \def ALFA
|
||||
* Constant used by "selectCheapestClient" method.
|
||||
* \def BETA
|
||||
* Constant used by "selectCheapestClient" method.
|
||||
* \def GAMMA
|
||||
* Constant used by "selectCheapestClient" method.
|
||||
*/
|
||||
|
||||
#define ALFA 0.7
|
||||
#define BETA 0.1
|
||||
#define GAMMA 0.2
|
||||
|
||||
/**
|
||||
* \class eoVRPInit eoVRPInit.h
|
||||
* \brief Class defining the initializer functor.
|
||||
* This class initializes an individual of the VRP problem using
|
||||
* an heuristic initializer.
|
||||
*/
|
||||
|
||||
class eoVRPInit: public eoInit <eoVRP> {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Default constructor: nothing to do here.
|
||||
*/
|
||||
|
||||
eoVRPInit () {
|
||||
|
||||
unsigned sz = eoVRPUtils::clients.size ();
|
||||
|
||||
if (sz <= 0) {
|
||||
|
||||
std::cerr << "Error: the dataset MUST be read before creating the initializer object." << std::endl;
|
||||
abort ();
|
||||
|
||||
}
|
||||
|
||||
mSeedsUsedCount = 0;
|
||||
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
mSeedsUsed.push_back (false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Functor member.
|
||||
* Initializes a genotype using an heuristic initializer.
|
||||
* \param _gen Generally a genotype that has been default-constructed.
|
||||
* Whatever it contains will be lost.
|
||||
*/
|
||||
|
||||
void operator () (eoVRP& _gen) {
|
||||
|
||||
HeuristicInitialization (_gen);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
unsigned mSeedsUsedCount; /**< Number of clients already used as seeds. */
|
||||
std::vector<bool> mSeedsUsed; /**< Vector storing if a client has been used as a seed or not. */
|
||||
|
||||
|
||||
/**
|
||||
* \brief Heuristic initializer.
|
||||
* This initializer constructs and individual from routes. Each route is built
|
||||
* in a constructive way. The first client of each route is selected trying to
|
||||
* maximize a function depending on its time window and how far it is from the depot.
|
||||
* We always try to select the hardest clients as seeds. Used seeds are stored
|
||||
* so that different seeds are selected for different individuals and thus guarantee
|
||||
* the diversity of the initial population.
|
||||
* \param _gen The individual to be initialized.
|
||||
*/
|
||||
|
||||
void HeuristicInitialization (eoVRP& _gen) {
|
||||
|
||||
// Aux var to override seed used checking
|
||||
bool seedCheckingOverride = false;
|
||||
|
||||
// Erase any previous contents
|
||||
_gen.clear ();
|
||||
|
||||
// Aux vector to store unvisited clients
|
||||
std::vector<int> unvisited;
|
||||
|
||||
// And an index to point to the last unvisited cutomer
|
||||
int unvisitedIdx = eoVRPUtils::clients.size () - 2;
|
||||
|
||||
// Initialization of the unvisited vector with all the clients
|
||||
for (unsigned i = 1; i < eoVRPUtils::clients.size (); i++)
|
||||
unvisited.push_back (i);
|
||||
|
||||
// Main loop: keep iterating until all clients are visited
|
||||
while (unvisitedIdx >= 0) {
|
||||
|
||||
// Aux var to store the new route
|
||||
Route route;
|
||||
|
||||
createNewRoute (unvisited, unvisitedIdx, seedCheckingOverride, route);
|
||||
seedCheckingOverride = true;
|
||||
|
||||
for (unsigned i = 0; i < route.size (); i++)
|
||||
_gen.push_back (route [i]);
|
||||
|
||||
}
|
||||
|
||||
// Invalidates the genotype forcing its re-evaluation
|
||||
_gen.invalidate ();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Creates a new route.
|
||||
* Creates a new route selecting the best (hardest) client as seed and then adding
|
||||
* the cheapest clients until one of the constraints (time window or vehicle's capacity)
|
||||
* is broken.
|
||||
* \param _unvisited Vector of unvisited and thus available clients for constructing the new route.
|
||||
* \param _unvisitedIdx Position of the last univisted client in _unvisited vector.
|
||||
* \param _seedCheckingOverride If true, it overrides the seed checking mecanism. It must be
|
||||
* always false for the first route and then true for the following ones.
|
||||
* This way we will preserve diversity in our initial population as every individual
|
||||
* will be initialized from a different initial route.
|
||||
* \param _route The brand new route we have constructed.
|
||||
* \return True if everything went ok.
|
||||
*/
|
||||
|
||||
bool createNewRoute (std::vector<int>& _unvisited, int& _unvisitedIdx,
|
||||
bool _seedCheckingOverride, Route& _route ) {
|
||||
|
||||
// Selection of seed client for current route
|
||||
unsigned seed = selectBestClientAsSeed (_unvisited, _unvisitedIdx, _seedCheckingOverride);
|
||||
|
||||
// Add the seed client to the route
|
||||
_route.push_back (_unvisited [seed]);
|
||||
|
||||
// Mark the client as already selected as a main seed
|
||||
// (i.e., as a seed for the first subroute of an individual)
|
||||
if (!_seedCheckingOverride) {
|
||||
|
||||
mSeedsUsed [_unvisited [seed]] = true;
|
||||
mSeedsUsedCount++;
|
||||
|
||||
if (mSeedsUsedCount == mSeedsUsed.size () - 1) {
|
||||
|
||||
mSeedsUsedCount = 0;
|
||||
|
||||
for (unsigned i = 0; i < mSeedsUsed.size (); i++)
|
||||
mSeedsUsed [i] = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Delete the selected client from the unvisited vector
|
||||
_unvisited [seed] = _unvisited [_unvisitedIdx];
|
||||
_unvisitedIdx--;
|
||||
|
||||
bool feasibleInsert = true;
|
||||
|
||||
while (feasibleInsert && _unvisitedIdx >= 0) {
|
||||
|
||||
// Aux var to store the position to insert new clients in the route
|
||||
Route::iterator it;
|
||||
|
||||
unsigned next;
|
||||
|
||||
if (selectBestInsertion (_unvisited, _unvisitedIdx, _route, next, it)) {
|
||||
|
||||
if (it == _route.end ())
|
||||
_route.insert (_route.begin (), _unvisited [next]);
|
||||
else
|
||||
_route.insert (it + 1, _unvisited [next]);
|
||||
|
||||
_unvisited [next] = _unvisited [_unvisitedIdx];
|
||||
_unvisitedIdx--;
|
||||
|
||||
}
|
||||
else
|
||||
feasibleInsert = false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Selects the best client and the best position for its insertion in a given route.
|
||||
* Given a subroute, this method tries to find the best client and the best position for it
|
||||
* among all the univisited clients.
|
||||
* \param _unvisited Vector of unvisited and thus available clients for constructing the new route.
|
||||
* \param _unvisitedIdx Position of the last univisted client in _unvisited vector.
|
||||
* \param _route The route where we are trying to insert a new client.
|
||||
* \param _nextClient A return value. The selected client to be inserted.
|
||||
* \param _it A return value. The position for selected client to be inserted.
|
||||
* \return True if a new insertion is possible. False otherwise.
|
||||
*/
|
||||
|
||||
bool selectBestInsertion (std::vector<int>& _unvisited, unsigned _unvisitedIdx, Route& _route,
|
||||
unsigned& _nextClient, Route::iterator& _it ) {
|
||||
|
||||
double minCost = 999999999;
|
||||
bool found = false;
|
||||
|
||||
bool insertionPossible = false;
|
||||
double cost = 0.0;
|
||||
|
||||
for (unsigned i = 0; i < _unvisitedIdx; i++) {
|
||||
|
||||
insertionPossible = evaluateInsertion (_route, _unvisited [i], -1, cost);
|
||||
|
||||
if (insertionPossible && cost < minCost) {
|
||||
|
||||
_it = _route.end ();
|
||||
_nextClient = i;
|
||||
minCost = cost;
|
||||
found = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (Route::iterator it = _route.begin (); it != _route.end (); it++) {
|
||||
|
||||
for (unsigned i = 0; i < _unvisitedIdx; i++) {
|
||||
|
||||
insertionPossible = evaluateInsertion (_route, _unvisited [i], *it, cost);
|
||||
|
||||
if (insertionPossible && cost < minCost) {
|
||||
|
||||
_it = it;
|
||||
_nextClient = i;
|
||||
minCost = cost;
|
||||
found = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return found;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Evaluates the feasibility and the cost of inserting a new client in a given subroute.
|
||||
* Given a subroute, this method tries evaluates if it is possible to insert a client in a position.
|
||||
* It will return the cost of the resulting route if this insertion is possible.
|
||||
* \param _route The route where we are trying to insert a new client.
|
||||
* \param _newClient The client we are trying to insert.
|
||||
* \param _afterClient The position of insertion.
|
||||
* \param _cost A return value. The cost of inserting the given client at the given position.
|
||||
* \return True if the new insertion is possible. False otherwise.
|
||||
*/
|
||||
|
||||
bool evaluateInsertion (Route& _route, unsigned _newClient, int _afterClient, double& _cost) {
|
||||
|
||||
// First of all, we check for capacity constraint to be satisfied
|
||||
// before trying to insert the new client in the route
|
||||
double demand = 0.0;
|
||||
|
||||
// Cummulate the demand of all the clients in the current route
|
||||
for (unsigned i = 0; i < _route.size (); i++)
|
||||
demand += eoVRPUtils::clients [i].demand;
|
||||
|
||||
// And then the demand of the new client
|
||||
demand += eoVRPUtils::clients [_newClient].demand;
|
||||
|
||||
// And finally, check if the cummulated demand exceeds vehicle's capacity
|
||||
if (demand > VEHICLE_CAPACITY)
|
||||
return false;
|
||||
|
||||
// Now check for insertion position and TW constraints
|
||||
double readyTime, dueTime, serviceTime;
|
||||
|
||||
// If the client must be inserted after client "-1" that means that it
|
||||
// has to be inserted at the very beginning of the route
|
||||
if (_afterClient == - 1) {
|
||||
|
||||
// We calculate the distante from the depot to the inserted client
|
||||
_cost = eoVRPUtils::distance (0, _newClient);
|
||||
|
||||
// And check that its TW is not exceeded
|
||||
eoVRPUtils::getTimeWindow (_newClient, readyTime, dueTime, serviceTime);
|
||||
|
||||
if (_cost > dueTime)
|
||||
return false;
|
||||
|
||||
// If the vehicle arrives before client's ready time, it has
|
||||
// to wait until the client is ready
|
||||
if (_cost < readyTime)
|
||||
_cost = readyTime;
|
||||
|
||||
// Add the service time for the newly inserted client
|
||||
_cost += serviceTime;
|
||||
|
||||
// And the cost of traveling to the next one (the first one in the old route)
|
||||
_cost = _cost + eoVRPUtils::distance (_newClient, _route [0]);
|
||||
|
||||
}
|
||||
else
|
||||
// We just need to add the cost of traveling from the depot to the first client
|
||||
_cost = eoVRPUtils::distance (0, _route [0]);
|
||||
|
||||
// Main loop to evaluate the rest of the route (except the last position)
|
||||
for (unsigned i = 0; i < _route.size () - 1; i++) {
|
||||
|
||||
// Check that the TW is not exceeded for the current client
|
||||
eoVRPUtils::getTimeWindow (_route [i], readyTime, dueTime, serviceTime);
|
||||
|
||||
if (_cost > dueTime)
|
||||
return false;
|
||||
|
||||
// If it is not exceeded, we check wether the vehicle arrives before
|
||||
// the client is ready. If that's the case, it has to wait
|
||||
if (_cost < readyTime)
|
||||
_cost = readyTime;
|
||||
|
||||
// We add the service time for this client
|
||||
_cost += serviceTime;
|
||||
|
||||
// And now check if we have to insert the new client after the current one
|
||||
if (_route [i] == _afterClient) {
|
||||
|
||||
// If that's the case, we add the cost of traveling from current client
|
||||
// to the new one
|
||||
_cost = _cost + eoVRPUtils::distance (_route [i], _newClient);
|
||||
|
||||
// And check for its TW to be not exceeded
|
||||
eoVRPUtils::getTimeWindow (_newClient, readyTime, dueTime, serviceTime);
|
||||
|
||||
if (_cost > dueTime)
|
||||
return false;
|
||||
|
||||
// If the vehicle arrives before client's ready time, it has
|
||||
// to wait until the client is ready
|
||||
if (_cost < readyTime)
|
||||
_cost = readyTime;
|
||||
|
||||
// Add the service time for the newly inserted client
|
||||
_cost += serviceTime;
|
||||
|
||||
// And the cost of traveling to the next one
|
||||
_cost = _cost + eoVRPUtils::distance (_newClient, _route [i + 1]);
|
||||
|
||||
}
|
||||
else
|
||||
// We simply add the cost of traveling to the next client
|
||||
_cost = _cost + eoVRPUtils::distance (_route [i], _route [i + 1]);
|
||||
|
||||
}
|
||||
|
||||
// Consider the special case where the new client has
|
||||
// to be inserted at the end of the route
|
||||
unsigned last =_route [_route.size () - 1];
|
||||
|
||||
// We first check that the TW of the last client in the old route
|
||||
// has not been exedeed
|
||||
eoVRPUtils::getTimeWindow (last, readyTime, dueTime, serviceTime);
|
||||
|
||||
if (_cost > dueTime)
|
||||
return false;
|
||||
|
||||
// If the vehicle arrives before the client is ready, it waits
|
||||
if (_cost < readyTime)
|
||||
_cost = readyTime;
|
||||
|
||||
// Now we add its service time
|
||||
_cost += serviceTime;
|
||||
|
||||
// And check if the new client has to be inserted at the end
|
||||
// of the old route
|
||||
if (_afterClient == last) {
|
||||
|
||||
// In that case, we add the cost of traveling from the last client
|
||||
// to the one being inserted
|
||||
_cost = _cost + eoVRPUtils::distance (last, _newClient);
|
||||
|
||||
// Check for its TW not being exceeded
|
||||
eoVRPUtils::getTimeWindow (_newClient, readyTime, dueTime, serviceTime);
|
||||
|
||||
if (_cost > dueTime)
|
||||
return false;
|
||||
|
||||
// If the vehicle arrives before the new client is ready, it waits
|
||||
if (_cost < readyTime)
|
||||
_cost = readyTime;
|
||||
|
||||
// Now we add its service time
|
||||
_cost += serviceTime;
|
||||
|
||||
// And, finally, the time to travel back to the depot
|
||||
_cost = _cost + eoVRPUtils::distance (_newClient, 0);
|
||||
|
||||
}
|
||||
else
|
||||
// In this case we just add the cost of traveling back to the depot
|
||||
_cost = _cost + eoVRPUtils::distance (last, 0);
|
||||
|
||||
// Last thing to check is that the vehicle is back on time to the depot
|
||||
eoVRPUtils::getTimeWindow (0, readyTime, dueTime, serviceTime);
|
||||
|
||||
if (_cost > dueTime)
|
||||
return false;
|
||||
|
||||
// If all constraints are satisfied, we return true, and the cost of the
|
||||
// insertion in the variable "_cost"
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Selects the farthest client as seed for a new route.
|
||||
* \param _unvisited Vector of unvisited and thus available clients for constructing the new route.
|
||||
* \param _unvisitedIdx Position of the last univisted client in _unvisited vector.
|
||||
* \return The position of the client farthest from the depot.
|
||||
*/
|
||||
|
||||
unsigned selectFarthestClientAsSeed (const std::vector<int>& _unvisited, int _unvisitedIdx) {
|
||||
|
||||
unsigned maxPos = 0;
|
||||
double maxDist = eoVRPUtils::distance (0, _unvisited [0]);
|
||||
|
||||
for (unsigned i = 1; i <= _unvisitedIdx; i++)
|
||||
if (eoVRPUtils::distance (0, _unvisited [i]) > maxDist) {
|
||||
|
||||
maxPos = i;
|
||||
maxDist = eoVRPUtils::distance (0, _unvisited [i]);
|
||||
|
||||
}
|
||||
|
||||
return maxPos;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Selects the cheapest client as seed for a new route.
|
||||
* \param _unvisited Vector of unvisited and thus available clients for constructing the new route.
|
||||
* \param _unvisitedIdx Position of the last univisted client in _unvisited vector.
|
||||
* \param _seedCheckingOverride If true, it overrides the seed checking mecanism.
|
||||
* \return The position of the cheapest client.
|
||||
*/
|
||||
|
||||
unsigned selectCheapestClient (const std::vector<int>& _unvisited, int _unvisitedIdx, bool _seedCheckingOverride) {
|
||||
|
||||
int cheapestPos = -1;
|
||||
double cheapestCost = 999999999;
|
||||
|
||||
for (unsigned i = 0; i <= _unvisitedIdx; i++) {
|
||||
|
||||
double cost = (-ALFA * eoVRPUtils::distance (0, _unvisited [i]) ) +
|
||||
( BETA * eoVRPUtils::clients [_unvisited [i]].dueTime) +
|
||||
(GAMMA * eoVRPUtils::polarAngle (0, _unvisited [i]) / 360 * eoVRPUtils::distance (0, _unvisited [i]));
|
||||
|
||||
if ((cost < cheapestCost || (cost == cheapestCost && rng.flip ())) &&
|
||||
(!mSeedsUsed [_unvisited [i]] || _seedCheckingOverride ) ) {
|
||||
|
||||
cheapestPos = i;
|
||||
cheapestCost = cost;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return cheapestPos;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Selects the best (the "hardest" one) client as seed for a new route.
|
||||
* \param _unvisited Vector of unvisited and thus available clients for constructing the new route.
|
||||
* \param _unvisitedIdx Position of the last univisted client in _unvisited vector.
|
||||
* \param _seedCheckingOverride If true, it overrides the seed checking mecanism.
|
||||
* \return The position of the best client.
|
||||
*/
|
||||
|
||||
unsigned selectBestClientAsSeed (const std::vector<int>& _unvisited, int _unvisitedIdx, bool _seedCheckingOverride) {
|
||||
|
||||
int cheapestPos = -1;
|
||||
double cheapestCost = 999999999;
|
||||
double alfa, beta;
|
||||
|
||||
alfa = rng.uniform ();
|
||||
beta = rng.uniform ();
|
||||
|
||||
for (unsigned i = 0; i <= _unvisitedIdx; i++) {
|
||||
|
||||
double cost = (alfa * eoVRPUtils::distance (0, _unvisited [i])) +
|
||||
(beta * (eoVRPUtils::clients [_unvisited [i]].dueTime - eoVRPUtils::clients [_unvisited [i]].readyTime));
|
||||
|
||||
|
||||
if ((cost < cheapestCost || (cost == cheapestCost && rng.flip ())) &&
|
||||
(!mSeedsUsed [_unvisited [i]] || _seedCheckingOverride ) ) {
|
||||
|
||||
cheapestPos = i;
|
||||
cheapestCost = cost;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return cheapestPos;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Random initializer.
|
||||
* Initializes a genotype using a random initializer.
|
||||
* @param _gen Generally a genotype that has been default-constructed.
|
||||
* Whatever it contains will be lost.
|
||||
*/
|
||||
|
||||
void RandomInitializationNoCheck (eoVRP& _gen) {
|
||||
|
||||
// Erase any previous contents
|
||||
_gen.clear ();
|
||||
|
||||
// Aux vector to store unvisited clients
|
||||
std::vector<int> unvisited;
|
||||
|
||||
// And an index to point to the last unvisited cutomer
|
||||
int unvisitedIdx = eoVRPUtils::clients.size () - 2;
|
||||
|
||||
// Initialization of the unvisited vector with all the clients
|
||||
for (unsigned i = 1; i < eoVRPUtils::clients.size (); i++)
|
||||
unvisited.push_back (i);
|
||||
|
||||
while (unvisitedIdx >= 0) {
|
||||
|
||||
unsigned n = rng.random (unvisitedIdx);
|
||||
|
||||
for (unsigned i = 0; i <= n; i++) {
|
||||
|
||||
unsigned pos = rng.random (unvisitedIdx);
|
||||
|
||||
_gen.push_back (unvisited [pos]);
|
||||
|
||||
unvisited [pos] = unvisited [unvisitedIdx];
|
||||
unvisitedIdx--;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2007
|
||||
* (C) OPAC Team, LIFL, 2002-2007
|
||||
*
|
||||
* (c) Antonio LaTorre <atorre@fi.upm.es>, 2007
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*
|
||||
* ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
* Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef eoVRPMutation_H
|
||||
#define eoVRPMutation_H
|
||||
|
||||
// General includes
|
||||
#include <algorithm>
|
||||
|
||||
// The base definition of eoMonOp
|
||||
#include <eoOp.h>
|
||||
|
||||
/**
|
||||
* \class eoVRPMutation eoVRPMutation.h
|
||||
* \brief Implementation of variations of the four mutation operators for the VRP-TW defined by Tavares et al.
|
||||
* These four operators should be separated in different classes and their probabilities
|
||||
* made parameterizable.
|
||||
*/
|
||||
|
||||
class eoVRPMutation: public eoMonOp <eoVRP> {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Default constructor: nothing to do here.
|
||||
*/
|
||||
|
||||
eoVRPMutation () {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns a string containing the name of the class. Used to display statistics.
|
||||
* \return The string containing the name of the class.
|
||||
*/
|
||||
|
||||
std::string className () const {
|
||||
|
||||
return "eoVRPMutation";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Functor operator.
|
||||
* Applies one of the four mutation operators available, each of them with a predefined
|
||||
* (hard-coded) probability. These operators should be separated in different classes
|
||||
* and their probabilities made parameterizable to do it in a more "paradisEO" way.
|
||||
* \param _genotype The genotype being mutated (it will be probably modified).
|
||||
* \return True if the individual has been modified. False otherwise.
|
||||
*/
|
||||
|
||||
bool operator () (eoVRP& _genotype) {
|
||||
|
||||
bool res = false;
|
||||
double op = rng.uniform ();
|
||||
|
||||
|
||||
if (op <= 0.05)
|
||||
res = swapMutation (_genotype);
|
||||
else if ((op > 0.05) && (op <= 0.20))
|
||||
res = inversionMutation (_genotype);
|
||||
else if ((op > 0.20) && (op <= 0.25))
|
||||
res = insertionMutation (_genotype);
|
||||
else if ((op > 0.25) && (op <= 0.45))
|
||||
res = DisplacementMutation (_genotype);
|
||||
|
||||
if (res)
|
||||
_genotype.cleanRoutes ();
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/**
|
||||
* \brief It exhanges the positions of two clients within the individual.
|
||||
* Clients may or may not be in the same route.
|
||||
* \param _genotype The genotype being mutated (it will be probably modified).
|
||||
* \return True if the individual has been modified. False otherwise.
|
||||
*/
|
||||
|
||||
bool swapMutation (eoVRP& _genotype) {
|
||||
|
||||
int p1 = rng.random (_genotype.size ());
|
||||
int p2 = -1;
|
||||
|
||||
do {
|
||||
p2 = rng.random (_genotype.size ());
|
||||
} while (_genotype [p2] == _genotype [p1]);
|
||||
|
||||
std::swap (_genotype [p1], _genotype [p2]);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief It selects two positions in the genotype and inverts the clients between them.
|
||||
* Clients may or may not be in the same route.
|
||||
* \param _genotype The genotype being mutated (it will be probably modified).
|
||||
* \return True if the individual has been modified. False otherwise.
|
||||
*/
|
||||
|
||||
bool inversionMutation (eoVRP& _genotype) {
|
||||
|
||||
int p1 = rng.random (_genotype.size ());
|
||||
int p2 = -1;
|
||||
|
||||
do {
|
||||
p2 = rng.random (_genotype.size ());
|
||||
} while (_genotype [p2] == _genotype [p1]);
|
||||
|
||||
if (p1 > p2)
|
||||
std::swap (p1, p2);
|
||||
|
||||
// Reverse the subroute
|
||||
reverse (_genotype.begin () + p1, _genotype.begin () + p2 + 1);
|
||||
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief It selects and individual, erases it from its original position and inserts it somewhere else.
|
||||
* The insertion may or may not be within the same route.
|
||||
* \param _genotype The genotype being mutated (it will be probably modified).
|
||||
* \return True if the individual has been modified. False otherwise.
|
||||
*/
|
||||
|
||||
bool insertionMutation (eoVRP& _genotype) {
|
||||
|
||||
int p = -1;
|
||||
|
||||
// Selection of the client to be moved
|
||||
do {
|
||||
p = rng.random (_genotype.size ());
|
||||
} while (_genotype [p] == -1);
|
||||
|
||||
// Temporary copy of the client
|
||||
unsigned client = _genotype [p];
|
||||
|
||||
_genotype.erase (_genotype.begin () + p);
|
||||
|
||||
p = rng.random (_genotype.size () - 1);
|
||||
_genotype.insert (_genotype.begin () + p, client);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief It selects a set of clients, erases them from their original position and inserts them somewhere else.
|
||||
* The selected set of clients may cover different routes.
|
||||
* \param _genotype The genotype being mutated (it will be probably modified).
|
||||
* \return True if the individual has been modified. False otherwise.
|
||||
*/
|
||||
|
||||
bool DisplacementMutation (eoVRP& _genotype) {
|
||||
|
||||
int p1 = rng.random (_genotype.size ());
|
||||
int p2 = -1;
|
||||
|
||||
do {
|
||||
p2 = rng.random (_genotype.size ());
|
||||
} while (_genotype [p2] == _genotype [p1]);
|
||||
|
||||
if (p1 > p2)
|
||||
std::swap (p1, p2);
|
||||
|
||||
// Temporary copy of the fragment being moved
|
||||
Route route;
|
||||
|
||||
for (unsigned i = p1; i <= p2; i++)
|
||||
route.push_back (_genotype [i]);
|
||||
|
||||
_genotype.erase (_genotype.begin () + p1, _genotype.begin () + p2 + 1);
|
||||
|
||||
unsigned p = rng.random ((_genotype.size () > 0) ? _genotype.size () - 1 : 0);
|
||||
_genotype.insert (_genotype.begin () + p, route.begin (), route.end ());
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2007
|
||||
* (C) OPAC Team, LIFL, 2002-2007
|
||||
*
|
||||
* (c) Antonio LaTorre <atorre@fi.upm.es>, 2007
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*
|
||||
* ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
* Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef eoVRPQuadCrossover_H
|
||||
#define eoVRPQuadCrossover_H
|
||||
|
||||
// General includes
|
||||
#include <assert.h>
|
||||
#include <values.h>
|
||||
#include <utils/eoRNG.h>
|
||||
#include <set>
|
||||
|
||||
// The base definition of eoQuadOp
|
||||
#include <eoOp.h>
|
||||
|
||||
/**
|
||||
* \class eoVRPGenericCrossover eoVRPQuadCrossover.h
|
||||
* \brief Implementation of the generic crossover for the VRP-TW by Tavares et al.
|
||||
*/
|
||||
|
||||
class eoVRPGenericCrossover: public eoQuadOp <eoVRP> {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Deafult constructor.
|
||||
*/
|
||||
|
||||
eoVRPGenericCrossover () {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns a string containing the name of the class. Used to display statistics.
|
||||
* \return The string containing the name of the class.
|
||||
*/
|
||||
|
||||
std::string className () const {
|
||||
|
||||
return "eoVRPGenericCrossover";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Both parameters are the parents and the (future) children of the crossover.
|
||||
* \param _genotype1 The first parent.
|
||||
* \param _genotype2 The second parent.
|
||||
* \return True if any of the parents was modified. False otherwise.
|
||||
*/
|
||||
|
||||
bool operator () (eoVRP& _genotype1, eoVRP& _genotype2) {
|
||||
|
||||
Routes c1 = _genotype1.routes ();
|
||||
Routes c2 = _genotype2.routes ();
|
||||
|
||||
GenericCrossover (_genotype1.routes (), c2);
|
||||
GenericCrossover (_genotype2.routes (), c1);
|
||||
|
||||
_genotype1.encode (c1);
|
||||
_genotype2.encode (c2);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* \brief Actually performs the generic crossover.
|
||||
* \param _donor Set of routes from the first parent.
|
||||
* \param _receiver Set of routes from the second parent
|
||||
* \return True if the second parent was modified. False otherwise.
|
||||
*/
|
||||
|
||||
bool GenericCrossover (const Routes& _donor, Routes& _receiver) const {
|
||||
|
||||
unsigned srcRoute = rng.random (_donor.size ());
|
||||
unsigned srcPos1 = rng.random (_donor [srcRoute].size ());
|
||||
unsigned srcPos2 = rng.random (_donor [srcRoute].size ());
|
||||
|
||||
if (srcPos1 > srcPos2)
|
||||
std::swap (srcPos1, srcPos2);
|
||||
|
||||
Route::iterator it;
|
||||
|
||||
for (unsigned i = srcPos1; i <= srcPos2; i++)
|
||||
for (unsigned j = 0; j < _receiver.size (); j++) {
|
||||
|
||||
it = find (_receiver [j].begin (), _receiver [j].end (), _donor [srcRoute][i]);
|
||||
|
||||
if (it != _receiver [j].end ()) {
|
||||
|
||||
// Deletion of the repeated client
|
||||
_receiver [j].erase (it);
|
||||
|
||||
// Deletion of empty route, if necessary
|
||||
if (_receiver [j].size () == 0)
|
||||
_receiver.erase (_receiver.begin () + j);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unsigned dstRoute = rng.random (_receiver.size ());
|
||||
|
||||
it = _receiver [dstRoute].begin () + rng.random (_receiver [dstRoute].size ());
|
||||
|
||||
_receiver [dstRoute].insert (it + 1, _donor [srcRoute].begin () + srcPos1, _donor [srcRoute].begin () + srcPos2 + 1);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \class eoVRPOnePointCrossover eoVRPQuadCrossover.h
|
||||
* \brief Implementation of the simple One Point Crossover.
|
||||
*/
|
||||
|
||||
class eoVRPOnePointCrossover: public eoQuadOp <eoVRP> {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Deafult constructor.
|
||||
*/
|
||||
|
||||
eoVRPOnePointCrossover () {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns a string containing the name of the class. Used to display statistics.
|
||||
* \return The string containing the name of the class.
|
||||
*/
|
||||
|
||||
std::string className () const {
|
||||
|
||||
return "eoVRPOnePointCrossover";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Performs a one point crossover. Both parameters are the parents and the (future) children of the crossover.
|
||||
* \param _genotype1 The first parent.
|
||||
* \param _genotype2 The second parent.
|
||||
* \return True if any of the parents was modified. False otherwise.
|
||||
*/
|
||||
|
||||
bool operator () (eoVRP& _genotype1, eoVRP& _genotype2) {
|
||||
|
||||
eoVRP& _gen = _genotype1;
|
||||
|
||||
unsigned orig1, orig2, dest;
|
||||
|
||||
// First child
|
||||
orig1 = rng.random (_genotype2.size ());
|
||||
orig2 = rng.random (_genotype2.size ());
|
||||
|
||||
if (orig1 > orig2)
|
||||
std::swap (orig1, orig2);
|
||||
|
||||
for (unsigned i = orig1; i <= orig2; i++)
|
||||
_genotype1.erase (find (_genotype1.begin (), _genotype1.end (), _genotype2 [i]));
|
||||
|
||||
dest = rng.random (_genotype1.size ());
|
||||
|
||||
_genotype1.insert (_genotype1.begin () + dest, _genotype2.begin () + orig1, _genotype2.begin () + orig2 + 1);
|
||||
|
||||
// Second child
|
||||
orig1 = rng.random (_gen.size ());
|
||||
orig2 = rng.random (_gen.size ());
|
||||
|
||||
if (orig1 > orig2)
|
||||
std::swap (orig1, orig2);
|
||||
|
||||
for (unsigned i = orig1; i <= orig2; i++)
|
||||
_genotype2.erase (find (_genotype2.begin (), _genotype2.end (), _gen [i]));
|
||||
|
||||
dest = rng.random (_genotype2.size ());
|
||||
|
||||
_genotype2.insert (_genotype2.begin () + dest, _gen.begin () + orig1, _gen.begin () + orig2 + 1);
|
||||
|
||||
_genotype1.cleanRoutes ();
|
||||
_genotype2.cleanRoutes ();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \class eoVRPEdgeCrossover eoVRPQuadCrossover.h
|
||||
* \brief Implementation of the classic Edge Crossover from the TSP.
|
||||
*/
|
||||
|
||||
class eoVRPEdgeCrossover: public eoQuadOp <eoVRP> {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Deafult constructor.
|
||||
*/
|
||||
|
||||
eoVRPEdgeCrossover () {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns a string containing the name of the class. Used to display statistics.
|
||||
* \return The string containing the name of the class.
|
||||
*/
|
||||
|
||||
std::string className () const {
|
||||
|
||||
return "eoVRPEdgeCrossover";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Both parameters are the parents and the (future) children of the crossover.
|
||||
* \param _genotype1 The first parent.
|
||||
* \param _genotype2 The second parent.
|
||||
* \return True if any of the parents was modified. False otherwise.
|
||||
*/
|
||||
|
||||
bool operator () (eoVRP& _genotype1, eoVRP& _genotype2) {
|
||||
|
||||
eoVRP par [2];
|
||||
|
||||
// Backup of the parents
|
||||
par [0] = _genotype1;
|
||||
par [1] = _genotype2;
|
||||
|
||||
_genotype1.clean ();
|
||||
_genotype2.clean ();
|
||||
|
||||
EdgeCrossover (par [0], par [1], _genotype1);
|
||||
EdgeCrossover (par [0], par [1], _genotype2);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* \brief Actually performs the edge crossover.
|
||||
* \param _genotype1 First parent.
|
||||
* \param _genotype2 Second parent.
|
||||
* \param _child Child.
|
||||
* \return True if the second parent was modified. False otherwise.
|
||||
*/
|
||||
|
||||
bool EdgeCrossover (eoVRP& _genotype1, eoVRP& _genotype2, eoVRP& _child) {
|
||||
|
||||
std::vector <std::set <unsigned> > _map;
|
||||
std::vector <bool> visited;
|
||||
|
||||
// Build map
|
||||
unsigned len = _genotype1.size () ;
|
||||
|
||||
_map.resize (len+1) ;
|
||||
|
||||
for (unsigned i = 0 ; i < len ; i ++) {
|
||||
|
||||
_map [_genotype1 [i]].insert (_genotype1 [(i + 1) % len]) ;
|
||||
_map [_genotype2 [i]].insert (_genotype2 [(i + 1) % len]) ;
|
||||
_map [_genotype1 [i]].insert (_genotype1 [(i - 1 + len) % len]) ;
|
||||
_map [_genotype2 [i]].insert (_genotype2 [(i - 1 + len) % len]) ;
|
||||
|
||||
}
|
||||
|
||||
visited.clear () ;
|
||||
visited.resize (len+1, false) ;
|
||||
|
||||
|
||||
_child.clear () ;
|
||||
|
||||
unsigned cur_vertex = rng.random (len)+1;
|
||||
|
||||
add_vertex (cur_vertex, visited, _map, _child);
|
||||
|
||||
for (unsigned i = 1; i < len; i ++) {
|
||||
|
||||
unsigned len_min_entry = MAXINT;
|
||||
|
||||
std::set <unsigned>& neigh = _map [cur_vertex];
|
||||
|
||||
for (std::set <unsigned>::iterator it = neigh.begin (); it != neigh.end (); it ++) {
|
||||
|
||||
unsigned l = _map [*it].size ();
|
||||
|
||||
if (len_min_entry > l)
|
||||
len_min_entry = l;
|
||||
|
||||
}
|
||||
|
||||
std::vector <unsigned> cand; /* Candidates */
|
||||
|
||||
for (std::set <unsigned>::iterator it = neigh.begin (); it != neigh.end (); it ++) {
|
||||
|
||||
unsigned l = _map [*it].size ();
|
||||
|
||||
if (len_min_entry == l)
|
||||
cand.push_back (*it);
|
||||
|
||||
}
|
||||
|
||||
if (!cand.size ()) {
|
||||
|
||||
/* Oh no ! Implicit mutation */
|
||||
for (unsigned j = 1; j <= len; j ++)
|
||||
if (!visited [j])
|
||||
cand.push_back (j);
|
||||
|
||||
}
|
||||
|
||||
cur_vertex = cand [rng.random (cand.size ())] ;
|
||||
|
||||
add_vertex (cur_vertex, visited, _map, _child);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Removes a vertex from all his neighbours.
|
||||
* \param _vertex The vertex being erased.
|
||||
* \param _map The structure containing the neighbourhood relationship.
|
||||
*/
|
||||
|
||||
void remove_entry (unsigned _vertex, std::vector <std::set <unsigned> >& _map) {
|
||||
|
||||
std::set <unsigned>& neigh = _map [_vertex];
|
||||
|
||||
for (std::set <unsigned>::iterator it = neigh.begin (); it != neigh.end (); it++)
|
||||
_map [*it].erase (_vertex);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Adds a vertex to a child and erases it from the list of available vertices.
|
||||
* \param _vertex The vertex being added to the child.
|
||||
* \param _visited The vector of visited vertices.
|
||||
* \param _map The structure containing the neighbourhood relationship.
|
||||
* \param _child The child where we add the vertex.
|
||||
*/
|
||||
|
||||
void add_vertex (unsigned _vertex, std::vector <bool>& _visited, std::vector <std::set <unsigned> >& _map, eoVRP& _child) {
|
||||
|
||||
_visited [_vertex] = true;
|
||||
_child.push_back (_vertex);
|
||||
remove_entry (_vertex, _map);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2007
|
||||
* (C) OPAC Team, LIFL, 2002-2007
|
||||
*
|
||||
* (c) Antonio LaTorre <atorre@fi.upm.es>, 2007
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*
|
||||
* ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
* Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _eoVRPStat_h
|
||||
#define _eoVRPStat_h
|
||||
|
||||
// The base definition of eoInit
|
||||
#include <utils/eoStat.h>
|
||||
|
||||
/**
|
||||
* \class eoVRPStat eoVRPStat.h
|
||||
* \brief Manages the statistics of the VRP problem.
|
||||
*/
|
||||
|
||||
class eoVRPStat : public eoStat<eoVRP, double> {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Constructor: initializes variables properly.
|
||||
* \param _description A string identifying the class.
|
||||
*/
|
||||
|
||||
eoVRPStat (std::string _description = "eoVRPStat ") : eoStat<eoVRP, double> (0.0, _description) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Gets statistics from a population.
|
||||
* \param _pop The population that will be analyzed.
|
||||
*/
|
||||
|
||||
void operator() (const eoPop<eoVRP>& _pop) {
|
||||
|
||||
double tmpStat (0.);
|
||||
eoStat<eoVRP, double>::value () = tmpStat;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns a string containing the name of the class. Used to display statistics.
|
||||
* \return The string containing the name of the class.
|
||||
*/
|
||||
|
||||
virtual std::string className (void) const {
|
||||
|
||||
return "eoVRPStat";
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
294
contribution/trunk/combinatorial/routing/vrptw/src/eoVRPUtils.h
Normal file
294
contribution/trunk/combinatorial/routing/vrptw/src/eoVRPUtils.h
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2007
|
||||
* (C) OPAC Team, LIFL, 2002-2007
|
||||
*
|
||||
* (c) Antonio LaTorre <atorre@fi.upm.es>, 2007
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*
|
||||
* ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
* Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef eoVRPUtils_h
|
||||
#define eoVRPUtils_h
|
||||
|
||||
// General includes
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
* \def PI
|
||||
* Guess you know what this constant represents.
|
||||
*/
|
||||
|
||||
#define PI 3.14159265
|
||||
|
||||
/**
|
||||
* \def VEHICLE_CAPACITY
|
||||
* Hard-coded parameter for the capacity of the vehicles. This
|
||||
* should be parametrized in a config file in a future version.
|
||||
*/
|
||||
|
||||
#define VEHICLE_CAPACITY 200
|
||||
|
||||
|
||||
typedef std::vector<int> Route;
|
||||
typedef std::vector< Route > Routes;
|
||||
|
||||
|
||||
/**
|
||||
* \namespace eoVRPUtils
|
||||
* \brief A set of structures and utility functions for the VRP-TW problem.
|
||||
*/
|
||||
|
||||
namespace eoVRPUtils {
|
||||
|
||||
/**
|
||||
* \var typedef struct ClientData ClientDataT.
|
||||
* \brief Renaming of struct ClientData.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \struct ClientData
|
||||
* \brief Information regarding each client in the dataset.
|
||||
* This structure is intended to be used to store the information of each
|
||||
* client read from the data file.
|
||||
*/
|
||||
|
||||
typedef struct ClientData {
|
||||
|
||||
unsigned id; /**< Client ID number. */
|
||||
double x; /**< Client's 'x' position in the map. */
|
||||
double y; /**< Client's 'y' position in the map. */
|
||||
double demand; /**< Client's demand of delivered product. */
|
||||
double readyTime; /**< Client's beginning of the time window. */
|
||||
double dueTime; /**< Client's end of the time window. */
|
||||
double serviceTime; /**< Client's service time (time needed to serve the product). */
|
||||
|
||||
} ClientDataT;
|
||||
|
||||
|
||||
static std::vector <ClientDataT> clients; /**< Vector to store clients's information. */
|
||||
static std::vector <std::vector <double> > dist; /**< Distance matrix. */
|
||||
|
||||
|
||||
/**
|
||||
* \brief Computes the distance between two clients.
|
||||
* The computed distances will be stored in dist.
|
||||
*/
|
||||
|
||||
void computeDistances () {
|
||||
|
||||
unsigned numClients = clients.size ();
|
||||
|
||||
dist.resize (numClients) ;
|
||||
|
||||
for (unsigned i = 0; i < dist.size (); i ++)
|
||||
dist [i].resize (numClients);
|
||||
|
||||
// Distances computation
|
||||
for (unsigned i = 0; i < dist.size (); i ++)
|
||||
for (unsigned j = i + 1 ; j < dist.size (); j ++) {
|
||||
|
||||
double distX = clients [i].x - clients [j].x;
|
||||
double distY = clients [i].y - clients [j].y;
|
||||
|
||||
dist [i][j] = dist [j][i] = sqrt (distX * distX + distY * distY);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns the time window information of a given client.
|
||||
* \param _client The client whose information we want to know.
|
||||
* \param _readyTime Return value. The beginning of the client's time window.
|
||||
* \param _dueTime Return value. The end of the client's time window.
|
||||
* \param _serviceTime Return value. The client's service time.
|
||||
*/
|
||||
|
||||
void getTimeWindow (unsigned _client, double& _readyTime, double& _dueTime, double& _serviceTime) {
|
||||
|
||||
assert (_client >= 0 && _client < clients.size ());
|
||||
|
||||
_readyTime = clients [_client].readyTime;
|
||||
_dueTime = clients [_client].dueTime;
|
||||
_serviceTime = clients [_client].serviceTime;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief A function to get the distance between two clients.
|
||||
* \param _from The first client.
|
||||
* \param _to The second client.
|
||||
* \return The distance between _from and _to.
|
||||
*/
|
||||
|
||||
float distance (unsigned _from, unsigned _to) {
|
||||
|
||||
assert (_from >= 0 && _from < clients.size ());
|
||||
assert (_to >= 0 && _to < clients.size ());
|
||||
|
||||
return dist [_from][_to];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Computes de polar angle between clients.
|
||||
* \param _from The first client.
|
||||
* \param _to The second client.
|
||||
* \return The polar angle between _from and _to.
|
||||
*/
|
||||
|
||||
float polarAngle (unsigned _from, unsigned _to) {
|
||||
|
||||
assert (_from >= 0 && _from < clients.size ());
|
||||
assert (_to >= 0 && _to < clients.size ());
|
||||
|
||||
double angle = atan2 (clients [_from].y - clients [_to].y,
|
||||
clients [_from].x - clients [_to].x);
|
||||
|
||||
// To convert it from radians to degrees
|
||||
angle *= 180 / PI;
|
||||
|
||||
if (angle < 0)
|
||||
angle *= -1;
|
||||
|
||||
return angle;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Loads the problem data from a given file.
|
||||
* \param _fileName The file to load data from.
|
||||
* \warning No error check is performed!
|
||||
*/
|
||||
|
||||
void load (const char* _fileName) {
|
||||
|
||||
std::ifstream f (_fileName);
|
||||
|
||||
if (f) {
|
||||
|
||||
while (!f.eof ()) {
|
||||
|
||||
ClientDataT client;
|
||||
|
||||
f >> client.id;
|
||||
f >> client.x;
|
||||
f >> client.y;
|
||||
f >> client.demand;
|
||||
f >> client.readyTime;
|
||||
f >> client.dueTime;
|
||||
f >> client.serviceTime;
|
||||
|
||||
clients.push_back (client);
|
||||
|
||||
}
|
||||
|
||||
f.close ();
|
||||
|
||||
computeDistances ();
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
std::cerr << "Error: the file: " << _fileName << " doesn't exist !!!" << std::endl ;
|
||||
exit (1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Prints a route to the standard output.
|
||||
* \param _route The route to print.
|
||||
*/
|
||||
|
||||
void printRoute (const Route& _route) {
|
||||
|
||||
std::cout << "[";
|
||||
|
||||
for (unsigned i = 0; i < _route.size (); i++) {
|
||||
|
||||
std::cout << _route [i];
|
||||
|
||||
if (i != _route.size () -1)
|
||||
std::cout << ", ";
|
||||
|
||||
}
|
||||
|
||||
std::cout << "]";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Prints a set of routes to the standard output.
|
||||
* \param _routes The set of routes to print.
|
||||
*/
|
||||
|
||||
void printRoutes (Routes& _routes) {
|
||||
|
||||
std::cout << "[";
|
||||
|
||||
for (unsigned i = 0; i < _routes.size (); i++) {
|
||||
|
||||
std::cout << "[";
|
||||
|
||||
for (unsigned j = 0; j < _routes [i].size (); j++) {
|
||||
|
||||
std::cout << _routes [i][j];
|
||||
|
||||
if (j != _routes [i].size () -1)
|
||||
std::cout << ", ";
|
||||
|
||||
}
|
||||
|
||||
if (i == _routes.size () -1)
|
||||
std::cout << "]";
|
||||
else
|
||||
std::cout << "]," << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "]";
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
59
contribution/trunk/combinatorial/routing/vrptw/src/index.h
Normal file
59
contribution/trunk/combinatorial/routing/vrptw/src/index.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/** @mainpage Welcome to PARADISEO - CVRP-TW contribution
|
||||
|
||||
@section Introduction
|
||||
|
||||
The capacitated vehicle routing problem with time windows or CVRP-TW is a combinatorial
|
||||
optimization problem seeking to service a number of customers with a fleet of vehicles
|
||||
where the vehicles have a mimited capacity and the delivery locations have time windows
|
||||
within which the deliveries (or visits) must be made. Often the context is that of
|
||||
delivering goods located at a central depot to customers who have placed orders for such
|
||||
goods. Implicit is the goal of minimizing the cost of distributing the goods. Finding the
|
||||
global minimum for the cost function, except for the smallest instances, is
|
||||
computationally complex.
|
||||
|
||||
@section authors AUTHORS
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>Dolphin project-team INRIA Futurs, 2007.</TD>
|
||||
<TD>Antonio LaTorre atorre[at]fi.upm.es</TD>
|
||||
<TD>Thomas Legrand paradiseo-help[at]lists.gforge.inria.fr</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
@section LICENSE
|
||||
|
||||
This software is governed by the CeCILL license under French law and
|
||||
abiding by the rules of distribution of free software. You can use,
|
||||
modify and/ or redistribute the software under the terms of the CeCILL
|
||||
license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
"http://www.cecill.info".
|
||||
|
||||
As a counterpart to the access to the source code and rights to copy,
|
||||
modify and redistribute granted by the license, users are provided only
|
||||
with a limited warranty and the software's author, the holder of the
|
||||
economic rights, and the successive licensors have only limited liability.
|
||||
|
||||
In this respect, the user's attention is drawn to the risks associated
|
||||
with loading, using, modifying and/or developing or reproducing the
|
||||
software by the user in light of its specific status of free software,
|
||||
that may mean that it is complicated to manipulate, and that also
|
||||
therefore means that it is reserved for developers and experienced
|
||||
professionals having in-depth computer knowledge. Users are therefore
|
||||
encouraged to load and test the software's suitability as regards their
|
||||
requirements in conditions enabling the security of their systems and/or
|
||||
data to be ensured and, more generally, to use and operate it in the
|
||||
same conditions as regards security.
|
||||
The fact that you are presently reading this means that you have had
|
||||
knowledge of the CeCILL license and that you accept its terms.
|
||||
|
||||
ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
|
||||
|
||||
@section Paradiseo Home Page
|
||||
|
||||
<A href=http://paradiseo.gforge.inria.fr>http://paradiseo.gforge.inria.fr</A>
|
||||
|
||||
*/
|
||||
Loading…
Add table
Add a link
Reference in a new issue