Narzędzia użytkownika

Narzędzia witryny


generate_kod

Przykład wykorzystania generate i generate_n

/**
	Bernard Fugas E1-ISIII
 
	Przykład wykorzystania szablonów generate oraz generate_n
 
	W skrócie:
	Szablony generate i generate_n pozwalają przypisać wartości zwracane
	przez bezargumentową funkcję lub obiekt funkcyjny do tablicy
	lub kontenera udostępniającego iterator.
*/
 
#include <ostream>
#include <algorithm>	// tu jest definicja generate i generate_n
#include <vector>
#include "boost/random.hpp" //generator liczb losowych - użyty w przykładzie
 
using namespace std;
 
/** GeneticAlgorithm to klasa realizująca przykładowy algorytm genetyczny.
	Nie wnikamy w jego implementację.
 
	Istotne jest to, że populacja początkowa składa się nie tylko z osobników
	wygenerowanych losowo, ale również ze znanych "w miarę dobrych" rozwiązań
	zwanych "ekspertami".
	Szablony generate oraz generate_n pozwalają w wygodny sposób stworzyć
	populację początkową o zadanej procentowej ilości ekspertów.
 
	Przykłady użycia w funkcjach createGeneration0() 
	oraz operator<<(ostream& os, const GeneticAlgorithm& ga)
*/
class GeneticAlgorithm {
public:
	/** Przykładowa klasa osobnika używanego w algorytmie genetycznym */
	class Individual {
		unsigned char chromosome_; //w rzeczywistym algorytmie byłaby to co najmniej tablica bajtów
	public:
		Individual() {}
		Individual(unsigned char chromosome) : chromosome_(chromosome) {}
		friend class GeneticAlgorithm;
		friend ostream& operator<<(ostream& os, const Individual& i);
	};
 
	/** Obiekt funkcyjny generujący liczby pseudolosowe */
	class RandomIndividualGenerator {
		boost::mt19937 state_;
		boost::uniform_int<unsigned> rng_;
	public:
		RandomIndividualGenerator(unsigned long state) : state_(state), rng_(0,255) {}
		Individual operator() (void) { return Individual( static_cast<unsigned char>(rng_(state_)) ); }
	};
 
////Definicje typów
	typedef vector<Individual> Individuals;
	typedef vector<Individual>::iterator IndividualsIt;
	typedef vector<Individual>::const_iterator IndividualsCit;
 
////Metody publiczne
	/**
	@brief Konstruktor algorytmu. 
	@param[in] population_size Rozmiar populacji
	@param[in] expert_percent  Procent ekspertów w populacji początkowej
	*/
	GeneticAlgorithm(unsigned long seed, size_t population_size, size_t expert_percent) :
		rig_(seed),
		population_size_(population_size), 
		expert_percent_(expert_percent)
		{}
 
	/** @brief Uruchamia szkielet algorytmu. */
	void run(void) {
		bool finish_condition = false;
		createGeneration0(); //stwórz populację początkową
 
		while( !finish_condition ) {
			//korzystaj z operatorów genetycznych
			//selekcja, krzyżowanie, mutacja, ...
 
			//w w którejś z iteracji...
			finish_condition = true;
		}
	}
 
private:
	/**
	@brief Zwraca osobników "ekspertów" - znane, dość dobre rozwiązania
	@return Nowy osobnik "ekspert"
	@note Eksperci tworzeni są zgodnie z jakąś zależnością funkcyjną.
	*/
	static Individual getExpert(void) {
		static unsigned char i = 0x77;
		++i;
		return Individual(i);
	}
 
	/**
	@brief Tworzy populację początkową
	@note Przykład użycia generate
	*/
	void createGeneration0(void) {
		individuals_ = Individuals(population_size_);
		size_t experts_num = population_size_*expert_percent_/100; //liczba ekspertów
		IndividualsIt expertsEnd = individuals_.begin() + experts_num; //iterator "końca ekspertów"
 
		/**************************************************************************************
		void generate(_FwdIt _First, _FwdIt _Last, _Fn0 _Func)
 
		Pozwala przypisać elementom od iteratora _First (włącznie z _First) 
		do _Last (bez _Last) kolejne wartości funkcji _Func
		**************************************************************************************/
 
		//generuj ekspertów
		//zgodnie z zależnością funkcyjną; korzystając z funkcji
		generate(individuals_.begin(), expertsEnd, getExpert); 
 
		//generuj losowe osobniki
		//losowo; korzystając z funktora
		generate(expertsEnd, individuals_.end(), rig_);
 
		//można sobie wyobrazić jeszcze inne rodzaje tworzonych w ten sposób osobników...
	}
 
	Individuals individuals_; /**< wektor osobników w populacji */
	size_t population_size_;  /**< rozmiar populacji */
	size_t expert_percent_;   /**< procentowy udział ekspertów w populacji początkowej */
	RandomIndividualGenerator rig_; /**< generator losowych osobników (obiekt funkcyjny) */
	friend ostream& operator<<(ostream& os, const GeneticAlgorithm& ga);
	friend class Individual;
}; //class GeneticAlgorithm
 
/**
@brief Zaimplementowany w celu łatwego wyświetlenia rezultatu
*/
ostream& operator<<(ostream& os, const GeneticAlgorithm::Individual& individual) {
	os.setf(ios::hex, ios::basefield);
	os.width(2);
	os.fill('0');
	return os << static_cast<unsigned>(individual.chromosome_);
}
 
/**
@brief Wyświetla bieżącą populację. 
Dla celów dydaktycznych rozpoczyna od wyświetlenia sekwencji losowych osobników.
@note Przykład użycia generate_n
*/
ostream& operator<<(ostream& os, const GeneticAlgorithm& ga) {
	/**************************************************************************************
	generate_n(_OutIt _Dest, _Diff _Count, _Fn0 _Func)
 
	Pozwala przypisać n elementom począwszy od _First 
	kolejne wartości zwracane przez _Func
 
	Uwaga: tego nie da się wykonać za pomocą generate
	**************************************************************************************/
	os << "Losowe liczby:" << endl;
	generate_n(ostream_iterator<GeneticAlgorithm::Individual>(os, " "), 10, ga.rig_);
	os << endl << "Populacja:" << endl;
 
	for(GeneticAlgorithm::IndividualsCit it=ga.individuals_.begin(); it != ga.individuals_.end(); ++it) 
		os << *it << endl;
	return os;
}
 
// ================== main ================ 
int main(/*int argc, char** argv*/) {
	size_t population_size = 20; /** < całkowity rozmiar populacji */
	size_t expert_percent = 10; /** < procentowa ilość ekspertów w populacji początkowej */
	unsigned long seed = 0;
 
	GeneticAlgorithm ga(seed, population_size, expert_percent); //stwórz algorytm
	ga.run();  //i go uruchom
	//...
	cout << ga;	//wyświetl populację
}
generate_kod.txt · ostatnio zmienione: 2008/12/12 20:24 przez bfugas