This is cheap.m in view mode; [Download] [Up]
#include <stdlib.h> #ifdef MYDIR #else #include "TwoDView.h" #include "TwoDTSP.h" #include <appkit/graphics.h> #endif #include <math.h> #include <limits.h> #include <stdio.h> #include "tspheaders.h" #include "prototypes.h" /************************************************************************/ /* This function implements the Cheapest Insertion Algorithm for the Travelling Salesperson Algorithm. It provides an approximate optimal value rather than the optimal value. Reference: Salkin & Mathur, Foundations Of Integer Programming, 1989 North-Holland, p 683. */ /************************************************************************/ /* Parameters: TwoDView *self: Ye Old Drawing Object float *Data: Pointer to the list of points. Used to draw intermediate graph. float *Distance: Pointer to area that contains the Distances Between Each Pair of Cities int *Tour: Pointer to area that will contain the indices of the n arcs that are selected to be a part of the tour int NumberOfCities: Number of cities in the problem */ /************************************************************************/ /************************************************************************/ #ifdef MYDIR float CheapestInsertion(float *Distance,int *Tour,int NumberOfCities) { #else float CheapestInsertion(TwoDView *self,float *data,float *Distance,int *Tour, int NumberOfCities) { #endif int i,j,k,l,m,x,y,I,J,Arc,From,To,CurrentCity,SubTourEnd,NewCity,FromIndex; int *OnTour; float MinDistance,OldDistance,ThisDistance,NewDistance,OptimalValue; char msg[256]; /* allocate space for OnTour */ OnTour = (int *)malloc(NumberOfCities*sizeof(int)); if (OnTour == (int *) 0) printf("Malloc for OnTour failed. \n"); for (i=0;i<NumberOfCities;i++) { OnTour[i] = 0; } #ifdef DEBUGMYDIR for (i=0;i<(NumberOfCities-1)*NumberOfCities/2;i++) { printf("Distance[%d] = %f; \n",i,Distance[i]); } #endif /* find the two cities with the minimum distance */ /* these two cities make up the initial subtour */ MinDistance = ClosestCities(Distance,&From,&To,NumberOfCities); /* if MinDistance doesn't change, there is a problem ... */ if (MinDistance == INT_MAX) { printf("Error no initial subtour found. \n"); #ifdef DEBUGMYDIR #else STATUS("No initial subtour found."); #endif } #ifdef DEBUGMYDIR else { printf("initial subtour \n"); printf("from %d to %d distance %f \n",From,To,MinDistance); } #endif /* given a subtour of m cities, add city k with minimum insertion cost */ /* cost of inserting city k between cities i and j = Distance(i,k) + Distance(k,j) - Distance(i,j) */ /* OnTour indicates status of city 1 -- city is on tour 0 -- city is not yet on the tour */ Tour[0] = Tour[3] = From; Tour[1] = Tour[2] = To; OnTour[From] = OnTour[To] = 1; /* FromIndex is the number of the city currently being tested */ FromIndex = 0; NewDistance = INT_MAX; OptimalValue = 2*MinDistance; SubTourEnd = 1; CurrentCity = -1; NewCity = NumberOfCities; /* keep adding cities until you include all NumberOfCities of them */ while (SubTourEnd < NumberOfCities-1) { #ifdef DEBUGMYDIR printf("Start of Iteration with %d cities in tour \n",SubTourEnd+1); printf("From is %d \n",From); printf("To is %d \n",To); printf("FromIndex is %d \n",FromIndex); #else sprintf(msg,"From %d To %d",From, To); //added wgr STATUS(msg);// wgr #endif /* at the end of this while loop, there will be a new city to insert */ while (CurrentCity < SubTourEnd) { /* look at the next city already on the tour */ CurrentCity+=1; From = Tour[2*CurrentCity]; To = Tour[2*CurrentCity+1]; OldDistance = Distance[kfrom(From,To,NumberOfCities)]; /* look at all arcs starting at From */ I = ArcIndex(From,NumberOfCities); J = ArcIndex((From+1),NumberOfCities); for (Arc=I;Arc<J;Arc++) { /* j = terminating end of this arc */ j = Arc-I+From+1; /* if the city at the other end isn't already on the tour ...*/ if (!OnTour[j]) { /* Is the arc a new candidate for insertion? */ if ((j != From) && (j != To)) { k = kfrom(From,j,NumberOfCities); l = kfrom(j,To,NumberOfCities); ThisDistance = Distance[k] + Distance[l] - OldDistance; if (ThisDistance < 0) { printf("Error: ThisDistance = %f for From %f To %f j %f \n", From,To,j); } if (ThisDistance < NewDistance) { #ifdef DEBUGMYDIR printf("Changing cities from %d to %d \n",NewCity,j); printf("From, To, j, %d %d %d \n",From,To,j); #else sprintf(msg,"Change from %d to %d",From,To); STATUS(msg); #endif NewDistance = ThisDistance; NewCity = j; FromIndex = CurrentCity; } } } } /* look at all arcs ending at From */ for (m=0;m<From;m++) { /* if the starting city isn't already on the tour ...*/ if (!OnTour[m]) { /* Is this arc a new candidate for insertion? */ if ((m != From) && (m != To)) { k = kfrom(m,From,NumberOfCities); l = kfrom(m,To,NumberOfCities); ThisDistance = Distance[k] + Distance[l] - OldDistance; if (ThisDistance < 0) { printf("Error: ThisDistance = %f for From %f To %f m %f \n", From,To,m); } if (ThisDistance < NewDistance) { #ifdef DEBUGMYDIR printf("Changing cities from %d to %d \n",NewCity,m); printf("From, To, J, %d %d %d \n",From,To,m); #else sprintf(msg,"change from %d to %d",NewCity,m); STATUS(msg); #endif NewDistance = ThisDistance; NewCity = m; FromIndex = CurrentCity; } } } } } if (NewCity >= NumberOfCities) { printf("Error: new city has not been found for tour. \n"); CurrentCity = SubTourEnd = NumberOfCities; OptimalValue = -1; } else { /* add the new arc going from j to FromIndex+1 Tour */ #ifdef DEBUGMYDIR printf("adding arc from %d to %d \n",NewCity,Tour[2*FromIndex+1]); #else sprintf(msg,"add arc %d to %d \n",NewCity,Tour[2*FromIndex+1]); STATUS(msg); #endif SubTourEnd+=1; Tour[2*SubTourEnd] = NewCity; Tour[2*SubTourEnd+1] = Tour[2*FromIndex+1]; OnTour[NewCity] = 1; /* replace arc indexed by FromIndex in Tour with new arc going from old From to NewCity */ #ifdef DEBUGMYDIR printf("replacing arc from %d to %d with %d to %d \n", Tour[2*FromIndex],Tour[2*FromIndex+1],Tour[2*FromIndex],NewCity); #else sprintf(msg,"replace %d %d with %d %d", Tour[2*FromIndex],Tour[2*FromIndex+1],Tour[2*FromIndex],NewCity); STATUS(msg); #endif Tour[2*FromIndex] = Tour[2*FromIndex]; Tour[2*FromIndex+1] = NewCity; /* update the Optimal Value */ OptimalValue+=NewDistance; #ifdef DEBUGMYDIR printf("addding %f to Opval to get %f \n",NewDistance,OptimalValue); #endif /* get ready to start at the top of the list again */ FromIndex = 0; CurrentCity = -1; NewDistance = INT_MAX; NewCity = NumberOfCities; #ifdef DEBUGMYDIR /* print out current subtour */ for (i=0;i<2*(SubTourEnd+1);i++) { printf("i tour %d %d \n",i,Tour[i]); } #endif #ifdef MYDIR #else /* draw the intermediate tour */ PSnewinstance(); for(i=0;i<2*(SubTourEnd+1);i+=2) { x = Tour[i]; y = Tour[i+1]; [self drawEdge:X(x):Y(x):X(y):Y(y)]; } NXPing(); [self->optimalValueField setFloatValue: OptimalValue at: 0]; usleep(self->drawTime); #endif } } /* clean up */ free(OnTour); /* return the optimal value */ return(OptimalValue); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.