forked from jibsen/galib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathex20.C
182 lines (150 loc) · 5.34 KB
/
ex20.C
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
/* ----------------------------------------------------------------------------
ex20.C
mbwall 5sep95
Copyright (c) 1995-1996 Massachusetts Institute of Technology
DESCRIPTION:
This example runs the royal road problem. See the comments near the
objective functions for details about the function itself.
Some of this was copied (at least partially) from the galopps genetic
algorithm library and from the pga package. I used a bunch of globals in this
example - not good programming style, but it gets the job done.
---------------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <ga/ga.h>
#include <ga/std_stream.h>
#define cout STD_COUT
// This is the objective function for computing Holland's 1993 ICGA version
// of the Royal Road problem. It has been corrected per GAList volume 7
// number 23, 8/26/93. No bonus points are awarded for a given level until
// it has been achieved (this fixes Holland's coding error in GAList).
// Holland posed this problem as a challenge to test the
// performance of genetic algorithms. He indicated that, with the parameter
// settings of
//
// schemata size = 8
// bits between schemata = 7
// m* = 4
// U* = 1.0
// u = 0.3
// v = 0.02
//
// he could attain royal_road_level 3 most of the time within
// 10,000 function evaluations. He challenged other GA users to match or beat
// that performance. He indicated that he used a population size of 512 to
// obtain his solutions, and did NOT use a "simple genetic algorithm."
// The genome for this problem is a single-dimension bit string with length
// defined by the block size and gap size as:
//
// length = (blocksize+gapsize) * (2^K)
//
// where K= 1,2,3, or 4. Holland used K = 4.
#define NBLOCKS 16 // this number is 2^K
const int BLOCKSIZE=8; // block size - length of target schemata
const int GAPSIZE=7; // gap size - number of bits between target schemata
const int MSTAR=4; // Holland's m* - up to this many bits in low level
// block gets reward
const float USTAR=1.0; // Holland's U* - first block earns this
const float RR_U=0.3; // Holland's u - increment for lowest level match
const float RR_V=0.02; // Holland's v - reward/penalty per bit
int nbits = (BLOCKSIZE+GAPSIZE)*NBLOCKS;
int blockarray[NBLOCKS];
int highestLevel=0;
float
RoyalRoad(GAGenome & c){
GA1DBinaryStringGenome & genome = (GA1DBinaryStringGenome &)c;
float score = 0.0;
int total, i, j, index, n;
// do the lowest level blocks first
n = 0;
for(i=0; i<NBLOCKS; i++) {
total = 0;
for(j=i*(BLOCKSIZE + GAPSIZE); j<i*(BLOCKSIZE+GAPSIZE)+BLOCKSIZE; j++)
if(genome.gene(j) == 1) total++; // count the bits in the block
if(total > MSTAR && total < BLOCKSIZE)
score -= (total-MSTAR)*RR_V;
else if(total <= MSTAR)
score += total * RR_V;
if(total == BLOCKSIZE) {
blockarray[i] = 1;
n++;
}
else{
blockarray[i] = 0;
}
}
// bonus for filled low-level blocks
if(n > 0) score += USTAR + (n-1)*RR_U;
// now do the higher-level blocks
n = NBLOCKS; // n is now number of filled low level blocks
int proceed = 1; // should we look at the next higher level?
int level = 0;
while ((n > 1) && proceed) {
proceed = 0;
total = 0;
/* there are n valid blocks in the blockarray each time */
/* round, so n=2 is the last. */
for(i=0,index=0; i<(n/2)*2; i+=2,index++) {
if(blockarray[i] == 1 && blockarray[i+1] == 1) {
total++;
proceed = 1;
blockarray[index] = 1;
}
else{
blockarray[index] = 0;
}
}
if(total > 0){
score += USTAR + (total-1)*RR_U;
level++;
}
n /= 2;
}
if(highestLevel < level) highestLevel = level;
return(score);
}
// The rest of this is standard for the GAlib examples.
int
main(int argc, char *argv[])
{
cout << "Example 20\n\n";
cout << "Running Holland's Royal Road test problem with a genome that is\n";
cout << nbits << " bits long (" << NBLOCKS << " blocks). The parameters ";
cout << "are as follows: \n\n";
cout << "\tblock size: " << BLOCKSIZE << "\n";
cout << "\t gap size: " << GAPSIZE << "\n";
cout << "\t m*: " << MSTAR << "\n";
cout << "\t u*: " << USTAR << "\n";
cout << "\t u: " << RR_U << "\n";
cout << "\t v: " << RR_V << "\n";
cout << "\n\n";
cout.flush();
// See if we've been given a seed to use (for testing purposes). When you
// specify a random seed, the evolution will be exactly the same each time
// you use that seed number.
unsigned int seed = 0;
for(int ii=1; ii<argc; ii++) {
if(strcmp(argv[ii++],"seed") == 0) {
seed = atoi(argv[ii]);
}
}
GA1DBinaryStringGenome genome(nbits, RoyalRoad);
GASteadyStateGA ga(genome);
ga.populationSize(512);
ga.pCrossover(0.9);
ga.pMutation(0.001);
ga.nGenerations(10000);
ga.scoreFilename("bog.dat");
ga.flushFrequency(100);
ga.scoreFrequency(20);
ga.parameters(argc, argv);
GASigmaTruncationScaling trunc;
ga.scaling(trunc);
ga.evolve(seed);
cout << "the ga generated:\n" << ga.statistics().bestIndividual() << "\n";
cout << "the highest level achieved was " << highestLevel << "\n";
cout << "\nthe statistics for the run are:\n" << ga.statistics();
cout << "\nthe parameters for the run are:\n" << ga.parameters();
cout.flush();
return 0;
}