Skip to main content

qsample

Install

pip install qsample

Prerequisites

  • python3
  • pdflatex (for circuit rendering)

When to use

  • For QEC protocols with in-sequence measurements and feed-forward of measurement information
  • Apply circuit-level incoherent Pauli noise at low physical error rates (i.e. high fidelity physical operations)
  • Simulate and sample protocol execution over ranges of varying physical error rates, using customizable callbacks

Getting started

import qsample as qs  # import qsample
import matplotlib.pyplot as plt  # import matplotlib for visualization of results

First, we need to define a quantum protocol of which we would like to know the logical error rate. In qsample a protocol is represented as a graph of quantum Circuits as nodes and transition checks (to be checked at samplingt ime) as edges.

Example: To sample logical error rates of an error-corrected quantum state teleportation protocol, we define the teleportation circuit which sends the state of the first to the third qubit.

teleport = qs.Circuit([{"init": {0, 1, 2}},
                       {"H": {1}},
                       {"CNOT": {(1, 2)}},
                       {"CNOT": {(0, 1)}},
                       {"H": {0}},
                       {"measure": {0, 1}}])

teleport.draw()

Additionally, we need a circuit to (perfectly) measure the third qubit after running teleport. If the outcome of this measurement is 0 (corresponding to the initially prepared $|0\rangle$ state of qubit 1) the teleportation succeded. If the outcome is 1 however, we want to count a logical failure of this protocol. Let’s create a circuit for this measurement and let’s assume we can perform this measurement without noise.

meas = qs.Circuit([{"measure": {2}}], noisy=False)

Between the teleport and meas circuits apply a correction to qubit 3 conditioned on the measurement outcome (syndrome) of the teleportation circuit. We define the lookup function lut

def lut(syn):
    op = {0: 'I', 1: 'X', 2: 'Z', 3: 'Y'}[syn]
    return qs.Circuit([{op: {2}}], noisy=False)

Finally, define the circuit sequence and transition logic together within a Protocol object. Note that protocols must always commence with a unique START node and terminate at a unique FAIL node, where the latter expresses a logical failure event.

tele_proto = qs.Protocol(check_functions={'lut': lut})
tele_proto.add_nodes_from(['tele', 'meas'], circuits=[teleport, meas])
tele_proto.add_edge('START', 'tele', check='True')
tele_proto.add_edge('tele', 'COR', check='lut(tele[-1])')
tele_proto.add_edge('COR', 'meas', check='True')
tele_proto.add_edge('meas', 'FAIL', check='meas[-1] == 1')

tele_proto.draw(figsize=(8,5))

Notice that we do not define any initial circuit for the correction COR but pass our lookup function to the check_functions dictionary, which makes it accessible inside the check transition statements (edges) between circuits. This way we can dynamically insert circuits into the protocol at execution time.

After the protocol has been defined we can repeatedly execute (i.e. sample) it in the presence of incoherent noise. Let’s say we are interested in the logical error rates for physical error rates on all 1- and 2-qubit gates of $p_{phy}=10^{-5}, \dots, 10^{-1}$, and $0.5$. The corresponding noise model is called E1 in qsample. The groups of all 1- and 2-qubit gates are indexed by the key q in E1. Other noise models (and their parameters) are described in the documentation.

err_model = qs.noise.E1
err_params = {'q': [1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 0.5]}

We are ready to sample. As our protocol only contains Clifford gates let’s choose the StabilizerSimulator, as well as the PlotStats callback for plotting the resulting logical error rate as function of $p_{phy}$.

sam = qs.DirectSampler(protocol=tele_proto, simulator=qs.StabilizerSimulator, err_model=err_model, err_params=err_params)
sam.run(n_shots=20000, callbacks=[qs.callbacks.PlotStats()])
p=('1.00e-05',):   0%|          | 0/20000 [00:00<?, ?it/s]

p=('1.00e-04',):   0%|          | 0/20000 [00:00<?, ?it/s]

p=('1.00e-03',):   0%|          | 0/20000 [00:00<?, ?it/s]

p=('1.00e-02',):   0%|          | 0/20000 [00:00<?, ?it/s]

p=('1.00e-01',):   0%|          | 0/20000 [00:00<?, ?it/s]

p=('5.00e-01',):   0%|          | 0/20000 [00:00<?, ?it/s]

