1/6 LU 分解

         LU 分解可以写成A = LU,这里的L代表下三角矩阵,U代表上三角矩阵。对应的matlab代码如下:

function[L, U] =zlu(A)

% ZLU - LU decomposition for matrix A

% work as gauss elimination

 

[m, n] = size(A);

if m ~= n 

    error('Error, current time only support square matrix');

end

 

L = zeros(n);

U = zeros(n);

 

for k = 1:n-1

    gauss_vector = A(:,k);

    gauss_vector(k+1:end) = gauss_vector(k+1:end) ./ gauss_vector(k);

    gauss_vector(1:k) = zeros(k,1);

    L(:,k) = gauss_vector;

    L(k,k) = 1;

    for l=k+1:n

        A(l,:) = A(l,:) - gauss_vector(l)*A(k,:);

    end

end    

 

U = A;

 

这段代码的目的非常简单,就是使用高斯消元法给出L,U。但是计算的稳定性非常不好,这点可以通过这段代码的分解结果和matlab自带lu的分解结果相比较得出。比较的方法非常简单:就是计算l*u与原始矩阵想减之后的Frobinus范数大小,使用如下的代码做出两个结果的比较:

n = 1000;

my_error = zeros(1, 1000);

sys_error = zeros(1, 1000);

 

for i = 1:n

    test = randn(5);

    [zl, zu] = zlu(test);

    [l, u] = lu(test);

 

    my_error(i) = norm(zl*zu - test, 'fro');

    sys_error(i) = norm(l*u - test, 'fro');

end

 

disp(mean(my_error));

disp(var(my_error));

disp(mean(sys_error));

disp(var(sys_error));

 

在这段代码里面,随机的生成一个5x5的符合高斯分布的矩阵,然后使用自己写的lu分解和matlab自带的lu分解分别给出L和U,再计算norm(L*U - test),从这里就可以看出我们自己计算出来的结果精度和matlab自带的lu真实的差异了。这个差异就体现为这些值的均值和方差。结果如下:

mean of my lu : 13.313846
variance of my lu : 43622.114147
mean of matlab lu : 0.000000
variance of matlab lu : 0.000000

从这个结果可以看出,我们自己写的lu分解的结果在均值和方差上比matlab自带的差了很多。个人认为原因有两点:第一个方法的原因,matlab给出的结果是pivoted LU,第二个是因为实现的原因,matlab基于成熟的LAPACK,肯定会比自己写的更好了。

 

这一步使用PA = LU来完成LU分解。代码如下:

function [P, L, U] = zplu(A)

% pivoted LU decompositon P*A = L*U

 

[m, n] = size(A);

 

if m ~= n

    error('zplu:test', 'current time only support square matrix');

end

 

P = eye(n);

L = zeros(n, n);

 

for k = 1:n-1

 

    %find the largest element in k column of A from row k to n

    [max_value, max_index] = max(A(k:end, k));

    

    max_index = max_index + k - 1;

    if max_index ~= k

        A([k max_index], :) = A([max_index k], :);

        P([k max_index], :) = P([max_index k], :);

        L([k max_index], :) = L([max_index k], :);

    end

    

    if A(k,k) ~= 0

        gauss_vector = A(:,k);

        gauss_vector(k+1:end) = gauss_vector(k+1:end) ./ gauss_vector(k);

        gauss_vector(1:k) = zeros(k,1);

        L(:,k) = gauss_vector;

        L(k, k) = 1;

    

        for l=k+1:n

            A(l,:) = A(l,:) - gauss_vector(l)*A(k,:);

        end

    end

end

U = triu(A);

 

下面是运行前面检测程序的输出:

mean of my lu : 7.803258
variance of my lu : 1450.332510
mean of matlab lu : 0.000000
variance of matlab lu : 0.000000

两个结果相比较可以看到,Matlab的lu一样的稳定,但是使用pivot来调整矩阵A的次序可以极大的提高LU分解的稳定度,这个可以从下降了非常多的方差可以看出。

pivot LU是从k列的k+1到n个元素种选择最大的一个,调换到第k个位置。从我个人的角度理解,除以最大的元素使得高斯变换矩阵中非对角元素全部小于1。由于计算机种存储浮点数的机制,绝对值越靠近0,其精度越高。所以使用pivot这种方法可以极大的提高LU分解的稳定程度。但是也需要指出,使用pivot并不一定能提高LU分解的精度,对于特定的矩阵,不使用pivot说不定可以获得更好的性能。

为了进一步提高提高LU分解的稳定性,可以使用full pivoted LU。分解公式:P*A*Q = L * U; 对应的Matlab代码如下:

 

function [P, Q, L, U] = zflu(A)

%full pivoted LU decomposition

%

% full pivoted LU decomposition

 

[m, n] = size(A);

 

if m ~= n

    error('current only support square matrix')

end

 

P = eye(n);

Q = eye(n);

 

for k=1:n-1

    

    %find the larget element in A(k:n,k:n)

    [max_value, row_index] = max(A(k:n, k:n));

    [max_value, col_index] = max(max_value);

    

    real_row = k-1 + row_index(col_index);

    real_col = k-1 + col_index;

    

    %exchange the row and column of matrix A

    

    if real_row ~= k

        A([k real_row],:) = A([real_row k], :);

        P([k real_row],:) = P([real_row k], :);

    end

    

    if real_col ~= k

        A(:, [k real_col]) = A(:, [real_col k]);

        Q(:, [k real_col]) = Q(:, [real_col k]);

    end

    

    if A(k, k) ~= 0

        rows = k+1:n;

        A(rows, k) = A(rows, k) ./ A(k, k);

        A(rows, rows) = A(rows, rows) - A(rows, k)*A(k, rows);

    end

end

 

L = tril(A);

for k=1:n

    L(k, k) = 1;

end

U = triu(A);

 

跑完test之后的结果如下:

mean of my lu : 7.77222e-16
variance of my lu : 4.3478e-29
mean of matlab lu : 3.69764e-16
variance of matlab lu : 2.03659e-32

可以看到使用full pivoted LU 分解可以在很大程度上保证分解的稳定性,即便是使用我们自己写的代码。但是即便如此,仍然推荐使用LAPACK中的代码,因为那里面的代码是经过严格的测试和分析的,在各种一场情况下应该都有很好的表现。

这里所介绍的LU分解可以使用另外一种基于GaxPy形式的运行,将在下面介绍。

LU分解(1)的更多相关文章

  1. matlab 求解线性方程组之LU分解

    线性代数中的一个核心思想就是矩阵分解,既将一个复杂的矩阵分解为更简单的矩阵的乘积.常见的有如下分解: LU分解:A=LU,A是m×n矩阵,L是m×m下三角矩阵,U是m×n阶梯形矩阵 QR分解: 秩分解 ...

  2. LU分解,Javascript代码

    ///A 为矩阵,这里写成一维数组,如 [1],[1,2,3,4] function GetLU(a) { var n = a.length;//矩阵的总数据数目 var s = Math.sqrt( ...

  3. matlab实现高斯消去法、LU分解

    朴素高斯消去法: function x = GauElim(n, A, b) if nargin < 2 for i = 1 : 1 : n for j = 1 : 1 : n A(i, j) ...

  4. LU分解(2)

    接着上次LU分解的讲解,这次给出使用不同的计算LU分解的方法,这种方法称为基于GaxPy的计算方法.这里需要了解lapapck中的一些函数.lapack中有一个函数名为gaxpy,所对应的矩阵计算公式 ...

  5. MATLAB矩阵的LU分解及在解线性方程组中的应用

    作者:凯鲁嘎吉 - 博客园http://www.cnblogs.com/kailugaji/ 三.实验程序 五.解答(按如下顺序提交电子版) 1.(程序) (1)LU分解源程序: function [ ...

  6. 线性代数笔记10——矩阵的LU分解

    在线性代数中, LU分解(LU Decomposition)是矩阵分解的一种,可以将一个矩阵分解为一个单位下三角矩阵和一个上三角矩阵的乘积(有时是它们和一个置换矩阵的乘积).LU分解主要应用在数值分析 ...

  7. 矩阵分解---QR正交分解,LU分解

    相关概念: 正交矩阵:若一个方阵其行与列皆为正交的单位向量,则该矩阵为正交矩阵,且该矩阵的转置和其逆相等.两个向量正交的意思是两个向量的内积为 0 正定矩阵:如果对于所有的非零实系数向量x ,都有 x ...

  8. 计算方法 -- 解线性方程组直接法(LU分解、列主元高斯消元、追赶法)

    #include <iostream> #include <cstdio> #include <algorithm> #include <cstdlib> ...

  9. 矩阵LU分解分块算法实现

    本文主要描述实现LU分解算法过程中遇到的问题及解决方案,并给出了全部源代码. 1. 什么是LU分解? 矩阵的LU分解源于线性方程组的高斯消元过程.对于一个含有N个变量的N个线性方程组,总可以用高斯消去 ...

随机推荐

  1. iOS:编译错误Undefined symbols for architecture i386: _OBJC_CLASS_$_XXX&quot;, referenced from: error

    Undefined symbols for architecture i386: _OBJC_CLASS_$_XXX", referenced from: error 这个意思为无法找到名为 ...

  2. 用Wget进行下载

    wget下载可以不用考虑资源的双向认证的问题,即 wget -N -S -O " + filePath + " " + urlStr + " --no-chec ...

  3. 如何成为一名优秀的web前端工程师(转给自己,共勉)

    来源:王子墨的博客 程序设计之道无远弗届,御晨风而返.———— 杰佛瑞 · 詹姆士 我所遇到的前端程序员分两种: 第一种一直在问:如何学习前端? 第二种总说:前端很简单,就那么一点东西. 我从没有听到 ...

  4. HTML5 History对象,Javascript修改地址栏而不刷新页面

    一.History对象 History 对象包含用户(在浏览器窗口中)访问过的 URL. History 对象是 window 对象的一部分,可通过 window.history 属性对其进行访问. ...

  5. iOS 上传项目常见问题

    一. Archive项目 时,出现"Your build settings specify a provisioning profile with the UUID "XXX&qu ...

  6. NOI 193棋盘分割.cpp

    193:棋盘分割 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分 ...

  7. 你好,C++(35)类是如何藏私房钱的?6.2.4 拷贝构造函数

    6.2.6  类成员的访问控制 类成员包括类的成员变量和成员函数,它们分别用来描述类的属性和行为.而类成员的访问控制决定了哪些成员是公开的,可以被外界访问,也可以被自身访问:哪些成员是私有的,只能在类 ...

  8. Android Studio删除Project

    最直截了当的方法是在Project所在目录直接删除整个Project,然后再次打开Android Studio的欢迎界面中把光标移到你的Project上,然后按键盘上的Delete键即可! 参考自st ...

  9. Windows Phone中使用Storyboard做类似 IOS 屏幕小白点的效果

    windows phone中做动画其实很方便的,可以使用Blend拖来拖去就做出一个简单的动画,下面做了一个 ios屏幕小白点的拖动效果,包括速度判断移动 使用Blend生成以下代码 <Stor ...

  10. Ajax的load方法演示

    load方法的参数形式为: load(url,[data],[callback]); 其中url为请求HTML页面的URL地址.[data]表示发送至服务器的key/value数据.callback表 ...