variable nested "for" loop

Pages: 12
This code is used in scientific calculation for optimization problem.

Basically a particle is moving in a three dimensional space, its position is (x,y,z).
At each position, there is a fitness value associated with that position.
The fitness value is given by fitness(x,y,z) (code line 12~19).

We need to find out, when the particle moves around randomly, what is the highest possible fitness value.

To solve this, below code is used, and it produces correct result.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#define DIMENSION 3
#define MAXX 4
#define MINX 0
#define MESHsize 1

#include <iostream>
using namespace std;

float maxValue = 0.0;
float X[DIMENSION];

int fitness( float X[] )    // arbitrary function
{
    int total = 0;
    for (int i=0; i < DIMENSION; i++)
        total += X[i] * X[i] ;

    return total;
}

void findMaxValue ( const int level = 0, int x1 = 0, int x2 = 0, int x3 = 0 )
{
    if ( level < DIMENSION )
    {
        for (int i=MINX; i < MAXX; i += MESHsize)
        {
            switch (level)
             {
                case 0:
                    x1 = i;
                    break;

                case 1:
                    x2 = i;
                    break;

                case 2:
                    x3 = i;
                    break;
             }

            findMaxValue( level + 1, x1, x2, x3 );
        }

        cout << endl;
    }

    else
    {
        X[0] = x1;
        X[1] = x2;
        X[2] = x3;
        float answer = fitness(X);

        cout << "[ fitness(" << x1 << "," << x2 << "," << x3 << ") = " << answer << "]  ";

        if ( answer > maxValue )
            maxValue = answer;
    }
}


int main()
{
    findMaxValue();
    cout << "Answer: highest fitness = " << maxValue << endl;
}


The output of the code:


[ fitness(0,0,0) = 0]  [ fitness(0,0,1) = 1]  [ fitness(0,0,2) = 4]  [ fitness(0,0,3) = 9]  
[ fitness(0,1,0) = 1]  [ fitness(0,1,1) = 2]  [ fitness(0,1,2) = 5]  [ fitness(0,1,3) = 10]  
[ fitness(0,2,0) = 4]  [ fitness(0,2,1) = 5]  [ fitness(0,2,2) = 8]  [ fitness(0,2,3) = 13]  
[ fitness(0,3,0) = 9]  [ fitness(0,3,1) = 10]  [ fitness(0,3,2) = 13]  [ fitness(0,3,3) = 18]  

[ fitness(1,0,0) = 1]  [ fitness(1,0,1) = 2]  [ fitness(1,0,2) = 5]  [ fitness(1,0,3) = 10]  
[ fitness(1,1,0) = 2]  [ fitness(1,1,1) = 3]  [ fitness(1,1,2) = 6]  [ fitness(1,1,3) = 11]  
[ fitness(1,2,0) = 5]  [ fitness(1,2,1) = 6]  [ fitness(1,2,2) = 9]  [ fitness(1,2,3) = 14]  
[ fitness(1,3,0) = 10]  [ fitness(1,3,1) = 11]  [ fitness(1,3,2) = 14]  [ fitness(1,3,3) = 19]  

[ fitness(2,0,0) = 4]  [ fitness(2,0,1) = 5]  [ fitness(2,0,2) = 8]  [ fitness(2,0,3) = 13]  
[ fitness(2,1,0) = 5]  [ fitness(2,1,1) = 6]  [ fitness(2,1,2) = 9]  [ fitness(2,1,3) = 14]  
[ fitness(2,2,0) = 8]  [ fitness(2,2,1) = 9]  [ fitness(2,2,2) = 12]  [ fitness(2,2,3) = 17]  
[ fitness(2,3,0) = 13]  [ fitness(2,3,1) = 14]  [ fitness(2,3,2) = 17]  [ fitness(2,3,3) = 22]  

