cengines

The ProjectQ compiler engines package.

projectq.cengines.BasicEngine() Basic compiler engine: All compiler engines are derived from this class.
projectq.cengines.ForwarderEngine(engine[, …]) A ForwarderEngine is a trivial engine which forwards all commands to the next engine.
projectq.cengines.CommandModifier(cmd_mod_fun) CommandModifier is a compiler engine which applies a function to all incoming commands, sending on the resulting command instead of the original one.
projectq.cengines.IBMCNOTMapper() CNOT mapper for the IBM backend.
projectq.cengines.ManualMapper([map_fun]) Manual Mapper which adds QubitPlacementTags to Allocate gate commands according to a user-specified mapping.
projectq.cengines.MainEngine([backend, …]) The MainEngine class provides all functionality of the main compiler engine.
projectq.cengines.LocalOptimizer([m]) LocalOptimizer is a compiler engine which optimizes locally (merging rotations, cancelling gates with their inverse) in a local window of user- defined size.
projectq.cengines.AutoReplacer(…[, …]) The AutoReplacer is a compiler engine which uses engine.is_available in order to determine which commands need to be replaced/decomposed/compiled further.
projectq.cengines.InstructionFilter(filterfun) The InstructionFilter is a compiler engine which changes the behavior of is_available according to a filter function.
projectq.cengines.DecompositionRuleSet([…]) A collection of indexed decomposition rules.
projectq.cengines.DecompositionRule(…[, …]) A rule for breaking down specific gates into sequences of simpler gates.
projectq.cengines.TagRemover([tags]) TagRemover is a compiler engine which removes temporary command tags (see the tag classes such as LoopTag in projectq.meta._loop).
projectq.cengines.CompareEngine() CompareEngine is an engine which saves all commands.
projectq.cengines.DummyEngine([save_commands]) DummyEngine used for testing.

Module contents

class projectq.cengines.AutoReplacer(decompositionRuleSet, decomposition_chooser=<function AutoReplacer.<lambda>>)[source]

The AutoReplacer is a compiler engine which uses engine.is_available in order to determine which commands need to be replaced/decomposed/compiled further. The loaded setup is used to find decomposition rules appropriate for each command (e.g., setups.default).

__init__(decompositionRuleSet, decomposition_chooser=<function AutoReplacer.<lambda>>)[source]

Initialize an AutoReplacer.

Parameters:decomposition_chooser (function) – A function which, given the Command to decompose and a list of potential Decomposition objects, determines (and then returns) the ‘best’ decomposition.

The default decomposition chooser simply returns the first list element, i.e., calling

repl = AutoReplacer()

Amounts to

def decomposition_chooser(cmd, decomp_list):
    return decomp_list[0]
repl = AutoReplacer(decomposition_chooser)
receive(command_list)[source]

Receive a list of commands from the previous compiler engine and, if necessary, replace/decompose the gates according to the decomposition rules in the loaded setup.

Parameters:command_list (list<Command>) – List of commands to handle.
class projectq.cengines.BasicEngine[source]

Basic compiler engine: All compiler engines are derived from this class. It provides basic functionality such as qubit allocation/deallocation and functions that provide information about the engine’s position (e.g., next engine).

This information is provided by the MainEngine, which initializes all further engines.

next_engine

BasicEngine – Next compiler engine (or the back-end).

main_engine

MainEngine – Reference to the main compiler engine.

is_last_engine

bool – True for the last engine, which is the back-end.

__init__()[source]

Initialize the basic engine.

Initializes local variables such as _next_engine, _main_engine, etc. to None.

allocate_qubit(dirty=False)[source]

Return a new qubit as a list containing 1 qubit object (quantum register of size 1).

Allocates a new qubit by getting a (new) qubit id from the MainEngine, creating the qubit object, and then sending an AllocateQubit command down the pipeline. If dirty=True, the fresh qubit can be replaced by a pre-allocated one (in an unknown, dirty, initial state). Dirty qubits must be returned to their initial states before they are deallocated / freed.

All allocated qubits are added to the MainEngine’s set of active qubits as weak references. This allows proper clean-up at the end of the Python program (using atexit), deallocating all qubits which are still alive. Qubit ids of dirty qubits are registered in MainEngine’s dirty_qubits set.

Parameters:dirty (bool) – If True, indicates that the allocated qubit may be dirty (i.e., in an arbitrary initial state).
Returns:Qureg of length 1, where the first entry is the allocated qubit.
allocate_qureg(n)[source]

