сделать эффективную копию симметричной матрицы в c # - PullRequest
3 голосов
/ 27 января 2012

Я хочу сохранить в массиве симметричную матрицу

для матрицы, которой я занимался

    double[,] mat = new double[size,size];
    for (int i = 0; i < size; i++)
    {
      for (int j = 0; j <= i; j++)
           mat[i, j] = mat[j, i] = (n * other_matrix[i,j]);
    }

Если я хочу сохранить в массиве

double[] mat = new double[size*size];

вместо

 double[,] mat

Какой будет наиболее эффективный способ?

с использованием mat[i*n+j]?

Ответы [ 3 ]

6 голосов
/ 28 января 2012

Да.

Сохранять элементы по строкам, где i -я строка и j -й столбец хранятся в индексе k=i*NC+j с NC количеством столбцов. Это относится к несимметричной общей матрице.

Чтобы сохранить симметричную матрицу размера N, вам нужно всего лишь N*(N+1)/2 элементов в массиве. Можно предположить, что i<=j таков, что индексы массива идут так:

k(i,j) = i*N-i*(i+1)/2+j            i<=j  //above the diagonal
k(i,j) = j*N-j*(j+1)/2+i            i>j   //below the diagonal

с

i = 0 .. N-1
j = 0 .. N-1

Пример, когда N = 5, индексы массива идут следующим образом

| 0   1   2   3   4 |
|                   |
| 1   5   6   7   8 |
|                   |
| 2   6   9  10  11 |
|                   |
| 3   7  10  12  13 |
|                   |
| 4   8  11  13  14 |

Общее количество необходимых элементов: 5*(5+1)/2 = 15, поэтому индексы начинаются с 0..14. Check

i -я диагональ имеет индекс k(i,i) = i*(N+1)-i*(i+1)/2. Таким образом, третий ряд (i=2) имеет диагональный индекс k(2,2) = 2*(5+1)-2*(2+1)/2 = 9. Check

Последний элемент i -ой строки имеет индекс = k(i,N) = N*(i+1)-i*(i+1)/2-1. Таким образом, последний элемент 3-й строки - k(2,4) = 5*(2+1)-2*(2+1)/2-1 = 11. Check

Последняя часть, которая может вам понадобиться, - как перейти от индекса массива k к строке i и столбцу j. Снова при условии, что i<=j (выше диагонали) ответ будет

i(k) = (int)Math.Floor(N+0.5-Math.Sqrt(N*(N+1)-2*k+0.25))
j(k) = k + i*(i+1)/2-N*i

Чтобы проверить вышесказанное, я запустил это для N=5, k=0..14 и получил следующие результаты:

Table of indexes

Что правильно! Check

Чтобы сделать копию, просто используйте Array.Copy() на элементах, которые очень быстрые. Также для выполнения таких операций, как сложение и масштабирование, вам просто нужно работать с уменьшенными элементами в массиве, а не с полной матрицей N*N. Матричное умножение немного сложнее, но выполнимо. Может быть, вы можете задать другой вопрос для этого, если хотите.

2 голосов
/ 10 марта 2012

Относительно выбранного ответа, если только я не полный идиот, код неправильный:

Попробуйте:

i = 2, j = 1

therefore we use:

k(i,j) = j*N-j*(j-1)/2+i

to find the index k, solving:

k(i,j) = 1*5 - 1*(1-1)/2 + 2

k(i,j) = 5 - 0 + 2 = 7

Из матрицы в выбранном ответе мы видим, что(2,1) не 7, кажется 6. В действительности (так как это, кажется, 0-основание), 7 происходит в (3,1) или (1,3).Вторая формула для i> j кажется неточной, если я что-то упустил.

ОБНОВЛЕНИЕ:

Это сработает, если вы измените формулу i> j на:

k(i,j) = j*(N-1)-j*(j-1)/2+i
1 голос
/ 28 января 2012

Если n - размер квадратной матрицы, вам необходимо n * (n + 1) / 2 суммарных значения для симметричной матрицы. Это сумма 1 + 2 + 3 + ... (n - 2) + (n - 1) + n.

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

...