PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/ant_colony.c

https://gitlab.com/fpadula/ant_tsp
C | 412 lines | 350 code | 46 blank | 16 comment | 76 complexity | dda7cc34aa9ebd55dc0bed6c268ba7e2 MD5 | raw file
  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include <math.h>
  6. #include <float.h>
  7. #include <string.h>
  8. #include "ant_colony.h"
  9. float eucli2d(graph_n *node1, graph_n *node2){
  10. return ( sqrtf( powf( (node1->x - node2->x), 2 ) + powf( (node1->y - node2->y), 2 )) );
  11. }
  12. long random_at_most(long max) {
  13. unsigned long
  14. /* max <= RAND_MAX < ULONG_MAX, so this is okay. */
  15. num_bins = (unsigned long) max + 1,
  16. num_rand = (unsigned long) RAND_MAX + 1,
  17. bin_size = num_rand / num_bins,
  18. defect = num_rand % num_bins;
  19. long x;
  20. do {
  21. x = random();
  22. }
  23. /* This is carefully written not to overflow */
  24. while (num_rand - defect <= (unsigned long)x);
  25. /* Truncated division is intentional*/
  26. return x/bin_size;
  27. }
  28. graph_n *get_graph_node_with_number(graph *graph, int node_number){
  29. int i;
  30. if(graph->graph_nodes[node_number-1].node_number == node_number)
  31. return &graph->graph_nodes[node_number-1];
  32. for(i = 0; i < graph->size; i++){
  33. if(graph->graph_nodes[i].node_number == node_number)
  34. return &graph->graph_nodes[i];
  35. }
  36. return NULL;
  37. }
  38. tsp_ants *init_tsp(char *path_to_data, int n_ants, float alpha, float beta, float q0){
  39. tsp_ants *ret;
  40. int n_edges;
  41. int i,j,k;
  42. int pascal_height;
  43. ret = (tsp_ants *)malloc(sizeof(tsp_ants));
  44. ret->n_ants = n_ants;
  45. ret->alpha = alpha;
  46. ret->beta = beta;
  47. ret->q0 = q0;
  48. ret->graph = read_tsp_graph(path_to_data);
  49. if(ret->graph == NULL)
  50. return NULL;
  51. n_edges = ((ret->graph->size - 1)*ret->graph->size)/2; /* Number of edges in a full conected graph */
  52. pascal_height = ret->graph->size - 1;
  53. ret->pheromone_trails = (pheromone *)malloc(sizeof(pheromone)*(n_edges));
  54. ret->ants = (ant *)malloc(sizeof(ant)*n_ants);
  55. /* for(i = 0; i < n_ants; i++)
  56. ret->ants[i].path = (graph_n *)malloc(sizeof(graph_n)*n_edges); */
  57. k = 0;
  58. for(j = 1; j<= pascal_height; j++){
  59. for (i = j+1; i <= pascal_height+1; i++){
  60. ret->pheromone_trails[k].node_1 = get_graph_node_with_number(ret->graph,j);
  61. ret->pheromone_trails[k].node_2 = get_graph_node_with_number(ret->graph,i);
  62. ret->pheromone_trails[k].value = 1;
  63. k++;
  64. }
  65. }
  66. return ret;
  67. }
  68. graph *read_tsp_graph(char *filename){
  69. FILE * fp;
  70. char *line;
  71. int size;
  72. size_t len;
  73. ssize_t read;
  74. graph *ret;
  75. int i;
  76. i = 0;
  77. line = NULL;
  78. len = 0;
  79. ret = (graph *)malloc(sizeof(graph));
  80. fp = fopen(filename, "r");
  81. if (!fp)
  82. return NULL;
  83. while ((read = getline(&line, &len, fp)) != -1) {
  84. if(strstr(line,"DIMENSION")){
  85. sscanf(line,"DIMENSION: %d",&size);
  86. ret->size = size;
  87. ret->graph_nodes = (graph_n *)malloc(sizeof(graph_n)*size);
  88. }
  89. if(strstr(line,"NODE_COORD_SECTION")){
  90. break;
  91. }
  92. }
  93. while ((read = getline(&line, &len, fp)) != -1) {
  94. if(!strstr(line,"EOF")){
  95. sscanf(line,"%d %f %f",&ret->graph_nodes[i].node_number,&ret->graph_nodes[i].x,&ret->graph_nodes[i].y);
  96. i++;
  97. }
  98. }
  99. fclose(fp);
  100. if (line)
  101. free(line);
  102. return ret;
  103. }
  104. void init_randomizer(){
  105. srand(time(NULL));
  106. }
  107. int try_to_hit(float probability){
  108. float r;
  109. r = (float) rand()/RAND_MAX;
  110. if(probability > r)
  111. return 1;
  112. else
  113. return 0;
  114. }
  115. int is_on_interval(float down, float up, float value){
  116. if(value >= down && value <= up)
  117. return 1;
  118. else
  119. return 0;
  120. }
  121. int roullete(float *probability_dist,int size){
  122. float **range;
  123. float hit;
  124. int i;
  125. range = (float **)malloc(sizeof(float *)*size);
  126. for(i = 0; i < size; i++)
  127. range[i] = (float *)malloc(sizeof(float)*2);
  128. range[0][0] = 0;
  129. range[0][1] = probability_dist[0];
  130. for(i = 1; i < size; i++){
  131. range[i][0] = range[i-1][1] + FLT_MIN;
  132. range[i][1] = range[i][0] + probability_dist[i];
  133. }
  134. hit = (float)rand()/RAND_MAX;
  135. for(i = 0; i < size; i++){
  136. if (is_on_interval(range[i][0],range[i][1],hit))
  137. return i+1;
  138. }
  139. return -1;
  140. }
  141. int isOnList(int *list, int value, int list_size){
  142. int i;
  143. for(i = 0; i< list_size; i++){
  144. if(list[i] == value)
  145. return i;
  146. }
  147. return -1;
  148. }
  149. void initialize_ants_randomly(tsp_ants *tsp){
  150. int i;
  151. int random_node;
  152. int *ants_nodes;
  153. ants_nodes = (int *)malloc(sizeof(int)*tsp->n_ants);
  154. for(i = 0; i < tsp->n_ants; i++){
  155. do{
  156. random_node = random_at_most(tsp->graph->size-1) + 1;
  157. }while(isOnList(ants_nodes, random_node, tsp->n_ants)!=-1);
  158. ants_nodes[i] = random_node;
  159. tsp->ants[i].present_node = get_graph_node_with_number(tsp->graph, random_node);
  160. tsp->ants[i].initial_node = get_graph_node_with_number(tsp->graph, random_node);
  161. tsp->ants[i].path = initialize_list(((tsp->graph->size - 1)*tsp->graph->size)/2);
  162. push(tsp->ants[i].path, tsp->ants[i].initial_node);
  163. tsp->ants[i].tour_value = -1;
  164. }
  165. free(ants_nodes);
  166. }
  167. void local_trail_update(){}
  168. int shortest_ant_tour_index(tsp_ants *tsp){
  169. int i,ret;
  170. float shortest;
  171. shortest = tsp->ants[0].tour_value;
  172. ret = 0;
  173. for (i = 1; i< tsp->n_ants; i++){
  174. if(tsp->ants[i].tour_value < shortest){
  175. shortest = tsp->ants[i].tour_value;
  176. ret = i;
  177. }
  178. }
  179. return ret;
  180. }
  181. int all_ants_finished(tsp_ants *tsp){
  182. int i;
  183. for (i = 0; i< tsp->n_ants; i++){
  184. if(tsp->ants[i].initial_node != tsp->ants[i].present_node && tsp->ants[i].tour_value != -1)
  185. return 0;
  186. }
  187. return 1;
  188. }
  189. int move_with_arg_max(tsp_ants *tsp, ant *ant){
  190. int i;
  191. int u;
  192. float max;
  193. float temp;
  194. int ret;
  195. max = -1.0;
  196. ret = -1.0;
  197. if(ant->path->last_node_pos == tsp->graph->size - 1){ /*Must return to begin*/
  198. printf("ENTRO AQUI 1\n");
  199. return ant->initial_node->node_number;
  200. }
  201. for(i = 1; i <= tsp->graph->size; i++){
  202. if (i == ant->present_node->node_number || find(ant->path,i)){
  203. continue;
  204. }
  205. u = find_pheromone_with_nodes(tsp,i,ant->present_node->node_number);
  206. temp = tsp->pheromone_trails[u].value*powf((1/eucli2d(tsp->pheromone_trails[u].node_1,tsp->pheromone_trails[u].node_2)),tsp->beta);
  207. // printf("Distance between %d and %d : %f\n",tsp->pheromone_trails[u].node_1->node_number,
  208. // tsp->pheromone_trails[u].node_2->node_number,
  209. // temp);
  210. if(max < temp){
  211. max = temp;
  212. ret = i;
  213. }
  214. }
  215. return ret;
  216. }
  217. int move_with_probability(tsp_ants *tsp, ant *ant){
  218. float *probabilities, sum;
  219. int i;
  220. int s;
  221. int ret;
  222. if(ant->path->last_node_pos == tsp->graph->size - 1){ /*Must return to begin*/
  223. printf("ENTRO AQUI 2\n");
  224. return ant->initial_node->node_number;
  225. }
  226. probabilities = (float *)malloc(sizeof(float)*tsp->graph->size);
  227. for(i = 1; i <= tsp->graph->size; i++){
  228. if (i == ant->present_node->node_number || find(ant->path,i)){
  229. probabilities[i-1] = 0.0;
  230. continue;
  231. }
  232. s = find_pheromone_with_nodes(tsp,i,ant->present_node->node_number);
  233. // printf("Distance between %d and %d : %f\n",tsp->pheromone_trails[s].node_1->node_number,
  234. // tsp->pheromone_trails[s].node_2->node_number,
  235. // eucli2d(tsp->pheromone_trails[s].node_1,tsp->pheromone_trails[s].node_2));
  236. probabilities[i-1] = tsp->pheromone_trails[s].value*powf((1/eucli2d(tsp->pheromone_trails[s].node_1,tsp->pheromone_trails[s].node_2)),tsp->beta);
  237. }
  238. sum = 0.0;
  239. for(i = 0; i < tsp->graph->size; i++){
  240. // printf("Probability %d: %f\n",i,probabilities[i]);
  241. sum += probabilities[i];
  242. }
  243. for(i = 0; i < tsp->graph->size; i++){
  244. probabilities[i] = probabilities[i]/sum;
  245. // printf("Probability of moving to city %d: %f\n",i+1,probabilities[i]);
  246. }
  247. ret = roullete(probabilities,tsp->graph->size);
  248. free(probabilities);
  249. return ret;
  250. }
  251. void move_to_new_city(tsp_ants *tsp, ant *ant){
  252. int city_to_move;
  253. graph_n *node;
  254. if(ant->initial_node == ant->present_node && ant->tour_value != -1){
  255. printf("ENTRO AQUI 3\n");
  256. return;
  257. }
  258. if(try_to_hit(tsp->q0)){
  259. city_to_move = move_with_arg_max(tsp, ant);
  260. }else{
  261. city_to_move = move_with_probability(tsp, ant);
  262. }
  263. node = get_graph_node_with_number(tsp->graph,city_to_move);
  264. ant->tour_value += eucli2d(ant->present_node,node);
  265. ant->present_node = node;
  266. push(ant->path,node);
  267. // printf("Moving to city %d\n",city_to_move);
  268. }
  269. int find_pheromone_with_nodes(tsp_ants *tsp, int node_1, int node_2){
  270. int i;
  271. int n_edges;
  272. n_edges = ((tsp->graph->size - 1)*tsp->graph->size)/2;
  273. for(i = 0; i < n_edges; i++){
  274. if( (tsp->pheromone_trails[i].node_1->node_number == node_1 || tsp->pheromone_trails[i].node_2->node_number == node_1) &&
  275. (tsp->pheromone_trails[i].node_1->node_number == node_2 || tsp->pheromone_trails[i].node_2->node_number == node_2) )
  276. return i;
  277. }
  278. return -1;
  279. }
  280. int global_trail_update(tsp_ants *tsp){
  281. float pheromoneDelta;
  282. int i;
  283. int shortest_index;
  284. graph_n *node_1, *node_2;
  285. shortest_index = shortest_ant_tour_index(tsp);
  286. pheromoneDelta = 1/tsp->ants[shortest_index].tour_value;
  287. // printf("PATH: ");
  288. pop(tsp->ants[shortest_index].path,&node_2);
  289. do{
  290. node_1 = node_2;
  291. pop(tsp->ants[shortest_index].path,&node_2);
  292. i = find_pheromone_with_nodes(tsp, node_1->node_number, node_2->node_number);
  293. // printf("%d-%d\t",node_1->node_number, node_2->node_number);
  294. if(i == -1){
  295. printf("Error: cannot find node\n");
  296. return -1;
  297. }
  298. tsp->pheromone_trails[i].value = (1 - tsp->alpha)*tsp->pheromone_trails[i].value + tsp->alpha*pheromoneDelta;
  299. }while(tsp->ants[shortest_index].path->last_node_pos != -1);
  300. return shortest_index;
  301. }
  302. float generate_solution(tsp_ants *tsp){
  303. int i;
  304. int shortest_ant_tour_index;
  305. float ret;
  306. initialize_ants_randomly(tsp);
  307. do{
  308. for(i = 0; i< tsp->n_ants; i++){
  309. move_to_new_city(tsp, &tsp->ants[i]);
  310. local_trail_update();
  311. }
  312. }while(!all_ants_finished(tsp));
  313. shortest_ant_tour_index = global_trail_update(tsp);
  314. ret = tsp->ants[shortest_ant_tour_index].tour_value;
  315. return ret;
  316. }
  317. void release_graph(graph *graph){
  318. free(graph->graph_nodes);
  319. free(graph);
  320. }
  321. void release_tsp_ants(tsp_ants *tsp){
  322. int i;
  323. for(i = 0; i < tsp->n_ants; i++){
  324. free(tsp->ants[i].path->list_nodes);
  325. free(tsp->ants[i].path);
  326. }
  327. free(tsp->ants);
  328. free(tsp->pheromone_trails);
  329. release_graph(tsp->graph);
  330. free(tsp);
  331. }
  332. list *initialize_list(int size){
  333. list *ret;
  334. ret = (list *)malloc(sizeof(list));
  335. ret->size = size;
  336. ret->list_nodes = (graph_n **)malloc(sizeof(graph_n *)*size);
  337. ret->last_node_pos = -1;
  338. return ret;
  339. }
  340. int find(list *list, int node_number){
  341. int i;
  342. for (i=0;i<=list->last_node_pos;i++){
  343. if(list->list_nodes[i]->node_number == node_number)
  344. return 1;
  345. }
  346. return 0;
  347. }
  348. int pop(list *list, graph_n **node){
  349. if(list->last_node_pos > -1){
  350. *node = list->list_nodes[list->last_node_pos];
  351. list->list_nodes[list->last_node_pos] = NULL;
  352. list->last_node_pos--;
  353. return 1;
  354. }else{
  355. return 0;
  356. }
  357. }
  358. int push(list *list, graph_n *node){
  359. if(list->last_node_pos < list->size - 1){
  360. list->last_node_pos++;
  361. list->list_nodes[list->last_node_pos] = node;
  362. return 1;
  363. }else{
  364. return 0;
  365. }
  366. }