Allocate n qubits and return them as a quantum register, which is a list of qubit objects.

Parameters:n (int) – Number of qubits to allocate
Returns:Qureg of length n, a list of n newly allocated qubits.
deallocate_qubit(qubit)[source]

Deallocate a qubit (and sends the deallocation command down the pipeline). If the qubit was allocated as a dirty qubit, add DirtyQubitTag() to Deallocate command.

Parameters:qubit (BasicQubit) – Qubit to deallocate.
Raises:ValueError – Qubit already deallocated. Caller likely has a bug.
is_available(cmd)[source]

Default implementation of is_available: Ask the next engine whether a command is available, i.e., whether it can be executed by the next engine(s).

Parameters:cmd (Command) – Command for which to check availability.
Returns:True if the command can be executed.
Raises:LastEngineException – If is_last_engine is True but is_available is not implemented.
is_meta_tag_supported(meta_tag)[source]

Check if there is a compiler engine handling the meta tag

Parameters:
  • engine – First engine to check (then iteratively calls getNextEngine)
  • meta_tag – Meta tag class for which to check support
Returns:

True if one of the further compiler engines is a meta tag handler, i.e., engine.is_meta_tag_handler(meta_tag) returns True.

Return type:

supported (bool)

send(command_list)[source]

Forward the list of commands to the next engine in the pipeline.

class projectq.cengines.CommandModifier(cmd_mod_fun)[source]

CommandModifier is a compiler engine which applies a function to all incoming commands, sending on the resulting command instead of the original one.

__init__(cmd_mod_fun)[source]

Initialize the CommandModifier.

Parameters:cmd_mod_fun (function) – Function which, given a command cmd, returns the command it should send instead.

Example

def cmd_mod_fun(cmd):
    cmd.tags += [MyOwnTag()]
compiler_engine = CommandModifier(cmd_mod_fun)
...
receive(command_list)[source]

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

Parameters:command_list (list<Command>) – List of commands to receive and then (after modification) send on.
class projectq.cengines.CompareEngine[source]

CompareEngine is an engine which saves all commands. It is only intended for testing purposes. Two CompareEngine backends can be compared and return True if they contain the same commmands.

class projectq.cengines.DecompositionRule(gate_class, gate_decomposer, gate_recognizer=<function DecompositionRule.<lambda>>)[source]

A rule for breaking down specific gates into sequences of simpler gates.

__init__(gate_class, gate_decomposer, gate_recognizer=<function DecompositionRule.<lambda>>)[source]
Parameters:
  • gate_class (type) –

    The type of gate that this rule decomposes.

    The gate class is redundant information used to make lookups faster when iterating over a circuit and deciding “which rules apply to this gate?” again and again.

    Note that this parameter is a gate type, not a gate instance. You supply gate_class=MyGate or gate_class=MyGate().__class__, not gate_class=MyGate().

  • gate_decomposer (function[projectq.ops.Command]) – Function which, given the command to decompose, applies a sequence of gates corresponding to the high-level function of a gate of type gate_class.
  • (function[projectq.ops.Command] (gate_recognizer) –

    boolean): A predicate that determines if the decomposition applies to the given command (on top of the filtering by gate_class).

    For example, a decomposition rule may only to apply rotation gates that rotate by a specific angle.

    If no gate_recognizer is given, the decomposition applies to all gates matching the gate_class.

class projectq.cengines.DecompositionRuleSet(rules=None, modules=None)[source]

A collection of indexed decomposition rules.

__init__(rules=None, modules=None)[source]
Parameters:
  • list[DecompositionRule] (rules) – Initial decomposition rules.
  • modules (iterable[ModuleWithDecompositionRuleSet]) – A list of things with an “all_defined_decomposition_rules” property containing decomposition rules to add to the rule set.
add_decomposition_rule(rule)[source]

Add a decomposition rule to the rule set.

Parameters:rule (DecompositionRuleGate) – The decomposition rule to add.
class projectq.cengines.DummyEngine(save_commands=False)[source]

DummyEngine used for testing.

The DummyEngine forwards all commands directly to next engine. If self.is_last_engine == True it just discards all gates. By setting save_commands == True all commands get saved as a list in self.received_commands. Elements are appended to this list so they are ordered according to when they are received.

__init__(save_commands=False)[source]

Initialize DummyEngine

Parameters:save_commands (default = False) – If True, commands are saved in self.received_commands.
class projectq.cengines.ForwarderEngine(engine, cmd_mod_fun=None)[source]

