Ejemplo n.º 1
0
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);
	
}
Ejemplo n.º 2
0
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;
}    
Ejemplo n.º 3
0
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);
}