[ fitness(3,0,0) = 9]  [ fitness(3,0,1) = 10]  [ fitness(3,0,2) = 13]  [ fitness(3,0,3) = 18]  
[ fitness(3,1,0) = 10]  [ fitness(3,1,1) = 11]  [ fitness(3,1,2) = 14]  [ fitness(3,1,3) = 19]  
[ fitness(3,2,0) = 13]  [ fitness(3,2,1) = 14]  [ fitness(3,2,2) = 17]  [ fitness(3,2,3) = 22]  
[ fitness(3,3,0) = 18]  [ fitness(3,3,1) = 19]  [ fitness(3,3,2) = 22]  [ fitness(3,3,3) = 27]  


Answer: highest fitness = 27


Note: In this case, the values of x,y and z is integers from 0 to 3 inclusive.

For 3-dimensional space above, actually the code had run through 3 nested "for" loops.

Question:
Above code works for 3-dimensional space.
How to generalize the code, so that it works also for N-dimensional space, where N is an arbitrary integer?
( Note: possibly N = 30 )
Last edited on
You may f.e. define a class Particle as follows. An object will be parametrized with DIMENSION on its creation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Particle
{
private:
    static const size_t DFLT_DIMENSION = 3;
    static const size_t MAXX = 4;
    static const size_t MINX = 0;
    static const size_t MESHsize = 1;

private:
    const size_t DIMENSION;

    float maxValue;
    float *X;

private:
    int fitness( float X[] );    // arbitrary function

public:
    // initializes all variable attributes
    Particle(size_t dimension = DFLT_DIMENSION);

    void findMaxValue ( const int level = 0, int x1 = 0, int x2 = 0, int x3 = 0 );

};

int Particle::fitness( float X[] )
{
    // ...
}

// ... and so on ... 


Additionally you may use generics (C++ templates) to speed up execution time by giving DIMENSION as generic parameter. See http://www.cplusplus.com/doc/tutorial/templates/.
(I didn't checked for syntax errors, sorry)
Hi tcs,

The problem didn't seem to be solved.

The DIMENSION is an integer that is fixed before the program starts. We don't need to put it as an argument in the nested constructor.

The problem is at here:
1
2
void findMaxValue ( const int level = 0, int x1 = 0, int x2 = 0, int x3 = 0 )
 { ... }


If 30 dimensional space is used, then I have to write 30 arguments:
1
2
void findMaxValue ( const int level = 0, int x1 = 0, int x2 = 0, ....., int x30 = 0 )
 { ... }


Also, I have to write 30 arguments here:
findMaxValue( level + 1, x1, x2, x3, ...., x30 );

Also, I have to write 30 cases here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
           
switch (level)
  {
          case 0:
               x1 = i;
               break;

           case 1:
               x2 = i;
               break;

           case 2:
               x3 = i;
               break;
          .....
          .....
            case 29:
                x30 = i;
                break;


And also, I have to write 30 lines of this:
1
2
3
4
5
        X[0] = x1;
        X[1] = x2;
        X[2] = x3;
        ......
        X[29] = x30;


So I am looking for another way to write the code, so that I do not need to write multiple of 30 lines above.
(Please note that the initial code already works for 3 dimensional space, but not yet for 30 dimensional space)
Thanks.
Last edited on
Well, having 30 arguments named x1, x2,... x30 is silly. Just have a vector x that is sized dynamically to store the same number of ints as there are dimensions. Then you can pass the vector into findMaxValue. You won't need a switch/case statement at all - you can just use x[level] = i, and you can loop over the number of dimensions, setting X[i] = x[i].

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;

typedef vector<float> FloatVec;

#define DIMENSION 3
#define MAXX 4
#define MINX 0
#define MESHsize 1

float maxValue = 0.0;

int fitness(FloatVec x)    // arbitrary function
{
    int total = 0;
    for (int i = 0; i < DIMENSION; i++)
        total += x[i] * x[i] ;

    return total;

} /* fitness() */
     
void findMaxValue(const int level, FloatVec &x)
{
    if (level < x.size())
    {
        for (int i = MINX; i < MAXX; i += MESHsize)
        {
            x[level] = i;
            findMaxValue(level + 1, x);
        }
        cout << endl;
    }
    else
    {
        float answer = fitness(x);

        const char *sep = "";
        cout << "[ fitness(";
        for (size_t i = 0; i < x.size(); ++i)
        {
            cout << sep << x[i]; 
            sep = ",";
        }
        cout << ") = " << answer << "]  ";
    
        if ( answer > maxValue )
            maxValue = answer;
    }

} /* findMaxValue() */


And call it like:

1
2
3
4
FloatVec x(DIMENSION, 0.0);

findMaxValue(0, x);
cout << "Answer: highest fitness = " << maxValue << endl;
Dear tcs and MikeyBoy,

Thanks. It works perfectly !
Just that we don't really need to use vector in this case, because the value of DIMENSION is fixed during the program execution.

So I've modified your code accordingly, as below.
It produces the same result, without using vector.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
using std::cout;
using std::endl;

#define DIMENSION 3
#define MAXX 4
#define MINX 0
#define MESHsize 1

float maxValue = 0.0;

int fitness( float x[] )    // arbitrary function
{
    int total = 0;
    for (int i = 0; i < DIMENSION; i++)
        total += x[i] * x[i] ;

    return total;

} /* fitness() */


void findMaxValue(const int level, float x[] )
{
    if (level < DIMENSION)
    {
        for (int i = MINX; i < MAXX; i += MESHsize)
        {
            x[level] = i;
            findMaxValue(level + 1, x);
        }
        cout << endl;
    }
    else
    {
        float answer = fitness(x);

        const char *sep = "";
        cout << "[ fitness(";
        for (size_t i = 0; i < DIMENSION; ++i)
        {
            cout << sep << x[i];
            sep = ",";
        }
        cout << ") = " << answer << "]  ";

        if ( answer > maxValue )
            maxValue = answer;
    }

} /* findMaxValue() */


int main ()
{
    float x[DIMENSION];
    for (int i=0; i < DIMENSION; i++)
        x[i] = 0.0;

    findMaxValue(0, x);
    cout << "Answer: highest fitness = " << maxValue << endl;
}


Thank you very much.
Last edited on
You're welcome. Glad it worked :)

Although I'd advise you to get into the habit of using vectors rather than arrays in general. They're a lot safer and more powerful, and you won't regret it.
Last edited on
Yes, I'm convinced. Now I believe vector is better than array.
http://www.parashift.com/c++-faq/arrays-are-evil.html
Today I have tried using vectors rather than arrays in a program.
A big performance penalty!

Using arrays gain 48 iterations per second,
whereas using vectors gain 12 iterations per second.
(the more iterations per second, the better)

It is fourfold difference in performance !
Vector really slows down significantly if it is used extensively.
Last edited on
If you are miss-using a vector or not compiling with optimizations the of course it will cause slowdown. Make sure you always test with optimizations (because when wouldn't you use optimizations?)
How to compile with optimization for vector?
For most compilers it is the -O flag, e.g. -O0 for no optimizations, generally up to -O3 for maximum optimizations.
Using vector with -O3 it improves to 33 iterations per second.

Using arrays without optimization gains 48 iterations per second.
Using arrays with -O3 gains 66 iterations per second.
Last edited on
I'm not seeing the same results, can you post your test cases?
Below is part of the project.
The function float z_value(int x, int y) is called 40,000 times in each iteration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230


float z_value(int x, int y)
{
    vector <float> tempX (dimension, 0.0);
    tempX[0] = x; tempX[1] = y;

    return z_value( tempX );
}


float z_value( vector <float> X )
{
    return z_value( calc_fitness(X) );
}


float z_value( float fitness )
{
    float maxAbsolute = std::max( maxFuncFitness, -minFuncFitness );

    if ( maxAbsolute > 0.0 )
        return fitness * (float) maxX / ( maxAbsolute ) / 4.0 ;
    else
        return 0.0;
}


float normalizeX(float x)
{
    switch (functionSelect)
    {
        case 1:  // Rastrigin's function
            return x * 5.12 / (float) maxX;
            break;

        case 2:  // De Jong 1's function
            return x * 5.12 / (float) maxX;
            break;

        case 3:  // Rosenbrock function (De Jong 2)
            return x * 2.048 / (float) maxX;
            break;

        case 4:  // Ackley's function
            return x * 32.768 / (float) maxX;
            break;

        case 5:  // Shubert's function
            return x * 10.28 / (float) maxX;
            break;

        case 6:  // Griewangk's function
            //return x * 600.0 / (float) MAXx;
            return x * 80.0 / (float) maxX;
            break;

        default:
            return 0.0;
    }
}

float calc_fitness( vector <float> X )
{
    float fitness = 0.0;
    switch(functionSelect)
    {
        case 1:
            fitness = Rastrigin_func(X);
            break;

        case 2:
            fitness = DeJong1(X);
            break;

        case 3:
            fitness = Rosenbrock_func(X);
            break;

        case 4:
            fitness = Ackley_func(X);
            break;

        case 5:
            fitness = Shubert_func(X);
            break;

        case 6:
            fitness = Griewangk_func(X);
            break;

        default:
            fitness = 0.0;
            break;
    }

    if      (fitness > maxFuncFitness)
    {
        maxFuncFitness = fitness;
        if (!verbose)
            cout << "new maxFuncFitness value is " << maxFuncFitness << " at (" << X[0] << ", " << X[1] << ")" << endl;
    }

    else if (fitness < minFuncFitness)
    {
        minFuncFitness = fitness;
        if (!verbose)
            cout << " new minFuncFitness value is " << minFuncFitness << " at (" << X[0] << ", " << X[1] << ")" << endl;
    }

    return fitness;
}




float Rastrigin_func( vector <float> X )          // function no. 1
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum = 10.0 * dimension;
    for (int i=0; i < dimension; i++)
    {
        if (online) sum += SQUARE(XX[i]) - 10 * cos( 2 * pi * XX[i] + onlineCounter/10.0 );
        else        sum += SQUARE(XX[i]) - 10 * cos( 2 * pi * XX[i] );
    }
    return sum;
}



float DeJong1( vector <float> X )            // function no. 2
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum = 0.0;
    for (int i=0; i < dimension; i++)
    {
        if (online) sum += SQUARE( XX[i] + 2 * sin( onlineCounter/10.0) );
        else        sum += SQUARE( XX[i] );
    }
    return sum;
}


float Rosenbrock_func( vector <float> X )         // function no. 3
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum =0.0;
    for (int i=0; i < dimension - 1; i++)
    {
        if (online) sum += 100 * SQUARE( XX[i+1] - SQUARE(XX[i]) + sin(onlineCounter/10.0) ) + SQUARE( 1 - XX[i] );
        else        sum += 100 * SQUARE( XX[i+1] - SQUARE(XX[i])                           ) + SQUARE( 1 - XX[i] );
    }
    return sum;
}


