/*** * @file Population.hpp * * This is based on what we did with A. Kornilov for his Master Thesis * work, but I ended up removing the Hadoop-connectivity, because it * made this a bit cluttered and dependent on the Hadoop platform. I * suppose it could be re-implemented here, should we return to those * issues later on. For my PhD, I'll be dealing with datasets that fit * in memory. */ #include #include #include #include #include "Individual.hpp" using namespace std; #ifndef POPULATION_HPP_ #define POPULATION_HPP_ /** A population of individual solutions; this is the core of a * Pareto-based memetic algorithm. The population is responsible for * the storage of individuals, and dispatching the the operations * that produce the next population. The population can also be used * as an archive of any number of historical solutions. */ class Population { // -------------------- Internals --------------------- protected: /** Pointers to individuals. FIXME: Expect some brainwork with the * pointers and the issue of who should own each individual! */ vector > _individuals; /** Number of objectives. FIXME: Shouldn't require this in the general Population, but only in some friend class that operates on the population? */ size_t _nobj; public: // Means of creation and destroying /** Create a population for individuals that have nobj objectives. */ Population(int nobj); Population() = delete; /* Become the merger of two populations; invalidates parents. */ //Population(Population &p1, Population &p2); virtual ~Population(); // -------------- read and write ------------------ /** Insert individuals from a stream, using a concrete reader. */ void fromStream(istream & ist, const IndividualReader * rdr); /** Write all individuals to a stream. */ void toStream (ostream & ost) const; /** Get one objective value from an indexed individual. */ double getObjectiveValue (int individualIndex, int objectiveIndex) const; /** Get the vector of traced values from an indexed individual. */ vector getTrace (int individualIndex) const; /** Get the unique ID of an individual. */ int getIndividualID (int individualIndex) const; /** Set the unique ID of an individual. */ void setIndividualID (int individualIndex, int newID); /** Get the current size of the population. */ size_t size() const; /** Insert a new individual, obtaining ownership. */ void adopt(unique_ptr indiv); /** Clear contents; individuals become deleted. */ void clear(); /** Insert new individuals whose ownership is taken from the other pop. */ void adoptFrom(Population & p1); /** Insert new individuals whose ownership is taken from two other pops. */ void adoptFromTwo(Population & p1, Population & p2); /** Insert new individuals that are cloned from the other pop. */ void deepCopyFrom(Population & p1); // -------------- operations delegated to individuals ------------------ /** Command all individuals to evaluate their objectives. */ void evaluate(); /** Command all individuals to mutate, according to their * (possibly individually evolving) rules. */ void mutate(); /** Command all individuals to do local improvement, according to * their own, possibly individually evolving or stochastic, * rules. A thread-specific random generator must always be * given, because some operators may require randomization. */ void improve(mt19937 * mt); /** Return the index of the winner of a binary tournament. Needs a * random generator to resolve ties. */ int binaryTournament(int ii1, int ii2, mt19937 * mt); // -------------- operations partially delegated to individuals ---- #if 1 //----------------- FIXME: NOT YET (RE-) IMPLEMENTED PROPERLY public: // ----- Public interface for Nondominated sorting: /** Assign ranks and crowding distances to all individuals. */ void assignRankAndCrowdingDistance(); /** Insert copies of individuals from a parent population, as per * the nondominated fill of NSGA-II. */ void fillNondominatedSortFrom(Population &parent); // Interface for tournament selection and crossover: // Nah.. wouldn't we want a separate selector (friend) class? void selectAndCrossFrom(Population &parent, mt19937 *mt); // ----- Routines for Nondominated sorting, with protected helpers: protected: void quicksortFrontObj(int objcount, int *obj_array, int front_size) const; void quicksortDist(int *dist, int front_size) const; void crowdingFillFrom(Population &mixed, int count, int front_size, void *plstelite); void assignCrowdingDistance (int *dist, int **obj_array, int front_size); void assignCrowdingDistanceList (void *plst, int front_size); void assignCrowdingDistanceIndices (int c1, int c2); int binaryTournament (int a, int b, mt19937 *mt) const; #endif // ---------------------------- end of unimplemented part. }; #endif