Skip to content

Commit

Permalink
Remove cvxopt and use cvxpy instead (qiskit-community#1035)
Browse files Browse the repository at this point in the history
* Remove cvxopt and use cvxpy instead

This commit removes the usage of cvxopt from aqua. It was supposed to be
removed as part of the 0.7 release since some users have issue
installing it, and other users aren't allowed to have GPL code installed
in their environment. However, cvxopt is still used for the quadratic
program solver utility. cvxopt is not needed to solve a quadratic
program and other elements are already doing this with cvxpy which
doesn't have the same issues [1][2]. This commit migrates the cvxopt
usage to cvxpy to be consistent with the rest of qiskit.

[1] Qiskit/qiskit-aer@e41d868
[2] qiskit-community/qiskit-ignis@42cbbf8

* fix lint, unit tests

* remove cvxopt from travis

Co-authored-by: Manoel Marques <manoel@us.ibm.com>
(cherry picked from commit b79f835)

Conflicts:
    .travis.yml
    test/aqua/test_qsvm.py
  • Loading branch information
mtreinish committed Jun 12, 2020
1 parent d188431 commit da3de8c
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 35 deletions.
6 changes: 0 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ jobs:
- aqua137.dep
before_script:
- pip install cplex
- pip install cvxopt
- export PYTHON="coverage3 run --source qiskit/aqua,qiskit/chemistry,qiskit/finance,qiskit/ml,qiskit/optimization --omit */gauopen/* --parallel-mode"
script:
- stestr --test-path test/aqua run --blacklist-file selection.txt 2> >(tee /dev/stderr out.txt > /dev/null)
Expand All @@ -163,8 +162,6 @@ jobs:
name: aqua138
paths: aqua138.dep
python: 3.8
before_script:
- pip install cvxopt
script:
- stestr --test-path test/aqua run --blacklist-file selection.txt 2> >(tee /dev/stderr out.txt > /dev/null)
- python tools/extract_deprecation.py -file out.txt -output aqua138.dep
Expand All @@ -179,7 +176,6 @@ jobs:
- aqua237.dep
before_script:
- pip install cplex
- pip install cvxopt
- export PYTHON="coverage3 run --source qiskit/aqua,qiskit/chemistry,qiskit/finance,qiskit/ml,qiskit/optimization --omit */gauopen/* --parallel-mode"
script:
- stestr --test-path test/aqua run --whitelist-file selection.txt 2> >(tee /dev/stderr out.txt > /dev/null)
Expand All @@ -194,8 +190,6 @@ jobs:
name: aqua238
paths: aqua238.dep
python: 3.8
before_script:
- pip install cvxopt
script:
- stestr --test-path test/aqua run --whitelist-file selection.txt 2> >(tee /dev/stderr out.txt > /dev/null)
- python tools/extract_deprecation.py -file out.txt -output aqua238.dep
Expand Down
44 changes: 17 additions & 27 deletions qiskit/aqua/utils/qp_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,12 @@

from typing import Optional, Tuple
import logging

import numpy as np
import cvxpy

logger = logging.getLogger(__name__)

_HAS_CVXOPT = False
try:
from cvxopt import matrix, solvers
_HAS_CVXOPT = True
except ImportError:
logger.info('CVXOPT is not installed. See http://cvxopt.org/install/index.html')


def optimize_svm(kernel_matrix: np.ndarray,
y: np.ndarray,
Expand All @@ -36,9 +31,6 @@ def optimize_svm(kernel_matrix: np.ndarray,
"""
Solving quadratic programming problem for SVM; thus, some constraints are fixed.
The notation is follows the equation here:
http://cvxopt.org/userguide/coneprog.html#quadratic-programming
Args:
kernel_matrix: NxN array
y: Nx1 array
Expand All @@ -51,13 +43,8 @@ def optimize_svm(kernel_matrix: np.ndarray,
np.ndarray: Sx1 array, where S is the number of supports
np.ndarray: Sx1 array, where S is the number of supports
np.ndarray: Sx1 array, where S is the number of supports
Raises:
NameError: CVXOPT not installed.
"""
# pylint: disable=invalid-name
if not _HAS_CVXOPT:
raise NameError('CVXOPT is not installed. See http://cvxopt.org/install/index.html')
# pylint: disable=invalid-name, unused-argument
if y.ndim == 1:
y = y[:, np.newaxis]
H = np.outer(y, y) * kernel_matrix
Expand All @@ -69,17 +56,20 @@ def optimize_svm(kernel_matrix: np.ndarray,
tolerance = 1e-2
n = kernel_matrix.shape[1]

P = matrix(H)
q = matrix(f)
G = matrix(-np.eye(n))
h = matrix(np.zeros(n))
A = matrix(y, y.T.shape)
b = matrix(np.zeros(1), (1, 1))
solvers.options['maxiters'] = max_iters
solvers.options['show_progress'] = show_progress

ret = solvers.qp(P, q, G, h, A, b, kktsolver='ldl')
alpha = np.asarray(ret['x']) * scaling
P = np.array(H)
q = np.array(f)
G = -np.eye(n)
h = np.zeros(n)
A = y.reshape(y.T.shape)
b = np.zeros((1, 1))
x = cvxpy.Variable(n)
prob = cvxpy.Problem(
cvxpy.Minimize((1 / 2) * cvxpy.quad_form(x, P) + q.T@x),
[G@x <= h,
A@x == b])
prob.solve(verbose=show_progress)
result = np.asarray(x.value).reshape((n, 1))
alpha = result * scaling
avg_y = np.sum(y)
avg_mat = (alpha * y).T.dot(kernel_matrix.dot(np.ones(y.shape)))
b = (avg_y - avg_mat) / n
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"h5py",
"networkx>=2.2",
"pyscf; sys_platform != 'win32'",
'cvxpy>1.0.0,<1.1.0',
]

if not hasattr(setuptools, 'find_namespace_packages') or not inspect.ismethod(setuptools.find_namespace_packages):
Expand Down
4 changes: 2 additions & 2 deletions test/aqua/test_qsvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ def test_qsvm_binary(self, data_preparation_type):
[0.33608333, 0.3765, 0.02316667, 0.15858333]])

# ref_alpha = np.array([0.36064489, 1.49204209, 0.0264953, 1.82619169])
ref_alpha = np.array([0.34903335, 1.48325498, 0.03074852, 1.80153981])
ref_alpha = np.array([0.34902907, 1.48325913, 0.03073616, 1.80155205])
# ref_bias = np.array([-0.03380763])
ref_bias = np.array([-0.03059226])
ref_bias = np.array([-0.03059395])

ref_support_vectors = np.array([[2.95309709, 2.51327412], [3.14159265, 4.08407045],
[4.08407045, 2.26194671], [4.46106157, 2.38761042]])
Expand Down

0 comments on commit da3de8c

Please sign in to comment.