我正在尝试编写解决A * x = b线性系统的代码。
我使用高斯消除过程制作了以下代码,并且如果A中没有任何0,它每次都能工作。如果A中有零,则有时它起作用,有时则不起作用。基本上,我正在尝试替代MATLAB中的“ A \ b”。
是否有更好/更简单的方法?
A = randn(5,5);
b = randn(5,1);
nn = size(A);
n = nn(1,1);
U = A;
u = b;
for c = 1:1:n
k = U(:,c);
for r = n:-1:c
if k(r,1) == 0
continue;
else
U(r,:) = U(r,:)/k(r,1);
u(r,1) = u(r,1)/k(r,1);
end
end
for r = n:-1:(c+1)
if k(r,1) == 0
continue;
else
U(r,:) = U(r,:) - U(r-1,:);
u(r,1) = u(r,1) - u(r-1,1);
end
end
end
x = zeros(size(b));
for r = n:-1:1
if r == n
x(r,1) = u(r,1);
else
x(r,1) = u(r,1);
x(r,1) = x(r,1) - U(r,r+1:n)*x(r+1:n,1);
end
end
error = A*x - b;
for i = 1:1:n
if abs(error(i)) > 0.001
disp('ERROR!');
break;
else
continue;
end
end
disp('x:');
disp(x);
工作示例为0:
A = [1, 3, 1, 3;
3, 4, 4, 1;
3, 0, 3, 9;
0, 4, 0, 1];
b = [3;
4;
5;
6];
失败的示例(A * x-b不是[0])
A = [1, 3, 1, 3;
3, 4, 4, 1;
0, 0, 3, 9;
0, 4, 0, 1];
b = [3;
4;
5;
6];
我的算法的解释: 可以说我有以下A矩阵:
|4, 1, 9|
|3, 4, 5|
|1, 3, 5|
对于第一列,我将每一行除以该行的第一个数字,因此每一行都以1开头
|1, 1/4, 9/4|
|1, 4/3, 5/3|
|1, 3, 5|
然后我将最后一行减去上面的那一行,然后对上面的行做同样的操作,依此类推。
|1, 1/4, 9/4|
|0, 4/3-1/4, 5/3-9/4|
|0, 3-4/3, 5-5/3|
|1, 0.25, 2.250|
|0, 1.083, -0.5833|
|0, 1.667, 3.333|
然后在其余各列中重复相同的操作。
|1, 0.25, 2.250|
|0, 1, -0.5385|
|0, 1, 1.999|
|1, 0.25, 2.250|
|0, 1, -0.5385|
|0, 0, -8.7700|
|1, 0.25, 2.250|
|0, 1, -0.5385|
|0, 0, 1|
我在A中所做的操作与在b中所做的操作相同,因此系统保持等效。
重新更新:
我在“ for c = 1:1:n”之后添加了这个名称
因此,在执行任何操作之前,它会对A(和b)的行进行排序,以使“ c”列具有新月条目(A的底部行将保留0)。现在,它似乎适用于任何可逆的方阵,尽管我不确定是否可以。
r = c;
a = r + 1;
while r <= n
if r == n
r = r + 1;
elseif a <= n
while a <= n
if abs(U(r,c)) < abs(U(a,c))
UU = U(r,:);
U(r,:) = U(a,:);
U(a,:) = UU;
uu = u(r,1);
u(r,1) = u(a,1);
u(a,1) = uu;
else
a = a+1;
end
end
else
r = r+1;
a = r+1;
end
end
答案 0 :(得分:2)
具有旋转的高斯消除如下。
function [L,U,P] = my_lu_piv(A)
n = size(A,1);
I = eye(n);
O = zeros(n);
L = I;
U = O;
P = I;
function change_rows(k,p)
x = P(k,:); P(k,:) = P(p,:); P(p,:) = x;
x = A(k,:); A(k,:) = A(p,:); A(p,:) = x;
x = v(k); v(k) = v(p); v(p) = x;
end
function change_L(k,p)
x = L(k,1:k-1); L(k,1:k-1) = L(p,1:k-1);
L(p,1:k-1) = x;
end
for k = 1:n
if k == 1, v(k:n) = A(k:n,k);
else
z = L(1:k-1,1:k -1)\ A(1:k-1,k);
U(1:k-1,k) = z;
v(k:n) = A(k:n,k)-L(k:n,1:k-1)*z;
end
if k<n
x = v(k:n); p = (k-1)+find(abs(x) == max(abs(x))); % find index p
change_rows(k,p);
L(k+1:n,k) = v(k+1:n)/v(k);
if k > 1, change_L(k,p); end
end
U(k,k) = v(k);
end
end
为了解决系统问题。
%A x = b(1)原始系统%L U = P A
(2)将P A或A(p,:)分解为乘积L U%P A x = P b(3)将(1)的两边乘以P%L U x = P b
(4)将(2)代入(3)%,让y = U x(5)将y定义为 U x%让c = P b(6)将c定义为P b%L y = c
(7)将(5)和(6)代入(4)%U * x = y(8)a 重写(5)
为此。
%[L U p] = lu(A); %分解%y = L \(P * b);前进百分比 (7)的解,较低的三角系统%x = U \ y; % (8)的后求解,一个上三角系统
答案 1 :(得分:1)
高斯算法假定矩阵被转换为上三角矩阵。在您的示例中不会发生这种情况。算法的结果是
A =
1 3 1 3
3 4 4 1
0 0 3 9
0 4 0 1
U =
1.00000 3.00000 1.00000 3.00000
-0.00000 1.00000 -0.20000 1.60000
0.00000 0.00000 1.00000 3.00000
0.00000 4.00000 -0.00000 1.00000
如您所见,它不是上三角。如果数据透视元素为零,则您正在跳过行。那行不通。要解决此问题,如果枢轴元素为零,则需要交换矩阵中的列和向量中的行。最后,您必须在结果b
中换回行。 u
。
高斯算法是:
1 Set n = 1
2 Take pivot element (n, n)
3 If (n, n) == 0, swap column n with column m, so that m > n and (n, m) != 0 (swap row m and n in vector b)
4 Divide n-th row by pivot element (divide n-th row in vector b)
5 For each m > n
6 If (m, n) != 0
7 Divide row m by m and subtract element-wise row n (same for vector b)
8 n = n + 1
9 If n <= number of rows, go to line 2
就数值稳定性而言,最好将每一行的最大值用作枢轴元素。您也可以通过交换列和行来将矩阵的最大值用作枢轴元素。但是请记住要交换b
并重新交换解决方案。
答案 2 :(得分:1)
试试这个:
Ab = [A,b] % Extended matrix of the system of equations
rref(Ab) % Result of applying the Gauss-Jordan elimination to the extended matrix
有关详细信息和示例,请参阅 rref
documentation。