New style for MOEO
git-svn-id: svn://scm.gforge.inria.fr/svnroot/paradiseo@788 331e1502-861f-0410-8da2-ba01fb791d7f
This commit is contained in:
parent
7161febf9c
commit
39709d3d12
103 changed files with 2607 additions and 2521 deletions
|
|
@ -41,6 +41,7 @@
|
||||||
/**
|
/**
|
||||||
* Abstract class for multi-objective algorithms.
|
* Abstract class for multi-objective algorithms.
|
||||||
*/
|
*/
|
||||||
class moeoAlgo {};
|
class moeoAlgo
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOALGO_H_*/
|
#endif /*MOEOALGO_H_*/
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
* Abstract class for multi-objective evolutionary algorithms.
|
* Abstract class for multi-objective evolutionary algorithms.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoEA : public moeoAlgo, public eoAlgo < MOEOT > {};
|
class moeoEA : public moeoAlgo, public eoAlgo < MOEOT >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOEA_H_*/
|
#endif /*MOEOEA_H_*/
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,8 @@ public:
|
||||||
s.append( " in moeoEasyEA");
|
s.append( " in moeoEasyEA");
|
||||||
throw std::runtime_error( s );
|
throw std::runtime_error( s );
|
||||||
}
|
}
|
||||||
} while (continuator(_pop));
|
}
|
||||||
|
while (continuator(_pop));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -223,16 +224,28 @@ protected:
|
||||||
bool evalFitAndDivBeforeSelection;
|
bool evalFitAndDivBeforeSelection;
|
||||||
/** a dummy eval */
|
/** a dummy eval */
|
||||||
class eoDummyEval : public eoEvalFunc < MOEOT >
|
class eoDummyEval : public eoEvalFunc < MOEOT >
|
||||||
{ public: /** the dummy functor */
|
{
|
||||||
void operator()(MOEOT &) {}} dummyEval;
|
public: /** the dummy functor */
|
||||||
|
void operator()(MOEOT &)
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
dummyEval;
|
||||||
/** a dummy select */
|
/** a dummy select */
|
||||||
class eoDummySelect : public eoSelect < MOEOT >
|
class eoDummySelect : public eoSelect < MOEOT >
|
||||||
{ public: /** the dummy functor */
|
{
|
||||||
void operator()(const eoPop < MOEOT > &, eoPop < MOEOT > &) {} } dummySelect;
|
public: /** the dummy functor */
|
||||||
|
void operator()(const eoPop < MOEOT > &, eoPop < MOEOT > &)
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
dummySelect;
|
||||||
/** a dummy transform */
|
/** a dummy transform */
|
||||||
class eoDummyTransform : public eoTransform < MOEOT >
|
class eoDummyTransform : public eoTransform < MOEOT >
|
||||||
{ public: /** the dummy functor */
|
{
|
||||||
void operator()(eoPop < MOEOT > &) {} } dummyTransform;
|
public: /** the dummy functor */
|
||||||
|
void operator()(eoPop < MOEOT > &)
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
dummyTransform;
|
||||||
/** a dummy merge */
|
/** a dummy merge */
|
||||||
eoNoElitism < MOEOT > dummyMerge;
|
eoNoElitism < MOEOT > dummyMerge;
|
||||||
/** a dummy reduce */
|
/** a dummy reduce */
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,8 @@ public:
|
||||||
popEval (_pop, offspring);
|
popEval (_pop, offspring);
|
||||||
// after replace, the new pop is in _pop. Worths are recalculated if necessary
|
// after replace, the new pop is in _pop. Worths are recalculated if necessary
|
||||||
replace (_pop, offspring);
|
replace (_pop, offspring);
|
||||||
} while (continuator (_pop));
|
}
|
||||||
|
while (continuator (_pop));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,8 @@ public:
|
||||||
previousArchive.update(archive);
|
previousArchive.update(archive);
|
||||||
oneStep(_pop);
|
oneStep(_pop);
|
||||||
archive.update(_pop);
|
archive.update(_pop);
|
||||||
} while ( (! archive.equals(previousArchive)) && (continuator(_arch)) );
|
}
|
||||||
|
while ( (! archive.equals(previousArchive)) && (continuator(_arch)) );
|
||||||
_arch.update(archive);
|
_arch.update(archive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
* Starting from a Type (i.e.: an individual, a pop, an archive...), it produces a set of new non-dominated solutions.
|
* Starting from a Type (i.e.: an individual, a pop, an archive...), it produces a set of new non-dominated solutions.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT, class Type >
|
template < class MOEOT, class Type >
|
||||||
class moeoLS: public moeoAlgo, public eoBF < Type, moeoArchive < MOEOT > &, void > {};
|
class moeoLS: public moeoAlgo, public eoBF < Type, moeoArchive < MOEOT > &, void >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOLS_H_*/
|
#endif /*MOEOLS_H_*/
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,8 @@ public:
|
||||||
popEval (_pop, offspring);
|
popEval (_pop, offspring);
|
||||||
// after replace, the new pop is in _pop. Worths are recalculated if necessary
|
// after replace, the new pop is in _pop. Worths are recalculated if necessary
|
||||||
replace (_pop, offspring);
|
replace (_pop, offspring);
|
||||||
} while (continuator (_pop));
|
}
|
||||||
|
while (continuator (_pop));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,8 @@ public:
|
||||||
popEval (_pop, offspring);
|
popEval (_pop, offspring);
|
||||||
// after replace, the new pop is in _pop. Worths are recalculated if necessary
|
// after replace, the new pop is in _pop. Worths are recalculated if necessary
|
||||||
replace (_pop, offspring);
|
replace (_pop, offspring);
|
||||||
} while (continuator (_pop));
|
}
|
||||||
|
while (continuator (_pop));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
* Functor allowing to compare two solutions.
|
* Functor allowing to compare two solutions.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoComparator : public eoBF < const MOEOT &, const MOEOT &, const bool > {};
|
class moeoComparator : public eoBF < const MOEOT &, const MOEOT &, const bool >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOCOMPARATOR_H_*/
|
#endif /*MOEOCOMPARATOR_H_*/
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
* The template argument ObjectiveVector have to be a moeoObjectiveVector.
|
* The template argument ObjectiveVector have to be a moeoObjectiveVector.
|
||||||
*/
|
*/
|
||||||
template < class ObjectiveVector >
|
template < class ObjectiveVector >
|
||||||
class moeoObjectiveVectorComparator : public eoBF < const ObjectiveVector &, const ObjectiveVector &, const bool > {};
|
class moeoObjectiveVectorComparator : public eoBF < const ObjectiveVector &, const ObjectiveVector &, const bool >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOOBJECTIVEVECTORCOMPARATOR_H_*/
|
#endif /*MOEOOBJECTIVEVECTORCOMPARATOR_H_*/
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* Virtual dtor
|
* Virtual dtor
|
||||||
*/
|
*/
|
||||||
virtual ~MOEO() {};
|
virtual ~MOEO()
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
* Functor that evaluates one MOEO by setting all its objective values.
|
* Functor that evaluates one MOEO by setting all its objective values.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoEvalFunc : public eoEvalFunc< MOEOT > {};
|
class moeoEvalFunc : public eoEvalFunc< MOEOT >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOEVALFUNC_H_*/
|
#endif /*MOEOEVALFUNC_H_*/
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,8 @@ public:
|
||||||
static void setup(unsigned int _nObjectives, std::vector < bool > & _bObjectives)
|
static void setup(unsigned int _nObjectives, std::vector < bool > & _bObjectives)
|
||||||
{
|
{
|
||||||
// in case the number of objectives was already set to a different value
|
// in case the number of objectives was already set to a different value
|
||||||
if ( nObj && (nObj != _nObjectives) ) {
|
if ( nObj && (nObj != _nObjectives) )
|
||||||
|
{
|
||||||
std::cout << "WARNING\n";
|
std::cout << "WARNING\n";
|
||||||
std::cout << "WARNING : the number of objectives are changing\n";
|
std::cout << "WARNING : the number of objectives are changing\n";
|
||||||
std::cout << "WARNING : Make sure all existing objects are destroyed\n";
|
std::cout << "WARNING : Make sure all existing objects are destroyed\n";
|
||||||
|
|
@ -102,7 +103,8 @@ public:
|
||||||
* Returns true if the _ith objective have to be maximized
|
* Returns true if the _ith objective have to be maximized
|
||||||
* @param _i the index
|
* @param _i the index
|
||||||
*/
|
*/
|
||||||
static bool maximizing(unsigned int _i) {
|
static bool maximizing(unsigned int _i)
|
||||||
|
{
|
||||||
return (! minimizing(_i));
|
return (! minimizing(_i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,8 @@ moeoLS < MOEOT, eoPop<MOEOT> & > & do_make_ls_moeo (
|
||||||
moeoLS < MOEOT, eoPop<MOEOT> & > * ls;
|
moeoLS < MOEOT, eoPop<MOEOT> & > * ls;
|
||||||
if (lsParam == std::string("IBMOLS"))
|
if (lsParam == std::string("IBMOLS"))
|
||||||
{
|
{
|
||||||
ls = new moeoIBMOLS < MOEOT, Move > (_moveInit, _nextMove, _eval, _moveIncrEval, *fitnessAssignment, _continue);;
|
ls = new moeoIBMOLS < MOEOT, Move > (_moveInit, _nextMove, _eval, _moveIncrEval, *fitnessAssignment, _continue);
|
||||||
|
;
|
||||||
}
|
}
|
||||||
else if (lsParam == std::string("I-IBMOLS"))
|
else if (lsParam == std::string("I-IBMOLS"))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
* moeoCriterionBasedFitnessAssignment is a moeoFitnessAssignment for criterion-based strategies.
|
* moeoCriterionBasedFitnessAssignment is a moeoFitnessAssignment for criterion-based strategies.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoCriterionBasedFitnessAssignment : public moeoFitnessAssignment < MOEOT > {};
|
class moeoCriterionBasedFitnessAssignment : public moeoFitnessAssignment < MOEOT >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOCRITERIONBASEDFITNESSASSIGNMENT_H_*/
|
#endif /*MOEOCRITERIONBASEDFITNESSASSIGNMENT_H_*/
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,8 @@ private:
|
||||||
private:
|
private:
|
||||||
/** the corresponding comparator for objective vectors */
|
/** the corresponding comparator for objective vectors */
|
||||||
moeoObjectiveObjectiveVectorComparator < ObjectiveVector > cmp;
|
moeoObjectiveObjectiveVectorComparator < ObjectiveVector > cmp;
|
||||||
} objComparator;
|
}
|
||||||
|
objComparator;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
* moeoIndicatorBasedFitnessAssignment is a moeoFitnessAssignment for Indicator-based strategies.
|
* moeoIndicatorBasedFitnessAssignment is a moeoFitnessAssignment for Indicator-based strategies.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoIndicatorBasedFitnessAssignment : public moeoFitnessAssignment < MOEOT > {};
|
class moeoIndicatorBasedFitnessAssignment : public moeoFitnessAssignment < MOEOT >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOINDICATORBASEDFITNESSASSIGNMENT_H_*/
|
#endif /*MOEOINDICATORBASEDFITNESSASSIGNMENT_H_*/
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
* moeoParetoBasedFitnessAssignment is a moeoFitnessAssignment for Pareto-based strategies.
|
* moeoParetoBasedFitnessAssignment is a moeoFitnessAssignment for Pareto-based strategies.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoParetoBasedFitnessAssignment : public moeoFitnessAssignment < MOEOT > {};
|
class moeoParetoBasedFitnessAssignment : public moeoFitnessAssignment < MOEOT >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOPARETOBASEDFITNESSASSIGNMENT_H_*/
|
#endif /*MOEOPARETOBASEDFITNESSASSIGNMENT_H_*/
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
* moeoScalarFitnessAssignment is a moeoFitnessAssignment for scalar strategies.
|
* moeoScalarFitnessAssignment is a moeoFitnessAssignment for scalar strategies.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoScalarFitnessAssignment : public moeoFitnessAssignment < MOEOT > {};
|
class moeoScalarFitnessAssignment : public moeoFitnessAssignment < MOEOT >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOSCALARFITNESSASSIGNMENT_H_*/
|
#endif /*MOEOSCALARFITNESSASSIGNMENT_H_*/
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
* moeoIndicatorBasedFitnessAssignment for unary indicators.
|
* moeoIndicatorBasedFitnessAssignment for unary indicators.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoUnaryIndicatorBasedFitnessAssignment : public moeoIndicatorBasedFitnessAssignment < MOEOT > {};
|
class moeoUnaryIndicatorBasedFitnessAssignment : public moeoIndicatorBasedFitnessAssignment < MOEOT >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOINDICATORBASEDFITNESSASSIGNMENT_H_*/
|
#endif /*MOEOINDICATORBASEDFITNESSASSIGNMENT_H_*/
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,8 @@ public:
|
||||||
* @param _set1 the first Pareto set
|
* @param _set1 the first Pareto set
|
||||||
* @param _set2 the second Pareto set
|
* @param _set2 the second Pareto set
|
||||||
*/
|
*/
|
||||||
double operator()(const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2) {
|
double operator()(const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2)
|
||||||
|
{
|
||||||
unsigned int c = card_C(_set1, _set2);
|
unsigned int c = card_C(_set1, _set2);
|
||||||
unsigned int w1 = card_W(_set1, _set2);
|
unsigned int w1 = card_W(_set1, _set2);
|
||||||
unsigned int n1 = card_N(_set1, _set2);
|
unsigned int n1 = card_N(_set1, _set2);
|
||||||
|
|
@ -76,11 +77,13 @@ private:
|
||||||
* @param _set1 the first Pareto set
|
* @param _set1 the first Pareto set
|
||||||
* @param _set2 the second Pareto set
|
* @param _set2 the second Pareto set
|
||||||
*/
|
*/
|
||||||
unsigned int card_C (const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2) {
|
unsigned int card_C (const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2)
|
||||||
|
{
|
||||||
unsigned int c=0;
|
unsigned int c=0;
|
||||||
for (unsigned int i=0; i<_set1.size(); i++)
|
for (unsigned int i=0; i<_set1.size(); i++)
|
||||||
for (unsigned int j=0; j<_set2.size(); j++)
|
for (unsigned int j=0; j<_set2.size(); j++)
|
||||||
if (_set1[i] == _set2[j]) {
|
if (_set1[i] == _set2[j])
|
||||||
|
{
|
||||||
c++;
|
c++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -93,7 +96,8 @@ private:
|
||||||
* @param _set1 the first Pareto set
|
* @param _set1 the first Pareto set
|
||||||
* @param _set2 the second Pareto set
|
* @param _set2 the second Pareto set
|
||||||
*/
|
*/
|
||||||
unsigned int card_W (const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2) {
|
unsigned int card_W (const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2)
|
||||||
|
{
|
||||||
unsigned int w=0;
|
unsigned int w=0;
|
||||||
for (unsigned int i=0; i<_set1.size(); i++)
|
for (unsigned int i=0; i<_set1.size(); i++)
|
||||||
for (unsigned int j=0; j<_set2.size(); j++)
|
for (unsigned int j=0; j<_set2.size(); j++)
|
||||||
|
|
@ -111,9 +115,11 @@ private:
|
||||||
* @param _set1 the first Pareto set
|
* @param _set1 the first Pareto set
|
||||||
* @param _set2 the second Pareto set
|
* @param _set2 the second Pareto set
|
||||||
*/
|
*/
|
||||||
unsigned int card_N (const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2) {
|
unsigned int card_N (const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2)
|
||||||
|
{
|
||||||
unsigned int n=0;
|
unsigned int n=0;
|
||||||
for (unsigned int i=0; i<_set1.size(); i++) {
|
for (unsigned int i=0; i<_set1.size(); i++)
|
||||||
|
{
|
||||||
bool domin_rel = false;
|
bool domin_rel = false;
|
||||||
for (unsigned int j=0; j<_set2.size(); j++)
|
for (unsigned int j=0; j<_set2.size(); j++)
|
||||||
if ( (paretoComparator(_set2[j], _set1[i])) || (paretoComparator(_set1[i], _set2[j])) )
|
if ( (paretoComparator(_set2[j], _set1[i])) || (paretoComparator(_set1[i], _set2[j])) )
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,8 @@ public:
|
||||||
* @param _set1 the first Pareto set
|
* @param _set1 the first Pareto set
|
||||||
* @param _set2 the second Pareto set
|
* @param _set2 the second Pareto set
|
||||||
*/
|
*/
|
||||||
double operator()(const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2) {
|
double operator()(const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2)
|
||||||
|
{
|
||||||
// normalization
|
// normalization
|
||||||
std::vector< ObjectiveVector > set1 = _set1;
|
std::vector< ObjectiveVector > set1 = _set1;
|
||||||
std::vector< ObjectiveVector > set2= _set2;
|
std::vector< ObjectiveVector > set2= _set2;
|
||||||
|
|
@ -79,10 +80,12 @@ public:
|
||||||
float omega=0;
|
float omega=0;
|
||||||
float entropy=0;
|
float entropy=0;
|
||||||
|
|
||||||
for (unsigned int i=0 ; i<C ; i++) {
|
for (unsigned int i=0 ; i<C ; i++)
|
||||||
|
{
|
||||||
unsigned int N_i = howManyInNicheOf (union_set1_star, union_set1_star[i], star.size());
|
unsigned int N_i = howManyInNicheOf (union_set1_star, union_set1_star[i], star.size());
|
||||||
unsigned int n_i = howManyInNicheOf (set1, union_set1_star[i], star.size());
|
unsigned int n_i = howManyInNicheOf (set1, union_set1_star[i], star.size());
|
||||||
if (n_i > 0) {
|
if (n_i > 0)
|
||||||
|
{
|
||||||
omega += 1.0 / N_i;
|
omega += 1.0 / N_i;
|
||||||
entropy += (float) n_i / (N_i * C) * log (((float) n_i / C) / log (2.0));
|
entropy += (float) n_i / (N_i * C) * log (((float) n_i / C) / log (2.0));
|
||||||
}
|
}
|
||||||
|
|
@ -107,8 +110,10 @@ private:
|
||||||
* Removes the dominated individuals contained in _f
|
* Removes the dominated individuals contained in _f
|
||||||
* @param _f a Pareto set
|
* @param _f a Pareto set
|
||||||
*/
|
*/
|
||||||
void removeDominated(std::vector < ObjectiveVector > & _f) {
|
void removeDominated(std::vector < ObjectiveVector > & _f)
|
||||||
for (unsigned int i=0 ; i<_f.size(); i++) {
|
{
|
||||||
|
for (unsigned int i=0 ; i<_f.size(); i++)
|
||||||
|
{
|
||||||
bool dom = false;
|
bool dom = false;
|
||||||
for (unsigned int j=0; j<_f.size(); j++)
|
for (unsigned int j=0; j<_f.size(); j++)
|
||||||
if (i != j && paretoComparator(_f[i],_f[j]))
|
if (i != j && paretoComparator(_f[i],_f[j]))
|
||||||
|
|
@ -116,7 +121,8 @@ private:
|
||||||
dom = true;
|
dom = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (dom) {
|
if (dom)
|
||||||
|
{
|
||||||
_f[i] = _f.back();
|
_f[i] = _f.back();
|
||||||
_f.pop_back();
|
_f.pop_back();
|
||||||
i--;
|
i--;
|
||||||
|
|
@ -129,13 +135,16 @@ private:
|
||||||
* Prenormalization
|
* Prenormalization
|
||||||
* @param _f a Pareto set
|
* @param _f a Pareto set
|
||||||
*/
|
*/
|
||||||
void prenormalize (const std::vector< ObjectiveVector > & _f) {
|
void prenormalize (const std::vector< ObjectiveVector > & _f)
|
||||||
|
{
|
||||||
vect_min_val.clear();
|
vect_min_val.clear();
|
||||||
vect_max_val.clear();
|
vect_max_val.clear();
|
||||||
|
|
||||||
for (unsigned int i=0 ; i<ObjectiveVector::nObjectives(); i++) {
|
for (unsigned int i=0 ; i<ObjectiveVector::nObjectives(); i++)
|
||||||
|
{
|
||||||
float min_val = _f.front()[i], max_val = min_val;
|
float min_val = _f.front()[i], max_val = min_val;
|
||||||
for (unsigned int j=1 ; j<_f.size(); j++) {
|
for (unsigned int j=1 ; j<_f.size(); j++)
|
||||||
|
{
|
||||||
if (_f[j][i] < min_val)
|
if (_f[j][i] < min_val)
|
||||||
min_val = _f[j][i];
|
min_val = _f[j][i];
|
||||||
if (_f[j][i]>max_val)
|
if (_f[j][i]>max_val)
|
||||||
|
|
@ -151,7 +160,8 @@ private:
|
||||||
* Normalization
|
* Normalization
|
||||||
* @param _f a Pareto set
|
* @param _f a Pareto set
|
||||||
*/
|
*/
|
||||||
void normalize (std::vector< ObjectiveVector > & _f) {
|
void normalize (std::vector< ObjectiveVector > & _f)
|
||||||
|
{
|
||||||
for (unsigned int i=0 ; i<ObjectiveVector::nObjectives(); i++)
|
for (unsigned int i=0 ; i<ObjectiveVector::nObjectives(); i++)
|
||||||
for (unsigned int j=0; j<_f.size(); j++)
|
for (unsigned int j=0; j<_f.size(); j++)
|
||||||
_f[j][i] = (_f[j][i] - vect_min_val[i]) / (vect_max_val[i] - vect_min_val[i]);
|
_f[j][i] = (_f[j][i] - vect_min_val[i]) / (vect_max_val[i] - vect_min_val[i]);
|
||||||
|
|
@ -164,12 +174,15 @@ private:
|
||||||
* @param _f2 the second Pareto set
|
* @param _f2 the second Pareto set
|
||||||
* @param _f the final Pareto set
|
* @param _f the final Pareto set
|
||||||
*/
|
*/
|
||||||
void computeUnion(const std::vector< ObjectiveVector > & _f1, const std::vector< ObjectiveVector > & _f2, std::vector< ObjectiveVector > & _f) {
|
void computeUnion(const std::vector< ObjectiveVector > & _f1, const std::vector< ObjectiveVector > & _f2, std::vector< ObjectiveVector > & _f)
|
||||||
|
{
|
||||||
_f = _f1 ;
|
_f = _f1 ;
|
||||||
for (unsigned int i=0; i<_f2.size(); i++) {
|
for (unsigned int i=0; i<_f2.size(); i++)
|
||||||
|
{
|
||||||
bool b = false;
|
bool b = false;
|
||||||
for (unsigned int j=0; j<_f1.size(); j ++)
|
for (unsigned int j=0; j<_f1.size(); j ++)
|
||||||
if (_f1[j] == _f2[i]) {
|
if (_f1[j] == _f2[i])
|
||||||
|
{
|
||||||
b = true;
|
b = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -182,9 +195,11 @@ private:
|
||||||
/**
|
/**
|
||||||
* How many in niche
|
* How many in niche
|
||||||
*/
|
*/
|
||||||
unsigned int howManyInNicheOf (const std::vector< ObjectiveVector > & _f, const ObjectiveVector & _s, unsigned int _size) {
|
unsigned int howManyInNicheOf (const std::vector< ObjectiveVector > & _f, const ObjectiveVector & _s, unsigned int _size)
|
||||||
|
{
|
||||||
unsigned int n=0;
|
unsigned int n=0;
|
||||||
for (unsigned int i=0 ; i<_f.size(); i++) {
|
for (unsigned int i=0 ; i<_f.size(); i++)
|
||||||
|
{
|
||||||
if (euclidianDistance(_f[i], _s) < (_s.size() / (double) _size))
|
if (euclidianDistance(_f[i], _s) < (_s.size() / (double) _size))
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +210,8 @@ private:
|
||||||
/**
|
/**
|
||||||
* Euclidian distance
|
* Euclidian distance
|
||||||
*/
|
*/
|
||||||
double euclidianDistance (const ObjectiveVector & _set1, const ObjectiveVector & _to, unsigned int _deg = 2) {
|
double euclidianDistance (const ObjectiveVector & _set1, const ObjectiveVector & _to, unsigned int _deg = 2)
|
||||||
|
{
|
||||||
double dist=0;
|
double dist=0;
|
||||||
for (unsigned int i=0; i<_set1.size(); i++)
|
for (unsigned int i=0; i<_set1.size(); i++)
|
||||||
dist += pow(fabs(_set1[i] - _to[i]), (int)_deg);
|
dist += pow(fabs(_set1[i] - _to[i]), (int)_deg);
|
||||||
|
|
|
||||||
|
|
@ -44,49 +44,56 @@
|
||||||
/**
|
/**
|
||||||
* Base class for performance metrics (also known as quality indicators).
|
* Base class for performance metrics (also known as quality indicators).
|
||||||
*/
|
*/
|
||||||
class moeoMetric : public eoFunctorBase {};
|
class moeoMetric : public eoFunctorBase
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for unary metrics.
|
* Base class for unary metrics.
|
||||||
*/
|
*/
|
||||||
template < class A, class R >
|
template < class A, class R >
|
||||||
class moeoUnaryMetric : public eoUF < A, R >, public moeoMetric {};
|
class moeoUnaryMetric : public eoUF < A, R >, public moeoMetric
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for binary metrics.
|
* Base class for binary metrics.
|
||||||
*/
|
*/
|
||||||
template < class A1, class A2, class R >
|
template < class A1, class A2, class R >
|
||||||
class moeoBinaryMetric : public eoBF < A1, A2, R >, public moeoMetric {};
|
class moeoBinaryMetric : public eoBF < A1, A2, R >, public moeoMetric
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for unary metrics dedicated to the performance evaluation of a single solution's objective vector.
|
* Base class for unary metrics dedicated to the performance evaluation of a single solution's objective vector.
|
||||||
*/
|
*/
|
||||||
template < class ObjectiveVector, class R >
|
template < class ObjectiveVector, class R >
|
||||||
class moeoSolutionUnaryMetric : public moeoUnaryMetric < const ObjectiveVector &, R > {};
|
class moeoSolutionUnaryMetric : public moeoUnaryMetric < const ObjectiveVector &, R >
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for unary metrics dedicated to the performance evaluation of a Pareto set (a vector of objective vectors)
|
* Base class for unary metrics dedicated to the performance evaluation of a Pareto set (a vector of objective vectors)
|
||||||
*/
|
*/
|
||||||
template < class ObjectiveVector, class R >
|
template < class ObjectiveVector, class R >
|
||||||
class moeoVectorUnaryMetric : public moeoUnaryMetric < const std::vector < ObjectiveVector > &, R > {};
|
class moeoVectorUnaryMetric : public moeoUnaryMetric < const std::vector < ObjectiveVector > &, R >
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for binary metrics dedicated to the performance comparison between two solutions's objective vectors.
|
* Base class for binary metrics dedicated to the performance comparison between two solutions's objective vectors.
|
||||||
*/
|
*/
|
||||||
template < class ObjectiveVector, class R >
|
template < class ObjectiveVector, class R >
|
||||||
class moeoSolutionVsSolutionBinaryMetric : public moeoBinaryMetric < const ObjectiveVector &, const ObjectiveVector &, R > {};
|
class moeoSolutionVsSolutionBinaryMetric : public moeoBinaryMetric < const ObjectiveVector &, const ObjectiveVector &, R >
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for binary metrics dedicated to the performance comparison between two Pareto sets (two vectors of objective vectors)
|
* Base class for binary metrics dedicated to the performance comparison between two Pareto sets (two vectors of objective vectors)
|
||||||
*/
|
*/
|
||||||
template < class ObjectiveVector, class R >
|
template < class ObjectiveVector, class R >
|
||||||
class moeoVectorVsVectorBinaryMetric : public moeoBinaryMetric < const std::vector < ObjectiveVector > &, const std::vector < ObjectiveVector > &, R > {};
|
class moeoVectorVsVectorBinaryMetric : public moeoBinaryMetric < const std::vector < ObjectiveVector > &, const std::vector < ObjectiveVector > &, R >
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
#endif /*MOEOMETRIC_H_*/
|
#endif /*MOEOMETRIC_H_*/
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
#include <eoFunctor.h>
|
#include <eoFunctor.h>
|
||||||
|
|
||||||
template < class Move >
|
template < class Move >
|
||||||
class moeoMoveIncrEval : public eoBF < const Move &, const typename Move::EOType &, typename Move::EOType::ObjectiveVector > {};
|
class moeoMoveIncrEval : public eoBF < const Move &, const typename Move::EOType &, typename Move::EOType::ObjectiveVector >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
/** the comparator */
|
/** the comparator */
|
||||||
moeoComparator < MOEOT > & comp;
|
moeoComparator < MOEOT > & comp;
|
||||||
} comparator;
|
}
|
||||||
|
comparator;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
/** the comparator */
|
/** the comparator */
|
||||||
moeoComparator < MOEOT > & comp;
|
moeoComparator < MOEOT > & comp;
|
||||||
} comparator;
|
}
|
||||||
|
comparator;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
* Replacement strategy for multi-objective optimization.
|
* Replacement strategy for multi-objective optimization.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoReplacement : public eoReplacement < MOEOT > {};
|
class moeoReplacement : public eoReplacement < MOEOT >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOREPLACEMENT_H_*/
|
#endif /*MOEOREPLACEMENT_H_*/
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* Ctor.
|
* Ctor.
|
||||||
*/
|
*/
|
||||||
moeoRandomSelect(){}
|
moeoRandomSelect()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
* Selection strategy for multi-objective optimization that selects only one element from a whole population.
|
* Selection strategy for multi-objective optimization that selects only one element from a whole population.
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoSelectOne : public eoSelectOne < MOEOT > {};
|
class moeoSelectOne : public eoSelectOne < MOEOT >
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /*MOEOSELECTONE_H_*/
|
#endif /*MOEOSELECTONE_H_*/
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* Saves the fitness of the archive's members into the file
|
* Saves the fitness of the archive's members into the file
|
||||||
*/
|
*/
|
||||||
void operator()() {
|
void operator()()
|
||||||
|
{
|
||||||
char buff[MAX_BUFFER_SIZE];
|
char buff[MAX_BUFFER_SIZE];
|
||||||
if (count)
|
if (count)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* Updates the archive with newly found non-dominated solutions contained in the main population
|
* Updates the archive with newly found non-dominated solutions contained in the main population
|
||||||
*/
|
*/
|
||||||
void operator()() {
|
void operator()()
|
||||||
|
{
|
||||||
arch.update(pop);
|
arch.update(pop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,12 +72,16 @@ public:
|
||||||
/**
|
/**
|
||||||
* Saves the metric's value for the current generation
|
* Saves the metric's value for the current generation
|
||||||
*/
|
*/
|
||||||
void operator()() {
|
void operator()()
|
||||||
if (pop.size()) {
|
{
|
||||||
if (firstGen) {
|
if (pop.size())
|
||||||
|
{
|
||||||
|
if (firstGen)
|
||||||
|
{
|
||||||
firstGen = false;
|
firstGen = false;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// creation of the two Pareto sets
|
// creation of the two Pareto sets
|
||||||
std::vector < ObjectiveVector > from;
|
std::vector < ObjectiveVector > from;
|
||||||
std::vector < ObjectiveVector > to;
|
std::vector < ObjectiveVector > to;
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,8 @@ typedef moeoRealObjectiveVector < Sch1ObjectiveVectorTraits > Sch1ObjectiveVecto
|
||||||
class Sch1 : public moeoRealVector < Sch1ObjectiveVector, double, double >
|
class Sch1 : public moeoRealVector < Sch1ObjectiveVector, double, double >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Sch1() : moeoRealVector < Sch1ObjectiveVector, double, double > (1) {}
|
Sch1() : moeoRealVector < Sch1ObjectiveVector, double, double > (1)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,14 +72,17 @@ void FlowShopBenchmarkParser::printOn(std::ostream & _os) const
|
||||||
{
|
{
|
||||||
_os << "M=" << M << " N=" << N << std::endl;
|
_os << "M=" << M << " N=" << N << std::endl;
|
||||||
_os << "*** processing times" << std::endl;
|
_os << "*** processing times" << std::endl;
|
||||||
for (unsigned int i=0; i<M; i++) {
|
for (unsigned int i=0; i<M; i++)
|
||||||
for (unsigned int j=0; j<N; j++) {
|
{
|
||||||
|
for (unsigned int j=0; j<N; j++)
|
||||||
|
{
|
||||||
_os << p[i][j] << " ";
|
_os << p[i][j] << " ";
|
||||||
}
|
}
|
||||||
_os << std::endl;
|
_os << std::endl;
|
||||||
}
|
}
|
||||||
_os << "*** due-dates" << std::endl;
|
_os << "*** due-dates" << std::endl;
|
||||||
for (unsigned int j=0; j<N; j++) {
|
for (unsigned int j=0; j<N; j++)
|
||||||
|
{
|
||||||
_os << d[j] << " ";
|
_os << d[j] << " ";
|
||||||
}
|
}
|
||||||
_os << std::endl << std::endl;
|
_os << std::endl << std::endl;
|
||||||
|
|
@ -106,7 +109,8 @@ void FlowShopBenchmarkParser::init(const std::string _benchmarkFileName)
|
||||||
p = std::vector< std::vector<unsigned int> > (M,N);
|
p = std::vector< std::vector<unsigned int> > (M,N);
|
||||||
d = std::vector<unsigned int> (N);
|
d = std::vector<unsigned int> (N);
|
||||||
// for each job...
|
// for each job...
|
||||||
for (unsigned int j=0 ; j<N ; j++) {
|
for (unsigned int j=0 ; j<N ; j++)
|
||||||
|
{
|
||||||
// index of the job (<=> j)
|
// index of the job (<=> j)
|
||||||
getline(inputFile, buffer, '\n');
|
getline(inputFile, buffer, '\n');
|
||||||
// due-date of the job j
|
// due-date of the job j
|
||||||
|
|
@ -115,7 +119,8 @@ void FlowShopBenchmarkParser::init(const std::string _benchmarkFileName)
|
||||||
// processing times of the job j on each machine
|
// processing times of the job j on each machine
|
||||||
getline(inputFile, buffer, '\n');
|
getline(inputFile, buffer, '\n');
|
||||||
start = buffer.find_first_not_of(" ");
|
start = buffer.find_first_not_of(" ");
|
||||||
for (unsigned int i=0 ; i<M ; i++) {
|
for (unsigned int i=0 ; i<M ; i++)
|
||||||
|
{
|
||||||
end = buffer.find_first_of(" ", start);
|
end = buffer.find_first_of(" ", start);
|
||||||
p[i][j] = atoi(buffer.substr(start, end-start).data());
|
p[i][j] = atoi(buffer.substr(start, end-start).data());
|
||||||
start = buffer.find_first_not_of(" ", end);
|
start = buffer.find_first_not_of(" ", end);
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,8 @@ double FlowShopEval::tardiness(const FlowShop & _flowshop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector< std::vector<unsigned int> > FlowShopEval::completionTime(const FlowShop & _flowshop) {
|
std::vector< std::vector<unsigned int> > FlowShopEval::completionTime(const FlowShop & _flowshop)
|
||||||
|
{
|
||||||
std::vector< std::vector<unsigned int> > C(M,N);
|
std::vector< std::vector<unsigned int> > C(M,N);
|
||||||
C[0][_flowshop[0]] = p[0][_flowshop[0]];
|
C[0][_flowshop[0]] = p[0][_flowshop[0]];
|
||||||
for (unsigned int j=1; j<N; j++)
|
for (unsigned int j=1; j<N; j++)
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ bool FlowShopOpCrossoverQuad::operator()(FlowShop & _flowshop1, FlowShop & _flow
|
||||||
{
|
{
|
||||||
point1 = rng.random(std::min(_flowshop1.size(), _flowshop2.size()));
|
point1 = rng.random(std::min(_flowshop1.size(), _flowshop2.size()));
|
||||||
point2 = rng.random(std::min(_flowshop1.size(), _flowshop2.size()));
|
point2 = rng.random(std::min(_flowshop1.size(), _flowshop2.size()));
|
||||||
} while (fabs((double) point1-point2) <= 2);
|
}
|
||||||
|
while (fabs((double) point1-point2) <= 2);
|
||||||
// computation of the offspring
|
// computation of the offspring
|
||||||
FlowShop offspring1 = generateOffspring(_flowshop1, _flowshop2, point1, point2);
|
FlowShop offspring1 = generateOffspring(_flowshop1, _flowshop2, point1, point2);
|
||||||
FlowShop offspring2 = generateOffspring(_flowshop2, _flowshop1, point1, point2);
|
FlowShop offspring2 = generateOffspring(_flowshop2, _flowshop1, point1, point2);
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ bool FlowShopOpMutationExchange::operator()(FlowShop & _flowshop)
|
||||||
{
|
{
|
||||||
point1 = rng.random(result.size());
|
point1 = rng.random(result.size());
|
||||||
point2 = rng.random(result.size());
|
point2 = rng.random(result.size());
|
||||||
} while (point1 == point2);
|
}
|
||||||
|
while (point1 == point2);
|
||||||
// swap
|
// swap
|
||||||
std::swap (result[point1], result[point2]);
|
std::swap (result[point1], result[point2]);
|
||||||
// update (if necessary)
|
// update (if necessary)
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,8 @@ bool FlowShopOpMutationShift::operator()(FlowShop & _flowshop)
|
||||||
{
|
{
|
||||||
point1 = rng.random(result.size());
|
point1 = rng.random(result.size());
|
||||||
point2 = rng.random(result.size());
|
point2 = rng.random(result.size());
|
||||||
} while (point1 == point2);
|
}
|
||||||
|
while (point1 == point2);
|
||||||
// direction
|
// direction
|
||||||
if (point1 < point2)
|
if (point1 < point2)
|
||||||
direction = 1;
|
direction = 1;
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,8 @@ eoEvalFuncCounter<FlowShop> & do_make_eval(eoParser& _parser, eoState& _state)
|
||||||
{
|
{
|
||||||
// benchmark file name
|
// benchmark file name
|
||||||
std::string benchmarkFileName = _parser.getORcreateParam(std::string(), "BenchmarkFile", "Benchmark file name (benchmarks are available at www.lifl.fr/~liefooga/benchmarks)", 'B',"Representation", true).value();
|
std::string benchmarkFileName = _parser.getORcreateParam(std::string(), "BenchmarkFile", "Benchmark file name (benchmarks are available at www.lifl.fr/~liefooga/benchmarks)", 'B',"Representation", true).value();
|
||||||
if (benchmarkFileName == "") {
|
if (benchmarkFileName == "")
|
||||||
|
{
|
||||||
std::string stmp = "*** Missing name of the benchmark file\n";
|
std::string stmp = "*** Missing name of the benchmark file\n";
|
||||||
stmp += " Type '-B=the_benchmark_file_name' or '--BenchmarkFile=the_benchmark_file_name'\n";
|
stmp += " Type '-B=the_benchmark_file_name' or '--BenchmarkFile=the_benchmark_file_name'\n";
|
||||||
stmp += " Benchmarks files are available at www.lifl.fr/~liefooga/benchmarks";
|
stmp += " Benchmarks files are available at www.lifl.fr/~liefooga/benchmarks";
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ eoInit<FlowShop> & do_make_genotype(eoParser& _parser, eoState& _state)
|
||||||
{
|
{
|
||||||
// benchmark file name
|
// benchmark file name
|
||||||
std::string benchmarkFileName = _parser.getORcreateParam(std::string(), "BenchmarkFile", "Benchmark file name (benchmarks are available at www.lifl.fr/~liefooga/benchmarks/)", 'B',"Representation", true).value();
|
std::string benchmarkFileName = _parser.getORcreateParam(std::string(), "BenchmarkFile", "Benchmark file name (benchmarks are available at www.lifl.fr/~liefooga/benchmarks/)", 'B',"Representation", true).value();
|
||||||
if (benchmarkFileName == "") {
|
if (benchmarkFileName == "")
|
||||||
|
{
|
||||||
std::string stmp = "*** Missing name of the benchmark file\n";
|
std::string stmp = "*** Missing name of the benchmark file\n";
|
||||||
stmp += " Type '-B=the_benchmark_file_name' or '--BenchmarkFile=the_benchmark_file_name'\n";
|
stmp += " Type '-B=the_benchmark_file_name' or '--BenchmarkFile=the_benchmark_file_name'\n";
|
||||||
stmp += " Benchmarks files are available at www.lifl.fr/~liefooga/benchmarks";
|
stmp += " Benchmarks files are available at www.lifl.fr/~liefooga/benchmarks";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue