meta
Contains meta statements which allow more optimal code while making it easier for users to write their code. Examples are with Compute, followed by an automatic uncompute or with Control, which allows the user to condition an entire code block upon the state of a qubit.
Definition of Compute, Uncompute and CustomUncompute. |
|
Contains the tools to make an entire section of operations controlled. |
|
Tools to easily invert a sequence of gates. |
|
Define the DirtyQubitTag meta tag. |
|
Exception classes for projectq.meta. |
|
Definition of LogicalQubitIDTag to annotate a MeasureGate for mapped qubits. |
|
Tools to implement loops. |
|
Tools to add/remove compiler engines to the MainEngine list. |
|
Return canonical form for control state. |
|
|
Start a compute-section. |
Compute meta tag. |
|
|
Condition an entire code block on the value of qubits being 1. |
|
Start a custom uncompute-section. |
|
Invert an entire code block. |
Dirty qubit meta tag. |
|
|
Remove an engine from the singly-linked list of engines. |
Return the number of control qubits of the command object cmd. |
|
Return whether a command has negatively controlled qubits. |
|
|
Insert an engine into the singly-linked list of engines. |
|
LogicalQubitIDTag for a mapped qubit to annotate a MeasureGate. |
|
Loop n times over an entire code block. |
Loop meta tag. |
|
|
Uncompute automatically. |
Uncompute meta tag. |
Submodules
_compute
Definition of Compute, Uncompute and CustomUncompute.
Contains Compute, Uncompute, and CustomUncompute classes which can be used to annotate Compute / Action / Uncompute sections, facilitating the conditioning of the entire operation on the value of a qubit / register (only Action needs controls). This file also defines the corresponding meta tags.
- class projectq.meta._compute.Compute(engine)[source]
Start a compute-section.
Example
with Compute(eng): do_something(qubits) action(qubits) Uncompute(eng) # runs inverse of the compute section
Warning
If qubits are allocated within the compute section, they must either be uncomputed and deallocated within that section or, alternatively, uncomputed and deallocated in the following uncompute section.
This means that the following examples are valid:
with Compute(eng): anc = eng.allocate_qubit() do_something_with_ancilla(anc) ... uncompute_ancilla(anc) del anc do_something_else(qubits) Uncompute(eng) # will allocate a new ancilla (with a different id) # and then deallocate it again
with Compute(eng): anc = eng.allocate_qubit() do_something_with_ancilla(anc) ... do_something_else(qubits) Uncompute(eng) # will deallocate the ancilla!
After the uncompute section, ancilla qubits allocated within the compute section will be invalid (and deallocated). The same holds when using CustomUncompute.
Failure to comply with these rules results in an exception being thrown.
- class projectq.meta._compute.ComputeEngine[source]
Add Compute-tags to all commands and stores them (to later uncompute them automatically).
- end_compute()[source]
End the compute step (exit the with Compute() - statement).
Will tell the Compute-engine to stop caching. It then waits for the uncompute instruction, which is when it sends all cached commands inverted and in reverse order down to the next compiler engine.
- Raises
QubitManagementError – If qubit has been deallocated in Compute section which has not been allocated in Compute section
- receive(command_list)[source]
Receive a list of commands.
If in compute-mode, receive commands and store deepcopy of each cmd. Add ComputeTag to received cmd and send it on. Otherwise, send all received commands directly to next_engine.
- Parameters
command_list (list<Command>) – List of commands to receive.
- run_uncompute()[source]
Send uncomputing gates.
Sends the inverse of the stored commands in reverse order down to the next engine. And also deals with allocated qubits in Compute section. If a qubit has been allocated during compute, it will be deallocated during uncompute. If a qubit has been allocated and deallocated during compute, then a new qubit is allocated and deallocated during uncompute.
- class projectq.meta._compute.CustomUncompute(engine)[source]
Start a custom uncompute-section.
Example
with Compute(eng): do_something(qubits) action(qubits) with CustomUncompute(eng): do_something_inverse(qubits)
- Raises
QubitManagementError – If qubits are allocated within Compute or within CustomUncompute context but are not deallocated.
- exception projectq.meta._compute.NoComputeSectionError[source]
Exception raised if uncompute is called but no compute section found.
- projectq.meta._compute.Uncompute(engine)[source]
Uncompute automatically.
Example
with Compute(eng): do_something(qubits) action(qubits) Uncompute(eng) # runs inverse of the compute section
_control
Contains the tools to make an entire section of operations controlled.
Example
with Control(eng, qubit1):
H | qubit2
X | qubit3
- class projectq.meta._control.Control(engine, qubits, ctrl_state=CtrlAll.One)[source]
Condition an entire code block on the value of qubits being 1.
Example
with Control(eng, ctrlqubits): do_something(otherqubits)
- class projectq.meta._control.ControlEngine(qubits, ctrl_state=CtrlAll.One)[source]
Add control qubits to all commands that have no compute / uncompute tags.
- projectq.meta._control.canonical_ctrl_state(ctrl_state, num_qubits)[source]
Return canonical form for control state.
- Parameters
ctrl_state (int,str,CtrlAll) – Initial control state representation
num_qubits (int) – number of control qubits
- Returns
Canonical form of control state (currently a string composed of ‘0’ and ‘1’)
Note
In case of integer values for ctrl_state, the least significant bit applies to the first qubit in the qubit register, e.g. if ctrl_state == 2, its binary representation if ‘10’ with the least significan bit being 0.
This means in particular that the followings are equivalent:
canonical_ctrl_state(6, 3) == canonical_ctrl_state(6, '110')
_dagger
Tools to easily invert a sequence of gates.
with Dagger(eng):
H | qubit1
Rz(0.5) | qubit2
- class projectq.meta._dagger.Dagger(engine)[source]
Invert an entire code block.
Use it with a with-statement, i.e.,
with Dagger(eng): [code to invert]
Warning
If the code to invert contains allocation of qubits, those qubits have to be deleted prior to exiting the ‘with Dagger()’ context.
This code is NOT VALID:
with Dagger(eng): qb = eng.allocate_qubit() H | qb # qb is still available!!!
The correct way of handling qubit (de-)allocation is as follows:
with Dagger(eng): qb = eng.allocate_qubit() ... del qb # sends deallocate gate (which becomes an allocate)
_dirtyqubit
Define the DirtyQubitTag meta tag.
_exceptions
Exception classes for projectq.meta.
_logicalqubit
Definition of LogicalQubitIDTag to annotate a MeasureGate for mapped qubits.
_loop
Tools to implement loops.
Example
with Loop(eng, 4):
H | qb
Rz(M_PI/3.) | qb
- class projectq.meta._loop.Loop(engine, num)[source]
Loop n times over an entire code block.
Example
with Loop(eng, 4): # [quantum gates to be executed 4 times]
Warning
If the code in the loop contains allocation of qubits, those qubits have to be deleted prior to exiting the ‘with Loop()’ context.
This code is NOT VALID:
with Loop(eng, 4): qb = eng.allocate_qubit() H | qb # qb is still available!!!
The correct way of handling qubit (de-)allocation is as follows:
with Loop(eng, 4): qb = eng.allocate_qubit() ... del qb # sends deallocate gate
- class projectq.meta._loop.LoopEngine(num)[source]
A compiler engine to represent executing part of the code multiple times.
Stores all commands and, when done, executes them num times if no loop tag handler engine is available. If there is one, it adds a loop_tag to the commands and sends them on.
- receive(command_list)[source]
Receive (and potentially temporarily store) all commands.
Add LoopTag to all receiving commands and send to the next engine if a further engine is a LoopTag-handling engine. Otherwise store all commands (to later unroll them). Check that within the loop body, all allocated qubits have also been deallocated. If loop needs to be unrolled and ancilla qubits have been allocated within the loop body, then store a reference all these qubit ids (to change them when unrolling the loop)
- Parameters
command_list (list<Command>) – List of commands to store and later unroll or, if there is a LoopTag-handling engine, add the LoopTag.
_util
Tools to add/remove compiler engines to the MainEngine list.
- projectq.meta._util.drop_engine_after(prev_engine)[source]
Remove an engine from the singly-linked list of engines.
- Parameters
prev_engine (projectq.cengines.BasicEngine) – The engine just before the engine to drop.
- Returns
The dropped engine.
- Return type
Engine
- projectq.meta._util.insert_engine(prev_engine, engine_to_insert)[source]
Insert an engine into the singly-linked list of engines.
It also sets the correct main_engine for engine_to_insert.
- Parameters
prev_engine (projectq.cengines.BasicEngine) – The engine just before the insertion point.
engine_to_insert (projectq.cengines.BasicEngine) – The engine to insert at the insertion point.
Module contents
The projectq.meta package features meta instructions which help both the user and the compiler in writing/producing efficient code. It includes, e.g.,
Loop (with Loop(eng): …)
Compute/Uncompute (with Compute(eng): …, […], Uncompute(eng))
Control (with Control(eng, ctrl_qubits): …)
Dagger (with Dagger(eng): …)
- class projectq.meta.Compute(engine)[source]
Start a compute-section.
Example
with Compute(eng): do_something(qubits) action(qubits) Uncompute(eng) # runs inverse of the compute section
Warning
If qubits are allocated within the compute section, they must either be uncomputed and deallocated within that section or, alternatively, uncomputed and deallocated in the following uncompute section.
This means that the following examples are valid:
with Compute(eng): anc = eng.allocate_qubit() do_something_with_ancilla(anc) ... uncompute_ancilla(anc) del anc do_something_else(qubits) Uncompute(eng) # will allocate a new ancilla (with a different id) # and then deallocate it again
with Compute(eng): anc = eng.allocate_qubit() do_something_with_ancilla(anc) ... do_something_else(qubits) Uncompute(eng) # will deallocate the ancilla!
After the uncompute section, ancilla qubits allocated within the compute section will be invalid (and deallocated). The same holds when using CustomUncompute.
Failure to comply with these rules results in an exception being thrown.
- __init__(engine)[source]
Initialize a Compute context.
- Parameters
engine (BasicEngine) – Engine which is the first to receive all commands (normally: MainEngine).
- class projectq.meta.Control(engine, qubits, ctrl_state=CtrlAll.One)[source]
Condition an entire code block on the value of qubits being 1.
Example
with Control(eng, ctrlqubits): do_something(otherqubits)
- class projectq.meta.CustomUncompute(engine)[source]
Start a custom uncompute-section.
Example
with Compute(eng): do_something(qubits) action(qubits) with CustomUncompute(eng): do_something_inverse(qubits)
- Raises
QubitManagementError – If qubits are allocated within Compute or within CustomUncompute context but are not deallocated.
- __init__(engine)[source]
Initialize a CustomUncompute context.
- Parameters
engine (BasicEngine) – Engine which is the first to receive all commands (normally: MainEngine).
- class projectq.meta.Dagger(engine)[source]
Invert an entire code block.
Use it with a with-statement, i.e.,
with Dagger(eng): [code to invert]
Warning
If the code to invert contains allocation of qubits, those qubits have to be deleted prior to exiting the ‘with Dagger()’ context.
This code is NOT VALID:
with Dagger(eng): qb = eng.allocate_qubit() H | qb # qb is still available!!!
The correct way of handling qubit (de-)allocation is as follows:
with Dagger(eng): qb = eng.allocate_qubit() ... del qb # sends deallocate gate (which becomes an allocate)
- class projectq.meta.LogicalQubitIDTag(logical_qubit_id)[source]
LogicalQubitIDTag for a mapped qubit to annotate a MeasureGate.
- logical_qubit_id
Logical qubit id
- Type
int
- class projectq.meta.Loop(engine, num)[source]
Loop n times over an entire code block.
Example
with Loop(eng, 4): # [quantum gates to be executed 4 times]
Warning
If the code in the loop contains allocation of qubits, those qubits have to be deleted prior to exiting the ‘with Loop()’ context.
This code is NOT VALID:
with Loop(eng, 4): qb = eng.allocate_qubit() H | qb # qb is still available!!!
The correct way of handling qubit (de-)allocation is as follows:
with Loop(eng, 4): qb = eng.allocate_qubit() ... del qb # sends deallocate gate
- __init__(engine, num)[source]
Enter a looped section.
- Parameters
engine – Engine handling the commands (usually MainEngine)
num (int) – Number of loop iterations
Example
with Loop(eng, 4): H | qb Rz(M_PI/3.) | qb
- Raises
TypeError – If number of iterations (num) is not an integer
ValueError – If number of iterations (num) is not >= 0
- projectq.meta.Uncompute(engine)[source]
Uncompute automatically.
Example
with Compute(eng): do_something(qubits) action(qubits) Uncompute(eng) # runs inverse of the compute section
- projectq.meta.canonical_ctrl_state(ctrl_state, num_qubits)[source]
Return canonical form for control state.
- Parameters
ctrl_state (int,str,CtrlAll) – Initial control state representation
num_qubits (int) – number of control qubits
- Returns
Canonical form of control state (currently a string composed of ‘0’ and ‘1’)
Note
In case of integer values for ctrl_state, the least significant bit applies to the first qubit in the qubit register, e.g. if ctrl_state == 2, its binary representation if ‘10’ with the least significan bit being 0.
This means in particular that the followings are equivalent:
canonical_ctrl_state(6, 3) == canonical_ctrl_state(6, '110')
- projectq.meta.drop_engine_after(prev_engine)[source]
Remove an engine from the singly-linked list of engines.
- Parameters
prev_engine (projectq.cengines.BasicEngine) – The engine just before the engine to drop.
- Returns
The dropped engine.
- Return type
Engine
- projectq.meta.get_control_count(cmd)[source]
Return the number of control qubits of the command object cmd.
- projectq.meta.has_negative_control(cmd)[source]
Return whether a command has negatively controlled qubits.
- projectq.meta.insert_engine(prev_engine, engine_to_insert)[source]
Insert an engine into the singly-linked list of engines.
It also sets the correct main_engine for engine_to_insert.
- Parameters
prev_engine (projectq.cengines.BasicEngine) – The engine just before the insertion point.
engine_to_insert (projectq.cengines.BasicEngine) – The engine to insert at the insertion point.