Описание подпрограммы

Подпрограмма SVDDecomposition осуществляет SVD-разложение прямоугольной матрицы размером MxN. На выходе подпрограмма возвращает массив сингулярных значений, упорядоченных по убыванию, и, по требованию, матрицы U и V T, причем возможно как возвращение только левых и правых сингулярных векторов, так и полных матриц размером MxM и NxN (в зависимости от параметров UNeeded и VTNeeded). Обратите внимание, что в переменной VT алгоритм возвращает не матрицу V, а матрицу V T.

Более подробно параметры подпрограммы описаны в комментариях к ней.

(***********************************************************************

Ýòîò êîä ñãåíåðèðîâàí òðàíñëÿòîðîì AlgoPascal â ðàìêàõ ïðîåêòà ALGLIB

Óñëîâèÿ, íà êîòîðûõ ðàñïðîñòðàíÿåòñÿ ýòîò êîä, ìîæíî ïîëó÷èòü ïî àäðåñó

http://alglib.sources.ru/copyrules.php

***********************************************************************)

uses Math, Ap;

(*

Ýòè ïîäïðîãðàììû äîëæåí îïðåäåëèòü ïðîãðàììèñò:

procedure ToBidiagonal(var A: TReal2DArray;

M: Integer;

N: Integer;

var TauQ: TReal1DArray;

var TauP: TReal1DArray);

procedure UnpackQFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TAUQ: TReal1DArray;

QColumns: Integer;

var Q: TReal2DArray);

procedure MultiplyByQFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TauQ: TReal1DArray;

var Z: TReal2DArray;

ZRows: Integer;

ZColumns: Integer;

FromTheRight: Boolean;

DoTranspose: Boolean);

procedure UnpackPTFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TAUP: TReal1DArray;

PTRows: Integer;

var PT: TReal2DArray);

procedure MultiplyByPFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TauP: TReal1DArray;

var Z: TReal2DArray;

ZRows: Integer;

ZColumns: Integer;

FromTheRight: Boolean;

DoTranspose: Boolean);

procedure UnpackDiagonalsFromBidiagonal(const B: TReal2DArray;

M: Integer;

N: Integer;

var IsUpper: Boolean;

var D: TReal1DArray;

var E: TReal1DArray);

function BidiagonalSVDDecomposition(var D: TReal1DArray;

E: TReal1DArray;

N: Integer;

IsUpper: Boolean;

IsFractionalAccuracyRequired: Boolean;

var U: TReal2DArray;

NRU: Integer;

var C: TReal2DArray;

NCC: Integer;

var VT: TReal2DArray;

NCVT: Integer):Boolean;

procedure QRDecomposition(var A: TReal2DArray;

M: Integer;

N: Integer;

var Tau: TReal1DArray);

procedure UnpackQFromQR(const QR: TReal2DArray;

M: Integer;

N: Integer;

const Tau: TReal1DArray;

QColumns: Integer;

var Q: TReal2DArray);

procedure LQDecomposition(var A: TReal2DArray;

M: Integer;

N: Integer;

var Tau: TReal1DArray);

procedure UnpackQFromLQ(const LQ: TReal2DArray;

M: Integer;

N: Integer;

const Tau: TReal1DArray;

QRows: Integer;

var Q: TReal2DArray);

procedure CopyAndTranspose(const A: TReal2DArray;

IS1: Integer;

IS2: Integer;

JS1: Integer;

JS2: Integer;

var B: TReal2DArray;

ID1: Integer;

ID2: Integer;

JD1: Integer;

JD2: Integer);

procedure InplaceTranspose(var A: TReal2DArray;

I1: Integer;

I2: Integer;

J1: Integer;

J2: Integer;

var WORK: TReal1DArray);

procedure MatrixMatrixMultiply(const A: TReal2DArray;

AI1: Integer;

AI2: Integer;

AJ1: Integer;

AJ2: Integer;

TransA: Boolean;

const B: TReal2DArray;

BI1: Integer;

BI2: Integer;

BJ1: Integer;

BJ2: Integer;

TransB: Boolean;

Alpha: Double;

var C: TReal2DArray;

CI1: Integer;

CI2: Integer;

CJ1: Integer;

CJ2: Integer;

Beta: Double;

var WORK: TReal1DArray);

procedure CopyMatrix(const A: TReal2DArray;

IS1: Integer;

IS2: Integer;

JS1: Integer;

JS2: Integer;

var B: TReal2DArray;

ID1: Integer;

ID2: Integer;

JD1: Integer;

JD2: Integer);

*)

function SVDDecomposition(A: TReal2DArray;

M: Integer;

N: Integer;

UNeeded: Integer;

VTNeeded: Integer;

AdditionalMemory: Integer;

var W: TReal1DArray;

var U: TReal2DArray;

var VT: TReal2DArray):Boolean;forward;

(*************************************************************************

Ñèíãóëÿðíîå ðàçëîæåíèå ïðÿìîóãîëüíîé ìàòðèöû.

Àëãîðèòì âû÷èñëÿåò ñèíãóëÿðíîå ðàçëîæåíèå ìàòðèöû ðàçìåðîì MxN:

A = U * S * V^T

Àëãîðèòì íàõîäèò ñèíãóëÿðíûå çíà÷åíèÿ è, îïöèîíàëüíî, ìàòðèöû U è V^T.

Ïðè ýòîì âîçìîæíî êàê íàõîæäåíèå ïåðâûõ min(M,N) ñòîëáöîâ ìàòðèöû U è

ñòðîê ìàòðèöû V^T (ñèíãóëÿðíûõ âåêòîðîâ), òàê è ïîëíûõ ìàòðèö U è V^T

(ðàçìåðîì MxM è NxN).

Îáðàòèòå âíèìàíèå, ÷òî ïîäïðîãðàììà âîçâðàùàåò ìàòðèöó V^T, à íå V.

Âõîäíûå ïàðàìåòðû:

A - ðàçëàãàåìàÿ ìàòðèöà.

Ìàññèâ ñ íóìåðàöèåé ýëåìåíòîâ [1..M, 1..N]

M - ÷èñëî ñòðîê â ìàòðèöå A

N - ÷èñëî ñòîëáöîâ â ìàòðèöå A

UNeeded - 0, 1 èëè 2. Ïîäðîáíåå ñì. îïèñàíèå ïàðàìåòðà U

VTNeeded - 0, 1 èëè 2. Ïîäðîáíåå ñì. îïèñàíèå ïàðàìåòðà VT

AdditionalMemory-

åñëè ïàðàìåòð:

* ðàâåí 0, òî àëãîðèòì íå èñïîëüçóåò äîïîëíèòåëüíóþ

ïàìÿòü (ìåíüøå òðåáîâàíèÿ ê ðåñóðñàì, íèæå ñêîðîñòü).

* ðàâåí 1, òî àëãîðèòì ìîæåò èñïîëüçîâàòü äîïîëíèòåëüíóþ

ïàìÿòü â ðàçìåðå min(M,N)*min(M,N) âåùåñòâåííûõ ÷èñåë.

 ðÿäå ñëó÷àåâ óâåëè÷èâàåò ñêîðîñòü àëãîðèòìà.

* ðàâåí 2, òî àëãîðèòì ìîæåò èñïîëüçîâàòü äîïîëíèòåëüíóþ

ïàìÿòü â ðàçìåðå M*min(M,N) âåùåñòâåííûõ ÷èñåë.  ðÿäå

ñëó÷àåâ ýòî ïîçâîëÿåò äîáèâàòüñÿ ìàêñèìàëüíîé ñêîðîñòè.

Ðåêîìåíäóåìîå çíà÷åíèå ïàðàìåòðà: 2.

Âûõîäíûå ïàðàìåòðû:

W - ñîäåðæèò ñèíãóëÿðíûå çíà÷åíèÿ, óïîðÿäî÷åííûå ïî óáûâàíèþ.

U - åñëè UNeeded=0, íå èçìåíÿåòñÿ. Ëåâûå ñèíãóëÿðíûå âåêòîðû

íå âû÷èñëÿþòñÿ.

åñëè UNeeded=1, ñîäåðæèò ëåâûå ñèíãóëÿðíûå âåêòîðû (ïåðâûå

min(M,N) ñòîëáöîâ ìàòðèöû U). Ìàññèâ ñ íóìåðàöèåé ýëåìåíòîâ

[1..M, 1..Min(M,N)].

åñëè UNeeded=2, ñîäåðæèò ïîëíóþ ìàòðèöó U. Ìàññèâ ñ íóìåðà-

öèåé ýëåìåíòîâ [1..M, 1..M].

VT - åñëè VTNeeded=0, íå èçìåíÿåòñÿ. Ïðàâûå ñèíãóëÿðíûå âåêòîðû

íå âû÷èñëÿþòñÿ.

åñëè VTNeeded=1, ñîäåðæèò ïðàâûå ñèíãóëÿðíûå âåêòîðû

(ïåðâûå min(M,N) ñòðîê ìàòðèöû V^T). Ìàññèâ ñ íóìåðàöèåé

ýëåìåíòîâ [1..min(M,N), 1..N].

åñëè VTNeeded=2, ñîäåðæèò ïîëíóþ ìàòðèöó V^T. Ìàññèâ ñ

íóìåðàöèåé ýëåìåíòîâ [1..N, 1..N].

-- ALGLIB --

Copyright 2005 by Bochkanov Sergey

*************************************************************************)

function SVDDecomposition(A: TReal2DArray;

M: Integer;

N: Integer;

UNeeded: Integer;

VTNeeded: Integer;

AdditionalMemory: Integer;

var W: TReal1DArray;

var U: TReal2DArray;

var VT: TReal2DArray):Boolean;

var

TauQ: TReal1DArray;

TauP: TReal1DArray;

Tau: TReal1DArray;

E: TReal1DArray;

WORK: TReal1DArray;

T2: TReal2DArray;

IsUpper: Boolean;

MinMN: Integer;

NCU: Integer;

NRVT: Integer;

NRU: Integer;

NCVT: Integer;

I: Integer;

J: Integer;

IM1: Integer;

SM: Double;

begin

A:= DynamicArrayCopy(A);

Result:= True;

if (M=0) or (N=0) then

begin

Exit;

end;

Assert((UNeeded>=0) and (UNeeded<=2), 'SVDDecomposition: wrong parameters!');

Assert((VTNeeded>=0) and (VTNeeded<=2), 'SVDDecomposition: wrong parameters!');

Assert((AdditionalMemory>=0) and (AdditionalMemory<=2), 'SVDDecomposition: wrong parameters!');

