Skip to content

Commit

Permalink
Remove qiskit.test (#1292)
Browse files Browse the repository at this point in the history
* replace qiskit.test.ReferenceCircuits

* replace BaseQiskitTest

* Update qiskit_ibm_runtime/qiskit_runtime_service.py

Co-authored-by: Jessie Yu <[email protected]>

* Update qiskit_ibm_runtime/sampler.py

Co-authored-by: Jessie Yu <[email protected]>

* Update qiskit_ibm_runtime/session.py

Co-authored-by: Jessie Yu <[email protected]>

* Update test/utils.py

Co-authored-by: Jessie Yu <[email protected]>

---------

Co-authored-by: Jessie Yu <[email protected]>
  • Loading branch information
kt474 and jyu00 authored Jan 29, 2024
1 parent 786b494 commit 6365dd9
Show file tree
Hide file tree
Showing 21 changed files with 227 additions and 153 deletions.
24 changes: 19 additions & 5 deletions qiskit_ibm_runtime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
Below is an example of using primitives within a session::
from qiskit_ibm_runtime import QiskitRuntimeService, Session, Sampler, Estimator, Options
from qiskit.test.reference_circuits import ReferenceCircuits
from qiskit.circuit.library import RealAmplitudes
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.quantum_info import SparsePauliOp
# Initialize account.
Expand All @@ -49,15 +49,21 @@
options = Options(optimization_level=3)
# Prepare inputs.
bell = ReferenceCircuits.bell()
psi = RealAmplitudes(num_qubits=2, reps=2)
H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
theta = [0, 1, 1, 2, 3, 5]
# Bell Circuit
qr = QuantumRegister(2, name="qr")
cr = ClassicalRegister(2, name="qc")
qc = QuantumCircuit(qr, cr, name="bell")
qc.h(qr[0])
qc.cx(qr[0], qr[1])
qc.measure(qr, cr)
with Session(service=service, backend="ibmq_qasm_simulator") as session:
# Submit a request to the Sampler primitive within the session.
sampler = Sampler(session=session, options=options)
job = sampler.run(circuits=bell)
job = sampler.run(circuits=qc)
print(f"Sampler results: {job.result()}")
# Submit a request to the Estimator primitive within the session.
Expand Down Expand Up @@ -130,17 +136,25 @@
program by passing in the ``callback`` parameter, or at a later time using
the :meth:`RuntimeJob.stream_results` method. For example::
from qiskit.test.reference_circuits import ReferenceCircuits
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
service = QiskitRuntimeService()
backend = service.backend("ibmq_qasm_simulator")
# Bell Circuit
qr = QuantumRegister(2, name="qr")
cr = ClassicalRegister(2, name="qc")
qc = QuantumCircuit(qr, cr, name="bell")
qc.h(qr[0])
qc.cx(qr[0], qr[1])
qc.measure(qr, cr)
def result_callback(job_id, result):
print(result)
# Stream results as soon as the job starts running.
job = Sampler(backend).run(ReferenceCircuits.bell(), callback=result_callback)
job = Sampler(backend).run(qc, callback=result_callback)
print(job.result())
Expand Down
13 changes: 10 additions & 3 deletions qiskit_ibm_runtime/qiskit_runtime_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ class QiskitRuntimeService(Provider):
A sample workflow of using the runtime service::
from qiskit_ibm_runtime import QiskitRuntimeService, Session, Sampler, Estimator, Options
from qiskit.test.reference_circuits import ReferenceCircuits
from qiskit.circuit.library import RealAmplitudes
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.quantum_info import SparsePauliOp
# Initialize account.
Expand All @@ -82,15 +82,22 @@ class QiskitRuntimeService(Provider):
options = Options(optimization_level=1)
# Prepare inputs.
bell = ReferenceCircuits.bell()
psi = RealAmplitudes(num_qubits=2, reps=2)
H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
theta = [0, 1, 1, 2, 3, 5]
# Bell Circuit
qr = QuantumRegister(2, name="qr")
cr = ClassicalRegister(2, name="cr")
qc = QuantumCircuit(qr, cr, name="bell")
qc.h(qr[0])
qc.cx(qr[0], qr[1])
qc.measure(qr, cr)
with Session(service=service, backend="ibmq_qasm_simulator") as session:
# Submit a request to the Sampler primitive within the session.
sampler = Sampler(session=session, options=options)
job = sampler.run(circuits=bell)
job = sampler.run(circuits=qc)
print(f"Sampler results: {job.result()}")
# Submit a request to the Estimator primitive within the session.
Expand Down
13 changes: 10 additions & 3 deletions qiskit_ibm_runtime/sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,23 @@ class Sampler(BasePrimitive, BaseSampler):
Example::
from qiskit.test.reference_circuits import ReferenceCircuits
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit_ibm_runtime import QiskitRuntimeService, Session, Sampler
service = QiskitRuntimeService(channel="ibm_cloud")
bell = ReferenceCircuits.bell()
# Bell Circuit
qr = QuantumRegister(2, name="qr")
cr = ClassicalRegister(2, name="cr")
qc = QuantumCircuit(qr, cr, name="bell")
qc.h(qr[0])
qc.cx(qr[0], qr[1])
qc.measure(qr, cr)
with Session(service, backend="ibmq_qasm_simulator") as session:
sampler = Sampler(session=session)
job = sampler.run(bell, shots=1024)
job = sampler.run(qc, shots=1024)
print(f"Job ID: {job.job_id()}")
print(f"Job result: {job.result()}")
Expand Down
12 changes: 10 additions & 2 deletions qiskit_ibm_runtime/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,22 @@ class Session:
For example::
from qiskit.test.reference_circuits import ReferenceCircuits
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit_ibm_runtime import Sampler, Session, Options
# Bell Circuit
qr = QuantumRegister(2, name="qr")
cr = ClassicalRegister(2, name="cr")
qc = QuantumCircuit(qr, cr, name="bell")
qc.h(qr[0])
qc.cx(qr[0], qr[1])
qc.measure(qr, cr)
options = Options(optimization_level=3)
with Session(backend="ibmq_qasm_simulator") as session:
sampler = Sampler(session=session, options=options)
job = sampler.run(ReferenceCircuits.bell())
job = sampler.run(qc)
print(f"Sampler job ID: {job.job_id()}")
print(f"Sampler job result: {job.result()}")
Expand Down
44 changes: 0 additions & 44 deletions qiskit_ibm_runtime/test/ibm_runtime_service_mock.py

This file was deleted.

104 changes: 97 additions & 7 deletions test/ibm_test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,20 @@
import logging
import inspect
import warnings
from unittest import TestCase
from unittest.util import safe_repr
from contextlib import suppress
from collections import defaultdict
from typing import DefaultDict, Dict

from qiskit.test.reference_circuits import ReferenceCircuits
from qiskit.test.base import BaseQiskitTestCase

from qiskit_ibm_runtime import QISKIT_IBM_RUNTIME_LOGGER_NAME
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Options

from .utils import setup_test_logging
from .utils import setup_test_logging, bell
from .decorators import IntegrationTestDependencies, integration_test_setup


class IBMTestCase(BaseQiskitTestCase):
class IBMTestCase(TestCase):
"""Custom TestCase for use with qiskit-ibm-runtime."""

log: logging.Logger
Expand Down Expand Up @@ -69,6 +68,97 @@ def _set_logging_level(cls, logger: logging.Logger) -> None:
logger.addHandler(logging.StreamHandler())
logger.propagate = False

def assert_dict_almost_equal(
self, dict1, dict2, delta=None, msg=None, places=None, default_value=0
):
"""Assert two dictionaries with numeric values are almost equal.
Fail if the two dictionaries are unequal as determined by
comparing that the difference between values with the same key are
not greater than delta (default 1e-8), or that difference rounded
to the given number of decimal places is not zero. If a key in one
dictionary is not in the other the default_value keyword argument
will be used for the missing value (default 0). If the two objects
compare equal then they will automatically compare almost equal.
Args:
dict1 (dict): a dictionary.
dict2 (dict): a dictionary.
delta (number): threshold for comparison (defaults to 1e-8).
msg (str): return a custom message on failure.
places (int): number of decimal places for comparison.
default_value (number): default value for missing keys.
Raises:
TypeError: if the arguments are not valid (both `delta` and
`places` are specified).
AssertionError: if the dictionaries are not almost equal.
"""

error_msg = self.dicts_almost_equal(dict1, dict2, delta, places, default_value)

if error_msg:
msg = self._formatMessage(msg, error_msg)
raise self.failureException(msg)

def dicts_almost_equal(self, dict1, dict2, delta=None, places=None, default_value=0):
"""Test if two dictionaries with numeric values are almost equal.
Fail if the two dictionaries are unequal as determined by
comparing that the difference between values with the same key are
not greater than delta (default 1e-8), or that difference rounded
to the given number of decimal places is not zero. If a key in one
dictionary is not in the other the default_value keyword argument
will be used for the missing value (default 0). If the two objects
compare equal then they will automatically compare almost equal.
Args:
dict1 (dict): a dictionary.
dict2 (dict): a dictionary.
delta (number): threshold for comparison (defaults to 1e-8).
places (int): number of decimal places for comparison.
default_value (number): default value for missing keys.
Raises:
TypeError: if the arguments are not valid (both `delta` and
`places` are specified).
Returns:
String: Empty string if dictionaries are almost equal. A description
of their difference if they are deemed not almost equal.
"""

def valid_comparison(value):
"""compare value to delta, within places accuracy"""
if places is not None:
return round(value, places) == 0
else:
return value < delta

# Check arguments.
if dict1 == dict2:
return ""
if places is not None:
if delta is not None:
raise TypeError("specify delta or places not both")
msg_suffix = " within %s places" % places
else:
delta = delta or 1e-8
msg_suffix = " within %s delta" % delta

# Compare all keys in both dicts, populating error_msg.
error_msg = ""
for key in set(dict1.keys()) | set(dict2.keys()):
val1 = dict1.get(key, default_value)
val2 = dict2.get(key, default_value)
if not valid_comparison(abs(val1 - val2)):
error_msg += f"({safe_repr(key)}: {safe_repr(val1)} != {safe_repr(val2)}), "

if error_msg:
return error_msg[:-2] + msg_suffix
else:
return ""


class IBMIntegrationTestCase(IBMTestCase):
"""Custom integration test case for use with qiskit-ibm-runtime."""
Expand Down Expand Up @@ -163,7 +253,7 @@ def _run_program(
if inputs is not None
else {
"interim_results": interim_results or {},
"circuits": circuits or ReferenceCircuits.bell(),
"circuits": circuits or bell(),
}
)
pid = program_id or self.program_ids[service.channel]
Expand All @@ -184,7 +274,7 @@ def _run_program(
if max_execution_time:
options.max_execution_time = max_execution_time
sampler = Sampler(backend=backend, options=options)
job = sampler.run(circuits or ReferenceCircuits.bell(), callback=callback)
job = sampler.run(circuits or bell(), callback=callback)
else:
job = service.run(
program_id=pid,
Expand Down
6 changes: 3 additions & 3 deletions test/integration/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from qiskit.transpiler.target import Target
from qiskit import QuantumCircuit
from qiskit.providers.exceptions import QiskitBackendNotFoundError
from qiskit.test.reference_circuits import ReferenceCircuits

from qiskit_ibm_provider.ibm_qubit_properties import IBMQubitProperties
from qiskit_ibm_provider.exceptions import IBMBackendValueError
Expand All @@ -28,6 +27,7 @@

from ..ibm_test_case import IBMIntegrationTestCase
from ..decorators import run_integration_test, production_only, quantum_only
from ..utils import bell


class TestIntegrationBackend(IBMIntegrationTestCase):
Expand Down Expand Up @@ -243,7 +243,7 @@ def test_sim_backend_options(self):
backend = self.service.backend("ibmq_qasm_simulator")
backend.options.shots = 2048
backend.set_options(memory=True)
inputs = backend.run(ReferenceCircuits.bell(), shots=1, foo="foo").inputs
inputs = backend.run(bell(), shots=1, foo="foo").inputs
self.assertEqual(inputs["shots"], 1)
self.assertTrue(inputs["memory"])
self.assertEqual(inputs["foo"], "foo")
Expand All @@ -256,7 +256,7 @@ def test_paused_backend_warning(self):
paused_status.status_msg = "internal"
backend.status = mock.MagicMock(return_value=paused_status)
with self.assertWarns(Warning):
backend.run(ReferenceCircuits.bell())
backend.run(bell())

def test_backend_wrong_instance(self):
"""Test that an error is raised when retrieving a backend not in the instance."""
Expand Down
Loading

0 comments on commit 6365dd9

Please sign in to comment.