def solve_lyap_dense(A, E, B, trans=False, options=None): """Compute the solution of a Lyapunov equation. See :func:`pymor.algorithms.lyapunov.solve_lyap_dense` for a general description. This function uses `slycot.sb03md` (if `E is None`) and `slycot.sg03ad` (if `E is not None`), which are based on the Bartels-Stewart algorithm. Parameters ---------- A The operator A as a 2D |NumPy array|. E The operator E as a 2D |NumPy array| or `None`. B The operator B as a 2D |NumPy array|. trans Whether the first operator in the Lyapunov equation is transposed. options The solver options to use (see :func:`lyap_dense_solver_options`). Returns ------- X Lyapunov equation solution as a |NumPy array|. """ _solve_lyap_dense_check_args(A, E, B, trans) options = _parse_options(options, lyap_dense_solver_options(), 'slycot_bartels-stewart', None, False) if options['type'] == 'slycot_bartels-stewart': n = A.shape[0] C = -B.dot(B.T) if not trans else -B.T.dot(B) trana = 'T' if not trans else 'N' dico = 'C' job = 'B' if E is None: U = np.zeros((n, n)) X, scale, sep, ferr, _ = slycot.sb03md(n, C, A, U, dico, job=job, trana=trana) _solve_check(A.dtype, 'slycot.sb03md', sep, ferr) else: fact = 'N' uplo = 'L' Q = np.zeros((n, n)) Z = np.zeros((n, n)) _, _, _, _, X, scale, sep, ferr, _, _, _ = slycot.sg03ad(dico, job, fact, trana, uplo, n, A, E, Q, Z, C) _solve_check(A.dtype, 'slycot.sg03ad', sep, ferr) X /= scale else: raise ValueError(f"Unexpected Lyapunov equation solver ({options['type']}).") return X
def solve_lyap_dense(A, E, B, trans=False, options=None): """Compute the solution of a Lyapunov equation. See :func:`pymor.algorithms.lyapunov.solve_lyap_dense` for a general description. This function uses `slycot.sb03md` (if `E is None`) and `slycot.sg03ad` (if `E is not None`), which are based on the Bartels-Stewart algorithm. Parameters ---------- A The operator A as a 2D |NumPy array|. E The operator E as a 2D |NumPy array| or `None`. B The operator B as a 2D |NumPy array|. trans Whether the first operator in the Lyapunov equation is transposed. options The solver options to use (see :func:`lyap_dense_solver_options`). Returns ------- X Lyapunov equation solution as a |NumPy array|. """ _solve_lyap_dense_check_args(A, E, B, trans) options = _parse_options(options, lyap_dense_solver_options(), 'slycot_bartels-stewart', None, False) if options['type'] == 'slycot_bartels-stewart': n = A.shape[0] C = -B.dot(B.T) if not trans else -B.T.dot(B) trana = 'T' if not trans else 'N' dico = 'C' job = 'B' if E is None: U = np.zeros((n, n)) X, scale, sep, ferr, _ = slycot.sb03md(n, C, A, U, dico, job=job, trana=trana) _solve_check(A.dtype, 'slycot.sb03md', sep, ferr) else: fact = 'N' uplo = 'L' Q = np.zeros((n, n)) Z = np.zeros((n, n)) _, _, _, _, X, scale, sep, ferr, _, _, _ = slycot.sg03ad(dico, job, fact, trana, uplo, n, A, E, Q, Z, C) _solve_check(A.dtype, 'slycot.sg03ad', sep, ferr) X /= scale else: raise ValueError(f"Unexpected Lyapunov equation solver ({options['type']}).") return X
def solve_lyap_dense(A, E, B, trans=False, options=None): """Compute the solution of a Lyapunov equation. See :func:`pymor.algorithms.lyapunov.solve_lyap_dense` for a general description. This function uses `scipy.linalg.solve_continuous_lyapunov`, which is a dense solver for Lyapunov equations with E=I. .. note:: If E is not `None`, the problem will be reduced to a standard continuous-time algebraic Lyapunov equation by inverting E. Parameters ---------- A The operator A as a 2D |NumPy array|. E The operator E as a 2D |NumPy array| or `None`. B The operator B as a 2D |NumPy array|. trans Whether the first operator in the Lyapunov equation is transposed. options The solver options to use (see :func:`lyap_dense_solver_options`). Returns ------- X Lyapunov equation solution as a |NumPy array|. """ _solve_lyap_dense_check_args(A, E, B, trans) options = _parse_options(options, lyap_dense_solver_options(), 'scipy', None, False) if options['type'] == 'scipy': if E is not None: A = solve(E, A) if not trans else solve(E.T, A.T).T B = solve(E, B) if not trans else solve(E.T, B.T).T if trans: A = A.T B = B.T X = solve_continuous_lyapunov(A, -B.dot(B.T)) else: raise ValueError( f"Unexpected Lyapunov equation solver ({options['type']}).") return X
def solve_lyap_dense(A, E, B, trans=False, options=None): """Compute the solution of a Lyapunov equation. See :func:`pymor.algorithms.lyapunov.solve_lyap_dense` for a general description. This function uses `scipy.linalg.solve_continuous_lyapunov`, which is a dense solver for Lyapunov equations with E=I. .. note:: If E is not `None`, the problem will be reduced to a standard continuous-time algebraic Lyapunov equation by inverting E. Parameters ---------- A The operator A as a 2D |NumPy array|. E The operator E as a 2D |NumPy array| or `None`. B The operator B as a 2D |NumPy array|. trans Whether the first operator in the Lyapunov equation is transposed. options The solver options to use (see :func:`lyap_dense_solver_options`). Returns ------- X Lyapunov equation solution as a |NumPy array|. """ _solve_lyap_dense_check_args(A, E, B, trans) options = _parse_options(options, lyap_dense_solver_options(), 'scipy', None, False) if options['type'] == 'scipy': if E is not None: A = solve(E, A) if not trans else solve(E.T, A.T).T B = solve(E, B) if not trans else solve(E.T, B.T).T if trans: A = A.T B = B.T X = solve_continuous_lyapunov(A, -B.dot(B.T)) else: raise ValueError(f"Unexpected Lyapunov equation solver ({options['type']}).") return X
def solve_lyap_dense(A, E, B, trans=False, options=None): """Compute the solution of a Lyapunov equation. See :func:`pymor.algorithms.lyapunov.solve_lyap_dense` for a general description. This function uses `pymess.glyap`. Parameters ---------- A The operator A as a 2D |NumPy array|. E The operator E as a 2D |NumPy array| or `None`. B The operator B as a 2D |NumPy array|. trans Whether the first operator in the Lyapunov equation is transposed. options The solver options to use (see :func:`lyap_dense_solver_options`). Returns ------- X Lyapunov equation solution as a |NumPy array|. """ _solve_lyap_dense_check_args(A, E, B, trans) options = _parse_options(options, lyap_lrcf_solver_options(), 'pymess_glyap', None, False) if options['type'] == 'pymess_glyap': Y = B.dot(B.T) if not trans else B.T.dot(B) op = pymess.MESS_OP_NONE if not trans else pymess.MESS_OP_TRANSPOSE X = pymess.glyap(A, E, Y, op=op)[0] X = np.asarray(X) else: raise ValueError( f'Unexpected Lyapunov equation solver ({options["type"]}).') return X
def solve_lyap_dense(A, E, B, trans=False, options=None): """Compute the solution of a Lyapunov equation. See :func:`pymor.algorithms.lyapunov.solve_lyap_dense` for a general description. This function uses `pymess.glyap`. Parameters ---------- A The operator A as a 2D |NumPy array|. E The operator E as a 2D |NumPy array| or `None`. B The operator B as a 2D |NumPy array|. trans Whether the first operator in the Lyapunov equation is transposed. options The solver options to use (see :func:`lyap_dense_solver_options`). Returns ------- X Lyapunov equation solution as a |NumPy array|. """ _solve_lyap_dense_check_args(A, E, B, trans) options = _parse_options(options, lyap_lrcf_solver_options(), 'pymess_glyap', None, False) if options['type'] == 'pymess_glyap': Y = B.dot(B.T) if not trans else B.T.dot(B) op = pymess.MESS_OP_NONE if not trans else pymess.MESS_OP_TRANSPOSE X = pymess.glyap(A, E, Y, op=op)[0] else: raise ValueError(f'Unexpected Lyapunov equation solver ({options["type"]}).') return X