Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

kitano.cc

Go to the documentation of this file.
00001 
00025 #include <magic/mclass.h>
00026 #include <inanna/annetwork.h>
00027 #include <inanna/initializer.h>
00028 #include <nhp/individual.h>
00029 #include "annalee/kitano.h"
00030 
00031 impl_dynamic (KitanoEncoding, {Gentainer});
00032 
00034 //                                                                          //
00035 //  |  / o                      -----                      | o              //
00036 //  | /     |   ___    _        |       _    ___           |     _          //
00037 //  |/   | -+-  ___| |/ \   __  |---  |/ \  |   \  __   ---| | |/ \   ___   //
00038 //  | \  |  |  (   | |   | /  \ |     |   | |     /  \ (   | | |   | (   \  //
00039 //  |  \ |   \  \__| |   | \__/ |____ |   |  \__/ \__/  ---| | |   |  ---/  //
00040 //                                                                    __/   //
00042 
00043 KitanoEncoding::KitanoEncoding (const GeneticID& name, const StringMap& params)
00044         : ANNEncoding (name, params)
00045 {
00046     mIters        = getOrDefault (params, "KitanoEncoding.rewrites", String(5)).toInt ();
00047     mNonTerminals = getOrDefault (params, "KitanoEncoding.nonTerminals", String(26)).toInt ();
00048     mRules        = getOrDefault (params, "KitanoEncoding.rules", String(64)).toInt ();
00049 }
00050 
00051 KitanoEncoding::KitanoEncoding (const KitanoEncoding& orig) : ANNEncoding (orig) {
00052     mIters        = orig.mIters;
00053     mNonTerminals = orig.mNonTerminals;
00054     mRules        = orig.mRules;
00055 }
00056 
00057 void KitanoEncoding::copy (const Genstruct& o) {
00058     ANNEncoding::copy (o);
00059     const KitanoEncoding& orig = dynamic_cast<const KitanoEncoding&> (o);
00060     mIters        = orig.mIters;
00061     mNonTerminals = orig.mNonTerminals;
00062     mRules        = orig.mRules;
00063 }
00064 
00065 void KitanoEncoding::addPrivateGenes (Gentainer& p, const StringMap& params) {
00066     Gentainer::addPrivateGenes (p, params);
00067 
00068     for (int i=0; i<mRules; i++) {
00069         // Add nonterminal rule (N->NNNN, where N is a nont. symbol)
00070         // Left-hand-side:
00071         add (&(new IntGene (format ("R%d-0", i), 16, 16+mNonTerminals))->set(i).hide());
00072         for (int j=1; j<5; j++) // Right-hand-side:
00073             add (&(new IntGene (format ("R%d-%d", i, j), 0, 15+mNonTerminals))->hide());
00074     }
00075 }
00076 
00077 bool KitanoEncoding::execute (const GeneticMsg& msg) const
00078 {
00079     // Cache the grammar into tables
00080 
00081     // One rule for each possible leftside.
00082     PackTable<int> rules (16+mNonTerminals,4);
00083 
00084     // Set terminal rules
00085     for (int i=0; i<16; i++)
00086         for (int j=0; j<4; j++)
00087             rules.get (i,j) = (i&(1<<j))? FINALONE : FINALZERO;
00088     
00089     // Set all nonterminal rules default to undefined value
00090     for (int i=0; i<mNonTerminals; i++)
00091         for (int j=0; j<4; j++)
00092             rules.get (16+i,j) = VOIDAREA;
00093 
00094     // Read the rules from the genome
00095     for (int i=16; i<rules.rows; i++) {
00096         int leftside=-1, symb=-1;
00097         for (int j=0; j<5; j++) {
00098             if (i==16 && j==0)
00099                 symb = 16;  // The first rule in the chromosome is fixed
00100             else
00101                 symb = static_cast<const IntGene&> (*getGene (
00102                     format ("R%d-%d",i,j))).getvalue ();
00103 
00104             if (j==0) // Read the LHS of the production
00105                 leftside = symb;
00106             else
00107                 rules.get (leftside, j-1) = symb;
00108         }
00109     }
00110 
00111     //
00112     // Decode the grammar
00113     //
00114     
00115     // Make start rule
00116     PackTable<int> axiom (1,1);
00117     axiom.get (0,0) = 16; // 16 means the first nonterminal
00118 
00119     // Decode nonterminals recursively
00120     PackTable<int>* connmat = decodeMatrix (axiom, rules, mIters);
00121 
00122     // Calculate some statistics (probability of connection)
00123     int conns=0, totconns=0;
00124     for (int i=0; i<connmat->rows-mOutputs; i++)
00125         for (int j=(i>=mInputs)?i+1:mInputs; j<connmat->rows; j++) {
00126             totconns++;
00127             conns += (connmat->get(i,j)==1);
00128         }
00129 
00130     double pConn = double(conns) / double(totconns);
00131     msg.host.set ("pConn", new String (format ("%f", pConn)));
00132 
00133     // Create a network from the connection matrix
00134     ANNetwork* net = makeNet (*connmat);
00135 
00136     if (net) {
00137         net->setInitializer (new GaussianInitializer (0.5));
00138         
00139         // Take baby pictures only if this is a picture-taking recreation
00140         bool takePics = int(dynamic_cast<const TakeBrainPicsMsg*>(&msg));
00141 
00142         if (takePics) {
00143             net->cleanup (false);
00144             msg.host.set ("brainpic1", new String (net->drawEPS()));
00145         }
00146         net->cleanup (true, mPrunePassthroughs);
00147         if (takePics) {
00148             msg.host.set ("brainpic2", new String (net->drawEPS()));
00149             net->drawFeedForward();
00150             msg.host.set ("brainpic3", new String (net->drawEPS()));
00151 
00152             const String& matStr = dynamic_cast<const String&> (net->getAttribute("matrix"));
00153             msg.host.set ("braindesc1", new String (matStr));
00154             delete net;
00155         } else {
00156             // Place the brain description into host
00157             msg.host.set ("brainplan", net);
00158         }
00159     }
00160     delete connmat;
00161 
00162     return true;
00163 }
00164 
00165 PackTable<int>* KitanoEncoding::decodeMatrix (const PackTable<int>& string, const PackTable<int>& rules, int l) const
00166 {
00167 
00168     // Create a table to place the results of the next production
00169     PackTable<int>* nextString = new PackTable<int> (string.rows*2, string.cols*2);
00170 
00171     // Iterate through nonterminal matrix
00172     for (int i=0; i<string.rows; i++)
00173         for (int j=0; j<string.cols; j++) {
00174             // Decode a value in the matrix
00175             int k = string.get (i,j);
00176             
00177             // For nonterminals
00178             nextString->get (i*2  ,j*2  ) = (k<0)? k : rules.get (k, 0);
00179             nextString->get (i*2+1,j*2  ) = (k<0)? k : rules.get (k, 1);
00180             nextString->get (i*2  ,j*2+1) = (k<0)? k : rules.get (k, 2);
00181             nextString->get (i*2+1,j*2+1) = (k<0)? k : rules.get (k, 3);
00182         }
00183     
00184     // Recurse
00185     if (l>1) {
00186         PackTable<int>* retval = decodeMatrix (*nextString, rules, l-1);
00187         delete nextString;
00188         return retval;
00189     } else  {
00190         // Convert the temporary values to final
00191         for (int i=0; i<nextString->rows; i++)
00192             for (int j=0; j<nextString->cols; j++) {
00193                 int& value = nextString->get(i,j);
00194                 switch (value) {
00195                   case FINALONE:    value=1; break;
00196                   case FINALZERO:   value=0; break;
00197                   case VOIDAREA:    value=VOIDAREA; break;
00198                   default:          value=UNRESOLVED; // Unresolved
00199                 };
00200             }
00201         
00202         return nextString;
00203     }
00204 }
00205 
00206 ANNetwork* KitanoEncoding::makeNet (const PackTable<int>& connmatPar) const {
00207     ASSERT (connmatPar.rows == connmatPar.cols);
00208     ASSERT (connmatPar.rows != 0);
00209     ASSERT (connmatPar.rows > mInputs+mOutputs);
00210 
00211     PackTable<int> connmat = connmatPar;
00212     int hiddens = connmat.rows-(mInputs+mOutputs);
00213     
00214     // Outputs always enabled
00215     //for (int i=0; i<connmat.rows; i++)
00216     for (int i=mInputs+hiddens; i<connmat.rows; i++)
00217         connmat.get(i,i) = 1;
00218 
00219     String pic;
00220     pic.reserve(connmat.rows*(connmat.cols+1)+10);
00221     for (int i=0; i<connmat.rows; i++) {
00222         for (int j=0; j<connmat.rows; j++) {
00223             switch (connmat.get(i,j)) {
00224               case 0:           pic += '0';     break;
00225               case 1:           pic += '1';     break;
00226               case VOIDAREA:    pic += ' ';     break;
00227               case UNRESOLVED:  pic += 'x';     break;
00228               default:
00229                   ASSERT (false);
00230             };
00231         }
00232         pic += '\n';
00233     } 
00234     
00235     ANNetwork* net = new ANNetwork (format("%dl-%d-%dl", mInputs, hiddens, mOutputs));
00236     net->setAttribute ("matrix", new String(pic));
00237 
00238     // Connect the network
00239     for (int i=0; i<connmat.rows; i++) {
00240 
00241         // Set the position of the unit
00242         if (i>=mInputs)
00243             (*net)[i].moveTo (double(i-mInputs)/hiddens*10+5, 20*frnd(), 20*frnd());
00244 
00245         // Disable unit if 0 at diagonal
00246         if (connmat.get(i,i)!=1) {
00247             (*net)[i].enable(false);
00248             (*net)[i].moveTo (-1,-1,-1);
00249         } else  // Connect the unit
00250             for (int j=mInputs; j<connmat.cols; j++)
00251                 if (i<j && connmat.get(i,j)==1) // && i>=mInputs 
00252                     net->connect (i,j);
00253     }
00254 
00255     net->check ();
00256     
00257     return net;
00258 }
00259 
00260 void KitanoEncoding::check () const {
00261     ANNEncoding::check ();
00262     ASSERT (mIters>0);
00263     ASSERT (mIters<10);
00264     ASSERT (mNonTerminals>0);
00265     ASSERT (mNonTerminals<100);
00266     ASSERT (mRules>=16);
00267     ASSERT (mRules<=1000);
00268 }
00269 
00271 // Here is some code for statistical analysis of neural
00272 // structures. This is not nice code and it exists for purely
00273 // "debugging" purposes. More precisely, validation of propabilistic
00274 // analysis of Kitano encoding.
00275 
00276 void kitanoStat () {
00277 }
00278 

Generated on Thu Feb 10 20:21:26 2005 for Annalee by doxygen1.2.18