У меня есть этот пример кода, который создает диагональную матрицу полос

T = 6;
d1 = ones(T-2, 1);
d2 = 2*ones(T-1, 1);
d3 = 3*ones(T, 1);

f = sparse(diag(d1, -2) + diag(d2, -1) + diag(d3) + diag(d2, 1) + diag(d1, 2));

Но я хочу избежать создания полной матрицы TxT, поэтому я хочу использовать spdiags, например:

f2 = spdiags(d1, -2, T, T) + spdiags(d2, -1, T, T) + spdiags(d3, 0, T, T) + ...
    spdiags(d2, 1, T, T) + spdiags(d1, 2, T, T);

Matlab сообщает мне, что «индекс превышает размер матрицы», и проблема возникает из-за этих команд

spdiags(d2, 1, T, T)
spdiags(d3, 2, T, T)

Но эти команды работают нормально:

spdiags(d1, -2, T, T)
spdiags(d2, -1, T, T)

Что тут происходит? Итоговая матрица должна выглядеть примерно так:

f =
     3     2     1     0     0     0
     2     3     2     1     0     0
     1     2     3     2     1     0
     0     1     2     3     2     1
     0     0     1     2     3     2
     0     0     0     1     2     3

Также это образцы матриц, которые я использую только в качестве примеров.

Этот код тоже работает:

T = 6;
d1 = ones(T-2, 1);
d2 = 2*ones(T-1, 1);
d3 = 3*ones(T, 1);

f = sparse(diag(d1, -2) + diag(d2, -1) + diag(d3) + diag(d2, 1) + diag(d1, 2));

B = [[d1;0;0], [d2;0], d3, [0;d2], [0;0;d1]];
f2 = spdiags(B, -2:2, T, T);
1
Michael A 20 Авг 2014 в 03:58
Хороший улов. Я должен был просто привести пример с d1 по d5, поскольку технически диагонали не будут симметричными, и это привело к некоторым слишком конкретным примерам. длина является ключевым моментом здесь. Спасибо!
 – 
Michael A
20 Авг 2014 в 19:17

1 ответ

Лучший ответ

Документация не очень ясна. Похоже, вам нужно, чтобы ваш вектор d имел длину T, даже если некоторые значения будут проигнорированы (а именно, первые значения игнорируются для положительных диагоналей, а последние - для отрицательных диагоналей) . Но почему-то на самом деле Matlab жалуется только на положительные диагонали; для отрицательных диагоналей он принимает более короткие векторы.

Итак: используйте все d векторы длины T:

T = 6;
d1 = ones(T, 1);
d2 = 2*ones(T, 1);
d3 = 3*ones(T, 1);
f2 = spdiags(d1, -2, T, T) + spdiags(d2, -1, T, T) + spdiags(d3, 0, T, T) + ...
    spdiags(d2, 1, T, T) + spdiags(d1, 2, T, T);

Кстати, вы можете построить матрицу, содержащую все векторы d в виде столбцов (теперь, когда все они имеют одинаковую длину), и вызвать spdiags только один раз:

f2 = spdiags([d1 d2 d3 d2 d1], -2:2, T, T);
1
Luis Mendo 20 Авг 2014 в 04:37
О, ладно, в этом ... есть смысл, я думаю. так что Matlab просто обрезает последние несколько значений, если они находятся за пределами матрицы? это объясняет, почему мое редактирование, добавляющее нули к матрицам d *, работает нормально.
 – 
Michael A
20 Авг 2014 в 04:20
Он отсекает последнюю для отрицательных диагоналей или первую для положительных диагоналей. Также посмотрите мое изменение, чтобы позвонить spdiags только один раз
 – 
Luis Mendo
20 Авг 2014 в 04:27
Спасибо за помощь. как я уже сказал, это всего лишь несколько простых примеров матриц, которые я использовал в качестве примера. мои фактические матрицы немного отличаются (и не могут быть сделаны простым вызовом bsxfun).
 – 
Michael A
20 Авг 2014 в 04:29
Но вы все равно можете объединить все векторы в матрицу и вызвать spdiags с этой матрицей. Возможно, это быстрее, чем вызывать его несколько раз, каждый раз с вектором. Я отредактировал свой ответ, удалив bsxfun, так как он слишком специфичен для вашего примера
 – 
Luis Mendo
20 Авг 2014 в 04:32
Правильно, я должен объединять их после того, как они созданы, а не когда я их создаю (как в вашем редактировании, которое все еще слишком специфично). в моем фактическом коде они созданы с размерами, которые я использовал в своем вопросе (поэтому я не могу просто изменить его, чтобы создать их с d1 = ones(T, 1);, как это сделали вы). Это работает для моих простых примеров, но все еще слишком специфично, чтобы относиться к реальной проблеме (поэтому они являются примерами). Конкатенация, безусловно, является ключевым моментом.
 – 
Michael A
20 Авг 2014 в 19:13