Example #1
0
def calculate_route(matrix):
    matrix_sym = atsp_tsp(matrix, strategy="avg")

    # write temporary file in the `tsp` format
    outf = "myroute_concorde.tsp"

    silentremove(outf)
    silentremove("myroute_concorde.mas")
    silentremove("myroute_concorde.pul")
    silentremove("myroute_concorde.sav")
    silentremove("myroute_concorde.sol")
    silentremove("o.txt")
    silentremove("o2.txt")
    silentremove("Omyroute_concorde.mas")
    silentremove("Omyroute_concorde.pul")
    silentremove("Omyroute_concorde.sav")

    with open(outf, 'w') as dest:
        dest.write(dumps_matrix(matrix_sym, name="My Route"))
    # print(dumps_matrix(matrix_sym, name="My Route"))
    # run the optimization with concorde
    tour = run_concorde(outf, start=0, solver="concorde")
    # or with LKH
    # tour = run(outf, start=10, solver="LKH")
    tour['tour'].append(tour['tour'][0])
    return tour
Example #2
0
def calculate_route(matrix):
    matrix_sym = atsp_tsp(matrix, strategy="avg")

    # write temporary file in the `tsp` format
    outf = "myroute_concorde.tsp"

    silentremove(outf)
    silentremove("myroute_concorde.mas")
    silentremove("myroute_concorde.pul")
    silentremove("myroute_concorde.sav")
    silentremove("myroute_concorde.sol")
    silentremove("o.txt")
    silentremove("o2.txt")
    silentremove("Omyroute_concorde.mas")
    silentremove("Omyroute_concorde.pul")
    silentremove("Omyroute_concorde.sav")

    with open(outf, 'w') as dest:
        dest.write(dumps_matrix(matrix_sym, name="My Route"))
    # print(dumps_matrix(matrix_sym, name="My Route"))
    # run the optimization with concorde
    tour = run_concorde(outf, start=0, solver="concorde")
    # or with LKH
    # tour = run(outf, start=10, solver="LKH")
    tour['tour'].append(tour['tour'][0])
    return tour
Example #3
0
def test_tour_LKH(matrix):
    matrix_sym = atsp_tsp(matrix, strategy="avg")
    outf = "/tmp/myroute_lkh.tsp"
    with open(outf, 'w') as dest:
        dest.write(dumps_matrix(matrix_sym, name="My Route"))
    tour = run(outf, start=10, solver="lkh")

    assert tour['solution'] == 102975
    assert tour['tour'][0] == 10
Example #4
0
def test_tour_LKH(matrix):
    matrix_sym = atsp_tsp(matrix, strategy="avg")
    outf = "/tmp/myroute_lkh.tsp"
    with open(outf, 'w') as dest:
        dest.write(dumps_matrix(matrix_sym, name="My Route"))
    tour = run(outf, start=10, solver="lkh")

    assert tour['solution'] == 102975
    assert tour['tour'][0] == 10
Example #5
0
matrix = [[0, 2910, 4693], [2903, 0, 5839], [4695, 5745, 0]]

from pytsp import atsp_tsp, run, dumps_matrix
matrix_sym = atsp_tsp(matrix, strategy="avg")
outf = "./tsp_dist.tsp"
with open(outf, 'w') as dest:
    dest.write(dumps_matrix(matrix_sym, name="My Route"))
