Skip to content

builder

eigenkit.core.builder

A builder that creates a CircuitSpec one gate at a time.

The style follows Qiskit, Amazon Braket and CUDA Quantum: qc.rx(angle, qubit) adds a gate to qc itself and returns qc, so that calls can be chained.

CircuitBuilder sits between the ready-made blocks and writing the circuit data by hand. You can write a circuit gate by gate when that is the natural way, and then, if you want, call .to_block() to combine the result with other blocks.

CircuitBuilder

Build a CircuitSpec one gate at a time.

Example
qc = CircuitBuilder(n_qubits=3)
weights = qc.add_weights(6)
inputs = qc.add_inputs(3)
for qubit in range(3):
    qc.ry(inputs[qubit], qubit=qubit)
for depth in range(2):
    for qubit in range(3):
        qc.ry(weights[depth * 3 + qubit], qubit=qubit)
    for qubit in range(2):
        qc.cnot(qubit, qubit + 1)
spec = qc.build()

Parameters:

Name Type Description Default
n_qubits int

The number of qubits of the circuit being built. Every qubit index that a gate uses must be between 0 and n_qubits - 1.

required

Raises:

Type Description
ValueError

If n_qubits is not positive.

n_inputs property

The number of input features that add_inputs() has reserved so far.

The built CircuitSpec has the same number.

n_qubits property

The number of qubits of the circuit, as given to the constructor.

Every qubit index that a gate uses must be smaller than this number, and the number never changes.

n_weights property

The number of trainable weights that add_weights() has reserved so far.

The built CircuitSpec has the same number.

add_inputs(count)

Reserve count input features and return references to them.

This is the counterpart of add_weights() for data instead of trainable parameters.

Parameters:

Name Type Description Default
count int

The number of input features to reserve.

required

Returns:

Type Description
list[InputRef]

One InputRef for each reserved feature, in order.

add_weights(count)

Reserve count trainable weights and return references to them.

Pass a returned WeightRef wherever a gate takes an angle. The indices are local to this builder and start at 0. When the block is combined with others, assemble shifts them to their positions in the whole circuit.

Parameters:

Name Type Description Default
count int

The number of weights to reserve.

required

Returns:

Type Description
list[WeightRef]

One WeightRef for each reserved weight, in order.

build()

Return the current state of the builder as an immutable CircuitSpec.

cnot(control, target)

Add a controlled-NOT (CNOT) gate.

Parameters:

Name Type Description Default
control int

The qubit that controls the flip.

required
target int

The qubit that is flipped.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

Raises:

Type Description
ValueError

If control and target are the same qubit.

cphase(angle, control, target)

Add a controlled phase shift gate.

The gate is symmetric: the control and the target play the same role.

Parameters:

Name Type Description Default
angle ParameterLike

The phase. It can be a number or a symbolic reference.

required
control int

One of the two qubits.

required
target int

The other qubit. The gate acts in the same way if the two qubits are exchanged.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

cry(angle, control, target)

Add a controlled RY gate.

Parameters:

Name Type Description Default
angle ParameterLike

The rotation angle. It can be a number or a symbolic reference.

required
control int

The qubit that controls the rotation.

required
target int

The qubit that is rotated.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

h(qubit)

Add a Hadamard gate.

Parameters:

Name Type Description Default
qubit int

The target qubit.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

mcx(*qubits)

Add a multi-controlled X gate.

All the qubits except the last one are controls.

Parameters:

Name Type Description Default
*qubits int

Two or more distinct qubits. The controls come first, and the target is the last one.

()

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

Raises:

Type Description
ValueError

If fewer than two qubits are given, or if a qubit is repeated.

mcz(*qubits)

Add a multi-controlled Z gate.

All the qubits except the last one are controls.

Parameters:

Name Type Description Default
*qubits int

Two or more distinct qubits. The controls come first, and the target is the last one.

()

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

Raises:

Type Description
ValueError

If fewer than two qubits are given, or if a qubit is repeated.

pauli_exponential(paulis, angle, coefficient=1.0)

Add the exponential of a product of Pauli operators.

The gate is exp(-i * coefficient * angle * P), where P is the product of paulis. Each element of paulis is a pair (op, qubit), where op is "X", "Y" or "Z", and the qubits are distinct.

This is the Trotter building block that the quantum approximate optimisation algorithm (QAOA) needs for its cost and mixer layers, and that the unitary coupled-cluster singles and doubles (UCCSD) ansatz needs for its excitation operators. It is built from the core gates only. First, H gates (for X) and RX(π/2) gates (for Y) change each factor to the Z basis. Then a ladder of controlled-NOT (CNOT) gates accumulates the parity on the last qubit, and a central RZ(2 * coefficient * angle) is applied (because RZ(φ) = exp(-i φ Z / 2)). Finally, the inverse of the first steps is applied.

Parameters:

Name Type Description Default
paulis Sequence[tuple[str, int]]

The Pauli product, as (operator, qubit) pairs, where the operator is "X", "Y" or "Z" and the qubits are distinct. An empty sequence is the identity, and nothing is added.

required
angle ParameterLike

The rotation angle. It can be a number or a symbolic reference.

required
coefficient float

A number that multiplies the angle. This is where the weight of a Hamiltonian term goes. Default: 1.0.

1.0

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

phase_shift(angle, qubit)

Add a phase shift gate R(φ).

The gate multiplies |1⟩ by e^(iφ) and leaves |0⟩ unchanged.

Parameters:

Name Type Description Default
angle ParameterLike

The phase φ. It can be a number or a symbolic reference.

required
qubit int

The target qubit.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

rx(angle, qubit)

Add a rotation about the X axis.

Parameters:

Name Type Description Default
angle ParameterLike

The rotation angle. It can be a number, or a WeightRef, an InputRef or an expression, which is evaluated when the circuit is called.

required
qubit int

The target qubit.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

ry(angle, qubit)

Add a rotation about the Y axis.

Parameters:

Name Type Description Default
angle ParameterLike

The rotation angle. It can be a number, or a WeightRef, an InputRef or an expression.

required
qubit int

The target qubit.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

rz(angle, qubit)

Add a rotation about the Z axis.

Parameters:

Name Type Description Default
angle ParameterLike

The rotation angle. It can be a number, or a WeightRef, an InputRef or an expression.

required
qubit int

The target qubit.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

s(qubit)

Add an S gate, which is a quarter turn about the Z axis.

Its inverse is sdg().

Parameters:

Name Type Description Default
qubit int

The target qubit.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

sdg(qubit)

Add an S-dagger gate (Sdg), which is the inverse of s().

Parameters:

Name Type Description Default
qubit int

The target qubit.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

swap(qubit0, qubit1)

Add a SWAP gate, which exchanges the states of two qubits.

Parameters:

Name Type Description Default
qubit0 int

The first qubit.

required
qubit1 int

The second qubit.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

to_block()

Wrap the current state of the builder in a CustomBlock.

This is useful to build a part of a circuit one gate at a time, and then to combine it with other blocks. When the blocks are assembled, the indices of the WeightRef and InputRef objects of this block are shifted to their positions in the whole circuit.

x(qubit)

Add a Pauli X gate, which is a bit flip.

Parameters:

Name Type Description Default
qubit int

The target qubit.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.

z(qubit)

Add a Pauli Z gate, which is a phase flip.

Parameters:

Name Type Description Default
qubit int

The target qubit.

required

Returns:

Type Description
'CircuitBuilder'

This builder, so that calls can be chained.