Narzędzia użytkownika

Narzędzia witryny


generate_kod

To jest stara wersja strony!


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.1229109751.txt.gz · ostatnio zmienione: 2008/12/12 20:22 przez bfugas