QCut API reference#

Submodules#

QCut.backend_utility module#

Utility functions for running on real backends.

QCut.backend_utility.expectation_values(counts: dict, observables: list, shots: int) list[source]#

Calculate expectation values.

Parameters:
  • counts (dict) – Counts obtained from circuit run, where keys are measurement outcomes and values are the number of times each outcome was observed.

  • observables (list) – List of observables to calculate expectation values for. Each observable can be an integer (index of a single qubit) or a list of integers (indices of multiple qubits).

  • shots (int) – Number of shots (total number of measurements).

Returns:

A list of expectation values for each observable.

Return type:

list

QCut.backend_utility.run_and_expectation_value(circuit: QuantumCircuit, backend, observables: list, shots: int, mitigate=False) tuple[dict, list][source]#

Run circuit and calculate expectation value.

Parameters:
  • circuit (QuantumCircuit) – A quantum circuit.

  • backend – Backend to run circuit on.

  • observables (list) – Observables to calculate expectation values for.

  • shots (int) – Number of shots.

  • mitigate (bool) – If True, use readout error mitigation.

Returns:

A tuple containing:
  • dict: Counts from the circuit run.

  • list: A list of expectation values.

Return type:

tuple

QCut.backend_utility.run_on_backend(circuit: QuantumCircuit, backend, shots: int) dict[source]#

Run a quantum circuit on a specified backend.

Parameters:
  • circuit (QuantumCircuit) – The quantum circuit to be executed.

  • backend (Backend) – The backend to use for executing the circuit.

  • shots (int) – The number of shots (repetitions) to run the circuit.

Returns:

A dictionary of counts from the circuit run.

Return type:

dict

QCut.backend_utility.transpile_experiments(experiment_circuits: list, backend) list[source]#

Transpile experiment circuits.

Parameters:
  • experiment_circuits – (list): Experiment circuits to be transpiled.

  • backend (str) – Backend to transpile to.

Returns:

A list of transpiled experiment circuits.

Return type:

list

QCut.helper module#

Helper functions for circuit knitting.

QCut.helper.get_pauli_list(input_list: list, length: int) PauliList[source]#

Transform list of observable indices to Paulilist of Z observables.

Parameters:
  • input_list (list) – list of observables as qubit indices

  • length (int) – number of qubits in the circuit

Returns:

a PauliList of Z observables

Return type:

PauliList

QCut.helper.relative_error(actual: list, approx: list) list[source]#

Calculate the relative error between actual and approximate values. :param actual: The list of actual values. :type actual: list :param approx: The list of approximate values. :type approx: list

Returns:

The list of relative errors for each corresponding pair of actual and approximate values.

Return type:

list

Raises:

ValueError – If the lengths of actual and approx lists are not the same.

QCut.qpd_gates module#

Helper gates for circuit knitting.

QCut.identity_qpd module#

Define identity channel quasi probability decomposition.

QCut.wirecut module#

Circuit knitting wire cut functionality.

QCut.wirecut.estimate_expectation_values(results: list[TotalResult], coefficients: list[int], cut_locations: ndarray[CutLocation], observables: list[int | list[int]], map_qubits: dict[int, int] | None = None) list[float][source]#

Calculate the estimated expectation values.

Loop through processed results. For each result group generate all products of different measurements from different subcircuits of the group. For each result from qpd measurements calculate qpd coefficient and from counts calculate weight. Get results for qubits corresponding to the observables. If multiqubit observable multiply individual qubit eigenvalues and multiply by (-1)^(m+1) where m is number of qubits in the observable. Multiply by weight and add to sub expectation value. Once all results iterated over move to next circuit group. Lastly multiply by 4^(2*n), where n is the number of cuts, and divide by number of samples.

Parameters:
  • results (list[TotalResult]) – results from experiment circuits

  • coefficients (list[int]) – list of coefficients for each subcircuit group

  • cut_locations (np.ndarray[CutLocation]) – cut locations

  • observables (list[int | list[int]]) – observables to calculate expectation values for

