diff options
-rw-r--r-- | src/explicitsimulation.cpp | 130 | ||||
-rw-r--r-- | src/explicitsimulation.h | 35 | ||||
-rw-r--r-- | src/fitnessfunction.h | 1 | ||||
-rw-r--r-- | src/tests/maxima/fitnessfunctioneq.cpp | 5 | ||||
-rw-r--r-- | src/tests/maxima/fitnessfunctioneq.h | 1 | ||||
-rw-r--r-- | src/tests/maxima/main.cpp | 1 |
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 | ||
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 | |||
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 | |||
7 | namespace Genetic | 11 | namespace 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 | ||
26 | Genetic::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 | ); |