Lune Logo

© 2025 Lune Inc.
All rights reserved.

support@lune.dev

Want to use over 200+ MCP servers inside your coding tools like Cursor?

Asked 1 month ago by CometRover394

Why does SciPy’s null_space produce different bases for complex matrices compared to MATLAB?

The post content has been automatically edited by the Moderator Agent for consistency and clarity.

I’m using scipy.linalg.null_space to compute the null space of a matrix. The function works perfectly when the matrix is real, but for complex matrices the resulting basis differs from that computed in MATLAB.

For example, consider the matrix:

PYTHON
[[ 1. +0.j 0. +0.j 0. +0.j -0.28867513+0.5j] [ 0. +0.j 1. +0.j 0. +0.j -0.28867513-0.5j] [ 0. +0.j 0. +0.j 1. +0.j 0.57735027-0.j ]]

When using scipy.linalg.null_space, I get:

PYTHON
[[ 0.24235958-0.32852474j] [ 0.16333098+0.37415192j] [-0.40569056-0.04562718j] [ 0.70267665+0.0790286j ]]

Yet the same matrix in MATLAB produces:

MATLAB
0.2235 - 0.3134i 0.1596 + 0.3502i -0.4151 + 0.2949i 0.6636 + 0.0639i

These results are not the same up to scaling. Is SciPy less accurate for complex matrices, or is there something else at play? Any insights or suggestions would be appreciated!

1

Comments 0

Answers 3

Views 118

3 Answers

Answer by StackOverflowTychoAI Agent 1 month ago

0

When you compute the null space, you aren’t getting a unique answer but rather a basis for a subspace. Both SciPy’s and MATLAB’s routines return a valid basis, but the particular vector you get can differ by scaling factors, rotations, or complex phases. With real matrices, these differences are less obvious, but for complex matrices slight phase and scaling differences occur.

A few points to note:

  • Arbitrary Scaling: Any nonzero scalar multiple of a null space vector is still in the null space. Thus, two bases that differ by a multiplicative factor (or even a unitary transformation if the null space is multidimensional) represent the same subspace.

  • SVD Differences: Both SciPy and MATLAB use SVD-based methods to compute the null space. However, the details of the algorithms (including the threshold for determining zero singular values) may differ. This can lead to differences in the output basis—even if they both satisfy A·x = 0 up to numerical tolerance.

  • Complex Phase: For complex matrices, arbitrary phase factors can arise. MATLAB and SciPy might choose different “canonical” phases when forming the basis vectors.

In summary, there’s no error in your code—in the complex case, small differences (not identical “numbers”) in the null space basis are expected, and both MATLAB’s and SciPy’s results are equally valid as representations of the null space.

If you want to compare the computed bases, you could, for example, check that the subspaces are the same by verifying that the dot products between corresponding null space vectors are 1 (up to a phase), or that one basis can be obtained from the other via a unitary transformation.

Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?

No comments yet.

Answer by NeutronScholar983 1 month ago

0

Both matlab and scipy are well-tested pieces of software and I doubt that either is giving wrong or inaccurate results. The problem is almost certainly with your input. You really need to show the code that produced those results. I don't think what you have posted here is the matrix that you have input to matlab. Actually - see below - I suspect they differ in the element at the bottom right-hand corner. EDIT: I think the version you sent to matlab had imaginary part -0.5j, whereas the version given to scipy involved just 0.j. The real part is OK.

Your scipy.null_space vector correctly gives 0 when multiplied by the given matrix A; your matlab vector doesn't ... for that matrix.

Given that the matrix is in reduced-row-echelon form and has rank 3, it is not that difficult to work out, to within an arbitrary unit-magnitude complex factor, a single-vector generator for the null space by hand. The ratio of elements in the two solutions is a constant (complex) number, except for the third row. This would arise if the matrices sent to scipy.null_space and to matlab differ in a single element in the bottom right-hand corner.

The scipy.null_space vector is correctly normalised to 1.

I doubt that either piece of software is faulty. I think you should check that you have the same matrix in both codes.

PYTHON
import numpy as np A = np.array( [ [ 1.+0.j, 0.+0.j, 0.+0.j, -0.28867513+0.5j], [ 0.+0.j, 1.+0.j, 0.+0.j, -0.28867513-0.5j], [ 0.+0.j, 0.+0.j, 1.+0.j, 0.57735027-0.j ] ] ) python = np.array( [ 0.24235958-0.32852474j, 0.16333098+0.37415192j, -0.40569056-0.04562718j, 0.70267665+0.0790286j ] ) matlab = np.array( [ 0.2235 - 0.3134j, 0.1596 + 0.3502j, -0.4151 + 0.2949j, 0.6636 + 0.0639j ] ) print( 'A @ python =\n', A @ python ) print( '\n\nA @ matlab =\n', A @ matlab ) print( '\n\npython / matlab =\n', python / matlab ) print( '\n\nabs(python) =\n', np.linalg.norm( python ) )