Returns:

expectation values as a list of floats

Return type:

list[float]

QCut.wirecut.get_experiment_circuits(subcircuits: list[QuantumCircuit], cut_locations: ndarray[CutLocation]) tuple[CutCircuit, list[int], list[tuple[int, int, int]]][source]#

Generate experiment circuits by inserting QPD operations on measure/initialize nodes.

Loop through qpd combinations. Calculate coefficient for subcircuit group by taking the product of all coefficients in the current qpd row. Loop through subcircuits generated in 4. Make deepcopy of subcircuit and iterate over its circuit data. When hit either Meas_{ind} of Init_{ind} repace it with operation found in qpd[ind][“op”/”init”]. WHile generating experiment circuits also generate a list of locations that have an identity basis measurement. These measurement outcomes need to be added during post-processing. Locations added as [index of experiment circuit, index of subcircuit, index of classical bit corresponding to measurement]. Repeat untill looped through all qpd rows. sircuits reutrned as [circuit_group0, circuit_group1, …], where circuit_goup is [subciruit0, subcircuit1, …].

Parameters:
  • subcircuits (list[QuantumCircuit]) – subcircuits with measure/initialize nodes.

  • cut_locations (np.ndarray[CutLocation]) – cut locations.

Returns:

A tuple containing:
  • CutCircuit: A CutCircuit object containing the experiment circuits.

  • list[int]: A list of coefficients for each circuit.

  • list[tuple[int, int, int]]:

    A list of index pointers to results that need additional post-processing due to identity basis measurement.

Return type:

tuple

QCut.wirecut.get_placeholder_locations(subcircuits: list[QuantumCircuit]) list[source]#

Identify the locations of placeholder operations in a list of quantum subcircuits. This function scans through each quantum subcircuit provided in the input list and identifies the indices and operations where either measurement (“Meas”) or initialization (“Init”) operations occur. It returns a list of lists, where each sublist corresponds to a subcircuit and contains tuples of the form (index, operation).

Parameters:

subcircuits (list[QuantumCircuit]) – A list of QuantumCircuit objects to be analyzed.

Returns:

A list of lists, where each sublist contains tuples (index, operation) indicating the positions of measurement or initialization operations in the corresponding subcircuit.

Return type:

list

QCut.wirecut.get_qpd_combinations(cut_locations: np.ndarray[CutLocation]) Iterable[tuple[dict]][source]#

Get all possible combinations of the QPD operations so that each combination has len(cut_locations) elements.

For a single cut operations can be straightforwardly inserted from the identity qpd. If multiple cuts are made one need to take the cartesian product of the identity qpd with itself n times, where n is number of cuts. This will give a qpd with 8^n rows. Each row corresponds to a subcircuit group. These operations can then be inserted to generate the experiment circuits.

Parameters:

cut_locations (np.ndarray[CutLocation]) – cut locations

Returns:

Iterable of the possible QPD operations

Return type:

Iterable[tuple[dict]]

QCut.wirecut.run_experiments(experiment_circuits: CutCircuit, cut_locations: ndarray[CutLocation], id_meas: list[tuple[int, int, int]], shots: int = 4096, backend: None = None, mitigate: bool = False) list[TotalResult][source]#

Run experiment circuits.

Loop through experiment circuits and then loop through circuit group and run each circuit. Store results as [group0, group1, …] where group is [res0, res1, …]. where res is “xxx yy”: count xxx are the measurements from the end of circuit measurements on the meas classical register and yy are the qpd basis measurement results from the qpd_meas class register.

Parameters:
  • experiment_circuits (CutCircuit) – experiment circuits

  • cut_locations (np.ndarray[CutLocation]) – list of cut locations

  • id_meas (list[int, int, int]) – list of identity basis measurement locations

  • shots (int) – number of shots per circuit run (optional)

  • backend – backend used for running the circuits (optional)

  • mitigate (bool) – wether to use readout error mitigation or not (optional)

Returns:

list of transformed results

Return type:

list[TotalResult]

Module contents#

Init circuit knitting.

QCut.estimate_expectation_values(results: list[TotalResult], coefficients: list[int], cut_locations: ndarray[CutLocation], observables: list[int | list[int]], map_qubits: dict[int, int] | None = None) list[float][source]#

Calculate the estimated expectation values.

Loop through processed results. For each result group generate all products of different measurements from different subcircuits of the group. For each result from qpd measurements calculate qpd coefficient and from counts calculate weight. Get results for qubits corresponding to the observables. If multiqubit observable multiply individual qubit eigenvalues and multiply by (-1)^(m+1) where m is number of qubits in the observable. Multiply by weight and add to sub expectation value. Once all results iterated over move to next circuit group. Lastly multiply by 4^(2*n), where n is the number of cuts, and divide by number of samples.

Parameters:
  • results (list[TotalResult]) – results from experiment circuits

  • coefficients (list[int]) – list of coefficients for each subcircuit group

  • cut_locations (np.ndarray[CutLocation]) – cut locations

  • observables (list[int | list[int]]) – observables to calculate expectation values for

Returns:

expectation values as a list of floats

Return type:

list[float]

QCut.expectation_values(counts: dict, observables: list, shots: int) list[source]#

Calculate expectation values.

Parameters:
  • counts (dict) – Counts obtained from circuit run, where keys are measurement outcomes and values are the number of times each outcome was observed.

  • observables (list) – List of observables to calculate expectation values for. Each observable can be an integer (index of a single qubit) or a list of integers (indices of multiple qubits).

  • shots (int) – Number of shots (total number of measurements).

Returns:

A list of expectation values for each observable.

Return type:

list

QCut.get_experiment_circuits(subcircuits: list[QuantumCircuit], cut_locations: ndarray[CutLocation]) tuple[CutCircuit, list[int], list[tuple[int, int, int]]][source]#

Generate experiment circuits by inserting QPD operations on measure/initialize nodes.

Loop through qpd combinations. Calculate coefficient for subcircuit group by taking the product of all coefficients in the current qpd row. Loop through subcircuits generated in 4. Make deepcopy of subcircuit and iterate over its circuit data. When hit either Meas_{ind} of Init_{ind} repace it with operation found in qpd[ind][“op”/”init”]. WHile generating experiment circuits also generate a list of locations that have an identity basis measurement. These measurement outcomes need to be added during post-processing. Locations added as [index of experiment circuit, index of subcircuit, index of classical bit corresponding to measurement]. Repeat untill looped through all qpd rows. sircuits reutrned as [circuit_group0, circuit_group1, …], where circuit_goup is [subciruit0, subcircuit1, …].

Parameters:
  • subcircuits (list[QuantumCircuit]) – subcircuits with measure/initialize nodes.

  • cut_locations (np.ndarray[CutLocation]) – cut locations.

Returns:

A tuple containing:
  • CutCircuit: A CutCircuit object containing the experiment circuits.

  • list[int]: A list of coefficients for each circuit.

  • list[tuple[int, int, int]]:

    A list of index pointers to results that need additional post-processing due to identity basis measurement.

Return type:

tuple

QCut.get_locations_and_subcircuits(circuit: QuantumCircuit)[source]#

Get cut locations and subcircuits with placeholder operations.

Parameters:

circuit (QuantumCircuit) – circuit with cuts inserted

Returns:

A tuple containing:
  • list[SingleQubitCutLocation]: Locations of the cuts as a list

  • list[QuantumCircuit]: Subcircuits with placeholder operations

Return type:

tuple

QCut.get_pauli_list(input_list: list, length: int) PauliList[source]#

Transform list of observable indices to Paulilist of Z observables.

