【问题标题】:Path Connecting Points without overlapping in PythonPython中不重叠的路径连接点
【发布时间】:2021-06-13 21:22:31
【问题描述】:

我想要一个这样的路径连接点: enter image description here

根据我的尝试,这是我能够在 Python 中实现的结果: enter image description here

看起来相当简单。有可能吗?

【问题讨论】:

    标签: python shortest-path shapely


    【解决方案1】:
    points=[[2031.0974638138432, 8871.788899127823],
     [1946.0939073523768, 8687.702718346474],
     [1868.9610243990464, 8542.951197953029],
     [2061.006139498597, 8393.47953820238],
     [2163.3253106537886, 8264.46188196409],
     [2541.119051912334, 8232.994153653774],
     [2785.1108448732557, 8292.782817554034],
     [2967.711185007007, 8424.947266512696],
     [2967.711185007007, 8602.739911576653],
     [2709.552146487491, 8752.211571327301],
     [2429.355105791343, 8808.853442507185],
     [2150.732166552858, 8744.34463924972],
     [2087.7665291581216, 8531.937522878434],
     [2402.594716131818, 8379.319070407408],
     [2638.7157524747163, 8461.135134180222],
     [2446.670637375166, 8541.377851316203],
     [2492.849155914053, 8630.642922304622],
     [2444.788613747456, 8669.072915834848],
     [2366.462005771966, 8620.088463227232]]
    
    starting=5
    
    
    
    import math
    from ortools.constraint_solver import routing_enums_pb2
    from ortools.constraint_solver import pywrapcp
    
    
    def create_data_model(points,starting):
        """Stores the data for the problem."""
        data = {}
        # Locations in block units
        data['locations'] = points  
        data['num_vehicles'] = 1
        data['depot'] = starting
        return data
    
    
    def compute_euclidean_distance_matrix(locations):
        """Creates callback to return distance between points."""
        distances = {}
        for from_counter, from_node in enumerate(locations):
            distances[from_counter] = {}
            for to_counter, to_node in enumerate(locations):
                if from_counter == to_counter:
                    distances[from_counter][to_counter] = 0
                else:
                    # Euclidean distance
                    distances[from_counter][to_counter] = (int(
                        math.hypot((from_node[0] - to_node[0]),
                                   (from_node[1] - to_node[1]))))
        return distances
    
    
    def print_solution(manager, routing, solution):
        """Prints solution on console."""
        index = routing.Start(0)
        plan_output = []
        route_distance = 0
        while not routing.IsEnd(index):
            plan_output.append(manager.IndexToNode(index))
            previous_index = index
            index = solution.Value(routing.NextVar(index))
            route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
       
        return plan_output
        
    
    
    def main(points,starting=0):
        """Entry point of the program."""
        # Instantiate the data problem.
        data = create_data_model(points,starting)
    
        # Create the routing index manager.
        manager = pywrapcp.RoutingIndexManager(len(data['locations']),
                                               data['num_vehicles'], data['depot'])
    
        # Create Routing Model.
        routing = pywrapcp.RoutingModel(manager)
    
        distance_matrix = compute_euclidean_distance_matrix(data['locations'])
    
        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 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)
    
    
    if __name__ == '__main__':
        permutation = main(points,starting=starting)
        points2=[]
        for i in permutation:
            points2.append(points[i])
        x,y = map(list,zip(*points2))
        from matplotlib import pyplot as plt
        plt.plot(x,y,'-o')
    

    【讨论】:

    • 这需要安装ortools(pip install ortools)。现在在顶部只需更改变量点和起点,即您要开始路线的位置。它应该可以解决您的问题
    【解决方案2】:

    您是否每次都通过最短路线将线路从点连接到点?看起来是这样的。我建议您标记您放置的每个点,以便您可以按照放置所有内容的方式连接所有内容。

    【讨论】:

      【解决方案3】:

      这看起来像是一个旅行推销员问题。我在网上查了一下,发现了一个关于旅行商问题的库。 https://pypi.org/project/python-tsp/。它应该有助于创建有效的非重叠路线。一旦它给你一个排列,使用这些点并组织你的新点列表。

      例子:

      points2=[]
      for i in permutation:
          points2.append(points[i])
      

      之后,您可以绘制points2

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-02
        • 2021-07-21
        相关资源
        最近更新 更多