summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Buland <mike@xagasoft.com>2012-07-09 12:01:50 -0600
committerMike Buland <mike@xagasoft.com>2012-07-09 12:01:50 -0600
commit1f7c135934b6604c5409d4b6f34861105c0a64cb (patch)
treecc421e2e8620b72e202f0eddf2cd5f1478d3bc06 /src
parent40ee7ad5aeadeb9823e1cd6e1218a1999c608a65 (diff)
downloadlibgenetic-1f7c135934b6604c5409d4b6f34861105c0a64cb.tar.gz
libgenetic-1f7c135934b6604c5409d4b6f34861105c0a64cb.tar.bz2
libgenetic-1f7c135934b6604c5409d4b6f34861105c0a64cb.tar.xz
libgenetic-1f7c135934b6604c5409d4b6f34861105c0a64cb.zip
It works well enough to solve polynomial maxima.
Diffstat (limited to 'src')
-rw-r--r--src/config.h12
-rw-r--r--src/explicitsimulation.cpp139
-rw-r--r--src/explicitsimulation.h48
-rw-r--r--src/fitnessfunction.cpp10
-rw-r--r--src/fitnessfunction.h18
-rw-r--r--src/phenotype.cpp21
-rw-r--r--src/phenotype.h19
-rw-r--r--src/phenotypebinary.cpp34
-rw-r--r--src/phenotypebinary.h3
-rw-r--r--src/population.cpp77
-rw-r--r--src/population.h36
-rw-r--r--src/tests/maxima/fitnessfunctioneq.cpp25
-rw-r--r--src/tests/maxima/fitnessfunctioneq.h15
-rw-r--r--src/tests/maxima/main.cpp39
14 files changed, 494 insertions, 2 deletions
diff --git a/src/config.h b/src/config.h
new file mode 100644
index 0000000..2563eb9
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,12 @@
1#ifndef GENETIC_CONFIG_H
2#define GENETIC_CONFIG_H
3
4#include <stdint.h>
5
6namespace Genetic
7{
8 typedef uint32_t Time;
9 typedef uint32_t PhenotypeId;
10};
11
12#endif
diff --git a/src/explicitsimulation.cpp b/src/explicitsimulation.cpp
new file mode 100644
index 0000000..281e7e5
--- /dev/null
+++ b/src/explicitsimulation.cpp
@@ -0,0 +1,139 @@
1#include "genetic/explicitsimulation.h"
2#include "genetic/operator.h"
3#include "genetic/fitnessfunction.h"
4
5#include <bu/random.h>
6#include <bu/sio.h>
7
8using namespace Bu;
9
10Genetic::ExplicitSimulation::ExplicitSimulation( Genetic::Operator *pOper,
11 Genetic::FitnessFunction *pFunc, int iPopSize, float fKeep,
12 float fRandom, bool bKeepBest ) :
13 pOper( pOper ),
14 pFunc( pFunc ),
15 iPopSize( iPopSize ),
16 fKeep( fKeep ),
17 fRandom( fRandom ),
18 bKeepBest( bKeepBest )
19{
20 for( int j = 0; j < iPopSize; j++ )
21 {
22 xPop.addPhenotype( pOper->random() );
23 }
24
25 updateFitness();
26}
27
28Genetic::ExplicitSimulation::~ExplicitSimulation()
29{
30 delete pOper;
31 delete pFunc;
32}
33
34void Genetic::ExplicitSimulation::timestep()
35{
36 PhenotypeList lNew;
37
38 int iChildren = iPopSize*(1.0-fKeep-fRandom);
39
40 // Create children
41 for( int j = 0; j < iChildren; j++ )
42 {
43 PhenotypeList lParents;
44 for( int k = 0; k < pOper->parentCount(); k++ )
45 lParents.append( xPop.getPhenotype( selectWeighted() ) );
46 lNew.append( pOper->mate( lParents ) );
47 }
48
49 // Select phenotypes for keeping
50 int iKeep = iPopSize*fKeep;
51 FitnessHash hTempFitness;
52 for( int j = 0; j < iKeep; j++ )
53 {
54 Genetic::PhenotypeId id = selectWeighted();
55 lNew.append( xPop.takePhenotype( id ) );
56 hTempFitness.insert( id, hFitness.get( id ) );
57 hFitness.erase( id );
58 dTotalFitness -= hTempFitness.get( id );
59 }
60
61 if( bKeepBest && hFitness.has( uMaxFitness ) )
62 {
63 lNew.append( xPop.takePhenotype( uMaxFitness ) );
64 hTempFitness.insert( uMaxFitness, hFitness.get( uMaxFitness ) );
65 hFitness.erase( uMaxFitness );
66 dTotalFitness -= hTempFitness.get( uMaxFitness );
67 }
68
69 // Fill in the remainder with random phenotypes
70 while( lNew.getSize() < iPopSize )
71 {
72 lNew.append( pOper->random() );
73 }
74
75 // Refill the population
76 hFitness = hTempFitness;
77 xPop.clear();
78 xPop.timestep();
79 for( PhenotypeList::iterator i = lNew.begin(); i; i++ )
80 {
81 xPop.addPhenotype( *i );
82 }
83
84 updateFitness();
85}
86
87Genetic::PhenotypeId Genetic::ExplicitSimulation::selectWeighted()
88{
89 double dSel = Bu::Random::randNorm()*dTotalFitness;
90 double dRun = 0.0;
91
92 for( FitnessHash::iterator i = hFitness.begin(); i; i++ )
93 {
94 dRun += *i;
95 if( dSel < dRun )
96 return i.getKey();
97 }
98
99 sio << "Genetic::ExplicitSimulation::selectWeighted() - failed, picked max"
100 << sio.nl;
101
102 return uMaxFitness;
103}
104
105void Genetic::ExplicitSimulation::updateFitness()
106{
107 dMinFitness = -1.0;
108 dTotalFitness = 0.0;
109 for( Population::iterator i = xPop.begin(); i; i++ )
110 {
111 double dFitness;
112 if( hFitness.has( i.getKey() ) )
113 {
114 dFitness = hFitness.get( i.getKey() );
115 }
116 else
117 {
118 dFitness = (*pFunc)( *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 }
138 }
139}
diff --git a/src/explicitsimulation.h b/src/explicitsimulation.h
new file mode 100644
index 0000000..ebddd62
--- /dev/null
+++ b/src/explicitsimulation.h
@@ -0,0 +1,48 @@
1#ifndef GENETIC_EXPLICIT_SIMULATION_H
2#define GENETIC_EXPLICIT_SIMULATION_H
3
4#include "genetic/population.h"
5#include "genetic/config.h"
6
7namespace Genetic
8{
9 class Operator;
10 class FitnessFunction;
11
12 class ExplicitSimulation
13 {
14 public:
15 ExplicitSimulation( Operator *pOper, FitnessFunction *pFunc,
16 int iPopSize, float fKeep, float fRandom, bool bKeepBest=true );
17 virtual ~ExplicitSimulation();
18
19 void timestep();
20
21 Genetic::PhenotypeId selectWeighted();
22
23 double getMinFitness() const { return dMinFitness; }
24 double getMaxFitness() const { return dMaxFitness; }
25
26 protected:
27 void updateFitness();
28
29 protected:
30 Population xPop;
31 Operator *pOper;
32 FitnessFunction *pFunc;
33
34 private:
35 int iPopSize;
36 float fKeep;
37 float fRandom;
38 bool bKeepBest;
39 typedef Bu::Hash<Genetic::PhenotypeId, double> FitnessHash;
40 FitnessHash hFitness;
41 double dMinFitness;
42 double dMaxFitness;
43 double dTotalFitness;
44 PhenotypeId uMaxFitness;
45 };
46};
47
48#endif
diff --git a/src/fitnessfunction.cpp b/src/fitnessfunction.cpp
new file mode 100644
index 0000000..dd2ee08
--- /dev/null
+++ b/src/fitnessfunction.cpp
@@ -0,0 +1,10 @@
1#include "genetic/fitnessfunction.h"
2
3Genetic::FitnessFunction::FitnessFunction()
4{
5}
6
7Genetic::FitnessFunction::~FitnessFunction()
8{
9}
10
diff --git a/src/fitnessfunction.h b/src/fitnessfunction.h
new file mode 100644
index 0000000..c41f733
--- /dev/null
+++ b/src/fitnessfunction.h
@@ -0,0 +1,18 @@
1#ifndef GENETIC_FITNESS_FUNCTION_H
2#define GENETIC_FITNESS_FUNCTION_H
3
4namespace Genetic
5{
6 class Phenotype;
7
8 class FitnessFunction
9 {
10 public:
11 FitnessFunction();
12 virtual ~FitnessFunction();
13
14 virtual double operator()( Phenotype *pTest )=0;
15 };
16};
17
18#endif
diff --git a/src/phenotype.cpp b/src/phenotype.cpp
index 1eca170..b965ffd 100644
--- a/src/phenotype.cpp
+++ b/src/phenotype.cpp
@@ -1,6 +1,9 @@
1#include "genetic/phenotype.h" 1#include "genetic/phenotype.h"
2 2
3Genetic::Phenotype::Phenotype() 3Genetic::Phenotype::Phenotype() :
4 tCreated( 0 ),
5 uId( 0 ),
6 bActive( false )
4{ 7{
5} 8}
6 9
@@ -8,3 +11,19 @@ Genetic::Phenotype::~Phenotype()
8{ 11{
9} 12}
10 13
14bool Genetic::Phenotype::hasProperty( const Bu::String &sKey ) const
15{
16 return hProp.has( sKey );
17}
18
19Bu::Variant Genetic::Phenotype::getProperty( const Bu::String &sKey ) const
20{
21 return hProp.get( sKey );
22}
23
24void Genetic::Phenotype::setProperty( const Bu::String &sKey,
25 Bu::Variant vValue )
26{
27 hProp.insert( sKey, vValue );
28}
29
diff --git a/src/phenotype.h b/src/phenotype.h
index 7c564d5..0eafb78 100644
--- a/src/phenotype.h
+++ b/src/phenotype.h
@@ -2,6 +2,10 @@
2#define GENETIC_PHENOTYPE_H 2#define GENETIC_PHENOTYPE_H
3 3
4#include <bu/string.h> 4#include <bu/string.h>
5#include <bu/hash.h>
6#include <bu/variant.h>
7
8#include "genetic/config.h"
5 9
6namespace Genetic 10namespace Genetic
7{ 11{
@@ -29,7 +33,22 @@ namespace Genetic
29 33
30 virtual Bu::String toString()=0; 34 virtual Bu::String toString()=0;
31 35
36 bool hasProperty( const Bu::String &sKey ) const;
37 Bu::Variant getProperty( const Bu::String &sKey ) const;
38 void setProperty( const Bu::String &sKey, Bu::Variant vValue );
39 void setCreated( Genetic::Time t, Genetic::PhenotypeId id )
40 { tCreated = t; uId = id; bActive = true; }
41 Genetic::Time getCreated() const { return tCreated; }
42 Genetic::PhenotypeId getId() const { return uId; }
43
44 bool isActive() const { return bActive; }
45
32 private: 46 private:
47 Genetic::Time tCreated;
48 Genetic::PhenotypeId uId;
49 bool bActive;
50 typedef Bu::Hash<Bu::String, Bu::Variant> PropHash;
51 PropHash hProp;
33 }; 52 };
34}; 53};
35 54
diff --git a/src/phenotypebinary.cpp b/src/phenotypebinary.cpp
index d16588b..68f9ebf 100644
--- a/src/phenotypebinary.cpp
+++ b/src/phenotypebinary.cpp
@@ -99,3 +99,37 @@ Bu::String Genetic::PhenotypeBinary::toString()
99 return sRet; 99 return sRet;
100} 100}
101 101
102void Genetic::PhenotypeBinary::extractBits( uint32_t &rTarget, int iStart,
103 int iBits )
104{
105 rTarget = 0;
106 if( iBits > sizeof(rTarget)*8 )
107 iBits = sizeof(rTarget)*8;
108
109 // This is pretty much the same problem as copyFrom, so I'm doing it the
110 // same way for now.
111 for( int j = 0; j < iBits; j++ )
112 {
113 int ws = wordWithBit(j+iStart);
114 if( (aGenes[ws]&(1<<((j+iStart)%BPW))) != 0 )
115 rTarget |= (1<<(j%BPW));
116 }
117}
118
119void Genetic::PhenotypeBinary::extractBits( uint64_t &rTarget, int iStart,
120 int iBits )
121{
122 rTarget = 0;
123 if( iBits > sizeof(rTarget)*8 )
124 iBits = sizeof(rTarget)*8;
125
126 // This is pretty much the same problem as copyFrom, so I'm doing it the
127 // same way for now.
128 for( int j = 0; j < iBits; j++ )
129 {
130 int ws = wordWithBit(j+iStart);
131 if( (aGenes[ws]&(1<<((j+iStart)%BPW))) != 0 )
132 rTarget |= (1ll<<(j));
133 }
134}
135
diff --git a/src/phenotypebinary.h b/src/phenotypebinary.h
index 72435ed..cbae392 100644
--- a/src/phenotypebinary.h
+++ b/src/phenotypebinary.h
@@ -19,6 +19,9 @@ namespace Genetic
19 int iCount, int iDest=-1 ); 19 int iCount, int iDest=-1 );
20 virtual Bu::String toString(); 20 virtual Bu::String toString();
21 21
22 void extractBits( uint32_t &rTarget, int iStart, int iBits );
23 void extractBits( uint64_t &rTarget, int iStart, int iBits );
24
22 private: 25 private:
23 int iSize; 26 int iSize;
24 int iWords; 27 int iWords;
diff --git a/src/population.cpp b/src/population.cpp
index 85b859e..fbd6d6c 100644
--- a/src/population.cpp
+++ b/src/population.cpp
@@ -1,10 +1,85 @@
1#include "genetic/population.h" 1#include "genetic/population.h"
2#include "genetic/phenotype.h"
2 3
3Genetic::Population::Population() 4#include <bu/mutexlocker.h>
5
6Genetic::Population::Population() :
7 uNextId( 0 ),
8 uTime( 0 )
4{ 9{
5} 10}
6 11
7Genetic::Population::~Population() 12Genetic::Population::~Population()
8{ 13{
14 for( PhenotypeHash::iterator i = hPhenotype.begin(); i; i++ )
15 delete *i;
16}
17
18Genetic::PhenotypeId Genetic::Population::addPhenotype(
19 Genetic::Phenotype *pNew )
20{
21 Bu::MutexLocker ml( mGeneral );
22 if( !pNew->isActive() )
23 pNew->setCreated( uTime, uNextId++ );
24
25 hPhenotype.insert( pNew->getId(), pNew );
26 return pNew->getId();
27}
28
29bool Genetic::Population::hasProperty( Genetic::PhenotypeId id,
30 const Bu::String &sKey ) const
31{
32 Bu::MutexLocker ml( mGeneral );
33 return hPhenotype.get( id )->hasProperty( sKey );
34}
35
36Bu::Variant Genetic::Population::getProperty(
37 Genetic::PhenotypeId id, const Bu::String &sKey ) const
38{
39 Bu::MutexLocker ml( mGeneral );
40 return hPhenotype.get( id )->getProperty( sKey );
41}
42
43void Genetic::Population::setProperty( Genetic::PhenotypeId id,
44 const Bu::String &sKey, Bu::Variant vValue )
45{
46 Bu::MutexLocker ml( mGeneral );
47
48 hPhenotype.get( id )->setProperty( sKey, vValue );
49}
50
51void Genetic::Population::delPhenotype( PhenotypeId id )
52{
53 Bu::MutexLocker ml( mGeneral );
54 delete hPhenotype.get( id );
55 hPhenotype.erase( id );
56}
57
58Genetic::Phenotype *Genetic::Population::takePhenotype( PhenotypeId id )
59{
60 Bu::MutexLocker ml( mGeneral );
61 Phenotype *pRet = hPhenotype.get( id );
62 hPhenotype.erase( id );
63 return pRet;
64}
65
66void Genetic::Population::clear()
67{
68 Bu::MutexLocker ml( mGeneral );
69 for( PhenotypeHash::iterator i = hPhenotype.begin(); i; i++ )
70 delete *i;
71 hPhenotype.clear();
72}
73
74Genetic::PhenotypeId Genetic::Population::timestep()
75{
76 Bu::MutexLocker ml( mGeneral );
77 return (++uTime);
78}
79
80Genetic::PhenotypeId Genetic::Population::time() const
81{
82 Bu::MutexLocker ml( mGeneral );
83 return uTime;
9} 84}
10 85
diff --git a/src/population.h b/src/population.h
index 0fdad32..c2d1bec 100644
--- a/src/population.h
+++ b/src/population.h
@@ -1,13 +1,49 @@
1#ifndef GENETIC_POPULATION_H 1#ifndef GENETIC_POPULATION_H
2#define GENETIC_POPULATION_H 2#define GENETIC_POPULATION_H
3 3
4#include <bu/string.h>
5#include <bu/hash.h>
6#include <bu/mutex.h>
7
8#include "genetic/config.h"
9
4namespace Genetic 10namespace Genetic
5{ 11{
12 class Phenotype;
13
6 class Population 14 class Population
7 { 15 {
8 public: 16 public:
9 Population(); 17 Population();
10 virtual ~Population(); 18 virtual ~Population();
19
20 typedef Bu::Hash<PhenotypeId, Phenotype *> PhenotypeHash;
21 typedef PhenotypeHash::iterator iterator;
22 typedef PhenotypeHash::const_iterator const_iterator;
23
24 iterator begin() { return hPhenotype.begin(); }
25 const_iterator begin() const { return hPhenotype.begin(); }
26 int getSize() const { return hPhenotype.getSize(); }
27
28 PhenotypeId addPhenotype( Phenotype *pNew );
29 Phenotype *getPhenotype( PhenotypeId id )
30 { return hPhenotype.get( id ); }
31 bool hasProperty( PhenotypeId id, const Bu::String &sKey ) const;
32 Bu::Variant getProperty( PhenotypeId id, const Bu::String &sKey ) const;
33 void setProperty( PhenotypeId id, const Bu::String &sKey,
34 Bu::Variant vValue );
35 void delPhenotype( PhenotypeId id );
36 Phenotype *takePhenotype( PhenotypeId id );
37 void clear();
38
39 PhenotypeId timestep();
40 PhenotypeId time() const;
41
42 private:
43 PhenotypeId uNextId;
44 PhenotypeId uTime;
45 PhenotypeHash hPhenotype;
46 mutable Bu::Mutex mGeneral;
11 }; 47 };
12}; 48};
13 49
diff --git a/src/tests/maxima/fitnessfunctioneq.cpp b/src/tests/maxima/fitnessfunctioneq.cpp
new file mode 100644
index 0000000..5694507
--- /dev/null
+++ b/src/tests/maxima/fitnessfunctioneq.cpp
@@ -0,0 +1,25 @@
1#include "fitnessfunctioneq.h"
2#include "genetic/phenotypebinary.h"
3
4FitnessFunctionEq::FitnessFunctionEq()
5{
6}
7
8FitnessFunctionEq::~FitnessFunctionEq()
9{
10}
11
12double FitnessFunctionEq::operator()( Genetic::Phenotype *pTest )
13{
14 Genetic::PhenotypeBinary *pbTest =
15 dynamic_cast<Genetic::PhenotypeBinary *>( pTest );
16 if( pbTest == NULL )
17 return 0.0;
18
19 uint32_t uRaw;
20 pbTest->extractBits( uRaw, 0, 32 );
21 double x = ((double)uRaw / (double)(0xfffffffful))*5.0 - 2.5;
22
23 return -1.8*(x*x*x*x) + 0.86*(x*x*x) + 4.0*(x*x);
24}
25
diff --git a/src/tests/maxima/fitnessfunctioneq.h b/src/tests/maxima/fitnessfunctioneq.h
new file mode 100644
index 0000000..7139532
--- /dev/null
+++ b/src/tests/maxima/fitnessfunctioneq.h
@@ -0,0 +1,15 @@
1#ifndef GENETIC_FITNESS_FUNCTION_EQ_H
2#define GENETIC_FITNESS_FUNCTION_EQ_H
3
4#include "genetic/fitnessfunction.h"
5
6class FitnessFunctionEq : public Genetic::FitnessFunction
7{
8public:
9 FitnessFunctionEq();
10 virtual ~FitnessFunctionEq();
11
12 virtual double operator()( Genetic::Phenotype *pTest );
13};
14
15#endif
diff --git a/src/tests/maxima/main.cpp b/src/tests/maxima/main.cpp
new file mode 100644
index 0000000..ab90e0b
--- /dev/null
+++ b/src/tests/maxima/main.cpp
@@ -0,0 +1,39 @@
1#include "genetic/population.h"
2#include "genetic/phenotypebinary.h"
3#include "genetic/operatorbasic.h"
4#include "genetic/explicitsimulation.h"
5#include "fitnessfunctioneq.h"
6
7#include <time.h>
8
9#include <bu/random.h>
10#include <bu/sio.h>
11using namespace Bu;
12
13int main( int argc, char *argv[] )
14{
15 Bu::Random::seed( time( NULL ) );
16 sio << "Global maxima equation test" << sio.nl
17 << " - -1.8*x^4 + 0.86*x^3 + 4.0*x^2 == 3.53518 (approx)" << sio.nl
18 << sio.nl;
19
20 Genetic::ExplicitSimulation ex(
21 new Genetic::OperatorBasic(
22 new Genetic::PhenotypeBinary( 32 ),
23 0.01
24 ),
25 new FitnessFunctionEq(),
26 100,
27 .1, .05
28 );
29
30 for( int j = 0; j < 100; j++ )
31 {
32 ex.timestep();
33 sio << ex.getMinFitness() << " - " << ex.getMaxFitness() <<
34 sio.nl;
35 }
36
37 return 0;
38}
39