Example #1
0
File: route.py Project: pcoving/tsp
def charge_start(cities, route):

    '''
    reroute starting point optimally
    '''
    Nc = cities.shape[0]
    new_route = [np.zeros(Nc, dtype=int),
                 np.zeros(Nc, dtype=int)]

    for ir in range(2):
        max_ind = -1
        max_dist = 0.0
        for ic in xrange(Nc-1):
            dist = city_dist(cities, route[ir][ic], route[ir][ic+1])
            if (dist > max_dist):
                max_dist = dist
                max_ind = ic
        print route[ir][max_ind], route[ir][max_ind+1] 
        count = 0
        for ic in xrange(max_ind+1,Nc):
            new_route[ir][count] = route[ir][ic]
            count += 1
        for ic in xrange(max_ind+1):
            new_route[ir][count] = route[ir][ic]
            count += 1
    
    return new_route
Example #2
0
File: route.py Project: pcoving/tsp
def opt3(cities, route, look_ahead=9999999, checkpoint=50, name='test'):
        
    Nc = cities.shape[0]
    assert(Nc > 0)
    
    # don't want to modify input route...
    route = [route[0].copy(),
             route[1].copy()]

    # fill edges (defined in NN above) and compute distance
    # for input route
    edges = [-np.ones([Nc,2], dtype=int), 
             -np.ones([Nc,2], dtype=int)]
    
    dist = np.array([0.0, 0.0])
    for ir in range(2):
        edges[ir][route[ir][0],    0] = 999999
        edges[ir][route[ir][Nc-1], 1] = 999999
        for ic in xrange(Nc-1):
            dist[ir] += city_dist(cities, route[ir][ic], route[ir][ic+1])
            edges[ir][route[ir][ic],   1] = route[ir][ic+1]
            edges[ir][route[ir][ic+1], 0] = route[ir][ic]
    
    # route we're currently optimizing is stored in ir 
    # (always trying to push down maximum distance)
    if (dist[0] > dist[1]):
        ir = 0
    else:
        ir = 1
    iter = 0
    while (1):
        # pick three random cities
        ic = np.zeros(3, dtype=int)
        ic[0] = np.random.randint(low=0,     high=Nc-3)
        ic[1] = np.random.randint(low=ic[0]+1, high=np.min([ic[0]+look_ahead, Nc-2]))
        ic[2] = np.random.randint(low=ic[1]+1, high=np.min([ic[1]+look_ahead, Nc-1]))
        #ic = np.array([137293, 137367, 137369])       
        rr = route[ir]
        
        found = False
    
        dist_old = city_dist(cities, rr[ic[0]], rr[ic[0]+1]) +\
            city_dist(cities, rr[ic[1]], rr[ic[1]+1]) +\
            city_dist(cities, rr[ic[2]], rr[ic[2]+1]) 
        
        dist_new = city_dist(cities, rr[ic[0]], rr[ic[1]+1]) +\
            city_dist(cities, rr[ic[2]], rr[ic[0]+1]) +\
            city_dist(cities, rr[ic[1]], rr[ic[2]+1])
        if (dist_new < dist_old):
            if ((edges[(ir+1)%2][rr[ic[0]], 0] != rr[ic[1]+1]) &
                (edges[(ir+1)%2][rr[ic[0]], 1] != rr[ic[1]+1]) &
                (edges[(ir+1)%2][rr[ic[2]], 0] != rr[ic[0]+1]) &
                (edges[(ir+1)%2][rr[ic[2]], 1] != rr[ic[0]+1]) &
                (edges[(ir+1)%2][rr[ic[1]], 0] != rr[ic[2]+1]) &
                (edges[(ir+1)%2][rr[ic[1]], 1] != rr[ic[2]+1]) ):
                print 0
                route_new = rr.copy();
                # rearrange route
                count = ic[0]+1
                for ii in xrange(ic[1]+1, ic[2]+1):
                    route_new[count] = rr[ii]
                    count += 1
                for ii in xrange(ic[0]+1, ic[1]+1):
                    route_new[count] = rr[ii]
                    count += 1
                for ii in xrange(ic[2]+1, ic[0]+1):
                    route_new[count] = rr[ii]
                    count += 1
                    
                route[ir] = route_new                    
                dist[ir] += (dist_new - dist_old)
                
                found = True
        
        if (found != True):
            dist_new = city_dist(cities, rr[ic[0]],   rr[ic[1]+1]) +\
                       city_dist(cities, rr[ic[2]],   rr[ic[1]]) +\
                       city_dist(cities, rr[ic[0]+1], rr[ic[2]+1])
            if (dist_new < dist_old):
                if ((edges[(ir+1)%2][rr[ic[0]], 0]   != rr[ic[1]+1]) &
                    (edges[(ir+1)%2][rr[ic[0]], 1]   != rr[ic[1]+1]) &
                    (edges[(ir+1)%2][rr[ic[2]], 0]   != rr[ic[1]]) &
                    (edges[(ir+1)%2][rr[ic[2]], 1]   != rr[ic[1]]) &
                    (edges[(ir+1)%2][rr[ic[0]+1], 0] != rr[ic[2]+1]) &
                    (edges[(ir+1)%2][rr[ic[0]+1], 1] != rr[ic[2]+1]) ):
                    print 1
                    route_new = rr.copy();
                    
                    count = ic[0]+1
                    for ii in xrange(ic[1]+1, ic[2]+1):
                        route_new[count] = rr[ii]
                        count += 1
                    for ii in xrange(ic[1], ic[0], -1):
                        route_new[count] = rr[ii]
                        count += 1
                    for ii in xrange(ic[2]+1, ic[0]+1):
                        route_new[count] = rr[ii]
                        count += 1
                    
                    route[ir] = route_new                    
                    dist[ir] += (dist_new - dist_old)
                
                    found = True
        
        if (found != True):
            dist_new = city_dist(cities, rr[ic[0]],   rr[ic[2]]) +\
                       city_dist(cities, rr[ic[1]+1], rr[ic[0]+1]) +\
                       city_dist(cities, rr[ic[1]],   rr[ic[2]+1])
            if (dist_new < dist_old):
                if ((edges[(ir+1)%2][rr[ic[0]], 0]   != rr[ic[2]]) &
                    (edges[(ir+1)%2][rr[ic[0]], 1]   != rr[ic[2]]) &
                    (edges[(ir+1)%2][rr[ic[1]+1], 0] != rr[ic[0]+1]) &
                    (edges[(ir+1)%2][rr[ic[1]+1], 1] != rr[ic[0]+1]) &
                    (edges[(ir+1)%2][rr[ic[1]], 0]   != rr[ic[2]+1]) &
                    (edges[(ir+1)%2][rr[ic[1]], 1]   != rr[ic[2]+1]) ):
                    print 2
                    route_new = rr.copy();
                    
                    count = ic[0]+1
                    for ii in xrange(ic[2], ic[1], -1):
                        route_new[count] = rr[ii]
                        count += 1
                    for ii in xrange(ic[0]+1, ic[1]+1):
                        route_new[count] = rr[ii]
                        count += 1
                    for ii in xrange(ic[2]+1, ic[0]+1):
                        route_new[count] = rr[ii]
                        count += 1
                    
                    route[ir] = route_new                    
                    dist[ir] += (dist_new - dist_old)
                
                    found = True
                    
        if (found != True):
            dist_new = city_dist(cities, rr[ic[0]],   rr[ic[1]]) +\
                       city_dist(cities, rr[ic[0]+1], rr[ic[2]]) +\
                       city_dist(cities, rr[ic[1]+1], rr[ic[2]+1])
            if (dist_new < dist_old):
                if ((edges[(ir+1)%2][rr[ic[0]], 0]   != rr[ic[1]]) &
                    (edges[(ir+1)%2][rr[ic[0]], 1]   != rr[ic[1]]) &
                    (edges[(ir+1)%2][rr[ic[0]+1], 0] != rr[ic[2]]) &
                    (edges[(ir+1)%2][rr[ic[0]+1], 1] != rr[ic[2]]) &
                    (edges[(ir+1)%2][rr[ic[1]+1], 0] != rr[ic[2]+1]) &
                    (edges[(ir+1)%2][rr[ic[1]+1], 1] != rr[ic[2]+1]) ):
                    print 3
                    route_new = rr.copy();
                    
                    count = ic[0]+1
                    for ii in xrange(ic[1], ic[0], -1):
                        route_new[count] = rr[ii]
                        count += 1
                    for ii in xrange(ic[2], ic[1], -1):
                        route_new[count] = rr[ii]
                        count += 1
                    for ii in xrange(ic[2]+1, ic[0]+1):
                        route_new[count] = rr[ii]
                        count += 1
                    
                    route[ir] = route_new                    
                    dist[ir] += (dist_new - dist_old)
                
                    found = True

        if (found == True):
            # rebuild edges
            edges[ir][route[ir][0],    0] = 999999
            edges[ir][route[ir][Nc-1], 1] = 999999
            for ic in xrange(Nc-1):
                edges[ir][route[ir][ic],   1] = route[ir][ic+1]
                edges[ir][route[ir][ic+1], 0] = route[ir][ic]
                
            iter += 1
            score = int(np.max(dist))
            print score
            if (iter%checkpoint == 0):
                # when we checkpoint make sure tours are disjoint and valid
                print score, calc_score(cities, route)
                #assert(score == calc_score(cities, route))
                io.write_route(route, name + '_' + str(score))
        
        # switch to other route if it's longer
        if (dist[ir] < dist[(ir+1)%2]):
            ir = (ir+1)%2

    return route
