Circuit

class Circuit(num_qudits, radixes=[])[source]

Bases: DifferentiableUnitary, StateVectorMap, Collection[Operation]

A Circuit is a quantum program composed of operation objects.

The operations are organized in 2-dimensions, and are indexed by a CircuitPoint. The first index corresponds to an operation’s cycle. This describes when an operation will be executed. The second index is the qudit index and describes where the operation will execute. An operation can be multi-qudit meaning its location - list of qudit indices describing which qudits the operation affects - contains multiple indices. All operations exist in only one cycle at a time, but if an operation is multi-qudit, then it is pointed to by multiple qudit indices.

Invariants:
  1. A circuit method will never complete with an idle cycle. An idle cycle is one that contains no gates.

  2. No one logical operation will ever be pointed to from more than one cycle.

  3. Iterating through the entire circuit always produces operations in simulation order. This means that if those operations were applied to a quantum state in the same order, then the result is the same as simulating the circuit.

Notes

While a guarantee is made that the circuit never has any idle cycles, this means that cycles can be deleted or inserted during a method call. Therefore, cycle indices may need to be updated in between calls to circuit methods. There are several “batch” variants of methods that can handle this for you.

__init__(num_qudits, radixes=[])[source]

Build an empty circuit with the specified number of qudits.

By default, all qudits are qubits, but this can be changed with radixes.

Parameters:
  • num_qudits (int) – The number of qudits in this circuit.

  • radixes (Sequence[int]) – A sequence with its length equal to num_qudits. Each element specifies the base of a qudit. Defaults to qubits.

Raises:

ValueError – if num_qudits is nonpositive.

Examples

>>> circ = Circuit(4)  # Creates four-qubit empty circuit.
>>> circ = Circuit(2, [2, 3])  # Creates one qubit and one qutrit.
>>> circ = Circuit(2)
>>> from bqskit.ir.gates import HGate, CXGate, HGate
>>> circ.append_gate(HGate(), 0)
>>> circ.append_gate(CXGate(), (0, 1))
>>> circ.append_gate(HGate(), 1)
>>> circ.get_unitary()
array([[ 0.5+0.j,  0.5+0.j,  0.5+0.j,  0.5+0.j],
       [ 0.5+0.j, -0.5+0.j,  0.5+0.j, -0.5+0.j],
       [ 0.5+0.j,  0.5+0.j, -0.5+0.j, -0.5+0.j],
       [-0.5+0.j,  0.5+0.j,  0.5+0.j, -0.5+0.j]])
>>> circ.get_statevector([1, 0, 0, 0])
array([ 0.5+0.j,  0.5+0.j,  0.5+0.j, -0.5+0.j])

Attributes

active_qudits

The qudits involved in at least one operation.

coupling_graph

The qudit connectivity in the circuit.

depth

The length of the critical path in the circuit.

dim

The matrix dimension for this unitary.

front

The positions of operations with no dependencies.

gate_counts

The count of each type of gate in the circuit.

gate_set

The set of gates in the circuit.

gate_set_no_blocks

The set of gates in the circuit, recurses into circuit gates.

is_empty

If there are no operations in the Circuit.

multi_qudit_depth

The length of the critical path excluding single-qudit gates.

num_cycles

The number of cycles in the circuit.

num_operations

The total number of operations in the circuit.

num_params

The total number of parameters in the circuit.

num_qudits

The number of qudits this unitary can act on.

parallelism

The amount of parallelism in the circuit.

params

The stored parameters for the circuit.

radixes

The number of orthogonal states for each qudit.

rear

The positions of operations with nothing after them.

Methods

append(op)

Append op to the end of the circuit and return its cycle index.

append_circuit(circuit, location[, ...])

Append circuit at the qudit location specified.

append_gate(gate, location[, params])

Append the gate object to the circuit on the qudits in location.

append_qudit([radix])

Append a qudit to the circuit.

batch_pop(points)

Pop all operatons at points at once.

batch_replace(points, ops)

Replace the operations at points with ops.

batch_unfold(points)

Unfold the CircuitGates at points into the circuit.

become(circuit[, deepcopy])

Become a copy of circuit.

check_parameters(params)

Check parameters are valid and match the unitary.

check_region(region[, strict])

Check region to be a valid in the context of this circuit.

check_valid_operation(op)

Check that op can be applied to the circuit.

clear()

Clear the circuit.

compress()

Compress the circuit's cycles.

copy()

Return a deep copy of this circuit.

count(op)

Count the number of times op occurs in the circuit.

downsize_region(region)

Remove all idle qudits-cycles in region while keeping it valid.

extend(ops)

Append all operations in ops to the circuit.

extend_qudits(radixes)

Append many qudits to the circuit.

find_available_cycle(location)

Finds the first available cycle for qudits in location.

first_on(qudit)

Report the point for the first operation on qudit if it exists.

fold(region)

Fold the specified region into a CircuitGate.

freeze_param(param_index)

Freeze a circuit parameter to its current value.

from_file(filename)

Restore a circuit from a file.

from_operation(op)

Construct a circuit from a single operation.

from_unitary(utry)

Construct a circuit from a single unitary.

get_grad([params])

Return the gradient of the circuit.

get_inverse()

Return the circuit's inverse circuit.

get_operation(point)

Retrieve the operation at the point.

get_operations(points)

Retrieve operations from points without throwing IndexError.

get_param(param_index)

Return the parameter at param_index.

get_param_location(param_index)

Converts a param_index to a cycle, qudit, and operation-param index.

get_region(points)

Calculate the minimal region from a sequence of points.

get_slice(points)

Return a copy of a slice of this circuit.

get_statevector(in_state[, params])

Return the result of applying self to in_state

get_unitary([params])

Return the unitary matrix of the circuit.

get_unitary_and_grad([params])

Return the unitary and gradient of the circuit.

insert(cycle_index, op)

Insert op in the circuit at the specified cycle.

insert_circuit(cycle_index, circuit, location)

Insert circuit at the cycle and location specified.

insert_gate(cycle_index, gate, location[, ...])

Insert the gate object in the circuit on the qudits in location.

insert_qudit(qudit_index[, radix])

Insert a qudit into the circuit.

instantiate(target[, method, multistarts, ...])

Instantiate the circuit with respect to a target state or unitary.

is_constant()

Return true if this unitary doesn't take parameters.

is_cycle_in_range(cycle_index)

Return true if cycle is a valid in-range index in the circuit.

is_cycle_unoccupied(cycle_index, location)

Check if a cycle is unoccupied for all qudits in location.

is_differentiable()

Check if all gates are differentiable.

is_parameterized()

Return true if this unitary is parameterized.

is_point_idle(point)

Return true if an operation does not exist at point.

is_point_in_range(point)

Return true if point is a valid in-range index in the circuit.

is_qubit_only()

Return true if this unitary can only act on qubits.

is_qudit_idle(qudit_index)

Return true if the qudit is not involved in any operations.

is_qudit_in_range(qudit_index)

Return true if qudit_index is in-range for the circuit.

is_qudit_only(radix)

Return true if this unitary can only act on radix-qudits.

is_qutrit_only()

Return true if this unitary can only act on qutrits.

is_self_inverse([params])

Checks whether the unitary is its own inverse.

is_valid_region(region[, strict])

Return true if region is valid in the context of this circuit.

last_on(qudit)

Report the point for the last operation on qudit if it exists.

minimize(cost, **kwargs)

Minimize the circuit's cost with respect to some CostFunction.

next(point)

Return the points of operations dependent on the one at point.

normalize_point(point)

Flip negative indices to positive indices.

operations([start, end, qudits_or_region, ...])

Create and return an iterator, for more info see CircuitIterator.

operations_with_cycles([start, end, ...])

Create and return an iterator, for more info see CircuitIterator.

perform(compiler_pass[, data])

Execute the provided compiler_pass on this circuit.

point(op[, start, end])

Return point of the first occurrence of op.

pop([point])

Pop the operation at point, defaults to last operation.

pop_cycle(cycle_index)

Pop a cycle from the circuit and all operations in it.

pop_qudit(qudit_index)

Pop a qudit from the circuit and all gates attached to it.

prev(point)

Return the points of operations the one at point depends on.

remove(op)

Removes the first occurrence of op in the circuit.

remove_all(op)

Removes the all occurrences of op in the circuit.

remove_all_measurements()

Remove all measurement placeholders from the circuit.

renumber_qudits(qudit_permutation)

Permute the qudits in the circuit.

replace(point, op)

Replace the operation at point with op.

replace_gate(point, gate, location[, params])

Replace the operation at 'point' with gate.

replace_with_circuit(point, circuit[, ...])

Replace the operation at 'point' with circuit.

save(filename)

Save the circuit to a file.

set_param(param_index, value)

Set a circuit parameter.

set_params(params)

Set all parameters at once.

straighten(region)

Push gates back so the region has a single starting cycle.

surround(point, num_qudits[, ...])

Retrieve the maximal region in this circuit with point included.

to(type)

Convert circuit to language.

unfold(point)

Unfold the CircuitGate at point into the circuit.

unfold_all()

Unfold all CircuitGates in the circuit.