I am working on linear equations like A*X = B. I got a matrix like A = magic(4) and B = [1;3;2;4]. I used several methods to solve this problem, also including MATLAB A\B.
What's annoyed is the resulf of MATLAB A\B is different from those of NumPy, SciPy and LAPACK (LAPACKE_dgetrf, LAPACKE_dgels, LAPACKE_dgelsd).
The folowing are the results.
MATLAB A\B (Ubuntu Matlab 2021a and Matlab Online)
>> A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
>> B = [1;3;2;4]
B =
1
3
2
4
>> A \ B
RCOND = 4.625929e-18。
ans =
-0.0098
0.0735
0.1985
0.0319
>> lsqr(A, B)
ans =
0.0110
0.1360
0.1360
0.0110
>> x = pinv(A)*B
x =
0.0110
0.1360
0.1360
0.0110
>> [L, U, P] = lu(A) %lu decomposition
L =
1.0000 0 0 0
0.2500 1.0000 0 0
0.5625 0.4352 1.0000 0
0.3125 0.7685 1.0000 1.0000
U =
16.0000 2.0000 3.0000 13.0000
0 13.5000 14.2500 -2.2500
0 0 -1.8889 5.6667
0 0 0 0.0000
P =
1 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
>> y = L \ (P * B) % LU tril solver
y =
1.0000
3.7500
-0.1944
0.0000
>> x = U \ y % LU triu solver
x =
-0.0098
0.0735
0.1985
0.0319
Python numpy.linalg.solve(a, b)
import numpy as np
a = np.array([[16., 2., 3., 13.], [5., 11., 10., 8.], [9., 7., 6., 12.], [4., 14., 15., 1.]]);
b = np.array([[1.],[3.],[2.],[4]]);
x = np.linalg.solve(a, b)
'''
x =
array([[ 0.10799632],
[ 0.42693015],
[-0.15487132],
[-0.0859375 ]])
'''
Python scipy.linalg.solve(a, b)
from scipy import linalg
x1 = linalg.solve(a, b)
'''
x1 =
array([[ 0.10799632],
[ 0.42693015],
[-0.15487132],
[-0.0859375 ]])
'''
Octave Online
octave:1> A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
octave:2> B = [1;3;2;4]
B =
1
3
2
4
octave:3> A\B
warning: matrix singular to machine precision, rcond = 1.30614e-17
ans =
0.011029
0.136029
0.136029
0.011029
Lapack LAPACKE_degelsd
a =
Matrix(Row = 4, Col = 4, Major = ColMajor)
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
B =
Vector(Size = 4)
1
3
2
4
info = 0
X =
Vector(Size = 4)
0.107996
0.42693
-0.154871
-0.0859375
My problem is what the MATLAB A \ B exactly computes. I know that pinv(A) * B computes the minimum norm least-squares solution, and so do np.linalg.solve and scipy.linalg.solve.
And the MATLAB reference page said:
If
Ais a square matrix, thenA\Bis roughly equal toinv(A)*B, but MATLAB processesA\Bdifferently and more robustly.If the rank of
Ais less than the number of columns inA, thenx = A\Bis not necessarily the minimum norm solution. You can compute the minimum norm least-squares solution usingx = lsqminnorm(A,B)orx = pinv(A)*B.
Well I know the solution is not unique when A is nearly singular. There are many feasible solutions (like numpy, octave and LAPACK. They solve this problem to minimize the norm of ||AX - B|| by QR, SVD(pinv)). However what makes matlab get its solution, and what's the magic?
So, I want to ask what the operation A\B exactly computes and what the result of A\B is when A is a singular square matrix.
P.S.
I do know there isn't an unique solution for linear equations when its coefficient matrix is singular or nearly singular .aka. ill conditioned. According to the reference page of \(mldivide), x = A\B is not necessarily the minimum norm solution. I want to know the underlying details of A\B. If it is not necessarily the minimum norm solution, then what? As I know, scipy, numpy, LAPACK and Octave get a minimum norm solution. Is there another fomulation for this problem that I haven't know?