//

// initialize

//

MinMN:= Min(M, N);

SetLength(W, MinMN+1);

NCU:= 0;

NRU:= 0;

if UNeeded=1 then

begin

NRU:= M;

NCU:= MinMN;

SetLength(U, NRU+1, NCU+1);

end;

if UNeeded=2 then

begin

NRU:= M;

NCU:= M;

SetLength(U, NRU+1, NCU+1);

end;

NRVT:= 0;

NCVT:= 0;

if VTNeeded=1 then

begin

NRVT:= MinMN;

NCVT:= N;

SetLength(VT, NRVT+1, NCVT+1);

end;

if VTNeeded=2 then

begin

NRVT:= N;

NCVT:= N;

SetLength(VT, NRVT+1, NCVT+1);

end;

//

// M much larger than N

// Use bidiagonal reduction with QR-decomposition

//

if M>1.6*N then

begin

if UNeeded=0 then

begin

//

// No left singular vectors to be computed

//

QRDecomposition(A, M, N, Tau);

I:=2;

while I<=N do

begin

J:=1;

while J<=I-1 do

begin

A[I,J]:= 0;

Inc(J);

end;

Inc(I);

end;

ToBidiagonal(A, N, N, TauQ, TauP);

UnpackPTFromBidiagonal(A, N, N, TauP, NRVT, VT);

UnpackDiagonalsFromBidiagonal(A, N, N, IsUpper, W, E);

Result:= BidiagonalSVDDecomposition(W, E, N, IsUpper, False, U, 0, A, 0, VT, NCVT);

Exit;

end

else

begin

//

// Left singular vectors (may be full matrix U) to be computed

//

QRDecomposition(A, M, N, Tau);

UnpackQFromQR(A, M, N, Tau, NCU, U);

I:=2;

while I<=N do

begin

J:=1;

while J<=I-1 do

begin

A[I,J]:= 0;

Inc(J);

end;

Inc(I);

end;

ToBidiagonal(A, N, N, TauQ, TauP);

UnpackPTFromBidiagonal(A, N, N, TauP, NRVT, VT);

UnpackDiagonalsFromBidiagonal(A, N, N, IsUpper, W, E);

if AdditionalMemory<1 then

begin

//

// No additional memory can be used

//

MultiplyByQFromBidiagonal(A, N, N, TauQ, U, M, N, True, False);

Result:= BidiagonalSVDDecomposition(W, E, N, IsUpper, False, U, M, A, 0, VT, NCVT);

end

else

begin

//

// Large U. Transforming intermediate matrix T2

//

SetLength(WORK, Max(M, N)+1);

UnpackQFromBidiagonal(A, N, N, TauQ, N, T2);

CopyMatrix(U, 1, M, 1, N, A, 1, M, 1, N);

InplaceTranspose(T2, 1, N, 1, N, WORK);

Result:= BidiagonalSVDDecomposition(W, E, N, IsUpper, False, U, 0, T2, N, VT, NCVT);

MatrixMatrixMultiply(A, 1, M, 1, N, False, T2, 1, N, 1, N, True, 1.0, U, 1, M, 1, N, 0.0, WORK);

end;

Exit;

end;

end;

//

// N much larger than M

// Use bidiagonal reduction with LQ-decomposition

//

if N>1.6*M then

begin

if VTNeeded=0 then

begin

//

// No right singular vectors to be computed

//

LQDecomposition(A, M, N, Tau);

I:=1;

while I<=M-1 do

begin

J:=I+1;

while J<=M do

begin

A[I,J]:= 0;

Inc(J);

end;

Inc(I);

end;

ToBidiagonal(A, M, M, TauQ, TauP);

UnpackQFromBidiagonal(A, M, M, TauQ, NCU, U);

UnpackDiagonalsFromBidiagonal(A, M, M, IsUpper, W, E);

SetLength(WORK, M+1);

InplaceTranspose(U, 1, NRU, 1, NCU, WORK);

Result:= BidiagonalSVDDecomposition(W, E, M, IsUpper, False, A, 0, U, NRU, VT, 0);

InplaceTranspose(U, 1, NRU, 1, NCU, WORK);

Exit;

end

else

begin

//

// Right singular vectors (may be full matrix VT) to be computed

//

LQDecomposition(A, M, N, Tau);

UnpackQFromLQ(A, M, N, Tau, NRVT, VT);

I:=1;

while I<=M-1 do

begin

J:=I+1;

while J<=M do

begin

A[I,J]:= 0;

Inc(J);

end;

Inc(I);

end;

ToBidiagonal(A, M, M, TauQ, TauP);

UnpackQFromBidiagonal(A, M, M, TauQ, NCU, U);

UnpackDiagonalsFromBidiagonal(A, M, M, IsUpper, W, E);

SetLength(WORK, Max(M, N)+1);

InplaceTranspose(U, 1, NRU, 1, NCU, WORK);

if AdditionalMemory<1 then

begin

//

// No additional memory available

//

MultiplyByPFromBidiagonal(A, M, M, TauP, VT, M, N, False, True);

Result:= BidiagonalSVDDecomposition(W, E, M, IsUpper, False, A, 0, U, NRU, VT, N);

end

else

begin

//

// Large VT. Transforming intermediate matrix T2

//

UnpackPTFromBidiagonal(A, M, M, TauP, M, T2);

Result:= BidiagonalSVDDecomposition(W, E, M, IsUpper, False, A, 0, U, NRU, T2, M);

CopyMatrix(VT, 1, M, 1, N, A, 1, M, 1, N);

MatrixMatrixMultiply(T2, 1, M, 1, M, False, A, 1, M, 1, N, False, 1.0, VT, 1, M, 1, N, 0.0, WORK);

end;

InplaceTranspose(U, 1, NRU, 1, NCU, WORK);

Exit;

end;

end;

//

// M<=N

// We can use inplace transposition of U to get rid of columnwise operations

//

if M<=N then

begin

ToBidiagonal(A, M, N, TauQ, TauP);

UnpackQFromBidiagonal(A, M, N, TauQ, NCU, U);

UnpackPTFromBidiagonal(A, M, N, TauP, NRVT, VT);

UnpackDiagonalsFromBidiagonal(A, M, N, IsUpper, W, E);

SetLength(WORK, M+1);

InplaceTranspose(U, 1, NRU, 1, NCU, WORK);

Result:= BidiagonalSVDDecomposition(W, E, MinMN, IsUpper, False, A, 0, U, NRU, VT, NCVT);

InplaceTranspose(U, 1, NRU, 1, NCU, WORK);

Exit;

end;

//

// Simple bidiagonal reduction

//

ToBidiagonal(A, M, N, TauQ, TauP);

UnpackQFromBidiagonal(A, M, N, TauQ, NCU, U);

UnpackPTFromBidiagonal(A, M, N, TauP, NRVT, VT);

UnpackDiagonalsFromBidiagonal(A, M, N, IsUpper, W, E);

if (AdditionalMemory<2) or (UNeeded=0) then

begin

//

// We cant use additional memory or there is no need in such operations

//

Result:= BidiagonalSVDDecomposition(W, E, MinMN, IsUpper, False, U, NRU, A, 0, VT, NCVT);

end

else

begin

//

// We can use additional memory

//

SetLength(T2, MinMN+1, M+1);

CopyAndTranspose(U, 1, M, 1, MinMN, T2, 1, MinMN, 1, M);

Result:= BidiagonalSVDDecomposition(W, E, MinMN, IsUpper, False, U, 0, T2, M, VT, NCVT);

CopyAndTranspose(T2, 1, MinMN, 1, M, U, 1, M, 1, MinMN);

end;

end;

Приведение прямоугольной матрицы к двухдиагональной форме

(***********************************************************************

Ýòîò êîä ñãåíåðèðîâàí òðàíñëÿòîðîì AlgoPascal â ðàìêàõ ïðîåêòà ALGLIB

Óñëîâèÿ, íà êîòîðûõ ðàñïðîñòðàíÿåòñÿ ýòîò êîä, ìîæíî ïîëó÷èòü ïî àäðåñó

http://alglib.sources.ru/copyrules.php

***********************************************************************)

uses Math, Ap;

(*

Ýòè ïîäïðîãðàììû äîëæåí îïðåäåëèòü ïðîãðàììèñò:

procedure GenerateReflection(var X: TReal1DArray;

N: Integer;

var Tau: Double);

procedure ApplyReflectionFromTheLeft(var C: TReal2DArray;

Tau: Double;

const V: TReal1DArray;

M1: Integer;

M2: Integer;

N1: Integer;

N2: Integer;

var WORK: TReal1DArray);

procedure ApplyReflectionFromTheRight(var C: TReal2DArray;

Tau: Double;

const V: TReal1DArray;

M1: Integer;

M2: Integer;

N1: Integer;

N2: Integer;

var WORK: TReal1DArray);

*)

procedure ToBidiagonal(var A: TReal2DArray;

M: Integer;

N: Integer;

var TauQ: TReal1DArray;

var TauP: TReal1DArray);forward;

procedure UnpackQFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TauQ: TReal1DArray;

QColumns: Integer;

var Q: TReal2DArray);forward;

procedure MultiplyByQFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TauQ: TReal1DArray;

var Z: TReal2DArray;

ZRows: Integer;

ZColumns: Integer;

FromTheRight: Boolean;

DoTranspose: Boolean);forward;

procedure UnpackPTFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TauP: TReal1DArray;

PTRows: Integer;

var PT: TReal2DArray);forward;

procedure MultiplyByPFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TauP: TReal1DArray;

var Z: TReal2DArray;

ZRows: Integer;

ZColumns: Integer;

FromTheRight: Boolean;

DoTranspose: Boolean);forward;

procedure UnpackDiagonalsFromBidiagonal(const B: TReal2DArray;

M: Integer;

N: Integer;

var IsUpper: Boolean;

var D: TReal1DArray;

var E: TReal1DArray);forward;

(*************************************************************************

Ïðèâåäåíèå ïðÿìîóãîëüíîé ìàòðèöû ê äâóõäèàãîíàëüíîìó âèäó

Àëãîðèòì ïðèâîäèò ïðÿìîóãîëüíóþ ìàòðèöó A ê äâóõäèàãîíàëüíîìó âèäó

îðòîãîíàëüíûìè ïðåîáðàçîâàíèÿìè P è Q, òàêèìè, ÷òî A = Q*B*P'

Âõîäíûå ïàðàìåòðû:

A - èñõîäíàÿ ìàòðèöà A. Ìàññèâ ñ íóìåðàöèåé ýëåìåíòîâ [1..M, 1..N]

M - ÷èñëî ñòðîê â ìàòðèöå

N - ÷èñëî ñòîëáöîâ â ìàòðèöå

Âûõîäíûå ïàðàìåòðû:

A - ìàòðèöû Q, B, P â óïàêîâàííîé ôîðìå (ñì. íèæå).

TauQ- ñêàëÿðíûå ìíîæèòåëè, ó÷àñòâóþùèå â ôîðìèðîâàíèè ìàòðèöû Q

TauP- ñêàëÿðíûå ìíîæèòåëè, ó÷àñòâóþùèå â ôîðìèðîâàíèè ìàòðèöû Q

 ðåçóëüòàòå ðàáîòû àëãîðèòìà ãëàâíàÿ äèàãîíàëü ìàòðèöû A è îäíà èç ïîáî÷íûõ

çàìåùàþòñÿ áèäèàãîíàëüíîé ìàòðèöåé B, à â îñòàëüíûõ ýëåìåíòàõ õðàíÿòñÿ

ýëåìåíòàðíûå îòðàæåíèÿ, ôîðìèðóþùèå ìàòðèöû Q è P ðàçìåðîì MxM è NxN

ñîîòâåòñòâåííî.

Åñëè M>=N, òî ìàòðèöà B - âåðõíÿÿ äâóõäèàãîíàëüíàÿ ðàçìåðîì MxN è õðàíèòñÿ

â ñîîòâåòñòâóþùèõ ýëåìåíòàõ ìàòðèöû A. Ìàòðèöà Q ïðåäñòàâëÿåòñÿ â âèäå

ïðîèçâåäåíèÿ ýëåìåíòàðíûõ îòðàæåíèé Q = H(1)*H(2)*...*H(n), ãäå H(i) =

= 1 - tau*v*v'. Çäåñü tau - ñêàëÿðíàÿ âåëè÷èíà, õðàíÿùàÿ â TauQ[i], à

âåêòîð v èìååò ñëåäóþùóþ ñòðóêòóðó: v(1:i-1)=0, v(i)=1, v(i+1:m) õðàíèòñÿ

â ýëåìåíòàõ A(i+1:m,i). Ìàòðèöà P èìååò âèä P = G(1)*G(2)*...*G(n-1), ãäå

G(i) = 1 - tau*u*u'. Tau õðàíèòñÿ â TauP[i], u(1:i)=0, u(i+1)=1, u(i+2:n)

õðàíèòñÿ â ýëåìåíòàõ A(i,i+2:n).

Åñëè M<N, òî ìàòðèöà B - íèæíÿÿ äâóõäèàãîíàëüíàÿ ðàçìåðîì MxN, è õðàíèòñÿ

â ñîîòâåòñòâóþùèõ ýëåìåíòàõ ìàòðèöû A. Q = H(1)*H(2)*...*H(m-1), ãäå

H(i) = 1 - tau*v*v', tau õðàíèòñÿ â TauQ, v(1:i)=0, v(i+1)=1, v(i+2:m)

õðàíèòñÿ â A(i+2:m,i). P = G(1)*G(2)*...*G(m), G(i) = 1 - tau*u*u', tau

õðàíèòñÿ â TauP, u(1:i-1)=0, u(i)=1, u(i+1:n) õðàíèòñÿ â A(i,i+1:n).

ÏÐÈÌÅÐ:

m=6, n=5 (m > n): m=5, n=6 (m < n):

(d e u1 u1 u1) (d u1 u1 u1 u1 u1)

(v1 d e u2 u2) (e d u2 u2 u2 u2)

(v1 v2 d e u3) (v1 e d u3 u3 u3)

(v1 v2 v3 d e) (v1 v2 e d u4 u4)

(v1 v2 v3 v4 d) (v1 v2 v3 e d u5)

(v1 v2 v3 v4 v5)

çäåñü vi è ui îáîçíà÷àåò âåêòîðû, ôîðìèðóþùèå H(i) è G(i), à d è e -

äèàãîíàëüíûå è âíåäèàãîíàëüíûå ýëåìåíòû ìàòðèöû B.

*************************************************************************)

procedure ToBidiagonal(var A: TReal2DArray;

M: Integer;

N: Integer;

var TauQ: TReal1DArray;

var TauP: TReal1DArray);

var

WORK: TReal1DArray;

T: TReal1DArray;

MinMN: Integer;

MaxMN: Integer;

I: Integer;

LTau: Double;

MMIP1: Integer;

NMI: Integer;

IP1: Integer;

NMIP1: Integer;

MMI: Integer;

i_: Integer;

i1_: Integer;

begin

MinMN:= Min(M, N);

MaxMN:= Max(M, N);

SetLength(Work, MaxMN+1);

SetLength(T, MaxMN+1);

SetLength(TauP, MinMN+1);

SetLength(TauQ, MinMN+1);

if M>=N then

begin

//

// Reduce to upper bidiagonal form

//

I:=1;

while I<=N do

begin

//

// Generate elementary reflector H(i) to annihilate A(i+1:m,i)

//

MMIP1:= M-I+1;

i1_:= (I) - (1);

for i_:= 1 to MMIP1 do

begin

T[i_]:= A[i_+i1_,I];

end;

GenerateReflection(T, MMIP1, LTau);

TauQ[I]:= LTau;