Parameters:
  • input_list (list) – list of observables as qubit indices

  • length (int) – number of qubits in the circuit

Returns:

a PauliList of Z observables

Return type:

PauliList

QCut.run(circuit: QuantumCircuit, observables: list[int, list[int]], backend=AerSimulator('aer_simulator'), mitigate: bool = False) list[float][source]#

Run the whole circuit knitting sequence with one function call.

Parameters:
  • circuit (QuantumCircuit) – circuit with cut experiments

  • observables (list[int | list[int]]) – list of observbles in the form of qubit indices (Z-obsevable).

  • backend – backend to use for running experiment circuits (optional)

  • mitigate (bool) – wether or not to use readout error mitigation (optional)

Returns:

a list of expectation values

Return type:

list

QCut.run_and_expectation_value(circuit: QuantumCircuit, backend, observables: list, shots: int, mitigate=False) tuple[dict, list][source]#

Run circuit and calculate expectation value.

Parameters:
  • circuit (QuantumCircuit) – A quantum circuit.

  • backend – Backend to run circuit on.

  • observables (list) – Observables to calculate expectation values for.

  • shots (int) – Number of shots.

  • mitigate (bool) – If True, use readout error mitigation.

Returns:

A tuple containing:
  • dict: Counts from the circuit run.

  • list: A list of expectation values.

Return type:

tuple

QCut.run_cut_circuit(subcircuits: list[QuantumCircuit], cut_locations: ndarray[SingleQubitCutLocation], observables: list[int | list[int]], map_qubits: dict[int, int], backend=AerSimulator('aer_simulator'), mitigate: bool = False) ndarray[float][source]#

After splitting the circuit run the rest of the circuit knitting sequence.

Parameters:
  • subcircuits (list[QuantumCircuit]) – subcircuits containing the placeholder operations

  • cut_locations (np.ndarray[CutLocation]) – list of cut locations

  • observables (list[int | list[int]]) – list of observables as qubit indices (Z observable)

  • backend – backend to use for running experiment circuits (optional)

  • mitigate (bool) – wether or not to use readout error mitigation (optional)

Returns:

a list of expectation values

Return type:

list

QCut.run_experiments(experiment_circuits: CutCircuit, cut_locations: ndarray[CutLocation], id_meas: list[tuple[int, int, int]], shots: int = 4096, backend: None = None, mitigate: bool = False) list[TotalResult][source]#

Run experiment circuits.

Loop through experiment circuits and then loop through circuit group and run each circuit. Store results as [group0, group1, …] where group is [res0, res1, …]. where res is “xxx yy”: count xxx are the measurements from the end of circuit measurements on the meas classical register and yy are the qpd basis measurement results from the qpd_meas class register.

Parameters:
  • experiment_circuits (CutCircuit) – experiment circuits

  • cut_locations (np.ndarray[CutLocation]) – list of cut locations

  • id_meas (list[int, int, int]) – list of identity basis measurement locations

  • shots (int) – number of shots per circuit run (optional)

  • backend – backend used for running the circuits (optional)

  • mitigate (bool) – wether to use readout error mitigation or not (optional)

Returns:

list of transformed results

Return type:

list[TotalResult]

QCut.run_on_backend(circuit: QuantumCircuit, backend, shots: int) dict[source]#

Run a quantum circuit on a specified backend.

Parameters:
  • circuit (QuantumCircuit) – The quantum circuit to be executed.

  • backend (Backend) – The backend to use for executing the circuit.

  • shots (int) – The number of shots (repetitions) to run the circuit.

Returns:

A dictionary of counts from the circuit run.

Return type:

dict

QCut.transpile_experiments(experiment_circuits: list, backend) list[source]#

Transpile experiment circuits.

Parameters:
  • experiment_circuits – (list): Experiment circuits to be transpiled.

  • backend (str) – Backend to transpile to.

Returns:

A list of transpiled experiment circuits.

Return type:

list