5D массив хеш-таблицы - PullRequest
1 голос
/ 28 мая 2009

В настоящее время у меня есть 5D массив в переменной с именем template, записанный в 1D массив с именем template1D, с хэш-таблицей из 3456 (8 * 12 * 3 * 4 * 3) записей. В Matlab доступ к многомерному массиву осуществлялся следующим образом:

template{idx_r, idx_l, idx_rho, idx_alpha, idx_beta}

Однако, так как у меня индексы идут от 0-7, 0-11, 0-2, 0-3 и 0-2 соответственно, я не совсем уверен, что было бы самым простым способом получить общее индекс из этих пяти индексов, чтобы правильно получить правильный сегмент в массиве шаблонов. Какой самый простой способ правильно создать такие хеш-функции?

Ответы [ 5 ]

7 голосов
/ 28 мая 2009

Не совсем точно, что вы пытаетесь сделать здесь, но вы рассматривали функции ind2sub и sub2ind? Они могут помочь. Возможно, вам придется беспокоиться о показателях 0 против 1, поскольку MATLAB основан на 1.

- Loren

3 голосов
/ 28 мая 2009

Если бы это был двумерный массив, упорядоченный как плоский массив, вы бы умножили первый индекс на размер первого измерения и добавили второй индекс. Таким же образом, с 5 измерениями вы бы сделали что-то вроде:

index = (((i1*l1 + i2)*l2 + i3)*l3 + i4)*l4 + i5;
2 голосов
/ 28 мая 2009

Несмотря на то, что вы, безусловно, можете самостоятельно вычислить линейный индекс (как указано Tal ), было бы чище и проще читать с помощью встроенной функции SUB2IND (как указано Лорен ). Для вашего примера вы бы использовали его следующим образом:

index = sub2ind([8 12 3 4 3], idx_r, idx_l, idx_rho, idx_alpha, idx_beta);

Если все ваши индексы основаны на 0, вам придется добавить 1 к каждому из них, прежде чем передавать их в SUB2IND.

EDIT:

Если вы хотите узнать, как самостоятельно вычислять линейные индексы в MATLAB, чтобы они соответствовали результатам SUB2IND, вот код, который вы будете использовать:

index = (((idx_beta*4 + idx_alpha)*3 + idx_rho)*12 + idx_l)*8 + idx_r + 1;

ПРИМЕЧАНИЕ , что индексы, которые необходимо использовать с этим уравнением, должны быть основаны на 0, а индексы, передаваемые в SUB2IND, должны быть основаны на 1. Чтобы обобщить это уравнение на произвольное число измерений N :

index = (...(idx(N)*sz(N-1) + idx(N-1))*sz(N-2) + ...)*sz(1) + idx(1) + 1;

или более кратко:

index = 1 + sum(idx.*cumsum([1 sz(1:(N-1))]));

где idx - это массив значений индекса на основе 0 для каждого измерения, а sz - это массив размеров каждого измерения.

2 голосов
/ 28 мая 2009

Рассматривали ли вы использовать строку для хеширования? Вы даже можете сделать это шестнадцатеричным числом,

5 символов

#Character 0 is in the range '0'...'7',
#Character 1 is in the range '0'...'B',
#Character 2 is in the range '0'...'2',
#Character 3 is in the range '0'...'3',
#Character 4 is in the range '0'...'2'

Часть красоты строки в виде шестнадцатеричного числа заключается в том, что она имеет простое int ... err ... длинное длинное представление без знака, если вам когда-либо понадобится преобразование.

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

Я не знаю, правильно ли я понял вопрос, поэтому скажу, что понял:

  • У вас есть массив заданного размера, который представляет многомерную матрицу.
  • Вы хотите преобразовать 5-мерный вектор в реальную позицию массива

Сначала я создал бы класс для его инкапсуляции, и я бы предоставил operator (), определенный с 5 аргументами (std :: size_t, unsigned int или около того). Этот оператор () должен сначала проверить диапазоны (возможно, выдать исключение и преобразовать все аргументы в конечную позицию.

Простейшим преобразованием будет:

size_t position( size_t idx_r, size_t idx_l, size_t idx_rho, size_t idx_alpha, size_t idx_beta )
{
   size_t pos = (((((((idx_r * dim_l) + idx_l) * dim_rho) + idx_rho) * dim_alpha) + idx_alpha) * dim_beta) + idx_beta;
   return pos;
}

Где dim_XXX представляет размер матрицы в измерении XXX.

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

Общий алгоритм конвертирует каждый индекс в одном измерении в следующий элемент измерения и добавляет смещение в этом измерении. Самый простой пример - система с двумя измерениями. Чтобы получить доступ к строке 3, столбцу 2 в массиве из 10 столбцов (при условии, что вы сохраняете по строкам, и для аргумента рассчитываете от 1 до) вы сначала рассчитаете начало третьей строки, то есть 3 * 10 элементов в строке. Затем вы добавляете смещение в строку 2 (столбец 2).

Если вы увеличите его до 3-мерного массива, сначала вам нужно будет найти искомую плоскость, умножив индекс плоскости на размер плоскости, а затем использовать предыдущий алгоритм:

size_t position( size_t x, size_t y, size_t z )
{
   size_t start_of_plane_z = z * dim_y * dim_x; // z * size_of_plane
   size_t start_of_row_y = y * dim_x; // y * size_of_row
   size_t offset_inside_row = x;

   return start_of_plane_z + start_of_row_y + offset_inside_row;
}

Теперь, применяя некоторую базовую алгебру, вы можете преобразовать уравнение в:

size_t pos = (((z * dim_y) + y) * dim_x) + x;

Это уменьшит количество умножений и будет легче определить для большего числа измерений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...