Example #1
0
    def _check_inputs(self, b_csr, u_constraints_csr, u_constraints_rhs,
                      allow_constants):
        'Run assersion checks on input matrices'

        assert u_constraints_csr.shape[0] == u_constraints_rhs.shape[
            0], "u_constraints rows shoud match rhs len"
        assert u_constraints_csr.shape[1] == b_csr.shape[
            1], "u_constraints cols should match b.width"

        assert b_csr.shape[0] == self.a_csr.shape[0], \
                "B-mat shape {} incompatible with A-mat shape {}".format(b_csr.shape, self.a_csr.shape)

        # make sure the input constraints are feasible
        assert lputil.is_feasible(
            u_constraints_csr,
            u_constraints_rhs), "input constraints were infeasible"

        #make sure there are not inputs that are fixed to a constant. This is for efficiency reasons. It is better
        #to add an affine variable to the a matrix and including this as part of A.

        num_inputs = b_csr.shape[1]

        for i in range(num_inputs):
            # does this input only affect a single variable? --> does b_col have a single nonzero?
            b_col = b_csr[:, i].toarray()
            nonzeros = sum([1 if x != 0 else 0 for x in b_col])

            if nonzeros != 1:
                continue

            # check if is there a fixed lower and upper bound for this input
            lb_row = np.array([0 if n != i else 1 for n in range(num_inputs)],
                              dtype=float)
            ub_row = np.array([0 if n != i else -1 for n in range(num_inputs)],
                              dtype=float)
            lb = ub = None

            for row, rhs in zip(u_constraints_csr, u_constraints_rhs):
                row = row.toarray()
                if np.array_equiv(lb_row, row):
                    lb = rhs
                elif np.array_equiv(ub_row, row):
                    ub = -rhs

            if ub is None or lb is None:
                continue

            if abs(ub - lb) < 1e-9:
                msg = ("Time-varying input #{} is fixed to {}. This is a (very) inefficient " + \
                    "way encode affine terms. Instead, introduce a fixed affine variable in the A matrix with a' = 0" + \
                    " and a(0) = 1, and refer to that variable in any differential equations that use affine " + \
                    "terms. This can be made a warning by using 'allow_constants=True' in set_inputs().").format(i, lb)

                if not allow_constants:
                    raise RuntimeError(msg)
                else:
                    print("Warning: " + msg)
Example #2
0
    def set_invariant(self, constraints_csr, constraints_rhs):
        'sets the invariant'

        assert self.a_csr is not None, "A matrix must be set first"

        if not isinstance(constraints_csr, csr_matrix):
            constraints_csr = csr_matrix(constraints_csr, dtype=float)

        if not isinstance(constraints_rhs, np.ndarray):
            constraints_rhs = np.array(constraints_rhs, dtype=float)

        constraints_rhs.shape = (len(constraints_rhs),
                                 )  # flatten rhs into a 1-d array
        assert constraints_csr.shape[1] == self.a_csr.shape[0], \
            "width of invaraiant constraints({}) must equal A matrix size({})".format( \
            constraints_csr.shape[1], self.a_csr.shape[0])
        assert constraints_csr.shape[0] == len(constraints_rhs)

        assert lputil.is_feasible(
            constraints_csr,
            constraints_rhs), "invariant constraints were infeasible"

        # for efficiency in checking, the invariant is split into a list of individual constraints
        for row, rhs in enumerate(constraints_rhs):
            inds = []
            data = []
            indptr = [0]

            for i in range(constraints_csr.indptr[row],
                           constraints_csr.indptr[row + 1]):
                column = constraints_csr.indices[i]
                d = constraints_csr.data[i]

                inds.append(column)
                data.append(d)

            indptr.append(len(data))

            constraint_vec = csr_matrix((data, inds, indptr),
                                        dtype=float,
                                        shape=(1, constraints_csr.shape[1]))

            self.inv_list.append(LinearConstraint(constraint_vec, rhs))
