00001
00002
00003
00004
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
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) {
00125 return false;
00126 }
00127
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
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
00154
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