Skip to content

Commit

Permalink
Merge branch 'master' into workflow-badge-update
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-Preciado authored Oct 27, 2023
2 parents 074459c + 6f566d4 commit d9968c9
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 17 deletions.
50 changes: 35 additions & 15 deletions pennylane_qiskit/qiskit_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,6 @@ class QiskitDevice(QubitDevice, abc.ABC):
def __init__(self, wires, provider, backend, shots=1024, **kwargs):
super().__init__(wires=wires, shots=shots)

# Keep track if the user specified analytic to be True
if shots is None and backend not in self._state_backends:
# Raise a warning if no shots were specified for a hardware device
warnings.warn(self.hw_analytic_warning_message.format(backend), UserWarning)

self.shots = 1024

self.provider = provider

if isinstance(backend, Backend):
Expand All @@ -181,7 +174,14 @@ def __init__(self, wires, provider, backend, shots=1024, **kwargs):

self.backend_name = _get_backend_name(self._backend)

self._capabilities["returns_state"] = self.backend_name in self._state_backends
# Keep track if the user specified analytic to be True
if shots is None and not self._is_state_backend:
# Raise a warning if no shots were specified for a hardware device
warnings.warn(self.hw_analytic_warning_message.format(backend), UserWarning)

self.shots = 1024

self._capabilities["returns_state"] = self._is_state_backend

# Perform validation against backend
b = self.backend
Expand Down Expand Up @@ -225,6 +225,26 @@ def process_kwargs(self, kwargs):
# Consider the remaining kwargs as keyword arguments to run
self.run_args.update(kwargs)

@property
def _is_state_backend(self):
"""Returns whether this device has a state backend."""
return self.backend_name in self._state_backends or self.backend.options.get("method") in {
"unitary",
"statevector",
}

@property
def _is_statevector_backend(self):
"""Returns whether this device has a statevector backend."""
method = "statevector"
return method in self.backend_name or self.backend.options.get("method") == method

@property
def _is_unitary_backend(self):
"""Returns whether this device has a unitary backend."""
method = "unitary"
return method in self.backend_name or self.backend.options.get("method") == method

def set_transpile_args(self, **kwargs):
"""The transpile argument setter.
Expand Down Expand Up @@ -278,7 +298,7 @@ def create_circuit_object(self, operations, **kwargs):
for circuit in applied_operations:
self._circuit &= circuit

if self.backend_name not in self._state_backends:
if not self._is_state_backend:
# Add measurements if they are needed
for qr, cr in zip(self._reg, self._creg):
self._circuit.measure(qr, cr)
Expand Down Expand Up @@ -357,7 +377,7 @@ def qubit_state_vector_check(self, operation):
DeviceError: If the operation is QubitStateVector or StatePrep
"""
if operation in ("QubitStateVector", "StatePrep"):
if "unitary" in self.backend_name:
if self._is_unitary_backend:
raise DeviceError(
f"The {operation} operation "
"is not supported on the unitary simulator backend."
Expand All @@ -382,7 +402,7 @@ def run(self, qcirc):
self._current_job = self.backend.run(qcirc, shots=self.shots, **self.run_args)
result = self._current_job.result()

if self.backend_name in self._state_backends:
if self._is_state_backend:
self._state = self._get_state(result)

def _get_state(self, result, experiment=None):
Expand All @@ -395,10 +415,10 @@ def _get_state(self, result, experiment=None):
Returns:
array[float]: size ``(2**num_wires,)`` statevector
"""
if "statevector" in self.backend_name:
if self._is_statevector_backend:
state = np.asarray(result.get_statevector(experiment))

elif "unitary" in self.backend_name:
elif self._is_unitary_backend:
unitary = np.asarray(result.get_unitary(experiment))
initial_state = np.zeros([2**self.num_wires])
initial_state[0] = 1
Expand All @@ -422,7 +442,7 @@ def generate_samples(self, circuit=None):
"""

# branch out depending on the type of backend
if self.backend_name in self._state_backends:
if self._is_state_backend:
# software simulator: need to sample from probabilities
return super().generate_samples()

Expand Down Expand Up @@ -491,7 +511,7 @@ def batch_execute(self, circuits, timeout: int = None):
self.tracker.update(executions=1, shots=self.shots)
self.tracker.record()

if self.backend_name in self._state_backends:
if self._is_state_backend:
self._state = self._get_state(result, experiment=circuit_obj)

# generate computational basis samples
Expand Down
4 changes: 2 additions & 2 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ def test_rotation(self, init_state, state_vector_device, shots, tol):

dev = state_vector_device(1)

if "unitary" in dev.backend_name:
if dev._is_unitary_backend:
pytest.skip("Test only runs for backends that are not the unitary simulator.")

state = init_state(1)
Expand Down Expand Up @@ -480,7 +480,7 @@ def test_noise_applied(self):
bit_flip = aer.noise.pauli_error([("X", 1), ("I", 0)])

# Create a noise model where the RX operation always flips the bit
noise_model.add_all_qubit_quantum_error(bit_flip, ["z"])
noise_model.add_all_qubit_quantum_error(bit_flip, ["z", "rz"])

dev = qml.device("qiskit.aer", wires=2, noise_model=noise_model)

Expand Down

0 comments on commit d9968c9

Please sign in to comment.