Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

One-shot for noise in Python #26

Merged
merged 4 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion catalyst
Submodule catalyst updated 370 files
40 changes: 33 additions & 7 deletions pennylane_qrack/qrack_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ def __init__(self, wires=0, shots=None, **kwargs):
self.isHostPointer = options['isHostPointer']
if 'noise' in options:
self.noise = options['noise']
if (self.noise != 0) and (shots is None):
WrathfulSpatula marked this conversation as resolved.
Show resolved Hide resolved
raise ValueError("Shots must be finite for noisy simulation (not analytical mode).")
super().__init__(wires=wires, shots=shots)
self._state = QrackSimulator(
self.num_wires,
Expand All @@ -200,6 +202,7 @@ def __init__(self, wires=0, shots=None, **kwargs):
isHostPointer=self.isHostPointer,
noise = self.noise
)
self._circuit = []
WrathfulSpatula marked this conversation as resolved.
Show resolved Hide resolved

def _reverse_state(self):
end = self.num_wires - 1
Expand All @@ -216,7 +219,14 @@ def apply(self, operations, **kwargs):
operations (List[pennylane.Operation]): operations to be applied
"""

for i, op in enumerate(operations):
self._circuit = self._circuit + operations
if self.noise == 0:
self._apply()
self._circuit = []
# else: Defer application until shots or expectation values are requested

def _apply(self):
for op in self._circuit:
if isinstance(op, QubitStateVector):
self._apply_qubit_state_vector(op)
elif isinstance(op, BasisState):
Expand Down Expand Up @@ -647,20 +657,36 @@ def expval(self, observable, **kwargs):
# estimate the ev
return np.mean(self.sample(observable))


def _generate_sample(self):
rev_sample = self._state.m_all()
sample = 0
for i in range(self.num_wires):
if (rev_sample & (1 << i)) > 0:
WrathfulSpatula marked this conversation as resolved.
Show resolved Hide resolved
sample |= 1 << (self.num_wires - (i + 1))
return sample


def generate_samples(self):
if self.shots is None:
raise qml.QuantumFunctionError(
"The number of shots has to be explicitly set on the device "
"when using sample-based measurements."
)

if self.noise != 0:
self._samples = []
for _ in range(self.shots):
self._state.reset_all()
self._apply()
self._samples.append(self._generate_sample())
self._samples = QubitDevice.states_to_binary(np.array([self._generate_sample()]), self.num_wires)
self._circuit = []

return self._samples

if self.shots == 1:
rev_sample = self._state.m_all()
sample = 0
for i in range(self.num_wires):
if (rev_sample & (1 << i)) > 0:
sample |= 1 << (self.num_wires - (i + 1))
self._samples = QubitDevice.states_to_binary(np.array([sample]), self.num_wires)
self._samples = QubitDevice.states_to_binary(np.array([self._generate_sample()]), self.num_wires)

return self._samples

Expand Down