2016-09-23 3 views
1

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

Для этого я придумал две структуры.

  • GlobalPoint имеет отношение к большой разреженной нулевой матрице A. GlobalPoint - это матрица n x 4, которая содержит линейные индексы для доступа A.
  • LM имеет приращения, которые будут добавлены в большой разреженной матрицы

Например:

GlobalPoint 

1 730 10 739 
83 2 82 1 
83 812 92 821 
165 84 164 83 
165 894 174 903 

LM 

-0,531249999999875 0,531249999999875 0,531249999999875 -0,531249999999875 
-0,531250000000125 0,531250000000125 0,531250000000126 -0,531250000000126 
-0,343749999999875 0,343749999999875 0,343749999999875 -0,343749999999875 
-0,249999999999812 0,249999999999812 0,250000000000332 -0,250000000000332 
-0,249999999999909 0,249999999999909 0,249999999999909 -0,249999999999909 

Первоначально A содержит все нули. Для того, чтобы выполнить то, что я хотел, я сделал следующее сообщение на A:

A(GlobalPoint) = A(GlobalPoint) + LM; 

Линейный индекс a означает место (1,1) в разреженной матрице А. Так как индекс Лир 1 показывает в первая и вторая строки в первом столбце ((1,1) и (2,1), ожидаемый результат должен быть: (-0.531249) + (-0.53125) = -1.6025. Однако это обновление появляется только с -0.53124999. Я вполне уверен в ссылках в GlobalPoints Я уверен, что LM рассчитан правильно, но мне не удается увидеть, как это обновление работает.

Итак, как мне обновить несколько ссылок на s время? Это мешает моему обновлению?

+0

А в самом деле большая редко встречающаяся матрица нулей, но поскольку я использую ссылку 1 дважды, это может быть только -0,53125.Этот код должен добавить -0,531249999999875 + -0,531250000000126. –

+0

ах я вижу. Нет, к сожалению, это не так. Если у вас несколько значений доступа к одной координате, она будет помнить только последнее ** обновление ... поэтому последний индекс '1' отображается в позиции' (2,4) 'в вашей матрице, которая является' 0.53125'. Это обновление использует только обновление. На самом деле поведение указания нескольких значений для ссылки на одно местоположение не определено. Если вы хотите их накопить, вам нужно использовать что-то еще. – rayryeng

+0

Я напишу вам ответ. Оставайтесь на линии. – rayryeng

ответ

2

Что происходит в коде, так это то, что если вы укажете повторяющиеся линейные индексы в одном месте в матрице, вы ожидаете, что все значения, которые будут сопоставляться с одним и тем же индексом, будут суммироваться. К сожалению, это не так, как это работает в MATLAB. Он будет помнить только обновление, соответствующее в последний раз, оно видит линейный индекс.

Вот очень маленький пример. Предположим, у меня есть этот маленький 2 х 2 матрица:

>> A = [1 2; 3 4] 

A = 

    1  2 
    3  4 

Давайте также сказать, что у меня есть следующие 2 х 2 матрица линейных индексов B, а также матрицу C, что я хочу, чтобы аккумулировать с:

Если я правильно интерпретировать ваш вопрос, результат, который вы ожидаете, должно быть:

A = [1 + 10 + 20, 2; 
    3 + 30 + 40, 4] 

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

>> A(B) = A(B) + C 

A = 

    21  2 
    43  4 

Как вы можете видеть, в верхнем левом углу только обновляется с 20 + 1, как значение 20 совпадает с последним временем мы увидел индекс 1 для первой строки. Аналогично, нижний левый угол обновляется только с 40 + 3, так как 40 - это последний раз, когда мы видели индекс 2 для второй строки.

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

Что-то, как это должно работать:

[vals,~,ind] = unique(GlobalPoint); 
sums = accumarray(ind, LM(:)); 
A(vals) = A(vals) + sums; 

Приведенный выше код занимает немного фантазии, но это работает. Функция unique определяет все уникальные линейные индексы в матрице GlobalPoint и возвращает это как 1D-вектор, сохраненный в vals. Третий параметр ind перепараметрирует все значения в GlobalPoint, так что они меняются на индексы от 1 до нескольких уникальных значений в vals. Затем мы используем accumarray, где ind указывает , в котором корзина соответствует каждому соответствующему значению в LM. Результатом будет массив, в котором каждый элемент соответствует сумме всех значений, которые соответствуют одному линейному индексу. Последний шаг - взять этот массив сумм и обновить правильные позиции в A.


Вот краткий пример выполнения шагов, о которых я только что говорил. Выход первой строки кода данной ваши данные дает мне это:

>> vals.' 

ans = 

    1  2 10 82 83 84 92 164 165 174 730 739 812 821 894 903 

>> ind.' 

ans = 

    Columns 1 through 17 

    1  5  5  9  9 11  2 13  6 15  3  4  7  8 10 12  1 

    Columns 18 through 20 

    14  5 16 

vals содержит все уникальные значения в GlobalPoint и ind содержит идентификатор, который говорит вам, какое значение в GlobalPoint каждое значение карты для. Следовательно, индекс 1 сопоставляется с значением 1 в GlobalPoint, значение 3 сопоставляется с значением 10 в GlobalPoint и так далее. Обратите внимание, что это отсортировано, и всего 16 уникальных очков.

После того, как я бегу через accumarray, теперь я получаю это для моих сумм:

>> sums.' 

ans = 

    Columns 1 through 4 

        -1.0625   0.531250000000125   0.531249999999875   0.531250000000126 

    Columns 5 through 8 

     -1.12500000000033   0.249999999999812   0.343749999999875   0.250000000000332 

    Columns 9 through 12 

     -0.499999999999721   0.249999999999909   0.531249999999875  -0.531249999999875 

    Columns 13 through 16 

     0.343749999999875  -0.343749999999875   0.249999999999909  -0.249999999999909 

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

>> [vals sums] 

ans = 

         1     -1.0625 
         2   0.531250000000125 
         10   0.531249999999875 
         82   0.531250000000126 
         83   -1.12500000000033 
         84   0.249999999999812 
         92   0.343749999999875 
         164   0.250000000000332 
         165  -0.499999999999721 
         174   0.249999999999909 
         730   0.531249999999875 
         739  -0.531249999999875 
         812   0.343749999999875 
         821  -0.343749999999875 
         894   0.249999999999909 
         903  -0.249999999999909 

Взглянув линейный индекс-уже дает мне уверенность. Мы видим, что оба значения, отображаемые в индекс 1, суммируются должным образом. Например, если вы посмотрите на линейный индекс 83, мы видим, что есть три значения, которые совпадают с этой позицией: (2,1), (3,1) и (4,4). Значения для них: -0.53125, -0.34375 и -0.25. Накопление их дает примерно -1,125, и это то, что мы видим в результате. Если вы повторите вычисления для остальных значений, мы можем проверить, правильно ли вычислены суммы.

+1

Чувак, ты хороший. Я читаю объяснение, но я уверен, что вы поняли это правильно. Большое спасибо. Как только я заработаю, я дам вам знать. –

+0

@ArturCastiel hehe thanks :) Вы очень желанны. BTW, я обновил свой пост, чтобы предоставить некоторые примеры результатов. Я убежден, что они правы, но у меня нет фактической матрицы 'A', о которой вы говорите, поэтому я не могу проверить это для вас ... но суммы и соответствующие уникальные линейные индексы говорят мне, что я правильно. – rayryeng

+0

@ArturCastiel Добавлены новые результаты. Удачи! – rayryeng

Смежные вопросы