void nearest_ins(int parent, heur_prob *p) { printf("\nIn nearest_ins....\n\n"); int numroutes, cur_route, nearnode, *starter; int mytid, info, r_bufid; int *intour; int last, cost; neighbor *nbtree; _node *tour; route_data *route_info; int start; best_tours *tours; double t=0; mytid = pvm_mytid(); (void) used_time(&t); tours = p->cur_tour = (best_tours *) calloc (1, sizeof(best_tours)); /*-----------------------------------------------------------------------*\ | Receive the VRP data | \*-----------------------------------------------------------------------*/ PVM_FUNC(r_bufid, pvm_recv(-1, ROUTE_NINS_VRP_DATA)); PVM_FUNC(info, pvm_upkbyte((char *)tours, sizeof(best_tours), 1)); tour = p->cur_tour->tour = (_node *) calloc (p->vertnum, sizeof(_node)); PVM_FUNC(info, pvm_upkbyte((char *)tour, (p->vertnum)*sizeof(_node), 1)); numroutes = p->cur_tour->numroutes; starter = (int *) calloc (numroutes, sizeof(int)); route_info = p->cur_tour->route_info = (route_data *) calloc (numroutes+1, sizeof(route_data)); PVM_FUNC(r_bufid, pvm_recv(-1, ROUTE_NINS_START_RULE)); PVM_FUNC(info, pvm_upkint(&start, 1, 1));/*receive the start rule*/ if (start != FAR_INS) srand(start); /*if the start rule is random, then*\ \*initialize the random number gen.*/ starters(p, starter, route_info, start);/*generate the route starters for*\ \*all the clusters. */ /*-----------------------------------------------------------------------*\ | Allocate arrays | \*-----------------------------------------------------------------------*/ nbtree = (neighbor *) malloc (p->vertnum * sizeof(neighbor)); intour = (int *) calloc (p->vertnum, sizeof(int)); /*-----------------------------------------------------------------------*\ | Find the nearest insertion tour from 'starters' | \*-----------------------------------------------------------------------*/ for (cur_route=1; cur_route<=numroutes; cur_route++){ /*---------------------------------------------------------------------*\ | The first part of this loop adds the starter and the nearest node to | | it into the route to initialize it. Then a function is called | | which inserts the rest of the nodes into the route in nearest | | insert order. | \*---------------------------------------------------------------------*/ if (route_info[cur_route].numcust <= 1) continue; cost = 0; last = 0; intour[0] = 0; intour[starter[cur_route-1]] = IN_TOUR; ni_insert_edges(p, starter[cur_route-1], nbtree, intour, &last, tour, cur_route); nearnode = closest(nbtree, intour, &last); intour[nearnode] = IN_TOUR; ni_insert_edges(p, nearnode, nbtree, intour, &last, tour, cur_route); tour[starter[cur_route-1]].next = nearnode; tour[nearnode].next = starter[cur_route-1]; if (starter[cur_route - 1] == 0) route_info[cur_route].first = route_info[cur_route].last = nearnode; if (nearnode == 0) route_info[cur_route].first = route_info[cur_route].last = starter[cur_route-1]; cost = 2 * ICOST(&p->dist, starter[cur_route-1], nearnode); cost = nearest_ins_from_to(p, tour, cost, 2, route_info[cur_route].numcust+1, starter[cur_route-1], nbtree, intour, &last, route_info, cur_route); route_info[cur_route].cost = cost; } tour[0].next = route_info[1].first; /*-------------------------------------------------------------------------*\ | This loop points the last node of each route to the first node of the next| | route. At the end of this procedure, the last node of each route is | | pointing at the depot, which is not what we want. | \*-------------------------------------------------------------------------*/ for (cur_route = 1; cur_route< numroutes; cur_route++) tour[route_info[cur_route].last].next = route_info[cur_route+1].first; cost = compute_tour_cost(&p->dist, tour); /*-----------------------------------------------------------------------*\ | Transmit the tour back to the parent | \*-----------------------------------------------------------------------*/ send_tour(tour, cost, numroutes, tours->algorithm, used_time(&t), parent, p->vertnum, 1, route_info); if ( nbtree ) free ((char *) nbtree); if ( intour ) free ((char *) intour); if ( starter) free ((char *) starter); free_heur_prob(p); }
void make_routes(heur_prob *p, _node *tsp_tour, int start, best_tours *new_tour) { int cur_node, prev_node, route_beg, prev_route_beg; int weight, i, capacity = p->capacity; int cur_route = 1; int cost; _node *tour = new_tour->tour; adj_list **adj; adj_list *temp, *path; int *pi, route_end; int vertnum = p->vertnum; int *demand = p->demand; adj = (adj_list **) calloc (vertnum, sizeof(adj_list *)); /*--------------------------------------------------------------------*\ | First we must construct the graph to give to the shortest path | | algorithm. In this graph, the edge costs are as follows. The cost of | | edge between nodes i and j is the cost of a route beginning with i's | | successor on the TSP tour and ending with j (in bewtween, the route | | follows the same ordering as the TSP tour itself) if this is a | | feasible route and infinity otherwise. Now if we find a | | shortest cycle in this graph, then the nodes in the cycle will be the| | endpoints of the routes in an optimal partition. This is what I do. | | We need to arbitrarily specify the fist endpoint in advance. | | This is the value contained the start variable. The tsp_tour | | structure contains the original TSP tour. | \*--------------------------------------------------------------------*/ for (prev_route_beg = start, route_beg = tsp_tour[start].next, i=0; i<vertnum-1; prev_route_beg = route_beg, route_beg = tsp_tour[route_beg].next, i++){ cur_node = route_beg; prev_node = 0; temp = adj[prev_route_beg] = (adj_list *) calloc (1, sizeof(adj_list)); weight = demand[cur_node]; cost = ICOST(&p->dist, prev_node, cur_node); temp->cost = cost + ICOST(&p->dist, 0, cur_node); temp->custnum = cur_node; prev_node = cur_node; cur_node = tsp_tour[cur_node].next; while (weight + demand[cur_node] <= capacity){ weight += demand[cur_node]; cost += ICOST(&p->dist, prev_node, cur_node); temp->next = (adj_list *) calloc (1, sizeof(adj_list)); temp = temp->next; temp->cost = cost + ICOST(&p->dist, 0, cur_node); temp->custnum = cur_node; prev_node = cur_node; cur_node = tsp_tour[cur_node].next; } } /* The graph is constructed. Now find a shortest cycle in it */ pi = sp(adj, vertnum, start, start); /*--------------------------------------------------------------------*\ | Now the shortest cycle information is contained in pi. However, using| | pi, we can only trace the shortest cycle in one direction since it is| | actually stored as a directed path from the start node to itself. | | Also, we can only trace the TSp tour in one direction since it is | | stored in the same way. So we must store the cycle in the reverse | | direction in order to break up the TSP tour. That is what this piece | | of code does. It stores the nodes on the cycle in opposite order in a| | linked list to be used in the next part of the code. | \*--------------------------------------------------------------------*/ path = (adj_list *) calloc (1, sizeof(adj_list)); path->custnum = start; cur_node = pi[start]; while (cur_node){ temp = (adj_list *) calloc (1, sizeof(adj_list)); temp->custnum = cur_node; temp->next = path; path = temp; cur_node = pi[cur_node]; } temp = path; /*--------------------------------------------------------------------*\ | Now we have the optimal break points stored in order in a liked list.| | We trace the TSP tour, copying each node into the VRP tour until we | | reach the endpoint of a route and then we change the route number. | \*--------------------------------------------------------------------*/ tour[0].next = tsp_tour[start].next; cur_node = tour[0].next; route_end = temp->custnum; for (i=1; i<vertnum-1; i++){ tour[cur_node].next = tsp_tour[cur_node].next; tour[cur_node].route = cur_route; if (cur_node == route_end){ cur_route++; if (temp->next){ temp = temp->next; route_end = temp->custnum; } else break; } cur_node = tsp_tour[cur_node].next; } tour[cur_node].next = 0; tour[cur_node].route = cur_route; new_tour->cost = compute_tour_cost(&p->dist, tour); new_tour->numroutes = cur_route; }
void make_tour(heur_prob *p, sweep_data *data, best_tours *final_tour) { int i, k, weight = 0, j=1, l; int interval, start=0; int cost; _node *tour; int *demand = p->demand; int vertnum = p->vertnum; int capacity = p->capacity; if (p->par.sweep_trials>vertnum - 1) p->par.sweep_trials = vertnum-1; final_tour->cost = MAXINT; tour = (_node *) calloc (vertnum, sizeof(_node)); interval = vertnum/p->par.sweep_trials; for (l=0; l < p->par.sweep_trials; l++){ tour[0].next = data[start].cust; tour[0].route = 0; for (k=1; k < vertnum-1; k++){ i = (k-1) + start; if (i>vertnum-2) i-=(vertnum-1); if (weight + demand[data[i].cust] <= capacity){ weight += demand[data[i].cust]; if (i != vertnum - 2) tour[data[i].cust].next = data[i+1].cust; else tour[data[i].cust].next = data[0].cust; tour[data[i].cust].route=j; } else{ weight = demand[data[i].cust]; j++; if (i != vertnum - 2) tour[data[i].cust].next = data[i+1].cust; else tour[data[i].cust].next = data[0].cust; tour[data[i].cust].route=j; } } i = (k-1) + start; if (i>vertnum-2) i-=(vertnum-1); if (weight + demand[data[i].cust] <= capacity){ tour[data[i].cust].next = 0; tour[data[i].cust].route = j; } else{ j++; tour[data[i].cust].next = 0; tour[data[i].cust].route = j; } cost = compute_tour_cost (&p->dist, tour); if (cost < final_tour->cost){ memcpy((char *)final_tour->tour,(char *)tour, vertnum*sizeof(_node)); final_tour->cost = cost; final_tour->numroutes=j; } j=1; weight=0; start += interval; } free((char *)tour); }