예제 #1
0
def bb_dare(A, B, Q, R):
    """Solve Riccati equation for discrete time systems

    Usage
    =====
    [K, S, E] = care(A, B, Q, R)

    Inputs
    ------
    A, B: 2-d arrays with dynamics and input matrices
    sys: linear I/O system 
    Q, R: 2-d array with state and input weight matrices

    Outputs
    -------
    X: solution of the Riccati eq.
    """

    # Check dimensions for consistency
    nstates = B.shape[0]
    ninputs = B.shape[1]
    if (A.shape[0] != nstates or A.shape[1] != nstates):
        raise ControlDimension("inconsistent system dimensions")

    elif (Q.shape[0] != nstates or Q.shape[1] != nstates
          or R.shape[0] != ninputs or R.shape[1] != ninputs):
        raise ControlDimension("incorrect weighting matrix dimensions")

    X,rcond,w,S,T = \
        sb02od(nstates, ninputs, A, B, Q, R, 'D')

    return X
예제 #2
0
def kalman(A, B, C, Q, R):
    """Solves for the steady state kalman gain and covariance matricies.

    Args:
      A, B, C: SS matricies.
      Q: The model uncertantity
      R: The measurement uncertainty

    Returns:
      KalmanGain, Covariance.
  """
    I = numpy.matrix(numpy.eye(Q.shape[0]))
    Z = numpy.matrix(numpy.zeros(Q.shape[0]))
    n = A.shape[0]
    m = C.shape[0]

    controllability_rank = numpy.linalg.matrix_rank(ctrb(A.T, C.T))
    if controllability_rank != n:
        glog.warning('Observability of %d != %d, unobservable state',
                     controllability_rank, n)

    # Compute the steady state covariance matrix.
    P_prior, rcond, w, S, T = slycot.sb02od(n=n,
                                            m=m,
                                            A=A.T,
                                            B=C.T,
                                            Q=Q,
                                            R=R,
                                            dico='D')
    S = C * P_prior * C.T + R
    K = numpy.linalg.lstsq(S.T, (P_prior * C.T).T)[0].T
    P = (I - K * C) * P_prior

    return K, P
def dare(A,B,Q,R):
    """Solve Riccati equation for discrete time systems

    Usage
    =====
    [K, S, E] = care(A, B, Q, R)

    Inputs
    ------
    A, B: 2-d arrays with dynamics and input matrices
    sys: linear I/O system 
    Q, R: 2-d array with state and input weight matrices

    Outputs
    -------
    X: solution of the Riccati eq.
    """

    # Check dimensions for consistency
    nstates = B.shape[0];
    ninputs = B.shape[1];
    if (A.shape[0] != nstates or A.shape[1] != nstates):
        raise ControlDimension("inconsistent system dimensions")

    elif (Q.shape[0] != nstates or Q.shape[1] != nstates or
          R.shape[0] != ninputs or R.shape[1] != ninputs) :
        raise ControlDimension("incorrect weighting matrix dimensions")

    X,rcond,w,S,T = \
        sb02od(nstates, ninputs, A, B, Q, R, 'D');

    return X
예제 #4
0
def kalman(A, B, C, Q, R):
  """Solves for the steady state kalman gain and covariance matricies.

    Args:
      A, B, C: SS matricies.
      Q: The model uncertantity
      R: The measurement uncertainty

    Returns:
      KalmanGain, Covariance.
  """
  I = numpy.matrix(numpy.eye(Q.shape[0]))
  Z = numpy.matrix(numpy.zeros(Q.shape[0]))
  n = A.shape[0]
  m = C.shape[0]

  controllability_rank = numpy.linalg.matrix_rank(ctrb(A.T, C.T))
  if controllability_rank != n:
    glog.warning('Observability of %d != %d, unobservable state',
                 controllability_rank, n)

  # Compute the steady state covariance matrix.
  P_prior, rcond, w, S, T = slycot.sb02od(n=n, m=m, A=A.T, B=C.T, Q=Q, R=R, dico='D')
  S = C * P_prior * C.T + R
  K = numpy.linalg.lstsq(S.T, (P_prior * C.T).T)[0].T
  P = (I - K * C) * P_prior

  return K, P
예제 #5
0
파일: examples.py 프로젝트: repagh/Slycot
def sb02od_example():
    from numpy import zeros, shape, dot, ones
    A = array([[0, 1], [0, 0]])
    B = array([[0], [1]])
    C = array([[1, 0], [0, 1], [0, 0]])
    Q = dot(C.T, C)
    R = ones((1, 1))
    out = slycot.sb02od(2, 1, A, B, Q, R, 'C')
    print('--- Example for sb02od ...')
    print('The solution X is')
    print(out[0])
    print('rcond =', out[1])
예제 #6
0
 def dlqr(A, B, Q, R):
   """Solves for the optimal lqr controller.
 
     x(n+1) = A * x(n) + B * u(n)
     J = sum(0, inf, x.T * Q * x + u.T * R * u)
   """
 
   # P = (A.T * P * A) - (A.T * P * B * numpy.linalg.inv(R + B.T * P *B) * (A.T * P.T * B).T + Q
   P, rcond, w, S, T = slycot.sb02od(n=A.shape[0],m=B.shape[1],A=A,B=B,Q=Q,R=R,dico='D')
 
   F = numpy.linalg.inv(R + B.T * P *B) * B.T * P * A
   return F
예제 #7
0
def dlqr(A, B, Q, R):
  """Solves for the optimal lqr controller.

    x(n+1) = A * x(n) + B * u(n)
    J = sum(0, inf, x.T * Q * x + u.T * R * u)
  """

  # P = (A.T * P * A) - (A.T * P * B * numpy.linalg.inv(R + B.T * P *B) * (A.T * P.T * B).T + Q

  P, rcond, w, S, T = slycot.sb02od(A.shape[0], B.shape[1], A, B, Q, R, 'D')

  F = numpy.linalg.inv(R + B.T * P *B) * B.T * P * A
  return F
예제 #8
0
파일: examples.py 프로젝트: painyeph/Slycot
def sb02od_example():
    from numpy import zeros, shape, dot, ones
    A = array([ [0, 1],
                [0, 0]])
    B = array([ [0],
                [1]])
    C = array([ [1, 0],
                [0, 1],
                [0, 0]])
    Q = dot(C.T,C)
    R = ones((1,1))
    out = slycot.sb02od(2,1,A,B,Q,R,'C')
    print('--- Example for sb02od ...')
    print('The solution X is')
    print(out[0])
    print('rcond =', out[1])
예제 #9
0
 def solve_slycot(self):
     """Directly solves the DARE using the SLICOT library's SB02MD 
     implementation of a generalized Schur vectors method.  If the Slycot
     package is unavailable, a RuntimeError will be thrown.  This solver
     should be considerably more robust than the pure-Python implementation
     in solve_direct().  Only minimal shape checking is performed.
     
     More on SLICOT: http://www.slicot.org/
 
     Python Interface (Slycot): https://github.com/avventi/Slycot
     """
 
     if self.a.shape[0] != self.a.shape[1]:
         raise ValueError('input "a" must be a square matrix')
 
     try:
         self.solution,rcond,w,s,t = slycot.sb02od(self.a.shape[1],self.b.shape[1],\
                                                   self.a, self.b, self.q, self.r,'D')
     except NameError:
         raise RuntimeError('SLICOT not available')
     
     return self.solution
