Suppose I have a function y of n variables x[0]..x[n-1]:
y = 1 + a[0][0]*x[0] + a[1][0]*x[0]^2 + a[0][1]*x[1] + a[1][1]*x[1]^2 + ...
I want to find values of variables x[0]..x[n-1], which minimize y. This optimization task will be performed by a genetic algorithm. The basic steps of the algorithm are:
- Generate a pool (population) of random solutions x[0]..x[n-1] (also called chromosomes)
- Evaluate these random solutions y = F(x[0],..,x[n-1])
- Divide the pool solutions into two groups: those with low y (best solutions) and those with high y (poor solutions).
- Throw away poor solutions and breed the best ones by a crossover (swap individual elements x[j] of different solutions).
- Mutate new solutions by adding a random value to selected elements x[j]. We got a new pool of solutions.
- Repeat 2-5 until a stopping criteria is met.
Below is the code of two classes that implement the above algorithm:
The class Solution, which describes an individual solution x[0]..x[n-1], the y value, associated with this solution, and the function y = F(x[0],..,x[n-1]).
The class Pool, which describes the pool of different solutions along with the functions of selection, breeding and mutation.
Here is the code:
class Solution
{
double *x;
double y;
double **a; // the same for all instances
int n; // the same for all instances
public:
Solution(int,double*);
~Solution();
double yFunc();
}
class Pool
{
vector<Solution> sols;
int poolSize;
// other private members
public:
Pool(int,int,double*);
~Pool();
// other public functions
}
// construct Solution
Solution::Solution(int numX,double **coef)
{
n=numX;
// allocate memory for coefficients
a = new double*[2];
for(int i=0;i<2;i++) a[i] = new double[n];
// assign coefficients
for(int i=0;i<2;i++)
for(int j=0;j<n;j++)
a[i][j] = coef[i][j];
// generate a random solution in [-1,+1] range
srand(time(0));
for(int j=0;j<n;j++)
x[j] = 2.0*(rand()/(double)RAND_MAX-0.5);
}
// destroy Solution
Solution::~Solution()
{
delete[] x;
for(int i=0;i<2;i++) delete[] a[i];
delete[] a;
}
// define optimized function
double Solution::yFunc()
{
double sum=1.0;
for(int j=0;j<n;j++)
sum += a[0][j]*x[j]+a[1][j]*x[j]*x[j];
return sum;
}
// construct Pool
Pool::Pool(int numSols, int numX, double **coef)
{
poolSize = numSols;
for(int i=0;i<poolSize;i++)
{
Solution sol = new Solution (numX,coef);
sols.push_back(sol);
}
}
I have only one question:
When I construct the pool of solutions, I create many instances of class Solution with their individual vectors x[0]..x[n-1] and the corresponding function value y. However, the a[][] coefficients of the function y = F(x[0],..,x[n-1]) and the function itself also get instantiated poolSize times even though they are the same for all solution vectors.
How can I modify the code such that only single instances of a[][],F(x[0],..,x[n-1]), and n are created? I heard about static members, but as I understand, a user is not allowed to assign their values through an external function call. These static members can only to be initialized within a class or a static Solution() function that does not except any arguments.
Even if there is a way to initialize these static members with external user-provided values, they are not multi-thread safe. So, I am looking for a way to separate the shared members of class Solution from the individual members, to avoid instantiation of the shared members poolSize times.