Лучший способ пойти к индексу в numpy, с переносом - PullRequest
0 голосов
/ 11 ноября 2018

Допустим, у меня есть 2D-массив ниже:

 [[ 0 0 0 0 0 0 ]
  [ 0 0 0 0 0 0 ]
  [ 0 0 0 0 0 0 ]
  [ 0 0 0 0 0 2 ]
  [ 0 1 0 0 0 0 ]
  [ 0 0 0 0 0 0 ]]

Я бы хотел получить направление от «1» (индекс 4,1) до «2» (индекс 3,5). Предполагая направления только вверх, вниз, влево, вправо. Таким образом, нет диагонального движения.

Один из способов получить направления:

"right" if destination.x > start.x else "left" if target.x < start.x else None

"down" if destination.y > start.y else "up" if destination.y < start.y else None

Таким образом, для этого примера мы можем перейти к «2» или пункту назначения, перейдя «вверх» или «вправо». Это, конечно, всего один шаг, после перемещения вы можете выполнить ту же логику, чтобы приблизиться к месту назначения.

Проблема с этой логикой заключается в том, что она не учитывает упаковку. С этой логикой потребуется 5 шагов, чтобы добраться до места назначения. Существует более короткий путь, когда вы фактически идете влево или вверх, что может привести к цели всего за 3 шага из-за переноса.

Думал о создании другого массива, где начало будет серединой массива и будет выполнять ту же логику Проблема в том, что если массив четный (например, это 6x6, нужно дополнить его до середины. Например:

 [[ 0 0 0 0 0 0 0]
  [ 0 0 0 0 0 0 0]
  [ 0 2 0 0 0 0 0]
  [ 0 0 0 1 0 0 0]
  [ 0 0 0 0 0 0 0]
  [ 0 0 0 0 0 0 0]
  [ 0 0 0 0 0 0 0]]

Здесь массив теперь 7x7. Я считаю, что есть простой способ получить ответ без этого дополнительного шага, но я не могу об этом думать.

Ответы [ 3 ]

0 голосов
/ 11 ноября 2018

Ну, есть довольно простая формула для вычисления расстояния в случае периодических граничных условий. Ниже я рассматриваю только периодические по оси X:

import numpy as np

# periodic boundary condition for the x-axis only
def steps(start, dest, L_x):
    x_start = start[1]
    y_start = start[0]
    x_dest = dest[1]
    y_dest = dest[0]

    dx = x_dest - x_start
    if np.abs(dx) <= L_x/2:
        steps_x = x_dest - x_start
    else:
        if dx > 0:
            steps_x = (x_dest - L_x) - x_start
        else:
            steps_x = (x_dest + L_x) - x_start            

    steps_y = y_dest - y_start

    return steps_x, steps_y

Пример:

grid = np.array([[0, 0, 0, 0, 0, 0 ],
                 [0, 0, 0, 0, 0, 0 ],
                 [0, 0, 0, 0, 0, 0 ],
                 [0, 0, 0, 0, 0, 2 ],
                 [0, 1, 0, 0, 0, 0 ],
                 [0, 0, 0, 0, 0, 0 ]])

L_x = grid.shape[1]    
start = (4, 1)  # (y, x) or (i, j)
dest = (3, 5)

steps_x, steps_y = steps(start, dest, grid)
dir_x = 'left' if steps_x < 0 else 'right'
dir_y = 'up' if steps_y < 0 else 'down'
print(abs(steps_x), dir_x, ',', abs(steps_y), dir_y)

Out: 2 left , 1 up
0 голосов
/ 12 ноября 2018

Я пытаюсь по-другому:

На горизонтальной оси длины size перейти от a до b, пусть delta = ((b-a)%size*2-1)//size.

  • , если delta=-1, a=b: вы не двигаетесь.
  • , если delta=0: вам нужно идти направо.
  • , если delta=1: вам нужно идти налево.

Так что этот код работает

size=10
vertical=['down','up',None]
horizontal=['right','left',None]

def side(a,b):
    return ((b-a)%size*2-1)//size

def step(M1,M2):
    x1,y1=M1
    x2,y2=M2
    return (vertical[side(x1,x2)],horizontal[side(y1,y2)])

Например:

In [6]: step((2,1),(2,8))
Out[6]: (None, 'left')
0 голосов
/ 11 ноября 2018

Можете ли вы рассмотреть возможность использования этого метода?

import numpy as np

# build the array
a = np.zeros( (6,6), dtype=int )
a[4][1] = 1
a[3][5] = 2

# extract required informations
i,j = np.where(a == 1)
h,k =np.where(a == 2)

print (i-h) => [1]
print (j-k) => [-4]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...