Simulators#

Quantum states and their dynamics are simulated by classes belonging to the namespace simulators. PECOS contains a stabilizer simulator called SparseSim.

Expected Methods#

The set of gates allowed by a simulator may differ (the standard set for PECOS is given in Standard Gates; however, each simulator is expected to have a set of standard methods. I will describe them in this section.

When initializing a simulator, the first argument is expected to be the number of qudits to be simulated. This reserves the size of the quantum registry:

>>> from pecos.simulators import SparseSim
>>> state = SparseSim(4)

Note, for all simulators, the initial state of each qudit is the state \(|0\rangle\).

The only other method expected is the run_gate method. This method can be used to apply gates to a simulator instance by using the run_gate method:

>>> # Continuing from the previous code block.
>>> state.run_gate("X", {0, 1})
{}

Here the first argument is a gate symbol that is recognized by the simulator and the second argument is a set of gate locations. Other keywords and arguments may be supplied if it is allowed by the simulator. Such arguments could be used to change the behavior of the gate. For example, arguments could be used to define gate rotation-angles.

If measurements are made then a dictionary indicating the measurement results is returned by run_gate:

>>> # Continuing from the previous code block.
>>> state.run_gate("measure Z", {0, 1, 3})
{0: 1, 1: 1}

Here we see that the keys of the results dictionary are the qudit locations of the measurements, and the values are the corresponding measurement results except that zero results are not returned.

Classes in the circuit_runners namespace combine QuantumCircuits and simulators to apply gates to simulated uantum states. For a discussion about these classes see Circuit Runners.

StabSim#

Methods that specific to SparseSim will now be described.

The print_stabs method prints a stabilizer table corresponding to the state currently store in the simulator:

>>> state = SparseSim(3)
>>> state.run_gate("CNOT", {(0, 1)})
{}
>>> state.run_gate("X", {0})
{}
>>> state.print_stabs(print_destabs=True)
 -ZII
 -ZZI
  IIZ
-------------------------------
  XXI
  IXI
  IIX
([' -ZII', ' -ZZI', '  IIZ'], ['  XXI', '  IXI', '  IIX'])

Here in the print output stabilizer generators are indicated by the strings above the dashed lines, while destabilizer generators are indicated by the strings below. Note that the destabilizers are only given when print_destabs is set to True (default value is False).

The logical_sign method can be used to determine the sign of stabilizer generators. As the stabilizer simulators represent stabilizer states, logical basis-states are stabilized by logical operators. Therefore, this method is useful in Monte Carlo simulations to determine if logical errors have flipped the sign of logical operators.

An example of using the logical_sign method is seen in the following:

>>> # Continuing with the following example:
>>> from pecos.circuits import QuantumCircuit
>>> stab = QuantumCircuit([{"Z": {0, 1}}])
>>> state.logical_sign(stab)
1
>>> stab = QuantumCircuit([{"Z": {2}}])
>>> state.logical_sign(stab)
0

A \(1\) is returned if the phase of the stabilizer is \(-1\), and a \(0\) is returned if the phase is \(+1\). If the stabilizer supplied to logical_sign is not a stabilizer of the state, then an exception will be raised.