Пример #1
0
    def make_key_seq(self, keys, name):
        # INTERNAL Takes as input a candidate keys input and returns a valid key sequence
        used_name = name
        check_keys = True
        used_keys = []
        if is_iterable(keys):
            if is_pandas_dataframe(keys):
                used_keys = keys.index.values
            elif has_len(keys):
                used_keys = keys
            elif is_iterator(keys):
                used_keys = list(keys)
            else:
                # TODO: make a test for this case.
                self.fatal(
                    "Cannot handle iterable var keys: {0!s} : no len() and not an iterator",
                    keys)  # pragma: no cover

        elif is_int(keys) and keys >= 0:
            # if name is str and we have a size, disable automatic names
            used_name = None if name is str else name
            used_keys = range(keys)
            check_keys = False
        else:
            self.fatal(
                "Unexpected var keys: {0!s}, expecting iterable or integer",
                keys)  # pragma: no cover

        if check_keys and len(
                used_keys
        ):  # do not check truth value of used_keys: can be a Series!
            self._checker.typecheck_key_seq(used_keys)
        return used_name, used_keys
Пример #2
0
 def generate_rows(cls, coef_mat):
     if is_pandas_dataframe(coef_mat):
         row_gen = cls.generate_df_rows(coef_mat)
     elif is_numpy_matrix(coef_mat):
         row_gen = cls.generate_np_matrix_rows(coef_mat)
     else:
         row_gen = iter(coef_mat)
     return row_gen
Пример #3
0
    def matrix_ranges(self, coef_mat, dvars, lbs, ubs):
        """
        Creates a list of range constraints
        from a matrix of coefficients, a sequence of variables, and two sequence of numbers.

        This method returns the list of range constraints built from

            L <= Ax <= U

        where A is the coefficient matrix (of size (M,N)), X is the variable sequence (size N),
        L and B are sequence of numbers (resp. the lower and upper bounds of the ranges) both with size M.


        :param coef_mat: A matrix of coefficients with M rows and N columns. This argument accepts
            either a list of lists of numbers, a `numpy` array with size (M,N), or a `scipy` sparse matrix.
        :param dvars: An ordered sequence of decision variables: accepts a Python list, `numpy` array,
            or a `pandas` series. The size of the sequence must match the number of columns in the matrix.
        :param lbs: A sequence of numbers: accepts a Python list, a `numpy` array,
            or a `pandas` series. The size of the sequence must match the number of rows in the matrix.
        :param ubs: A sequence of numbers: accepts a Python list, a `numpy` array,
            or a `pandas` series. The size of the sequence must match the number of rows in the matrix.

        :returns: A list of range constraints.

        Example::

            If A is a matrix of coefficients with 2 rows and 3 columns:

                    A = [[1, 2, 3],
                         [4, 5, 6]],
                    X = [x, y, z] where x, y, and z are decision variables (size 3), and

                    L = [101. 102], a sequence of numbers (size 2),
                    U = [201, 202]

            then::

                `mdl.range_constraints(A, X, L, U)` returns a list of two ranges
                [(101 <= x + 2y+3z <= 102), (201 <= 4x + 5y +6z <= 202)].

        Note:
            If the dimensions of the matrix and variables or of the matrix and number sequence do not match,
            an error is raised.

        """
        checker = self._checker
        if is_pandas_dataframe(coef_mat) or is_numpy_matrix(
                coef_mat) or is_scipy_sparse(coef_mat):
            nb_rows, nb_cols = coef_mat.shape
        else:
            # a sequence of sequences
            a_mat = list(coef_mat)
            nb_rows = len(a_mat)
            nb_cols = None
            try:
                shared_len = None
                for r in a_mat:
                    checker.check_ordered_sequence(r, 'matrix_constraints')
                    r_len = len(r)
                    if shared_len is None:
                        shared_len = r_len
                    elif r_len != shared_len:
                        self.fatal(
                            'All columns should have same length found  {0} != {1}'
                            .format(shared_len, r_len))
                nb_cols = shared_len if shared_len is not None else 0
            except AttributeError:
                self.fatal('All columns should have a len()')

        s_dvars = self._to_list(dvars, caller='Model.range_constraints()')
        s_lbs = self._to_list(lbs, caller='Model.range_constraints()')
        s_ubs = self._to_list(ubs, caller='Model.range_constraints()')
        # check

        checker.typecheck_var_seq(s_dvars)
        checker.typecheck_num_seq(s_lbs)
        checker.typecheck_num_seq(s_ubs)

        # ---
        # check dimensions and whether to transpose or not.
        # ---
        nb_vars = len(s_dvars)
        nb_lbs = len(s_lbs)
        nb_ubs = len(s_ubs)
        if nb_lbs != nb_rows:
            self.fatal(
                'Incorrect size for range lower bounds, expecting: {1}, got: {0},'
                .format(nb_lbs, nb_rows))
        if nb_ubs != nb_rows:
            self.fatal(
                'Incorrect size for range upper bounds, expecting: {1}, got: {0}'
                .format(nb_ubs, nb_rows))
        if nb_cols != nb_vars:
            self.fatal(
                'Incorrect number of variables, expecting: {1}, got: {0},  matrix is ({0},{1})'
                .format(nb_vars, nb_cols, nb_rows, nb_cols))

        if is_scipy_sparse(coef_mat):
            return self._aggregator._sparse_matrix_ranges(
                coef_mat, s_dvars, s_lbs, s_ubs)
        else:
            return self._aggregator._matrix_ranges(coef_mat, s_dvars, s_lbs,
                                                   s_ubs)
Пример #4
0
    def matrix_constraints(self, coef_mat, dvars, rhs, sense='le'):
        """
        Creates a list of linear constraints
        from a matrix of coefficients, a sequence of variables, and a sequence of numbers.

        This method returns the list of constraints built from

            A.X <op> B

        where A is the coefficient matrix (of size (M,N)), X is the variable sequence (size N),
        and B is the sequence of right-hand side values (of size M).

        <op> is the comparison operator that defines the sense of the constraint. By default, this generates
        a 'less-than-or-equal' constraint.

        Example:
            `Model.scal_prod_vars_triple([x, y], [z, t], [2, 3])` returns the expression `2xz + 3yt`.

        :param coef_mat: A matrix of coefficients with M rows and N columns. This argument accepts
            either a list of lists of numbers, a `numpy` array with size (M,N), or a `scipy` sparse matrix.
        :param dvars: An ordered sequence of decision variables: accepts a Python list, `numpy` array,
            or a `pandas` series. The size of the sequence must match the number of columns in the matrix.
        :param rhs: A sequence of numbers: accepts a Python list, a `numpy` array,
            or a `pandas` series. The size of the sequence must match the number of rows in the matrix.
        :param sense: A constraint sense \; accepts either a
            value of type `ComparisonType` or a string (e.g 'le', 'eq', 'ge').

        :returns: A list of linear constraints.

        Example:

            If A is a matrix of coefficients with 2 rows and 3 columns::

                    A = [[1, 2, 3],
                         [4, 5, 6]],
                    X = [x, y, z] where x, y, and z are decision variables (size 3), and

                    B = [100, 200], a sequence of numbers (size 2),

            then::

                `mdl.matrix_constraint(A, X, B, 'GE')` returns a list of two constraints
                [(x + 2y+3z <= 100), (4x + 5y +6z <= 200)].

        Note:
            If the dimensions of the matrix and variables or of the matrix and number sequence do not match,
            an error is raised.

        """
        checker = self._checker
        if is_pandas_dataframe(coef_mat) or is_numpy_matrix(
                coef_mat) or is_scipy_sparse(coef_mat):
            nb_rows, nb_cols = coef_mat.shape
        else:
            # a sequence of sequences
            a_mat = list(coef_mat)
            nb_rows = len(a_mat)
            nb_cols = None
            try:
                shared_len = None
                for r in a_mat:
                    checker.check_ordered_sequence(r, 'matrix_constraints')
                    r_len = len(r)
                    if shared_len is None:
                        shared_len = r_len
                    elif r_len != shared_len:
                        self.fatal(
                            'All columns should have same length found  {0} != {1}'
                            .format(shared_len, r_len))
                nb_cols = shared_len if shared_len is not None else 0
            except AttributeError:
                self.fatal('All columns should have a len()')

        s_dvars = self._to_list(dvars, caller='Model.matrix-constraints()')
        s_rhs = self._to_list(rhs, caller='Model.matrix-constraints()')
        # check

        checker.typecheck_var_seq(s_dvars)
        for k in s_rhs:
            checker.typecheck_num(k)

        op = ComparisonType.parse(sense)
        # ---
        # check dimensions and whether to transpose or not.
        # ---
        nb_rhs = len(s_rhs)
        nb_vars = len(s_dvars)
        if (nb_rows, nb_cols) != (nb_rhs, nb_vars):
            self.fatal(
                'Dimension error, matrix is ({0},{1}), expecting ({3}, {2})'.
                format(nb_rows, nb_cols, nb_vars, nb_rhs))

        if is_scipy_sparse(coef_mat):
            return self._aggregator._sparse_matrix_constraints(
                coef_mat, s_dvars, s_rhs, op)
        else:
            return self._aggregator._matrix_constraints(
                coef_mat, s_dvars, s_rhs, op)