scalerqec package

Subpackages

Submodules

scalerqec.interface module

bits_split.py

Read a text file whose lines are 0-1 bit-strings. For every line

abc…xyz

all but the final bit (“abc…y”) become one row of the state matrix, and the final bit (“z”) becomes one row of the observable vector.

Example

Input file lines:

000000000 010101011 111111110

Output (JSON): [

[[false,false,false,false,false,false,false,false],

[false,false,false,false,false,false,false,false], [true,true,true,true,true,true,true,true]],

[[false],[true],[false]]

]

scalerqec.interface.main()[source]
scalerqec.interface.parse_line(line: str)[source]

Return (state_row, observable_row) or None for blank lines.

scalerqec.interface.read_file(path: Path)[source]

Produce two nested-list structures: states and observables.

scalerqec.qepg module

Pybind11 bindings for QEPG library

class scalerqec.qepg.CliffordCircuit

Bases: pybind11_object

compile_from_rewrited_stim_string(self: scalerqec.qepg.CliffordCircuit, prog_str: str) None

Compile circuit from Stim string

get_num_detector(self: scalerqec.qepg.CliffordCircuit) int
get_num_noise(self: scalerqec.qepg.CliffordCircuit) int
get_num_qubit(self: scalerqec.qepg.CliffordCircuit) int
class scalerqec.qepg.DynamicBitset

Bases: pybind11_object

size(self: scalerqec.qepg.DynamicBitset) int

Get the size of the bitset

test(self: scalerqec.qepg.DynamicBitset, pos: SupportsInt) bool

Test if the bit at position pos is set

to_list(self: scalerqec.qepg.DynamicBitset) list[bool]

Convert the bitset to a list of booleans

class scalerqec.qepg.QEPGGraph

Bases: pybind11_object

backward_graph_construction(self: scalerqec.qepg.QEPGGraph) None
class scalerqec.qepg.Sampler

Bases: pybind11_object

scalerqec.qepg.compile_QEPG(prog_str: str) scalerqec.qepg.QEPGGraph

compile_QEPG(prog_str: str) → QEPGGraph Parse a Stim‐style program string into a QEPGGraph object, run its backward_graph_construction() pass, and return it.

scalerqec.qepg.return_detector_matrix(prog_str: str) list[list[bool]]

Function that returns the detector matrix

scalerqec.qepg.return_samples(prog_str: str, weight: SupportsInt, shots: SupportsInt) list[list[bool]]

Function that returns samples based on a circuit and parameters

scalerqec.qepg.return_samples_Monte_separate_obs_with_QEPG(graph: scalerqec.qepg.QEPGGraph, error_rate: SupportsFloat, shot: SupportsInt) tuple[numpy.typing.NDArray[numpy.bool], numpy.typing.NDArray[numpy.bool]]

Function that returns samples based on a QEPG with monte carlo method

scalerqec.qepg.return_samples_many_weights(prog_str: str, weight: collections.abc.Sequence[SupportsInt], shots: collections.abc.Sequence[SupportsInt]) list[list[list[bool]]]

Function that returns samples of a list of weights based on a circuit and parameters

scalerqec.qepg.return_samples_many_weights_numpy(prog_str: str, weight: collections.abc.Sequence[SupportsInt], shots: collections.abc.Sequence[SupportsInt]) list[numpy.typing.NDArray[numpy.bool]]

Function that returns samples of a list of weights based on a circuit and parameters, it return numpy vector directly

scalerqec.qepg.return_samples_many_weights_separate_obs(prog_str: str, weight: collections.abc.Sequence[SupportsInt], shots: collections.abc.Sequence[SupportsInt]) tuple[numpy.typing.NDArray[numpy.bool], numpy.typing.NDArray[numpy.bool]]
scalerqec.qepg.return_samples_many_weights_separate_obs_with_QEPG(graph: scalerqec.qepg.QEPGGraph, weight: collections.abc.Sequence[SupportsInt], shots: collections.abc.Sequence[SupportsInt]) tuple[numpy.typing.NDArray[numpy.bool], numpy.typing.NDArray[numpy.bool]]
scalerqec.qepg.return_samples_numpy(prog_str: str, weight: SupportsInt, shots: SupportsInt) numpy.typing.NDArray[numpy.bool]

