Как разработать алгоритм на python для создания определенных пар из значений в массиве numpy

#python #algorithm #numpy

#python #алгоритм #numpy

Вопрос:

Я хочу автоматически создать несколько пар на основе данных, хранящихся в виде массивов numpy. Фактически, числа в моих первых массивах — это номера нескольких строк. Я хочу соединить линии и создать поверхности, используя созданные пары. Это массив строк:

 line_no= np.arange (17, 25)
 

Эти строки расположены в двух перпендикулярных направлениях. Я загрузил рисунок, чтобы показать его (они имеют синий и красный цвета). Я знаю, где меняется направление моих строк, и вызываю его как sep .

 sep=20
 

Другие данные, которые должны быть полезными, — это количество точек, создающих строки. Я называю это rep .

 rep = np.array([3,3,1])
 

Затем я использовал следующий код для достижения своей цели, но это неверно:

 start =line_no[0]
N_x = len(rep) - 1
N_y = max(rep) - 1
grid = np.zeros((N_y   1, N_x   1, 2))
kxs = [0]   [min(rep[i], rep[i 1]) for i in range(len(rep)-1)]
T_x = sum(kxs)
T_y = sum(rep) - len(rep)
T_total = T_x   T_y
lines = np.arange(start, start T_total)
lines_before = 0
for i in range(N_x):
    for j in range(N_y, -1, -1):
        if j >= kxs[i 1]:
            continue
        grid[j,i,0] = lines[lines_before]
        lines_before  = 1
for i in range(N_x 1):
    for j in range(N_y-1, -1, -1):
        if j < rep[i] - 1:
            grid[j,i,1] = lines[lines_before]
            lines_before  = 1
joints=np.array([])
for i in range(N_x - 1):
    for j in range(N_y - 1):
        square = np.append(grid[j:j 2, i, 0], grid[j, i:i 2, 1])
        if all(square):
            new_joints = square
            joints=np.append (new_joints,joints)
 

На моем рисунке у меня есть два сценария: A ( rep = np.array([3,3,1]) ) и B ( rep = np.array([1,3,3]) ). Для A я хочу иметь следующие пары:

 17, 21, 18, 23
18, 22, 19, 24
 

И для B:

 18, 21, 19, 23
19, 22, 20, 24
 

На самом деле распределение моих строк может измениться. Например, в сценарии A последняя строка не создает никакой поверхности, а в B первая не находится ни на одной поверхности, и в случае, если у меня может быть несколько строк, которые не являются частью какой-либо поверхности. Например, у меня может быть другая красная строка с номером строки ниже 21 , которая не создает никакой поверхности. Спасибо, что обратили внимание на мою проблему. Я заранее признателен за любую помощь.

введите описание изображения здесь

Более сложный случай также показан ниже. В сценарии C у меня есть:

 line_no= np.arange (17, 42)
sep=29
rep = np.array([5,4,4,2,2,1])
 

В сценарии D у меня есть:

 line_no= np.arange (17, 33)
sep=24
rep = np.array([1,3,4,4])
 

введите описание изображения здесь

Ответ №1:

Извините, но я не смог пройти через вашу реализацию. Совет на следующий раз — пожалуйста, попробуйте прокомментировать свой код, это помогает.

В любом случае, вот несколько удобочитаемая реализация, которая выполняет эту работу. Но я советую вам проверить больше сценариев, чтобы проверить правильность сценариев, прежде чем делать какие-либо выводы.

 import numpy as np

line_no = np.arange(17, 25)
sep = 20  # this information is redundant for the problem
nodes = np.array(np.array([1,3,4,4]))

# for generalised implementation hlines start from 0 and vlines start where hlines end
# offset parameter can be used to change the origin or start number of hlines and hence changed the vlines also
offset = 17

# calculate the number of horizontal lines and vertical lines in sequence
hlines = np.array([min(a, b) for a, b in zip(nodes[:-1], nodes[1:])])
# vlines = np.array([max(a, b) - 1 for a, b in zip(nodes[:-1], nodes[1:])])
vlines = nodes - 1

print(f"hlines: {hlines}, vlines: {vlines}")
# nodes = np.array([3, 3, 1]) ---> hlines: [3, 1], vlines: [2, 2]
# nodes = np.array([1, 3, 3]) ---> hlines: [1, 3], vlines: [2, 2]

hlines_no = list(range(sum(hlines)))
vlines_no = list(range(sum(hlines), sum(hlines) sum(vlines)))

print(f"hlines numbers: {hlines_no}, vlines numbers: {vlines_no}")
# nodes = np.array([3, 3, 1]) ---> hlines numbers: [0, 1, 2, 3], vlines numbers: [4, 5, 6, 7]
# nodes = np.array([1, 3, 3]) ---> hlines numbers: [0, 1, 2, 3], vlines numbers: [4, 5, 6, 7]

cells = []  # to store complete cell tuples
hidx = 0    # to keep track of horizontal lines index
vidx = 0    # to keep track of vertical lines index
previous_cells = 0
current_cells = 0

for LN, RN in zip(nodes[:-1], nodes[1:]):
    # if either the left or right side nodes is equal to 1, implies only 1 horizontal line exists
    # and the horizontal index is updated
    if LN == 1 or RN == 1:
        hidx  = 1
    else:
        # to handle just a blank vertical line
        if LN - RN == 1:
            vidx  = 1
        # iterate 'cell' number of times
        # number of cells are always 1 less than the minimum of left and right side nodes
        current_cells = min(LN, RN)-1
        if previous_cells != 0 and previous_cells > current_cells:
            vidx  = previous_cells - current_cells
        for C in range(current_cells):
            cell = (offset   hlines_no[hidx],
                    offset   vlines_no[vidx],
                    offset   hlines_no[hidx 1],
                    offset   vlines_no[vidx current_cells])
            hidx  = 1
            vidx  = 1
            cells.append(cell)
        # skip the last horizontal line in a column
        hidx  = 1
        previous_cells = min(LN, RN)-1

print(cells)
 

Результаты

 # nodes = np.array([3, 3, 1]) ---> [(17, 21, 18, 23), (18, 22, 19, 24)]

# nodes = np.array([1, 3, 3]) ---> [(18, 21, 19, 23), (19, 22, 20, 24)]

# nodes = np.array([5,4,4,2,2,1]) ---> [(17, 31, 18, 34), 
#                                       (18, 32, 19, 35), 
#                                       (19, 33, 20, 36), 
#                                       (21, 34, 22, 37), 
#                                       (22, 35, 23, 38), 
#                                       (23, 36, 24, 39), 
#                                       (25, 39, 26, 40), 
#                                       (27, 40, 28, 41)]

# nodes = np.array([1,3,4,4]) ---> [(18, 25, 19, 27), 
#                                   (19, 26, 20, 28), 
#                                   (21, 27, 22, 30), 
#                                   (22, 28, 23, 31), 
#                                   (23, 29, 24, 32)]
 

Редактировать: обновлен код для учета особых сценариев

Комментарии:

1. Уважаемый @sai, я ценю ваше решение. Извините за мой поздний отзыв. В то время меня не было перед моим рабочим столом, и я не мог это проверить. У меня всего две проблемы. Когда я добавляю еще одну строку в сценарий, приведенный ниже 21 , и nodes = np.array([4, 3, 1]) , у меня нет правильного результата. А также в реальности поверхности не создаются в столбце, они создают сетку. Например, в сценарии A вы можете думать, что в правой части существующих двух поверхностей также есть две другие: line_no=np.arange(17, 31) , sep=23 и nodes = np.array([4, 4, 2, 1]) . Спасибо за такую поддержку.

2. Можете ли вы добавить (картинки) другие сценарии крайнего случая, которые должен удовлетворять сценарий? Дополнительная информация помогла бы мне и всем остальным в SO получить полную картину и предоставить полное решение.

3. Дорогой @sai, я обновил свой пост, чтобы показать, чего я хочу. Заранее я ценю любой вклад.

4. Уважаемый @sai. Я действительно ценю вашу помощь. Проблема в том, что в других случаях я сталкиваюсь с ошибками. Например, допустим, в сценарии D я удаляю первую горизонтальную строку (число 17 ). Тогда у меня будет line_no = np.arange(18, 25) , sep = 24 nodes = np.array(np.array([3,4,4])) и все же у меня должны быть одинаковые поверхности, но я сталкиваюсь с ошибкой : IndexError: list index out of range

5. Попробуйте с vlines = nodes - 1