【问题标题】:Traveling Sales man algorithm without returning to the starting point旅行推销员算法不返回起点
【发布时间】:2021-07-18 05:41:28
【问题描述】:

您好,我在 python 中找到了旅行商算法。但我想要一个不同的版本,其中推销员不会回到起始位置。路径应该是最短的。请提出解决方案。我还尝试了 Held-Karp(它使用动态编程来解决 TSP),但它也返回了错误的结果。路径不是最短的。 谢谢。

import json

import flask
import numpy as np
from flask import request, jsonify
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

app = flask.Flask(__name__)
app.config["DEBUG"] = True


def create_data_model(distance_input_matrix):
    """Stores the data for the problem."""
    data = {'distance_matrix': distance_input_matrix, 'num_vehicles': 1, 'depot': 0}
    return data


def print_solution(manager, routing, solution):
    """Prints solution on console."""
    # print('Objective: {} miles'.format(solution.ObjectiveValue()))
    index = routing.Start(0)
    # plan_output = 'Route for vehicle 0:\n'
    plan_output = ''
    route_distance = 0
    while not routing.IsEnd(index):
        plan_output += '{}->'.format(manager.IndexToNode(index))
        previous_index = index
        index = solution.Value(routing.NextVar(index))
        route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
    plan_output += '{}'.format(manager.IndexToNode(index))
    return plan_output
    # print(plan_output)
    # plan_output += 'Route distance: {}miles\n'.format(route_distance)


def main(distance_input_matrix=None):
    """Entry point of the program."""
    # Instantiate the data problem.
    data = create_data_model(distance_input_matrix)

    # Create the routing index manager.
    manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
                                           data['num_vehicles'], data['depot'])

    # Create Routing Model.
    routing = pywrapcp.RoutingModel(manager)

    def distance_callback(from_index, to_index):
        """Returns the distance between the two nodes."""
        # Convert from routing variable Index to distance matrix NodeIndex.
        from_node = manager.IndexToNode(from_index)
        to_node = manager.IndexToNode(to_index)
        return data['distance_matrix'][from_node][to_node]

    transit_callback_index = routing.RegisterTransitCallback(distance_callback)

    # Define cost of each arc.
    routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)

    # Setting first solution heuristic.
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)

    # Solve the problem.
    solution = routing.SolveWithParameters(search_parameters)

    # Print solution on console.
    if solution:
        return print_solution(manager, routing, solution)


@app.route('/', methods=['GET'])
def home():
    return main()


@app.route('/optimize', methods=['POST'])
def optimize():
    if request.json:
        data_matrix = request.json['data']
        narrows = len(data_matrix)  # 3 rows in your example
        narcs = len(data_matrix[0])
        a = np.zeros((narrows + 1, narcs + 1), dtype='int32').tolist()
        for i in range(len(data_matrix)):
            for j in range(len(data_matrix[i])):
                a[i][j] = data_matrix[i][j]
        #result = main(a)
        result = main(data_matrix)
        r_l = result.split('->')
        #r_l.remove(str(narrows))
        return jsonify({'data': r_l})


app.run()

我尝试添加一个新位置的另一种方法,该位置与所有现有点的距离为零。使用 TSP 解决它并删除该点。但它也没有给出正确的结果。

【问题讨论】:

  • 也许在运筹学 StackExchange 上问这个问题? or.stackexchange.com
  • 添加虚拟位置应该是要走的路。你给程序提供了哪些输入,它输出了什么用于复制?

标签: python traveling-salesman


【解决方案1】:

如果我正确阅读了代码,对 distance_callback 函数的调整可能会起作用:

def distance_callback(from_index, to_index):
        """Returns the distance between the two nodes."""
        # Convert from routing variable Index to distance matrix NodeIndex.
        HUGE_DISTANCE = 1e9 # Pick something suitable
        if to_index == 0:
            return HUGE_DISTANCE
        else:
            from_node = manager.IndexToNode(from_index)
            to_node = manager.IndexToNode(to_index)
            return data['distance_matrix'][from_node][to_node]

这(希望)所做的是使返回起始节点的成本如此昂贵(距离很远),因此强烈建议不要使用任何此类解决方案。请注意,离开起始节点不受影响 - “自然”距离保持不变。

以上假设起始节点的索引为 0。如果这是错误的,代码可以很容易地调整。如果data['distance_matrix'][x][y] 的元素不仅仅是一个数字(我无法从您发布的内容中看出),那么您将需要上述版本,它仅通过手术改变返回起始节点的距离/成本.

【讨论】:

    猜你喜欢
    • 2013-06-09
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    • 2014-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多