diff --git a/.travis.yml b/.travis.yml index f35b70f56..22b12d451 100644 --- a/.travis.yml +++ b/.travis.yml @@ -101,6 +101,12 @@ matrix: - MPLBACKEND=ps - PYTHON_VERSION=3.8.1 - TOXENV=py38 + - python: "3.8" + name: "Python 3.8 tests without optional dependencies" + stage: all_python + env: TOXENV=no-opt + stage: all_python + script: tox - if: tag IS present python: "3.6" env: diff --git a/releasenotes/notes/missing-dependency-e7c99c7751bcd162.yaml b/releasenotes/notes/missing-dependency-e7c99c7751bcd162.yaml new file mode 100644 index 000000000..86b10c64d --- /dev/null +++ b/releasenotes/notes/missing-dependency-e7c99c7751bcd162.yaml @@ -0,0 +1,10 @@ +--- +upgrade: + - | + A new requirement `scikit-learn `__ has + been added to the requirements list. This dependency was added in the 0.3.0 + release but wasn't properly exposed as a dependency in that release. This + would lead to an ``ImportError`` if the + :mod:`qiskit.ignis.measurement.discriminator.iq_discriminators` module was + imported. This is now correctly listed as a dependency so that + ``scikit-learn`` will be installed with qiskit-ignis. diff --git a/setup.py b/setup.py index 874046f08..fec7c9de5 100644 --- a/setup.py +++ b/setup.py @@ -23,6 +23,7 @@ "qiskit-terra>=0.13.0", "scipy>=0.19,!=0.19.1", "setuptools>=40.1.0", + "scikit-learn>=0.17", ] diff --git a/test/tomography/test_process_tomography.py b/test/tomography/test_process_tomography.py index d2f4bf872..76489ee85 100644 --- a/test/tomography/test_process_tomography.py +++ b/test/tomography/test_process_tomography.py @@ -24,20 +24,23 @@ from qiskit.quantum_info import Choi import qiskit.ignis.verification.tomography as tomo +from qiskit.ignis.verification.tomography.fitters import cvx_fit -def run_circuit_and_tomography(circuit, qubits): +def run_circuit_and_tomography(circuit, qubits, method): choi_ideal = Choi(circuit).data qst = tomo.process_tomography_circuits(circuit, qubits) job = qiskit.execute(qst, Aer.get_backend('qasm_simulator'), shots=5000) tomo_fit = tomo.ProcessTomographyFitter(job.result(), qst) - choi_cvx = tomo_fit.fit(method='cvx').data - choi_mle = tomo_fit.fit(method='lstsq').data - return (choi_cvx, choi_mle, choi_ideal) + choi = tomo_fit.fit(method=method).data + return (choi, choi_ideal) class TestProcessTomography(unittest.TestCase): + def setUp(self): + super().setUp() + self.method = 'lstsq' def test_bell_2_qubits(self): q2 = QuantumRegister(2) @@ -45,11 +48,16 @@ def test_bell_2_qubits(self): bell.h(q2[0]) bell.cx(q2[0], q2[1]) - choi_cvx, choi_mle, choi_ideal = run_circuit_and_tomography(bell, q2) - F_bell_cvx = state_fidelity(choi_ideal/4, choi_cvx/4, validate=False) - self.assertAlmostEqual(F_bell_cvx, 1, places=1) - F_bell_mle = state_fidelity(choi_ideal/4, choi_mle/4, validate=False) - self.assertAlmostEqual(F_bell_mle, 1, places=1) + choi, choi_ideal = run_circuit_and_tomography(bell, q2, self.method) + F_bell = state_fidelity(choi_ideal/4, choi/4, validate=False) + self.assertAlmostEqual(F_bell, 1, places=1) + + +@unittest.skipUnless(cvx_fit._HAS_CVX, 'cvxpy is required for this test') +class TestProcessTomographyCVX(TestProcessTomography): + def setUp(self): + super().setUp() + self.method = 'cvx' if __name__ == '__main__': diff --git a/test/tomography/test_state_tomography.py b/test/tomography/test_state_tomography.py index 786c019a8..c79d4ab98 100644 --- a/test/tomography/test_state_tomography.py +++ b/test/tomography/test_state_tomography.py @@ -26,19 +26,18 @@ import qiskit.ignis.verification.tomography.fitters.cvx_fit as cvx_fit -def run_circuit_and_tomography(circuit, qubits): +def run_circuit_and_tomography(circuit, qubits, method='lstsq'): psi = Statevector.from_instruction(circuit) qst = tomo.state_tomography_circuits(circuit, qubits) job = qiskit.execute(qst, Aer.get_backend('qasm_simulator'), shots=5000) tomo_fit = tomo.StateTomographyFitter(job.result(), qst) - rho_cvx = tomo_fit.fit(method='cvx') - rho_mle = tomo_fit.fit(method='lstsq') - return (rho_cvx, rho_mle, psi) + rho = tomo_fit.fit(method=method) + return (rho, psi) +@unittest.skipUnless(cvx_fit._HAS_CVX, 'cvxpy is required to run this test') class TestFitter(unittest.TestCase): - def test_trace_constraint(self): p = numpy.array([1/2, 1/2, 1/2, 1/2, 1/2, 1/2]) @@ -58,6 +57,9 @@ def test_trace_constraint(self): class TestStateTomography(unittest.TestCase): + def setUp(self): + super().setUp() + self.method = 'lstsq' def test_bell_2_qubits(self): q2 = QuantumRegister(2) @@ -65,22 +67,18 @@ def test_bell_2_qubits(self): bell.h(q2[0]) bell.cx(q2[0], q2[1]) - rho_cvx, rho_mle, psi = run_circuit_and_tomography(bell, q2) - F_bell_cvx = state_fidelity(psi, rho_cvx, validate=False) - self.assertAlmostEqual(F_bell_cvx, 1, places=1) - F_bell_mle = state_fidelity(psi, rho_mle, validate=False) - self.assertAlmostEqual(F_bell_mle, 1, places=1) + rho, psi = run_circuit_and_tomography(bell, q2, self.method) + F_bell = state_fidelity(psi, rho, validate=False) + self.assertAlmostEqual(F_bell, 1, places=1) def test_bell_2_qubits_no_register(self): bell = QuantumCircuit(2) bell.h(0) bell.cx(0, 1) - rho_cvx, rho_mle, psi = run_circuit_and_tomography(bell, (0, 1)) - F_bell_cvx = state_fidelity(psi, rho_cvx, validate=False) - self.assertAlmostEqual(F_bell_cvx, 1, places=1) - F_bell_mle = state_fidelity(psi, rho_mle, validate=False) - self.assertAlmostEqual(F_bell_mle, 1, places=1) + rho, psi = run_circuit_and_tomography(bell, (0, 1), self.method) + F_bell = state_fidelity(psi, rho, validate=False) + self.assertAlmostEqual(F_bell, 1, places=1) def test_different_qubit_sets(self): circuit = QuantumCircuit(5) @@ -92,12 +90,10 @@ def test_different_qubit_sets(self): circuit.cx(1, 3) for qubit_pair in [(0, 1), (2, 3), (1, 4), (0, 3)]: - rho_cvx, rho_mle, psi = run_circuit_and_tomography(circuit, qubit_pair) + rho, psi = run_circuit_and_tomography(circuit, qubit_pair, self.method) psi = partial_trace(psi, [x for x in range(5) if x not in qubit_pair]) - F_cvx = state_fidelity(psi, rho_cvx, validate=False) - self.assertAlmostEqual(F_cvx, 1, places=1) - F_mle = state_fidelity(psi, rho_mle, validate=False) - self.assertAlmostEqual(F_mle, 1, places=1) + F = state_fidelity(psi, rho, validate=False) + self.assertAlmostEqual(F, 1, places=1) def test_bell_3_qubits(self): q3 = QuantumRegister(3) @@ -106,22 +102,18 @@ def test_bell_3_qubits(self): bell.cx(q3[0], q3[1]) bell.cx(q3[1], q3[2]) - rho_cvx, rho_mle, psi = run_circuit_and_tomography(bell, q3) - F_bell_cvx = state_fidelity(psi, rho_cvx, validate=False) - self.assertAlmostEqual(F_bell_cvx, 1, places=1) - F_bell_mle = state_fidelity(psi, rho_mle, validate=False) - self.assertAlmostEqual(F_bell_mle, 1, places=1) + rho, psi = run_circuit_and_tomography(bell, q3, self.method) + F_bell = state_fidelity(psi, rho, validate=False) + self.assertAlmostEqual(F_bell, 1, places=1) def test_complex_1_qubit_circuit(self): q = QuantumRegister(1) circ = QuantumCircuit(q) circ.u3(1, 1, 1, q[0]) - rho_cvx, rho_mle, psi = run_circuit_and_tomography(circ, q) - F_bell_cvx = state_fidelity(psi, rho_cvx, validate=False) - self.assertAlmostEqual(F_bell_cvx, 1, places=1) - F_bell_mle = state_fidelity(psi, rho_mle, validate=False) - self.assertAlmostEqual(F_bell_mle, 1, places=1) + rho, psi = run_circuit_and_tomography(circ, q, self.method) + F_bell = state_fidelity(psi, rho, validate=False) + self.assertAlmostEqual(F_bell, 1, places=1) def test_complex_3_qubit_circuit(self): def rand_angles(): @@ -133,11 +125,16 @@ def rand_angles(): for j in range(3): circ.u3(*rand_angles(), q[j]) - rho_cvx, rho_mle, psi = run_circuit_and_tomography(circ, q) - F_bell_cvx = state_fidelity(psi, rho_cvx, validate=False) - self.assertAlmostEqual(F_bell_cvx, 1, places=1) - F_bell_mle = state_fidelity(psi, rho_mle, validate=False) - self.assertAlmostEqual(F_bell_mle, 1, places=1) + rho, psi = run_circuit_and_tomography(circ, q, self.method) + F_bell = state_fidelity(psi, rho, validate=False) + self.assertAlmostEqual(F_bell, 1, places=1) + + +@unittest.skipUnless(cvx_fit._HAS_CVX, 'cvxpy is required to run this test') +class TestStateTomographyCVX(TestStateTomography): + def setUp(self): + super().setUp() + self.method = 'cvx' if __name__ == '__main__': diff --git a/tox.ini b/tox.ini index 95c9fd2bc..23363d840 100644 --- a/tox.ini +++ b/tox.ini @@ -20,6 +20,16 @@ commands = pip check stestr run {posargs} +[testenv:no-opt] +deps = + git+https://github.com/Qiskit/qiskit-terra.git + qiskit-aer + ddt>=1.2.0,!=1.4.0 + stestr>=2.5.0 +commands = + pip check + stestr run {posargs} + [testenv:lint] basepython = python3 deps =