Массив за пределы, проверяя элементы - PullRequest
0 голосов
/ 28 мая 2020

Мой для l oop всегда выходит за пределы. Он продолжает проверять, является ли элемент> 0. Я пробовал множество ограничений, но ни одно из них не сработало. Есть ли у вас предложения?

###Creation of the graph in a method
def graph(self):
    ###Creation of the given array I added zero rows and columns because of no restrictions at the boarders.
    a = np.array([
        [0, 16, 12, 21, 0, 0, 0],
        [16, 0, 0, 17, 20, 0, 0],
        [12, 0, 0, 28, 0, 31, 0],
        [21, 17, 28, 0, 18, 19, 23],
        [0, 20, 0, 18, 0, 0, 11],
        [0, 0, 31, 19, 0, 0, 27],
        [0, 0, 0, 23, 11, 27, 0]]),
        ###Determination of datatype size
        dtype = np.uint8
    )
    ###Graph dictionary for letting the bfs know who's connected to whom
    graph = {}
    ###For loop in order to iterate through the elements
    for r in range(len(a)):
        for c in range(len(a)):
            ###Checking whether element is greater than 0
            if a[r, c] > 0:
                ###List of coordinates for checking elements connection
                d = [r-1, c+1, r+1, c-1]
                ###Checking whether one of the surrounding elements is greater than 0
                if (a[d[0], c] > 0 and r >= 0) or (a[r, d[1]] > 0 and c <= len(a)) or (a[d[2], c] > 0 and r <= len(a)) or (a[r, d[3]] > 0 and c >= 0):
                    ###Creates the key in the dictionary without values
                    graph[a[r, c]] = []
                    ###Add value(s) to the specific key in the dictionary
                    if a[d[0], c] > 0:
                        graph[a[r, c]].append(a[d[0], c])
                    if a[r, d[1]] > 0:
                        graph[a[r, c]].append(a[r, d[1]])
                    if a[d[2], c] > 0:
                        graph[a[r, c]].append(a[d[2], c])
                    if a[r, d[3]] > 0:
                        graph[a[r, c]].append(a[r, d[3]])
    ###Return of the graph in form of a dictionary
    return(graph)

1 Ответ

0 голосов
/ 28 мая 2020

Чтобы ответить на вопрос, почему ограничения не работают, давайте рассмотрим одно из них, например (подставив значение d[0], поскольку список d на самом деле не помогает нам ни в решении проблемы, ни в упрощение кода):

a[r-1, c] > 0 and r >= 0

Короткое замыкание and можно использовать, чтобы убедиться, что значение не проверяется, да. Но короткое замыкание работает наоборот. В этом примере a[d[0], c] > 0 проверяется безоговорочно, а затем r >= 0 проверяется только в том случае, если первое, что привело к истинному значению. Но первая часть вызывает ошибку, поэтому вторая уже слишком поздно, чтобы предотвратить ошибку. Вы хотели r >= 0 and a[r-1, c] > 0. (Заменяя r-1 на d[0], становится понятнее: мы проверяем значение r, а , затем пробуем индексирование, использующее r.)


Но мы можем добиться большего, если воспользуемся преимуществами операций Numpy. Numpy в значительной степени специально разработан, чтобы упростить кодирование таких проблем и сделать их более производительными.

Первое, что мы хотим сделать, это увидеть места, где есть ненулевые значения в данных :

>>> a = np.array([
...     [0, 16, 12, 21, 0, 0, 0],
...     [16, 0, 0, 17, 20, 0, 0],
...     [12, 0, 0, 28, 0, 31, 0],
...     [21, 17, 28, 0, 18, 19, 23],
...     [0, 20, 0, 18, 0, 0, 11],
...     [0, 0, 31, 19, 0, 0, 27],
...     [0, 0, 0, 23, 11, 27, 0]
... ], dtype = np.uint8)
>>> a
array([[ 0, 16, 12, 21,  0,  0,  0],
       [16,  0,  0, 17, 20,  0,  0],
       [12,  0,  0, 28,  0, 31,  0],
       [21, 17, 28,  0, 18, 19, 23],
       [ 0, 20,  0, 18,  0,  0, 11],
       [ 0,  0, 31, 19,  0,  0, 27],
       [ 0,  0,  0, 23, 11, 27,  0]], dtype=uint8)
>>> a != 0 # Yes, it's really *this* easy
array([[False,  True,  True,  True, False, False, False],
       [ True, False, False,  True,  True, False, False],
       [ True, False, False,  True, False,  True, False],
       [ True,  True,  True, False,  True,  True,  True],
       [False,  True, False,  True, False, False,  True],
       [False, False,  True,  True, False, False,  True],
       [False, False, False,  True,  True,  True, False]])

И давайте получим индексы этих позиций:

>>> np.where(a != 0)
(array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
       6, 6], dtype=int64), array([1, 2, 3, 0, 3, 4, 0, 3, 5, 0, 1, 2, 4, 5, 6, 1, 3, 6, 2, 3, 6, 3,
       4, 5], dtype=int64))

Этот результат немного сложно понять; мы получаем кортеж из двух одномерных массивов, представляющих все x-координаты и y-координаты ненулевых значений (они также сохраняются с использованием собственного целочисленного типа вашей системы, поскольку они являются индексами; как вы можете видеть , Я на 64-битной машине). К счастью, Numpy также легко объединить их в пары:

>>> np.transpose(np.where(a != 0))
# long output omitted

Это все хорошо, но как теперь искать соседей? Я рассмотрю случай соседей выше текущей позиции, а остальное оставлю в качестве упражнения.

Мы сделаем это, построив массив, значения которого представляют те, которые находятся над исходной позицией массива ( заполнение нулями верхнего ряда). Мы делаем это, разрезая массив, а затем добавляя строку. Нам нужны все строки, кроме last , а затем мы заполняем нулями top . Но более простой способ сделать это - начать с двумерного массива нулей равного размера и поместить соответствующие строки в нижнюю . Итак:

>>> above = np.zeros(a.shape, dtype=np.uint8)
>>> above[1:, :] = a[:-1, :]
>>> above
array([[ 0,  0,  0,  0,  0,  0,  0],
       [ 0, 16, 12, 21,  0,  0,  0],
       [16,  0,  0, 17, 20,  0,  0],
       [12,  0,  0, 28,  0, 31,  0],
       [21, 17, 28,  0, 18, 19, 23],
       [ 0, 20,  0, 18,  0,  0, 11],
       [ 0,  0, 31, 19,  0,  0, 27]], dtype=uint8)

Обратите внимание на пары значений, используемые для нарезки: каждая соответствует отдельному измерению массива. Таким образом, [1:, :] выполняет срезы начиная со строки 1 и далее, сохраняя все столбцы в качестве места назначения; [:-1, :] нарезает каждую строку, кроме последней, в качестве наших исходных данных.

Теперь мы можем проверить ненулевые места, а также ненулевые соседние элементы выше:

>>> (a != 0) & (above != 0)
array([[False, False, False, False, False, False, False],
       [False, False, False,  True, False, False, False],
       [ True, False, False,  True, False, False, False],
       [ True, False, False, False, False,  True, False],
       [False,  True, False, False, False, False,  True],
       [False, False, False,  True, False, False,  True],
       [False, False, False,  True, False, False, False]])

(Скобки здесь необходимы; объяснение немного сложно.)

Наконец, мы можем посмотреть эти координаты и для каждой из них записать ссылку на график обычным способом:

>>> for r, c in np.transpose(np.where((a != 0) & (above != 0))):
...    print('there is a link from ({r}, {c}) to ({r - 1}, {c})')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...