-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Specific representations #7
Comments
hi, do you have some ideas about how to implement the real-valued representation inside of the GALGO? Thanks! |
Hi langongjin, I have used Galgo many times, From memory, you have already 64 bit of precision for real number (parameter), which covers all the value of a double (usually quite enough for most applications). You can even increase the number of bit 0/1 with simple code adjustment if need more precision per parameter (but simpler to use 2 (64 bits) parameters to mimic one 128 bit parameter). Do you really need to change the internal representation, for what purposes (Do you have any sample code of your app)? AL |
Extra info: std::string GetBinary(uint64_t value) An example of c++ code for converting IEEE 754 is here: AL |
hi, Alanthie, std::string GetBinary(uint64_t value)
uint64_t GetValue(const std::string& s) How to implement the real-valued representation? |
Galgo dont use real-value internally (only bits of 0/1) Galgo has currently only 3 mutations operators: // uniform mutation: replacing a chromosome gene by a new one // boundary mutation: replacing a chromosome gene by its lower or upper bound You just need to implement the Gaussian mutation GaM = min(max(N(x,stddev),a,b). Galgo has only uniform random probability in range [0,1) I may try to do it, when I find some time this week. |
hi, Alanthie, Thank you very much! |
Hi langongjin, 1 - Normally, a problem is a bunch of real-value parameters (external) to be optimized (internal algorithm) according to an utility function (external). Internally, Galgo use 01 bit representations, but anything would have work also (just more complex to code). Our DNA, AGTC is not real-valued internally, just 4 discrete values (00, 01, 10, 11). You rarely need to bother about the internal representation (Unless PROVED too inefficient). 2- 3- Thanks |
Extra Info (The problem with real-valued internal representation): |
Gaussian Mutator Run on the example.cpp Running Genetic Algorithm...Generation = 0 | X1 = 1.2362554360 | X2 = 1.5742732891 | F(x) = -0.2669181560 AL |
hi, Thank you very much for your time.
Last, thank you very much for you code. I am testing the code with my task. I will give you feedback if I have any questions. Cheers! |
one more thing, could give me a hint how/what you changed? This will be useful for me to handle the code. Thanks! |
Hi, In my branch, on each *.hpp file, there is an history button that shows the list of changes made. I will do the Xover with a gaussian (after I figure it out - switching position should be easy). Do you a function I can test that would shows the advantage of gaussian Xover/Mutation over classics one? AL |
Hi, Thanks |
hi, Alanthie, Thank you for your time and information. Regarding my test function, my final function depend on a simulator, therefore, it does not work for you. But right now, I just test the classic functions from https://www.sfu.ca/~ssurjano/optimization.html. Therefore, I have the almost same test functions in your code. Regarding the real-valued crossover, I would say I need Single arithmetic crossover and Simple arithmetic crossover from my intuition. I am not sure which one is better because I did not test. Therefore, could you implemented both of Single arithmetic crossover and Simple arithmetic crossover if you have time. Thank you very much! |
Hi langongjin, I will implement the required crossovers. AL |
cool, Thank you very much! |
Yes, it is recommended to be nearer 1.0. But I dont see much improvement by doing so in my tests cases! AL |
yes, for (int z = 1; z < chr->nogen(); z++) // number of generations
{
// sigma adapting with iteration
// TODO - One sigma per parameter
norm01 = distribution01(generator);
sigma = std::max(T(0), (T) (sigma * exp(norm01)));
} I do not understand why I printed a value as: generator: 412013968
norm01: -0.6605581884
sigma: 11.4456127296
value: -0.0780956741
norm: 6.0425012260
gaussian_value: 5.0000000000 you could see the value of norm is far away from value so that gaussian_value is set as the maximum. And it happens often. Thank you very much! |
Yes, mutation rate should change based on efficiency of the search... (Need to measure it first - TODO!) Let me know the algos for GAM you want to try. I' m adding some models to compare them in my branch: I will be able to compare them when a have the gaussian Xover and enough tests cases. Thanks |
hi, Alanthie, |
hi, Alanthie, I tested the Gaussian mutation and found a problem. The |
Hi langongjin, Thanks Yes, I`m currently fixing the various issues - work in progress in my branch. -I am implementing the real-valued gaussian mutation from 4.4.2 (page 57)
AL |
cool, Thanks for your work. I have no more idea for other mutations right now. Maybe I will have after test the code when you finish. "Gaussian Xover"? do you mean the Xover for real-valued representation? |
Hi, Xover for real-valued representation are in my branch now: Setup - see example.cpp: I have fixed the other issued also - but not sure at 100% for the moment. AL |
hi, Alanthie, |
Just pushed some fixes |
okay, I will let you know the results. Thanks! |
hi, Alanthie, /Users/lan/projects/bayesian/GALGOrealXover/GALGO/src/Evolution.hpp:283:33: error: redefinition of 'chrmat1'
const galgo::Chromosome<T>& chrmat1 = *x[idx1];
^
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/src/Evolution.hpp:260:33: note: previous definition is here
const galgo::Chromosome<T>& chrmat1 = *x[idx1];
^
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/src/Evolution.hpp:284:33: error: redefinition of 'chrmat2'
const galgo::Chromosome<T>& chrmat2 = *x[idx2];
^
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/src/Evolution.hpp:261:33: note: previous definition is here
const galgo::Chromosome<T>& chrmat2 = *x[idx2];
^
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/src/Evolution.hpp:322:9: error: redefinition of 'i'
int i = pos;
^
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/src/Evolution.hpp:313:9: note: previous definition is here
int i = pos;
^
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/src/Evolution.hpp:391:35: error: use of undeclared identifier 'chrmat1'
chr1->sigma_update(i, 0.5*(chrmat1.get_sigma(i)+chrmat2.get_sigma(i) ));
^
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/src/Evolution.hpp:391:56: error: use of undeclared identifier 'chrmat2'
chr1->sigma_update(i, 0.5*(chrmat1.get_sigma(i)+chrmat2.get_sigma(i) ));
^
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/src/Evolution.hpp:395:35: error: use of undeclared identifier 'chrmat1'
chr2->sigma_update(i, 0.5*(chrmat1.get_sigma(i) + chrmat2.get_sigma(i) ));
^
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/src/Evolution.hpp:395:58: error: use of undeclared identifier 'chrmat2'
chr2->sigma_update(i, 0.5*(chrmat1.get_sigma(i) + chrmat2.get_sigma(i) )); |
Sorry, it is now fixed. |
Thanks! for (int i = 0; i < chr1->nbgene(); i++) //0~dimensions
{
chr1->initGene(i, chrmat1.get_value(i));
} Is this still use the Binary string as the gene inside of funciton |
hi, Alanthie, > std::vector<CHR>& get_newpop() { return newpop;}
> std::vector<CHR>& get_matpop() { return matpop;} And add the following into std::vector<galgo::CHR>& np = x.get_matpop();
for(int k=0; k < np[matidx]->nbgene(); k++)
{
T t = np[matidx]->get_value(k) ;
std::cout << t;
} But I got some errors /Users/lan/projects/bayesian/GALGOrealXover/GALGO/Population.hpp:264:13: error: use of alias template 'CHR' requires template arguments
std::vector<CHR>& get_newpop() { return newpop;}
^~~
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/Galgo.hpp:56:1: note: template is declared here
using CHR = std::shared_ptr<Chromosome<T>>;
^
In file included from /Users/lan/projects/bayesian/GALGOrealXover/GALGO/main.cpp:7:
In file included from /Users/lan/projects/bayesian/GALGOrealXover/GALGO/Galgo.hpp:81:
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/Population.hpp:264:41: error: use of undeclared identifier 'newpop'
std::vector<CHR>& get_newpop() { return newpop;}
^
/Users/lan/projects/bayesian/GALGOrealXover/GALGO/Population.hpp:267:13: error: use of alias template 'CHR' requires template arguments
|
hi, Alanthie, A small issue for the latest code. There are also have some same configurations in main.cpp and GeneticAlgorithm.hpp. main.cpp
void set_my_config(galgo::ConfigInfo<_TYPE>& config)
{
// override some defaults
config.mutinfo._sigma = 1.0;
config.mutinfo._sigma_lowest = 0.01;
config.mutinfo._ratio_boundary = 0.10;
config.covrate = 0.50; // 0.0 if no cros-over
config.mutrate = 0.05;
config.recombination_ratio = 0.50;
config.elitpop = 5;
config.tntsize = 2;
config.Selection = TNT;
config.CrossOver = RealValuedSimpleArithmeticRecombination;
config.mutinfo._type = galgo::MutationType::MutationGAM_UncorrelatedNStepSizeBoundary;
config.popsize = 20;
config.nbgen = 20;
config.output = true;
} GeneticAlgorithm.hpp
template <typename ParamTYPE>
struct ConfigInfo
{
ConfigInfo() : mutinfo()
{
// DEFAULTS
covrate = .50; // cross-over rate
mutrate = 1.0; // mutation rate usually it is 1.0 for real-valued
SP = 1.5;
tolerance = 0.0;
recombination_ratio = 0.60; //Real Valued crossover ratio, can't be 0.5 because 0.5 will generate two same offsprings after Xover
elitpop = 1;
tntsize = 2; // k-tournament size k=2/4, higher value higher pressure
genstep = 10;
precision = 10;
Objective = nullptr;
Selection = TNT; // RWS, TNT, RNK, RSP, TRS
CrossOver = RealValuedSimpleArithmeticRecombination; //
//Mutation = SPM; // derived from by mutinfo._type
Adaptation = nullptr;
Constraint = nullptr;
FixedValue = nullptr;
StopCondition = nullptr;
nbgen = 10;
popsize = 20;
output = false;
}
MutationInfo<ParamTYPE> mutinfo;
double covrate;
double mutrate;
double SP;
double tolerance;
double recombination_ratio;
int elitpop;
//int matsize; // set to popsize when ga is constructed, maybe change by ga.matsize = ... after constructor and before ga.run()
int tntsize;
int genstep;
int precision;
std::vector<double> (*Objective)(const std::vector<ParamTYPE>&);
void (*Selection)(Population<ParamTYPE>&);
void (*CrossOver)(const Population<ParamTYPE>&, CHR<ParamTYPE>&, CHR<ParamTYPE>&);
void (*Mutation)(CHR<ParamTYPE>&);
void (*Adaptation)(Population<ParamTYPE>&) = nullptr;
std::vector<double> (*Constraint)(const std::vector<ParamTYPE>&);
void (*FixedValue)(Population<ParamTYPE>&, int k);
bool (*StopCondition)(galgo::GeneticAlgorithm<ParamTYPE>&);
std::vector<bool> force_value_flag;
std::vector<ParamTYPE> force_value;
int nbgen;
int popsize;
bool output;
}; Are they we want? |
Hi langongjin, struct ConfigInfo is needed. set_my_config() is just to setup the test exemples (in exemple.cpp) - not needed, but you can do something similar for your project. Usage: AL |
hi, Alanthie, I debug the real-valued code for days. Maybe the code real-valued representation is not good work. /********** 1# ACKLEY function N Dimensions **************/
template <typename T>
class AckleyObjective
{
public:
static std::vector<double> Objective(const std::vector<T>& x)
{
size_t dim_in = 5;
auto xx = x;
// transfer interval from [0, 1] to [-32.768, 32.768]
for (int i = 0; i < dim_in; i++)
{
xx[i] = 65.536 * x[i] - 32.768;
}
const double a = 20.;
const double b = 0.2;
const double c = 2 * M_PI;
double sum1 = 0.;
double sum2 = 0.;
for (size_t i = 0; i < dim_in; i++)
{
sum1 = sum1 + xx[i] * xx[i];
sum2 = sum2 + std::cos(c * xx[i]);
}
double term1 = -a * std::exp(-b * std::sqrt(sum1 / dim_in));
double term2 = -std::exp(sum2 / dim_in);
double obj = term1 + term2 + a + std::exp(1);
return {-obj}; //max = 0, at (0,...,0)
}
};
/********** 3# Ellipsoid function N Dimensions **************/
template <typename T>
class EllipsoidObjective
{
public:
static std::vector<double> Objective(const std::vector<T>& x)
{
size_t dim_in = 5;
double inner = 0., outer = 0.;
for (size_t i = 0; i < dim_in; ++i)
{
for(size_t j = 0; j < i; j++)
{
inner = inner + std::pow((131.072 * x[j] - 65.536), 2); //(-65.536, 65.536)
}
outer = outer + inner;
}
return {-outer}; //maximum = 0 at (0, ..., 0)
}
};
/********** 4# Sphere function N Dimensions **************/
template <typename T>
class SphereObjective
{
public:
static std::vector<double> Objective(const std::vector<T>& x)
{
size_t dim_in = 5;
double inner = 0.;
for (size_t i = 0; i < dim_in; ++i)
{
inner = inner + std::pow((10. * x[i] - 5.), 2);
}
return {-inner}; //maximum = 0 with (0, 0)
}
}; I tested the above three functions for 10 runs, 20 generations (Actually I also tested more runs), popsize = 20. I took the average for each generations and each run. Results as: The *.pdf are the results of real-valued representation. The *_bi.pdf are the results of binary representation. The binary representation works but not good. The real-valued representation is definitely not work/convergence. I want to say that we can not say it is convergence based on the best fitness. It is convergence only when the average should go up and the best fitness close to optimal, right? How is your idea? could you run the above three function to see the results? In addition, here is the R code I used to plot the figures. rm(list = ls())
library(ggplot2)
library(dplyr)
setwd("~/projects/bayesian/GALGOrealvalue/plot/")
fitness = read.table("sphere_bi_10.txt")
fitnessmean <- aggregate(fitness,list(rep(1:(nrow(fitness)%/%20+1),each=20,len=nrow(fitness))),mean)[-1]
fitmean = data.frame(gen = rep(1:20),fit = fitnessmean$V1)
fitmanaverage = aggregate( fit ~ gen, fitmean, mean)
ggplot(fitmanaverage, aes(1:nrow(fitmanaverage))) +
geom_point(aes(1:nrow(fitmanaverage), fitmanaverage$fit), alpha = 1/2, colour = "black", size = 1) +
geom_smooth(aes(1:nrow(fitmanaverage), fitmanaverage$fit), colour = "blue", method = "loess") +
labs(x="Generations", y="fitness",title="sphere_bi") +
ylim(-50,0) here is the data Thank you very much! |
hi, Alanthie, Good news, finally, it works as: The problem is I am testing more test suits, but let you know the good news firstly. |
hi, Alanthie, template <typename T>
class MichalewiczObjective //todo not good results
{
public:
static std::vector<double> Objective(const std::vector<T>& x)
{
size_t dim_in = 5;
auto xx = x;
// transfer interval from [0, 1] to [0, pi]
for (int i = 0; i < dim_in; i++)
xx[i] = M_PI * x[i];
double sum = 0.;
double term = 0.;
double m = 10.;
for(size_t i = 0; i < dim_in; i++)
{
term = std::sin(xx[i]) * std::pow(std::sin(i * xx[i] * xx[i]/M_PI), 2 * m);
sum = sum + term;
}
double obj = sum;
return {obj}; //max= -1.8013(2D) at (2.20,1.57)/-4.687658(5D)/-9.66015(10D)
}
}; I tried to tune the parameters but it always convergence to the local optimal (about 3.69), but the global optimal is 4.6876. Here EA looks for the maximum. I run the experiment ten times. No one is convergence to the global optimal. Can you give me some ideas? |
Hi, Good luck! - this function was designed against GA! We provide the global optimization community with new https://pdfs.semanticscholar.org/6e82/d0cd7acbd55774c131af8941db6c2f84b7ec.pdf AL |
hi, Alanthie, Thank you very much for the share. Could you give me some ideas about this? If you need the configuration of parameters, I will paste it. |
hi, Alanthie, How can I replace the initial individuals with my data? The data format is inline void Chromosome<T>::create()
{
chr.clear();
int i(0);
for (const auto& x : ptr->param)
{
std::string str = x->encode();
chr.append(str);
param[i] = indiv[i];
_sigma[i] = 0.0;
_sigma_iteration[i] = 0;
i++;
}
} Because I think the our EA is start from the |
Hi, In my branch I use the method call like (in void test_ga_binairo(int no = 0)): I dont know if your are able to compile the template class GeneticAlgorithmN in your environment, you had some problem the last time you tried. OR initGene(i, indiv[i]) will init the parameter i AL |
hi, Alanthie, It looks works as follows: inline void Chromosome<T>::create()
{
chr.clear();
int i(0);
for (const auto& x : ptr->param)
{
std::string str = x->encode();
chr.append(str);
T newvalue = (T) indiv[i];
initGene(i, newvalue);
_sigma[i] = 0.0;
_sigma_iteration[i] = 0;
i++;
}
} But I have a question about fitness0gen: -0.208807
fitness0gen: -0.304377
fitness0gen: -0.471944
fitness0gen: -0.499104
fitness0gen: -0.569336
fitness0gen: -0.619478
fitness0gen: -0.646309
fitness0gen: -0.661959
fitness0gen: -0.67193
fitness0gen: -0.678206
fitness0gen: -0.6824
fitness0gen: -0.684969
fitness0gen: -0.687315
fitness0gen: -0.689161
fitness0gen: -0.690344
fitness0gen: -0.69154
fitness0gen: -0.691996
fitness0gen: -0.692465
fitness0gen: -0.693179
fitness0gen: -0.693649
Generation = 0 | X1 = 0.5001509786 | X2 = 0.5007539988 | F(x) = -0.2088071643 The following is the individuals before TNT in second generation. x[0]fitness: -0.2088071643
x[1]fitness: -0.3043769839
x[2]fitness: -0.4719438822
x[3]fitness: -0.4991042813
x[4]fitness: -0.5693364160
x[5]fitness: -0.6194775181
x[6]fitness: -0.6463089924
x[7]fitness: -0.6619587092
x[8]fitness: -0.6719297516
x[9]fitness: -0.6782055116
x[10]fitness: -0.6824004377
x[11]fitness: -0.6849687433
x[12]fitness: -0.6873146298
x[13]fitness: -0.6891614621
x[14]fitness: -0.6903437218
x[15]fitness: -0.6915403313
x[16]fitness: -0.6919958815
x[17]fitness: -0.6924654243
x[18]fitness: -0.6931794691
x[19]fitness: -0.6936492204 We could see they are same. This means the |
hi, Alanthie, Another small question, How can I call I tried to use the following code for testing auto nogens = galgo::GeneticAlgorithm::nogen;
std::cout << "nogen: " << nogens << std::endl; But I got errors as: Evolution.hpp:854:24: error: 'GeneticAlgorithm' is not a class, namespace, or enumeration Thank you very much! |
Hi, chr.nogen() |
hi, Alanthie, nogen: 4
nogen: 4
Nu_evaluation_re: 1 param[0]: 0.5385897160 param[1]: 0.9728716016 fitness: -725.7636153229
Nu_evaluation_re- 2 param[0]: 0.7855494022 param[1]: 0.8774535060 fitness: -896.6737010010
nogen: 0
Nu_evaluation_com: 3 param[0]: 0.4803634286 param[1]: 0.9018497467 fitness: -445.0523364075
nogen: 0
...
Nu_evaluation_com: 12 param[0]: 0.4820629358 param[1]: 0.9322044849 fitness: -418.9475752838
nogen: 2
Nu_evaluation_com: 13 param[0]: 0.5676433444 param[1]: 0.8978191018 fitness: -421.1274363525
nogen: 3
Nu_evaluation_com: 14 param[0]: 0.5507441163 param[1]: 0.0000000000 fitness: -619.5801150330
nogen: 0
Nu_evaluation_com: 15 param[0]: 0.5308289528 param[1]: 0.0000000000 fitness: -677.9540335663
nogen: 3
Nu_evaluation_com: 16 param[0]: 0.5960704088 param[1]: 0.9870103598 fitness: -910.8542277344
nogen: 0
Nu_evaluation_com: 19 param[0]: 0.4062004983 param[1]: 0.8896992207 fitness: -510.7010046967
Generation = 4 | X1 = 0.5664529800 | X2 = 0.9243094921 | F(x) = -356.8659350403 How can I get the nogen that always equal the number of generations? |
hi, Yes chr.nogen() gives nogen when the chromosome was created or copied. Use
AL |
hi, Alanthie, void GAM_sigma_adapting_per_generation(galgo::CHR< T > &chr){
for (int z = 1; z < chr->nogen() / 2; z++)
{
norm01 = distribution01(galgo::rng);
sigma = std::max(double(0), sigma * exp(norm01));
}
} and, I do not understand why we update the sigma with |
Hi, Thanks for the bug. AL |
hi, Alanthie, Still, can you give me some ideas about the following question if you have time. You know, I am learning c++, therefore, I want to figure out how it works.
Thanks a lot! |
Hi, I dont understand your question... void GeneticAlgorithm::run() } AL |
hi, Alanthie,
Thanks a lot! |
Hi, You should print fitness values only after new population evalute() was called. Check code in Population::recombination()
AL |
hi, Alanthie, I am sorry it is not the answer for my question. I think I can describe it better as: for (const auto &x : ptr->param) //this is the iteration for dimension of parameters
{
initGene(i, newvalue); //update value of parameters.
} Why the parameters not be replaced for the different points? The |
Hi, In Galgo, the first chromosome is initialize with value passed, all other are randomly initialized. What is your needs for initializing the starting population? /-------------------------------------------------------------------------------------------------/ /-------------------------------------------------------------------------------------------------/
} /-------------------------------------------------------------------------------------------------/
} -------------------------------------------------------------------------------------------------/ -------------------------------------------------------------------------------------------------/ |
hi, Alanthie, I want to instead of the initial population with my special population that from another algorithm. Therefore, I implemented it based on your suggestion as following: inline void Chromosome<T>::create()
{
chr.clear();
int i(0);
for (const auto& x : ptr->param)
{
std::string str = x->encode();
chr.append(str);
T newvalue = (T) indiv[i]; //this is added, indiv is the special population from another algorithm
initGene(i, newvalue); // this is added, but I do not how it works for different population.
_sigma[i] = 0.0;
_sigma_iteration[i] = 0;
i++;
}
} I know how In addition, I think I understand most of the basic structure of GALGO, although all of them. |
Hi, global_counter = 0; T newvalue = (T) global_indiv[global_counter++]; |
hi, Alanthie, It already worked before. I just not understand how |
Hi, I added the ability to initialize all individuals of the initial population (in my branch). AL |
|
hi, Alanthie,
|
hi, Alanthie, Thanks a lot for your help in these issues. Do you have time to have look at the new issue about galgo? |
hi,
I saw the representation in GALGO is Bit string representation. And then, GALGO converts the bit string into the real-value. Does the GALGO support Real-valued representation? if yes, how can I set up in the GALGO?
Thanks!
The text was updated successfully, but these errors were encountered: