backends

Module contents

Contains back-ends for ProjectQ.

This includes:

  • a debugging tool to print all received commands (CommandPrinter)
  • a circuit drawing engine (which can be used anywhere within the compilation chain)
  • a simulator with emulation capabilities
  • a resource counter (counts gates and keeps track of the maximal width of the circuit)
  • an interface to the IBM Quantum Experience chip (and simulator).
class projectq.backends.CircuitDrawer(accept_input=False, default_measure=0)

CircuitDrawer is a compiler engine which generates TikZ code for drawing quantum circuits.

The circuit can be modified by editing the settings.json file which is generated upon first execution. This includes adjusting the gate width, height, shadowing, line thickness, and many more options.

After initializing the CircuitDrawer, it can also be given the mapping from qubit IDs to wire location (via the set_qubit_locations() function):

circuit_backend = CircuitDrawer()
circuit_backend.set_qubit_locations({0: 1, 1: 0}) # swaps lines 0 and 1
eng = MainEngine(circuit_backend)

... # run quantum algorithm on this main engine

print(circuit_backend.get_latex()) # prints LaTeX code

To see the qubit IDs in the generated circuit, simply set the draw_id option in the settings.json file under “gates”:”AllocateQubitGate” to True:

"gates": {
        "AllocateQubitGate": {
                "draw_id": True,
                "height": 0.15,
                "width": 0.2,
                "pre_offset": 0.1,
                "offset": 0.1
        },
        ...

The settings.json file has the following structure:

{
        "control": { # settings for control "circle"
                        "shadow": false,
                        "size": 0.1
        },
        "gate_shadow": true, # enable/disable shadows for all gates
        "gates": {
                        "GateClassString": {
                                GATE_PROPERTIES
                        }
                        "GateClassString2": {
                                ...
        },
        "lines": { # settings for qubit lines
                        "double_classical": true, # draw double-lines for classical bits
                        "double_lines_sep": 0.04, # gap between the two lines for double lines
                        "init_quantum": true, # start out with quantum bits
                        "style": "very thin" # line style
        }
}

All gates (except for the ones requiring special treatment) support the following properties:

"GateClassString": {
        "height": GATE_HEIGHT,
        "width": GATE_WIDTH
        "pre_offset": OFFSET_BEFORE_PLACEMENT,
        "offset": OFFSET_AFTER_PLACEMENT,
},
__init__(accept_input=False, default_measure=0)

Initialize a circuit drawing engine.

The TikZ code generator uses a settings file (settings.json), which can be altered by the user. It contains gate widths, heights, offsets, etc.

Parameters:
  • accept_input (bool) – If accept_input is true, the printer queries the user to input measurement results if the CircuitDrawer is the last engine. Otherwise, all measurements yield the result default_measure (0 or 1).
  • default_measure (bool) – Default value to use as measurement results if accept_input is False and there is no underlying backend to register real measurement results.
get_latex()

Return the latex document string representing the circuit.

Simply write this string into a tex-file or, alternatively, pipe the output directly to, e.g., pdflatex:

python3 my_circuit.py | pdflatex

where my_circuit.py calls this function and prints it to the terminal.

is_available(cmd)

Specialized implementation of is_available: Returns True if the CircuitDrawer is the last engine (since it can print any command).

Parameters:cmd (Command) – Command of which to check availability (all Commands can be printed).
Returns:True, unless the next engine cannot handle the Command (if there is a next engine).
Return type:availability (bool)
receive(command_list)

Receive a list of commands from the previous engine, print the commands, and then send them on to the next engine.

Parameters:command_list (list<Command>) – List of Commands to print (and potentially send on to the next engine).
set_qubit_locations(id_to_loc)

Sets the qubit lines to use for the qubits explicitly.

To figure out the qubit IDs, simply use the setting draw_id in the settings file. It is located in “gates”:”AllocateQubitGate”. If draw_id is True, the qubit IDs are drawn in red.

Parameters:id_to_loc (dict) – Dictionary mapping qubit ids to qubit line numbers.
Raises:RuntimeError – If the mapping has already begun (this function needs be called before any gates have been received).
class projectq.backends.CommandPrinter(accept_input=True, default_measure=False, in_place=False)

CommandPrinter is a compiler engine which prints commands to stdout prior to sending them on to the next compiler engine.

__init__(accept_input=True, default_measure=False, in_place=False)

Initialize a CommandPrinter.

Parameters:
  • accept_input (bool) – If accept_input is true, the printer queries the user to input measurement results if the CommandPrinter is the last engine. Otherwise, all measurements yield 0.
  • default_measure (bool) – Default measurement result (if accept_input is False).
  • in_place (bool) – If in_place is true, all output is written on the same line of the terminal.
is_available(cmd)

Specialized implementation of is_available: Returns True if the CommandPrinter is the last engine (since it can print any command).

Parameters:cmd (Command) – Command of which to check availability (all Commands can be printed).
Returns:True, unless the next engine cannot handle the Command (if there is a next engine).
Return type:availability (bool)
receive(command_list)

Receive a list of commands from the previous engine, print the commands, and then send them on to the next engine.

Parameters:command_list (list<Command>) – List of Commands to print (and potentially send on to the next engine).
class projectq.backends.IBMBackend(use_hardware=False, num_runs=1024, verbose=False, user=None, password=None)

The IBM Backend class, which stores the circuit, transforms it to JSON QASM, and sends the circuit through the IBM API.

__init__(use_hardware=False, num_runs=1024, verbose=False, user=None, password=None)

Initialize the Backend object.

Parameters:
  • use_hardware (bool) – If True, the code is run on the IBM quantum chip (instead of using the IBM simulator)
  • num_runs (int) – Number of runs to collect statistics. (default is 1024)
  • verbose (bool) – If True, statistics are printed, in addition to the measurement result being registered (at the end of the circuit).
  • user (string) – IBM Quantum Experience user name
  • password (string) – IBM Quantum Experience password
get_probabilities(qureg)

Return the list of basis states with corresponding probabilities.

The measured bits are ordered according to the supplied quantum register, i.e., the left-most bit in the state-string corresponds to the first qubit in the supplied quantum register.

Warning

Only call this function after the circuit has been executed!

Parameters:qureg (list<Qubit>) – Quantum register determining the order of the qubits.
Returns:Dictionary mapping n-bit strings to probabilities.
Return type:probability_dict (dict)
Raises:Exception – If no data is available (i.e., if the circuit has not been executed).
is_available(cmd)

Return true if the command can be executed.

The IBM quantum chip can do X, Y, Z, T, Tdag, S, Sdag, and CX / CNOT.

Parameters:cmd (Command) – Command for which to check availability
receive(command_list)

Receives a command list and, for each command, stores it until completion.

Parameters:command_list – List of commands to execute
class projectq.backends.ResourceCounter

ResourceCounter is a compiler engine which counts the number of gates and max. number of active qubits.

gate_counts

dict – Dictionary of gate counts. The keys are string representations of the gate.

max_width

int – Maximal width (=max. number of active qubits at any given point).

__init__()

Initialize a resource counter engine.

Sets all statistics to zero.

is_available(cmd)

Specialized implementation of is_available: Returns True if the ResourceCounter is the last engine (since it can count any command).

Parameters:cmd (Command) – Command for which to check availability (all Commands can be counted).
Returns:True, unless the next engine cannot handle the Command (if there is a next engine).
Return type:availability (bool)
receive(command_list)

Receive a list of commands from the previous engine, print the commands, and then send them on to the next engine.

Parameters:command_list (list<Command>) – List of commands to receive (and count).
class projectq.backends.Simulator(gate_fusion=False, rnd_seed=None)

Simulator is a compiler engine which simulates a quantum computer using C++- based kernels.

OpenMP is enabled and the number of threads can be controlled using the OMP_NUM_THREADS environment variable, i.e.

export OMP_NUM_THREADS=4 # use 4 threads
export OMP_PROC_BIND=spread # bind threads to processors by spreading
__init__(gate_fusion=False, rnd_seed=None)

Construct the C++/Python-simulator object and initialize it with a random seed.

Parameters:
  • gate_fusion (bool) – If True, gates are cached and only executed once a certain gate-size has been reached (only has an effect for the c++ simulator).
  • rnd_seed (int) – Random seed (uses random.randint(0, 1024) by default).

Example of gate_fusion: Instead of applying a Hadamard gate to 5 qubits, the simulator calculates the kronecker product of the 1-qubit matrices and then applies 1 5-qubit gate. This increases operational intensity and keeps the simulator from having to iterate through the state vector multiple times. Depending on the system (and, especially, number of threads), this may or may not be beneficial.

Note

If the C++ Simulator extension was not built or cannot be found, the Simulator defaults to a Python implementation of the kernels. While this is much slower, it is still good enough to run basic quantum algorithms.

If you need to run large simulations, check out the tutorial in the docs which gives futher hints on how to build the C++ extension.

cheat()

Access the ordering of the qubits and the state vector directly.

This is a cheat function which enables, e.g., more efficient evaluation of expectation values and debugging.

Returns:A tuple where the first entry is a dictionary mapping qubit indices to bit-locations and the second entry is the corresponding state vector
is_available(cmd)

Specialized implementation of is_available: The simulator can deal with all arbitrarily-controlled single-qubit gates which provide a gate-matrix (via gate.get_matrix()).

Parameters:cmd (Command) – Command for which to check availability (single-qubit gate, arbitrary controls)
Returns:True if it can be simulated and False otherwise.
receive(command_list)

Receive a list of commands from the previous engine and handle them (simulate them classically) prior to sending them on to the next engine.

Parameters:command_list (list<Command>) – List of commands to execute on the simulator.