Function that directly return numpy array

scalerqec.qepg.return_samples_with_fixed_QEPG(graph: scalerqec.qepg.QEPGGraph, weight: SupportsInt, shots: SupportsInt) list[list[bool]]

Function that returns samples based on a QEPG

scalerqec.qepg.return_samples_with_noise_vector(prog_str: str, weight: SupportsInt, shots: SupportsInt) tuple[list[list[tuple[int, int]]], list[list[bool]]]

Module contents

ScaLER: Scalable Logical Error Rate Estimation Toolkit

class scalerqec.CliffordCircuit(qubit_num)[source]

Bases: object

add_cnot(control, target)[source]
add_cz(qubit1, qubit2)[source]
add_depolarize(qubit)[source]
add_hadamard(qubit)[source]
add_measurement(qubit)[source]
add_paulix(qubit)[source]
add_pauliy(qubit)[source]
add_pauliz(qubit)[source]
add_phase(qubit)[source]
add_reset(qubit)[source]
add_xflip_noise(qubit)[source]
compile_detector_and_observable()[source]
compile_from_stim_circuit_str(stim_str)[source]
property error_rate
property gatelists
get_measIdx_to_parityIdx(measIdx)[source]
get_yquant_latex()[source]

Convert the circuit (stored in self._gatelists) into a yquant LaTeX string. This version simply prints each gate (or noise box) in the order they appear, without grouping or any fancy logic.

property observable
property parityMatchGroup
property qubit_num
property qubitnum
read_circuit_from_file(filename)[source]
reset_noise_type()[source]
save_circuit_to_file(filename)[source]
setShowNoise(show)[source]
set_noise_type(noiseindex, noisetype)[source]
show_all_noise()[source]
property stim_str
property stimcircuit
property totalMeas
property totalnoise
class scalerqec.StabCode(n: int, k: int, d: int)[source]

Bases: object

A class representing a quantum error-correcting code (QECC) using the stabilizer formalism.

add_stab(stab: str) None[source]

Add a stabilizer generator to the code.

Parameters:

stab (str) – A string representation of the stabilizer generator.

property circuit: None

Get the Clifford circuit for the quantum error-correcting code.

Returns:

The Clifford circuit.

compile_stim_circuit_from_IR_standard() None[source]

Compile the stim circuit from the intermediate representation (IR).

Returns:

The compiled stim circuit as a string.

Return type:

str

construct_IR_standard_scheme()[source]

Construct the quantum error-correcting circuit using the standard scheme. Now, we will create the intermediate representation (IR) for the circuit.

construct_circuit()[source]

Construct the quantum error-correcting circuit based on the stabilizers and scheme.

There is a two step compilation:

First, compile the stabilizers into an intermediate representation (IR) of the circuit. Second, translate the IR into a Clifford circuit. In IR, there is no concept of qubits, only Pauli operators, detectors, observables, and their relationships.

The IR has the form:

c0 = Prop XYZIX c1 = Prop IXYZI d0 = Parity c0 c1 o0 = Parity c0

construct_parity_check_matrix() None[source]

Construct the standard XZ parity check matrix for the quantum error-correcting code.

Returns:

The parity check matrix.

property d: int

Get the distance of the QECC.

Returns:

The distance.

Return type:

int

get_parity_check_matrix() None[source]

Get the standard XZ parity check matrix for the quantum error-correcting code.

Returns:

The parity check matrix.

init_by_parity_check_matrix(paritymatrix: ndarray) None[source]

Initialize the QECC stabilizer structures using a given parity check matrix.

