summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <mike@xagasoft.com>2012-07-17 09:11:40 -0600
committerMike Buland <mike@xagasoft.com>2012-07-17 09:11:40 -0600
commita2679e3bc2f407fae6b97908aeebb215c6678ebc (patch)
treeac220ef865dc38b6b4a10a03e5d48aad261cddd3
parenta48556c1c5c01892cf493cd3eb4ff969a2f548fd (diff)
downloadlibgenetic-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.
-rw-r--r--src/explicitsimulation.cpp130
-rw-r--r--src/explicitsimulation.h35
-rw-r--r--src/fitnessfunction.h1
-rw-r--r--src/tests/maxima/fitnessfunctioneq.cpp5
-rw-r--r--src/tests/maxima/fitnessfunctioneq.h1
-rw-r--r--src/tests/maxima/main.cpp1
6 files changed, 146 insertions, 27 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
8using namespace Bu; 12using namespace Bu;
9 13
10Genetic::ExplicitSimulation::ExplicitSimulation( Genetic::Operator *pOper, 14Genetic::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
28Genetic::ExplicitSimulation::~ExplicitSimulation() 42Genetic::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
34void Genetic::ExplicitSimulation::timestep() 55void 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
87Genetic::PhenotypeId Genetic::ExplicitSimulation::selectWeighted() 114Genetic::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
105void Genetic::ExplicitSimulation::updateFitness() 136void 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
162void 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
189Genetic::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
201Genetic::ExplicitSimulation::Processor::~Processor()
202{
203 delete pFunc;
204}
205
206void 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
diff --git a/src/explicitsimulation.h b/src/explicitsimulation.h
index ebddd62..c2aeed9 100644
--- a/src/explicitsimulation.h
+++ b/src/explicitsimulation.h
@@ -4,6 +4,10 @@
4#include "genetic/population.h" 4#include "genetic/population.h"
5#include "genetic/config.h" 5#include "genetic/config.h"
6 6
7#include <bu/thread.h>
8#include <bu/mutex.h>
9#include <bu/synchroqueue.h>
10
7namespace Genetic 11namespace Genetic
8{ 12{
9 class Operator; 13 class Operator;
@@ -13,7 +17,8 @@ namespace Genetic
13 { 17 {
14 public: 18 public:
15 ExplicitSimulation( Operator *pOper, FitnessFunction *pFunc, 19 ExplicitSimulation( Operator *pOper, FitnessFunction *pFunc,
16 int iPopSize, float fKeep, float fRandom, bool bKeepBest=true ); 20 int iThreads, int iPopSize, float fKeep, float fRandom,
21 bool bKeepBest=true );
17 virtual ~ExplicitSimulation(); 22 virtual ~ExplicitSimulation();
18 23
19 void timestep(); 24 void timestep();
@@ -25,11 +30,11 @@ namespace Genetic
25 30
26 protected: 31 protected:
27 void updateFitness(); 32 void updateFitness();
33 void setFitness( Genetic::PhenotypeId, double dFitness );
28 34
29 protected: 35 protected:
30 Population xPop; 36 Population xPop;
31 Operator *pOper; 37 Operator *pOper;
32 FitnessFunction *pFunc;
33 38
34 private: 39 private:
35 int iPopSize; 40 int iPopSize;
@@ -42,6 +47,32 @@ namespace Genetic
42 double dMaxFitness; 47 double dMaxFitness;
43 double dTotalFitness; 48 double dTotalFitness;
44 PhenotypeId uMaxFitness; 49 PhenotypeId uMaxFitness;
50
51 Bu::Mutex mFitness;
52 typedef Bu::SynchroQueue<Phenotype *> WorkQueue;
53 WorkQueue qWork;
54
55 class Processor : public Bu::Thread
56 {
57 public:
58 Processor( ExplicitSimulation &rSim, FitnessFunction *pFunc,
59 WorkQueue &rqWork, int iId );
60 virtual ~Processor();
61
62 void setRunning( bool b ) { bRunning = b; }
63
64 protected:
65 virtual void run();
66
67 ExplicitSimulation &rSim;
68 FitnessFunction *pFunc;
69 WorkQueue &rqWork;
70 int iId;
71 bool bRunning;
72 };
73
74 typedef Bu::List<Processor *> ProcessorList;
75 ProcessorList lProcessor;
45 }; 76 };
46}; 77};
47 78
diff --git a/src/fitnessfunction.h b/src/fitnessfunction.h
index c41f733..0f852fa 100644
--- a/src/fitnessfunction.h
+++ b/src/fitnessfunction.h
@@ -12,6 +12,7 @@ namespace Genetic
12 virtual ~FitnessFunction(); 12 virtual ~FitnessFunction();
13 13
14 virtual double operator()( Phenotype *pTest )=0; 14 virtual double operator()( Phenotype *pTest )=0;
15 virtual FitnessFunction *clone() const=0;
15 }; 16 };
16}; 17};
17 18
diff --git a/src/tests/maxima/fitnessfunctioneq.cpp b/src/tests/maxima/fitnessfunctioneq.cpp
index 5694507..c64e87a 100644
--- a/src/tests/maxima/fitnessfunctioneq.cpp
+++ b/src/tests/maxima/fitnessfunctioneq.cpp
@@ -23,3 +23,8 @@ double FitnessFunctionEq::operator()( Genetic::Phenotype *pTest )
23 return -1.8*(x*x*x*x) + 0.86*(x*x*x) + 4.0*(x*x); 23 return -1.8*(x*x*x*x) + 0.86*(x*x*x) + 4.0*(x*x);
24} 24}
25 25
26Genetic::FitnessFunction *FitnessFunctionEq::clone() const
27{
28 return new FitnessFunctionEq();
29}
30
diff --git a/src/tests/maxima/fitnessfunctioneq.h b/src/tests/maxima/fitnessfunctioneq.h
index 7139532..d1a64c5 100644
--- a/src/tests/maxima/fitnessfunctioneq.h
+++ b/src/tests/maxima/fitnessfunctioneq.h
@@ -10,6 +10,7 @@ public:
10 virtual ~FitnessFunctionEq(); 10 virtual ~FitnessFunctionEq();
11 11
12 virtual double operator()( Genetic::Phenotype *pTest ); 12 virtual double operator()( Genetic::Phenotype *pTest );
13 virtual Genetic::FitnessFunction *clone() const;
13}; 14};
14 15
15#endif 16#endif
diff --git a/src/tests/maxima/main.cpp b/src/tests/maxima/main.cpp
index ec02a41..db11f66 100644
--- a/src/tests/maxima/main.cpp
+++ b/src/tests/maxima/main.cpp
@@ -23,6 +23,7 @@ int main( int argc, char *argv[] )
23 0.05 23 0.05
24 ), 24 ),
25 new FitnessFunctionEq(), 25 new FitnessFunctionEq(),
26 4,
26 1000, 27 1000,
27 .1, .1 28 .1, .1
28 ); 29 );