C ++ source code for solving the TSP Problem Using Genetic Algorithms

Source: Internet
Author: User

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.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.