Example #3
0
File: route.py Project: pcoving/tsp
def NN(cities, start=np.array([0,0])):
    '''
    Nearest neighbor algorithm
    Input are indicies of starting cities
    Routes are built incrementally in a greedy fashion, cycling
    from one route to another
    gives solutions in the 7.9M range
    '''
    
    Nc = cities.shape[0]
    assert(Nc > 0)
    
    assert((start[0] < Nc) & (start[1] < Nc) &
           (start[0] >= 0) & (start[1] >= 0))
    
    myroute = [np.zeros(Nc, dtype=int),
               np.zeros(Nc, dtype=int)]
    myroute[0][0] = start[0]
    myroute[1][0] = start[1]
    
    '''
    the edges array keeps track of edges incident 
    to a city for each route
    for example, if city 10 is incident to cities 
    97 and 436 in route 0,
    edges[0][10,0] = 97 
    edges[0][10,1] = 436
    because it is a tour, each city will have at 
    most 2 edges incident to it
    a -1 indicates no edge
    '''
    edges = [-np.ones([Nc,2], dtype=int), 
             -np.ones([Nc,2], dtype=int)]
    
    # starting points get dummy edges since we don't
    # need to end up here
    edges[0][myroute[0][0], 0] = 999999
    edges[1][myroute[1][0], 0] = 999999
    
    # keep track of distance as we go...
    dist = np.array([0.0, 0.0])
    
    # build kdtree once for cities
    tree = cKDTree(cities)
    for ic in xrange(Nc-1):
        for ir in range(2):
        
            thiscity = myroute[ir][ic] 
        
            # make sure this city has degree exactly equal to 1
            assert(edges[ir][thiscity, 0] >= 0)
            assert(edges[ir][thiscity, 1] == -1)
            
            # start looking at the nearest 10 neighbors,
            # increasing this number until a valid city is found
            # to continue the tour
            knbrs = 10
            nextcity = -1
            while(nextcity == -1):
                nbrs_dist, nbrs = tree.query(cities[thiscity], knbrs)
                for nbr in nbrs:
                    # it's possible that there are no valid cities left,
                    # right at the end - rare, but has happened
                    # i.e. the last edge is already used by the other tour
                    if (nbr == Nc):
                        print "failed to find next city"
                        return None, 99999999999
                    # check if we've already been here...
                    if (edges[ir][nbr,0] == -1):
                        # eliminate edges in other route...
                        if ((edges[(ir+1)%2][thiscity, 0] != nbr) &
                            (edges[(ir+1)%2][thiscity, 1] != nbr)):
                            nextcity = nbr
                            break
                # we didn't find a valid city, so increase number of neighbors...
                knbrs *= 2
                        
            # add next city to route and add distance
            myroute[ir][ic+1] = nextcity
            dist[ir] += city_dist(cities, thiscity, nextcity)
            
            # fill in edges array
            edges[ir][thiscity, 1] = nextcity
            edges[ir][nextcity, 0] = thiscity
                
    score = int(np.max(dist))
    return myroute, score