float Ackley_func( vector <float> X )            // function no. 4
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float a;
    if (online)  a = 20.0 * cos(onlineCounter/10.0);
    else         a = 20.0;

    float b =  0.2;
    float c =    2 * pi ;

    float sum1 = 0.0;
    float sum2 = 0.0;
    for (int i=0; i < dimension; i++)
    {
        sum1 += SQUARE(XX[i]);
        sum2 += cos( c * XX[i] );
    }
    return -a * exp( -b * sqrt(sum1/dimension) ) - exp( sum2/dimension ) + exp(1) ;
}


float Shubert_func( vector <float> X )    // function no. 5
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float total = 1.0;
    float sum   = 0.0;

    for (int i=0; i < dimension; i++)
    {
        sum = 0.0;
        for (int j=1; j < 6; j++)
            if (online)  sum += j * cos( (j+1) * XX[i] + j + onlineCounter/10.0 );
            else         sum += j * cos( (j+1) * XX[i] + j );
        total *= sum;
    }
    return total;
}



float Griewangk_func( vector <float> X )   // function no. 6
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum = 0.0;
    float product = 1.0;

    for (int i=0; i < dimension; i++)
    {
        sum += SQUARE(XX[i]);
        if (online) product *= cos( ( XX[i] + onlineCounter/10.0 )/ sqrt(i+1) );
        else        product *= cos(   XX[i]                       / sqrt(i+1) );
    }
    return sum/4000.0 - product + 1;
}

And where is your array test case?
Above is using vector. It is part of a program. When compiled and run, the program runs at 12 iterations per second.
Then all vectors were changed back to arrays, as follows. When compiled and run, the program runs at 48 iterations per second.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
float z_value(int x, int y)
{
    float tempX[dimension];
    for (int i=0; i < dimension; i++)
        tempX[i] = 0.0;

    tempX[0] = x; tempX[1] = y;

    return z_value( tempX );
}


float z_value( float X[] )
{
    return z_value( calc_fitness(X) );
}


float z_value( float fitness )
{
    float maxAbsolute = std::max( maxFuncFitness, -minFuncFitness );

    if ( maxAbsolute > 0.0 )
        return fitness * (float) maxX / ( maxAbsolute ) / 4.0 ;
    else
        return 0.0;
}


float normalizeX(float x)
{
    switch (functionSelect)
    {
        case 1:  // Rastrigin's function
            return x * 5.12 / (float) maxX;
            break;

        case 2:  // De Jong 1's function
            return x * 5.12 / (float) maxX;
            break;

        case 3:  // Rosenbrock function (De Jong 2)
            return x * 2.048 / (float) maxX;
            break;

        case 4:  // Ackley's function
            return x * 32.768 / (float) maxX;
            break;

        case 5:  // Shubert's function
            return x * 10.28 / (float) maxX;
            break;

        case 6:  // Griewangk's function
            //return x * 600.0 / (float) MAXx;
            return x * 80.0 / (float) maxX;
            break;

        default:
            return 0.0;
    }
}

float calc_fitness( float X[] )
{
    float fitness = 0.0;
    switch(functionSelect)
    {
        case 1:
            fitness = Rastrigin_func(X);
            break;

        case 2:
            fitness = DeJong1(X);
            break;

        case 3:
            fitness = Rosenbrock_func(X);
            break;

        case 4:
            fitness = Ackley_func(X);
            break;

        case 5:
            fitness = Shubert_func(X);
            break;

        case 6:
            fitness = Griewangk_func(X);
            break;

        default:
            fitness = 0.0;
            break;
    }

    if      (fitness > maxFuncFitness)
    {
        maxFuncFitness = fitness;
        if (!verbose)
            cout << "new maxFuncFitness value is " << maxFuncFitness << " at (" << X[0] << ", " << X[1] << ")" << endl;
    }

    else if (fitness < minFuncFitness)
    {
        minFuncFitness = fitness;
        if (!verbose)
            cout << " new minFuncFitness value is " << minFuncFitness << " at (" << X[0] << ", " << X[1] << ")" << endl;
    }

    return fitness;
}




float Rastrigin_func( float X[] )          // function no. 1
{
    float XX[dimension];
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum = 10.0 * dimension;
    for (int i=0; i < dimension; i++)
    {
        if (online) sum += SQUARE(XX[i]) - 10 * cos( 2 * pi * XX[i] + onlineCounter/10.0 );
        else        sum += SQUARE(XX[i]) - 10 * cos( 2 * pi * XX[i] );
    }
    return sum;
}



float DeJong1( float X[] )            // function no. 2
{
    float XX[dimension];
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum = 0.0;
    for (int i=0; i < dimension; i++)
    {
        if (online) sum += SQUARE( XX[i] + 2 * sin( onlineCounter/10.0) );
        else        sum += SQUARE( XX[i] );
    }
    return sum;
}


float Rosenbrock_func( float X[] )         // function no. 3
{
    float XX[dimension];
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum =0.0;
    for (int i=0; i < dimension - 1; i++)
    {
        if (online) sum += 100 * SQUARE( XX[i+1] - SQUARE(XX[i]) + sin(onlineCounter/10.0) ) + SQUARE( 1 - XX[i] );
        else        sum += 100 * SQUARE( XX[i+1] - SQUARE(XX[i])                           ) + SQUARE( 1 - XX[i] );
    }
    return sum;
}


