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

Add optional readout error correction to Quantum Volume #2522

Merged
merged 11 commits into from
Nov 15, 2019
Merged

Add optional readout error correction to Quantum Volume #2522

merged 11 commits into from
Nov 15, 2019

Conversation

KevinVillela
Copy link
Contributor

This adds a parity qubit for each regular qubit in the compiled circuit. Each result where these qubits don't match up will be thrown out.

@googlebot googlebot added the cla: yes Makes googlebot stop complaining. label Nov 11, 2019
@KevinVillela KevinVillela changed the title Add optional readout error correction Add optional readout error correction to Quantum Volume Nov 11, 2019
v: k for k, v in mapping.items()
}

for final_qubit, original_qubit in mapping.items():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work?

data = trial_result.data
bad_measurements = set()
for q, pf in parity_mapping.items():
    p = inverse_mapping[pf]
    mismatches = np.nonzero(data[str(q)] != data[str(p)])
    bad_measurements.update(mismatches)

Or more involved:

data = trial_result.data
kept = np.ones(data.shape[0], dtype=np.bool)
for q, pf in parity_mapping.items():
    p = inverse_mapping[pf]
    kept &= data[str(q)] == data[str(p)]
return data.where(kept)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, something similar to that does. Thanks, much cleaner now!

Copy link
Collaborator

@mpharrigan mpharrigan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

  • prefer odd-parity encoding (see comment). You can do in follow-up pr
  • some other optional style things

# Add measure gates to the end of (a copy of) the circuit. Ensure that those
# gates measure those in the given mapping, preserving this order.
qubits = circuit.all_qubits()
key = None
if mapping:
# Add any qubits that were not explicitly mapped, so they aren't lost in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could do key = lambda q: mapping.get(q, q) if you don't actually need these in mapping

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, done.

final_parity_qubit = inverse_mapping[parity_qubit]
parity_meas = trial_result.measurements[str(final_parity_qubit)]
# Check each bit's parity qubit results to see if they are correct.
for idx, qubit_val in enumerate(qubit_meas):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I bet this could be faster with vectorized numpy operations

correct_strings = np.ones(dtype=bool)
for dataq, parityq in whatever:
  parity_check = (measurements[dataq] == measurements[parityq])
  correct_strings = np.logical_and(correct_strings, parity_check)
bitstrings = bitstrings[correct_strings]

(roughly)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that this should be improved - @Strilanc has a similar idea that uses the Pandas DataFrame directly, so I went with that.

@@ -338,6 +437,12 @@ def calculate_quantum_volume(
routing_attempts: The number of times to route each model circuit onto
the device. Each attempt will be graded using an ideal simulator
and the best one will be used.
add_readout_error_correction: If true, add some parity bits that willx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

willx -> will

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

add_readout_error_correction: If true, add some parity bits that willx
later be used to detect readout error. WARNING: This makes the
simulator run extremely slowly for any width/depth of 4 or more,
probably because it doubles the circuit size. In reality, the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can probably strike "probably" :) This is indeed the reason

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha good to know, thanks.

@@ -264,6 +360,8 @@ def execute_circuits(
compiler: An optional function to compiler the model circuit's
gates down to the target devices gate set and the optimize it.
repetitions: The number of bitstrings to sample per circuit.
add_readout_error_correction: If true, add some parity bits that willx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

willx -> will

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

# Sort just to make it deterministic.
for idx, qubit in enumerate(sorted(compiled_circuit.all_qubits())):
# For each qubit, create a new qubit that will serve as its parity
# check. This parity bit is initialized to 0 and then CNOTed with
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

readout error is asymmetric: p(0|0) > p(1|1). You can account for that by encoding into the single-excitation subspace; i.e. use an inverse-controlled not: X CNOT X to encode 0 -> 01 and 1 -> 10 so you (should) always readout one 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat, I did not know that - Fixed. Out of curiosity, why is readout error asymmetric? Is that just for our device, or for all devices?

Also, probably a dumb question, but could I instead do X(ancilla) CNOT(physical, ancilla) instead of X(physical) CNOT(physical, ancilla) X(physical) ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readout takes longer than gates (~1000ns vs 10) so the qubit can undergo T1 decay during readout (see cirq.contrib.noise_models). I think it's fairly common in superconducting architectures like ours.

You could do the suggested alternate, but please make sure that the X(ancilla) is done as late as possible. If cirq is left to its own devices, the X will happen at the beginning, the qubit will be hanging out in |1> and could more readily undergo T1 decay

@mpharrigan mpharrigan added the automerge Tells CirqBot to sync and merge this PR. (If it's running.) label Nov 15, 2019
@CirqBot CirqBot added the front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. label Nov 15, 2019
@CirqBot CirqBot merged commit 3a4d8a7 into quantumlib:master Nov 15, 2019
@CirqBot CirqBot removed automerge Tells CirqBot to sync and merge this PR. (If it's running.) front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. labels Nov 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Makes googlebot stop complaining.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants