Example #1
0
    def test_primal_and_dual_infeasible_problem(self):

        self.n = 2
        self.m = 4
        self.P = sparse.csc_matrix((2, 2))
        self.q = np.array([-1., -1.])
        self.A = sparse.csc_matrix([[1., -1.], [-1., 1.], [1., 0.], [0., 1.]])
        self.l = np.array([1., 1., 0., 0.])
        self.u = np.inf * np.ones(self.m)

        self.model = osqp.OSQP()
        self.model.setup(P=self.P, q=self.q, A=self.A, l=self.l, u=self.u,
                         **self.opts)

        # Warm start to avoid infeasibility detection at first step
        x0 = 25.*np.ones(self.n)
        y0 = -2.*np.ones(self.m)
        self.model.warm_start(x=x0, y=y0)

        # Solve
        res = self.model.solve()

        # Assert close
        self.assertIn(res.info.status_val, [constant('OSQP_PRIMAL_INFEASIBLE'),
                                            constant('OSQP_DUAL_INFEASIBLE')])
Example #2
0
    def test_primal_and_dual_infeasible_problem(self):

        self.n = 2
        self.m = 4
        self.P = sparse.csc_matrix((2, 2))
        self.q = np.array([-1., -1.])
        self.A = sparse.csc_matrix([[1., -1.], [-1., 1.], [1., 0.], [0., 1.]])
        self.l = np.array([1., 1., 0., 0.])
        self.u = np.inf * np.ones(self.m)

        self.model = osqp.OSQP()
        self.model.setup(P=self.P,
                         q=self.q,
                         A=self.A,
                         l=self.l,
                         u=self.u,
                         **self.opts)

        res = self.model.solve()

        # Assert close
        self.assertIn(res.info.status_val, [
            constant('OSQP_PRIMAL_INFEASIBLE'),
            constant('OSQP_DUAL_INFEASIBLE')
        ])
Example #3
0
    def test_update_time_limit(self):
        res = self.model.solve()
        self.assertEqual(res.info.status_val,
                         constant('OSQP_SOLVED'))

        # Ensure the solver will time out
        self.model.update_settings(time_limit=1e-6, verbose=True, max_iter=2000000000,
                                   eps_abs=1e-20, eps_rel=1e-20,
                                   check_termination=0)

        res = self.model.solve()
        self.assertEqual(res.info.status_val,
                         constant('OSQP_TIME_LIMIT_REACHED'))
Example #4
0
    def test_update_max_iter(self):
        self.model.update_settings(max_iter=80)
        res = self.model.solve()

        # Assert max iter reached
        self.assertEqual(res.info.status_val,
                         constant('OSQP_MAX_ITER_REACHED'))
Example #5
0
def linsys_solver_str_to_int(settings):
    linsys_solver_str = settings.pop('linsys_solver', '')
    if not isinstance(linsys_solver_str, str):
        raise TypeError("Setting linsys_solver " +
                        "is required to be a string.")
    linsys_solver_str = linsys_solver_str.lower()
    if linsys_solver_str == 'qdldl':
        settings['linsys_solver'] = _osqp.constant('QDLDL_SOLVER')
    elif linsys_solver_str == 'mkl pardiso':
        settings['linsys_solver'] = _osqp.constant('MKL_PARDISO_SOLVER')
    # Default solver: QDLDL
    elif linsys_solver_str == '':
        settings['linsys_solver'] = _osqp.constant('QDLDL_SOLVER')
    else:  # default solver: QDLDL
        warn("Linear system solver not recognized. " +
             "Using default solver QDLDL.")
        settings['linsys_solver'] = _osqp.constant('QDLDL_SOLVER')
    return settings
    def test_non_convex_big_sigma(self):
        # Setup workspace with new sigma
        opts = {'verbose': False, 'sigma': 5}
        self.model.setup(P=self.P,
                         q=self.q,
                         A=self.A,
                         l=self.l,
                         u=self.u,
                         **opts)

        # Solve problem
        res = self.model.solve()

        # Assert close
        self.assertEqual(res.info.status_val, constant('OSQP_NON_CVX'))
        nptest.assert_approx_equal(res.info.obj_val, np.nan)
