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.

projectq.meta._compute

Definition of Compute, Uncompute and CustomUncompute.

projectq.meta._control

Contains the tools to make an entire section of operations controlled.

projectq.meta._dagger

Tools to easily invert a sequence of gates.

projectq.meta._dirtyqubit

Define the DirtyQubitTag meta tag.

projectq.meta._exceptions

Exception classes for projectq.meta.

projectq.meta._logicalqubit

Definition of LogicalQubitIDTag to annotate a MeasureGate for mapped qubits.

projectq.meta._loop

Tools to implement loops.

projectq.meta._util

Tools to add/remove compiler engines to the MainEngine list.

projectq.meta.canonical_ctrl_state(...)

Return canonical form for control state.

projectq.meta.Compute(engine)

Start a compute-section.

projectq.meta.ComputeTag()

Compute meta tag.

projectq.meta.Control(engine, qubits[, ...])

Condition an entire code block on the value of qubits being 1.

projectq.meta.CustomUncompute(engine)

Start a custom uncompute-section.

projectq.meta.Dagger(engine)

Invert an entire code block.

projectq.meta.DirtyQubitTag()

Dirty qubit meta tag.

projectq.meta.drop_engine_after(prev_engine)

Remove an engine from the singly-linked list of engines.

projectq.meta.get_control_count(cmd)

Return the number of control qubits of the command object cmd.

projectq.meta.has_negative_control(cmd)

Return whether a command has negatively controlled qubits.

projectq.meta.insert_engine(prev_engine, ...)

Insert an engine into the singly-linked list of engines.

projectq.meta.LogicalQubitIDTag(logical_qubit_id)

LogicalQubitIDTag for a mapped qubit to annotate a MeasureGate.

projectq.meta.Loop(engine, num)

Loop n times over an entire code block.

projectq.meta.LoopTag(num)

Loop meta tag.

projectq.meta.Uncompute(engine)

Uncompute automatically.

projectq.meta.UncomputeTag()

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.ComputeTag[source]

Compute meta tag.

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
class projectq.meta._compute.UncomputeEngine[source]

Adds Uncompute-tags to all commands.

receive(command_list)[source]

Receive a list of commands.

Receive commands and add an UncomputeTag to their tags.

Parameters:

command_list (list<Command>) – List of commands to handle.

class projectq.meta._compute.UncomputeTag[source]

Uncompute meta tag.

_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.

receive(command_list)[source]

Receive a list of commands.

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 following are equivalent:

canonical_ctrl_state(6, 3) == canonical_ctrl_state(6, '110')
projectq.meta._control.get_control_count(cmd)[source]

Return the number of control qubits of the command object cmd.

projectq.meta._control.has_negative_control(cmd)[source]

Return whether a command has negatively controlled qubits.

_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]
    pass

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._dagger.DaggerEngine[source]

Store all commands and, when done, inverts the circuit & runs it.

receive(command_list)[source]

Receive a list of commands and store them for later inversion.

Parameters:

command_list (list<Command>) – List of commands to temporarily store.

run()[source]

Run the stored circuit in reverse and check that local qubits have been deallocated.

_dirtyqubit

Define the DirtyQubitTag meta tag.

class projectq.meta._dirtyqubit.DirtyQubitTag[source]

Dirty qubit meta tag.

_exceptions

Exception classes for projectq.meta.

exception projectq.meta._exceptions.QubitManagementError[source]

Exception raised when the lifetime of a qubit is problematic within a context manager.

This may occur within Loop, Dagger or Compute regions.

_logicalqubit

Definition of LogicalQubitIDTag to annotate a MeasureGate for mapped qubits.

class projectq.meta._logicalqubit.LogicalQubitIDTag(logical_qubit_id)[source]

LogicalQubitIDTag for a mapped qubit to annotate a MeasureGate.

logical_qubit_id

Logical qubit id

Type:

int

_loop

Tools to implement loops.

Example

with Loop(eng, 4):
    H | qb
Rz(M_PI / 3.0) | 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]
    pass

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.

run()[source]

Apply the loop statements to all stored commands.

Unrolls the loop if LoopTag is not supported by any of the following engines, i.e., if

is_meta_tag_supported(next_engine, LoopTag) == False
class projectq.meta._loop.LoopTag(num)[source]

Loop meta tag.

loop_tag_id = 0[source]

_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:

Module contents

Provides 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.ComputeTag[source]

Compute meta tag.

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)
__init__(engine, qubits, ctrl_state=CtrlAll.One)[source]

Enter a controlled section.

Parameters:
  • engine – Engine which handles the commands (usually MainEngine)

  • qubits (list of Qubit objects) – Qubits to condition on

Enter the section using a with-statement:

with Control(eng, ctrlqubits):
    ...
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]
    pass

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)
__init__(engine)[source]

Enter an inverted section.

Parameters:

engine – Engine which handles the commands (usually MainEngine)

Example (executes an inverse QFT):

with Dagger(eng):
    QFT | qubits
class projectq.meta.DirtyQubitTag[source]

Dirty qubit meta tag.

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

__init__(logical_qubit_id)[source]

Initialize a LogicalQubitIDTag object.

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]
    pass

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.0) | qb
Raises:
  • TypeError – If number of iterations (num) is not an integer

  • ValueError – If number of iterations (num) is not >= 0

class projectq.meta.LoopTag(num)[source]

Loop meta tag.

__init__(num)[source]

Initialize a LoopTag object.

loop_tag_id = 0[source]
projectq.meta.Uncompute(engine)[source]

Uncompute automatically.

Example

with Compute(eng):
    do_something(qubits)
action(qubits)
Uncompute(eng)  # runs inverse of the compute section
class projectq.meta.UncomputeTag[source]

Uncompute meta tag.

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 following 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: