From fdd5603af766f6a5ceb9c8ac03da6e78936385ff Mon Sep 17 00:00:00 2001 From: Paul Nation Date: Wed, 26 Feb 2020 06:12:40 -0500 Subject: [PATCH] Fix crash in newer macOS versions (#3884) There is an OpenBlas threading issue affecting scipy.linalg.eigh that is holding up #3591. This removes the call to eigh and replaces it with eig that uses a different underlying blas call and just takes the real part of the resulting eigenvalues. This also made explicit two of the tests that were causing issues as they were off by a minus sign in the test suite but were fine when run explicitly. * fix threading crash * fix tests to be explicit --- .../operators/channel/transformations.py | 5 ++++- .../operators/channel/test_kraus.py | 21 +++++++++++++------ .../operators/channel/test_stinespring.py | 21 +++++++++++++------ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/qiskit/quantum_info/operators/channel/transformations.py b/qiskit/quantum_info/operators/channel/transformations.py index 7e94a9ccdb69..a42ca80a06d7 100644 --- a/qiskit/quantum_info/operators/channel/transformations.py +++ b/qiskit/quantum_info/operators/channel/transformations.py @@ -208,7 +208,10 @@ def _choi_to_kraus(data, input_dim, output_dim, atol=ATOL_DEFAULT): # Check if hermitian matrix if is_hermitian_matrix(data, atol=atol): # Get eigen-decomposition of Choi-matrix - w, v = la.eigh(data) + # This should be a call to la.eigh, but there is an OpenBlas + # threading issue that is causing segfaults. + w, v = la.eig(data) + w = w.real # Check eigenvalues are non-negative if len(w[w < -atol]) == 0: # CP-map Kraus representation diff --git a/test/python/quantum_info/operators/channel/test_kraus.py b/test/python/quantum_info/operators/channel/test_kraus.py index de4443ec7def..b75c3c525bf9 100644 --- a/test/python/quantum_info/operators/channel/test_kraus.py +++ b/test/python/quantum_info/operators/channel/test_kraus.py @@ -18,9 +18,9 @@ import numpy as np from numpy.testing import assert_allclose -from qiskit import QiskitError +from qiskit import QiskitError, QuantumCircuit, QuantumRegister from qiskit.quantum_info.states import DensityMatrix -from qiskit.quantum_info.operators.channel import Kraus +from qiskit.quantum_info import Kraus, Operator from .channel_test_case import ChannelTestCase @@ -62,10 +62,19 @@ def test_init(self): def test_circuit_init(self): """Test initialization from a circuit.""" - circuit, target = self.simple_circuit_no_measure() - op = Kraus(circuit) - target = Kraus(target) - self.assertEqual(op, target) + unitary_x = np.array([[0, 1], [1, 0]]) + unitary_h = np.array([[1, 1], [1, -1]]) / np.sqrt(2) + y90 = (1 / np.sqrt(2)) * np.array([[1, -1], [1, 1]]) + + target = Operator(np.kron(y90, np.kron(unitary_x, unitary_h))) + qr = QuantumRegister(3) + circ = QuantumCircuit(qr) + circ.h(qr[0]) + circ.x(qr[1]) + circ.ry(np.pi / 2, qr[2]) + + ans = np.linalg.norm((Kraus(circ)-Kraus(target)).data) + self.assertAlmostEqual(ans, 0.0) def test_circuit_init_except(self): """Test initialization from circuit with measure raises exception.""" diff --git a/test/python/quantum_info/operators/channel/test_stinespring.py b/test/python/quantum_info/operators/channel/test_stinespring.py index 5a2d1a5850a0..7bcf43c31427 100644 --- a/test/python/quantum_info/operators/channel/test_stinespring.py +++ b/test/python/quantum_info/operators/channel/test_stinespring.py @@ -18,9 +18,9 @@ import numpy as np from numpy.testing import assert_allclose -from qiskit import QiskitError +from qiskit import QiskitError, QuantumCircuit, QuantumRegister from qiskit.quantum_info.states import DensityMatrix -from qiskit.quantum_info.operators.channel import Stinespring +from qiskit.quantum_info import Stinespring, Operator from .channel_test_case import ChannelTestCase @@ -56,10 +56,19 @@ def test_init(self): def test_circuit_init(self): """Test initialization from a circuit.""" - circuit, target = self.simple_circuit_no_measure() - op = Stinespring(circuit) - target = Stinespring(target) - self.assertEqual(op, target) + unitary_x = np.array([[0, 1], [1, 0]]) + unitary_h = np.array([[1, 1], [1, -1]]) / np.sqrt(2) + y90 = (1 / np.sqrt(2)) * np.array([[1, -1], [1, 1]]) + + target = Operator(np.kron(y90, np.kron(unitary_x, unitary_h))) + qr = QuantumRegister(3) + circ = QuantumCircuit(qr) + circ.h(qr[0]) + circ.x(qr[1]) + circ.ry(np.pi / 2, qr[2]) + + ans = np.linalg.norm((Stinespring(circ)-Stinespring(target)).data) + self.assertAlmostEqual(ans, 0.0) def test_circuit_init_except(self): """Test initialization from circuit with measure raises exception."""