Example #7
0
    def test_dual_infeasible_qp(self):

        # Dual infeasible example
        self.P = sparse.diags([4., 0.], format='csc')
        self.q = np.array([0, 2])
        self.A = sparse.csc_matrix([[1., 1.], [-1., 1.]])
        self.l = np.array([-np.inf, -np.inf])
        self.u = np.array([2., 3.])

        self.model = osqp.OSQP()
        self.model.setup(P=self.P, q=self.q, A=self.A, l=self.l, u=self.u,
                         **self.opts)

        # Solve problem with OSQP
        res = self.model.solve()

        # Assert close
        self.assertEqual(res.info.status_val,
                         constant('OSQP_DUAL_INFEASIBLE'))
Example #8
0
    def test_dual_infeasible_lp(self):

        # Dual infeasible example
        self.P = sparse.csc_matrix((2, 2))
        self.q = np.array([2, -1])
        self.A = sparse.eye(2, format='csc')
        self.l = np.array([0., 0.])
        self.u = np.array([np.inf, np.inf])

        self.model = osqp.OSQP()
        self.model.setup(P=self.P, q=self.q, A=self.A, l=self.l, u=self.u,
                         **self.opts)

        # Solve problem with OSQP
        res = self.model.solve()

        # Assert close
        self.assertEqual(res.info.status_val,
                         constant('OSQP_DUAL_INFEASIBLE'))
Example #9
0
    def test_primal_infeasible_problem(self):

        # Simple QP problem
        sp.random.seed(4)

        self.n = 50
        self.m = 500
        # Generate random Matrices
        Pt = np.random.rand(self.n, self.n)
        self.P = sparse.triu(Pt.T.dot(Pt), format='csc')
        self.q = np.random.rand(self.n)
        self.A = sparse.random(self.m, self.n).tolil()  # Lil for efficiency
        self.u = 3 + np.random.randn(self.m)
        self.l = -3 + np.random.randn(self.m)

        # Make random problem primal infeasible
        self.A[int(self.n / 2), :] = self.A[int(self.n / 2) + 1, :]
        self.l[int(self.n /
                   2)] = self.u[int(self.n / 2) + 1] + 10 * np.random.rand()
        self.u[int(self.n / 2)] = self.l[int(self.n / 2)] + 0.5

        # Convert A to csc
        self.A = self.A.tocsc()

        self.model = osqp.OSQP()
        self.model.setup(P=self.P,
                         q=self.q,
                         A=self.A,
                         l=self.l,
                         u=self.u,
                         **self.opts)

        # Solve problem with OSQP
        res = self.model.solve()

        # Assert close
        self.assertEqual(res.info.status_val,
                         constant('OSQP_PRIMAL_INFEASIBLE'))
Example #10
0
    def update(self,
               q=None,
               l=None,
               u=None,
               Px=None,
               Px_idx=np.array([]),
               Ax=None,
               Ax_idx=np.array([])):
        """
        Update OSQP problem arguments
        """

        # get problem dimensions
        (n, m) = self._model.dimensions()

        # check consistency of the input arguments
        if q is not None and len(q) != n:
            raise ValueError("q must have length n")
        if l is not None:
            if not isinstance(l, np.ndarray):
                raise TypeError("l must be numpy.ndarray, not %s" %
                                type(l).__name__)
            elif len(l) != m:
                raise ValueError("l must have length m")
            # Convert values to -OSQP_INFTY
            l = np.maximum(l, -_osqp.constant('OSQP_INFTY'))
        if u is not None:
            if not isinstance(u, np.ndarray):
                raise TypeError("u must be numpy.ndarray, not %s" %
                                type(u).__name__)
            elif len(u) != m:
                raise ValueError("u must have length m")
            # Convert values to OSQP_INFTY
            u = np.minimum(u, _osqp.constant('OSQP_INFTY'))
        if Ax is None:
            if len(Ax_idx) > 0:
                raise ValueError("Vector Ax has not been specified")
        else:
            if len(Ax_idx) > 0 and len(Ax) != len(Ax_idx):
                raise ValueError("Ax and Ax_idx must have the same lengths")
        if Px is None:
            if len(Px_idx) > 0:
                raise ValueError("Vector Px has not been specified")
        else:
            if len(Px_idx) > 0 and len(Px) != len(Px_idx):
                raise ValueError("Px and Px_idx must have the same lengths")
        if q is None and l is None and u is None and Px is None and Ax is None:
            raise ValueError("No updatable data has been specified")

        # update linear cost
        if q is not None:
            self._model.update_lin_cost(q)

        # update lower bound
        if l is not None and u is None:
            self._model.update_lower_bound(l)

        # update upper bound
        if u is not None and l is None:
            self._model.update_upper_bound(u)

        # update bounds
        if l is not None and u is not None:
            self._model.update_bounds(l, u)

        # update matrix P
        if Px is not None and Ax is None:
            self._model.update_P(Px, Px_idx, len(Px))

        # update matrix A
        if Ax is not None and Px is None:
            self._model.update_A(Ax, Ax_idx, len(Ax))

        # update matrices P and A
        if Px is not None and Ax is not None:
            self._model.update_P_A(Px, Px_idx, len(Px), Ax, Ax_idx, len(Ax))
Example #11
0
def prepare_data(P=None, q=None, A=None, l=None, u=None, **settings):
    """
        Prepare problem data of the form

        minimize     1/2 x' * P * x + q' * x
        subject to   l <= A * x <= u

        solver settings can be specified as additional keyword arguments
        """

    #
    # Get problem dimensions
    #

    if P is None:
        if q is not None:
            n = len(q)
        elif A is not None:
            n = A.shape[1]
        else:
            raise ValueError("The problem does not have any variables")
    else:
        n = P.shape[0]
    if A is None:
        m = 0
    else:
        m = A.shape[0]

    #
    # Create parameters if they are None
    #

    if (A is None and (l is not None or u is not None)) or \
            (A is not None and (l is None and u is None)):
        raise ValueError("A must be supplied together " +
                         "with at least one bound l or u")

    # Add infinity bounds in case they are not specified
    if A is not None and l is None:
        l = -np.inf * np.ones(A.shape[0])
    if A is not None and u is None:
        u = np.inf * np.ones(A.shape[0])

    # Create elements if they are not specified
    if P is None:
        P = sparse.csc_matrix((np.zeros(
            (0, ), dtype=np.double), np.zeros(
                (0, ), dtype=np.int), np.zeros((n + 1, ), dtype=np.int)),
                              shape=(n, n))
    if q is None:
        q = np.zeros(n)

    if A is None:
        A = sparse.csc_matrix((np.zeros(
            (0, ), dtype=np.double), np.zeros(
                (0, ), dtype=np.int), np.zeros((n + 1, ), dtype=np.int)),
                              shape=(m, n))
        l = np.zeros(A.shape[0])
        u = np.zeros(A.shape[0])

    #
    # Check vector dimensions (not checked from C solver)
    #

    # Check if second dimension of A is correct
    # if A.shape[1] != n:
    #     raise ValueError("Dimension n in A and P does not match")
    if len(q) != n:
        raise ValueError("Incorrect dimension of q")
    if len(l) != m:
        raise ValueError("Incorrect dimension of l")
    if len(u) != m:
        raise ValueError("Incorrect dimension of u")

    #
    # Check or Sparsify Matrices
    #
    if not sparse.issparse(P) and isinstance(P, np.ndarray) and \
            len(P.shape) == 2:
        raise TypeError("P is required to be a sparse matrix")
    if not sparse.issparse(A) and isinstance(A, np.ndarray) and \
            len(A.shape) == 2:
        raise TypeError("A is required to be a sparse matrix")

    # If P is not triu, then convert it to triu
    if sparse.tril(P, -1).data.size > 0:
        P = sparse.triu(P, format='csc')

    # Convert matrices in CSC form and to individual pointers
    if not sparse.isspmatrix_csc(P):
        warn("Converting sparse P to a CSC " +
             "(compressed sparse column) matrix. (It may take a while...)")
        P = P.tocsc()
    if not sparse.isspmatrix_csc(A):
        warn("Converting sparse A to a CSC " +
             "(compressed sparse column) matrix. (It may take a while...)")
        A = A.tocsc()

    # Check if P an A have sorted indices
    if not P.has_sorted_indices:
        P.sort_indices()
    if not A.has_sorted_indices:
        A.sort_indices()

    # Convert infinity values to OSQP Infinity
    u = np.minimum(u, _osqp.constant('OSQP_INFTY'))
    l = np.maximum(l, -_osqp.constant('OSQP_INFTY'))

    # Convert linsys_solver string to integer
    settings = linsys_solver_str_to_int(settings)

    return ((n, m), P.data, P.indices, P.indptr, q, A.data, A.indices,
            A.indptr, l, u), settings
 def test_nan(self):
     nptest.assert_approx_equal(constant('OSQP_NAN'), np.nan)