1

So I made a question some days ago (here is the question) basically what I'm trying to do is given a 3D array, and a list of coordinates, add values to those coordinates until shortest path changes, the user Mohammed Kashif help me with my question but that was with a 2D list of coordinates, now what I'm trying to do is doing the same but with a 3D list of coordinates, the first list of coordinate with the first 5 arrays and the second list of coordinates with the next 5 arrays. This is what I try: (This is just an example, my list of coordinates, and the 3D array can have more elements)

import numpy as np
import networkx as nx
from copy import deepcopy

arr = np.array ([[[  0., 303.,  43.,  26.,  20.],
                  [  0.,   0.,   0.,   0.,   0.],
                  [  0.,  21.,   0.,   8.,   0.],
                  [  0.,  47.,   5.,   0.,   4.],
                  [  0.,  35.,   0.,   1.,   0.]],

                 [[  0., 356.,  40.,  32.,  49.],
                  [  0.,   0.,   0.,   0.,   0.],
                  [  0.,  36.,   0.,   1.,   0.],
                  [  0.,  25.,   1.,   0.,   1.],
                  [  0.,  40.,   0.,   3.,   0.]],

                 [[  0., 372.,  27.,  34.,  44.],
                  [  0.,   0.,   0.,   0.,   0.],
                  [  0.,  37.,   0.,   3.,   0.],
                  [  0.,  41.,   8.,   0.,   1.],
                  [  0.,  34.,   0.,   6.,   0.]],

                 [[  0., 300.,  46.,  37.,  46.],
                  [  0.,   0.,   0.,   0.,   0.],
                  [  0.,  40.,   0.,   1.,   0.],
                  [  0.,  48.,   2.,   0.,   5.],
                  [  0.,  43.,   0.,   2.,   0.]],

                 [[  0., 321.,  42.,  22.,  22.],
                  [  0.,   0.,   0.,   0.,   0.],
                  [  0.,  42.,   0.,   3.,   0.],
                  [  0.,  20.,   3.,   0.,   5.],
                  [  0.,  20.,   0.,   9.,   0.]],

                 [[  0., 319.,  48.,  21.,  39.],
                  [  0.,   0.,   0.,   0.,   0.],
                  [  0.,  29.,   0.,   0.,   1.],
                  [  0.,  38.,   0.,   0.,   7.],
                  [  0.,  40.,   1.,   5.,   0.]],

                 [[  0., 374.,  46.,  25.,  28.],
                  [  0.,   0.,   0.,   0.,   0.],
                  [  0.,  25.,   0.,   0.,   2.],
                  [  0.,  44.,   0.,   0.,   6.],
                  [  0.,  44.,   2.,   9.,   0.]],

                 [[  0., 341.,  34.,  21.,  49.],
                  [  0.,   0.,   0.,   0.,   0.],
                  [  0.,  27.,   0.,   0.,   9.],
                  [  0.,  25.,   0.,   0.,   8.],
                  [  0.,  49.,   1.,   1.,   0.]],

                 [[  0., 310.,  30.,  44.,  47.],
                  [  0.,   0.,   0.,   0.,   0.],
                  [  0.,  34.,   0.,   0.,   2.],
                  [  0.,  21.,   0.,   0.,   8.],
                  [  0.,  37.,   9.,   8.,   0.]],

                 [[  0., 321.,  27.,  44.,  31.],
                  [  0.,   0.,   0.,   0.,   0.],
                  [  0.,  21.,   0.,   0.,   5.],
                  [  0.,  41.,   0.,   0.,   1.],
                  [  0.,  41.,   1.,   5.,   0.]]])

n = 5          #Number of array for each path list and coordinates list 
graphs = []
pathaux = []

for i in arr:
    graphs.append(nx.from_numpy_array(i, create_using = nx.DiGraph)) #Create graphs from numpy array

for graph in graphs:
    pathaux.append(nx.shortest_path(graph, 0, 1, weight = 'weight'))   #Find the shortest path

path = [pathaux[i: i+n] for i in range(0, len(pathaux), n)] #Creates a 3D list "separating" for each 5 arrays 

print(path)
#path = [[[0, 4, 3, 2, 1], [0, 3, 1], [0, 2, 1], [0, 3, 2, 1], [0, 3, 1]], [[0, 3, 4, 2, 1], [0, 4, 2, 1], [0, 3, 1], [0, 2, 4, 3, 1], [0, 2, 1]]]

