Circuits

Circuit objects

class quantumflow.Circuit(*elements: Iterable[Operation] | Operation, qubits: Sequence[Qubit] | None = None)

A quantum Circuit contains a sequences of circuit elements. These can be any quantum Operation, including other circuits.

property H: Circuit

Returns the Hermitian conjugate of this circuit. If all the subsidiary gates are unitary, returns the circuit inverse.

add(other: Iterable[Operation]) Circuit

Concatenate operations and return new circuit

aschannel() Channel

Convert this quantum operation to a channel (if possible).

Raises:

ValueError – If this operation cannot be converted to a Channel

asgate() Gate

Convert this quantum operation to a gate (if possible).

Raises:

ValueError – If this operation cannot be converted to a Gate

decompose() Iterator[Operation]

Decompose this operation into smaller or more standard subunits. If cannot be decomposed, returns self.

Returns: An iteration of operations.

evolve(rho: Density | None = None) Density

Apply the action of this operation upon a mixed state

flat() Iterator[Operation]

Iterate over all elementary elements of Circuit, recursively flattening composite elements such as sub-Circuit’s, DAGCircuit’s, and Moment’s

on(*qubits: Qubit) Circuit

Return a copy of this Operation with new qubits

param(name: str) float | Expr

Return a a named parameters of this Operation.

Raises:

KeyError – If unrecognized parameter name

property params: Tuple[float | Expr, ...]

Return all of the parameters of this Operation

resolve(subs: Mapping[str, float]) Circuit

Resolve the parameters of all of the elements of this circuit

rewire(labels: Dict[Qubit, Qubit]) Circuit

Relabel qubits and return copy of this Operation

run(ket: State | None = None) State

Apply the action of this circuit upon a state.

If no initial state provided an initial zero state will be created.

size() int

Return the number of operations in this circuit

specialize() Circuit

Specialize all of the elements of this circuit

class quantumflow.DAGCircuit(elements: Iterable[Operation])

A Directed Acyclic Graph representation of a Circuit.

The circuit is converted to a networkx directed acyclic multi-graph, stored in the graph attribute.

There are 3 node types, ‘in’ nodes representing qubits at the start of a circuit; operation nodes; and ‘out’ nodes for qubits at the end of a circuit. Edges are directed from ‘in’ to ‘out’ via the Operation nodes. Each edge is keyed to a qubit.

A DAGCircuit is considered a mutable object. But it should not be mutated if it is part of another Circuit or other immutable composite Operation.

DAGCircuit is iterable, yielding all of the operation nodes in topological sort order.

Note: Provisional API

property H: DAGCircuit

Return the Hermitian conjugate of this quantum operation.

For unitary Gates (and Circuits composed of the same) the Hermitian conjugate returns the inverse Gate (or Circuit)

Raises:

ValueError – If this operation does not support Hermitian conjugate

aschannel() Channel

Convert this quantum operation to a channel (if possible).

Raises:

ValueError – If this operation cannot be converted to a Channel

asgate() Gate

Convert this quantum operation to a gate (if possible).

Raises:

ValueError – If this operation cannot be converted to a Gate

component_nb() int

Return the number of independent components that this DAGCircuit can be split into.

components() List[DAGCircuit]

Split DAGCircuit into independent components

depth(local: bool = True) int

Return the circuit depth.

Parameters:

local – If True include local one-qubit gates in depth calculation. Else return the multi-qubit gate depth.

evolve(rho: Density) Density

Apply the action of this operation upon a mixed state

moments() Circuit

Split DAGCircuit into Moments, where the operations within each moment operate on different qubits (and therefore commute).

Returns: A Circuit of Moments

on(*qubits: Qubit) DAGCircuit

Return a copy of this Operation with new qubits

property qubit_nb: int

Return the total number of qubits

property qubits: Sequence[Qubit]

Return the total number of qubits

rewire(labels: Dict[Qubit, Qubit]) DAGCircuit

Relabel qubits and return copy of this Operation

run(ket: State) State

Apply the action of this operation upon a pure state

size() int

Return the number of operations.

Standard circuits

quantumflow.control_circuit(controls: Sequence[Qubit], gate: Gate) Circuit

Returns a circuit for a target gate controlled by a collection of control qubits. [Barenco1995]

Uses a number of gates quadratic in the number of control qubits.

[Barenco1995]

A. Barenco, C. Bennett, R. Cleve (1995) Elementary Gates for Quantum Computation`<https://arxiv.org/abs/quant-ph/9503016>`_ Sec 7.2

quantumflow.zyz_circuit(t0: float | Expr, t1: float | Expr, t2: float | Expr, q0: Qubit) Circuit

A circuit of ZPow, XPow, ZPow gates on the same qubit

quantumflow.euler_circuit(t0: float | Expr, t1: float | Expr, t2: float | Expr, q0: Qubit, euler: str = 'ZYZ') Circuit

A Euler decomposition of a 1-qubit gate.