Notice, that at low error rates DirectSampler performs badly, i.e. the error bars become very large, as most of the time the protocol is executed error free and, consequently, logical errors are measured infrequently. In this regime it is much more efficient to use an importance sampling strategy to avoid fault-free protocol execution and instead put more emphasis on execution with at least one fault happening. This approach is implemented in the SubsetSampler class. We only need to specify two additional parameter p_max which specifies the $p_{phy}$ at which sampling takes place, and L, the length of the longest possible fault-free path. The parameter p_max must be chosen experimentally by repeated sampling and observing which subsets have the largest impact on the failure rate. We must always choose a value such that the subset occurence probability has an exponentially falling shape. Only in this case are the scaling of the sampler results valid. Below we see that for the teleportation circuit p_max-values of 0.01 and 0.1 are still okay, while 0.3 would be problematic. For more information refer to the linked publication.

for p_phy in [0.01, 0.1, 0.3]:
    Aws = qs.math.subset_probs(teleport, err_model(), p_phy)
    plt.figure()
    plt.title("Subset occurence prob. $A_w$ at $p_{phy}$=%.2f" % p_phy)
    plt.bar(list(map(str,Aws.keys())), Aws.values())
    plt.ylabel("$A_w$")
    plt.xlabel("Subsets")

Let’s choose a $p_{max}=0.1$ for the same error model as before and start sampling. (Note the significant difference in the number of samples).

ss_sam = qs.SubsetSampler(protocol=tele_proto, simulator=qs.StabilizerSimulator,  p_max={'q': 0.1}, err_model=err_model, err_params=err_params, L=3)
ss_sam.run(1000, callbacks=[qs.callbacks.PlotStats()])
p=('1.00e-01',):   0%|          | 0/1000 [00:00<?, ?it/s]

The sampling results are internally stored by the SubsetSampler in a Tree data structure. In the tree we can also see why we chose L=3, as there are three circuits in the fault-free path sequence.

ss_sam.tree.draw(verbose=True)

We see that only the teleportation protocol has fault weight subsets, while the meas and COR circuits are noise-free (i.e. they only have the 0-subset). The leaf nodes FAIL and None represent logical failure and successful teleportation events, respectively. $\delta$ represents the missing subsets which have not been sampled and which result in the upper bound on the failure rate.

Finally, let’s compare the results of DirectSampler and SubsetSampler.

p_L_low, std_low, p_L_up, std_up = ss_sam.stats()
p_L, std = sam.stats()

sample_range = err_params['q']
plt.errorbar(sample_range, p_L, fmt='--', c="black", yerr=std, label="Direct MC")
plt.loglog(sample_range, p_L_low, label='SS low')
plt.fill_between(sample_range, p_L_low - std_low, p_L_low + std_low, alpha=0.2)
plt.loglog(sample_range, p_L_up, label='SS low')
plt.fill_between(sample_range, p_L_up - std_up, p_L_up + std_up, alpha=0.2)
plt.plot(sample_range, sample_range,'k:', alpha=0.5)
plt.xlabel('$p_{phy}$(q)')
plt.ylabel('$p_L$')
plt.legend();

More things to explore

  • qsample.examples shows more examples of protocol and protocol samplings.
  • qsample.noise defines more complex error models, as well as a superclass ErrorModel which can be used to define custom error models.
  • qsample.callbacks defines more callbacks, as well as the superclass Callback which allows for the implementation of custom callbacks.

Contribute

  • Feel free to submit your feature request via github issues

Team

qsample was developed by Don Winter in collaboration with Sascha Heußen under supervision of Prof. Dr. Markus Müller.

Metadata

Release files for qsample 0.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qsample 0.0.2
File Size Uploaded Provenance Actions
qsample-0.0.2.tar.gz 43.8 kB Without provenance Details for qsample-0.0.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for qsample 0.0.2
File Interpreter ABI Platform Actions
qsample-0.0.2-py3-none-any.whl Python 3 none any Details for qsample-0.0.2-py3-none-any.whl

Total release size: 88.5 kB

Release files / qsample-0.0.2.tar.gz

Download URL qsample-0.0.2.tar.gz
Size 43.8 kB
Tags Source
SHA-256 checksum
How to use checksums
92be0415d3ef45b574fc57f4eb242f5a0c182a4028029c2b18cc14bb42e33102
BLAKE2b-256 checksum
How to use checksums
bb55c0d0a6ab89c17dfe294425ec3cd32bebf61a8d23864383fca4f5cae856f8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.10.12

Release files / qsample-0.0.2-py3-none-any.whl

Download URL qsample-0.0.2-py3-none-any.whl
Size 44.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b6a85139dec3ab69e49b18b1b2f608814415efd2d07875b278a3644a42db58d2
BLAKE2b-256 checksum
How to use checksums
ae258dd8096cad59b98de59737c7ff7bfb9535d86216c5a95e403d06fc005c7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.10.12

Security for qsample 0.0.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.0.2 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page