예제 #10
0
파일: slycot.py 프로젝트: prklVIP/pymor
    def solve_ricc_lrcf(A, E, B, C, R=None, S=None, trans=False, options=None):
        """Compute an approximate low-rank solution of a Riccati equation.

        See :func:`pymor.algorithms.riccati.solve_ricc_lrcf` for a
        general description.

        This function uses `slycot.sb02md` (if E and S are `None`),
        `slycot.sb02od` (if E is `None` and S is not `None`) and
        `slycot.sg03ad` (if E is not `None`), which are dense solvers.
        Therefore, we assume all |Operators| and |VectorArrays| can be
        converted to |NumPy arrays| using
        :func:`~pymor.algorithms.to_matrix.to_matrix` and
        :func:`~pymor.vectorarrays.interfaces.VectorArrayInterface.to_numpy`.

        Parameters
        ----------
        A
            The |Operator| A.
        E
            The |Operator| E or `None`.
        B
            The operator B as a |VectorArray| from `A.source`.
        C
            The operator C as a |VectorArray| from `A.source`.
        R
            The operator R as a 2D |NumPy array| or `None`.
        S
            The operator S as a |VectorArray| from `A.source` or `None`.
        trans
            Whether the first |Operator| in the Riccati equation is
            transposed.
        options
            The solver options to use (see
            :func:`ricc_lrcf_solver_options`).

        Returns
        -------
        Z
            Low-rank Cholesky factor of the Riccati equation solution,
            |VectorArray| from `A.source`.
        """

        _solve_ricc_check_args(A, E, B, C, R, S, trans)
        options = _parse_options(options, ricc_lrcf_solver_options(), 'slycot',
                                 None, False)
        if options['type'] != 'slycot':
            raise ValueError(
                f"Unexpected Riccati equation solver ({options['type']}).")

        A_source = A.source
        A = to_matrix(A, format='dense')
        E = to_matrix(E, format='dense') if E else None
        B = B.to_numpy().T
        C = C.to_numpy()
        S = S.to_numpy().T if S else None

        n = A.shape[0]
        dico = 'C'

        if E is None:
            if S is None:
                if not trans:
                    A = A.T
                    G = C.T.dot(C) if R is None else slycot.sb02mt(
                        n, C.shape[0], C.T, R)[-1]
                else:
                    G = B.dot(B.T) if R is None else slycot.sb02mt(
                        n, B.shape[1], B, R)[-1]
                Q = B.dot(B.T) if not trans else C.T.dot(C)
                X, rcond = slycot.sb02md(n, A, G, Q, dico)[:2]
                _ricc_rcond_check('slycot.sb02md', rcond)
            else:
                m = C.shape[0] if not trans else B.shape[1]
                p = B.shape[1] if not trans else C.shape[0]
                if R is None:
                    R = np.eye(m)
                if not trans:
                    A = A.T
                    B, C = C.T, B.T
                X, rcond = slycot.sb02od(n,
                                         m,
                                         A,
                                         B,
                                         C,
                                         R,
                                         dico,
                                         p=p,
                                         L=S,
                                         fact='C')[:2]
                _ricc_rcond_check('slycot.sb02od', rcond)
        else:
            jobb = 'B'
            fact = 'C'
            uplo = 'U'
            jobl = 'Z' if S is None else 'N'
            scal = 'N'
            sort = 'S'
            acc = 'R'
            m = C.shape[0] if not trans else B.shape[1]
            p = B.shape[1] if not trans else C.shape[0]
            if R is None:
                R = np.eye(m)
            if S is None:
                S = np.empty((n, m))
            if not trans:
                A = A.T
                E = E.T
                B, C = C.T, B.T
            out = slycot.sg02ad(dico, jobb, fact, uplo, jobl, scal, sort, acc,
                                n, m, p, A, E, B, C, R, S)
            X = out[1]
            rcond = out[0]
            _ricc_rcond_check('slycot.sg02ad', rcond)

        return A_source.from_numpy(_chol(X).T)