#path[0] = [[0, 4, 3, 2, 1], [0, 3, 1], [0, 2, 1], [0, 3, 2, 1], [0, 3, 1]] #Shortest path for the first 5 arrays
#path[1] = [[0, 3, 4, 2, 1], [0, 4, 2, 1], [0, 3, 1], [0, 2, 4, 3, 1], [0, 2, 1]] #Shortest path for the next 5 arrays

#Here are the 3D list of coordinates, the first two pair is for the first 5 array, the next four pairs are for the other 5 arrays
coordinates = [[[4, 3], [3, 2]], [[3, 4], [4, 2], [2, 4], [4, 3]]]

for i in coordinates:
    for x,y in i:
        # Make deepcopies of path and arr
        # For the first iteration, set newpath = path
        new_path = deepcopy(pathaux)
        temp_arr = deepcopy(arr)

        # Set counter for each coordinate to zero
        cnt = 0

        # Iterate till a change in path is observed
        while pathaux == new_path:
            # Add 1 to x,y
            temp_arr[:, x, y] = temp_arr[:, x, y] + 1

            # Increment the counter
            cnt += 1

            # Reconstruct the graph and shortest path
            temp_graph = []
            new_path = []
            for i in temp_arr:
                temp_graph.append(nx.from_numpy_array(i, create_using = nx.DiGraph))
                
            for graph in temp_graph:
                new_path.append(nx.shortest_path(graph, 0, 1, weight = 'weight'))

        #If we are out of the loop, this means that
        # the shortest path has changed. Print the details.
        print("For coordinates X={} and Y={} the change is at {}".format(x, y, cnt))

Here is the output for this code

#For the first 5 arrays
For coordinates X=4 and Y=3 the change is at 3
For coordinates X=3 and Y=2 the change is at 1

#For the next 5 arrays
For coordinates X=3 and Y=4 the change is at 1
For coordinates X=4 and Y=2 the change is at 1
For coordinates X=2 and Y=4 the change is at 1
For coordinates X=4 and Y=3 the change is at 3

As you can see the coordinates are right, but the values of change are wrong, if I do it manually, adding values to the coordinates until my list changes this is my real output:

#For the first 5 arrays
For coordinates X=4 and Y=3 the change is at 5
For coordinates X=3 and Y=2 the change is at 6

#For the next 5 arrays
For coordinates X=3 and Y=4 the change is at 1
For coordinates X=4 and Y=2 the change is at 1
For coordinates X=2 and Y=4 the change is at 3
For coordinates X=4 and Y=3 the change is at 3

I thought about maybe reshape arr from a 3D array to a 4D array with shape (2, 5, 5, 5) but I believe I have to do a double for-loop so its more slow, I know it's a long question, but I don't know how to make the corresponding first 5 arrays with the first shortest path and the first list of coordinates work together and do the same for the next five arrays with the corresponding shortest path and coordinates. Again, sorry for the long question, any help will be appreciated, thank you!

1 Answers1

2

You should consider partitions separately. Apply the following changes to your existing code, and it should work:

...

arr_partition = [arr[i: i+n] for i in range(0, len(arr), n)]
j = 0
for i in coordinates:
    print("The tree is", j)
    for x, y in i:
        new_path = deepcopy(path[j])
        temp_arr = deepcopy(arr_partition[j])
        cnt = 0
        while path[j] == new_path:
            ...
    print()
    j += 1
        
...

Output:

The tree is 0
For coordinates X=4 and Y=3 the change is at 5
For coordinates X=3 and Y=2 the change is at 6

The tree is 1
For coordinates X=3 and Y=4 the change is at 1
For coordinates X=4 and Y=2 the change is at 1
For coordinates X=2 and Y=4 the change is at 3
For coordinates X=4 and Y=3 the change is at 3
Alperen
  • 3,772
  • 3
  • 27
  • 49
  • Wow, thank you so much! Maybe this to much but what if I need add a print("The tree is", j) but without repetition, so It would say something like "The tree is 0" and then print the two first lines of the output, and then say, "The tree is 1" and then print the next four lines? Because its inside a loop, if I try to print what I say, well it will repeat, maybe this is to much to ask, but thank you really! – Carlos Eduardo Corpus Jul 13 '20 at 22:22
  • @CarlosEduardoCorpus You are welcome. Take a look at the answer. Just updated it – Alperen Jul 14 '20 at 05:30