I want to find the shortest route to travel through all points

Continuation of the last time

In Previous article, I read the code to find the shortest path from the start point to the end point when I took some points. I couldn't go through all the points in the previous code, so let's think about that part for a moment. Please note that it is a study memo of optimization that has failed in various ways after all. Click here for a variety of textbooks (https://qiita.com/SaitoTsutomu/items/bfbf4c185ed7004b5721).

Implementation details

Last implementation

When I focused on a certain point, I formulated the relationship between the number of roads entering that point and the number of roads exiting that point. At the start point, there is one more road going out from that point, and at the end point, there is one more road going into that point. Other than that, both are the same number. With this implementation, it will not be the shortest path "through all points", so I will try that part.

for nd in g.nodes():
    m += lpSum(x[k] for k, (i, j) in r if i == nd) \
      == lpSum(x[k] for k, (i, j) in r if j == nd) + {source:1, sink:-1}.get(nd, 0) #Constraint

Progress 1: Define the number of lines that go in and out of a certain point

When paying attention to a certain point, if the total number of lines entering and exiting that point is 2 (the end point and start point is 1), it seems that "not passing" will disappear. However, when I actually tried it, it became a pattern that made a ring other than the favorite route. difficult···.

from pulp import *
import networkx as nx
g = nx.fast_gnp_random_graph(10, 0.8, 0) #When the third argument is 1, the bidirectional route is g.Hold on edges

source, sink = 0, 2 #start point,end point
r = list(enumerate(g.edges()))
m = LpProblem() #Mathematical model
x = [LpVariable('x%d'%k, lowBound=0, upBound=1) for k, (i, j) in r] #variable(Whether to enter the road)
m += lpSum(x) #Objective function
for nd in g.nodes():
    m += lpSum(x[k] for k, (i, j) in r if i == nd) \
         + lpSum(x[k] for k, (i, j) in r if j == nd) == {source:1, sink:1}.get(nd, 2) #Constraint
m.solve()
print([(i, j) for k, (i, j) in r if value(x[k]) ==1])

Here is the result. It should go from 0 to 2, but there is a ring at points other than 0,5,2. How should we connect these two routes? image.png

Progress 2: Introducing the concept of distance on the road

In the previous implementation, we considered all the paths to be the same length and chose the shortest path. In order to make it a little more practical, I tried to see what happens when I put in the concept of length. I once defined the length as "the value obtained by adding the node numbers at both ends of each route". I referred to this article for the manners such as g.edges [i, j] ["dist"].

#https://qiita.com/kzm4269/items/081ff2fdb8a6b0a6112f
n = 10 #Number of nodes
g = nx.random_graphs.fast_gnp_random_graph(n, 0.9, 8)
for i,j in g.edges():
    g.edges[i, j]["dist"] = i+j

The code for the optimization part hasn't changed much, but it's reprinted just in case.

source, sink = 0, 9 #start point,end point
r = list(enumerate(g.edges()))
m = LpProblem() #Mathematical model
x = [LpVariable('x%d'%k, lowBound=0, upBound=1) for k, (i, j) in r] #variable(Whether to enter the road)
m += lpSum(x[k] * g.edges[i,j]["dist"] for k, (i, j) in r) #Objective function
for nd in g.nodes():
    m += lpSum(x[k] for k, (i, j) in r if i == nd) \
        + lpSum(x[k] for k, (i, j) in r if j == nd) == {source:1, sink:1}.get(nd, 2) #Constraint
m.solve()
print([(i, j) for k, (i, j) in r if value(x[k]) ==1])

The one selected for the optimum route is taken out and illustrated. This article was useful for sprint_layout.

def draw(g):
    rn = g.nodes() #Node list
    pos = nx.spring_layout(g, pos={i:(i/4, i%4) for i in rn}) #Node position
    """drawing"""
    nx.draw_networkx_labels(g, pos=pos)
    nx.draw_networkx_nodes(g, node_color='w', pos=pos)
    nx.draw_networkx_edges(g, pos=pos)
    plt.show()

G = nx.DiGraph()
for k,(i,j) in r:
    if value(x[k]) == 1:
        nx.add_path(G, [i, j])
draw(G)

Click here for the drawing result. It seems that this time it happened to be a proper route. The phenomenon of forming a ring should be possible here as well.

image.png

Click here for the total distance for the optimal solution. There seems to be this too!

value(m.objective)
>>>81.0

Finally

Optimization fun!

Recommended Posts

I want to find the shortest route to travel through all points
I want to get the operation information of yahoo route
I want to automatically find high-quality parts from the videos I shot
I want to pin Spyder to the taskbar
I want to output to the console coolly
I want to scrape them all together.
I want to handle the rhyme part1
I want to handle the rhyme part3
I want to display the progress bar
I want to handle the rhyme part2
I want to handle the rhyme part5
I want to handle the rhyme part4
I want to handle the rhyme part7 (BOW)
I want to easily find a delicious restaurant
[Introduction to Algorithm] Find the shortest path [Python3]
I want to customize the appearance of zabbix
I want to use the activation function Mish
I want to display the progress in Python!
I want to see the file name from DataLoader
I want to grep the execution result of strace
I want to scroll the Django shift table, but ...
The shortest route to get a cultural fish environment
I want to find a popular package on PyPi
I want to inherit to the back with python dataclass
I want to fully understand the basics of Bokeh
I just want to find the 95% confidence interval for the difference in population ratios in Python
I want to write in Python! (3) Utilize the mock
I want to handle the rhyme part6 (organize once)
I want to automate ssh using the expect command!
I want to publish the product at the lowest cost
I want to use the R dataset in python
I want to handle the rhyme part8 (finished once)
I want to increase the security of ssh connections
I want to find a stock that will rise 5 minutes after the Nikkei Stock Average rises
I want to find the intersection of a Bezier curve and a straight line (Bezier Clipping method)
I tried to find the entropy of the image with python
I tried to find out the outline about Big Gorilla
[TensorFlow] I want to master the indexing for Ragged Tensor
I want to use the latest gcc without sudo privileges! !!
I want to initialize if the value is empty (python)
I want to save the photos sent by LINE to S3
I tried to find the average of the sequence with TensorFlow
I want to automate ssh using the expect command! part2
maya Python I want to fix the baked animation again.
I want to move selenium for the time being [for mac]
I want to use only the normalization process of SudachiPy
I want to change the Japanese flag to the Palau flag with Numpy
I want to calculate the allowable downtime from the operating rate
[Python] I want to use the -h option with argparse
I want to judge the authenticity of the elements of numpy array
I want to know the features of Python and pip
I want to make the Dictionary type in the List unique
I want to map the EDINET code and securities number
Keras I want to get the output of any layer !!
I want to align the significant figures in the Numpy array
I want to know the legend of the IT technology world
I want to create a Dockerfile for the time being.
I didn't want to write the AWS key in the program
I want to solve Sudoku (Sudoku)
I want to get the name of the function / method being executed
I want to record the execution time and keep a log.