예제 #11
0
파일: slycot.py 프로젝트: pymor/pymor
    def solve_ricc_lrcf(A, E, B, C, R=None, S=None, trans=False, options=None):
        """Compute an approximate low-rank solution of a Riccati equation.

        See :func:`pymor.algorithms.riccati.solve_ricc_lrcf` for a
        general description.

        This function uses `slycot.sb02md` (if E and S are `None`),
        `slycot.sb02od` (if E is `None` and S is not `None`) and
        `slycot.sg03ad` (if E is not `None`), which are dense solvers.
        Therefore, we assume all |Operators| and |VectorArrays| can be
        converted to |NumPy arrays| using
        :func:`~pymor.algorithms.to_matrix.to_matrix` and
        :func:`~pymor.vectorarrays.interfaces.VectorArrayInterface.to_numpy`.

        Parameters
        ----------
        A
            The |Operator| A.
        E
            The |Operator| E or `None`.
        B
            The operator B as a |VectorArray| from `A.source`.
        C
            The operator C as a |VectorArray| from `A.source`.
        R
            The operator R as a 2D |NumPy array| or `None`.
        S
            The operator S as a |VectorArray| from `A.source` or `None`.
        trans
            Whether the first |Operator| in the Riccati equation is
            transposed.
        options
            The solver options to use (see
            :func:`ricc_lrcf_solver_options`).

        Returns
        -------
        Z
            Low-rank Cholesky factor of the Riccati equation solution,
            |VectorArray| from `A.source`.
        """

        _solve_ricc_check_args(A, E, B, C, R, S, trans)
        options = _parse_options(options, ricc_lrcf_solver_options(), 'slycot', None, False)
        if options['type'] != 'slycot':
            raise ValueError(f"Unexpected Riccati equation solver ({options['type']}).")

        A_source = A.source
        A = to_matrix(A, format='dense')
        E = to_matrix(E, format='dense') if E else None
        B = B.to_numpy().T
        C = C.to_numpy()
        S = S.to_numpy().T if S else None

        n = A.shape[0]
        dico = 'C'

        if E is None:
            if S is None:
                if not trans:
                    A = A.T
                    G = C.T.dot(C) if R is None else slycot.sb02mt(n, C.shape[0], C.T, R)[-1]
                else:
                    G = B.dot(B.T) if R is None else slycot.sb02mt(n, B.shape[1], B, R)[-1]
                Q = B.dot(B.T) if not trans else C.T.dot(C)
                X, rcond = slycot.sb02md(n, A, G, Q, dico)[:2]
                _ricc_rcond_check('slycot.sb02md', rcond)
            else:
                m = C.shape[0] if not trans else B.shape[1]
                p = B.shape[1] if not trans else C.shape[0]
                if R is None:
                    R = np.eye(m)
                if not trans:
                    A = A.T
                    B, C = C.T, B.T
                X, rcond = slycot.sb02od(n, m, A, B, C, R, dico, p=p, L=S, fact='C')[:2]
                _ricc_rcond_check('slycot.sb02od', rcond)
        else:
            jobb = 'B'
            fact = 'C'
            uplo = 'U'
            jobl = 'Z' if S is None else 'N'
            scal = 'N'
            sort = 'S'
            acc = 'R'
            m = C.shape[0] if not trans else B.shape[1]
            p = B.shape[1] if not trans else C.shape[0]
            if R is None:
                R = np.eye(m)
            if S is None:
                S = np.empty((n, m))
            if not trans:
                A = A.T
                E = E.T
                B, C = C.T, B.T
            out = slycot.sg02ad(dico, jobb, fact, uplo, jobl, scal, sort, acc,
                                n, m, p,
                                A, E, B, C, R, S)
            X = out[1]
            rcond = out[0]
            _ricc_rcond_check('slycot.sg02ad', rcond)

        return A_source.from_numpy(_chol(X).T)
예제 #12
0
#Prepare the inputs for calling Slicot
C = matrix( C )
Q = matrix( Q )
F = matrix( F )
D = matrix( D )
E = matrix( E )

QFT = array( Q*(F.T) )
	
#Solve the ARME
#Note: The definitions of n and m are reversed in this function
# Slycot solves: X = A'XA - (L + A'XB)(R + B'XB)^-1 (L+A'XB)' + Q
# While GRP solves M = M + C - ( MQF' - D )(E + FQ'MQF )^-1(MQF' - D)'
# Arguments (n, m, A, B, Q, R, dico, [p, L, fact, uplo, sort, tol, ldwork])
M, rcond, w, S, T = slycot.sb02od( m, n, eye(m), QFT, C, E, dico="D", L= -D )

#	Compute the error to ensure that slycot solved the problem correctly
X = inv( E + F * ( Q.T ) * M * Q * ( F.T ) )
Y = M * Q * ( F.T ) - D
Mnew = M + C - Y * X * ( Y.T )

maxerror = 0.0
for i in range(0, m):
	for j in range(0, m):
		error = abs( ( M[i,j] - Mnew[i,j] ) / M[i,j] )
		if error > maxerror:
			maxerror = error

if maxerror > data["tolerance"]:
	sys.stderr.write("Warning: ARME tolerance not met! Max rel error %s\n" % maxerror)