Как создать трехдиагональную матрицу как 1D - PullRequest
0 голосов
/ 22 февраля 2019

Так что для моего приложения мне нужно было бы создать трехдиагональную матрицу.Это легко сделать с любым языком: вы перебираете все строки и столбцы, затем устанавливаете основные диагональные значения, субдиагональные значения и супердиагональные значения.Обычно это выполняется на 2d массиве.

Для моего приложения мне нужно создать 1d массив "трехугольника".Иначе сказать: возьмите 2d трехдиагональную матрицу, затем превратите ее в 1d.Я могу просто начать с 2d, а затем написать некоторые функции, которые преобразуют 2d массив в 1d массив.Это я могу сделать.Я хотел бы знать, можем ли мы перейти непосредственно к 1D "трехугольнику"?Например, скажем, двумерный массив имеет размер 10 * 10, тогда мой одномерный массив будет иметь длину 100 элементов, тогда мне нужно будет выяснить, какой индекс является основным, супер и субдиагональным.

Возможно ли это сделать?Пожалуйста, дайте мне знать и спасибо

Ответы [ 3 ]

0 голосов
/ 22 февраля 2019

Элементы на главной диагонали имеют индексы (i, i) и их n;над- и инфра-диагонали в (i, i-1) и (i, i + 1) и их n-1 (i начинается в 2 и заканчивается в n-1 соответственно).

Можно использовать три вектора и сохранить элементы по соответствующим индексам i в этих трех векторах.

Вы также можете упаковать все значения в один вектор длиной 3n (или 3n-2, если хотитесвободное место).Добавьте n или 2n к индексу, в зависимости от диагонали, к которой вы хотите обратиться.Для элемента (i, j) индекс диагонали определяется как j-i + 2.

0 голосов
/ 23 февраля 2019

Пожалуйста, примите во внимание также:

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

  • @ VladmirF, потому что сопоставление указателей может быть лучшим подходом (в зависимости от вашего варианта использования), чем копирование черезвесь массив до reshape, если все, что вам нужно, это временно внести изменения в индекс для удобства работы с данными.

Сказал, что давайте перейдем к моему ответу.

  • Заполнение трехдиагональной матрицы не является другой проблемой, чем построение любой матрицы.Я не думаю, что это действительно имеет значение здесь.Просто имейте в виду, что Fortran хранит массивы в мажорном порядке столбцов, индекс на основе 1.

  • Изменение формы ваших данных легко и очевидно, если хранилище непрерывно.Вы можете создать ассоциацию pointer или перенести ее в новую переменную с помощью reshape.

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

    program tridiagonal
      implicit none
      integer, parameter :: n = 4
      integer :: A(n, n), B(n**2), main(n), sub(n-1), sup(n-1)
    
      A(1,:) = [1, 4, 0, 0]
      A(2,:) = [3, 4, 1, 0]
      A(3,:) = [0, 2, 3, 4]
      A(4,:) = [0, 0, 1, 3]
                                ! Remember, colum major
      B = reshape(A, shape(B))  ! 1, 3, 0, 0, 4, 4, 2, 0, 0, 1, 3, 1, 0, 0, 4, 3
    
      main = B(  1:n**2:n+1)    ! 1, 4, 3, 3
      sub  = B(  2:n**2:n+1)    ! 3, 2, 1
      sup  = B(n+1:n**2:n+1)    ! 4, 1, 4
    end
    
0 голосов
/ 22 февраля 2019

Вы можете просто посмотреть на свой одномерный массив, используя указатель двумерного массива.Фортран:

  integer, target :: A(100)

  integer, pointer :: B(:,:)

  B(1:10,1:10) => A

  B = 0
  do i = 1, 10
    B(i,i) = 1
  end do

  print '(*(1x,g0))', A
end


> gfortran diag1d.f90 
> ./a.out 
 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1

В C ++ кастинг также прост.

...