-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Use Rust generator function for QuantumVolume class #13283
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -83,39 +83,48 @@ def __init__( | |||||
depth = depth or num_qubits # how many layers of SU(4) | ||||||
width = num_qubits // 2 # how many SU(4)s fit in each layer | ||||||
rng = seed if isinstance(seed, np.random.Generator) else np.random.default_rng(seed) | ||||||
seed_name = seed | ||||||
if seed is None: | ||||||
# Get the internal entropy used to seed the default RNG, if no seed was given. This | ||||||
# stays in the output name, so effectively stores a way of regenerating the circuit. | ||||||
# This is just best-effort only, for backwards compatibility, and isn't critical (if | ||||||
# someone needs full reproducibility, they should be manually controlling the seeding). | ||||||
seed = getattr(getattr(rng.bit_generator, "seed_seq", None), "entropy", None) | ||||||
seed_name = getattr(getattr(rng.bit_generator, "seed_seq", None), "entropy", None) | ||||||
|
||||||
super().__init__( | ||||||
num_qubits, name="quantum_volume_" + str([num_qubits, depth, seed]).replace(" ", "") | ||||||
num_qubits, | ||||||
name="quantum_volume_" + str([num_qubits, depth, seed_name]).replace(" ", ""), | ||||||
) | ||||||
base = self if flatten else QuantumCircuit(num_qubits, name=self.name) | ||||||
|
||||||
# For each layer, generate a permutation of qubits | ||||||
# Then generate and apply a Haar-random SU(4) to each pair | ||||||
unitaries = scipy.stats.unitary_group.rvs(4, depth * width, rng).reshape(depth, width, 4, 4) | ||||||
qubits = tuple(base.qubits) | ||||||
for row in unitaries: | ||||||
perm = rng.permutation(num_qubits) | ||||||
if classical_permutation: | ||||||
for w, unitary in enumerate(row): | ||||||
gate = UnitaryGate(unitary, check_input=False, num_qubits=2) | ||||||
qubit = 2 * w | ||||||
base._append( | ||||||
CircuitInstruction(gate, (qubits[perm[qubit]], qubits[perm[qubit + 1]])) | ||||||
) | ||||||
if classical_permutation: | ||||||
if seed is not None: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be slower than usual as I'm reviewing this before my first coffee, but should this be the following?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is actually correct. This code path is to normalize the seeds we pass to rust so it will fit in a uint64 (although I realized I used int64 by mistake, I'll fix that). The typing on the python class was a python int which was doesn't have an upper bound and it was possible to pass in an value greater than 18446744073709551615 which would cause an error when one didn't happen before. To solve that I used a numpy rng to select a random int from the provided seed value that we then pass to rust as a seed for it's internal rng. When |
||||||
seed = rng.integers(0, dtype=np.int64) | ||||||
qv_circ = quantum_volume(num_qubits, depth, seed) | ||||||
qv_circ.name = self.name | ||||||
if flatten: | ||||||
self.compose(qv_circ, inplace=True) | ||||||
Cryoris marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
else: | ||||||
self._append(CircuitInstruction(qv_circ.to_instruction(), tuple(self.qubits))) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we instead just early-return here instead of having the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't return because There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think pylint is fine with bare There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, that's probably it, I normally would do |
||||||
else: | ||||||
if seed is None: | ||||||
seed = seed_name | ||||||
|
||||||
base = self if flatten else QuantumCircuit(num_qubits, name=self.name) | ||||||
|
||||||
# For each layer, generate a permutation of qubits | ||||||
# Then generate and apply a Haar-random SU(4) to each pair | ||||||
unitaries = scipy.stats.unitary_group.rvs(4, depth * width, rng).reshape( | ||||||
depth, width, 4, 4 | ||||||
) | ||||||
qubits = tuple(base.qubits) | ||||||
for row in unitaries: | ||||||
perm = rng.permutation(num_qubits) | ||||||
base._append(CircuitInstruction(PermutationGate(perm), qubits)) | ||||||
for w, unitary in enumerate(row): | ||||||
gate = UnitaryGate(unitary, check_input=False, num_qubits=2) | ||||||
qubit = 2 * w | ||||||
base._append(CircuitInstruction(gate, qubits[qubit : qubit + 2])) | ||||||
if not flatten: | ||||||
self._append(CircuitInstruction(base.to_instruction(), tuple(self.qubits))) | ||||||
if not flatten: | ||||||
self._append(CircuitInstruction(base.to_instruction(), tuple(self.qubits))) | ||||||
|
||||||
|
||||||
def quantum_volume( | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it would be clearer to check if
seed_name
isNone
instead, since the purpose of this branch is to make sure it has a value.