помощь трехдиагональной матрицы клена 13 - PullRequest
1 голос
/ 17 марта 2010

Я пытаюсь создать трехдиагональную матрицу 100 x 100, где 2 идут вниз по диагонали, а -1 - вокруг 2. Я могу сделать трехдиагональную матрицу с только 1 в трех диагоналях и добавить матрицу преформ, чтобы получить то, что я хочу, но я хочу знать, есть ли способ настроить три диагонали так, как вам нужно. В maplehelp нет ничего полезного.

Ответы [ 4 ]

3 голосов
/ 17 марта 2010

Функция Matrix в пакете LinearAlgebra может вызываться с параметром (init), который является функцией, которая может присваивать значение каждому элементу матрицы в зависимости от ее положения.
Это будет работать:

f := (i, j) -> if i = j then 2 elif abs(i - j) = 1 then -1 else 0; end if;
Matrix(100, f);
1 голос
/ 11 мая 2010

Ответы, включающие функцию инициализатора f, выполнят O (n ^ 2) работу для квадрата nxn Matrix. В идеале эта задача должна быть O (n), так как нужно заполнить чуть менее 3 * n записей.

Предположим также, что вам нужна результирующая матрица без какой-либо специальной (например, полосовой) функции хранения или индексирования (чтобы впоследствии вы могли произвольно записывать в любую ее часть). И предположим также, что вы не хотите обойти такую ​​проблему, обернув структуру группы Matrix другим универсальным вызовом Matrix (), который удвоит временную используемую память и создаст коллекционный мусор.

Вот два способа сделать это (не применяя f к каждой записи способом O (n ^ 2) или используя отдельный цикл do). Первый включает создание трех полос в качестве временных файлов (что является мусором, который нужно собрать, но, по крайней мере, не размером n ^ 2).

М: = Матрица (100, [[- 1 $ 99], [2 $ 100], [- 1 $ 99]], сканирование = диапазон [1,1]);

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

М: = Матрица (100):

ArrayTools: -fill (100,2, M, 0100 + 1)

ArrayTools: -fill (99, -1, M, 1,100 + 1);

ArrayTools: -fill (99, -1, M, 100,100 + 1);

Обратите внимание, что ArrayTools: -Fill - это скомпилированная внешняя подпрограмма, и поэтому в принципе она может быть быстрее, чем интерпретируемый метод языка Maple (правильный). Это было бы особенно быстро для Matrix M с аппаратным типом данных, таким как 'float [8]'.

Кстати, причина, по которой вышеприведенная процедура со стрелкой завершилась ошибкой «Недопустимая процедура со стрелкой», вероятно, связана с тем, что она была введена в режиме 2D Math. Парсер 2D Math Maple 13 не понимает синтаксис if ... then ... end как тело оператора стрелки. Альтернативный вариант (кроме записи f в качестве процедуры, как кто-то другой ответил) состоит в том, чтобы ввести f (неотредактированный) в режиме записи 1D Maple или отредактировать f, чтобы использовать форму оператора if. Возможно, операторная форма if здесь требует вложенного if для обработки elif. Например,

f := (i,j) -> `if`(i=j,2,`if`(abs(i-j)=1,-1,0));
Matrix(100,f);
1 голос
/ 29 апреля 2010

LinearAlgebra [BandMatrix] тоже работает (и будет ПУТЬ быстрее), особенно если вы используете storage = band [1]. Вы, вероятно, должны также использовать shape = симметричный.

0 голосов
/ 10 мая 2010

Предлагаемые решения Jmbr могут быть адаптированы для работы:

f := proc(i, j)
  if i = j then 2
  elif abs(i - j) = 1 then -1
  else 0
  end if
end proc;
Matrix(100, f);

Кроме того, я понимаю, что ваш комментарий говорит о том, что вам позже необходимо уничтожить природу матричной полосы, что мешает вам использовать BandMatrix - это правильно? Самое простое решение - это обернуть вызов BandMatrix в обычный вызов Matrix, который даст вам матрицу, которую вы можете изменить, как вам захочется:

 Matrix(LinearAlgebra:-BandMatrix([1,2,1], 1, 100)); 
...