Other Operations

Custom gates

MimiqCircuitsBase.GateCustomType
struct GateCustom{N,T} <: AbstractGate{N}

N qubit gate specified by a $2^N \times 2^N$ matrix with elements of type T.

Use this to construct your own gates based on unitary matrices.

Note

Only one and two qubits gates are supported.

MIMIQ uses textbook convention for specifying gates.

One qubit gate matrices are defined in the basis $|0\rangle$, $|1\rangle$ e.g.,

\[\operatorname{Z} = \begin{pmatrix} 1&0\\ 0&-1 \end{pmatrix}\]

Two qubit gate matrices are defined in the basis $|00\rangle$, $|01\rangle$>, $|10\rangle$, $|11\rangle$ where the left-most qubit is the first to appear in the target list e.g.,

\[\operatorname{CNOT} = \begin{pmatrix} 1&0&0&0\\ 0&1&0&0\\ 0&0&0&1\\ 0&0&1&0 \end{pmatrix}\]

julia> CNOT = [1 0 0 0; 0 1 0 0; 0 0 0 1; 0 0 1 0]
4×4 Matrix{Int64}:
 1  0  0  0
 0  1  0  0
 0  0  0  1
 0  0  1  0

julia> # CNOT gate with control on q1 and target on q2

julia> Instruction(GateCustom(CNOT), 1, 2)
GateCustom([1 0 0 0; 0 1 0 0; 0 0 0 1; 0 0 1 0]) @ q1, q2

# Examples

jldoctest julia> g = GateCustom([1 0; 0 1]) Custom([1.0 0.0; 0.0 1.0])

julia> push!(Circuit(), g, 1) 1-qubit circuit with 1 instructions: └── Custom([1.0 0.0; 0.0 1.0]) @ q1 ```

source
MimiqCircuitsBase.OperatorType
Operator(matrix)

N qubit operator specified by an $2^N \times 2^N$ matrix.

Note

Only one and two qubits operators are supported.

This operator doesn't have to be unitary.

See also AbstractOperator, ExpectationValue, and Kraus.

Examples

julia> Operator([1 2; 3 4])
1-qubit Operator:
├── 1.0 2.0
└── 3.0 4.0

julia> Operator([1 0 0 1; 0 0 0 0; 0 0 0 0; 1 0 0 1])
2-qubit Operator:
├── 1.0 0.0 0.0 1.0
├── 0.0 0.0 0.0 0.0
├── 0.0 0.0 0.0 0.0
└── 1.0 0.0 0.0 1.0

Operators can be used for expectation values:

julia> push!(Circuit(), ExpectationValue(Operator([0 1; 0 0])), 1, 1)
1-qubit circuit with 1 instructions:
└── ⟨Operator([0.0 1.0; 0.0 0.0])⟩ @ q[1], z[1]
source
MimiqCircuitsBase.matrixFunction
matrix(operator)

Matrix associated to the given operator.

Note

if the operator is parametric, the matrix elements are wrapped in a Symbolics.Num object. To manipulate expressions use the Symbolics package.

Examples

julia> matrix(GateH())
2×2 Matrix{Float64}:
 0.707107   0.707107
 0.707107  -0.707107

julia> matrix(GateRX(π/2))
2×2 Matrix{ComplexF64}:
 0.707107+0.0im            0.0-0.707107im
      0.0-0.707107im  0.707107+0.0im
source
MimiqCircuitsBase.unwrappedmatrixMethod
unwrappedmatrix(operator)

Returns the matrix associated to the specified quantum operator without the Symbolics.Num wrapper.

Note

If any of the gate's parameters is symbolic, an error is thrown.

See also matrix.

Examples

julia> unwrappedmatrix(GateRX(π/2))
2×2 Matrix{ComplexF64}:
 0.707107+0.0im            0.0-0.707107im
      0.0-0.707107im  0.707107+0.0im

julia> unwrappedmatrix(GateH())
2×2 Matrix{Float64}:
 0.707107   0.707107
 0.707107  -0.707107
source

Gate definitions

MimiqCircuitsBase.GateCallType
GateCall(decl, args...)

Gate corresponding to a call to a GateDecl definition.

It is created by calling a GateDecl with the proper number of arguments.

Examples

julia> @gatedecl ansatz(θ) = begin
           c = Circuit()
           push!(c, GateX(), 1)
           push!(c, GateRX(θ), 2)
           return c
       end
gate ansatz(θ) =
├── X @ q[1]
└── RX(θ) @ q[2]


julia> @variables λ;


julia> ansatz(λ)
ansatz(λ)

See also

GateDecl

source
MimiqCircuitsBase.GateDeclType
GateDecl(name, args, circuit)

Define a new gate of given name, arguments and circuit.

Examples

A simple gate declaration, via the @gatedecl macro:

julia> @gatedecl ansatz(θ)  = begin
           c = Circuit()
           push!(c, GateX(), 1)
           push!(c, GateRX(θ), 2)
           return c
       end
gate ansatz(θ) =
├── X @ q[1]
└── RX(θ) @ q[2]

julia> @variables λ;


julia> decompose(ansatz(λ))
2-qubit circuit with 2 instructions:
├── X @ q[1]
└── RX(λ) @ q[2]

See also

GateCall

source

Non-unitary operations

MimiqCircuitsBase.MeasureResetType
MeasureReset()

This operation measures a qubit q, stores the value in a classical bit c, then applies a X operation to the qubit if the measured value is 1, effectively resetting the qubit to the :math:\\ket{0} state.

See also MeasureResetX, MeasureResetY, IfStatement, GateH.

Examples

julia> MeasureReset()
MR

julia> decompose(MeasureReset())
1-qubit circuit with 2 instructions:
├── M @ q[1], c[1]
└── IF(c==1) X @ q[1], c[1]

julia> c = push!(Circuit(), MeasureReset(), 1, 1)
1-qubit circuit with 1 instructions:
└── MR @ q[1], c[1]

julia> push!(c, MeasureReset(), 3, 4)
3-qubit circuit with 2 instructions:
├── MR @ q[1], c[1]
└── MR @ q[3], c[4]
source
MimiqCircuitsBase.MeasureResetXType
MeasureResetX()

The MeasureResetX operation first applies a Hadamard gate (H) to the qubit, performs a measurement and reset operation similar to the MeasureReset operation, and then applies another Hadamard gate. This sequence effectively measures the qubit in the X-basis and resets it to the |+> state.

See also MeasureReset, MeasureResetY, IfStatement, GateH.

Examples

julia> MeasureResetX()
MRX

julia> decompose(MeasureResetX())
1-qubit circuit with 3 instructions:
├── H @ q[1]
├── MR @ q[1], c[1]
└── H @ q[1]

julia> c = push!(Circuit(), MeasureResetX(), 1, 1)
1-qubit circuit with 1 instructions:
└── MRX @ q[1], c[1]

julia> push!(c, MeasureResetX(), 3, 4)
3-qubit circuit with 2 instructions:
├── MRX @ q[1], c[1]
└── MRX @ q[3], c[4]
source
MimiqCircuitsBase.MeasureResetYType
MeasureResetY()

The MeasureResetY operation applies (HYZ) gate to the qubit, performs a MeasureReset operation, and then applies another HYZ gate. This sequence effectively measures the qubit in the Y-basis.

See aclso MeasureResetX, MeasureReset, IfStatement, GateHYZ.

Examples

julia> MeasureResetY()
MRY

julia> decompose(MeasureResetY())
1-qubit circuit with 3 instructions:
├── HYZ @ q[1]
├── MR @ q[1], c[1]
└── HYZ @ q[1]


julia> c = push!(Circuit(), MeasureResetY(), 1, 1)
1-qubit circuit with 1 instructions:
└── MRY @ q[1], c[1]

julia> push!(c, MeasureResetY(), 3, 4)
3-qubit circuit with 2 instructions:
├── MRY @ q[1], c[1]
└── MRY @ q[3], c[4]
source
MimiqCircuitsBase.ResetType
Reset()

Quantum operation that resets the status of one qubit to the $\ket{0}$ state.

See also Operation, Measure.

Examples

julia> Reset()
Reset

julia> c = push!(Circuit(), Reset, 1)
1-qubit circuit with 1 instructions:
└── Reset @ q[1]

julia> push!(c, Reset(), 3)
3-qubit circuit with 2 instructions:
├── Reset @ q[1]
└── Reset @ q[3]
source
MimiqCircuitsBase.ResetXType
ResetX

Quantum operation that resets the status of one qubit to $\ket{+} = (\ket{0}+\ket{1})/\sqrt{2}$, the +1 eigenstate of the X gate.

This operation is equivalent to the sequence Reset, GateH.

See also Reset, Operation, Measure.

Examples

julia> ResetX()
ResetX

julia> decompose(ResetX())
1-qubit circuit with 3 instructions:
├── H @ q[1]
├── Reset @ q[1]
└── H @ q[1]

julia> c = push!(Circuit(), ResetX, 1)
1-qubit circuit with 1 instructions:
└── ResetX @ q[1]

julia> push!(c, ResetX(), 3)
3-qubit circuit with 2 instructions:
├── ResetX @ q[1]
└── ResetX @ q[3]
source
MimiqCircuitsBase.ResetYType
ResetY

Quantum operation that resets the status of one qubit to $\ket{y+} = (\ket{0}+i\ket{1})/\sqrt{2}$, the +1 eigenstate of the Y gate.

This operation is equivalent to the sequence Reset, GateH, GateS.

See also Reset, Operation, Measure.

Examples

julia> ResetY()
ResetY

julia> decompose(ResetY())
1-qubit circuit with 3 instructions:
├── HYZ @ q[1]
├── Reset @ q[1]
└── HYZ @ q[1]

julia> c = push!(Circuit(), ResetY, 1)
1-qubit circuit with 1 instructions:
└── ResetY @ q[1]

julia> push!(c, ResetY(), 3)
3-qubit circuit with 2 instructions:
├── ResetY @ q[1]
└── ResetY @ q[3]
source

No-ops

MimiqCircuitsBase.BarrierType
Barrier(numqubits)

No-op operation that does not affect the quantum state or the execution of a circuit, but prevents compression or optimization across it.

Examples

julia> Barrier(1)
Barrier

julia> Barrier(2)
Barrier

julia> c = push!(Circuit(), Barrier(1), 1)
1-qubit circuit with 1 instructions:
└── Barrier @ q[1]

julia> push!(c, Barrier(1), 1:3)
3-qubit circuit with 4 instructions:
├── Barrier @ q[1]
├── Barrier @ q[1]
├── Barrier @ q[2]
└── Barrier @ q[3]

julia> push!(c, Barrier(3), 1,2,3)
3-qubit circuit with 5 instructions:
├── Barrier @ q[1]
├── Barrier @ q[1]
├── Barrier @ q[2]
├── Barrier @ q[3]
└── Barrier @ q[1:3]
source

Others

MimiqCircuitsBase.AbstractAnnotationType
AbstractAnnotation{N, M, L} <: Operation{N, M, L}

An abstract type representing a general annotation operation for use in quantum circuits. This type supports annotations that are not strictly quantum operations but may carry metadata or extra circuit information.

source
MimiqCircuitsBase.DetectorType
Detector{N}(N::Integer, notes::AbstractVector)

An annotation class representing a detector in a quantum circuit. The Detector checks the parity of measurement results over N classical bits, where the parity should be deterministic under noiseless execution.

Detector monitors the results of a specific set of measurements and verifies that their combined parity (even or odd) remains consistent. This consistency is expected under ideal, noiseless conditions. If noise or errors disrupt the circuit, the Detector can identify this because the parity will change unexpectedly, signaling a potential error in the measurement outcomes. This helps in error detection by revealing inconsistencies that arise due to unintended disturbances.

See Also QubitCoordinates, ShiftCoordinates, or Tick

Arguments

  • N::Integer: The number of classical bits.
  • notes::AbstractVector: A vector of floating-point values that contain measurement notes.

Throws

  • ArgumentError: If N is zero or negative.

Examples

julia> detector = Detector(2, [1.0, 0.5])
Detector(1.0, 0.5)

julia> c = Circuit()
empty circuit

julia> push!(c,detector,1,2)
0-qubit circuit with 1 instructions:
└── Detector(1.0,0.5) @ c[1:2]
source
MimiqCircuitsBase.ObservableIncludeType
ObservableInclude{N}(N::Integer, notes::AbstractVector)

An annotation class for adding measurement records to a specified logical observable within a quantum circuit. Observables are sets of measurements expected to produce a deterministic result, used to track specific logical qubit states across operations.

The ObservableInclude class tags a group of measurement records as a logical observable, representing a consistent, predictable result under noiseless conditions. This grouping allows for tracking the state of logical qubits across circuit operations, which is crucial for error correction. Logical observables monitor encoded qubit states by combining multiple measurements, providing robustness against noise and helping to identify any deviations that indicate potential errors.

See Also QubitCoordinates, Detector, or Tick

Arguments

  • N::Integer: The number of classical bits observed in this logical observable.
  • notes::AbstractVector: A vector of integers identifying measurement records.

Throws

  • ArgumentError: If N is zero or negative.

Examples

julia> obs_include = ObservableInclude(2, [1, 2])
ObservableInclude(1, 2)

julia> c = Circuit()
empty circuit

julia> push!(c, obs_include,1,2)
0-qubit circuit with 1 instructions:
└── ObservableInclude(1,2) @ c[1:2]
source
MimiqCircuitsBase.QubitCoordinatesType
QubitCoordinates(coordinates...)

An annotation class used to specify the spatial location of a qubit in a quantum circuit. Coordinates do not affect simulation results but are useful for visualizing and organizing qubit layouts within the circuit.

See Also Detector, ShiftCoordinates, or Tick

Arguments

  • coordinates: A variable number of floating-point values representing the coordinates of the qubit.

Examples

julia> coords = QubitCoordinates(0.0, 1.0)
QubitCoordinates(0.0, 1.0)

julia> c = Circuit()
empty circuit

julia> push!(c,coords,1)
1-qubit circuit with 1 instructions:
└── QubitCoordinates(0.0,1.0) @ q[1]
source
MimiqCircuitsBase.ShiftCoordinatesType
ShiftCoordinates(coordinates...)

An annotation class used to apply a shift to the spatial coordinates of subsequent qubit or detector annotations in a quantum circuit. ShiftCoordinates accumulates offsets that adjust the position of related circuit components, aiding in visualization without affecting the simulation.

See Also QubitCoordinates, ShiftCoordinates, or Tick

Arguments

  • coordinates: A variable number of floating-point values representing the shift offsets for each coordinate.

Examples

julia> shift = ShiftCoordinates(1.0, 2.0)
ShiftCoordinates(1.0, 2.0)

julia> c = Circuit()
empty circuit

julia> push!(c, shift)
0-qubit circuit with 1 instructions:
└── ShiftCoordinates(1.0,2.0)
source
MimiqCircuitsBase.TickType
Tick()

An annotation class representing a timing marker or layer boundary in a quantum circuit. Tick does not affect simulation but provides structure by separating operations into distinct time steps, which is useful for visualization and analysis.

See Also QubitCoordinates, ShiftCoordinates, or Detector

Examples

julia> tick = Tick()
Tick()

julia> c = Circuit()
empty circuit

julia> push!(c, tick)
0-qubit circuit with 1 instructions:
└── Tick()
source