Esempio n. 1
0
 def _get_bigM_dynamics(self, tol=1.e-8):
     """
     Computes all the smallMs and bigMs for the dynamics of the PWA system.
     When the system is in mode j, n_x smallMs and n_x bigMs are needed to drop the equations of motion for the mode i.
     With s number of modes, m_dynamics and M_dynamics are two lists containing s lists, each list then constains s bigM vector of size n_x.
     m_dynamics[j][i] and M_dynamics[j][i] are used to drop the equations of motion of the mode i when the system is in mode j.
     """
     self._M_dynamics = []
     self._m_dynamics = []
     for i in range(self.sys.n_sys):
         M_i = []
         m_i = []
         lhs_i = np.hstack(
             (self.sys.affine_systems[i].A, self.sys.affine_systems[i].B))
         rhs_i = self.sys.affine_systems[i].c
         for domain_j in self.sys.domains:
             M_ij = []
             m_ij = []
             for k in range(lhs_i.shape[0]):
                 sol = linear_program(-lhs_i[k, :], domain_j.lhs_min,
                                      domain_j.rhs_min)
                 M_ijk = (-sol.min + rhs_i[k])[0]
                 M_ij.append(M_ijk)
                 sol = linear_program(lhs_i[k, :], domain_j.lhs_min,
                                      domain_j.rhs_min)
                 m_ijk = (sol.min + rhs_i[k])[0]
                 m_ij.append(m_ijk)
             M_ij = np.reshape(M_ij, (len(M_ij), 1))
             m_ij = np.reshape(m_ij, (len(m_ij), 1))
             M_i.append(M_ij)
             m_i.append(np.array(m_ij))
         self._M_dynamics.append(M_i)
         self._m_dynamics.append(m_i)
     return
Esempio n. 2
0
 def compute_big_M_dynamics(self):
     self.big_M_dynamics = []
     self.small_m_dynamics = []
     for i in range(self.sys.n_sys):
         big_M_i = []
         small_m_i = []
         lhs_i = np.hstack((self.sys.affine_systems[i].A, self.sys.affine_systems[i].B))
         rhs_i = self.sys.affine_systems[i].c
         for j in range(self.sys.n_sys):
             big_M_ij = []
             small_m_ij = []
             lhs_j = linalg.block_diag(self.sys.state_domains[j].lhs_min, self.sys.input_domains[j].lhs_min)
             rhs_j = np.vstack((self.sys.state_domains[j].rhs_min, self.sys.input_domains[j].rhs_min))
             for k in range(lhs_i.shape[0]):
                 big_M_ijk = - linear_program(-lhs_i[k,:], lhs_j, rhs_j)[1] + rhs_i[k]
                 big_M_ij.append(big_M_ijk[0])
                 small_m_ijk = linear_program(lhs_i[k,:], lhs_j, rhs_j)[1] + rhs_i[k]
                 small_m_ij.append(small_m_ijk[0])
             big_M_ij = np.reshape(big_M_ij, (len(big_M_ij), 1))
             small_m_ij = np.reshape(small_m_ij, (len(small_m_ij), 1))
             big_M_i.append(big_M_ij)
             small_m_i.append(np.array(small_m_ij))
         self.big_M_dynamics.append(big_M_i)
         self.small_m_dynamics.append(small_m_i)
     return
Esempio n. 3
0
 def solve(self, x0, u_length=None):
     x0 = np.reshape(x0, (x0.shape[0], 1))
     sol = linear_program(self.f, self.A, self.B.dot(x0) + self.c)
     u_star = sol.argmin[0:self.F_u.shape[1]]
     if u_length is not None:
         if not float(u_star.shape[0] / u_length).is_integer():
             raise ValueError('Uncoherent dimension of the input u_length.')
         u_star = [
             u_star[i * u_length:(i + 1) * u_length, :]
             for i in range(u_star.shape[0] / u_length)
         ]
     return u_star, sol.min
Esempio n. 4
0
def moas(A, X):
    """
    Returns the maximum output admissible set (see Gilbert, Tan - Linear Systems with State and Control Constraints, The Theory and Application of Maximal Output Admissible Sets) for a non-actuated linear system with state constraints (the output vector is supposed to be the entire state of the system, i.e. y=x and C=I).

    INPUTS:
        A: state transition matrix
        X: constraint polytope X.lhs * x <= X.rhs

    OUTPUTS:
        moas: maximum output admissible set (instatiated as a polytope)
    """

    # ensure that the system is stable (otherwise the algorithm doesn't converge)
    eig_max = np.max(np.absolute(np.linalg.eig(A)[0]))
    if eig_max > 1:
        raise ValueError('Cannot compute MOAS for unstable systems')

    # Gilber and Tan algorithm
    [n_constraints, n_variables] = X.lhs_min.shape
    t = 0
    convergence = False
    while convergence == False:

        # cost function gradients for all i
        J = X.lhs_min.dot(np.linalg.matrix_power(A, t + 1))

        # constraints to each LP
        cons_lhs = np.vstack([
            X.lhs_min.dot(np.linalg.matrix_power(A, k))
            for k in range(0, t + 1)
        ])
        cons_rhs = np.vstack([X.rhs_min for k in range(0, t + 1)])

        # list of all minima
        J_sol = []
        for i in range(0, n_constraints):
            J_sol_i = linear_program(np.reshape(-J[i, :], (n_variables, 1)),
                                     cons_lhs, cons_rhs)[1]
            J_sol.append(-J_sol_i - X.rhs_min[i])

        # convergence check
        if np.max(J_sol) < 0:
            convergence = True
        else:
            t += 1

    # define polytope
    moas = Polytope(cons_lhs, cons_rhs)
    moas.assemble()

    return moas
Esempio n. 5
0
 def compute_big_M_domains(self):
     self.big_M_domains = []
     for i in range(self.sys.n_sys):
         big_M_i = []
         lhs_i = linalg.block_diag(self.sys.state_domains[i].lhs_min, self.sys.input_domains[i].lhs_min)
         rhs_i = np.vstack((self.sys.state_domains[i].rhs_min, self.sys.input_domains[i].rhs_min))
         for j in range(self.sys.n_sys):
             big_M_ij = []
             if i != j:
                 lhs_j = linalg.block_diag(self.sys.state_domains[j].lhs_min, self.sys.input_domains[j].lhs_min)
                 rhs_j = np.vstack((self.sys.state_domains[j].rhs_min, self.sys.input_domains[j].rhs_min))
                 for k in range(lhs_i.shape[0]):
                     big_M_ijk = - linear_program(-lhs_i[k,:], lhs_j, rhs_j)[1] - rhs_i[k]
                     big_M_ij.append(big_M_ijk[0])
             big_M_ij = np.reshape(big_M_ij, (len(big_M_ij), 1))
             big_M_i.append(big_M_ij)
         self.big_M_domains.append(big_M_i)
     return
Esempio n. 6
0
 def _get_bigM_domains(self, tol=1.e-8):
     """
     Computes all the bigMs for the domains of the PWA system.
     When the system is in mode j, n_i bigMs are needed to drop each one the n_i inequalities of the polytopic domain for the mode i.
     With s number of modes, M_domains is a list containing s lists, each list then constains s bigM vector of size n_i.
     M_domains[j][i] is used to drop the inequalities of the domain i when the system is in mode j.
     """
     self._M_domains = []
     for i, domain_i in enumerate(self.sys.domains):
         M_i = []
         for j, domain_j in enumerate(self.sys.domains):
             M_ij = []
             if i != j:
                 for k in range(domain_i.lhs_min.shape[0]):
                     sol = linear_program(-domain_i.lhs_min[k, :],
                                          domain_j.lhs_min,
                                          domain_j.rhs_min)
                     M_ijk = (-sol.min - domain_i.rhs_min[k])[0]
                     M_ij.append(M_ijk)
             M_ij = np.reshape(M_ij, (len(M_ij), 1))
             M_i.append(M_ij)
         self._M_domains.append(M_i)
     return
Esempio n. 7
0
 def solve(self, x0):
     x0 = np.reshape(x0, (x0.shape[0], 1))
     u_star, V_star =  linear_program(self.f, self.A, self.B.dot(x0)+self.c)
     u_star = u_star[0:self.F_u.shape[1]]
     return u_star, V_star