Back to Top page.

EGTCrossover.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003 $Id: EGTCrossover.h,v 1.1.1.1 2002/10/19 08:14:51 motegi Exp $
00004 Copyright (C) 2002 Higuchi Lab. All rights reserved.
00005 
00006 *****************************************************************************/
00007 #ifndef INCLUDE__CROSSOVER_H__FILE
00008 #define INCLUDE__CROSSOVER_H__FILE
00009 
00010 #include "defs.h"
00011 #include "env.h"
00012 #include "EGException.h"
00013 #include "EGRandom.h"
00014 #include "EGTVector.h"
00015 
00023 template<class TP>
00024 class EGTCrossover {
00025 public:
00026   typedef TP                       Pop;
00027   typedef typename Pop::Graph      Graph;
00028   typedef EGTVector<const Graph*>  Graphs;
00029   typedef typename Graph::SubGraph SubGraph;
00030 
00032   virtual ~EGTCrossover() { }
00033   virtual UInt Crossover(const Graphs& src, Pop& dest);
00034 
00035 protected:
00036   virtual bool DoCrossover(const Graph& graph1, const Graph& graph2, Pop& dest);
00037 };
00038 
00039 //============================================================================
00047 template<class TP>
00048 UInt EGTCrossover<TP>::Crossover(const Graphs& src, Pop& dest)
00049 {
00050   Float fCrossoverRate = Env::Instance().CrossoverRate();
00051   UInt uPopSize = Env::Instance().PopSize();
00052 
00053   if (fCrossoverRate > 1.0) {
00054     fCrossoverRate = 1.0;
00055   }
00056   UInt uMax = src.Size();
00057   if (uMax < 2) {
00058     throw EGException("EGTCrossover::Crossover()"
00059                       "Can't perform the crossover operation: "
00060                       "the number of individuals is less than 2.",
00061                       __FILE__, __LINE__);
00062   }
00063 
00064   // Number of crossover operations
00065   UInt uCrossoverCount = (UInt)(uPopSize * fCrossoverRate) / 2;
00066 
00067   UInt uSel = (UInt)(uMax * EGRandom::NextReal());
00068   const Graph *pg1;
00069   const Graph *pg2;
00070 
00071   UInt n = 0;
00072   for (UInt i=0; i<uCrossoverCount; ++i) {
00073     if (uSel == uMax) {
00074       pg1 = src[0];
00075       pg2 = src[1];
00076       uSel = 2;
00077     }
00078     else if (uSel+1 == uMax) {
00079       pg1 = src[uSel];
00080       pg2 = src[0];
00081       uSel = 1;
00082     }
00083     else {
00084       pg1 = src[uSel];
00085       pg2 = src[uSel+1];
00086       uSel += 2;
00087     }
00088     if (DoCrossover(*pg1, *pg2, dest) == true) {
00089       ++n;
00090     }
00091   }
00092   return n;
00093 }
00094 
00095 //============================================================================
00104 template<class TP>
00105 bool EGTCrossover<TP>::DoCrossover(const Graph& graph1, const Graph& graph2,
00106                                    Pop& dest) {
00107   UInt uSel1, uSel2, uSelIndex;
00108   const SubGraph* psg1a;
00109   const SubGraph* psg2a;
00110   SubGraph* psg1b;
00111   SubGraph* psg2b;
00112 
00113   UInt uGraph1NumSubGraphs = graph1.GetNumSubGraphs();
00114   if (uGraph1NumSubGraphs == 0) {
00115     return false;
00116   }
00117   EGTVector<UInt> tIndex(uGraph1NumSubGraphs);
00118   for (UInt i=0; i<uGraph1NumSubGraphs; ++i) {
00119     tIndex[i] = i;
00120   }
00121 
00122   UInt uMaxNodeSize = 2 * Env::Instance().MaxNodeSize();
00123   while (1) {
00124     if (tIndex.Size() == 0) {  // No compatible SubGraphs between two Graphs.
00125       return false;
00126     }
00127     // Selects a SubGraph randomly from Graph 1.
00128     uSelIndex = EGRandom::NextInt(0, tIndex.Size()-1);
00129     uSel1 = tIndex[uSelIndex];
00130     psg1a = graph1.GetSubGraph(uSel1);
00131     tIndex.Erase(tIndex.Begin() + uSelIndex);
00132 
00133     // Selects a compatible SubGraph with "psg1a" from Graph 2.
00134     psg2a = graph2.GetSubGraph(*psg1a, &uSel2);
00135     if (psg2a != 0) {
00136       UInt uMax1b = uMaxNodeSize - psg2a->GetNumNodes();
00137       UInt uMax2b = uMaxNodeSize - psg1a->GetNumNodes();
00138       psg1b = graph1.CreateComplementarySubGraph(uSel1, uMax1b);
00139       psg2b = graph2.CreateComplementarySubGraph(uSel2, uMax2b);
00140       if (psg1b == 0 || psg2b == 0) {
00141         delete psg1b;
00142         delete psg2b;
00143       }
00144       else {
00145         break;
00146       }
00147     }
00148   }
00149 
00150   Graph* ptNewGraph1 = new Graph;
00151   Graph* ptNewGraph2 = new Graph;
00152 
00153   // Combines "psg1a" with "psg2b".
00154   // Combines "psg1b" with "psg2a".
00155   if (ptNewGraph1->InitGraph(*psg2b, *psg1a, 1) == false ||
00156       ptNewGraph2->InitGraph(*psg1b, *psg2a, 1) == false) {
00157     delete ptNewGraph1;
00158     delete ptNewGraph2;
00159     delete psg1b;
00160     delete psg2b;
00161     return false;
00162   };
00163 
00164   ptNewGraph1->SetOperator(OP_CROSSOVER);
00165   ptNewGraph2->SetOperator(OP_CROSSOVER);
00166   ptNewGraph1->SetMother(graph2.GetGraphID());
00167   ptNewGraph1->SetFather(graph1.GetGraphID());
00168   ptNewGraph2->SetMother(graph1.GetGraphID());
00169   ptNewGraph2->SetFather(graph2.GetGraphID());
00170   
00171   dest.AddGraph(ptNewGraph1);
00172   dest.AddGraph(ptNewGraph2);
00173 
00174 #ifdef CROSSOVER_DETAIL
00175   std::cout << "The crossover operation performed.\n";
00176   std::cout << "*** SubGraph1a ***\n";  psg1a->Display(std::cout);
00177   std::cout << "*** SubGraph1b ***\n";  psg1b->Display(std::cout);
00178   std::cout << "*** SubGraph2a ***\n";  psg2a->Display(std::cout);
00179   std::cout << "*** SubGraph2b ***\n";  psg2b->Display(std::cout);
00180 #endif
00181 
00182   delete psg1b;
00183   delete psg2b;
00184   return true;
00185 }
00186 
00187 #endif  //INCLUDE__CROSSOVER_H__FILE