diff options
author | Mike Buland <mike@xagasoft.com> | 2012-07-17 09:11:40 -0600 |
---|---|---|
committer | Mike Buland <mike@xagasoft.com> | 2012-07-17 09:11:40 -0600 |
commit | a2679e3bc2f407fae6b97908aeebb215c6678ebc (patch) | |
tree | ac220ef865dc38b6b4a10a03e5d48aad261cddd3 /src/explicitsimulation.cpp | |
parent | a48556c1c5c01892cf493cd3eb4ff969a2f548fd (diff) | |
download | libgenetic-a2679e3bc2f407fae6b97908aeebb215c6678ebc.tar.gz libgenetic-a2679e3bc2f407fae6b97908aeebb215c6678ebc.tar.bz2 libgenetic-a2679e3bc2f407fae6b97908aeebb215c6678ebc.tar.xz libgenetic-a2679e3bc2f407fae6b97908aeebb215c6678ebc.zip |
It all works multi-threaded.
It restarts the threads every generation. Maybe not the worst thing
every, but it seems like it would be better to stay in the thread and
notify the main thread that they're done with that iteration.
Diffstat (limited to 'src/explicitsimulation.cpp')
-rw-r--r-- | src/explicitsimulation.cpp | 130 |
1 files changed, 105 insertions, 25 deletions
diff --git a/src/explicitsimulation.cpp b/src/explicitsimulation.cpp index 281e7e5..6a9356b 100644 --- a/src/explicitsimulation.cpp +++ b/src/explicitsimulation.cpp | |||
@@ -1,17 +1,21 @@ | |||
1 | #include "genetic/explicitsimulation.h" | 1 | #include "genetic/explicitsimulation.h" |
2 | #include "genetic/operator.h" | 2 | #include "genetic/operator.h" |
3 | #include "genetic/fitnessfunction.h" | 3 | #include "genetic/fitnessfunction.h" |
4 | #include "genetic/phenotype.h" | ||
4 | 5 | ||
5 | #include <bu/random.h> | 6 | #include <bu/random.h> |
6 | #include <bu/sio.h> | 7 | #include <bu/sio.h> |
8 | #include <bu/mutexlocker.h> | ||
9 | |||
10 | #include <stdlib.h> | ||
7 | 11 | ||
8 | using namespace Bu; | 12 | using namespace Bu; |
9 | 13 | ||
10 | Genetic::ExplicitSimulation::ExplicitSimulation( Genetic::Operator *pOper, | 14 | Genetic::ExplicitSimulation::ExplicitSimulation( Genetic::Operator *pOper, |
11 | Genetic::FitnessFunction *pFunc, int iPopSize, float fKeep, | 15 | Genetic::FitnessFunction *pFunc, int iThreads, int iPopSize, |
12 | float fRandom, bool bKeepBest ) : | 16 | float fKeep, float fRandom, bool bKeepBest ) : |
13 | pOper( pOper ), | 17 | pOper( pOper ), |
14 | pFunc( pFunc ), | 18 | //pFunc( pFunc ), |
15 | iPopSize( iPopSize ), | 19 | iPopSize( iPopSize ), |
16 | fKeep( fKeep ), | 20 | fKeep( fKeep ), |
17 | fRandom( fRandom ), | 21 | fRandom( fRandom ), |
@@ -22,13 +26,30 @@ Genetic::ExplicitSimulation::ExplicitSimulation( Genetic::Operator *pOper, | |||
22 | xPop.addPhenotype( pOper->random() ); | 26 | xPop.addPhenotype( pOper->random() ); |
23 | } | 27 | } |
24 | 28 | ||
29 | if( iThreads < 1 ) | ||
30 | iThreads = 1; | ||
31 | |||
32 | int iId = 0; | ||
33 | lProcessor.append( new Processor( *this, pFunc, qWork, iId++ ) ); | ||
34 | while( lProcessor.getSize() < iThreads ) | ||
35 | lProcessor.append( | ||
36 | new Processor( *this, pFunc->clone(), qWork, iId++ ) | ||
37 | ); | ||
38 | |||
25 | updateFitness(); | 39 | updateFitness(); |
26 | } | 40 | } |
27 | 41 | ||
28 | Genetic::ExplicitSimulation::~ExplicitSimulation() | 42 | Genetic::ExplicitSimulation::~ExplicitSimulation() |
29 | { | 43 | { |
30 | delete pOper; | 44 | delete pOper; |
31 | delete pFunc; | 45 | |
46 | for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) | ||
47 | (*i)->setRunning( false ); | ||
48 | for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) | ||
49 | { | ||
50 | (*i)->join(); | ||
51 | delete *i; | ||
52 | } | ||
32 | } | 53 | } |
33 | 54 | ||
34 | void Genetic::ExplicitSimulation::timestep() | 55 | void Genetic::ExplicitSimulation::timestep() |
@@ -52,12 +73,15 @@ void Genetic::ExplicitSimulation::timestep() | |||
52 | for( int j = 0; j < iKeep; j++ ) | 73 | for( int j = 0; j < iKeep; j++ ) |
53 | { | 74 | { |
54 | Genetic::PhenotypeId id = selectWeighted(); | 75 | Genetic::PhenotypeId id = selectWeighted(); |
76 | mFitness.lock(); | ||
55 | lNew.append( xPop.takePhenotype( id ) ); | 77 | lNew.append( xPop.takePhenotype( id ) ); |
56 | hTempFitness.insert( id, hFitness.get( id ) ); | 78 | hTempFitness.insert( id, hFitness.get( id ) ); |
57 | hFitness.erase( id ); | 79 | hFitness.erase( id ); |
58 | dTotalFitness -= hTempFitness.get( id ); | 80 | dTotalFitness -= hTempFitness.get( id ); |
81 | mFitness.unlock(); | ||
59 | } | 82 | } |
60 | 83 | ||
84 | mFitness.lock(); | ||
61 | if( bKeepBest && hFitness.has( uMaxFitness ) ) | 85 | if( bKeepBest && hFitness.has( uMaxFitness ) ) |
62 | { | 86 | { |
63 | lNew.append( xPop.takePhenotype( uMaxFitness ) ); | 87 | lNew.append( xPop.takePhenotype( uMaxFitness ) ); |
@@ -65,6 +89,7 @@ void Genetic::ExplicitSimulation::timestep() | |||
65 | hFitness.erase( uMaxFitness ); | 89 | hFitness.erase( uMaxFitness ); |
66 | dTotalFitness -= hTempFitness.get( uMaxFitness ); | 90 | dTotalFitness -= hTempFitness.get( uMaxFitness ); |
67 | } | 91 | } |
92 | mFitness.unlock(); | ||
68 | 93 | ||
69 | // Fill in the remainder with random phenotypes | 94 | // Fill in the remainder with random phenotypes |
70 | while( lNew.getSize() < iPopSize ) | 95 | while( lNew.getSize() < iPopSize ) |
@@ -73,7 +98,9 @@ void Genetic::ExplicitSimulation::timestep() | |||
73 | } | 98 | } |
74 | 99 | ||
75 | // Refill the population | 100 | // Refill the population |
101 | mFitness.lock(); | ||
76 | hFitness = hTempFitness; | 102 | hFitness = hTempFitness; |
103 | mFitness.unlock(); | ||
77 | xPop.clear(); | 104 | xPop.clear(); |
78 | xPop.timestep(); | 105 | xPop.timestep(); |
79 | for( PhenotypeList::iterator i = lNew.begin(); i; i++ ) | 106 | for( PhenotypeList::iterator i = lNew.begin(); i; i++ ) |
@@ -86,6 +113,8 @@ void Genetic::ExplicitSimulation::timestep() | |||
86 | 113 | ||
87 | Genetic::PhenotypeId Genetic::ExplicitSimulation::selectWeighted() | 114 | Genetic::PhenotypeId Genetic::ExplicitSimulation::selectWeighted() |
88 | { | 115 | { |
116 | Bu::MutexLocker ml( mFitness ); | ||
117 | |||
89 | double dSel = Bu::Random::randNorm()*dTotalFitness; | 118 | double dSel = Bu::Random::randNorm()*dTotalFitness; |
90 | double dRun = 0.0; | 119 | double dRun = 0.0; |
91 | 120 | ||
@@ -98,42 +127,93 @@ Genetic::PhenotypeId Genetic::ExplicitSimulation::selectWeighted() | |||
98 | 127 | ||
99 | sio << "Genetic::ExplicitSimulation::selectWeighted() - failed, picked max" | 128 | sio << "Genetic::ExplicitSimulation::selectWeighted() - failed, picked max" |
100 | << sio.nl; | 129 | << sio.nl; |
130 | sio << " " << dMinFitness << " - " << dMaxFitness << " -- " << dTotalFitness << " > " << dRun << " > " << dSel << sio.nl; | ||
131 | abort(); | ||
101 | 132 | ||
102 | return uMaxFitness; | 133 | return uMaxFitness; |
103 | } | 134 | } |
104 | 135 | ||
105 | void Genetic::ExplicitSimulation::updateFitness() | 136 | void Genetic::ExplicitSimulation::updateFitness() |
106 | { | 137 | { |
138 | mFitness.lock(); | ||
107 | dMinFitness = -1.0; | 139 | dMinFitness = -1.0; |
108 | dTotalFitness = 0.0; | 140 | dTotalFitness = 0.0; |
141 | mFitness.unlock(); | ||
142 | |||
109 | for( Population::iterator i = xPop.begin(); i; i++ ) | 143 | for( Population::iterator i = xPop.begin(); i; i++ ) |
110 | { | 144 | { |
111 | double dFitness; | ||
112 | if( hFitness.has( i.getKey() ) ) | 145 | if( hFitness.has( i.getKey() ) ) |
113 | { | 146 | { |
114 | dFitness = hFitness.get( i.getKey() ); | 147 | setFitness( i.getKey(), hFitness.get( i.getKey() ) ); |
115 | } | 148 | } |
116 | else | 149 | else |
117 | { | 150 | { |
118 | dFitness = (*pFunc)( *i ); | 151 | qWork.enqueue( *i ); |
119 | if( dFitness < 0.0 ) | ||
120 | dFitness = 0.0; | ||
121 | hFitness.insert( i.getKey(), dFitness ); | ||
122 | } | ||
123 | dTotalFitness += dFitness; | ||
124 | if( dMinFitness < 0.0 ) | ||
125 | { | ||
126 | dMinFitness = dMaxFitness = dFitness; | ||
127 | uMaxFitness = i.getKey(); | ||
128 | } | ||
129 | else if( dMinFitness > dFitness ) | ||
130 | { | ||
131 | dMinFitness = dFitness; | ||
132 | } | ||
133 | else if( dMaxFitness < dFitness ) | ||
134 | { | ||
135 | dMaxFitness = dFitness; | ||
136 | uMaxFitness = i.getKey(); | ||
137 | } | 152 | } |
138 | } | 153 | } |
154 | |||
155 | for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) | ||
156 | (*i)->start(); | ||
157 | |||
158 | for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) | ||
159 | (*i)->join(); | ||
160 | } | ||
161 | |||
162 | void Genetic::ExplicitSimulation::setFitness( Genetic::PhenotypeId id, | ||
163 | double dFitness ) | ||
164 | { | ||
165 | Bu::MutexLocker ml( mFitness ); | ||
166 | if( dFitness < 0.0 ) | ||
167 | dFitness = 0.0; | ||
168 | |||
169 | // sio << id << ": " << dFitness << sio.nl; | ||
170 | hFitness.insert( id, dFitness ); | ||
171 | |||
172 | dTotalFitness += dFitness; | ||
173 | if( dMinFitness < 0.0 ) | ||
174 | { | ||
175 | dMinFitness = dMaxFitness = dFitness; | ||
176 | uMaxFitness = id; | ||
177 | } | ||
178 | else if( dMinFitness > dFitness ) | ||
179 | { | ||
180 | dMinFitness = dFitness; | ||
181 | } | ||
182 | else if( dMaxFitness < dFitness ) | ||
183 | { | ||
184 | dMaxFitness = dFitness; | ||
185 | uMaxFitness = id; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | Genetic::ExplicitSimulation::Processor::Processor( | ||
190 | Genetic::ExplicitSimulation &rSim, | ||
191 | Genetic::FitnessFunction *pFunc, | ||
192 | Genetic::ExplicitSimulation::WorkQueue &rqWork, | ||
193 | int iId ) : | ||
194 | rSim( rSim ), | ||
195 | pFunc( pFunc ), | ||
196 | rqWork( rqWork ), | ||
197 | iId( iId ) | ||
198 | { | ||
199 | } | ||
200 | |||
201 | Genetic::ExplicitSimulation::Processor::~Processor() | ||
202 | { | ||
203 | delete pFunc; | ||
204 | } | ||
205 | |||
206 | void Genetic::ExplicitSimulation::Processor::run() | ||
207 | { | ||
208 | bRunning = true; | ||
209 | while( bRunning && !rqWork.isEmpty() ) | ||
210 | { | ||
211 | Genetic::Phenotype *pPhen = rqWork.dequeue( 0, 250000 ); | ||
212 | if( pPhen == NULL ) | ||
213 | continue; | ||
214 | |||
215 | double dFitness = (*pFunc)( pPhen ); | ||
216 | rSim.setFitness( pPhen->getId(), dFitness ); | ||
217 | } | ||
139 | } | 218 | } |
219 | |||