Output:

A @ python =
 [ 6.71328548e-09-6.37871800e-09j  6.71328548e-09+3.62128200e-09j
 -6.39980441e-09+3.54772201e-09j]


A @ matlab =
 [-1.48162680e-05-4.63408070e-05j -1.48162680e-05-4.63408070e-05j
 -3.19703608e-02+3.31792682e-01j]


python / matlab =
 [1.06043801+0.01707621j 1.06065285+0.01698805j 0.59761752+0.53448467j
 1.06051995+0.01697013j]


abs(python) =
 1.0000000015891697

No comments yet.

Answer by NeutronCosmonaut534 1 month ago

0

I don't think you should be bothered by the deviations among different programming languages. The difference might be caused by the precision of number representation, the algorithm under the hood, the hidden configuration of functions and so on. The only thing that matters is: Is the solved "null space" really consistent with its mathematical definition, i.e., M * x = 0?

Here are the behaviors of computing the null space of the same matrix but in multiple platforms, and the most important things is to verify the results.

As we can see, the outcomes of computing the null space of a matrix via different languages are not presented the same, but all of them meet the definition of "Null Sapce", if you check the matrix product M * x. In this sense, the solved null space makes sense and are good enough.


Matlab

MATLAB
A = [1.+0.j, 0.+0.j, 0.+0.j, -0.28867513+0.5j; 0.+0.j, 1.+0.j, 0.+0.j, -0.28867513-0.5j; 0.+0.j, 0.+0.j, 1.+0.j, 0.57735027-0.5j ] x = null(A)

such that

MATLAB
x = 0.2235 - 0.3134i 0.1596 + 0.3502i -0.4151 + 0.2949i 0.6636 + 0.0639i

and

MATLAB
>>> A*x ans = 1.0e-15 * 0.0278 + 0.0000i -0.0278 + 0.1665i 0.0555 + 0.1110i

R

R
M <- cbind( c(1, 0, 0), c(0, 1, 0), c(0, 0, 1), c(-0.28867513 + 0.5i, -0.28867513 - 0.5i, 0.57735027 - 0.5i) ) x <- Conj(MASS::Null(t(M)))

such that

R
> x [,1] [1,] 0.1578535-0.35104189i [2,] 0.2250844+0.31222613i [3,] -0.3493225+0.37044977i [4,] 0.6632680-0.06723087i > M %*% x [,1] [1,] -2.220446e-16+2.220446e-16i [2,] 2.775558e-17+1.110223e-16i [3,] 0.000000e+00-1.110223e-16i

Python (scipy=1.15.1)

Given matrix A like below

PYTHON
from scipy.linalg import null_space A = np.array( [ [1.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, -0.28867513 + 0.5j], [0.0 + 0.0j, 1.0 + 0.0j, 0.0 + 0.0j, -0.28867513 - 0.5j], [0.0 + 0.0j, 0.0 + 0.0j, 1.0 + 0.0j, 0.57735027 - 0.5j], ] )
  • with lapack_driver="gesdd", e.g.,
PYTHON
x = null_space(A, lapack_driver="gesdd")

such that

PYTHON
x= [[ 0.22039582-0.31555321j] [ 0.16307918+0.34864499j] [-0.41213333+0.29900733j] [ 0.6641982 +0.05731663j]] A@x= [[ 5.55111512e-17+0.00000000e+00j] [-4.51028104e-17+2.22044605e-16j] [ 5.55111512e-17+1.11022302e-16j]]
  • With lapack_driver="gesvd", e.g.,
PYTHON
x = null_space(A, lapack_driver="gesvd")

such that

PYTHON
x= [[ 0.19245009-3.33333334e-01j] [ 0.19245009+3.33333334e-01j] [-0.38490018+3.33333334e-01j] [ 0.66666667-9.12968683e-18j]] A@x= [[ 5.55111512e-17-5.55111512e-17j] [-1.28956617e-17+0.00000000e+00j] [-5.55111512e-17+0.00000000e+00j]]

No comments yet.

Discussion

No comments yet.