The ‘euler’ argument can be used to specify any of the 6 Euler decompositions: ‘XYX’, ‘XZX’, ‘YXY’, ‘YZY’, ‘ZXZ’, ‘ZYZ’ (Default)

quantumflow.phase_estimation_circuit(gate: Gate, outputs: Sequence[Qubit]) Circuit

Returns a circuit for quantum phase estimation.

The gate has an eigenvector with eigenvalue e^(i 2 pi phase). To run the circuit, the eigenvector should be set on the gate qubits, and the output qubits should be in the zero state. After evolution and measurement, the output qubits will be (approximately) a binary fraction representation of the phase.

The output registers can be converted with the aid of the quantumflow.utils.bitlist_to_int() method.

>>> import numpy as np
>>> import quantumflow as qf
>>> N = 8
>>> phase = 1/4
>>> gate = qf.Rz(-4*np.pi*phase, N)
>>> circ = qf.phase_estimation_circuit(gate, range(N))
>>> res = circ.run().measure()[0:N]
>>> est_phase = int(''.join([str(d) for d in res]), 2) / 2**N # To float
>>> print(phase, est_phase)
0.25 0.25
quantumflow.addition_circuit(addend0: Sequence[Qubit], addend1: Sequence[Qubit], carry: Sequence[Qubit]) Circuit

Returns a quantum circuit for ripple-carry addition. [Cuccaro2004]

Requires two carry qubit (input and output). The result is returned in addend1.

[Cuccaro2004]

A new quantum ripple-carry addition circuit, Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David Petrie Moulton arXiv:quant-ph/0410184 (2004)

quantumflow.ghz_circuit(qubits: Sequence[Qubit]) Circuit

Returns a circuit that prepares a multi-qubit Bell state from the zero state.

quantumflow.graph_circuit(topology: Graph, steps: int, params: Sequence[float]) Circuit

Create a multilayer parameterized circuit given a graph of connected qubits.

We alternate between applying a sublayer of arbitrary 1-qubit gates to all qubits, and a sublayer of ZZ gates between all connected qubits.

In practice the pattern is ZPow, XPow, ZPow, (ZZ, XPow, ZPow )*, where ZPow are 1-qubit Z rotations, and XPow and 1-qubits X rotations. Since a Z rotation commutes across a ZZ, we only need one Z sublayer per layer.

Our fundamental 2-qubit interaction is the Ising like ZZ gate. We could apply a more general gate, such as the universal Canonical gate. But ZZ gates commute with each other, whereas other choice of gate would not, which would necessitate specifying the order of all 2-qubit gates within the layer.

quantumflow.graph_circuit_params(topology: Graph, steps: int, init_bias: float = 0.0, init_scale: float = 0.01) Sequence[float]

Return a set of initial parameters for graph_circuit()

Visualizations

quantumflow.circuit_to_diagram(circ: Circuit, qubits: Sequence[Qubit] | None = None, use_unicode: bool = True, transpose: bool = False, qubit_labels: bool = True) str

Draw a text diagram of a quantum circuit.

Parameters:
  • circ – A quantum Circuit

  • qubits – Optional qubit list to specify qubit order

  • use_unicode – If false, return ascii

  • qubit_labels – If false, do not display qubit names

Returns:

A string representation of the circuit.

quantumflow.circuit_to_image(circ: Circuit, qubits: Sequence[Qubit] | None = None) Image

Create an image of a quantum circuit.

A convenience function that calls circuit_to_latex() and latex_to_image().

Parameters:
  • circ – A quantum Circuit

  • qubits – Optional qubit list to specify qubit order

Returns:

Returns – A PIL Image (Use img.show() to display)

Raises:
  • NotImplementedError – For unsupported gates.

  • OSError – If an external dependency is not installed.

quantumflow.circuit_to_latex(circ: Circuit, qubits: Sequence[Qubit] | None = None, document: bool = True, package: str = 'quantikz', options: str | None = None, scale: float = 0.75, qubit_labels: bool = True, left_labels: Sequence[str] | None = None, right_labels: Sequence[str] | None = None) str

Create an image of a quantum circuit in LaTeX.

Parameters:
  • circ – A quantum Circuit

  • qubits – Optional qubit list to specify qubit order

  • document – If false, just the qcircuit latex is returned. Else the circuit image is wrapped in a standalone LaTeX document ready for typesetting.

  • package – The LaTeX package used for rendering. Either ‘qcircuit’ or ‘quantikz’ (default)

Returns:

A LaTeX string representation of the circuit.

Raises:

NotImplementedError – For unsupported gates.

Refs:
LaTeX Qcircuit package

(https://arxiv.org/pdf/quant-ph/0406003).

LaTeX quantikz package

(https://arxiv.org/abs/1809.03842).

quantumflow.latex_to_image(latex: str) Image

Convert a single page LaTeX document into an image.

To display the returned image, img.show()

Required external dependencies: pdflatex (with qcircuit package), and poppler (for pdftocairo).

Parameters:

string. (A LaTeX document as a) –

Returns:

A PIL Image

Raises:

OSError – If an external dependency is not installed.