loom.executor.eka_to_stim_converter
Copyright 2024 Entropica Labs Pte Ltd
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
- class loom.executor.eka_to_stim_converter.EkaToStimConverter(**data)[source]
Bases:
], dtype[bool]], dict[Channel, tuple[str, GateTarget]]]]Convert an InterpretationStep to a stim.Circuit.
Here’s a simple example of how to use this method to execute Eka experiment in Stim:
from loom.executor import EkaToStimConverter stim_converter = EkaToStimConverter() stim_program, quant_register, class_register = stim_converter.convert( eka ) import stim st = stim_program sampler = st.compile_sampler() result = sampler.sample(shots=5) print(stim_converter.parse_target_run_outcome((result, class_register)))
Create a new model by parsing and validating input data from keyword arguments.
Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.
self is explicitly positional-only to allow self as a field name.
-
ALLOW_ERROR_MODELS:
bool
-
STIM_CLASSICALLY_CONTROLLED_OPS:
frozenset[str]
-
SUPPORTED_OPERATIONS:
frozenset[OpSignature]
- convert(interpreted_eka, error_models=None, with_ticks=False)[source]
Convert a InterpretationStep. Call the default convert method to convert the final circuit of the step. Then, add the detectors and logical observables to the stim circuit.
- convert_circuit(input_circuit, error_models=None, with_ticks=False)[source]
Convert a Circuit to a text in stim format and a mapping of channel labels to stim target or measurement record indices.
- Parameters:
input_circuit (Circuit) – The EKA circuit to convert.
with_ticks (bool, optional) – Whether to include TICK instructions in the stim circuit, by default False.
- Returns:
A tuple containing the stim circuit, a dictionary mapping quantum channel ids to stim qubit targets and coordinates and a dictionary mapping classical channel ids to stim measurement record indices,
- Return type:
StimCircuitAndRegisters
- emit_circuit_program(input_circuit, error_models=None, with_ticks=False)[source]
Convert a Circuit to a text in stim format and a mapping of channel labels to stim target or measurement record indices.
- Parameters:
input_circuit (Circuit) – The EKA circuit to convert.
with_ticks (bool, optional) – Whether to include TICK instructions in the stim circuit, by default False.
- Returns:
A tuple containing the stim circuit as a string, a dictionary mapping quantum channel ids to stim qubit targets and coordinates and a dictionary mapping classical channel ids to stim measurement record indices,
- Return type:
str, dict[Channel, tuple[str, stim.GateTarget]], dict[Channel, int]
- static emit_detectors_and_observables(input_istep, rec_dict, measurement_offset=0)[source]
Get the detector instructions for the given interpretation step, and the given measurement offset which corresponds to the number of measurements in the circuit before adding detectors.
- Parameters:
input_istep (InterpretationStep) – The interpretation step to get detector instructions for.
rec_dict (dict[str, int]) – A mapping from channel labels to their corresponding record indices.
measurement_offset (int, optional) – An offset to apply to the measurement indices, by default 0
- Returns:
A list of stim circuit instructions for the detector measurements.
- Return type:
list[str]
- Raises:
ValueError – If the detector labels are not in the expected format.
- emit_init_instructions(circuit)[source]
Provide the python code (as a string) to initializes the quantum and classical registers, and return the mapping from eka channel to register.
In the beginning of the circuit, the mapping of classical channels to measurement record indices is None, since no classical channels have been measured yet.
- emit_leaf_circuit_instruction(circuit, quantum_channel_map, classical_channel_map, measurement_record_counter=0)[source]
Provide the python code (as a string) to emit an Eka instruction in the target language.
- Return type:
str
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'ALLOW_ERROR_MODELS': FieldInfo(annotation=bool, required=False, default=True, frozen=True, init=False), 'STIM_CLASSICALLY_CONTROLLED_OPS': FieldInfo(annotation=frozenset[str], required=False, default=frozenset({OpSignature(name='classical_controlled_z', op_type=<OpType.CUSTOM: 'custom'>, quantum_input=1, classical_input=1, is_clifford=True, description=''), OpSignature(name='classical_controlled_x', op_type=<OpType.CUSTOM: 'custom'>, quantum_input=1, classical_input=1, is_clifford=True, description=''), OpSignature(name='classical_controlled_y', op_type=<OpType.CUSTOM: 'custom'>, quantum_input=1, classical_input=1, is_clifford=True, description='')})), 'SUPPORTED_ERROR_TYPES': FieldInfo(annotation=frozenset[ErrorType], required=False, default=frozenset({<ErrorType.PAULI_Y: ('pauli_y', 1)>, <ErrorType.PAULI_CHANNEL: ('pauli_channel', 3)>, <ErrorType.PHASE_FLIP: ('phase-flip', 1)>, <ErrorType.DEPOLARIZING1: ('depolarizing1', 1)>, <ErrorType.PAULI_Z: ('pauli_z', 1)>, <ErrorType.PAULI_X: ('pauli_x', 1)>, <ErrorType.DEPOLARIZING2: ('depolarizing2', 1)>, <ErrorType.BIT_FLIP: ('bit-flip', 1)>})), 'SUPPORTED_OPERATIONS': FieldInfo(annotation=frozenset[OpSignature], required=False, default=frozenset({OpSignature(name='measure_z', op_type=<OpType.MEASUREMENT: 'measurement'>, quantum_input=1, classical_input=1, is_clifford=True, description=''), OpSignature(name='reset_0', op_type=<OpType.RESET: 'reset'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='reset_1', op_type=<OpType.RESET: 'reset'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='measure_y', op_type=<OpType.MEASUREMENT: 'measurement'>, quantum_input=1, classical_input=1, is_clifford=True, description=''), OpSignature(name='z', op_type=<OpType.SINGLE_QUBIT: 'single_qubit'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='phaseinv', op_type=<OpType.SINGLE_QUBIT: 'single_qubit'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='cy', op_type=<OpType.TWO_QUBIT: 'two_qubit'>, quantum_input=2, classical_input=0, is_clifford=True, description=''), OpSignature(name='reset_+', op_type=<OpType.RESET: 'reset'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='cx', op_type=<OpType.TWO_QUBIT: 'two_qubit'>, quantum_input=2, classical_input=0, is_clifford=True, description=''), OpSignature(name='reset_-', op_type=<OpType.RESET: 'reset'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='reset_+i', op_type=<OpType.RESET: 'reset'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='y', op_type=<OpType.SINGLE_QUBIT: 'single_qubit'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='reset_-i', op_type=<OpType.RESET: 'reset'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='cz', op_type=<OpType.TWO_QUBIT: 'two_qubit'>, quantum_input=2, classical_input=0, is_clifford=True, description=''), OpSignature(name='phase', op_type=<OpType.SINGLE_QUBIT: 'single_qubit'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='h', op_type=<OpType.SINGLE_QUBIT: 'single_qubit'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='measurement', op_type=<OpType.MEASUREMENT: 'measurement'>, quantum_input=1, classical_input=1, is_clifford=True, description=''), OpSignature(name='cnot', op_type=<OpType.TWO_QUBIT: 'two_qubit'>, quantum_input=2, classical_input=0, is_clifford=True, description=''), OpSignature(name='measure_x', op_type=<OpType.MEASUREMENT: 'measurement'>, quantum_input=1, classical_input=1, is_clifford=True, description=''), OpSignature(name='i', op_type=<OpType.SINGLE_QUBIT: 'single_qubit'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='reset', op_type=<OpType.RESET: 'reset'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='x', op_type=<OpType.SINGLE_QUBIT: 'single_qubit'>, quantum_input=1, classical_input=0, is_clifford=True, description=''), OpSignature(name='swap', op_type=<OpType.TWO_QUBIT: 'two_qubit'>, quantum_input=2, classical_input=0, is_clifford=True, description='')})), 'separator_for_else_in_condition': FieldInfo(annotation=str, required=False, default=', is_else=', description='The separator string used in the description for else conditions.', frozen=True, init=False)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- property operations_map: dict[str, Callable[[list[list[GateTarget]]], list[str]]]
Map of operation signatures to their corresponding StimCallable, which is a set of stim instructions (as strings) associated with values for the targets and parameters.
- static parse_if_operation(if_circuit)[source]
Parse control flow operation, allowing only specific cases supported by Stim. Stim only supports conditional pauli operations, with single bit conditions.
- Parameters:
if_circuit (IfElseCircuit) – The IfElseCircuit to parse.
- Returns:
A Circuit (gate) representing the parsed if operation in Stim, which is a CX (resp. CY or CZ) operation with a classical channel as control.
- Return type:
- static parse_target_run_outcome(output)[source]
Parse the run output of a stim circuit into a dictionary mapping the Eka classical channels labels to their measurement outcomes.
- Parameters:
output (StimOutputRunResult) – The output from stim simulation, which is a tuple of (NDArray of shape (shots, num_qubits), dict mapping classical channel to stim measurement record index).
- Returns:
A dictionary mapping the Eka classical channel labels to their measurement outcomes. If multiple shots were run, the outcomes are lists of integers (0 or 1), otherwise a single integer (0 or 1).
- Return type:
dict[Channel, int | list[int]]
- print_stim_circuit_for_crumble(final_step)[source]
Print the stim circuit along with polygon instructions to be used for crumble
- Parameters:
stim_circ (stim.Circuit) – input stim circuit
- Return type:
str
- classmethod stim_polygons(interpreted_eka)[source]
Define stim polygons using data qubits coordinates involved with each stabilizer on patches passed as argument to the function
- DEMO SYNTAX: #!pragma POLYGON(1,0,0,0.25) 5 11 16 23
POLYGON(<X>, <Y>, <Z>, <color intensity>) <data qubits involved>
Since polygon definitions are added as comments in the stim circuit body, and there is no way to add comments programmatically in stim.Circuit This function is only available to print polygon instructions from the patch stabilizers. The user MUST add these comments manually to the stim.Circuit string body to display the polygons in crumble
- Parameters:
interpreted_eka (InterpretationStep) – The InterpretationStep object containing information on the code stabilizers
- Returns:
stim_polygons – Stim polygon instructions as a string
- Return type:
str
-
ALLOW_ERROR_MODELS: