天天看點

GSL 系列 6 — 線性代數 2 — LU 分解

文章目錄

    • 0 寫在前面
    • 1 LU 分解相關對象和函數
      • 1.1 轉置矩陣對象
      • 1.2 LU 分解函數
      • 1.3 LU 求解方程
      • 1.4 LU 求逆
      • 1.5 LU 求行列式

0 寫在前面

關于 LU 分解的背景知識介紹,參見:GSL 系列 6 — 線性代數 1 — 背景知識 1 (LU 分解) 節,本篇隻說明相關函數

1 LU 分解相關對象和函數

1.1 轉置矩陣對象

轉置矩陣對象存儲着一列索引。第 j j j 個數為 k k k ,表示轉置矩陣第 j j j 列是相應機關矩陣的第 k k k 列,定義如下:

// gsl_permutation.h
struct gsl_permutation_struct
{
  size_t size;
  size_t *data;
};
typedef struct gsl_permutation_struct gsl_permutation;
           

1.2 LU 分解函數

将矩陣

A

進行 LU 分解,然後得到轉置矩陣

p

LU

矩陣儲存在

A

中,

signum

為 1 或 -1,代表交換的次數,奇數次為 -1,偶數次為 1

因為下三角(梯形)矩陣對角線為 1,不儲存,

A

剛好可以方向

LU

// gsl_linalg.h
int gsl_linalg_LU_decomp(gsl_matrix * A, gsl_permutation * p, int *signum);
int gsl_linalg_complex_LU_decomp(gsl_matrix_complex * A, 
                                  gsl_permutation * p, 
                                  int *signum);
           

1.3 LU 求解方程

solve

版本:給

LU

矩陣,

p

轉置矩陣,向量

b

,得到解向量

x

svx

版本: 給

LU

矩陣,

p

轉置矩陣,向量 b(就是

x

),得到解向量

x

,解向量存在

x

中,即

solve

的置換版本

refine

版本:應用疊代改進的辦法求解

x

,還需要給一個向量工作空間

work

,長度為

x

的長度

// gsl_linalg.h
int gsl_linalg_LU_solve (const gsl_matrix * LU,
                         const gsl_permutation * p,
                         const gsl_vector * b,
                         gsl_vector * x);
int gsl_linalg_complex_LU_solve (const gsl_matrix_complex * LU,
                                 const gsl_permutation * p,
                                 const gsl_vector_complex * b,
                                 gsl_vector_complex * x);
int gsl_linalg_LU_svx (const gsl_matrix * LU,
                       const gsl_permutation * p,
                       gsl_vector * x);
int gsl_linalg_complex_LU_svx (const gsl_matrix_complex * LU,
                               const gsl_permutation * p,
                               gsl_vector_complex * x);   
int gsl_linalg_LU_refine (const gsl_matrix * A,
                          const gsl_matrix * LU,
                          const gsl_permutation * p,
                          const gsl_vector * b,
                          gsl_vector * x,
                          gsl_vector * work);                               
int gsl_linalg_complex_LU_refine (const gsl_matrix_complex * A,
                                  const gsl_matrix_complex * LU,
                                  const gsl_permutation * p,
                                  const gsl_vector_complex * b,
                                  gsl_vector_complex * x,
                                  gsl_vector_complex * work);                                                   
           

1.4 LU 求逆

類似地,分為無置換版本 (

invert

) 和置換版本 (

invx

),無置換時,存在矩陣

inverse

中,有置換時,存在

LU

// gsl_linalg.h
int gsl_linalg_LU_invert (const gsl_matrix * LU,
                          const gsl_permutation * p,
                          gsl_matrix * inverse);
int gsl_linalg_complex_LU_invert (const gsl_matrix_complex * LU,
                                  const gsl_permutation * p,
                                  gsl_matrix_complex * inverse);                          
int gsl_linalg_LU_invx (gsl_matrix * LU, const gsl_permutation * p);
int gsl_linalg_complex_LU_invx (gsl_matrix_complex * LU, const gsl_permutation * p);                                  
           
最好避免通過直接求逆的方法來求解線性方程組,因為線性方程組求解函數更有效率和更準确

1.5 LU 求行列式

求解 det ⁡ ( A ) \det(A) det(A),需要給

LU

矩陣

// gsl_linalg.h
double gsl_linalg_LU_det (gsl_matrix * LU, int signum);
gsl_complex gsl_linalg_complex_LU_det (gsl_matrix_complex * LU,
                                       int signum);                                
           

求解 ln ⁡ ( ∣ det ⁡ ( A ) ∣ ) \ln(|\det(A)|) ln(∣det(A)∣),需要給

LU

矩陣

// gsl_linalg.h
double gsl_linalg_LU_lndet (gsl_matrix * LU);
double gsl_linalg_complex_LU_lndet (gsl_matrix_complex * LU);   
           

求解 det ⁡ ( A ) / ∣ det ⁡ ( A ) ∣ \det(A)/|\det(A)| det(A)/∣det(A)∣,需要給

LU

矩陣

// gsl_linalg.h
int gsl_linalg_LU_sgndet (gsl_matrix * lu, int signum);
gsl_complex gsl_linalg_complex_LU_sgndet (gsl_matrix_complex * LU,
                                          int signum);    
           

繼續閱讀