diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 31f9fc848..b6cc81115 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,6 +37,32 @@ jobs: QISKIT_IN_PARALLEL: TRUE run: tox -e py if: runner.os == 'macOS' + tests-no-opt: + name: tests-python3.8-no-optional-dependencies + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: [3.8] + os: ["ubuntu-latest"] + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Pip cache + uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-${{ matrix.python-version }}-pip-tests-${{ hashFiles('setup.py','requirements-dev.txt','constraints.txt') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.python-version }}-pip-tests- + ${{ runner.os }}-${{ matrix.python-version }}-pip- + ${{ runner.os }}-${{ matrix.python-version }} + - name: Install Deps + run: python -m pip install -U tox setuptools virtualenv wheel + - name: Install and Run Tests + run: tox -e no-opt windows-tests: name: tests-python${{ matrix.python-version }}-windows runs-on: windows-latest diff --git a/.pylintrc b/.pylintrc index 7626bcf45..e8956278b 100644 --- a/.pylintrc +++ b/.pylintrc @@ -295,7 +295,7 @@ ignore-mixin-members=yes # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis. It # supports qualified module names, as well as Unix pattern matching. -ignored-modules=matplotlib.cm,numpy.random,retworkx +ignored-modules=matplotlib.cm,numpy.random,retworkx,numba # List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of diff --git a/constraints.txt b/constraints.txt index 180ca0f9a..2344507f4 100644 --- a/constraints.txt +++ b/constraints.txt @@ -2,3 +2,4 @@ pylint==2.4.4 astroid==2.3.3 pywin32==225 setuptools==49.6.0 +pyfakefs==4.1.0 diff --git a/docs/conf.py b/docs/conf.py index f097808ae..7a542a1b1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -46,7 +46,7 @@ # The short X.Y version version = '' # The full version, including alpha/beta/rc tags -release = '0.5.0' +release = '0.5.1' # -- General configuration --------------------------------------------------- diff --git a/qiskit/ignis/VERSION.txt b/qiskit/ignis/VERSION.txt index 8f0916f76..4b9fcbec1 100644 --- a/qiskit/ignis/VERSION.txt +++ b/qiskit/ignis/VERSION.txt @@ -1 +1 @@ -0.5.0 +0.5.1 diff --git a/qiskit/ignis/mitigation/expval/base_meas_mitigator.py b/qiskit/ignis/mitigation/expval/base_meas_mitigator.py index c6b445b3f..bed5b6387 100644 --- a/qiskit/ignis/mitigation/expval/base_meas_mitigator.py +++ b/qiskit/ignis/mitigation/expval/base_meas_mitigator.py @@ -166,13 +166,13 @@ def stddev_upper_bound(self, shots: int = 1, qubits: Optional[List[int]] = None) return gamma / np.sqrt(shots) def plot_assignment_matrix(self, - qubits: Optional[List[int]] = None, - ax: Optional[plt.axes] = None) -> plt.axes: + qubits=None, + ax=None): """Matrix plot of the readout error assignment matrix. Args: - qubits: Optional, qubits being measured for operator expval. - ax: Optional. Axes object to add plot to. + qubits (list(int)): Optional, qubits being measured for operator expval. + ax (axes): Optional. Axes object to add plot to. Returns: plt.axes: the figure axes object. @@ -195,13 +195,13 @@ def plot_assignment_matrix(self, return ax def plot_mitigation_matrix(self, - qubits: Optional[List[int]] = None, - ax: Optional[plt.axes] = None) -> plt.axes: + qubits=None, + ax=None): """Matrix plot of the readout error mitigation matrix. Args: - qubits: Optional, qubits being measured for operator expval. - ax: Optional. Axes object to add plot to. + qubits (list(int)): Optional, qubits being measured for operator expval. + ax (plt.axes): Optional. Axes object to add plot to. Returns: plt.axes: the figure axes object. @@ -247,12 +247,12 @@ def _int_to_bitstring(i, num_qubits=None): return label @staticmethod - def _plot_axis(mat: np.ndarray, ax: plt.axes) -> plt.axes: + def _plot_axis(mat, ax): """Helper function for setting up axes for plots. Args: - mat: the N-qubit matrix to plot. - ax: Optional. Axes object to add plot to. + mat (np.ndarray): the N-qubit matrix to plot. + ax (plt.axes): Optional. Axes object to add plot to. Returns: plt.axes: the figure object and axes object. diff --git a/qiskit/ignis/verification/tomography/fitters/base_fitter.py b/qiskit/ignis/verification/tomography/fitters/base_fitter.py index 00322cba7..d31531d08 100644 --- a/qiskit/ignis/verification/tomography/fitters/base_fitter.py +++ b/qiskit/ignis/verification/tomography/fitters/base_fitter.py @@ -40,6 +40,7 @@ class TomographyFitter: """Base maximum-likelihood estimate tomography fitter class""" _HAS_SDP_SOLVER = None + _HAS_SDP_SOLVER_NOT_SCS = False def __init__(self, result: Union[Result, List[Result]], @@ -120,12 +121,14 @@ def fit(self, **kwargs) -> np.array: r"""Reconstruct a quantum state using CVXPY convex optimization. - **Fitter method** + **Fitter method** - The ``cvx`` fitter method used CVXPY convex optimization package. - The ``lstsq`` method uses least-squares fitting (linear inversion). - The ``auto`` method will use 'cvx' if the CVXPY package is found on - the system, otherwise it will default to 'lstsq'. + The ``'cvx'`` fitter method uses the CVXPY convex optimization package + with a SDP solver. + The ``'lstsq'`` method uses least-squares fitting. + The ``'auto'`` method will use ``'cvx'`` if the both the CVXPY and a suitable + SDP solver packages are found on the system, otherwise it will default + to ``'lstsq'``. **Objective function** @@ -165,9 +168,14 @@ def fit(self, **CVXPY Solvers:** Various solvers can be called in CVXPY using the `solver` keyword - argument. See the `CVXPY documentation + argument. If ``psd=True`` an SDP solver is required other an SOCP + solver is required. See the `CVXPY documentation `_ for more information on solvers. + Note that the default SDP solver ('SCS') distributed + with CVXPY will not be used for the ``'auto'`` method due its reduced + accuracy compared to other solvers. When using the ``'cvx'`` method we + strongly recommend installing one of the other supported SDP solvers. References: @@ -200,7 +208,11 @@ def fit(self, # Choose automatic method if method == 'auto': self._check_for_sdp_solver() - if self._HAS_SDP_SOLVER: + if self._HAS_SDP_SOLVER_NOT_SCS: + # We don't use the SCS solver for automatic method as it has + # lower accuracy than the other supported SDP solvers which + # typically results in the returned matrix not being + # completely positive. method = 'cvx' else: method = 'lstsq' @@ -516,7 +528,9 @@ def _check_for_sdp_solver(cls): # pylint:disable=import-error import cvxpy solvers = cvxpy.installed_solvers() - if 'CVXOPT' in solvers: + # Check for other SDP solvers cvxpy supports + if 'CVXOPT' in solvers or 'MOSEK' in solvers: + cls._HAS_SDP_SOLVER_NOT_SCS = True cls._HAS_SDP_SOLVER = True return if 'SCS' in solvers: @@ -524,7 +538,7 @@ def _check_for_sdp_solver(cls): # SCS solver cannot solver larger than 2x2 matrix # problems without BLAS try: - var = cvxpy.Variable((4, 4), PSD=True) + var = cvxpy.Variable((5, 5), PSD=True) obj = cvxpy.Minimize(cvxpy.norm(var)) cvxpy.Problem(obj).solve(solver='SCS') cls._HAS_SDP_SOLVER = True diff --git a/qiskit/ignis/verification/tomography/fitters/cvx_fit.py b/qiskit/ignis/verification/tomography/fitters/cvx_fit.py index 7c2e9a9a5..9f7aeee08 100644 --- a/qiskit/ignis/verification/tomography/fitters/cvx_fit.py +++ b/qiskit/ignis/verification/tomography/fitters/cvx_fit.py @@ -198,6 +198,8 @@ def cvx_fit(data: np.array, if 'solver' not in kwargs: if 'CVXOPT' in cvxpy.installed_solvers(): kwargs['solver'] = 'CVXOPT' + elif 'MOSEK' in cvxpy.installed_solvers(): + kwargs['solver'] = 'MOSEK' problem_solved = False while not problem_solved: diff --git a/releasenotes/notes/no-auto-scs-b82ebef53508fc7b.yaml b/releasenotes/notes/no-auto-scs-b82ebef53508fc7b.yaml new file mode 100644 index 000000000..71ab7a4d6 --- /dev/null +++ b/releasenotes/notes/no-auto-scs-b82ebef53508fc7b.yaml @@ -0,0 +1,13 @@ +--- +fixes: + - | + Fix the ``"auto"`` method of the + :class:`~qiskit.ignis.verification.tomography.TomographyFitter`, + :class:`~qiskit.ignis.verification.tomography.StateTomographyFitter`, and + :class:`~qiskit.ignis.verification.tomography.ProcessTomographyFitter` to + only use ``"cvx"`` if CVXPY is installed *and* a third-party SDP solver + other than SCS is available. This is because the SCS solver has lower + accuracy than other solver methods and often returns a density matrix or + Choi-matrix that is not completely-positive and fails validation when used + with the :func:`qiskit.quantum_info.state_fidelity` or + :func:`qiskit.quantum_info.process_fidelity` functions.