/** * @file Individual.hpp * * Interface of a population individual for population-based * optimization algorithms. * * This is based on an older project used in the MSc thesis project of * A. Kornilov. Heavily modified from original. */ #include #include #include #include #include using namespace std; #ifndef INDIVIDUAL_HPP_ #define INDIVIDUAL_HPP_ /** * Base class for the individuals in a Pareto optimization * population. Must be derived for concrete objective computations. * This base class is an abstraction layer that does not care about * internal representation or how to compute anything. Rather, this * implements only the facilities for Pareto dominance handling and * storage in the evolving population and in the total solution * archive. */ class Individual { protected: int _id; /// Running index or other ID tag. int _rank; /// Pareto rank within container pop. vector _objectives; /// Objective function values double _constraintViolation; /// Constraint violation double _crowding; /// "Crowding" value/dist. (e.g. NSGA-II) /** Read the actual (concrete) representation from a stream. */ virtual void impl_from_stream(istream & repr) = 0; /** Write the actual (concrete) representation to a stream. */ virtual void impl_to_stream(ostream & repr) = 0; public: /** Create uninitialized; only for reading from stream very soon.*/ Individual(){}; /** Create and initialize; should call this from derived constructor. */ Individual(size_t numObjectives); virtual ~Individual() {}; /* Deep-copying constructor.. default is fine? */ // Individual(const Individual & src); /** Cloning can use the default copy constructor, but otherwise it * is specific to the derived classes. */ virtual Individual * clone() = 0; /** Evaluate objective functions. Is to be called before getting * values, if any operators have been applied. The concrete * derived class must assign objective values when this is * called. */ virtual void evaluate() = 0; /* TODO: Proper abstraction for cooperation and improvement */ /** Apply evolutionary mutation operator(s). Up to the concrete class. */ virtual void mutate() = 0; /** Apply memetic improvement operator(s). Up to the concrete class. */ virtual void improve(mt19937 * mt) = 0; /** Binary cross-over with another individual. Up to the concrete class. */ virtual pair,unique_ptr > crossWith(Individual & other) = 0; // Could have an n-ary cooperateWith(vector others) ? /* Getters and setters */ virtual int getId(); virtual void setId(int id); virtual int getRank(); virtual void setRank(int rank); virtual double getCrowdingDistance(); virtual void setCrowdingDistance(double crowdingDistance); virtual double getObjective(size_t index); virtual void setObjective(size_t index, double value); /** Get measures that are interesting in post-run tracing; * subclasses would know which measures are of importance. By * default, the objectives are returned as a vector object. */ virtual vector getTrace(); /** * Dominance comparison operation as in NSGA-II; returns 1 if * ind1 dominates, -1 if ind2 dominates, and 0 upon mutual * non-domination. */ friend int checkDominance(const Individual &ind1, const Individual &ind2); /** * Returns true if this individual is better than another in the * NSGA-II -sense, i.e., based on dominance, crowding distance * within non-dominated solutions, and random selection in * complete draws. Needs the source for random numbers to make the * draw. */ virtual bool winsTournamentAgainst(const Individual &opponent, mt19937* mt); /* Serialization and de-serialization */ /** Replace contents with that read from an ASCII stream, for * analysis or continuing a halted computation. */ virtual void fromStream(istream & ist); /** Write content to an ASCII stream, for result output and computation tracing. */ virtual void toStream(ostream & ost); }; /** Abstract base class for creating a completely new instance from a * stream representation. Must be implemented along with any * ConcreteIndividual, because nobody else knows the stream format. */ class IndividualReader { public: virtual Individual * fromStream(istream & ist) const = 0; }; #endif