Parameters:

paritymatrix (np.ndarray) – The parity check matrix.

is_IR_compiled() bool[source]

Check if the intermediate representation (IR) has been compiled.

Returns:

True if the IR is compiled, False otherwise.

Return type:

bool

is_circuit_compiled() bool[source]

Check if the quantum error-correcting circuit has been compiled.

Returns:

True if the circuit is compiled, False otherwise.

Return type:

bool

property k: int

Get the number of logical qubits in the QECC.

Returns:

The number of logical qubits.

Return type:

int

property n: int

Get the number of physical qubits in the QECC.

Returns:

The number of physical qubits.

Return type:

int

property noisemodel: NoiseModel

Get the noise model associated with the QECC.

Returns:

The noise model.

Return type:

NoiseModel

property rounds: int

Get the number of error correction rounds.

Returns:

The number of rounds.

Return type:

int

property scheme: SCHEME

Get the error correction scheme for the code.

Returns:

The error correction scheme.

Return type:

SCHEME

set_logical_Z(index: int, logicalZ: str) None[source]

Set the logical Z operator for a given logical qubit.

Parameters:
  • index (int) – The index of the logical qubit.

  • logicalZ (str) – A string representation of the logical Z operator.

show_IR()[source]

Display the intermediate representation of the quantum error-correcting circuit.

The IR has the form:

property stimcirc: None

Get the stimulus circuit for the quantum error-correcting code.

Returns:

The stimulus circuit.

class scalerqec.MonteLERcalc(time_budget=10, samplebudget=100000, MIN_NUM_LE_EVENT=3)[source]

Bases: object

calculate_LER_from_StabCode(qeccirc: StabCode, noise_model: NoiseModel, repeat=1)[source]

Calculate the logical error rate from a StabCode object using Monte Carlo sampling.

calculate_LER_from_file(samplebudget, filepath, pvalue, repeat=1)[source]
calculate_LER_from_file_sinter(samplebudget, filepath, pvalue, repeat=1)[source]
calculate_LER_from_my_random_sampler(samplebudget, filepath, pvalue, repeat=1)[source]
calculate_standard_error()[source]

Calculate the standard error of the LER.

get_sample_used()[source]
class scalerqec.StratifiedLERcalc(error_rate=0, sampleBudget=10000, num_subspace=30)[source]

Bases: object

calculate_LER_from_StabCode(qeccirc: StabCode, noise_model: NoiseModel, repeat=1)[source]
calculate_LER()[source]
calculate_LER_from_file(filepath, pvalue)[source]
clear_all()[source]
determine_range_to_sample(epsilon=0.01)[source]

We need to be exact about the range of w we want to sample. We don’t want to sample too many subspaces, especially those subspaces with tiny binomial weights. This should comes from the analysis of the weight of each subspace.

We use the standard deviation to approimxate the range

get_LER_subspace(weight)[source]
get_LER_subspace_no_weight(weight)[source]
parse_from_file(filepath)[source]

Read the circuit, parse from the file

sample_all_subspace(shots_each_subspace=1000000)[source]

Aggressively sample all the subspace. This function is only used to test the correctness of the algorithm.

subspace_sampling()[source]

Sample around the subspaces.

class scalerqec.StratifiedScurveLERcalc(error_rate=0, sampleBudget=10000, k_range=3, num_subspace=5, beta=4)[source]

Bases: object

binary_search_lower(low, high, shots=5000)[source]
binary_search_upper(low, high, shots)[source]
calculate_LER_from_StabCode(qeccirc: StabCode, noise_model: NoiseModel, figname, titlename, repeat=1)[source]
calc_logical_error_rate_after_curve_fitting()[source]
calc_logical_error_rate_with_fixed_w(shots, w)[source]

Calculate the logical error rate with fixed w

