Template code

Simulation

class qsurface.codes._template.sim.PerfectMeasurements(size, **kwargs)

Simulation code class for perfect measurements.

The qubits of the code class are stored in a double dictionary, with the keys in the outer dictionary corresponding to the qubit layer. For perfect measurements, there is a single layer. For faulty measurements, there are multiple layers (and defaults to self.size). In the nested dictionaries each qubit is stored by qubit.loc as key. A qubit can thus be accessed by self.qubits[layer][(x,y)].

The qubit and edge classes from Code elements can be replaced with inherited classes to store decoder dependent attributes.

Parameters

size (int or tuple) – Size of the surface code in single dimension or two dimensions (x,y).

ancilla_qubits

Nested dictionary of AncillaQubit objects.

Type

dict of dict

data_qubits

Nested dictionary of DataQubit objects.

Type

dict of dict

pseudo_qubits

Nested dictionary of PseudoQubit objects.

Type

dict of dict

errors

Dictionary of error modules with the module name as key. All error modules from Error types loaded in self.errors will be applied during a simulation by random_errors().

Type

dict

logical_operators

Dictionary with lists of Edge objects that from a trivial loop over the surface and correspond to a logical operator. The logical state of each operator can be obtained by the state of each Edge in the list.

Type

dict of list

logical_state

Dictionary with the states corresponding to the logical operators in self.logical_operators.

Type

dict of bool

no_error

Property for whether there is a logical error in the last iteration. The value for self.no_error is updated after a call to self.logical_state.

Type

bool

trivial_ancillas

Property for whether all ancillas are trivial. Usefull for checking if decoding has been successfull.

Type

bool

instance

Time stamp that is renewed every time random_errors is called. Helps with identifying a ‘round’ of simulation when using class attributes.

Type

float

initialize(*args, **kwargs)

Initializes all data objects of the code.

Builds the surface with init_surface, adds the logical operators with init_logical_operator, and loads error modules with init_errors. All keyword arguments from these methods can be used for initialize.

abstract init_surface()

Initiates the surface code.

abstract init_logical_operator()

Initiates the logical operators.

init_errors(*error_modules, error_rates={}, **kwargs)

Initializes error modules.

Any error module from Error types can loaded as either a string equivalent to the module file name or as the module itself. The default error rates for all loaded error modules can be supplied as a dictionary with keywords corresponding to the default error rates of the associated error modules.

Parameters
  • error_modules (Union[str, Sim]) – The error modules to load. May be a string or an error module from Error types.

  • error_rates (dict) – The default error rates for the loaded modules. Must be a dictionary with probabilities with keywords corresponding to the default or overriding error rates of the associated error modules.

Examples

Load Pauli error and Erasure error modules via string names. Set default bitflip rate to 0.1 and erasure to 0.03.

>>> code.init_errors(
...    "pauli",
...    "erasure",
...    error_rates={"p_bitflip": 0.1, "p_erasure": 0.03}
... )

Load Pauli error module via module. Set default phaseflip rate to 0.05.

>>> import .errors.pauli as pauli
>>> code.init_errors(pauli, error_rates={"p_phaseflip": 0.05})
add_data_qubit(loc, z=0, initial_states=None, None, **kwargs)

Initializes a DataQubit and saved to self.data_qubits[z][loc].

Parameters

initial_states (Tuple[float, float]) – Initial state for the data-qubit.

Return type

DataQubit

add_ancilla_qubit(loc, z=0, state_type='x', **kwargs)

Initializes a AncillaQubit and saved to self.ancilla_qubits[z][loc].

Return type

AncillaQubit

add_pseudo_qubit(loc, z=0, state_type='x', **kwargs)

Initializes a PseudoQubit and saved to self.pseudo_qubits[z][loc].

Return type

PseudoQubit

static entangle_pair(data_qubit, ancilla_qubit, key, edge=None, **kwargs)

Entangles one DataQubit to a AncillaQubit for parity measurement.

Parameters
random_errors(apply_order=None, measure=True, **kwargs)

Applies all errors loaded in self.errors attribute to layer z.

The random error is applied for each loaded error module by calling random_error. If apply_order is specified, the error modules are applied in order of the error names in the list. If no order is specified, the errors are applied in a random order. Addionally, any error rate can set by supplying the rate as a keyword argument e.g. p_bitflip = 0.1.

Parameters
  • apply_order (Optional[List[str]]) – The order in which the error modules are applied. Items in the list must equal keys in self.errors or the names of the loaded error modules.

  • measure (bool) – Measure ancilla qubits after errors have been simulated.

class qsurface.codes._template.sim.FaultyMeasurements(size, *args, layers=None, p_bitflip_plaq=0, p_bitflip_star=0, **kwargs)

Simulation code class for faulty measurements.

A 3D graph is initiated with layers amount of 2D surfaces from PerfectMeasurement stacked on top of each other. The structure of the self.data_qubits, self.ancilla_qubits and self.pseudo_qubits dictionary attributes allows for the storage for various time instances of the same qubits in the first nested layer. E.g. self.data_qubits[0][(0,0)] and self.data_qubits[1][(0,0)] store the data-qubit at (0,0) at time instances 0 and 1, respectively. Consecutive instances of AncillaQubit objects and PseudoQubit objects are connected in the 3D graph by PseudoEdge objects.

Parameters
  • layers (Optional[int]) – Number of layers in 3D graph for faulty measurements.

  • p_bitflip_plaq (float) – Default bitflip rate during measurements on plaquette operators (XXXX).

  • p_bitflip_star (float) – Default bitflip rate during measurements on star operators (ZZZZ).

simulate(**kwargs)

Simulate an iteration or errors and measurement.

On all but the final layer, the default or overriding error rates (via keyworded arguments) are applied. On the final layer, perfect measurements are applied by setting p_bitflip_plaq=0 and p_bitflip_star=0.

init_surface(**kwargs)

Initiates the surface code.

The 3D lattice is initialized by first building the ground layer. After that each consecutive layer is built and pseudo-edges are added to connect the ancilla qubits of each layer.

add_vertical_edge(lower_ancilla, upper_ancilla, **kwargs)

Adds a PseudoEdge to connect two instances of an ancilla-qubit in time.

A surface code with faulty measurements must be decoded in 3D. Instances of the same ancilla qubits in time must be connected with an edge. Here, lower_ancilla is an older instance of layer ‘z’, and upper_ancilla is a newer instance of layer ‘z+1’.

Parameters
  • lower_ancilla (AncillaQubit) – Older instance of ancilla-qubit.

  • upper_ancilla (AncillaQubit) – Newer instance of ancilla-qubit.

random_errors(p_bitflip_plaq=None, p_bitflip_star=None, **kwargs)

Performs a round of parity measurements on layer z with faulty measurements.

Parameters
  • p_bitflip_plaq (int or float, optional) – Probability of a bitflip during a parity check measurement on plaquette operators (XXXX).

  • p_bitflip_star (int or float, optional) – Probability of a bitflip during a parity check measurement on star operators (ZZZZ).

random_errors_layer(**kwargs)

Applies a layer of random errors loaded in self.errors.

Parameters

kwargs – Keyword arguments are passed on to random_errors.

add_ancilla_qubit(loc, z=0, state_type='x', **kwargs)

Initializes a AncillaQubit and saved to self.ancilla_qubits[z][loc].

Return type

AncillaQubit

add_data_qubit(loc, z=0, initial_states=None, None, **kwargs)

Initializes a DataQubit and saved to self.data_qubits[z][loc].

Parameters

initial_states (Tuple[float, float]) – Initial state for the data-qubit.

Return type

DataQubit

add_pseudo_qubit(loc, z=0, state_type='x', **kwargs)

Initializes a PseudoQubit and saved to self.pseudo_qubits[z][loc].

Return type

PseudoQubit

static entangle_pair(data_qubit, ancilla_qubit, key, edge=None, **kwargs)

Entangles one DataQubit to a AncillaQubit for parity measurement.

Parameters
init_errors(*error_modules, error_rates={}, **kwargs)

Initializes error modules.

Any error module from Error types can loaded as either a string equivalent to the module file name or as the module itself. The default error rates for all loaded error modules can be supplied as a dictionary with keywords corresponding to the default error rates of the associated error modules.

Parameters
  • error_modules (Union[str, Sim]) – The error modules to load. May be a string or an error module from Error types.

  • error_rates (dict) – The default error rates for the loaded modules. Must be a dictionary with probabilities with keywords corresponding to the default or overriding error rates of the associated error modules.

Examples

Load Pauli error and Erasure error modules via string names. Set default bitflip rate to 0.1 and erasure to 0.03.

>>> code.init_errors(
...    "pauli",
...    "erasure",
...    error_rates={"p_bitflip": 0.1, "p_erasure": 0.03}
... )

Load Pauli error module via module. Set default phaseflip rate to 0.05.

>>> import .errors.pauli as pauli
>>> code.init_errors(pauli, error_rates={"p_phaseflip": 0.05})
abstract init_logical_operator()

Initiates the logical operators.

initialize(*args, **kwargs)

Initializes all data objects of the code.

Builds the surface with init_surface, adds the logical operators with init_logical_operator, and loads error modules with init_errors. All keyword arguments from these methods can be used for initialize.

random_measure_layer(**kwargs)

Measures a layer of ancillas.

If the measured state of the current ancilla is not equal to the measured state of the previous instance, the current ancilla is a syndrome.

Parameters

kwargs – Keyword arguments are passed on to get_state.

Plotting

class qsurface.codes._template.plot.PerfectMeasurements(*args, **kwargs)

Plotting template code class for perfect measurements.

figure

Figure object of the current code.

Type

Figure

initialize(*args, **kwargs)

Initializes the code with a figure. Also takes keyword arguments for init_plot.

Since each error object delivers extra plot properties to the figure, which are dependent on the self.params values in the figure itself, we must initialize in the following sequence.

  • First load figure to load self.params instance of the PlotParams dataclass.

  • Initialize lattice, error initialization must have figure properties

  • Draw figure with plot elements from errors

random_errors(*args, **kwargs)

Applies all errors loaded in self.errors attribute to layer z.

The random error is applied for each loaded error module by calling random_error. If apply_order is specified, the error modules are applied in order of the error names in the list. If no order is specified, the errors are applied in a random order. Addionally, any error rate can set by supplying the rate as a keyword argument e.g. p_bitflip = 0.1.

Parameters
  • apply_order – The order in which the error modules are applied. Items in the list must equal keys in self.errors or the names of the loaded error modules.

  • measure – Measure ancilla qubits after errors have been simulated.

show_corrected(**kwargs)

Redraws the qubits and ancillas to show their states after decoding.

plot_data(iter_name=None, **kwargs)

Update plots of all data-qubits. A plot iteration is added if a iter_name is supplied. See draw_figure.

plot_ancilla(iter_name=None, **kwargs)

Update plots of all ancilla-qubits. A plot iteration is added if a iter_name is supplied. See draw_figure.

class Figure(code, *args, **kwargs)

Surface code plot for perfect measurements.

The inner figure class that plots the surface code based on the Qubit.loc and Qubit.z values on the set of code.data_qubits, code.ancilla_qubits and code.pseudo_qubits. This allows for a high amount of code inheritance.

An additional matplotlib.widgets.RadioButtons object is added to the figure which allows for the user to choose one of the loaded errors and apply the error directly to a qubit via _pick_handler.

Parameters
error_methods

A dictionary of the various error methods loaded in the outer class.

Type

dict

code_params

Additional plotting parameters loaded to the plot.PlotParams instance at self.params.

init_plot(**kwargs)

Plots all elements of the surface code onto the figure. Also takes keyword arguments for init_legend.

An additional matplotlib.widgets.RadioButtons object is added to the figure which allows for the user to choose one of the loaded errors and apply the error directly to a qubit via _pick_handler. This object is added via the init_plot method to make sure that the errors are already loaded in self.code.errors. The method for each loaded error is saved to self.error_methods. See errors._template.Plot for more information.

init_legend(legend_items=[], **kwargs)

Initializes the legend of the main axis of the figure. Also takes keyword arguments for legend.

The legend of the main axis self.main_ax consists of a series of Line2D objects. The qubit, vertex and stars are always in the legend for a surface code plot. Any error from Error types loaded in the code at code.errors in de outer class will add an extra element to the legend for differentiation if an error occurs. The Line2D attributes are stored at error.Plot.legend_params of the error module (see errors._template.Plot).

Parameters

legend_items (list of Line2D, optional) – Additional elements to the legend.

static change_properties(artist, prop_dict)

Changes the plot properties and draw the plot object or artist.

close()

Closes the figure.

draw_figure(new_iter_name=None, output=True, carriage_return=False, **kwargs)

Draws the canvas and blocks code execution.

Draws the queued plot changes onto the canvas and calls for focus() which blocks the code execution and catches user input for history navigation.

If a new iteration is called by supplying a new_iter_name, we additionally check for future property changes in the self.future_dict, and add these changes to the queue. Finally, all queued property changes for the next iteration are applied by change_properties.

Parameters
  • new_iter_name (Optional[str]) – Name of the new iteration. If no name is supplied, no new iteration is called.

  • output (bool) – Prints information to the console.

  • carriage_return (bool) – Applies carriage return to remove last line printed.

focus()

Enables the blocking object, catches input for history navigation.

The BlockingKeyInput object is called which blocks the execution of the code. During this block, the user input is received by the blocking object and return to the current method. From here, we can manipulate the plot or move through the plot history and call focus() again when all changes in the history have been drawn and blit.

key

function

h

show help

i

show all iterations

d

redraw current iteration

enter or right

go to next iteration, enter iteration number

backspace or left

go to previous iteration

n

go to newest iteration

0-9

input iteration number

When the method is active, the focus is on the figure. This will be indicated by a green circle in the bottom right of the figure. When the focus is lost, the code execution is continued and the icon is red. The change is icon color is performed by _set_figure_state(), which also hides the interactive elements when the focus is lost.

property history_at_newest
load_interactive_backend()

