简体   繁体   中英

Finding all possible combinations of insertions in nested list python

For a vehicle routing problem, I need to check for a certain list with multiple routes, what the insertion of a certain city would do for the total length of that route list. All the cities are represented by integer numbers.

Basically I need to insert an integer element into every possible "location", and then proceed to calculate the shortest distance of all possibilities. Consider this nested list of routes:

rl = [[0, 7, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0],
[0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0],
[0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]] 

Where 0 is the headquarters, here is where the route starts and ends every day. Say I need to insert a city which is represented by a 9.

Expected output would than be:

[[0, 9, 7, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], ...rest of list] 
[[0, 7, 9, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], ...rest of list] 
[[0, 7, 40, 9  41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], ...rest of list] 
[[0, 7, 40, 41, 9  96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], ...rest of list]

and so on, until every possible location has been tried and appended to feasible_matrix.

I wrote the following function to achieve this:

def check_possible_insertions(city, route_list):
    feasible_matrix = []
    for i, route in enumerate(route_list):
        for j, value in enumerate(route[1:]):
            possibility = route_list.copy()
            possibility[i].insert(j+1, city)
            feasible_matrix.append(possibility)
    return feasible_matrix

Where i first create a "feasible" matrix, then loop over all the routes. Then, for every possible position in a route (second for-loop), I create a copy of route_list (The original route list passed as parameter). Then I insert the city in the right route [i] at the right place (j) and append the possibility to my feasible_matrix.

At least, that's how this code should work in my mind. A function call check_possible_insertions(9, rl) tells me the code doesn't behave as expected: It's simply inserting #j number of 9's at the front of every route. Am overlooking something but cannot figure out what. What am I doing wrong?

You are only shallow copying the whole list of lists. You meant to shallow copy an individual route:

possibility = route.copy()
possibility.insert(j, city)

Also in your inner loop value is unused, so a possible version of your function is:

def check_possible_insertions(city, route_list):
    feasible_matrix = []
    for i, route in enumerate(route_list):
        new_list=[]
        feasible_matrix.append(new_list)
        for j in range(1, len(route)):
            possibility = route.copy()
            possibility.insert(j, city)
            new_list.append(possibility)
    return feasible_matrix

This generates a list of lists of routes, which could be reduced down to a new rl when the optimal route is found. eg:

rl = [[0, 7, 40, 78, 0],
[0, 56, 45, 2, 0],
[0, 35, 97, 60, 0]]

result = check_possible_insertions(9,rl)
print(result)

Output:

[[[0, 9, 7, 40, 78, 0], [0, 7, 9, 40, 78, 0], [0, 7, 40, 9, 78, 0], [0, 7, 40, 78, 9, 0]], [[0, 9, 56, 45, 2, 0], [0, 56, 9, 45, 2, 0], [0, 56, 45, 9, 2, 0], [0, 56, 45, 2, 9, 0]], [[0, 9, 35, 97, 60, 0], [0, 35, 9, 97, 60, 0], [0, 35, 97, 9, 60, 0], [0, 35, 97, 60, 9, 0]]]

The problem is that route_list.copy() creates a shallow copy, the inner list are the same objects, as an example:

rl = [[0, 7, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0],
[0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0],
[0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]

cp = rl.copy()
cp[0].insert(0, 9)

for i in rl:
print(i)

Output

[9, 0, 7, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0]
[0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0]
[0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]

As you can see the first list of rl was modified because it is the same as the first in cp .

As a solution, you could use deepcopy

import copy


def check_possible_insertions(city, route_list):
    feasible_matrix = []
    for i, route in enumerate(route_list):
        for j, value in enumerate(route[1:]):
            possibility = copy.deepcopy(route_list)
            possibility[i].insert(j+1, city)
            feasible_matrix.append(possibility)
    return feasible_matrix

Output (first 5 results)

[[0, 9, 7, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], [0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0], [0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]
[[0, 7, 9, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], [0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0], [0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]
[[0, 7, 40, 9, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], [0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0], [0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]
[[0, 7, 40, 41, 9, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], [0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0], [0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]
[[0, 7, 40, 41, 96, 9, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], [0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0], [0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM