An assignment in the intelligent optimization algorithm course. I reported my attitude towards learning something and didn't download it from the Internet (the vc6 MFC program seems to be on the Internet). I started from scratch and learned how to use STL by the way.
# Include <iostream> <br/> # include <iomanip> <br/> # include <vector> <br/> # include <iterator> <br/> # include <Algorithm> <br/> # include <fstream> <br/> # include <math. h> <br/> # include <time. h> </P> <p> const int ncity = 51; <br/> struct citycoor <br/>{< br/> int Sn, X, Y; <br/>}; <br/> struct sequence <br/>{< br/> double distance; <br/> STD: vector <int> vseqnc; <br/>}; </P> <p> STD: vector <citycoor> vcitycoors (NCI Ty); <br/> STD: vector <double> vdistancematrix (ncity); </P> <p> double computdistance (const STD :: vector <int> & V); </P> <p> namespace ga <br/> {<br/> const int popsize = ncity * 5; <br/> const int Generation = 5000; // The value of const int similar_times = 5000 is changed significantly. <br/> const int similar_times = 200; <br/> const double diff = 1e-15; // The quantitative change is not significant. <br/> const double p_crossover = 0.3; // crossover probability <br/> const double p_mutation = 0.1; // mutation probability <br /> Int ngen = 0; </P> <p> STD: vector <int> vcitysequence (ncity); <br/> STD :: vector <sequence> vchromsome (popsize + 1); // The first chromosome only records the optimal genetic solution of the previous generation and does not participate in genetic computation <br/> STD :: vector <double> vprobability (popsize + 1); </P> <p> namespace itor <br/>{< br/> inline void printsequence (INT Sn) {STD :: cout <Sn <"" ;}< br/> inline void printcitycoors (const citycoor & CC) {STD: cout <CC. SN <"" <CC. x <"" <CC. Y <"/N" ;}< br/> Inline void printchromsome (const sequence & S) {STD: cout <S. distance <";}</P> <p> inline void itordistance (sequence & SE) {se. distance = computdistance (SE. vseqnc) ;}< br/> inline void initchromsome (sequence & V); </P> <p> inline void testprintseqlen (const sequence & S) {STD :: cout <S. vseqnc. size () <";}< br/>}// itor: <br/> inline bool less_second (const sequence & A, const sequence & B) {return. d Istance <B. distance ;}< br/>}// GA :: </P> <p> ///////////////////////////////// //////////////////////////////////////// /<br/> // iterator <br/> typedef STD:: vector <citycoor >:: iterator vitorcitycoor; <br/> typedef STD: vector <int >:: iterator vitorsn; </P> <p> typedef STD :: vector <int >:: size_type vintsize; </P> <p> typedef STD: vector <citycoor >:: const_iterator cvitorcitycoor; <br/> typedef STD :: vector <int>: const_iterat Or cvitorsn; <br/> typedef STD: vector <sequence >:: const_iterator cvitorchromsome; </P> <p> ///////////////////////////////// //////////////////////////////////////// /<br/> STD:: vector <sequence> vtemp (GA: popsize + 1 ); </P> <p> ///////////////////////////////// //////////////////////////////////////// /<br/> // global function, for details, see definition <br/> bool readtsp_data (); <br/> inline double myrand (double, double); <br/> void Crossover (); <br/> void mutation (); <br/> void selection (); <br/> void calcdistancematrix (); </P> <p> bool isvalid (STD: vector <int> V) <br/>{< br/> sort (v. begin (), V. end (); </P> <p> for (STD: vector <int >:: size_type I = 0; I <v. size ()-1; ++ I) <br/> If (V [I] = V [I + 1]) <br/>{< br/> STD:: cout <"sequence error !!!!!!!!! /N "; <br/> STD :: cout <"V [" <I <"]" <"= V [" <I + 1 <"]/n "; <br/> for_each (v. begin (), V. end (), GA: itor: printsequence); <br/> system ("pause"); <br/> return false; <br/>}< br/> STD: cout <"sequence correct/N"; <br/> return true; <br/>}</P> <p> int main () <br/> {<br/> /////////////////////////////// //////////////////////////////////////// /// <br/> STD:: cout <"# Read data"; <br/> If (! Readtsp_data () <br/>{< br/> STD: cerr <"--- An error occurred while reading the city coordinates! "; <Br/> exit (1); <br/>}< br/> STD: cout <" OK/N "; <br/> clock_t starttime = clock (); </P> <p> STD: cout <"# Calculate the city distance matrix"; <br/> calcdistancematrix (); <br/> STD: cout <"OK/N"; </P> <p> // evaluate the adaptive function <br/> GA :: vprobability [0] = 0.05; <br/> double A = 0.05; <br/> for (INT I = 1; I <= GA: popsize; ++ I) <br/> {<br/> A * = 0.95; <br/> GA: vprobability [I] = GA: vprobability [I-1] +; <br/>}< br/> /////////////////////////////// /////// /// // <Br/> STD:: cout <"# initialization" <GA: popsize <"chromosome:"; <br/> for_each (GA: vchromsome. begin () + 1, GA: vchromsome. end (), GA: itor: initchromsome); <br/> STD: cout <"OK/N"; </P> <p> GA :: vchromsome [0] = GA: vchromsome [1]; <br/> // first, it is eliminated once to optimize the initial value <br/> sort (GA: vchromsome. begin () + 1, GA: vchromsome. end (), GA: less_second ); </P> <p> ///////////////////////////////// ///////////////////// //////////////// <Br/> STD: cout <"/N # Start the genetic algorithm, the end condition is "<GA: similar_times <" generation change less than "<GA: Diff <""; </P> <p> int generwidth = static_cast <int> (Ceil (log10 (static_cast <double> (GA: Generation )))); <br/> for (INT I = 1; I <= GA: generation; ++ I) <br/>{< br/> selection (); <br/> double prevdistance = GA: vchromsome [0]. distance; </P> <p> srand (static_cast <unsigned> (Time (null); <br/> crossover (); <br/> mutation (); </P> <p> // calculate the distance between each chromosome <br/> for_each (GA: vchromsome. begin () + 1, GA: vchromsome. end (), GA: itor: itordistance); <br/> // evolution, good solution (small) before, the optimal solution of the previous generation is also included in <br/> sort (GA: vchromsome. begin (), GA: vchromsome. end (), GA: less_second); </P> <p> STD: cout <"/N"; <br/> STD :: cout <STD: setfill ('') <STD: SETW (generwidth) <I; <br/> STD :: cout <"shortest =" <GA: vchromsome [0]. distance; </P> <p> If (prevdistance-GA: vchroms Ome [0]. distance <GA: Diff) ++ GA: ngen; <br/> else GA: ngen = 0; </P> <p> If (GA :: similar_times <GA: ngen) break; <br/>}</P> <p> STD: cout <"/n # Test Result-> "; <br/> isvalid (GA: vchromsome [0]. vseqnc); </P> <p> for_each (GA: vchromsome [0]. vseqnc. begin (), GA: vchromsome [0]. vseqnc. end (), GA: itor: printsequence); <br/> STD: cout <"/N"; </P> <p> STD :: cout <"/n usage time:" <static_cast <double> (clock ()-starttime)/clocks_pe R_sec <"SEC/N"; <br/> system ("pause"); <br/> return 0; <br/>}</P> <p> bool readtsp_data () <br/>{< br/> try <br/>{< br/> STD :: ifstream fin ("TSP. data "); <br/> for (vitorcitycoor I = vcitycoors. begin (); I! = Vcitycoors. end (); ++ I) <br/>{< br/> fin> (* I ). sn> (* I ). x> (* I ). y; <br/>}< br/> fin. close (); <br/>}< br/> catch (...) <br/>{< br/> return false; <br/>}< br/> return true; <br/>}</P> <p> // greedy algorithm right <br/> int greedyright (STD: vector <int> & cityrouter, int ncity) <br/>{< br/> bool bfindcity = false; <br/> vitorsn iter_city; <br/> for (iter_city = cityrouter. begin (); iter_city! = Cityrouter. end (); ++ iter_city) <br/> If (* iter_city = ncity) <br/>{< br/> bfindcity = true; <br/> break; <br/>}</P> <p> If (bfindcity) <br/>{< br/> + + iter_city; <br/> If (iter_city = cityrouter. end () <br/> iter_city = cityrouter. begin (); </P> <p> return * iter_city; <br/>}< br/> else <br/> return-1; <br/>}</P> <p> // greedy algorithm left <br/> int greedyleft (STD: vector <int> & cityrouter, int ncity) <br/> {<br/> bool BF Indcity = false; <br/> vitorsn iter_city; <br/> for (iter_city = cityrouter. Begin (); iter_city! = Cityrouter. end (); ++ iter_city) <br/> If (* iter_city = ncity) <br/>{< br/> bfindcity = true; <br/> break; <br/>}</P> <p> If (bfindcity) <br/>{< br/> If (iter_city = cityrouter. begin () <br/> return cityrouter. back (); <br/> else <br/>{< br/> -- iter_city; <br/> return * iter_city; <br/>}< br/> else <br/> return-1; <br/>}</P> <p> void greedyerase (STD:: vector <int> & cityrouter, int ndelcity) <br/> {<br /> Bool bfindcity = false; <br/> vitorsn iter_city; <br/> for (iter_city = cityrouter. Begin (); iter_city! = Cityrouter. end (); ++ iter_city) <br/> If (* iter_city = ndelcity) <br/>{< br/> bfindcity = true; <br/> break; <br/>}</P> <p> If (bfindcity) cityrouter. erase (iter_city ); <br/>}</P> <p> //************************** * ********* <br/> // method: docrossover <br/> // fullname: docrossover <br/> // access: Public <br/> // returns: void <br/> // parameter: int nfathera <br/> // parameter: int nfatherb <br/> // quali Fier: greedy crossover. <br/> // For details about the algorithm, See Xie Shengli. an Improved Genetic Algorithm for Solving the TSP problem [J]. computer Engineering and application, 2002 (8): 58 ~ 245. See the download directory <br/> //******************************* ***** <br/> void docrossover (INT nfathera, int nfatherb) <br/>{< br/> int randomcity, nowopcity, nextopcity, righta, rightb, lefta, leftb; <br/> STD: vector <int> Sona, sonb; </P> <p> randomcity = static_cast <int> (myrand (1, ncity); </P> <p> nowopcity = randomcity; <br/> Sona. push_back (nowopcity); </P> <p> STD: vector <int> fathera = GA: vchromsome [nfathera]. vseqnc; <B R/> STD: vector <int> fatherb = GA: vchromsome [nfatherb]. vseqnc; </P> <p> while (fathera. size ()> 1 & fatherb. size ()> 1) <br/>{< br/> righta = greedyright (fathera, nowopcity); <br/> rightb = greedyright (fatherb, nowopcity ); </P> <p> If (vdistancematrix [nowopcity-1] [rightA-1] <vdistancematrix [nowopcity-1] [rightB-1]) <br/> {<br/> Sona. push_back (righta); <br/> nextopcity = righta; <br/>}< br/> else <br />{< Br/> Sona. push_back (rightb); <br/> nextopcity = rightb; <br/>}</P> <p> greedyerase (fathera, nowopcity); <br/> greedyerase (fatherb, nowopcity); <br/> nowopcity = nextopcity; <br/>}</P> <p> nowopcity = randomcity; <br/> sonb. push_back (nowopcity); <br/> fathera = GA: vchromsome [nfathera]. vseqnc; <br/> fatherb = GA: vchromsome [nfatherb]. vseqnc; </P> <p> while (fathera. size ()> 1 & fatherb. size ()> 1) <Br/>{< br/> lefta = greedyleft (fathera, nowopcity); <br/> leftb = greedyleft (fatherb, nowopcity ); </P> <p> If (vdistancematrix [nowopcity-1] [leftA-1] <vdistancematrix [nowopcity-1] [leftB-1]) <br/> {<br/> sonb. push_back (lefta); <br/> nextopcity = lefta; <br/>}< br/> else <br/>{< br/> sonb. push_back (leftb); <br/> nextopcity = leftb; <br/>}</P> <p> greedyerase (fathera, nowopcity); <br/> greedyerase (F Atherb, nowopcity); <br/> nowopcity = nextopcity; <br/>}</P> <p> swap (GA: vchromsome [nfathera]. vseqnc, Sona); <br/> swap (GA: vchromsome [nfatherb]. vseqnc, sonb ); <br/>}</P> <p> //************************** * ********* <br/> // method: crossover <br/> // fullname: crossover <br/> // access: Public <br/> // returns: void <br/> // qualifier: mating <br/> //********************************* *** <br/> void crossover () <br />{< Br/> STD: vector <int> veccrossoverindexs; <br/> double random; </P> <p> for (INT I = 1; I <= GA: popsize; I ++) <br/>{< br/> random = static_cast <double> (myrand (0, 1 )); <br/> If (random <GA: p_crossover) <br/> veccrossoverindexs. push_back (I); <br/>}</P> <p> size_t crossovernumber = veccrossoverindexs. size (); <br/> If (crossovernumber % 2! = 0) <br/> veccrossoverindexs. pop_back (); </P> <p> crossovernumber = veccrossoverindexs. size (); <br/> for (size_t I = 0; I <crossovernumber; I + = 2) <br/>{< br/> int nfathera = veccrossoverindexs [I]; <br/> int nfatherb = veccrossoverindexs [I + 1]; </P> <p> docrossover (nfathera, nfatherb); <br/>}</P> <p> void GA: itor :: initchromsome (sequence & V) <br/>{< br/> v. vseqnc. resize (ncity); </P> <p> for (INT I = 1; I <= NCIT Y; ++ I) <br/> v. vseqnc [I-1] = I; </P> <p> STD: random_shuffle (v. vseqnc. begin (), V. vseqnc. end (); <br/> v. distance = computdistance (v. vseqnc); <br/> STD: cout <". "; <br/>}</P> <p> //************************** * ********* <br/> // method: myrand <br/> // fullname: myrand <br/> // access: Public <br/> // returns: Double <br/> // qualifier: <br/> // parameter: Double A <br/> // parameter: Double B <br/> // uniform di Stribution <br/> // return a random num in area [, b] <br/> //******************************** * *** <br/> double myrand (double, double B) <br/>{< br/> double y; <br/> If (A> B) {<br/> printf ("/nthe first parameter shocould be less than the second! "); <Br/> exit (1 ); <br/>}< br/> /////////////////////////////// //////////////////////////////////////// /// <br/> // rand () can Reture a number in [0, rand_max] <br/> Y = static_cast <double> (RAND ()/rand_max; </P> <p> return (a + (B-a) * y ); <br/>}</P> <p> //************************** * ********* <br/> // method: mutation <br/> // fullname: mutation <br/> // access: Public <br/> // returns: void <br/> // qualifier: mutation Random city shuffling between two random locations <br/> //************************** * ********* <br/> void mutation () <br/> {<br/> vitorsn it; <br/> for (INT I = 1; I <= GA: popsize; ++ I) <br/> If (GA: p_mutation> myrand (0, 1) <br/>{< br/> int left = static_cast <int> (myrand (0, ncity/2); <br/> int right = static_cast <int> (myrand (ncity/2, ncity); <br/> it = GA :: vchromsome [I]. vseqnc. begin (); </P> <p> STD: random_shuffle (IT + left, it + right); <br/ >}< Br/>}</P> <p> double computdistance (const STD: vector <int> & V) <br/> {<br/> double TMP = 0.0; </P> <p> for (INT it = 0; it <NCITY-1; ++ it) <br/> TMP + = vdistancematrix [V [it]-1] [V [It + 1]-1]; </P> <p> TMP + = vdistancematrix [V [NCITY-1]-1] [V [0]-1]; <br/> return TMP; <br/>}</P> <p> //************************** * ********* <br/> // method: selection <br/> // fullname: selection <br/> // access: Public <br/> // returns: Void <br/> // qualifier: Select, make a round bet, let the previous solution (good solution) select with a high probability <br/> //**************************** * ******* <br/> void selection () <br/>{< br/> double r; <br/> int label; </P> <p> vtemp [0] = GA: vchromsome [0]; // use the first record only <br/> for (INT I = 1; I <= GA: popsize; ++ I) <br/>{< br/> r = myrand (0, GA: vprobability [GA: popsize]); <br/> label = 0; <br/> for (Int J = 0; j <= GA: popsize; ++ J) <br/>{< br/> If (r <= GA :: vprobability [J]) <BR/>{< br/> label = J; <br/> break; <br/>}< br/> vtemp [I] = GA :: vchromsome [label]; <br/>}</P> <p> swap (GA: vchromsome, vtemp ); <br/>}</P> <p> //************************** * ********* <br/> // method: calcdistancematrix <br/> // fullname: calcdistancematrix <br/> // access: Public <br/> // returns: void <br/> // qualifier: the distance matrix between cities is calculated in advance for later query, typical space change time <br/> //***************************** * ****** <br/> void Calcdistancematrix () <br/>{< br/> double dltx, dlty; </P> <p> STD: vector <double> :: iterator it = vdistancematrix. begin (); <br/> for (; it! = Vdistancematrix. end (); ++ it) <br/> (* it ). resize (ncity); </P> <p> for (INT I = 0; I <ncity; ++ I) <br/> for (Int J = I; j <ncity; ++ J) <br/> if (I = J) vdistancematrix [I] [J] = 0.0; <br/> else <br/> {<br/> dltx = vcitycoors [I]. x-vcitycoors [J]. x; <br/> dlty = vcitycoors [I]. y-vcitycoors [J]. y; <br/> vdistancematrix [I] [J] = SQRT (static_cast <double> (dltx * dltx + dlty * dlty )); <br/> vdistancematrix [J] [I] = vdistancematrix [I] [J]; <br/>}< br/>}
Running result:
# Read data OK
# Computing the city distance matrix OK
# Initialize the 255 chromosomes :.................................. ........................................ ........................................ ..........................
........................................ ........................................ ................................... OK
# Start genetic algorithm. The ending condition is 200 consecutive generations with changes less than 1e-015
Shortest Distance of generation 1st = 971.792
Shortest Distance of generation 2nd = 892.135
Shortest Distance of generation 3rd = 713.293
Shortest Distance of generation 4th = 670.46
Shortest Distance of generation 5th = 621.353
Shortest Distance of generation 6th = 597.599
Shortest Distance of generation 7th = 553.647
Shortest Distance of generation 8th = 523.755
Shortest Distance of generation 9th = 519.167
Shortest Distance of generation 10th = 494.994
Shortest Distance of generation 11th = 484.889
Shortest Distance of generation 12th = 477.425
Shortest Distance of generation 13th = 468.237
Shortest Distance of generation 14th = 449.349
Shortest Distance of generation 15th = 449.349
Shortest Distance of generation 16th = 446.246
Shortest Distance of generation 17th = 446.246
Shortest Distance of generation 18th = 446.246
Shortest Distance of generation 19th = 446.246
Shortest Distance of generation 20th = 445.269
Shortest Distance of generation 21st = 441.656
Shortest Distance of generation 22nd = 440.679
Shortest Distance of generation 23rd = 436.875
(The decimal places between the first generation and the second generation are equal to the third decimal places, which are not listed here)
Shortest Distance of generation 226th = 436.875
# Test Result-> the sequence is correct
1 22 2 21 29 20 35 36 3 28 31 26 8 48 6 23 7 43 24 14 25 13 41 19 42 44 15 45
33 39 10 30 34 50 16 11 38 9 49 5 37 17 4 18 47 12 46 51 27 32
Total time used: 1.931 seconds
Press any key to continue...
The greedy crossover greatly improves the convergence speed.