This is farthest.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 Farthest Insertion Algorithm for the Travelling Salesperson Algorithm. It provides an approximate optimal value rather than the optimal value. Reference: Lawler, Lenstra, et. al., The Traveling Salesman [sic] Problem, 1985, Wiley and Sons, p 226. */ /************************************************************************/ /* 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 FarthestInsertion(float *Distance,int *Tour,int NumberOfCities) { #else float FarthestInsertion(TwoDView *self,float *data,float *Distance,int *Tour, int NumberOfCities) { #endif int i,j,k,m,x,y,I,J, From,To,CurrentCity,SubTourEnd,TourIndex,NewCity, City1,City2,LeavingArc; int *OnTour, *TourCities; float NewDistance,MinDistance,ThisDistance,OptimalValue; char msg[256]; /* allocate space for OnTour and TourCities */ OnTour = (int *)malloc(NumberOfCities*sizeof(int)); TourCities = (int *)malloc(NumberOfCities*sizeof(int)); if (OnTour == (int *) 0) printf("Malloc for OnTour failed. \n"); if (TourCities == (int *) 0) printf("Malloc for TourCities failed. \n"); for (i=0;i<NumberOfCities;i++) { OnTour[i] = 0; } for (i=0;i<NumberOfCities;i++) { TourCities[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 maximum distance */ /* these two cities make up the initial subtour */ NewDistance = FarthestCities(Distance,&From,&To,NumberOfCities); /* if NewDistance doesn't change, there is a problem ... */ if (NewDistance == 0) { printf("Error no initial subtour found. \n"); } #ifdef DEBUGMYDIR else { printf("initial subtour \n"); printf("from %d to %d distance %f \n",From,To,NewDistance); } #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 is a list of cities on the tour already. */ Tour[0] = Tour[3] = From; Tour[1] = Tour[2] = To; OnTour[From] = OnTour[To] = 1; TourCities[0] = From; TourCities[1] = To; OptimalValue = 2*NewDistance; SubTourEnd = 1; TourIndex = -1; NewCity = NumberOfCities; NewDistance = 0; /* 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); #endif /* at the end of this while loop, there will be a new city to insert */ while (TourIndex < SubTourEnd) { /* look at the next city already on the tour */ TourIndex+=1; CurrentCity = TourCities[TourIndex]; #ifdef DEBUGMYDIR printf("Looking at city %d \n",CurrentCity); #endif /* look at all arcs starting at CurrentCity */ I = ArcIndex(CurrentCity,NumberOfCities); J = ArcIndex((CurrentCity+1),NumberOfCities); for (i=I;i<J;i++) { /* j = terminating end of this arc */ j = i-I+CurrentCity+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? */ k = kfrom(CurrentCity,j,NumberOfCities); if (Distance[k] > NewDistance) { #ifdef DEBUGMYDIR printf("Changing cities from %d to %d \n",NewCity,j); printf("Looking at city %d \n",CurrentCity); #endif NewDistance = Distance[k]; NewCity = j; } } } /* look at all arcs ending at CurrentCity */ for (m=0;m<CurrentCity;m++) { /* if the starting city isn't already on the tour ...*/ if (!OnTour[m]) { /* Is this arc a new candidate for insertion? */ k = kfrom(m,CurrentCity,NumberOfCities); if (Distance[k] > NewDistance) { #ifdef DEBUGMYDIR printf("Changing cities from %d to %d \n",NewCity,m); #endif NewDistance = Distance[k]; NewCity = m; } } } } if (NewCity >= NumberOfCities) { printf("Error: new city has not been found for tour. \n"); CurrentCity = SubTourEnd = NumberOfCities; OptimalValue = -1; } else { /* find two cities on the tour, City1 and City2 such that the distance from City1 to the NewCity plus the distance from the NewCity to City2 - the distance from City1 to City2 is minimized. */ k = 0; MinDistance = INT_MAX; #ifdef DEBUGMYDIR printf("NewCity is %d SubTourEnd %d \n",NewCity,SubTourEnd); #endif while (k <= 2*SubTourEnd) { City1 = Tour[k]; City2 = Tour[k+1]; ThisDistance = Distance[kfrom(City1,NewCity,NumberOfCities)] + Distance[kfrom(City2,NewCity,NumberOfCities)] - Distance[kfrom(City1,City2,NumberOfCities)]; #ifdef DEBUGMYDIR printf("This %f Min %f City1 %d City2 %d \n",ThisDistance, MinDistance,City1,City2); #endif if (ThisDistance < 0) { printf("Error: ThisDistance = %f for City1 %f City2 %f NewCity %f \n", City1,City2,NewCity); } if (ThisDistance < MinDistance) { MinDistance = ThisDistance; LeavingArc = k; } k+=2; } if (MinDistance == INT_MAX) { printf("Error: wasn't able to find a spot for %d \n",NewCity); } /* arc in Tour starting at LeavingArc is replaced by arcs between Tour[LeavingArc] and NewCity and arc between NewCity and Tour[LeavingArc+1]. */ /* add the new arc going from NewCity to Tour[LeavingArc+1] */ #ifdef DEBUGMYDIR printf("adding arc from %d to %d \n",NewCity,Tour[LeavingArc+1]); #else sprintf(msg,"add arc %d to %d \n",NewCity,Tour[LeavingArc+1]); STATUS(msg); #endif SubTourEnd+=1; Tour[2*SubTourEnd] = NewCity; Tour[2*SubTourEnd+1] = Tour[LeavingArc+1]; OnTour[NewCity] = 1; TourCities[SubTourEnd] = NewCity; #ifdef DEBUGMYDIR printf("replacing arc from %d to %d with %d to %d \n", Tour[LeavingArc],Tour[LeavingArc+1],Tour[LeavingArc],NewCity); #else sprintf(msg,"replacing arc from %d to %d with %d to %d \n", Tour[LeavingArc],Tour[LeavingArc+1],Tour[LeavingArc],NewCity); STATUS(msg); #endif Tour[LeavingArc+1] = NewCity; /* update the Optimal Value */ OptimalValue+=MinDistance; #ifdef DEBUGMYDIR printf("addding %f to Opval to get %f \n",MinDistance,OptimalValue); #else sprintf(msg,"addding %f to Opval to get %f \n",MinDistance,OptimalValue); STATUS(msg); #endif } /* get ready to start at the top of the list again */ TourIndex = -1; NewDistance = 0; 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.