Example #3
0
    def set_guard(self, guard_csr, guard_rhs):
        '''set the guard'''
        
        if not isinstance(guard_csr, csr_matrix):
            guard_csr = csr_matrix(guard_csr, dtype=float)
            
        if not isinstance(guard_rhs, np.ndarray):
            guard_rhs = np.array(guard_rhs, dtype=float)
        
        assert self.from_mode.a_csr is not None, "A-matrix not assigned in predecessor mode {}".format(self.from_mode)

        if guard_csr.shape[0] > 0:
            assert guard_csr.shape[1] == self.from_mode.a_csr.shape[0], "guard matrix expected {} columns, got {}" \
                                                          .format(self.from_mode.a_csr.shape[0], guard_csr.shape[1])

        assert lputil.is_feasible(guard_csr, guard_rhs), "guard constraints were infeasible"

        guard_rhs.shape = (len(guard_rhs), ) # flatten into a 1-d array
        assert guard_rhs.shape[0] == guard_csr.shape[0]

        self.guard_csr = guard_csr
        self.guard_rhs = guard_rhs
Example #4
0
    def set_reset(self,
                  reset_csr=None,
                  reset_minkowski_csr=None,
                  reset_minkowski_constraints_csr=None,
                  reset_minkowski_constraints_rhs=None):
        '''resets are of the form x' = Rx + My, Cy <= rhs, where y are fresh variables
        the reset_minowski variables can be None if no new variables are needed. If unassigned, the identity
        reset is assumed
 
        x' are the new variables
        x are the old variables       
        reset_csr is R
        reset_minkowski_csr is M
        reset_minkowski_constraints_csr is C
        reset_minkowski_constraints_rhs is rhs
        '''

        assert self.from_mode.a_csr is not None, "A matrix not assigned in predecessor mode {}".format(
            self.from_mode)

        to_mode_csr = self.to_mode.a_csr

        # reset to an error mode
        if to_mode_csr is None:
            to_mode_csr = self.from_mode.a_csr

        if reset_csr is None:
            assert self.from_mode.a_csr.shape[0] == to_mode_csr.shape[
                0], "identity reset but num dims changes"
            reset_csr = sp.sparse.identity(self.from_mode.a_csr.shape[0],
                                           dtype=float,
                                           format='csr')

        if not isinstance(reset_csr, csr_matrix):
            reset_csr = csr_matrix(reset_csr, dtype=float)

        if reset_minkowski_csr is not None and not isinstance(
                reset_minkowski_csr, csr_matrix):
            reset_minkowski_csr = csr_matrix(reset_minkowski_csr, dtype=float)

        if reset_minkowski_constraints_csr is not None and not isinstance(
                reset_minkowski_constraints_csr, csr_matrix):
            reset_minkowski_constraints_csr = csr_matrix(
                reset_minkowski_constraints_csr, dtype=float)

        if reset_minkowski_constraints_rhs is not None and not isinstance(
                reset_minkowski_constraints_rhs, np.ndarray):
            reset_minkowski_constraints_rhs = np.array(
                reset_minkowski_constraints_rhs, dtype=float)

        assert reset_csr.shape[1] == self.from_mode.a_csr.shape[
            0], "reset matrix expected {} columns, got {}".format(
                self.from_mode.a_csr.shape[0], reset_csr.shape[1])
        assert reset_csr.shape[0] == to_mode_csr.shape[
            0], "reset matrix expected {} rows, got {}".format(
                to_mode_csr.shape[0], reset_csr.shape[0])

        if reset_minkowski_constraints_rhs is not None:
            assert len(reset_minkowski_constraints_rhs.shape) == 1
            assert reset_minkowski_constraints_csr is not None
            assert reset_minkowski_constraints_csr.shape[0] == len(
                reset_minkowski_constraints_rhs)

            new_vars = reset_minkowski_constraints_csr.shape[1]

            if reset_minkowski_csr is None:
                reset_minkowski_csr = sp.sparse.identity(new_vars,
                                                         dtype=float,
                                                         format='csr')

            assert isinstance(reset_minkowski_csr, csr_matrix)
            assert reset_minkowski_csr.shape[0] == to_mode_csr.shape[0]
            assert reset_minkowski_csr.shape[1] == new_vars, \
                "expected num reset_minkowski columns({}) to match reset_minkowski_constraints columns({})".format( \
                reset_minkowski_csr.shape[1], new_vars)

            assert lputil.is_feasible(reset_minkowski_constraints_csr, reset_minkowski_constraints_rhs), \
                "reset minkowski variable constraints were infeasible"

        self.reset_csr = reset_csr
        self.reset_minkowski_csr = reset_minkowski_csr
        self.reset_minkowski_constraints_csr = reset_minkowski_constraints_csr
        self.reset_minkowski_constraints_rhs = reset_minkowski_constraints_rhs