i1_:= (1) - (I);

for i_:= I to M do

begin

A[i_,I]:= T[i_+i1_];

end;

T[1]:= 1;

//

// Apply H(i) to A(i:m,i+1:n) from the left

//

ApplyReflectionFromTheLeft(A, LTau, T, I, M, I+1, N, WORK);

if I<N then

begin

//

// Generate elementary reflector G(i) to annihilate

// A(i,i+2:n)

//

NMI:= N-I;

IP1:= I+1;

i1_:= (IP1) - (1);

for i_:= 1 to NMI do

begin

T[i_]:= A[I,i_+i1_];

end;

GenerateReflection(T, NMI, LTau);

TauP[I]:= LTau;

i1_:= (1) - (IP1);

for i_:= IP1 to N do

begin

A[I,i_]:= T[i_+i1_];

end;

T[1]:= 1;

//

// Apply G(i) to A(i+1:m,i+1:n) from the right

//

ApplyReflectionFromTheRight(A, LTau, T, I+1, M, I+1, N, WORK);

end

else

begin

TAUP[I]:= 0;

end;

Inc(I);

end;

end

else

begin

//

// Reduce to lower bidiagonal form

//

I:=1;

while I<=M do

begin

//

// Generate elementary reflector G(i) to annihilate A(i,i+1:n)

//

NMIP1:= N-I+1;

i1_:= (I) - (1);

for i_:= 1 to NMIP1 do

begin

T[i_]:= A[I,i_+i1_];

end;

GenerateReflection(T, NMIP1, LTau);

TauP[I]:= LTau;

i1_:= (1) - (I);

for i_:= I to N do

begin

A[I,i_]:= T[i_+i1_];

end;

T[1]:= 1;

//

// Apply G(i) to A(i+1:m,i:n) from the right

//

ApplyReflectionFromTheRight(A, LTau, T, I+1, M, I, N, WORK);

if I<M then

begin

//

// Generate elementary reflector H(i) to annihilate

// A(i+2:m,i)

//

MMI:= M-I;

IP1:= I+1;

i1_:= (IP1) - (1);

for i_:= 1 to MMI do

begin

T[i_]:= A[i_+i1_,I];

end;

GenerateReflection(T, MMI, LTau);

TauQ[I]:= LTau;

i1_:= (1) - (IP1);

for i_:= IP1 to M do

begin

A[i_,I]:= T[i_+i1_];

end;

T[1]:= 1;

//

// Apply H(i) to A(i+1:m,i+1:n) from the left

//

ApplyReflectionFromTheLeft(A, LTau, T, I+1, M, I+1, N, WORK);

end

else

begin

TAUQ[I]:= 0;

end;

Inc(I);

end;

end;

end;

(*************************************************************************

×àñòè÷íàÿ "ðàñïàêîâêà" ìàòðèöû Q, ïðèâîäÿùåé ìàòðèöó A ê äâóõäèàãîíàëüíîé

ôîðìå.

Âõîäíûå ïàðàìåòðû:

QP - ìàòðèöû Q è P â óïàêîâàííîé ôîðìå.

Ðåçóëüòàò ðàáîòû ïîäïðîãðàììû ToBidiagonal.

M - ÷èñëî ñòðîê â ìàòðèöå A

N - ÷èñëî ñòîëáöîâ â ìàòðèöå A

TAUQ - ñêàëÿðíûå ìíîæèòåëè, ôîðìèðóþùèå ìàòðèöó Q.

Ðåçóëüòàò ðàáîòû ïîäïðîãðàììû ToBidiagonal.

QColumns- òðåáóåìîå ÷èñëî ñòîëáöîâ ìàòðèöû Q. M >= QColumns >= 0

Âûõîäíûå ïàðàìåòðû:

Q - QColumns ïåðâûõ ñòîëáöîâ ìàòðèöû Q.

Ìàññèâ ñ íóìåðàöèåé ýëåìåíòîâ [1..M, 1..QColumns]

Åñëè QColumns=0, òî ìàññèâ íå èçìåíÿåòñÿ.

-- ALGLIB --

Copyright 2005 by Bochkanov Sergey

*************************************************************************)

procedure UnpackQFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TauQ: TReal1DArray;

QColumns: Integer;

var Q: TReal2DArray);

var

I: Integer;

J: Integer;

IP1: Integer;

V: TReal1DArray;

WORK: TReal1DArray;

VM: Integer;

i_: Integer;

i1_: Integer;

begin

Assert(QColumns<=M, 'UnpackQFromBidiagonal: QColumns>M!');

if (M=0) or (N=0) or (QColumns=0) then

begin

Exit;

end;

//

// init

//

SetLength(Q, M+1, QColumns+1);

SetLength(V, M+1);

SetLength(WORK, QColumns+1);

//

// prepare Q

//

I:=1;

while I<=M do

begin

J:=1;

while J<=QColumns do

begin

if I=J then

begin

Q[I,J]:= 1;

end

else

begin

Q[I,J]:= 0;

end;

Inc(J);

end;

Inc(I);

end;

if M>=N then

begin

I:=Min(N, QColumns);

while I>=1 do

begin

VM:= M-I+1;

i1_:= (I) - (1);

for i_:= 1 to VM do

begin

V[i_]:= QP[i_+i1_,I];

end;

V[1]:= 1;

ApplyReflectionFromTheLeft(Q, TAUQ[I], V, I, M, 1, QColumns, WORK);

Dec(I);

end;

end

else

begin

I:=Min(M-1, QColumns-1);

while I>=1 do

begin

VM:= M-I;

IP1:= I+1;

i1_:= (IP1) - (1);

for i_:= 1 to VM do

begin

V[i_]:= QP[i_+i1_,I];

end;

V[1]:= 1;

ApplyReflectionFromTheLeft(Q, TAUQ[I], V, I+1, M, 1, QColumns, WORK);

Dec(I);

end;

end;

end;

(*************************************************************************

Óìíîæåíèå íà ìàòðèöó Q, ïðèâîäÿùóþ ìàòðèöó A ê äâóõäèàãîíàëüíîé ôîðìå.

Àëãîðèòì ïîçâîëÿåò îñóùåñòâèòü ïî âûáîðó óìíîæåíèå ñïðàâà èëè ñëåâà, íà

ìàòðèöó Q èëè íà ìàòðèöó Q'.

Âõîäíûå ïàðàìåòðû:

QP - ìàòðèöû Q è P â óïàêîâàííîé ôîðìå.

Ðåçóëüòàò ðàáîòû ïîäïðîãðàììû ToBidiagonal.

M - ÷èñëî ñòðîê â ìàòðèöå A

N - ÷èñëî ñòîëáöîâ â ìàòðèöå A

TAUQ - ñêàëÿðíûå ìíîæèòåëè, ôîðìèðóþùèå ìàòðèöó Q.

Ðåçóëüòàò ðàáîòû ïîäïðîãðàììû ToBidiagonal.

Z - óìíîæàåìàÿ ìàòðèöà

ìàññèâ ñ íóìåðàöèåé ýëåìåíòîâ [1..ZRows,1..ZColumns]

ZRows - ÷èñëî ñòðîê â ìàòðèöå Z. Åñëè FromTheRight=False, òî

ZRows=M, èíà÷å ìîæåò áûòü ëþáûì.

ZColumns - ÷èñëî ñòîëáöîâ â ìàòðèöå Z. Åñëè FromTheRight=True, òî

ZColumns=M, èíà÷å ìîæåò áûòü ëþáûì.

FromTheRight- óìíîæåíèå ñïðàâà èëè ñëåâà

DoTranspose - óìíîæåíèå íà Q èëè íà Q'

Âûõîäíûå ïàðàìåòðû:

Z - Ïðîèçâåäåíèå Z è Q

Ìàññèâ ñ íóìåðàöèåé ýëåìåíòîâ [1..ZRows,1..ZColumns]

Åñëè ZRows=0 èëè ZColumns=0, òî ìàññèâ íå èçìåíÿåòñÿ.

-- ALGLIB --

Copyright 2005 by Bochkanov Sergey

*************************************************************************)

procedure MultiplyByQFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TauQ: TReal1DArray;

var Z: TReal2DArray;

ZRows: Integer;

ZColumns: Integer;

FromTheRight: Boolean;

DoTranspose: Boolean);

var

I: Integer;

J: Integer;

IP1: Integer;

I1: Integer;

I2: Integer;

IStep: Integer;

V: TReal1DArray;

WORK: TReal1DArray;

VM: Integer;

Mx: Integer;

i_: Integer;

i1_: Integer;

begin

if (M<=0) or (N<=0) or (ZRows<=0) or (ZColumns<=0) then

begin

Exit;

end;

Assert(FromTheRight and (ZColumns=M) or not FromTheRight and (ZRows=M), 'MultiplyByQFromBidiagonal: incorrect Z size!');

//

// init

//

Mx:= Max(M, N);

Mx:= Max(Mx, ZRows);

Mx:= Max(Mx, ZColumns);

SetLength(V, Mx+1);

SetLength(WORK, Mx+1);

if M>=N then

begin

//

// setup

//

if FromTheRight then

begin

I1:= 1;

I2:= N;

IStep:= +1;

end

else

begin

I1:= N;

I2:= 1;

IStep:= -1;

end;

if DoTranspose then

begin

I:= I1;

I1:= I2;

I2:= I;

IStep:= -IStep;

end;

//

// Process

//

I:= I1;

repeat

VM:= M-I+1;

i1_:= (I) - (1);

for i_:= 1 to VM do

begin

V[i_]:= QP[i_+i1_,I];

end;

V[1]:= 1;

if FromTheRight then

begin

ApplyReflectionFromTheRight(Z, TAUQ[I], V, 1, ZRows, I, M, WORK);

end

else

begin

ApplyReflectionFromTheLeft(Z, TAUQ[I], V, I, M, 1, ZColumns, WORK);

end;

I:= I+IStep;

until I=I2+IStep;

end

else

begin

//

// setup

//

if FromTheRight then

begin

I1:= 1;

I2:= M-1;

IStep:= +1;

end

else

begin

I1:= M-1;

I2:= 1;

IStep:= -1;

end;

if DoTranspose then

begin

I:= I1;

I1:= I2;

I2:= I;

IStep:= -IStep;

end;

//

// Process

//

if M-1>0 then

begin

I:= I1;

repeat

VM:= M-I;

IP1:= I+1;

i1_:= (IP1) - (1);

for i_:= 1 to VM do

begin

V[i_]:= QP[i_+i1_,I];

end;

V[1]:= 1;

if FromTheRight then

begin

ApplyReflectionFromTheRight(Z, TAUQ[I], V, 1, ZRows, I+1, M, WORK);

end

else

begin

ApplyReflectionFromTheLeft(Z, TAUQ[I], V, I+1, M, 1, ZColumns, WORK);

end;

I:= I+IStep;

until I=I2+IStep;

end;

end;

end;

(*************************************************************************

×àñòè÷íàÿ "ðàñïàêîâêà" ìàòðèöû P, ïðèâîäÿùåé ìàòðèöó A ê äâóõäèàãîíàëüíîé

ôîðìå. Ïîäïðîãðàììà âûâîäèò òðàíñïîíèðîâàííóþ ìàòðèöó P.

Âõîäíûå ïàðàìåòðû:

QP - ìàòðèöû Q è P â óïàêîâàííîé ôîðìå.

Ðåçóëüòàò ðàáîòû ïîäïðîãðàììû ToBidiagonal.

M - ÷èñëî ñòðîê â ìàòðèöå A

N - ÷èñëî ñòîëáöîâ â ìàòðèöå A

TAUP - ñêàëÿðíûå ìíîæèòåëè, ôîðìèðóþùèå ìàòðèöó P.

Ðåçóëüòàò ðàáîòû ïîäïðîãðàììû ToBidiagonal.

PTRows - òðåáóåìîå ÷èñëî ñòðîê ìàòðèöû P^T. N >= PTRows >= 0

Âûõîäíûå ïàðàìåòðû:

PT - PTRows ïåðâûõ ñòîëáöîâ ìàòðèöû PT.

Ìàññèâ ñ íóìåðàöèåé ýëåìåíòîâ [1..PTRows, 1..N]

Åñëè PTRows=0, òî ìàññèâ íå èçìåíÿåòñÿ.

-- ALGLIB --

Copyright 2005 by Bochkanov Sergey

*************************************************************************)

procedure UnpackPTFromBidiagonal(const QP: TReal2DArray;

M: Integer;

N: Integer;

const TauP: TReal1DArray;

PTRows: Integer;

var PT: TReal2DArray);

var

I: Integer;

J: Integer;

IP1: Integer;

V: TReal1DArray;

WORK: TReal1DArray;

VM: Integer;

i_: Integer;

i1_: Integer;

begin

Assert(PTRows<=N, 'UnpackPTFromBidiagonal: PTRows>N!');

if (M=0) or (N=0) or (PTRows=0) then

begin

Exit;

end;

//

// init

//

SetLength(PT, PTRows+1, N+1);

SetLength(V, N+1);

SetLength(WORK, PTRows+1);

//

// prepare PT

//

I:=1;

while I<=PTRows do

begin

J:=1;

while J<=N do

begin

if I=J then

begin

PT[I,J]:= 1;

end

else

begin

PT[I,J]:= 0;

end;

Inc(J);

end;

Inc(I);

end;

if M>=N then

begin

I:=Min(N-1, PTRows-1);

while I>=1 do

begin

VM:= N-I;

IP1:= I+1;

i1_:= (IP1) - (1);

for i_:= 1 to VM do

begin

V[i_]:= QP[I,i_+i1_];

end;

V[1]:= 1;

ApplyReflectionFromTheRight(PT, TAUP[I], V, 1, PTRows, I+1, N, WORK);

Dec(I);

end;

end

else

begin

I:=Min(M, PTRows);

while I>=1 do

begin

VM:= N-I+1;

i1_:= (I) - (1);

for i_:= 1 to VM do

begin

V[i_]:= QP[I,i_+i1_];

end;

V[1]:= 1;

ApplyReflectionFromTheRight(PT, TAUP[I], V, 1, PTRows, I, N, WORK);

Dec(I);

end;

end;

end;

(*************************************************************************

Óìíîæåíèå íà ìàòðèöó P, ïðèâîäÿùóþ ìàòðèöó A ê äâóõäèàãîíàëüíîé ôîðìå.

Àëãîðèòì ïîçâîëÿåò îñóùåñòâèòü ïî âûáîðó óìíîæåíèå ñïðàâà èëè ñëåâà, íà

ìàòðèöó P èëè íà ìàòðèöó P'

Âõîäíûå ïàðàìåòðû:

QP - ìàòðèöû Q è P â óïàêîâàííîé ôîðìå.

Ðåçóëüòàò ðàáîòû ïîäïðîãðàììû ToBidiagonal.

M - ÷èñëî ñòðîê â ìàòðèöå A

N - ÷èñëî ñòîëáöîâ â ìàòðèöå A

TAUP - ñêàëÿðíûå ìíîæèòåëè, ôîðìèðóþùèå ìàòðèöó P.

Ðåçóëüòàò ðàáîòû ïîäïðîãðàììû ToBidiagonal.

Z - óìíîæàåìàÿ ìàòðèöà

ìàññèâ ñ íóìåðàöèåé ýëåìåíòîâ [1..ZRows,1..ZColumns]

ZRows - ÷èñëî ñòðîê â ìàòðèöå Z. Åñëè FromTheRight=False, òî

ZRows=N, èíà÷å ìîæåò áûòü ëþáûì.

ZColumns - ÷èñëî ñòîëáöîâ â ìàòðèöå Z. Åñëè FromTheRight=True, òî

ZColumns=N, èíà÷å ìîæåò áû


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: