402 lines
10 KiB
C++
402 lines
10 KiB
C++
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// eoRealBounds.h
|
|
// (c) Marc Schoenauer 2001, Maarten Keijzer 2000, GeNeura Team, 1998
|
|
/*
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
|
|
Marc.Schoenauer@polytechnique.fr
|
|
mak@dhi.dk
|
|
*/
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef _eoRealBounds_h
|
|
#define _eoRealBounds_h
|
|
|
|
/**
|
|
\defgroup EvolutionStrategies
|
|
|
|
*/
|
|
|
|
|
|
/**
|
|
\class eoRealBounds eoRealBounds.h es/eoRealBounds.h
|
|
\ingroup EvolutionStrategies
|
|
|
|
Defines bound classes for real numbers.
|
|
|
|
Scalar type:
|
|
------------
|
|
Basic class is eoRealBounds, a pure virtual.
|
|
|
|
The following pure virtual methods are to be used in mutations:
|
|
- void foldsInBounds(double &) that folds any value that falls out of
|
|
the bounds back into the bounds, by bouncing on the limit (if any)
|
|
- bool isInBounds(double &) that simply says whether or not the argument
|
|
is in the bounds
|
|
|
|
So mutation can choose whetehr they want to iterate trying until
|
|
they fall in bounds, or only try once and "repair" by using
|
|
the foldsInBounds method
|
|
|
|
There is also a uniform() method that generates a uniform value
|
|
(if possible, i.e. if bounded) in the interval.
|
|
|
|
Derived class are
|
|
eoRealInterval, that holds a minimum and maximum value,
|
|
eoRealNoBounds, that implements the "unbounded bounds"
|
|
|
|
TODO: the eoRealMinBound and eoRealMaxBound that implement
|
|
the half-bounded intervals.
|
|
|
|
Vector type:
|
|
------------
|
|
Class eoRealVectorBounds implements the vectorized version:
|
|
it is basically a vector of eoRealBounds * and forwards all request
|
|
to the elements of the vector.
|
|
|
|
*/
|
|
class eoRealBounds
|
|
{
|
|
public:
|
|
virtual bool isBounded(void) = 0;
|
|
virtual bool isMinBounded(void) = 0;
|
|
virtual bool isMaxBounded(void) = 0;
|
|
virtual void foldsInBounds(double &) = 0;
|
|
virtual bool isInBounds(double) = 0;
|
|
|
|
// accessors
|
|
virtual double minimum() = 0;
|
|
virtual double maximum() = 0;
|
|
virtual double range() = 0;
|
|
|
|
// random generators
|
|
virtual double uniform(eoRng & _rng = eo::rng) = 0;
|
|
};
|
|
|
|
class eoRealNoBounds : public eoRealBounds
|
|
{
|
|
public:
|
|
virtual ~eoRealNoBounds(){}
|
|
|
|
virtual bool isBounded(void) {return false;}
|
|
virtual bool isMinBounded(void) {return false;}
|
|
virtual bool isMaxBounded(void) {return false;}
|
|
virtual void foldsInBounds(double &) {return;}
|
|
virtual bool isInBounds(double) {return true;}
|
|
|
|
// accessors
|
|
virtual double minimum()
|
|
{
|
|
throw logic_error("Trying to get minimum of unbounded eoRealBounds");
|
|
}
|
|
virtual double maximum()
|
|
{
|
|
throw logic_error("Trying to get maximum of unbounded eoRealBounds");
|
|
}
|
|
virtual double range()
|
|
{
|
|
throw logic_error("Trying to get range of unbounded eoRealBounds");
|
|
}
|
|
|
|
// random generators
|
|
virtual double uniform(eoRng & _rng = eo::rng)
|
|
{
|
|
throw logic_error("Trying to generate uniform values in unbounded eoRealBounds");
|
|
}
|
|
};
|
|
|
|
/* fully bounded == interval */
|
|
class eoRealInterval : public eoRealBounds
|
|
{
|
|
public :
|
|
|
|
/**
|
|
Simple bounds = minimum and maximum (allowed)
|
|
*/
|
|
eoRealInterval(double _min=0, double _max=1) :
|
|
repMinimum(_min), repMaximum(_max), repRange(_max-_min)
|
|
{
|
|
if (repRange<=0)
|
|
throw std::logic_error("Void range in eoRealBounds");
|
|
}
|
|
|
|
// accessors
|
|
virtual double minimum() { return repMinimum; }
|
|
virtual double maximum() { return repMaximum; }
|
|
virtual double range() { return repRange; }
|
|
|
|
// description
|
|
virtual bool isBounded(void) {return true;}
|
|
virtual bool isMinBounded(void) {return true;}
|
|
virtual bool isMaxBounded(void) {return true;}
|
|
|
|
double uniform(eoRng & _rng = eo::rng)
|
|
{
|
|
return repMinimum + _rng.uniform(repRange);
|
|
}
|
|
|
|
// says if a given double is within the bounds
|
|
virtual bool isInBounds(double _r)
|
|
{
|
|
if (_r < repMinimum)
|
|
return false;
|
|
if (_r > repMaximum)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// folds a value into bounds
|
|
void foldsInBounds(double & _r)
|
|
{
|
|
long iloc;
|
|
double dlargloc = 2 * range() ;
|
|
|
|
if (fabs(_r) > 1.0E9) // iloc too large!
|
|
{
|
|
_r = uniform();
|
|
return;
|
|
}
|
|
|
|
if ( (_r > maximum()) )
|
|
{
|
|
iloc = (long) ( (_r-minimum()) / dlargloc ) ;
|
|
_r -= dlargloc * iloc ;
|
|
if ( _r > maximum() )
|
|
_r = 2*maximum() - _r ;
|
|
}
|
|
|
|
if (_r < minimum())
|
|
{
|
|
iloc = (long) ( (maximum()-_r) / dlargloc ) ;
|
|
_r += dlargloc * iloc ;
|
|
if (_r < minimum())
|
|
_r = 2*minimum() - _r ;
|
|
}
|
|
}
|
|
|
|
private :
|
|
double repMinimum;
|
|
double repMaximum;
|
|
double repRange; // to minimize operations ???
|
|
};
|
|
|
|
|
|
/**
|
|
Class eoRealVectorBounds implements the vectorized version:
|
|
it is basically a vector of eoRealBounds * and forwards all request
|
|
to the elements of the vector.
|
|
*/
|
|
class eoRealVectorBounds : public vector<eoRealBounds *>
|
|
{
|
|
public:
|
|
// virtual desctructor (to avoid warining?)
|
|
virtual ~eoRealVectorBounds(){}
|
|
|
|
// Default Ctor
|
|
eoRealVectorBounds() :
|
|
vector<eoRealBounds *>(0) {}
|
|
|
|
/**
|
|
Simple bounds = minimum and maximum (allowed)
|
|
*/
|
|
// Ctor: same bonds for everybody, explicit
|
|
eoRealVectorBounds(unsigned _dim, double _min, double _max) :
|
|
vector<eoRealBounds *>(_dim, new eoRealInterval(_min, _max))
|
|
{
|
|
if (_max-_min<=0)
|
|
throw std::logic_error("Void range in eoRealVectorBounds");
|
|
}
|
|
|
|
// Ctor: same bonds for everybody, given as a eoRealBounds
|
|
eoRealVectorBounds(unsigned _dim, eoRealBounds & _bounds) :
|
|
vector<eoRealBounds *>(_dim, &_bounds)
|
|
{}
|
|
|
|
/** Ctor: different bonds for different variables, vectors of double
|
|
*/
|
|
eoRealVectorBounds(vector<double> _min, vector<double> _max)
|
|
{
|
|
if (_max.size() != _min.size())
|
|
throw std::logic_error("Dimensions don't match in eoRealVectorBounds");
|
|
for (unsigned i=0; i<_min.size(); i++)
|
|
{
|
|
push_back( new eoRealInterval(_min[i], _max[i]));
|
|
}
|
|
}
|
|
|
|
/** Ctor, particular case of dim-2
|
|
*/
|
|
eoRealVectorBounds(eoRealBounds & _xbounds, eoRealBounds & _ybounds) :
|
|
vector<eoRealBounds *>(0)
|
|
{
|
|
push_back( &_xbounds);
|
|
push_back( &_ybounds);
|
|
}
|
|
|
|
/** test: is i_th component bounded
|
|
*/
|
|
virtual bool isBounded(unsigned _i)
|
|
{
|
|
return (*this)[_i]->isBounded();
|
|
}
|
|
|
|
/** test: bounded iff all are bounded
|
|
*/
|
|
virtual bool isBounded(void)
|
|
{
|
|
for (unsigned i=0; i<size(); i++)
|
|
if (! (*this)[i]->isBounded())
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// these do not make any sense as vectors!
|
|
virtual bool isMinBounded(unsigned _i)
|
|
{ return (*this)[_i]->isMinBounded();} ;
|
|
|
|
virtual bool isMaxBounded(unsigned _i)
|
|
{ return (*this)[_i]->isMaxBounded();} ;
|
|
|
|
/** Modifies a real value so that it stays in the bounds - i_th component
|
|
*/
|
|
virtual void foldsInBounds(unsigned _i, double & _r)
|
|
{
|
|
(*this)[_i]->foldsInBounds(_r);
|
|
}
|
|
|
|
/** Modifies a vector of real value so that it stays in the bounds
|
|
*/
|
|
virtual void foldsInBounds(vector<double> & _v)
|
|
{
|
|
for (unsigned i=0; i<size(); i++)
|
|
{
|
|
foldsInBounds(i, _v[i]);
|
|
}
|
|
}
|
|
|
|
/** test: is i_th component within the bounds
|
|
*/
|
|
virtual bool isInBounds(unsigned _i, double _r)
|
|
{ return (*this)[_i]->isInBounds(_r); }
|
|
|
|
/** test: are ALL components within the bounds
|
|
*/
|
|
virtual bool isInBounds(vector<double> _v)
|
|
{
|
|
for (unsigned i=0; i<size(); i++)
|
|
if (! isInBounds(i, _v[i]))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// accessors
|
|
virtual double minimum(unsigned _i) {return (*this)[_i]->minimum();}
|
|
virtual double maximum(unsigned _i) {return (*this)[_i]->maximum();}
|
|
virtual double range(unsigned _i) {return (*this)[_i]->range();}
|
|
|
|
virtual double averageRange()
|
|
{
|
|
double r=0.0;
|
|
for (unsigned i=0; i<size(); i++)
|
|
r += range(i);
|
|
return r/size();
|
|
}
|
|
|
|
/** Generates a random number in i_th range
|
|
*/
|
|
virtual double uniform(unsigned _i, eoRng & _rng = eo::rng)
|
|
{
|
|
double r= (*this)[_i]->uniform();
|
|
return r;
|
|
}
|
|
|
|
/** fills a vector with uniformly chosen variables in bounds
|
|
*/
|
|
void uniform(vector<double> & _v, eoRng & _rng = eo::rng)
|
|
{
|
|
_v.resize(size());
|
|
for (unsigned i=0; i<size(); i++)
|
|
{
|
|
_v[i] = uniform(i, _rng);
|
|
}
|
|
}
|
|
};
|
|
|
|
/** the dummy unbounded eoRealVectorBounds: usefull if you don't need bounds!
|
|
*/
|
|
class eoRealVectorNoBounds: public eoRealVectorBounds
|
|
{
|
|
public:
|
|
// virtual desctructor (to avoid warining?)
|
|
virtual ~eoRealVectorNoBounds(){}
|
|
|
|
/**
|
|
Simple bounds = minimum and maximum (allowed)
|
|
*/
|
|
// Ctor: nothing to do!
|
|
eoRealVectorNoBounds(unsigned _dim=0) {}
|
|
|
|
|
|
virtual bool isBounded(unsigned) {return false;}
|
|
virtual bool isBounded(void) {return false;}
|
|
virtual bool isMinBounded(unsigned) {return false;}
|
|
virtual bool isMaxBounded(unsigned) {return false;}
|
|
|
|
virtual void foldsInBounds(unsigned, double &) {return;}
|
|
virtual void foldsInBounds(vector<double> &) {return;}
|
|
|
|
virtual bool isInBounds(unsigned, double) {return true;}
|
|
virtual bool isInBounds(vector<double>) {return true;}
|
|
|
|
// accessors
|
|
virtual double minimum(unsigned)
|
|
{
|
|
throw logic_error("Trying to get minimum of unbounded eoRealBounds");
|
|
}
|
|
virtual double maximum(unsigned)
|
|
{
|
|
throw logic_error("Trying to get maximum of unbounded eoRealBounds");
|
|
}
|
|
virtual double range(unsigned)
|
|
{
|
|
throw logic_error("Trying to get range of unbounded eoRealBounds");
|
|
}
|
|
|
|
virtual double averageRange()
|
|
{
|
|
throw logic_error("Trying to get average range of unbounded eoRealBounds");
|
|
}
|
|
|
|
// random generators
|
|
virtual double uniform(unsigned, eoRng & _rng = eo::rng)
|
|
{
|
|
throw logic_error("No uniform distribution on unbounded eoRealBounds");
|
|
}
|
|
|
|
// fills a vector with uniformly chosen variables in bounds
|
|
void uniform(vector<double> &, eoRng & _rng = eo::rng)
|
|
{
|
|
throw logic_error("No uniform distribution on unbounded eoRealBounds");
|
|
}
|
|
|
|
};
|
|
|
|
// one object for all
|
|
eoRealNoBounds eoDummyRealNoBounds;
|
|
eoRealVectorNoBounds eoDummyVectorNoBounds;
|
|
#endif
|