From e4bf96fd183951afed2ffb2d692b2350c32a188f Mon Sep 17 00:00:00 2001 From: fbhou <1816118394@qq.com> Date: Sat, 12 Dec 2020 21:25:36 +0800 Subject: [PATCH 1/4] Added evolution.h and evolution.cpp --- LinearAlgebra/LinearAlgebra.vcxproj | 2 ++ LinearAlgebra/LinearAlgebra.vcxproj.filters | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/LinearAlgebra/LinearAlgebra.vcxproj b/LinearAlgebra/LinearAlgebra.vcxproj index cf21a9d..005d004 100644 --- a/LinearAlgebra/LinearAlgebra.vcxproj +++ b/LinearAlgebra/LinearAlgebra.vcxproj @@ -140,6 +140,7 @@ + @@ -147,6 +148,7 @@ + diff --git a/LinearAlgebra/LinearAlgebra.vcxproj.filters b/LinearAlgebra/LinearAlgebra.vcxproj.filters index 4552c9f..6f824dd 100644 --- a/LinearAlgebra/LinearAlgebra.vcxproj.filters +++ b/LinearAlgebra/LinearAlgebra.vcxproj.filters @@ -26,6 +26,9 @@ 源文件 + + 源文件 + @@ -40,5 +43,8 @@ 头文件 + + 头文件 + \ No newline at end of file From dd7ac9fca6a6a11cdf08af82b32f18ea05e1b605 Mon Sep 17 00:00:00 2001 From: fbhou <1816118394@qq.com> Date: Sat, 12 Dec 2020 21:31:12 +0800 Subject: [PATCH 2/4] Added evolution.h and evolution.cpp --- LinearAlgebra/evolution.cpp | 107 ++++++++++++++++++++++++++++++++++++ LinearAlgebra/evolution.h | 45 +++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 LinearAlgebra/evolution.cpp create mode 100644 LinearAlgebra/evolution.h diff --git a/LinearAlgebra/evolution.cpp b/LinearAlgebra/evolution.cpp new file mode 100644 index 0000000..763402a --- /dev/null +++ b/LinearAlgebra/evolution.cpp @@ -0,0 +1,107 @@ +#include"linearvector.h" +#include"matrix.h" +#include"QuetionA.h" +#include"evolution.h" + +/* +source: The Matrix object you want to solve; +size: Number of individuals in the species (200 in the article); +max_generation: Maximum iteration times (1000 in the article); +cross_pos: Possibility of crossing (0.6 in the article); +cross_rate: Degree of crossing (0.66 in the article); +mutate_pos: Possibility of mutation (0.05 in the article); +mutate_rate: Dependence of mutation degree on the generation times (0.8 in the article); +*/ +Eigenvalue::Eigenvalue(const Matrix& source, const int& size, const int& max_generation, const double& cross_pos, const double& cross_rate, const double& mutate_pos, const double& mutate_rate) { + this->source = source; + this->size = size; + this->max_generation = max_generation; + this->cross_pos = cross_pos; + this->cross_rate = cross_rate; + this->mutate_pos = mutate_pos; + this->mutate_rate = mutate_rate; +} + +void initiallize(Eigenvalue e) { + e.generation = 0; + e.parents.clear(); e.children.clear(); + e.eigenpolyval.clear(); e.sum_cost.clear(); + e.upper_bound = 0.0; + for (int i = 0; i < e.source.get_row(); i++) { + for (int j = 0; j < e.source.get_column(); j++) { + e.upper_bound += std::fabs(e.source(i,j)); + } + } + e.lower_bound = -e.upper_bound; + e.answers.clear(); +} +double Eigenvalue::solve_eigenpolyval(double lam) { + tmp = source; + for (int i = 0; i < source.get_row(); i++) { + tmp(i, i) -= lam; + } + return std::fabs(tmp.determinant()); +} +void solve_total(Eigenvalue e) { + double max_eigenpolyval = 0.0; + e.eigenpolyval.clear(); e.sum_cost.clear(); + for (int i = 0; i < e.size; i++) { + e.eigenpolyval.push_back(e.solve_eigenpolyval(e.parents[i])); + if (e.eigenpolyval[i] > max_eigenpolyval) max_eigenpolyval = e.eigenpolyval[i]; + } + e.sum_cost.push_back(e.eigenpolyval[0]); + for (int i = 1; i < e.size; i++) { + e.sum_cost.push_back(max_eigenpolyval-e.eigenpolyval[i]); + } +} +int Eigenvalue::choose(double proportion) { + for (int i = 0; i < size; i++) if (sum_cost[i] > proportion * sum_cost[size - 1]) return i; +} +void mutate(Eigenvalue e, int idx, bool opt, double ran) { + double tmp = e.children[idx]; + if (opt) { + e.children[idx] += (e.upper_bound - tmp) * (1.0 - std::pow(ran, e.mutate_rate * (double)e.generation / e.max_generation)); + } + else { + e.children[idx] += (tmp - e.lower_bound) * (1.0 - std::pow(ran, e.mutate_rate * (double)e.generation / e.max_generation)); + } +} +void crossover(Eigenvalue e, int ida, int idb, bool opt) { + if (opt) { + e.children.push_back(e.cross_rate * e.parents[idb] + (1.0 - e.cross_rate) * e.parents[ida]); + e.children.push_back(e.cross_rate * e.parents[ida] + (1.0 - e.cross_rate) * e.parents[idb]); + } + else { + e.children.push_back(e.parents[ida]); + e.children.push_back(e.parents[idb]); + } +} +void produce_next(Eigenvalue e, std::mt19937 gen, std::uniform_real_distribution u) { + e.children.clear(); + e.generation++; + solve_total(e); + int ida, idb; + for (int i = 0; i < (e.size >> 1); i++) { + ida = e.choose(u(gen)); + idb = e.choose(u(gen)); + crossover(e, ida, idb, u(gen) u(0.0, 1.0); + if (source.get_column() != source.get_row()) { + std::cerr << "Baka!! Non-square matrices have no eigenvalue!!" << std::endl; + return; + } + initiallize(*this); + std::sort(parents.begin(), parents.end()); + answers.push_back(parents[0]); + for (int i = 1; i < size; i++) if(parents[i]-*answers.end() > eps){ + answers.push_back(parents[i]); + } +} \ No newline at end of file diff --git a/LinearAlgebra/evolution.h b/LinearAlgebra/evolution.h new file mode 100644 index 0000000..8e46bb6 --- /dev/null +++ b/LinearAlgebra/evolution.h @@ -0,0 +1,45 @@ +#pragma once +#ifndef EVOLUTION_H +#define EVOLUTION_H +#include"linearvector.h" +#include"matrix.h" +#include"QuetionA.h" +#include +#include +#include +#include +#include +#include + +class Eigenvalue { +private: + Matrix source; + Matrix tmp; + int size,generation,max_generation; + std::vector parents; + std::vector children; + std::vector eigenpolyval; + std::vector sum_cost; + double cross_pos, cross_rate, mutate_pos, mutate_rate; + double eps = 1e-6; +public: + + double upper_bound, lower_bound; + std::vector answers; + + Eigenvalue(const Matrix&, const int&, const int&, const double&, const double&, const double&, const double&); + ~Eigenvalue()=default; + + friend void initiallize(Eigenvalue); + double solve_eigenpolyval(double x); + friend void solve_total(Eigenvalue); + int choose(double); + friend void mutate(Eigenvalue, int, bool, double); + friend void crossover(Eigenvalue, int, int, bool); + friend void produce_next(Eigenvalue, std::mt19937, std::uniform_real_distribution); + void solve_eigenvalue(); +}; + + +#endif + From cbe9413132523258397b384df08419864c84a2ed Mon Sep 17 00:00:00 2001 From: fbhou <1816118394@qq.com> Date: Sun, 13 Dec 2020 01:55:13 +0800 Subject: [PATCH 3/4] Bug in evolution.cpp fixed --- LinearAlgebra/evolution.cpp | 104 +++++++++++++++++++----------------- LinearAlgebra/evolution.h | 12 ++--- LinearAlgebra/main.cpp | 19 +++++-- 3 files changed, 74 insertions(+), 61 deletions(-) diff --git a/LinearAlgebra/evolution.cpp b/LinearAlgebra/evolution.cpp index 763402a..d3a4e4f 100644 --- a/LinearAlgebra/evolution.cpp +++ b/LinearAlgebra/evolution.cpp @@ -22,86 +22,90 @@ Eigenvalue::Eigenvalue(const Matrix& source, const int& size, const int& max_gen this->mutate_rate = mutate_rate; } -void initiallize(Eigenvalue e) { - e.generation = 0; - e.parents.clear(); e.children.clear(); - e.eigenpolyval.clear(); e.sum_cost.clear(); - e.upper_bound = 0.0; - for (int i = 0; i < e.source.get_row(); i++) { - for (int j = 0; j < e.source.get_column(); j++) { - e.upper_bound += std::fabs(e.source(i,j)); +void Eigenvalue::initiallize(std::mt19937 gen, std::uniform_real_distribution u) { + generation = 0; + parents.clear(); children.clear(); + eigenpolyval.clear(); sum_cost.clear(); + upper_bound = 0.0; + for (int i = 0; i < source.get_row(); i++) { + for (int j = 0; j < source.get_column(); j++) { + upper_bound += std::fabs(source(i,j)); } } - e.lower_bound = -e.upper_bound; - e.answers.clear(); + lower_bound = -upper_bound; + answers.clear(); + for (int i = 0; i < size; i++) { + parents.push_back(u(gen)*(upper_bound-lower_bound)+lower_bound); + } } double Eigenvalue::solve_eigenpolyval(double lam) { - tmp = source; - for (int i = 0; i < source.get_row(); i++) { - tmp(i, i) -= lam; - } - return std::fabs(tmp.determinant()); + return std::fabs((source-lam*identity_matrix(source.get_column())).determinant()); } -void solve_total(Eigenvalue e) { +void Eigenvalue::solve_total() { double max_eigenpolyval = 0.0; - e.eigenpolyval.clear(); e.sum_cost.clear(); - for (int i = 0; i < e.size; i++) { - e.eigenpolyval.push_back(e.solve_eigenpolyval(e.parents[i])); - if (e.eigenpolyval[i] > max_eigenpolyval) max_eigenpolyval = e.eigenpolyval[i]; + eigenpolyval.clear(); sum_cost.clear(); + for (int i = 0; i < size; i++) { + eigenpolyval.push_back(solve_eigenpolyval(parents[i])); + if (eigenpolyval[i] > max_eigenpolyval) max_eigenpolyval = eigenpolyval[i]; } - e.sum_cost.push_back(e.eigenpolyval[0]); - for (int i = 1; i < e.size; i++) { - e.sum_cost.push_back(max_eigenpolyval-e.eigenpolyval[i]); + sum_cost.push_back(max_eigenpolyval - eigenpolyval[0]); + for (int i = 1; i < size; i++) { + sum_cost.push_back(sum_cost[i-1] + max_eigenpolyval - eigenpolyval[i]); } } int Eigenvalue::choose(double proportion) { - for (int i = 0; i < size; i++) if (sum_cost[i] > proportion * sum_cost[size - 1]) return i; + for (int i = 0; i < size; i++) { + if (sum_cost[i] > proportion * sum_cost[size - 1]) return i; + } } -void mutate(Eigenvalue e, int idx, bool opt, double ran) { - double tmp = e.children[idx]; +void Eigenvalue::mutate(int idx, bool opt, double ran) { + double tmp = children[idx]; if (opt) { - e.children[idx] += (e.upper_bound - tmp) * (1.0 - std::pow(ran, e.mutate_rate * (double)e.generation / e.max_generation)); + children[idx] += (upper_bound - tmp) * (1.0 - std::pow(ran, mutate_rate * (double)generation / max_generation)); } else { - e.children[idx] += (tmp - e.lower_bound) * (1.0 - std::pow(ran, e.mutate_rate * (double)e.generation / e.max_generation)); + children[idx] -= (tmp - lower_bound) * (1.0 - std::pow(ran, mutate_rate * (double)generation / max_generation)); } } -void crossover(Eigenvalue e, int ida, int idb, bool opt) { +void Eigenvalue::crossover(int ida, int idb, bool opt) { if (opt) { - e.children.push_back(e.cross_rate * e.parents[idb] + (1.0 - e.cross_rate) * e.parents[ida]); - e.children.push_back(e.cross_rate * e.parents[ida] + (1.0 - e.cross_rate) * e.parents[idb]); + children.push_back(cross_rate * parents[idb] + (1.0 - cross_rate) * parents[ida]); + children.push_back(cross_rate * parents[ida] + (1.0 - cross_rate) * parents[idb]); } else { - e.children.push_back(e.parents[ida]); - e.children.push_back(e.parents[idb]); + children.push_back(parents[ida]); + children.push_back(parents[idb]); } } -void produce_next(Eigenvalue e, std::mt19937 gen, std::uniform_real_distribution u) { - e.children.clear(); - e.generation++; - solve_total(e); +void Eigenvalue::produce_next(std::mt19937 gen, std::uniform_real_distribution u) { + children.clear(); + generation++; + solve_total(); int ida, idb; - for (int i = 0; i < (e.size >> 1); i++) { - ida = e.choose(u(gen)); - idb = e.choose(u(gen)); - crossover(e, ida, idb, u(gen)> 1); i++) { + ida = choose(u(gen)); + idb = choose(u(gen)); + crossover(ida, idb, u(gen) u(0.0, 1.0); if (source.get_column() != source.get_row()) { - std::cerr << "Baka!! Non-square matrices have no eigenvalue!!" << std::endl; + std::cerr << "[ERROR]Non-square matrices have no eigenvalue!!" << std::endl; return; } - initiallize(*this); + initiallize(gen,u); + for (int i = 0; i < max_generation; i++) { + produce_next(gen, u); + } std::sort(parents.begin(), parents.end()); - answers.push_back(parents[0]); - for (int i = 1; i < size; i++) if(parents[i]-*answers.end() > eps){ - answers.push_back(parents[i]); + + for (int i = 0; i < size; i++) { + if (solve_eigenpolyval(parents[i]) < eps2&&(answers.empty()||parents[i]-*(answers.end()-1)>eps)) answers.push_back(parents[i]); } -} \ No newline at end of file +} diff --git a/LinearAlgebra/evolution.h b/LinearAlgebra/evolution.h index 8e46bb6..74ccfdd 100644 --- a/LinearAlgebra/evolution.h +++ b/LinearAlgebra/evolution.h @@ -21,7 +21,7 @@ class Eigenvalue { std::vector eigenpolyval; std::vector sum_cost; double cross_pos, cross_rate, mutate_pos, mutate_rate; - double eps = 1e-6; + double eps = 1e-3, eps2=1e-3; public: double upper_bound, lower_bound; @@ -30,13 +30,13 @@ class Eigenvalue { Eigenvalue(const Matrix&, const int&, const int&, const double&, const double&, const double&, const double&); ~Eigenvalue()=default; - friend void initiallize(Eigenvalue); + void initiallize(std::mt19937, std::uniform_real_distribution); double solve_eigenpolyval(double x); - friend void solve_total(Eigenvalue); + void solve_total(); int choose(double); - friend void mutate(Eigenvalue, int, bool, double); - friend void crossover(Eigenvalue, int, int, bool); - friend void produce_next(Eigenvalue, std::mt19937, std::uniform_real_distribution); + void mutate(int, bool, double); + void crossover(int, int, bool); + void produce_next(std::mt19937, std::uniform_real_distribution); void solve_eigenvalue(); }; diff --git a/LinearAlgebra/main.cpp b/LinearAlgebra/main.cpp index 5d4bc71..61fc774 100644 --- a/LinearAlgebra/main.cpp +++ b/LinearAlgebra/main.cpp @@ -1,12 +1,21 @@ #include #include"QuetionA.h" #include"QuetionB.h" +#include"evolution.h" int main() { - std::cout<<"////////////////////////////////////////QUETION1////////////////////////////////////////"< Date: Tue, 15 Dec 2020 22:13:23 +0800 Subject: [PATCH 4/4] Renamed evolution.cpp/.h as GA.cpp/.h, in consistence with common habits --- LinearAlgebra/{evolution.cpp => GA.cpp} | 2 +- LinearAlgebra/{evolution.h => GA.h} | 2 +- LinearAlgebra/LinearAlgebra.vcxproj | 4 ++-- LinearAlgebra/LinearAlgebra.vcxproj.filters | 4 ++-- LinearAlgebra/main.cpp | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) rename LinearAlgebra/{evolution.cpp => GA.cpp} (99%) rename LinearAlgebra/{evolution.h => GA.h} (97%) diff --git a/LinearAlgebra/evolution.cpp b/LinearAlgebra/GA.cpp similarity index 99% rename from LinearAlgebra/evolution.cpp rename to LinearAlgebra/GA.cpp index d3a4e4f..318e56c 100644 --- a/LinearAlgebra/evolution.cpp +++ b/LinearAlgebra/GA.cpp @@ -1,7 +1,7 @@ #include"linearvector.h" #include"matrix.h" #include"QuetionA.h" -#include"evolution.h" +#include"GA.h" /* source: The Matrix object you want to solve; diff --git a/LinearAlgebra/evolution.h b/LinearAlgebra/GA.h similarity index 97% rename from LinearAlgebra/evolution.h rename to LinearAlgebra/GA.h index 74ccfdd..9bd1fa3 100644 --- a/LinearAlgebra/evolution.h +++ b/LinearAlgebra/GA.h @@ -21,7 +21,7 @@ class Eigenvalue { std::vector eigenpolyval; std::vector sum_cost; double cross_pos, cross_rate, mutate_pos, mutate_rate; - double eps = 1e-3, eps2=1e-3; + double eps = 1e-3, eps2=1e-2; public: double upper_bound, lower_bound; diff --git a/LinearAlgebra/LinearAlgebra.vcxproj b/LinearAlgebra/LinearAlgebra.vcxproj index 005d004..bfc297e 100644 --- a/LinearAlgebra/LinearAlgebra.vcxproj +++ b/LinearAlgebra/LinearAlgebra.vcxproj @@ -140,7 +140,7 @@ - + @@ -148,7 +148,7 @@ - + diff --git a/LinearAlgebra/LinearAlgebra.vcxproj.filters b/LinearAlgebra/LinearAlgebra.vcxproj.filters index 6f824dd..3c6a97f 100644 --- a/LinearAlgebra/LinearAlgebra.vcxproj.filters +++ b/LinearAlgebra/LinearAlgebra.vcxproj.filters @@ -26,7 +26,7 @@ 源文件 - + 源文件 @@ -43,7 +43,7 @@ 头文件 - + 头文件 diff --git a/LinearAlgebra/main.cpp b/LinearAlgebra/main.cpp index 61fc774..c7280dd 100644 --- a/LinearAlgebra/main.cpp +++ b/LinearAlgebra/main.cpp @@ -1,7 +1,7 @@ #include #include"QuetionA.h" #include"QuetionB.h" -#include"evolution.h" +#include"GA.h" int main() { // std::cout<<"////////////////////////////////////////QUETION1////////////////////////////////////////"<