float Ackley_func( float X[] )            // function no. 4
{
    float XX[dimension];
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float a;
    if (online)  a = 20.0 * cos(onlineCounter/10.0);
    else         a = 20.0;

    float b =  0.2;
    float c =    2 * pi ;

    float sum1 = 0.0;
    float sum2 = 0.0;
    for (int i=0; i < dimension; i++)
    {
        sum1 += SQUARE(XX[i]);
        sum2 += cos( c * XX[i] );
    }
    return -a * exp( -b * sqrt(sum1/dimension) ) - exp( sum2/dimension ) + exp(1) ;
}


float Shubert_func( float X[] )    // function no. 5
{
    float XX[dimension];
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float total = 1.0;
    float sum   = 0.0;

    for (int i=0; i < dimension; i++)
    {
        sum = 0.0;
        for (int j=1; j < 6; j++)
            if (online)  sum += j * cos( (j+1) * XX[i] + j + onlineCounter/10.0 );
            else         sum += j * cos( (j+1) * XX[i] + j );
        total *= sum;
    }
    return total;
}



float Griewangk_func( float X[] )   // function no. 6
{
    float XX[dimension];
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum = 0.0;
    float product = 1.0;

    for (int i=0; i < dimension; i++)
    {
        sum += SQUARE(XX[i]);
        if (online) product *= cos( ( XX[i] + onlineCounter/10.0 )/ sqrt(i+1) );
        else        product *= cos(   XX[i]                       / sqrt(i+1) );
    }
    return sum/4000.0 - product + 1;
}
Last edited on
12
13
14
15
float z_value( vector <float> X )
{
    return z_value( calc_fitness(X) );
}
Is notequivalent to
13
14
15
16
float z_value( float X[] )
{
    return z_value( calc_fitness(X) );
}


With the vector, you are passing by value, which involves a copy.
With the array, you are passing a pointer to the first element in the array, which is like passing the vector by reference.

You do this throughout all your code. It is not a fair comparison.
Thanks for pointing out.
So I've changed it to passing-by-reference.
By doing this its performance increases 2X.

Using vector (pass by reference) without optimization, it gains 23 iterations per second
Using vector (pass by reference) with optimization -O3, it gains 49 iterations per second.

In contrast,
Using arrays without optimization, it gains 48 iterations per second.
Using arrays with optimization -O3, it gains 66 iterations per second.

Probably it is already very good for vector.
Nevertheless I try to avoid compilation with optimization -O3 during the development stage.


Below is the modified code being used, for passing vector by reference.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

float z_value(int x, int y)
{
    vector <float> tempX (dimension, 0.0);
    tempX[0] = x; tempX[1] = y;

    return z_value( tempX );
}


float z_value( vector <float> & X )
{
    return z_value( calc_fitness(X) );
}


float z_value( float fitness )
{
    float maxAbsolute = std::max( maxFuncFitness, -minFuncFitness );

    if ( maxAbsolute > 0.0 )
        return fitness * (float) maxX / ( maxAbsolute ) / 4.0 ;
    else
        return 0.0;
}


float normalizeX(float x)
{
    switch (functionSelect)
    {
        case 1:  // Rastrigin's function
            return x * 5.12 / (float) maxX;
            break;

        case 2:  // De Jong 1's function
            return x * 5.12 / (float) maxX;
            break;

        case 3:  // Rosenbrock function (De Jong 2)
            return x * 2.048 / (float) maxX;
            break;

        case 4:  // Ackley's function
            return x * 32.768 / (float) maxX;
            break;

        case 5:  // Shubert's function
            return x * 10.28 / (float) maxX;
            break;

        case 6:  // Griewangk's function
            //return x * 600.0 / (float) MAXx;
            return x * 80.0 / (float) maxX;
            break;

        default:
            return 0.0;
    }
}