tour = run(outf, start=None, solver="lkh")
print("tour", tour)
Example #6
0
def lkh_TSP(list_of_kingdom_names, starting_kingdom, adjacency_matrix,
            conquered_kingdoms_indices, N, dict_kingdom_index_to_name,
            dict_kingdom_name_to_index, tuples_kingdom_name_to_cost,
            starting_kingdom_index, dict_kingdom_index_to_cost,
            adjacency_lists):

    # Build TSP Distance matrix
    special_nodes = conquered_kingdoms_indices
    if starting_kingdom_index not in special_nodes:
        special_nodes.append(starting_kingdom_index)

    G = adjacency_matrix_to_graph(adjacency_matrix)
    shortest_lengths = dict(nx.shortest_path_length(G, weight="weight"))
    shortest_paths = dict(nx.shortest_path(G, weight="weight"))

    # print(shortest_lengths)

    N_TSP = len(special_nodes)
    dict_TSP_index_to_index = {
        TSP_index: index
        for TSP_index, index in enumerate(special_nodes)
    }
    dict_index_to_TSP_index = {
        index: TSP_index
        for TSP_index, index in enumerate(special_nodes)
    }

    distance_matrix = [[0 for _ in range(N_TSP)] for _ in range(N_TSP)]

    # print(special_nodes)

    # upper_bound = 2**31
    for i in range(N_TSP):
        for j in range(N_TSP):
            if i != j:
                edge_weight = int(
                    round(shortest_lengths[dict_TSP_index_to_index[i]][
                        dict_TSP_index_to_index[j]] + 1))
                # distance_matrix[i][j] = min(edge_weight, upper_bound)
                distance_matrix[i][j] = edge_weight
            else:
                distance_matrix[i][j] = 0

    # print(distance_matrix)

    # run TSP concorde
    matrix_sym = atsp_tsp(distance_matrix, strategy="avg")
    outf = "/tmp/myroute.tsp"
    with open(outf, 'w') as dest:
        dest.write(dumps_matrix(matrix_sym, name="My Route"))
    try:
        tour = run(outf,
                   start=dict_index_to_TSP_index[starting_kingdom_index],
                   solver="lkh")

        # convert to original indices
        tour_G = [
            dict_TSP_index_to_index[TSP_index] for TSP_index in tour["tour"]
        ]
        # print(tour_G)

        # stitch path together
        edge_list = tour_to_list_of_edges(tour_G)
        # print(edge_list)
        stiched_tour = [edge_list[0][0]]  # starting node
        edge_list.append((edge_list[-1][1], starting_kingdom_index))
        for i, j in edge_list:
            stiched_tour.extend(shortest_paths[i][j][1:])

        closed_walk = [
            dict_kingdom_index_to_name[index] for index in stiched_tour
        ]
    except:
        closed_walk = "Error"
    # print(closed_walk)

    return closed_walk
Example #7
0
def optimal_tour(features, mode, profile, out_points, solver):
    """
    A command line interface for solving the traveling salesman problem

    Input geojson features with point geometries
    and output the optimal tour as geojson feature collection.

     \b
      $ optimal_tour waypoints.geojson | geojson-summary
      19 points and 1 line

    If using geodesic or directions modes, input must be in lonlat coordinates

    Directions mode requires a Mapbox account and a valid token set as
    the MAPBOX_ACCESS_TOKEN environment variable.
    """
    log("Get point features")
    features = [f for f in features if f['geometry']['type'] == 'Point']
    if len(features) <= 2:
        raise click.UsageError(
            "Need at least 3 point features to create route")

    if mode != 'cartesian' and not is_lonlat(features):
        raise click.UsageError(
            "For this {} mode, input must be in lonlat coordinates".format(
                mode))

    log("Create travel cost matrix")
    if mode == 'cartesian':
        matrix = local_matrix(features, 'cartesian')
    elif mode == 'geodesic':
        matrix = local_matrix(features, 'geodesic')
    elif mode == 'directions':
        dist_api = mapbox.Distance()
        res = dist_api.distances(features, profile=profile)
        if res.status_code == 200:
            matrix = res.json()['durations']
        else:
            raise Exception(
                "Got a {0} error from the Distances API: {1}".format(
                    res.status_code, res.content))

    log("Prep data")
    matrix_sym = atsp_tsp(matrix, strategy="avg")

    outf = "/tmp/myroute.tsp"
    with open(outf, 'w') as dest:
        dest.write(dumps_matrix(matrix_sym, name="My Route"))

    log("Run TSP solver")
    tour = run(outf, start=0, solver=solver)
    order = tour['tour']

    features_ordered = [features[i] for i in order]

    log("Create lines connecting the tour")
    if mode == 'directions':
        # gather geojson linestring features along actual route via directions
        directions_api = mapbox.Directions()
        route_features = []
        for chunk in split_overlap(features_ordered + [features_ordered[0]],
                                   24):
            res = directions_api.directions(chunk, profile='mapbox.' + profile)
            if res.status_code == 200:
                route_features.append(res.geojson()['features'][0])
            else:
                raise Exception(
                    "Got a {0} error from the Directions API: {1}".format(
                        res.status_code, res.content))
    else:
        # Alternative, straight line distance between points
        route_coords = [f['geometry']['coordinates'] for f in features_ordered]
        route_coords.append(features_ordered[0]['geometry']['coordinates'])
        route_features = [{
            'type': 'Feature',
            'properties': {
                'tour': tour
            },
            'geometry': {
                'type': 'LineString',
                'coordinates': route_coords
            }
        }]

    # meld into one geojson feature collection
    log("Output feature collection")
    out_features = route_features
    if out_points:
        out_features += features_ordered

    collection = {'type': 'FeatureCollection', 'features': out_features}

    click.echo(json.dumps(collection))