From 8933661f83c8a1533bd7827e9246e9b2f736fe6d Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 10 Nov 2020 16:05:54 -0500 Subject: [PATCH 1/5] Fix ignis without optional requirements installed (#533) * Fix ignis without optional requirements installed In #500 type hints were added for the plotting functions using the optional matplotlib dependencies. This breaks ignis installations without matplotlib present since it's an optional dependency. Since type hints are really just for documentation and not necessary this commit just removes those problematic hints and uses the docstring to document the types. At the same time the testing job verifying ignis works without any optional dependencies that was lost in the migration from travis to github actions is restored to verify that everything works moving forward. (cherry picked from commit d9fe8f93cbfdea1529e263c5f5bcb736c8fd9ccc) --- .github/workflows/main.yml | 26 +++++++++++++++++++ .../mitigation/expval/base_meas_mitigator.py | 22 ++++++++-------- 2 files changed, 37 insertions(+), 11 deletions(-) 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/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. From 9a8984e949823fa74d768af5d21f06991d1e5d8a Mon Sep 17 00:00:00 2001 From: "Christopher J. Wood" Date: Wed, 11 Nov 2020 16:31:33 -0500 Subject: [PATCH 2/5] Update 'auto' method to not use SCS solver for CVXPY (#536) Fix the "auto" method of the tomography fitters 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 state_fidelity or process_fidelity functions (cherry picked from commit 006876e6e6adb69200b4c96f35205301f8c1aeff) --- .../tomography/fitters/base_fitter.py | 32 +++++++++++++------ .../tomography/fitters/cvx_fit.py | 2 ++ .../notes/no-auto-scs-b82ebef53508fc7b.yaml | 13 ++++++++ 3 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 releasenotes/notes/no-auto-scs-b82ebef53508fc7b.yaml 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. From 423984760eaebee53c23ba81cece2e51eebf1a6c Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Thu, 12 Nov 2020 09:55:05 -0500 Subject: [PATCH 3/5] Prepare 0.5.1 release This commit bumps the package version to 0.5.1 to prepare for pushing it as a stable point release. --- docs/conf.py | 2 +- qiskit/ignis/VERSION.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 From da266b0768672d0f9a0fad0b2ccf0f853998b261 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Thu, 12 Nov 2020 10:30:38 -0500 Subject: [PATCH 4/5] Fix lint error on numba --- .pylintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 489bd9d2c72f6618a74d6d68de08a70563ac1a7b Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Mon, 2 Nov 2020 13:24:10 -0500 Subject: [PATCH 5/5] Pin pyfakefs to avoid broken release (#528) * Pin pyfakefs to avoid broken release The recent pyfakefs 4.2.0 release is raising an import error whenever it's imported, see jmcgeheeiv/pyfakefs#565 for more details. This commit pins the pyfakefs version to the last known working version until there is a new release fixing this issue. * Ignore numba namespace in pylint (cherry picked from commit c572b34c41a90011cad52e19e09d3a0e446608fe) --- constraints.txt | 1 + 1 file changed, 1 insertion(+) 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