float calc_fitness( vector <float> & X )
{
    float fitness = 0.0;
    switch(functionSelect)
    {
        case 1:
            fitness = Rastrigin_func(X);
            break;

        case 2:
            fitness = DeJong1(X);
            break;

        case 3:
            fitness = Rosenbrock_func(X);
            break;

        case 4:
            fitness = Ackley_func(X);
            break;

        case 5:
            fitness = Shubert_func(X);
            break;

        case 6:
            fitness = Griewangk_func(X);
            break;

        default:
            fitness = 0.0;
            break;
    }

    if      (fitness > maxFuncFitness)
    {
        maxFuncFitness = fitness;
        if (!verbose)
            cout << "new maxFuncFitness value is " << maxFuncFitness << " at (" << X[0] << ", " << X[1] << ")" << endl;
    }

    else if (fitness < minFuncFitness)
    {
        minFuncFitness = fitness;
        if (!verbose)
            cout << " new minFuncFitness value is " << minFuncFitness << " at (" << X[0] << ", " << X[1] << ")" << endl;
    }

    return fitness;
}




float Rastrigin_func( vector <float> & X )          // function no. 1
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum = 10.0 * dimension;
    for (int i=0; i < dimension; i++)
    {
        if (online) sum += SQUARE(XX[i]) - 10 * cos( 2 * pi * XX[i] + onlineCounter/10.0 );
        else        sum += SQUARE(XX[i]) - 10 * cos( 2 * pi * XX[i] );
    }
    return sum;
}



float DeJong1( vector <float> & X )            // function no. 2
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum = 0.0;
    for (int i=0; i < dimension; i++)
    {
        if (online) sum += SQUARE( XX[i] + 2 * sin( onlineCounter/10.0) );
        else        sum += SQUARE( XX[i] );
    }
    return sum;
}


float Rosenbrock_func( vector <float> & X )         // function no. 3
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum =0.0;
    for (int i=0; i < dimension - 1; i++)
    {
        if (online) sum += 100 * SQUARE( XX[i+1] - SQUARE(XX[i]) + sin(onlineCounter/10.0) ) + SQUARE( 1 - XX[i] );
        else        sum += 100 * SQUARE( XX[i+1] - SQUARE(XX[i])                           ) + SQUARE( 1 - XX[i] );
    }
    return sum;
}


float Ackley_func( vector <float> & X )            // function no. 4
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float a;
    if (online)  a = 20.0 * cos(onlineCounter/10.0);
    else         a = 20.0;

    float b =  0.2;
    float c =    2 * pi ;

    float sum1 = 0.0;
    float sum2 = 0.0;
    for (int i=0; i < dimension; i++)
    {
        sum1 += SQUARE(XX[i]);
        sum2 += cos( c * XX[i] );
    }
    return -a * exp( -b * sqrt(sum1/dimension) ) - exp( sum2/dimension ) + exp(1) ;
}


float Shubert_func( vector <float> & X )    // function no. 5
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float total = 1.0;
    float sum   = 0.0;

    for (int i=0; i < dimension; i++)
    {
        sum = 0.0;
        for (int j=1; j < 6; j++)
            if (online)  sum += j * cos( (j+1) * XX[i] + j + onlineCounter/10.0 );
            else         sum += j * cos( (j+1) * XX[i] + j );
        total *= sum;
    }
    return total;
}



float Griewangk_func( vector <float> & X )   // function no. 6
{
    vector <float> XX(dimension, 0.0);
    for (int i=0; i < dimension; i++)
        XX[i] = normalizeX(X[i]);

    float sum = 0.0;
    float product = 1.0;

    for (int i=0; i < dimension; i++)
    {
        sum += SQUARE(XX[i]);
        if (online) product *= cos( ( XX[i] + onlineCounter/10.0 )/ sqrt(i+1) );
        else        product *= cos(   XX[i]                       / sqrt(i+1) );
    }
    return sum/4000.0 - product + 1;
}
Last edited on
Pages: 12