Configures the plotting backend.

If the Tkinter backend is enabled or can be enabled, the function returns True. For other backends False is returned.

Return type

bool

new_artist(artist, axis=None)

Adds a new artist to the axis.

Newly added artists must be hidden in the previous iteration. To make sure the history is properly logged, the visibility of the artist is set to False, and a new property of shown visibility is added to the queue of the next iteration.

Parameters
  • artist (Artist) – New plot artist to add to the axis.

  • axis (Optional[Axes]) – Axis to add the figure to.

Return type

None

new_properties(artist, properties, saved_properties={}, **kwargs)

Parses a dictionary of property changes of a matplotlib artist.

New properties are supplied via properties. If any of the new properties is different from its current value, this is seen as a property change. The old property value is stored in self.history_dict[self.history_iteration], and the new property value is stored at self.history_dict[self.history_iteration+1]. These new properties are queued for the next interation. The queue is emptied by applying all changes when draw_figure is called. If the same property changes 2+ times within the same iteration, the previous property change is removed with next_prop.pop(key, None).

The saved_properties parameter is used when temporary property changes have been applied by temporary_changes, in which the original properties are saved to self.temporary_saved as the saved properties. Before a new iteration is drawn, the temporary changes, which can be overwritten, are compared with the saved changes and the differences in properties are saved to [self.history_dict[self.history_iter-1]] and self.history_dict[self.history_iteration].

Some color values from different matplotlib objects are nested, some are list or tuple, and others may be a numpy.ndarray. The nested methods get_nested() and get_nested_property() make sure that the return type is always a list.

Parameters
  • artist (Artist) – Plot object whose properties are changed.

  • properties (dict) – Plot properties to change.

  • saved_properties (dict) – Override current properties and parse previous and current history.

temporary_properties(artist, properties, **kwargs)

Applies temporary property changes to a matplotlib artist.

Only available on the newest iteration, as we cannot change what is already in the past. All values in properties are immediately applied to artist. Since temporary changes can be overwritten within the same iteration, the first time a temporary property change is requested, the previous value is saved to self.temporary_saved. When the iteration changes, the property differences of the previous and current iteration are recomputed and saved to self.history_dict in _draw_from_history().

Parameters
  • artist (Artist) – Plot object whose properties are changed.

  • properties (dict) – Plot properties to change.

add_ancilla_qubit(loc, z=0, state_type='x', **kwargs)

Initializes a AncillaQubit and saved to self.ancilla_qubits[z][loc].

Return type

AncillaQubit

add_data_qubit(loc, z=0, initial_states=None, None, **kwargs)

Initializes a DataQubit and saved to self.data_qubits[z][loc].

Parameters

initial_states (Tuple[float, float]) – Initial state for the data-qubit.

Return type

DataQubit

add_pseudo_qubit(loc, z=0, state_type='x', **kwargs)

Initializes a PseudoQubit and saved to self.pseudo_qubits[z][loc].

Return type

PseudoQubit

static entangle_pair(data_qubit, ancilla_qubit, key, edge=None, **kwargs)

Entangles one DataQubit to a AncillaQubit for parity measurement.

Parameters
init_errors(*error_modules, error_rates={}, **kwargs)

Initializes error modules.

Any error module from Error types can loaded as either a string equivalent to the module file name or as the module itself. The default error rates for all loaded error modules can be supplied as a dictionary with keywords corresponding to the default error rates of the associated error modules.

Parameters
  • error_modules (Union[str, Sim]) – The error modules to load. May be a string or an error module from Error types.

  • error_rates (dict) – The default error rates for the loaded modules. Must be a dictionary with probabilities with keywords corresponding to the default or overriding error rates of the associated error modules.

Examples

Load Pauli error and Erasure error modules via string names. Set default bitflip rate to 0.1 and erasure to 0.03.

>>> code.init_errors(
...    "pauli",
...    "erasure",
...    error_rates={"p_bitflip": 0.1, "p_erasure": 0.03}
... )

Load Pauli error module via module. Set default phaseflip rate to 0.05.

>>> import .errors.pauli as pauli
>>> code.init_errors(pauli, error_rates={"p_phaseflip": 0.05})
abstract init_logical_operator()

Initiates the logical operators.

abstract init_surface()

Initiates the surface code.

class qsurface.codes._template.plot.FaultyMeasurements(*args, figure3d=True, **kwargs)

Plotting template code class for faulty measurements.

Inherits from codes._template.sim.FaultyMeasurements and codes._template.plot.PerfectMeasurements. See documentation for these classes for more.

Dependent on the figure3d argument, either a 3D figure object is created that inherits from Template3D and codes._template.plot.PerfectMeasurements.Figure, or the 2D codes._template.plot.PerfectMeasurements.Figure is used.

Parameters