@@ -177,14 +177,26 @@ def modred(sys, ELIM, method='matchdc'):
177177 B1 = sys .B [NELIM ,:]
178178 B2 = sys .B [ELIM ,:]
179179
180- A22I = np .linalg .inv (A22 )
181-
182180 if method == 'matchdc' :
183181 # if matchdc, residualize
184- Ar = A11 - A12 * A22 .I * A21
185- Br = B1 - A12 * A22 .I * B2
186- Cr = C1 - C2 * A22 .I * A21
187- Dr = sys .D - C2 * A22 .I * B2
182+
183+ # Check if the matrix A22 is invertible
184+ # if np.linalg.matrix_rank(A22) != len(ELIM):
185+ # raise ValueError("Matrix A22 is singular to working precision.")
186+
187+ # Now precompute A22\A21 and A22\B2 (A22I = inv(A22))
188+ # We can solve two linear systems in one pass, since the
189+ # coefficients matrix A22 is the same. Thus, we perform the LU
190+ # decomposition (cubic runtime complexity) of A22 only once!
191+ # The remaining back substitutions are only quadratic in runtime.
192+ A22I_A21_B2 = np .linalg .solve (A22 , np .concatenate ((A21 , B2 ), axis = 1 ))
193+ A22I_A21 = A22I_A21_B2 [:, :A21 .shape [1 ]]
194+ A22I_B2 = A22I_A21_B2 [:, A21 .shape [1 ]:]
195+
196+ Ar = A11 - A12 * A22I_A21
197+ Br = B1 - A12 * A22I_B2
198+ Cr = C1 - C2 * A22I_A21
199+ Dr = sys .D - C2 * A22I_B2
188200 elif method == 'truncate' :
189201 # if truncate, simply discard state x2
190202 Ar = A11
@@ -373,8 +385,6 @@ def markov(Y, U, M):
373385 UU = np .hstack ((UU , Ulast ))
374386
375387 # Invert and solve for Markov parameters
376- H = UU .I
377- H = np .dot (H , Y )
388+ H = np .linalg .lstsq (UU , Y )[0 ]
378389
379390 return H
380-
0 commit comments