Example #4
0
File: route.py Project: pcoving/tsp
def opt2(cities, route, look_ahead=9999999, checkpoint=50, name='test'):

    '''
    opt-2 takes a route and shortens it by taking 
    two edges and un-bowties them like so:
    
 
    *     *      *-----*
     \   /
      \ /
      /\    ==>    
     /  \
    *    *       *-----*

    checkpoint is number of edges un-bowtied before writing out
    the route as name_<dist>.csv
    look_ahead is an attempt to make it more efficient - for a given edge,
    will only look for edges to perform 2-opt a specified number ahead in route
    '''
    
    Nc = cities.shape[0]
    assert(Nc > 0)
    
    # don't want to modify input route...
    route = [route[0].copy(),
             route[1].copy()]

    # fill edges (defined in NN above) and compute distance
    # for input route
    edges = [-np.ones([Nc,2], dtype=int), 
             -np.ones([Nc,2], dtype=int)]
    
    dist = np.array([0.0, 0.0])
    for ir in range(2):
        edges[ir][route[ir][0],    0] = 999999
        edges[ir][route[ir][Nc-1], 1] = 999999
        for ic in xrange(Nc-1):
            dist[ir] += city_dist(cities, route[ir][ic], route[ir][ic+1])
            edges[ir][route[ir][ic],   1] = route[ir][ic+1]
            edges[ir][route[ir][ic+1], 0] = route[ir][ic]
    
    # route we're currently optimizing is stored in ir 
    # (always trying to push down maximum distance)
    if (dist[0] > dist[1]):
        ir = 0
    else:
        ir = 1
    iter = 0
    while (1):
        # pick two random cities
        ic0 = np.random.randint(low=0,     high=Nc-2)
        ic1 = np.random.randint(low=ic0+1, high=np.min([ic0+look_ahead, Nc-1]))
        
        # just an alias to make things shorter...
        rr = route[ir]
        
        dist_old = city_dist(cities, rr[ic0],   rr[ic0+1]) +\
                   city_dist(cities, rr[ic1],   rr[ic1+1])
        dist_new = city_dist(cities, rr[ic0],   rr[ic1]) +\
                   city_dist(cities, rr[ic0+1], rr[ic1+1])
        if (dist_new < dist_old):
    
            # check if un-bowtieing conflicts with other tour...
            if ((edges[(ir+1)%2][rr[ic0], 0] != rr[ic1]) &
                (edges[(ir+1)%2][rr[ic0], 1] != rr[ic1]) &
                (edges[(ir+1)%2][rr[ic0+1], 0] != rr[ic1+1]) &
                (edges[(ir+1)%2][rr[ic0+1], 1] != rr[ic1+1])):
                                
                route_new = rr.copy();
                # rearrange route and update edges
                count = ic0+1
                edges[ir][rr[ic0], 1] = rr[ic1]
                edges[ir][rr[ic1], 0] = rr[ic0]
                for ii in xrange(ic1, ic0, -1):
                    route_new[count] = rr[ii]
                    edges[ir][rr[ii], 1] = rr[ii-1]
                    if (ii != ic0+1):
                        edges[ir][rr[ii-1], 0] = rr[ii]
                    count += 1
                edges[ir][rr[ic1+1], 0] = rr[ic0+1]
                edges[ir][rr[ic0+1], 1] = rr[ic1+1]
                    
                route[ir] = route_new                    
                dist[ir] += (dist_new - dist_old)
                
                iter += 1
                score = int(np.max(dist))
                print score
                if (iter%checkpoint == 0):
                    # when we checkpoint make sure tours are disjoint and valid
                    print score, calc_score(cities, route)
                    #assert(score == calc_score(cities, route))
                    io.write_route(route, name + '_' + str(score))
        
        # switch to other route if it's longer
        if (dist[ir] < dist[(ir+1)%2]):
            ir = (ir+1)%2

    return route