Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LP Tests #72

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, macos-latest, windows-2022]

steps:
- uses: actions/checkout@master
Expand Down
2 changes: 1 addition & 1 deletion osqp_sources
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ write_to = "src/osqp/_version.py"
build = "cp3*"
skip = "*-win32 *-manylinux_i686 *-musllinux_*"
test-requires = ["pytest"]
test-command = "pytest -s {project}/src/osqp/tests -k \"not codegen and not mkl\""
test-command = "pytest -s {project}/src/osqp/tests -k \"not mkl\""
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@

# Check if windows linux or mac to pass flag
if system() == 'Windows':
cmake_args += ['-G', 'Visual Studio 14 2015']
cmake_args += ['-G', 'Visual Studio 16 2019']
# Differentiate between 32-bit and 64-bit
if sys.maxsize // 2 ** 32 > 0:
cmake_args[-1] += ' Win64'
cmake_args += ['-A', 'x64']
cmake_build_flags += ['--config', 'Release']
lib_name = 'osqp.lib'
lib_subdir = ['Release']
Expand Down
2 changes: 2 additions & 0 deletions src/osqp/codegen/code_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,5 @@ def codegen(work, target_dir, python_ext_name, project_type, compile_python_ext,
sh.copy(module_name, current_dir)
os.chdir(current_dir)
print("[done]")

return current_dir
2 changes: 1 addition & 1 deletion src/osqp/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ def codegen(self, folder, project_type='', parameters='vectors',
print("[done]")

# Generate code with codegen module
cg.codegen(work, folder, python_ext_name, project_type, compile_python_ext,
return cg.codegen(work, folder, python_ext_name, project_type, compile_python_ext,
embedded, force_rewrite, float_flag, long_flag)

def derivative_iterative_refinement(self, rhs, max_iter=20, tol=1e-12):
Expand Down
110 changes: 110 additions & 0 deletions src/osqp/tests/codegen_lp_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Test osqp python module
import osqp
# import osqppurepy as osqp
import numpy as np
from scipy import sparse

# Unit Test
import unittest
import pytest
import numpy.testing as nptest
import shutil as sh
import sys


# OSQP Problem in which P is None, thus reducing it to an LP
class codegen_lp_tests(unittest.TestCase):

@classmethod
def setUpClass(cls):
P = None
q = np.array([3, 4])
A = sparse.csc_matrix([[-1, 0], [0, -1], [-1, -3],
[2, 5], [3, 4]])
A_new = sparse.csc_matrix([[-1, 0], [0, -1], [-2, -2],
[2, 5], [3, 4]])
u = np.array([0, 0, -15, 100, 80])
l = -np.inf * np.ones(len(u))
n = 2
m = A.shape[0]
opts = {'verbose': False,
'eps_abs': 1e-08,
'eps_rel': 1e-08,
'alpha': 1.6,
'max_iter': 3000,
'warm_start': True}

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

model_dir = model.codegen('code2', python_ext_name='mat_lp_emosqp', force_rewrite=True, parameters='matrices')
sh.rmtree('code2')
sys.path.append(model_dir)

cls.m = m
cls.n = n
cls.P = P
cls.q = q
cls.A = A
cls.A_new = A_new
cls.l = l
cls.u = u
cls.opts = opts

def setUp(self):

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

def test_solve(self):
import mat_lp_emosqp as mat_emosqp

# Solve problem
x, y, _, _, _ = mat_emosqp.solve()

# Assert close
nptest.assert_array_almost_equal(x, np.array([0., 5.]), decimal=5)
nptest.assert_array_almost_equal(
y, np.array([1.66666, 0., 1.33333, 0., 0.]), decimal=5)

def test_update_A(self):
import mat_lp_emosqp as mat_emosqp

# Update matrix A
Ax = self.A_new.data
Ax_idx = np.arange(self.A_new.nnz)
mat_emosqp.update_A(Ax, Ax_idx, len(Ax))

# Solve problem
x, y, _, _, _ = mat_emosqp.solve()

# Assert close
nptest.assert_array_almost_equal(x,
np.array([7.5, 2.09205935e-08]), decimal=5)
nptest.assert_array_almost_equal(
y, np.array([0., 1., 1.5, 0., 0.]), decimal=5)

# Update matrix A to the original value
Ax = self.A.data
Ax_idx = np.arange(self.A.nnz)
mat_emosqp.update_A(Ax, Ax_idx, len(Ax))

def test_update_A_allind(self):
import mat_lp_emosqp as mat_emosqp

# Update matrix A
Ax = self.A_new.data
mat_emosqp.update_A(Ax, None, 0)
x, y, _, _, _ = mat_emosqp.solve()

# Assert close
nptest.assert_array_almost_equal(x,
np.array([7.5, 2.09205935e-08]), decimal=5)
nptest.assert_array_almost_equal(
y, np.array([0., 1, 1.5, 0., 0.]), decimal=5)

# Update matrix A to the original value
Ax = self.A.data
Ax_idx = np.arange(self.A.nnz)
mat_emosqp.update_A(Ax, Ax_idx, len(Ax))
52 changes: 35 additions & 17 deletions src/osqp/tests/codegen_matrices_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,59 @@

# Unit Test
import unittest
import pytest
import numpy.testing as nptest
import shutil as sh
import sys


class codegen_matrices_tests(unittest.TestCase):

def setUp(self):
# Simple QP problem
self.P = sparse.diags([11., 0.1], format='csc')
self.P_new = sparse.eye(2, format='csc')
self.q = np.array([3, 4])
self.A = sparse.csc_matrix([[-1, 0], [0, -1], [-1, -3],
@classmethod
def setUpClass(cls):
P = sparse.diags([11., 0.1], format='csc')
P_new = sparse.eye(2, format='csc')
q = np.array([3, 4])
A = sparse.csc_matrix([[-1, 0], [0, -1], [-1, -3],
[2, 5], [3, 4]])
self.A_new = sparse.csc_matrix([[-1, 0], [0, -1], [-2, -2],
A_new = sparse.csc_matrix([[-1, 0], [0, -1], [-2, -2],
[2, 5], [3, 4]])
self.u = np.array([0, 0, -15, 100, 80])
self.l = -np.inf * np.ones(len(self.u))
self.n = self.P.shape[0]
self.m = self.A.shape[0]
self.opts = {'verbose': False,
u = np.array([0, 0, -15, 100, 80])
l = -np.inf * np.ones(len(u))
n = P.shape[0]
m = A.shape[0]
opts = {'verbose': False,
'eps_abs': 1e-08,
'eps_rel': 1e-08,
'alpha': 1.6,
'max_iter': 3000,
'warm_start': True}

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

model_dir = model.codegen('code2', python_ext_name='mat_emosqp', force_rewrite=True, parameters='matrices')
sh.rmtree('code2')
sys.path.append(model_dir)

cls.m = m
cls.n = n
cls.P = P
cls.P_new = P_new
cls.q = q
cls.A = A
cls.A_new = A_new
cls.l = l
cls.u = u
cls.opts = opts

def setUp(self):

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

def test_solve(self):
# Generate the code
self.model.codegen('code2', python_ext_name='mat_emosqp',
force_rewrite=True, parameters='matrices')

sh.rmtree('code2')
import mat_emosqp

# Solve problem
Expand Down
45 changes: 31 additions & 14 deletions src/osqp/tests/codegen_vectors_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,55 @@

# Unit Test
import unittest
import pytest
import numpy.testing as nptest
import shutil as sh
import sys


class codegen_vectors_tests(unittest.TestCase):

def setUp(self):
# Simple QP problem
self.P = sparse.diags([11., 0.], format='csc')
self.q = np.array([3, 4])
self.A = sparse.csc_matrix(
@classmethod
def setUpClass(cls):
P = sparse.diags([11., 0.], format='csc')
q = np.array([3, 4])
A = sparse.csc_matrix(
[[-1, 0], [0, -1], [-1, -3], [2, 5], [3, 4]])
self.u = np.array([0, 0, -15, 100, 80])
self.l = -np.inf * np.ones(len(self.u))
self.n = self.P.shape[0]
self.m = self.A.shape[0]
self.opts = {'verbose': False,
u = np.array([0, 0, -15, 100, 80])
l = -np.inf * np.ones(len(u))
n = P.shape[0]
m = A.shape[0]
opts = {'verbose': False,
'eps_abs': 1e-08,
'eps_rel': 1e-08,
'rho': 0.01,
'alpha': 1.6,
'max_iter': 10000,
'warm_start': True}

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

model_dir = model.codegen('code', python_ext_name='vec_emosqp',
force_rewrite=True)
sh.rmtree('code')
sys.path.append(model_dir)

cls.m = m
cls.n = n
cls.P = P
cls.q = q
cls.A = A
cls.l = l
cls.u = u
cls.opts = opts

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

def test_solve(self):
# Generate the code
self.model.codegen('code', python_ext_name='vec_emosqp',
force_rewrite=True)
sh.rmtree('code')
import vec_emosqp

# Solve problem
Expand Down