Advertisement
Guest User

Untitled

a guest
Nov 27th, 2015
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.61 KB | None | 0 0
  1. /*********************************************************************
  2. * Traveller Salesman algorithm implemented *
  3. * By : Arash DAKLAN *
  4. * Date : September 2015 *
  5. * Course Program : initiation a l'algorithmique system *
  6. * Proffessor : Xavier Gandibleux *
  7. * *******************************************************************/
  8.  
  9.  
  10.  
  11. /* Warning: This program, when executed in /bin generates two groups of
  12. files and saves them in the currently empty directory /temp. The
  13. files of these two groups have extensions .xe or .txt. The previous
  14. are the scripts produced by the program te become exetutable later
  15. via chmod comand and when executed produce the plots by gnuplot. The
  16. .txt files are the data file produced by program and used by the .xe
  17. files in the process of drawing the plot by gnuplot.
  18. The program reads the dat from a text file in the format already
  19. prepared. It is possible to use any data file in the format of the
  20. existing in the dirctory /dat.
  21. */
  22.  
  23. #include<stdio.h>
  24. #include<math.h>
  25. #include<time.h>
  26.  
  27. #define N 16
  28.  
  29. /**********************************************************************
  30. * Function Prototypes *
  31. *********************************************************************/
  32.  
  33. //We use this function to initialize hamiltonian_path matrix and also
  34. //to initialize a test matrix in the fucntion produce_hamiltonia_path
  35. //in odere to prevent a city from being chosen twice
  36.  
  37. void initialize_1D(int n, int array_1D[n]);
  38.  
  39. void initialize_2D(int n, float array_2D[n][n]);
  40.  
  41.  
  42. //This function produces a symmetrin N by N matrix containig the
  43. //distnaces between cities
  44. void produce_distance_array(int n, float distance[n][n],
  45. float coordinate[n][2]);
  46.  
  47. //This function produces the final result we are searching for the
  48. //wnated hamiltonian path is being produced as a series of numbers
  49. //each correspoinding to a city. We read in the main routine the
  50. //elements of this array in order and one by one then we choose the
  51. //corresponding name of the city from the matrix defined and
  52. //initialized in main
  53. void produce_hamiltonian_path(int n, int hamiltonian_p[n]);
  54.  
  55.  
  56. //This function modifies the hamiltonian path replacing it with the one that always
  57. //choses the nearest city to the current one
  58. void modified_hamiltonian(int n, int hamiltonian_p[n], float distance[n][n]);
  59.  
  60.  
  61. //This function measures the path-length travelled by the traveller
  62. float path_length(int n, float[n][n], int hamiltonian_p[n]);
  63.  
  64. //This fucntion finds the nearest city fo a given city
  65. int find_nearest(int index, int n, int test[n], float distance[n][n]);
  66.  
  67. //This function finds if with a change in the order of the cities we
  68. //can make the travel shorter
  69. void find_opt_path(int n, float distance[n][n],
  70. int hamiltonian_p[n]);
  71. /*
  72. //This function implements the 2-opt algorithme. This function calls
  73. //two other functions to do this job. One is the one right above, called
  74. //find_opt_path which finds if there is a shorter path and after finding
  75. //the corresponging answer, changes the order of the cities. In this
  76. //last process it calls repeatedly another fucntion called swap() which
  77. //just swaps two elemnts of the matrix passed to it as the addresses.
  78. void opt_hamiltonian(int nb, int hamiltonian_p[nb+1],
  79. float distance[nb][nb]);
  80. */
  81.  
  82. //This is the function that receives an array and the addresses of
  83. //two elemts to be changed and changes them.
  84. void swap(int *first, int *second);
  85.  
  86. // Thes two last functions are to display the matrixes
  87. void display_1D(int n, int array_1D[n]);
  88.  
  89. void display_2D(int n, int m, float array_2D[n][m]);
  90.  
  91.  
  92. //This function saves the results in a file to be managed then to
  93. //plot the diagram with gjuplot
  94. void gnu_results(int n, int hamiltonian_p[n], float coordinate[n][2],
  95. float distance[n][n], char file_name[10]);
  96.  
  97.  
  98. //This function generates the script files to be used for ploting
  99. //the final reslt with gnuplot
  100. void gnu_plot_file(char file_name[10], char source[10], char title[25],
  101. char destination[10], float path_langth);
  102.  
  103.  
  104.  
  105.  
  106. char city_names[N][25] = {"Carquefou", "Nort-sur-Erdre", "Ancenis", "Saint-Luce-sur-Loire", "Rouans", "Vertou", "Clisson", "Machecoul", "Vieillevigne", "Savenay",
  107. "Orvault", "Saint-Herblain", "Reze", "Vallet",
  108. "Saint-Philbert-de-GL", "Bouin"};
  109.  
  110.  
  111.  
  112. /**********************************************************************
  113. * MAIN FUNCTION *
  114. *********************************************************************/
  115.  
  116. int main(void)
  117. {
  118. /*Partie declaration */
  119.  
  120. float total_distance;
  121. int hamiltonian_path[N];
  122. float array_distance[N][N];
  123. float coordinate[N][2];
  124.  
  125.  
  126.  
  127.  
  128. /*Partie Execution*/
  129.  
  130. //initializing the arrays
  131. initialize_1D(N, hamiltonian_path);
  132. initialize_2D(N, array_distance);
  133.  
  134. //this parts generates the distance array and the array for the hamiltonian path
  135. produce_distance_array(N, array_distance, coordinate);
  136. produce_hamiltonian_path(N, hamiltonian_path);
  137.  
  138.  
  139. printf("\nHere comes the hamiltonian path for the cities: \n\n");
  140. display_1D(N, hamiltonian_path);
  141.  
  142. //evaluates the entire travelled length
  143. total_distance = path_length(N, array_distance, hamiltonian_path);
  144.  
  145. printf("The total distqnce is = %f\n", total_distance);
  146. //Produces the data in a text file to be used by gnuplot-script
  147. gnu_results(N, hamiltonian_path, coordinate, array_distance, "./../temp/hamiltonian.txt");
  148.  
  149. //generates a script for gnuplot.
  150. gnu_plot_file("./../temp/hamiltonian.xe", "./../temp/hamiltonian.txt", "Hamiltonian Path", "./../temp/plot_1.png", total_distance);
  151.  
  152.  
  153.  
  154. printf("\nThe modified hamiltonian path is:\n ");
  155. modified_hamiltonian(N, hamiltonian_path, array_distance);
  156. display_1D(N, hamiltonian_path);
  157.  
  158.  
  159. //evaluates teh total distance
  160. total_distance = path_length(N, array_distance, hamiltonian_path);
  161. //generates the datd file to be used by gnuplot-script
  162. gnu_results(N, hamiltonian_path, coordinate, array_distance, "./../temp/modified.txt");
  163.  
  164. //generates gnuplot script file
  165. gnu_plot_file("./../temp/modified.xe", "./../temp/modified.txt",
  166. "Modified Hamiltonian Path", "./../temp/plot_2.png",
  167. total_distance);
  168.  
  169.  
  170. printf("The distance traveled in this modified version = %f\n",
  171. total_distance);
  172.  
  173. find_opt_path(N, array_distance, hamiltonian_path);
  174. printf("\nThe List of the cities after otimization\n ");
  175.  
  176. display_1D(N, hamiltonian_path);
  177.  
  178. //evaluates teh totla distance
  179. total_distance = path_length(N, array_distance, hamiltonian_path);
  180.  
  181.  
  182. printf("\nTotal distance traveled in optimized algorithm = %5.2f\n", total_distance);
  183.  
  184. //generates the data file to be used by gnuplot-script
  185. gnu_results(N, hamiltonian_path, coordinate, array_distance,"./../temp/optimum.txt");
  186.  
  187. //generates gnuplot script-file
  188. gnu_plot_file("./../temp/optimum.xe", "./../temp/optimum.txt", "2-Opt", "./../temp/plot_3.png", total_distance);
  189. system("/bin/gnuplot ./../temp/hamiltonian.xe");
  190. system("/bin/gnuplot ./../temp/modified.xe");
  191. system("/bin/gnuplot ./../temp/optimum.xe");
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199. return 0;
  200. }
  201.  
  202. /**********************************************************************
  203. * Definition of Functions *
  204. *********************************************************************/
  205.  
  206. //This fucntion gets an integer for the dimension of the array and the
  207. //address of the array and returns nothing
  208.  
  209. void initialize_1D(int n, int array_1D[n])
  210. {
  211. int i;
  212. for (i = 0; i < n; i++)
  213. array_1D[i] = 0;
  214. }
  215.  
  216. //This function gets an integer for the dimension of a square matrix
  217. //and the address of a matrix whose elements are floating point reals
  218. //and returns nothing
  219.  
  220. void initialize_2D(int n, float array_2D[n][n])
  221. {
  222. int i, j;
  223.  
  224. for (i = 0; i < n; i++)
  225. for (j = 0; j < n; j++)
  226. array_2D[i][j] = 0;
  227. }
  228.  
  229. //This function gets an integer for the dimension of the matrix and
  230. //the address of the matrix as its argument and changes the lements of
  231. //the matrix to which it has got the address. the elements
  232. //distance[i][j] are the distance between the cities i and j, and
  233. //because we have considered the distance betweeen cities to be
  234. //symmteric, the resulting matrxi is symmetric
  235. void produce_distance_array(int n, float distance[n][n],
  236. float coordinate[n][2])
  237. {
  238. int i, j, k = 0; //indexes of the matrix
  239.  
  240. //coordinates of the two cities which we want to measure their
  241. //distance
  242. float x_1, y_1, x_2, y_2;
  243.  
  244. //the square root of this variable will be the distance we are
  245. //interested in
  246. float distance_squared;
  247.  
  248. for (i = 0; i < n; i++)
  249. {
  250. for (j =0; j < 2; j++)
  251. {
  252. scanf("%f", &x_1);
  253. coordinate[i][j] = x_1;
  254. }
  255. }
  256.  
  257. for (i = 0; i < n; i++)
  258. {
  259. x_1 = coordinate[i][k++];
  260. y_1 = coordinate[i][k];
  261. k=0;
  262. for (j = 0; j < n; j++)
  263. {
  264. if(i < j )
  265. {
  266. x_2 = coordinate[j][k++];
  267. y_2 = coordinate[j][k];
  268. distance_squared = pow((x_1 - x_2), 2.0) +
  269. pow((y_1 - y_2), 2.0);
  270. distance[i][j] = sqrt(distance_squared);
  271. distance[j][i] = distance[i][j];
  272. }
  273. k = 0;
  274. }
  275. k =0;
  276. }
  277.  
  278. }
  279.  
  280. //This is the function that produces what we want: The Hamiltonian Path
  281. //This function getes an integer as the dimension of the 1_d array and
  282. //using a random process produces the sequence of numbers corresponding
  283. //to cities in a way that each city comes just once. If we connect the
  284. //last member to the firts element then we have the result we wanted
  285. void produce_hamiltonian_path(int n, int hamiltonian_p[n])
  286. {
  287. int i = 0, j;
  288.  
  289. //This array is going to be initialized with zeros. Then each time a
  290. //random number has been chosen the corresponding element of this array
  291. //will be set to 1 and when producing the random number we can chech
  292. //if it has been chosen before or not.
  293. int test[n];
  294.  
  295. srand(time(NULL));
  296.  
  297. initialize_1D(n , test);
  298.  
  299. while(i < n)
  300. {
  301. j = rand() % n;
  302.  
  303. if (test[j] == 0)
  304. {
  305. hamiltonian_p[i] = j;
  306. i++;
  307. test[j] = 1;
  308. }
  309. }
  310.  
  311. }
  312.  
  313. //This function calculates the total length travelled by the traveller
  314. float path_length(int n, float distance_array[n][n],
  315. int hamiltonian_p[n])
  316. {
  317. float sum = 0;
  318. int i = 0;
  319.  
  320. /*the next variable is here to save the index of the first city. We will use this
  321. to add the disatnce betwen the first and the last cities to the sum the for-loop
  322. calculates.
  323. */
  324. int fix;
  325.  
  326. // the next two variables are going to used to index the elements of the disatnce array
  327. int row_index;
  328. int col_index;
  329.  
  330. fix = row_index = hamiltonian_p[i];
  331.  
  332. for (i = 1; i < n; i++)
  333. {
  334. col_index = hamiltonian_p[i];
  335. sum += distance_array[row_index][col_index];
  336. row_index = col_index;
  337.  
  338. }
  339. sum += distance_array[col_index][fix];
  340. return sum;
  341. }
  342.  
  343. //This function gets as argumnet the indexof city and finds the nearest city to it and
  344. //returns the index to the city it finds
  345. int find_nearest(int index, int n, int test[n], float distance[n][n])
  346. {
  347. int i = 0, j;
  348. float min;
  349. int min_index; //this is the variable that will be returned to the caller function
  350. if (index != i)
  351. {
  352. while(test[i] == 1)
  353. i++;
  354. min = distance[index][i];
  355. }
  356. else
  357. {
  358. i++;
  359. while(test[i] == 1)
  360. i++;
  361. min = distance[index][i];
  362. }
  363. min_index = i;
  364. j = i;
  365. for(i = j+1; i < n ; i++)
  366. {
  367. if (test[i] == 0 && distance[index][i] < min)
  368. {
  369. min = distance[index][i];
  370. min_index = i;
  371. }
  372.  
  373. }
  374. return min_index;
  375. }
  376.  
  377. //This function is the modified hamiltonian path which selects the cities one by one
  378. //based on their distance to the curent city. Based on this new algorithm traveller
  379. //in each city selects the city nearest to the one (s)he currently resides.
  380. void modified_hamiltonian(int n, int hamiltonian_p[n], float distance[n][n])
  381. {
  382. int i = 0 , index;
  383. int test[n];
  384. initialize_1D(n , test);
  385. index = rand() % n;
  386. test[index] = 1;
  387. hamiltonian_p[i] = index;
  388.  
  389. for(i = 1; i < n; i++)
  390. {
  391. index = find_nearest(index, n, test, distance);
  392. hamiltonian_p[i] = index;
  393. test[index] = 1;
  394. }
  395. }
  396.  
  397.  
  398. //This function gets a 2-D array whose elements are the distances
  399. //between the cities and and one one dimensional array of
  400. //hamiltonian path and checks if there are shorter paths. If yes
  401. //modifies the hamiltonian_path matrix and repeats this action, until
  402. //reaches to the point where no change is possible to make a shorter
  403. //path.
  404. void find_opt_path(int n, float distance[n][n],
  405. int hamiltonian_p[n])
  406. {
  407. int i, j, number;
  408. int opt_i=0, opt_j=0, m, p, m_1, p_1;
  409. float difference , min_path;
  410.  
  411. do
  412. {
  413. min_path = 0;
  414. for(i = 0; i < n-2; i++)
  415. {
  416. for (j = (i + 2)%n; j != (n+i-2)%n; j = (j+1)%n)
  417. {
  418. m = hamiltonian_p[i]; p = hamiltonian_p[j];
  419. m_1 = hamiltonian_p[i+1]; p_1=hamiltonian_p[(j+1)%n];
  420. difference = distance[m][p] + distance[m_1][p_1]
  421. - distance[m][m_1] - distance[p][p_1];
  422.  
  423. if (difference < min_path)
  424. {
  425. min_path = difference;
  426. opt_i = i;
  427. opt_j = j;
  428. }
  429. }
  430. }
  431.  
  432. number = ((opt_j - opt_i + n) % n ) / 2;
  433. for (i =0; i < number; i++)
  434. {
  435. opt_i++;
  436. swap (&hamiltonian_p[opt_i%n], &hamiltonian_p[opt_j]);
  437. opt_j--;
  438. if (opt_j < 0) opt_j = opt_j + n;
  439.  
  440. }
  441.  
  442. } while (min_path < 0);
  443. }
  444.  
  445. //
  446.  
  447. void gnu_results(int n, int hamiltonian_p[n], float coordinate[n][2],
  448. float distance[n][n], char file_name[10])
  449. {
  450. int i, j, k, index, index_p;
  451. float total_distance;
  452. FILE *fwrite;
  453.  
  454. total_distance = path_length(n, distance, hamiltonian_p);
  455. fwrite = fopen(file_name, "w");
  456. fprintf(fwrite, "%s", "# x_1-----y_1----------city-------------------x_2---------y_2\n");
  457. fprintf(fwrite, "#The total ditance travelled = %5.2f\n\n", total_distance);
  458. for (i=0, j=0, k=0; i < n; i++)
  459. {
  460. index = hamiltonian_p[i];
  461. index_p = hamiltonian_p[k%n];
  462. fprintf(fwrite, "%7.2f", coordinate[index_p][j++]);
  463. fprintf(fwrite, "%7.2f", coordinate[index_p][j--]);
  464. fprintf(fwrite, " %-25s", city_names[index]);
  465. k++;
  466. index_p =hamiltonian_p[k%n];
  467. fprintf(fwrite, "%10.2f", coordinate[index_p][j++]);
  468. fprintf(fwrite, "%10.2f\n", coordinate[index_p][j--]);
  469. }
  470. fclose(fwrite);
  471. }
  472.  
  473.  
  474. //This function generates the script files to be used for ploting
  475. //the final reslt with gnuplot
  476.  
  477. void gnu_plot_file(char file_name[10], char source[10], char title[25],
  478. char destination[10], float path_length)
  479. {
  480. FILE *fp;
  481. fp = fopen(file_name, "w");
  482. if (fp == NULL)
  483. fprintf(stderr, "Imposible to open %s\n", file_name);
  484.  
  485. fprintf(fp, "#!/usr/bin/gnuplot -persist\n");
  486. fprintf(fp, "set terminal push\n");
  487. fprintf(fp, "set terminal png\n");
  488. fprintf(fp, "set output \"%s\"\n", destination);
  489. fprintf(fp, "set title \"%s %5.2f km\" \n", title, path_length);
  490. fprintf(fp, "set xlabel \"X\"\n");
  491. fprintf(fp, "set ylabel \"Y\"\n");
  492. fprintf(fp, "set xrang[0:100]\n" );
  493. fprintf(fp, "set yrang[0:100]\n");
  494. fprintf(fp, "plot \"%s\" u 1:2:($4-$1):($5-$2) with vectors,\"\" u 1:2:3 with labels\n", source);
  495. fprintf(fp, "set terminal x11\n");
  496. fprintf(fp, "set output\n");
  497. fprintf(fp, "set terminal pop\n");
  498. fprintf(fp, "set terminal x11\n");
  499. fprintf(fp, "replot");
  500. fflush(fp);
  501. fclose(fp);
  502. }
  503.  
  504.  
  505.  
  506. void swap(int *first, int *second)
  507. {
  508. int temp;
  509.  
  510. temp = *first;
  511. *first = *second;
  512. *second = temp;
  513. }
  514.  
  515. //These two last functions dipaly the result
  516. void display_1D(int n, int array_1D[n])
  517. {
  518. int i, j;
  519. for (i =0; i < n; i++)
  520. {
  521. j = array_1D[i];
  522. printf("%s\n", city_names[j]);
  523. }
  524. }
  525.  
  526.  
  527. void display_2D(int n, int m, float array_2D[n][n])
  528. {
  529. int i, j;
  530. for (i = 0; i < n; i++)
  531. {
  532. for (j = 0; j < m; j++)
  533. printf("Tab[%d][%d] = %5.2f \n", i+1, j+1, array_2D[i][j]);
  534. printf("\n");
  535. }
  536. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement