Если двумерный массив (матрица) — это таблица, а трехмерный — стопка таблиц (или ящик, в который они помещены), тогда 4D — это комната с ящиками, а 5D — здание с комнатами.

import numpy as np

a = np.array([[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [10, 9, 8, 7, 6]],
              [[0, 1, 3, 2, 4], [3, 6, 7, 8, 9], [5, 7, 3, 8, 1]]])
print('Размерность массива:', a.ndim)
tables, rows, cols = a.shape
print(f'{tables} таблицы {rows}x{cols}')
print(a)
Размерность массива: 3
2 таблицы 3x5
[[[ 1  2  3  4  5]
  [ 6  7  8  9 10]
  [10  9  8  7  6]]

 [[ 0  1  3  2  4]
  [ 3  6  7  8  9]
  [ 5  7  3  8  1]]]

О пространстве речи здесь не идет. Это скорее выглядит как упаковка мелких объектов в крупные, или, от обратного, описание строения объекта через его составные компоненты на n-ном уровне вложенности.

Тогда под "многомерностью" следует понимать возможность исследования свойств объекта на разных уровнях. Чем больше мерность, тем рассматриваются более фундаментальные составные компоненты. Мы не характеризуем само здание, вместо этого можем сделать вывод о его назначении и планировке из того, что находится в таблицах, и как они рассортированы по папкам, шкафам, помещениям. При этом самым главным здесь являются данные в таблицах.

Даже к одномерной массиву можно приложить понятие "многомерность", подразумевая под ней измерение разных свойств предмета. Множество измерений на одном уровне — это описание самого объекта, а не его частей. Так в структуре можно сохранить информацию о самом здании: адрес, цвет, количество этажей, офисов, таблиц и т.д. Правда для этого лучше подойдет не массив, а список или словарь, так как разные свойства скорее всего будут иметь неодинаковый тип данных.

Хотя каждый тип данных кодируется более простым, то есть числами. Таким образом, на низком уровне за каждым свойством стоит свой массив данных, что, опять же, можно рассматривать как своего рода многомерность.

Однако слово "многомерность" во многих случаях ассоциируется с пространством. При этом руки тянутся по привычке использовать координаты как данные, хранимые в ячейках массива и задающие положение интересующих нас объектов. Если взять одномерный массив, то это точки на отрезке. Если двумерный, они же на плоскости.

import numpy as np
import matplotlib.pyplot as plt

points = np.array([[1, 12], [3, 19], [5, 17],
                   [6, 22], [8, 18], [9, 24]])
plt.plot(points[:, 0], points[:, 1], 'o-')

plt.grid()
plt.show()

Но на трехмерном пространстве возникает недоумение. Под координаты точек все-равно удобнее использовать тот же двумерный массив:

points = np.array([[1, 12, 8], [13, 19, 6], [5, 17, 10],
                   [6, 22, 10], [8, 18, 3], [19, 24, 16]])
ax.scatter(points[:,0], points[:,1], points[:,2])

Это объяснимо, если учесть, что координаты xy и z — это описательные свойства самого объекта в этом мире, они на одном уровне. К ним можно добавить характеристики цвета, прозрачности, размера, скорости и др.

point_type = [('x', 'i2'), ('y', 'f2'), ('z', 'i1'),
              ('color', 'U10'), ('size', 'i2')]
a = np.array([(100, 0.8, 90, 'red', 300),
              (120, 0.3, 48, 'green', 500),
              (200, 0.5, 28, 'orange', 800),
              (140, 0.1, -50, 'black', 200),
              (180, 0.9, 98, 'blue', 400),
              (150, 0.5, 25, 'purple', 600)],
             dtype=point_type)

fig = plt.figure(layout='constrained')
ax = fig.add_subplot(projection='3d')

ax.scatter(a['x'], a['y'], a['z'], s=a['size'], c=a['color'])

Примечание. Выше одномерный структурированный массив NumPy (вложенные структуры не являются массивами), но нам важна наглядность. Он похож на двумерный, где каждый вложенный экземпляр описывается через ряд свойств.

Однако снова вернемся к стопке таблиц. У листа, на котором нарисована таблица, должна быть толщина. Стопка имеет объем. Более того, в таблицах хранятся данные, адреса которых определяются индексами ячеек в массиве. Адрес — это место, координаты. Тогда вот оно — трехмерное пространство, кодируемое 3D–матрицей.

Воксель представляет собой трехмерную точку, объемный аналог таковой на плоском растровом изображении, которое можно закодировать двумерным массивом. Каждый элемент вложенного массива будет представлять собой цвет/яркость точки. И в плоской картинке, и в объемной размерность массива напрямую обозначает размерность пространства. Оно поделено на равные части, а каждое значение в такой матрице характеризует состояние своей точки.

На фигуре ниже в правой системе координат (массив b) цвет кирпичей определяется числами, хранимыми в массиве. Исключением является число 0.

fig = plt.figure(figsize=(10, 5))

a = np.random.choice([0,1], size=(10,10,10), p=[0.8,0.2])
ax = fig.add_subplot(1, 2, 1, projection='3d')
ax.voxels(a, edgecolor='k', facecolors='#bbf', alpha=0.7)
ax.set_title(f'Ячеек: {a.size}, единиц: {np.count_nonzero(a)}')

b = np.array([[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10],
               [10, 9, 8, 7, 6], [5, 4, 3, 2, 1]],
              [[0, 1, 3, 2, 4], [3, 6, 7, 8, 9],
               [5, 7, 3, 8, 1], [1, 3, 5, 7, 2]]])
bx = fig.add_subplot(122, projection='3d')
bx.voxels(b, edgecolors='#666',
          facecolors=plt.cm.hsv(b/np.max(b)))
bx.set_xticks([0, 1, 2])
bx.set_xlabel('X'); bx.set_ylabel('Y'); bx.set_zlabel('Z')

Однако забудем о свойствах данных и обратим внимание на их количество, на размер воксельного массива. Он огромен, так как хранит информацию обо всем пространстве. Там, где мы видим пустоту, на самом деле что-то есть, соответствующая область памяти все-равно занята. Иначе пространство схлопнется. Даже если нам нужно всего несколько вокселей–материи, 3D–матрица содержит данные о состоянии всех ячеек.

То ли дело векторная графика, где в центр "вселенной" ставится сам объект и дается его абстрактное небуквальное описание через расстояния и формулы. В памяти хранятся только необходимые числа и команды, все остальное — следуемое из них, кем-то или чем-то вычисляемое в момент представления.

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

Если в привычной физике без относительности невозможно жить, то в пространственной матрице она не обязательна. Хоть и можно продолжать измерять расстояние между объектами относительно друг друга, но у каждого есть абсолютный, независимый от других, адрес. Если одному расстояние между А и Б кажется короче, чем другому, это только следствие их личных особенностей (положения, скорости), а истинное расстояние там константно по определению.

В матрице уже движение может оказаться производным. Как анимация, когда на самом деле никто никуда не двигается, просто перерисовывается картинка. Данные переносятся из одной ячейки в другую. Движение имитируется путем обмена значениями между вокселями.

Тогда время должно иметь абсолютные по длине такты для всей матрицы, и наше относительное восприятие его зависит от того, через сколько тактов матрица перерисовывает конкретно нас, то есть от нашей скорости и от скорости "перерисовки" наблюдаемого соседа. Время может оказаться таким же фундаментальным свойством матрицы как пространство.

Если хранится описание только состояний вокселей, то на базовом уровне нет никаких объектов. Чтобы заметить их, надо посмотреть на точки со стороны, абстрагироваться от каждой, увидеть участок как единое целое. Тогда объекты в матрице — тоже производное, как и движение.

Комментарии (0)