green_fr: (Default)
[personal profile] green_fr
Есть задача.
Предположим, у нас есть некий вектор X (для читабельности все картинки ниже), нам нужно просуммировать элементы вектора таким образом, чтобы получился новый вектор Sx. Делается это просто, надо умножить X на треугольную матрицу:
          

Если X — квадратная матрица, но с помощью той же треугольной матрицы мы суммируем содержимое каждой колонки.

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


Задача скорее программистская, чем математическая, то есть мне не обязательно получить красивую формулу, главное, чтобы MatLab её считал быстро. В настоящее время я вынужден использовать написанную мною функцию shift, которая преобразовывает матрицу NxN в матрицу 2N-1xN, сдвигая колонки таким образом, чтобы суммируемые элементы находились в одной строке (лишние элементы в углах новой матрицы заполняются нулями). Затем я суммирую строки и вызываю unshift, которая возвращает матрице квадратную форму, отбрасывая ненужные элементы по уголкам.

P.S. Как ни странно, тупой вариант с двумя вложенными циклами тормозит жутко. Мой вариант в shift/unshift работает на 2-3 порядка быстрее. Но матрицы всё равно большие. Да и вообще, код некрасивый.

Date: 2010-09-30 09:08 am (UTC)
From: [identity profile] catpad.livejournal.com
Не уверен, подходит ли это в данном случае, но есть такая штука - Dynamic programming (http://en.wikipedia.org/wiki/Dynamic_programming), посмотри, может быть, это то, что тебе нужно.

Date: 2010-09-30 09:24 am (UTC)
From: [identity profile] green-fr.livejournal.com
По Википедии это кажется просто «не пишите избыточный код». Или я чего-то не уловил? В каком направлении там смотреть-то?

Date: 2010-09-30 11:13 am (UTC)
From: [identity profile] catpad.livejournal.com
Насколько я помню из своей учёбы, там речь идёт о реальном увеличении скорости, а не только кода. Но больше не помню ничего.

Date: 2010-09-30 10:43 am (UTC)
From: [identity profile] birdwatcher.livejournal.com
Надо взять горизонтальный срез исходной матрицы, содержащий искомую диагональ (больше в ширину, чем высоту), и вертикальный срез этой матрицы, тоже содержащий искомую диагональ.Получится небольшая квадратная матрица, где на главной диагонали стоят искомые элементы. Ответом является след этой матрицы.

кгхм

Date: 2010-09-30 11:26 am (UTC)
From: [identity profile] birdwatcher.livejournal.com
sum(diag(X, k))

Date: 2010-09-30 12:08 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Кстати, вариант! Попробую.

Date: 2010-09-30 12:20 pm (UTC)
From: [identity profile] birdwatcher.livejournal.com
да не надо это все, посмотри - матлабовский diag берет второй аргумент, номер диагонали

Date: 2010-09-30 02:21 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Да, спасибо, всё сейчас перепишу :-)
Я, правда, и так там уже миллисекунды ловлю, но всё равно.

а так?

Date: 2010-09-30 04:19 pm (UTC)
From: [identity profile] beremich.livejournal.com
clear; M = magic(5)
n = length(M), for i = -(n-2):n, M0 = [zeros(size(M)); M]; sumdiag(i+n-1) = sum(M0(i+n:(2*n+1):end)); end; sumdiag

Date: 2010-10-01 07:23 am (UTC)
From: [identity profile] green-fr.livejournal.com
Здорово! Я соседнюю задачку так решил, приведением всего к плоской индексации. А про эту не подумал :-)

Там небольшое осложнение из-за того, что мне нужны не суммы, а обратные cumsum (то есть результат — не вектор 2N-1×1, а матрица того же размера NxN), но это решается.

Date: 2010-10-01 01:24 pm (UTC)
From: [identity profile] yuriyag.livejournal.com
Для розв'язання Матриці треба з'їсти червону пігулку!

Profile

green_fr: (Default)
green_fr

January 2026

S M T W T F S
    123
4 5 6 7 8 910
11121314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 10th, 2026 11:11 pm
Powered by Dreamwidth Studios