00001
00020 #include "mutation.h"
00021 #include "problem.h"
00022 #include "random.h"
00023 #include <cassert>
00024 #include <string>
00025
00026 using std::string;
00027
00028 using namespace realea;
00029
00030 Mutation::Mutation(IMutation *mut, double ratio) {
00031 assert(mut != NULL);
00032 m_mutation = mut;
00033
00034 if (ratio < 0 || ratio > 1.0) {
00035 throw new string("Mutation::ratio is not a valide number");
00036 }
00037
00038 m_ratio = ratio;
00039 m_random = NULL;
00040 }
00041
00042 bool Mutation::apply(tChromosomeReal &sol) {
00043 bool changed = false;
00044 unsigned size = sol.size();
00045
00046 if (m_ratio > 0) {
00047 if (!m_random) {
00048 throw ConfigException("Mutation::random");
00049 }
00050
00051 changed = (m_random->rand() <= m_ratio);
00052 }
00053
00054 if (changed) {
00055 unsigned pos;
00056
00057 do {
00058 pos = m_random->randint(0, size-1);
00059 } while(!m_domain->canBeChanged(pos));
00060
00061 sol[pos] = m_mutation->mutate(sol, pos);
00062 }
00063
00064 return changed;
00065 }
00066
00067 void Mutation::setRandom(Random *random) {
00068 m_random = random;
00069 m_mutation->setRandom(random);
00070 }
00071
00072 void Mutation::setDomain(DomainRealPtr domain) {
00073 m_mutation->setDomain(domain);
00074 m_domain = domain;
00075 }
00076
00077 tGen MutationBGA::mutate(tChromosomeReal &sol, unsigned pos) {
00078 const unsigned num=16;
00079 const double pai = 1.0/num;
00080 tReal rangi, min, max;
00081 unsigned i;
00082 double dif;
00083 double sum=0;
00084
00085 if (!m_domain) {
00086 new ConfigException("MutationBGA::domain");
00087 }
00088
00089 m_domain->getValues(pos, &min, &max);
00090 rangi = 0.1*(max-min);
00091
00092 if (!m_random) {
00093 new ConfigException("MutationBGA::random");
00094 }
00095
00096 for (i = 0, dif = 1; i < num; i++, dif/=2) {
00097 if (m_random->rand() < pai) {
00098 sum += dif;
00099 }
00100
00101 }
00102
00103 tGen value = sol[pos];
00104
00105 if (sum == 0) {
00106 return value;
00107 }
00108
00109
00110 if (m_random->rand() < 0.5) {
00111 value += rangi*sum;
00112
00113 if (value > max) {
00114 value = max;
00115 }
00116 }
00117 else {
00118 value -= rangi*sum;
00119
00120 if (value < min) {
00121 value = min;
00122 }
00123
00124 }
00125
00126 return(value);
00127 }
00128
00129 Mutation::~Mutation(void) {
00130 if (m_mutation) {
00131 delete m_mutation;
00132 }
00133 }