calculate_LER()[source]
calculate_LER_from_file(filepath, pvalue, codedistance, figname, titlename, repeat=1)[source]
calculate_R_square_score()[source]
clear_all()[source]
determine_lower_w()[source]
determine_range_to_sample()[source]

We need to be exact about the range of w we want to sample. We don’t want to sample too many subspaces, especially those subspaces with tiny binomial weights. This should comes from the analysis of the weight of each subspace.

We use the standard deviation to approimxate the range

determine_saturated_w(shots=1000)[source]

Use binary search to determine the minw and maxw

fast_calculate_LER_from_file(filepath, pvalue, codedistance, figname, titlename, repeat=1)[source]
fit_Scurve()[source]
fit_linear_area()[source]
fit_log_S_model(filename, time=None)[source]
get_LER_subspace(weight)[source]
ground_truth_subspace_sampling()[source]

Sample around the subspaces. This is the ground truth value to test the accuracy of the curve fitting.

load_all_sample_result(filepath)[source]
parse_from_file(filepath)[source]

Read the circuit, parse from the file

plot_scurve(filename, title='S-curve')[source]

Plot the S-curve and its discrete estimate.

sample_all_subspaces(Nclip, Budget, save_path=None)[source]

Sample all subspaces from minw to maxw return the result of these samples as two dictionary

set_sample_bound(MIN_NUM_LE_EVENT, SAMPLE_GAP, MAX_SAMPLE_GAP, MAX_SUBSPACE_SAMPLE)[source]

Set the sample bound for the subspace sampling

set_t(t)[source]

Set the t value for the S-curve fitting. This is used to determine the range of subspace we need to sample.

subspace_sampling()[source]

wlist store the subset of weights we need to sample and get correct logical error rate.

In each subspace, we stop sampling until 100 logical error events are detected, or we hit the total budget.

subspace_sampling_to_fit_curve(sampleBudget)[source]

After we determine the minw and maxw, we generate an even distribution of points between minw and maxw.

The goal is for the curve fitting in the next step to get more accurate.

class scalerqec.symbolicLER(error_rate=0)[source]

Bases: object

calculate_LER_from_StabCode(qeccirc: StabCode, noise_model: NoiseModel) float[source]

Given a StabCode object, calculate the LER polynomial symbolically

Parameters:
  • qeccirc – A StabCode object

  • error_rate – The physical error rate

Returns:

The symbolic polynomial of LER

calc_error_row_indices()[source]

Based on the prediction result by pymatching of all possible input, build a list including all row indices that cause logical error

calculate_LER()[source]
calculate_LER_brute_force()[source]

Enumerate all possible noise input to get the exact LER polynomial

calculate_LER_from_file(filepath, pvalue) float[source]

The most import function. Read the stim circuit, calculate the exact polynomial of LER, and evaluate with the value of p(physical error rate).

Following steps are included:

Step1: Parse the circuit from the file, inject depolarization noise Step2: Compile the STIM detector graph, generate the entire prediction table Stem3: Construct the QEPG graph Step4: Calculate all row indices in the table that will cause logical error Step5: Use dynamic algorithm to calculate the probability of measuring any possible outcomes Step6: Sum up all probability in the row with logical error

Parameters:
  • filepath – The path of the file with the STIM circuit

  • pvalue – The physical error rate

Returns:

A floating value which store the final logical error rate

dynamic_calculation_of_dp()[source]
evaluate_LER(pval)[source]
evaluate_LER_subspace(pval, weight)[source]
generate_pymatching_table()[source]

For all detector result, generate the prediction through pymatching.

_all_predictions store all prediction by matching

get_totalnoise()[source]

Get the total number of noise in the circuit

initialize_dp()[source]

Given the circuit information, initialize the dp table for running the algorithm

initialize_single_pauli_propagation()[source]

Calculate and store the table of the propagation result of single pauli error

parse_from_file(filepath)[source]

Read the circuit, parse from the file

subspace_LER(weight)[source]

Get the subspace LER for a given weight

verify_table(i)[source]