A ForwarderEngine is a trivial engine which forwards all commands to the next engine.

It is mainly used as a substitute for the MainEngine at lower levels such that meta operations still work (e.g., with Compute).

__init__(engine, cmd_mod_fun=None)[source]

Initialize a ForwarderEngine.

Parameters:
  • engine (BasicEngine) – Engine to forward all commands to.
  • cmd_mod_fun (function) – Function which is called before sending a command. Each command cmd is replaced by the command it returns when getting called with cmd.
receive(command_list)[source]

Forward all commands to the next engine.

class projectq.cengines.IBMCNOTMapper[source]

CNOT mapper for the IBM backend.

Maps a given circuit to the IBM Quantum Experience chip. If necessary, it will flip around the CNOT gate by first applying Hadamard gates to both qubits, then CNOT with swapped control and target qubit, and finally Hadamard gates to both qubits. Furthermore, it adds QubitPlacementTags to Allocate gate commands.

Note

The mapper has to be run once on the entire circuit.

Warning

If the provided circuit cannot be mapped to the hardware layout without performing Swaps, the mapping procedure raises an Exception.

__init__()[source]

Initialize an IBM CNOT Mapper compiler engine.

Resets the mapping.

is_available(cmd)[source]

Check if the IBM backend can perform the Command cmd and return True if so.

Parameters:cmd (Command) – The command to check
receive(command_list)[source]

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

Parameters:command_list (list of Command objects) – list of commands to receive.
Raises:Exception – If mapping the CNOT gates to 1 qubit would require Swaps. The current version only supports remapping of CNOT gates without performing any Swaps due to the large costs associated with Swapping given the CNOT constraints.
class projectq.cengines.InstructionFilter(filterfun)[source]

The InstructionFilter is a compiler engine which changes the behavior of is_available according to a filter function. All commands are passed to this function, which then returns whether this command can be executed (True) or needs replacement (False).

__init__(filterfun)[source]

Initializer: The provided filterfun returns True for all commands which do not need replacement and False for commands that do.

Parameters:filterfun (function) – Filter function which returns True for available commands, and False otherwise. filterfun will be called as filterfun(self, cmd).
is_available(cmd)[source]

Specialized implementation of BasicBackend.is_available: Forwards this call to the filter function given to the constructor.

Parameters:cmd (Command) – Command for which to check availability.
receive(command_list)[source]

Forward all commands to the next engine.

Parameters:command_list (list<Command>) – List of commands to receive.
exception projectq.cengines.LastEngineException(engine)[source]

Exception thrown when the last engine tries to access the next one. (Next engine does not exist)

The default implementation of isAvailable simply asks the next engine whether the command is available. An engine which legally may be the last engine, this behavior needs to be adapted (see BasicEngine.isAvailable).

class projectq.cengines.LocalOptimizer(m=5)[source]

LocalOptimizer is a compiler engine which optimizes locally (merging rotations, cancelling gates with their inverse) in a local window of user- defined size.

It stores all commands in a list of lists, where each qubit has its own gate pipeline. After adding a gate, it tries to merge / cancel successive gates using the get_merged and get_inverse functions of the gate (if available). For examples, see BasicRotationGate. Once a list corresponding to a qubit contains >=m gates, the pipeline is sent on to the next engine.

__init__(m=5)[source]

Initialize a LocalOptimizer object.

Parameters:m (int) – Number of gates to cache per qubit, before sending on the first gate.
receive(command_list)[source]

Receive commands from the previous engine and cache them. If a flush gate arrives, the entire buffer is sent on.

class projectq.cengines.MainEngine(backend=None, engine_list=None, setup=None, verbose=False)[source]

The MainEngine class provides all functionality of the main compiler engine.

It initializes all further compiler engines (calls, e.g., .next_engine=…) and keeps track of measurement results and active qubits (and their IDs).

next_engine

BasicEngine – Next compiler engine (or the back-end).

main_engine

MainEngine – Self.

active_qubits

WeakSet – WeakSet containing all active qubits

dirty_qubits

Set – Containing all dirty qubit ids

backend

BasicEngine – Access the back-end.

__init__(backend=None, engine_list=None, setup=None, verbose=False)[source]

Initialize the main compiler engine and all compiler engines.

Sets ‘next_engine’- and ‘main_engine’-attributes of all compiler engines and adds the back-end as the last engine.

Parameters:
  • backend (BasicEngine) – Backend to send the circuit to.
  • engine_list (list<BasicEngine>) – List of engines / backends to use as compiler engines.
  • setup (module) – Setup module which defines a function called get_engine_list(). get_engine_list() returns the list of engines to be used as compiler engines. The default setup is projectq.setups.default (if no engine list and no setup is provided).
  • verbose (bool) – Either print full or compact error messages. Default: False (i.e. compact error messages).

Example

from projectq import MainEngine
eng = MainEngine() # uses default setup and the Simulator

Instead of the default setup one can use, e.g., one of the IBM setups which defines a custom engine_list useful for one of the IBM chips

Example

import projectq.setups.ibm
from projectq import MainEngine
eng = MainEngine(setup=projectq.setups.ibm)
# eng uses the default Simulator backend

Alternatively, one can specify all compiler engines explicitly, e.g.,

Example

from projectq.cengines import (TagRemover, AutoReplacer,
                               LocalOptimizer,
                               DecompositionRuleSet)
from projectq.backends import Simulator
from projectq import MainEngine
rule_set = DecompositionRuleSet()
engines = [AutoReplacer(rule_set), TagRemover(),
           LocalOptimizer(3)]
eng = MainEngine(Simulator(), engines)
flush(deallocate_qubits=False)[source]

Flush the entire circuit down the pipeline, clearing potential buffers (of, e.g., optimizers).

Parameters:deallocate_qubits (bool) – If True, deallocates all qubits that are still alive (invalidating references to them by setting their id to -1).
get_measurement_result(qubit)[source]

Return the classical value of a measured qubit, given that an engine registered this result previously (see setMeasurementResult).

Parameters:qubit (BasicQubit) – Qubit of which to get the measurement result.

Example

from projectq.ops import H, Measure
from projectq import MainEngine
eng = MainEngine()
qubit = eng.allocate_qubit() # quantum register of size 1
H | qubit
Measure | qubit
eng.get_measurement_result(qubit[0]) == int(qubit)
get_new_qubit_id()[source]

Returns a unique qubit id to be used for the next qubit allocation.

Returns:New unique qubit id.
Return type:new_qubit_id (int)
receive(command_list)[source]

Forward the list of commands to the first engine.

Parameters:command_list (list<Command>) – List of commands to receive (and then send on)
send(command_list)[source]

Forward the list of commands to the next engine in the pipeline.

It also shortens exception stack traces if self.verbose is False.

set_measurement_result(qubit, value)[source]

Register a measurement result

The engine being responsible for measurement results needs to register these results with the master engine such that they are available when the user calls an int() or bool() conversion operator on a measured qubit.

Parameters:
  • qubit (BasicQubit) – Qubit for which to register the measurement result.
  • value (bool) – Boolean value of the measurement outcome (True / False = 1 / 0 respectively).
class projectq.cengines.ManualMapper(map_fun=<function ManualMapper.<lambda>>)[source]

Manual Mapper which adds QubitPlacementTags to Allocate gate commands according to a user-specified mapping.

map

function – The function which maps a given qubit id to its location. It gets set when initializing the mapper.

__init__(map_fun=<function ManualMapper.<lambda>>)[source]

Initialize the mapper to a given mapping. If no mapping function is provided, the qubit id is used as the location.

Parameters:map_fun (function) – Function which, given the qubit id, returns an integer describing the physical location.
receive(command_list)[source]

Receives a command list and passes it to the next engine, adding qubit placement tags to allocate gates.

Parameters:command_list (list of Command objects) – list of commands to receive.
class projectq.cengines.TagRemover(tags=[<class 'projectq.meta._compute.ComputeTag'>, <class 'projectq.meta._compute.UncomputeTag'>])[source]

TagRemover is a compiler engine which removes temporary command tags (see the tag classes such as LoopTag in projectq.meta._loop).

Removing tags is important (after having handled them if necessary) in order to enable optimizations across meta-function boundaries (compute/ action/uncompute or loops after unrolling)

__init__(tags=[<class 'projectq.meta._compute.ComputeTag'>, <class 'projectq.meta._compute.UncomputeTag'>])[source]

Construct the TagRemover.

Parameters:tags – A list of meta tag classes (e.g., [ComputeTag, UncomputeTag]) denoting the tags to remove
receive(command_list)[source]

Receive a list of commands from the previous engine, remove all tags which are an instance of at least one of the meta tags provided in the constructor, and then send them on to the next compiler engine.

Parameters:command_list (list<Command>) – List of commands to receive and then (after removing tags) send on.