Operations
MimiqCircuitsBase.Operation
— TypeOperation{N,M,L}
Abstract supertype for all the quantum operations acting on N
qubits and M
classical bits.
Methods
iswrapper
, isunitary
, numbits
, numqubits
, opname
See also
MimiqCircuitsBase.cregsizes
— Methodcregsizes(operation)
cregsizes(operationtype)
Length of the classicalregisters the given operation acts on.
See also
MimiqCircuitsBase.getparam
— Functiongetparam(operation, name)
Value of the corresponding parameter in the given parametric operation.
Examples
getparam(GateRX(π/8), :θ)
See also
MimiqCircuitsBase.getparams
— Functiongetparams(operation)
Value of the parameters in the given parametric operation.
Examples
getparam(GateU(π/8, 3.1, sqrt(2)))
See also
MimiqCircuitsBase.hilbertspacedim
— Functionhilbertspacedim(operation)
hilbertspacedim(operationtype)
hilbertspacedim(N::Integer)
Hilbert space dimension for the given operation. For an operation actiing on N
qubits, it is 2^N
.
Examples
hilbertspacedim(Operation{2, 1})
hilbertspacedim(GateH)
hilbertspacedim(GateH())
hilbertspacedim(GateRX)
hilbertspacedim(GateCX)
hilbertspacedim(4)
See also
MimiqCircuitsBase.iswrapper
— Functioniswrapper(operation)
iswrapper(operationtype)
Checks if a given operation is a wrapper or not.
Examples
iswrapper(Control)
iswrapper(GateX)
iswrapper(GateSX) # SX is defined as Power(1//2, GateX())
iswrapper(GateCX) # CX is defined as Control(1, GateX())
See also
MimiqCircuitsBase.numparams
— Functionnumparams(operation)
numparams(operationtype)
Number of parameters for the given parametric operation. Zero for non parametric operations.
By default it returns the number of fields of the operations.
Examples
julia> numparams(GateH)
0
julia> numparams(GateU)
4
julia> numparams(GateRX)
1
julia> numparams(Measure)
0
See also
MimiqCircuitsBase.parnames
— Functionparnames(operation)
parnames(operationtype)
Name of the parameters allowed for the given operation.
By default it returns the fieldnames of the operation type.
Examples
parnames(GateH)
parnames(GateRX)
parnames(GateCRX)
parnames(Measure)
See also
MimiqCircuitsBase.qregsizes
— Methodqregsizes(operation)
qregsizes(operationtype)
Length of the quantum registers the given operation acts on.
Details
Some operations, such as adders or multipliers, acts on different groups of qubits (quantum registers).
Examples
julia> qregsizes(GateRX(0.1))
(1,)
julia> qregsizes(GateCRX(0.1))
(1, 1)
julia> qregsizes(QFT(4))
(4,)
See also
MimiqCircuitsBase.zregsizes
— Methodzregsizes(operation)
zregsizes(operationtype)
Length of the zregisters the given operation acts on.
MimiqCircuitsBase.GATES
— ConstantGATES
List of gates provided by the library.
Single qubit gates
GateID
, GateX
, GateY
, GateZ
, GateH
, GateS
, GateSDG
, GateT
, GateTDG
, GateSX
, GateSXDG
. GateSY
, GateSYDG
.
Single qubit parametric gates
GateU
, GateP
, GateRX
, GateRY
, GateRZ
, GateR
, GateU1
, GateU2
, GateU3
.
Two qubit gates
GateCX
, GateCY
, GateCZ
, GateCH
, GateSWAP
, GateISWAP
, GateCS
, GateCSDG
, GateCSX
, GateCSXDG
, GateECR
, GateDCX
,
Two qubit parametric gates
GateCP
, GateCU
, GateCRX
, GateCRY
, GateCRZ
, GateRXX
, GateRYY
, GateRZZ
, GateRZX
, GateXXplusYY
, GateXXminusYY
.
Multi qubit Gates
GateCCX
, GateC3X
, GateCCP
, GateCSWAP
.
Generalized gates
These defines an unitary quantum operation on non fixed number of qubits.
See GENERALIZED
for a list of them.
Operations
See OPERATIONS
for a complete list of operations.
Noise channels
These define a non-unitary quantum operation based on the Kraus representation.
See NOISECHANNELS
for a list of them.
MimiqCircuitsBase.GENERALIZED
— ConstantGENERALIZED
Definition of complex unitary quantum opteration on a not fixed number of qubits, or on multiple groups of qubits (registers).
Usually they are initialized with the number of qubits they operate on, or with the size of each group of qubits they act on
MimiqCircuitsBase.NOISECHANNELS
— ConstantNOISECHANNELS
List of noise channels provided by the library.
Not mixed-unitary noise channels
Kraus
, AmplitudeDamping
, GeneralizedAmplitudeDamping
, PhaseAmplitudeDamping
, ThermalNoise
, Reset
,
Mixed-Unitary noise channels
MixedUnitary
, PauliNoise
, PauliX
, PauliY
, PauliZ
, Depolarizing
,
MimiqCircuitsBase.OPERATIONS
— ConstantOPERATIONS
Phases and other unitaries
See GATES
for a complete list unitary gates.
For gate definitions and calls, see GateDecl
and GateCall
Other circuits elements
Modifiers
Control
, Parallel
, Power
, Inverse
Non-unitary operations
Measure
, MeasureX
, MeasureY
, MeasureZ
, MeasureXX
, MeasureYY
, MeasureZZ
MeasureReset
, MeasureResetX
, MeasureResetY
, MeasureResetZ
, Reset
,
Algorithms or complex gate builders
See GENERALIZED
for a complete list of generalized gates or algorithms.
Gates
MimiqCircuitsBase.AbstractGate
— TypeAbstractGate{N} <: AbstractOperator{N}
Supertype for all the N
-qubit unitary gates.
See also hilbertspacedim
, inverse
, isunitary
, matrix
, numqubits
, opname
MimiqCircuitsBase.RescaledGate
— TypeTODO
MimiqCircuitsBase.GateSY
— TypeGateSY()
Single qubit $\sqrt{Y}$ gate.
See also GateSYDG
, GateY
, Power
Matrix representation
\[\operatorname{SY} = \sqrt{\operatorname{Y}} = \frac{1}{2} \begin{pmatrix} 1+i & -1-i \\ 1+i & 1+i \end{pmatrix}\]
Examples
julia> GateSY()
SY
julia> matrix(GateSY())
2×2 Matrix{ComplexF64}:
0.5+0.5im -0.5-0.5im
0.5+0.5im 0.5+0.5im
julia> c = push!(Circuit(), GateSY(), 1)
1-qubit circuit with 1 instructions:
└── SY @ q[1]
julia> push!(c, GateSY, 2)
2-qubit circuit with 2 instructions:
├── SY @ q[1]
└── SY @ q[2]
julia> power(GateSY(), 2)
Y
Decomposition
julia> decompose(GateSY())
1-qubit circuit with 4 instructions:
├── S @ q[1]
├── S @ q[1]
├── H @ q[1]
└── U(0,0,0,π/4) @ q[1]
MimiqCircuitsBase.GateSYDG
— TypeGateSYDG()
Single qubit $\sqrt{Y}^\dagger$ gate (conjugate transpose of the $\sqrt{Y}$ gate)
See also GateSY
, GateY
, Power
, Inverse
Matrix representation
\[\operatorname{SYDG} = \sqrt{\operatorname{Y}}^\dagger = \frac{1}{2} \begin{pmatrix} 1-i & 1-i \\ -1+i & 1-i \end{pmatrix}\]
Examples
julia> GateSYDG()
SY†
julia> matrix(GateSYDG())
2×2 adjoint(::Matrix{ComplexF64}) with eltype ComplexF64:
0.5-0.5im 0.5-0.5im
-0.5+0.5im 0.5-0.5im
julia> c = push!(Circuit(), GateSYDG(), 1)
1-qubit circuit with 1 instructions:
└── SY† @ q[1]
julia> push!(c, GateSYDG, 2)
2-qubit circuit with 2 instructions:
├── SY† @ q[1]
└── SY† @ q[2]
julia> power(GateSYDG(), 2)
(SY†)^2
julia> inverse(GateSYDG())
SY
MimiqCircuitsBase.MeasureXX
— TypeMeasureXX()
The MeasureXX operation measures the joint parity of two qubits in the X-basis, determining whether the qubits are in the same or different states within this basis. The operation begins by applying a controlled-X (CX) gate between the two qubits to entangle them. Following this, a Hadamard (H) gate is applied to the first qubit, rotating it into the X-basis. The second qubit, designated as the target, is then measured to extract the parity information. After the measurement, the Hadamard gate is applied again to the first qubit to reverse the rotation, and a second controlled-X (CX) gate is applied to disentangle the qubits, restoring the system to its original state. Through this sequence, the MeasureXX operation efficiently captures the parity relationship of the qubits in the X-basis.
A result of 0
indicates that the qubits are in the same state, while a result of 1
indicates that they are in different states.
Examples
julia> c = Circuit()
empty circuit
julia> push!(c, MeasureXX(), 1, 2, 1)
2-qubit circuit with 1 instructions:
└── MXX @ q[1:2], c[1]
MimiqCircuitsBase.MeasureYY
— TypeMeasureYY()
The MeasureYY operation measures the joint parity of two qubits in the Y-basis, determining whether they are in the same or different states in this basis. This is achieved by first applying an S gate (a π/2 phase shift) to both qubits, followed by a controlled-X (CX) gate. A Hadamard gate (H) is then applied to the first qubit, and the second qubit is measured. To restore the system, a Z gate is applied to the first qubit, followed by another Hadamard gate, another CX gate, and finally another S gate to both qubits. The measurement result reflects whether the qubits are in the same or different states in the Y-basis.
A result of 0
indicates that the qubits are in the same state, while a result of 1
indicates that they are in different states.
Examples
julia> c = Circuit()
empty circuit
julia> push!(c, MeasureYY(), 1, 2, 1)
2-qubit circuit with 1 instructions:
└── MYY @ q[1:2], c[1]
MimiqCircuitsBase.MeasureZZ
— TypeMeasureZZ()
The MeasureZZ operation measures the joint parity of two qubits in the Z-basis. This is achieved by applying a controlled-X (CX) gate, measuring the target qubit, and then applying another CX gate to undo the entanglement. The measurement result indicates whether the qubits are in the same or different states in the Z-basis.
Examples
julia> c = Circuit()
empty circuit
julia> push!(c, MeasureZZ(), 1, 2, 1)
2-qubit circuit with 1 instructions:
└── MZZ @ q[1:2], c[1]
Wrappers
MimiqCircuitsBase.Control
— TypeControl(numcontrols, gate) <: AbstractGate
Control modifier, similar to OpenQASM 3.0 ctrl @ gate
. It wraps a given gate and adds a number of controls to it.
By default the first numcontrols
qubits are used as controls, and the remaining ones as targets for the wrapped gate.
See also Power
, Inverse
, getoperation
, iswrapper
, numcontrols
, numtargets
.
Examples
julia> Control(1, GateX())
CX
julia> Control(3, GateH())
C₃H
julia> Control(24, GateSWAP())
C₂₄SWAP
Decomposition
The default decomposition of a Control
gate is build by applying recursively Lemma 7.3 of [1]. This requires to decompose multicontrolled-$X$ gates, which is done recursively, according to Lemma 7.2 and 7.3 of [1].
Here we give a simple example of a decomposition of a $C_5T$ gate.
julia> decompose(Control(3,GateT()))
4-qubit circuit with 9 instructions:
├── C(Z^(1//8)) @ q[3], q[4]
├── C₂X @ q[1:2], q[3]
├── C((Z^(1//8))†) @ q[3], q[4]
├── C₂X @ q[1:2], q[3]
├── C(Z^(1//16)) @ q[2], q[4]
├── CX @ q[1], q[2]
├── C((Z^(1//16))†) @ q[2], q[4]
├── CX @ q[1], q[2]
└── C(Z^(1//16)) @ q[1], q[4]
Some decompositions have been overrided with optimized versions, to reduce the number of gates used.
MimiqCircuitsBase.Control
— MethodControl(gate)
Build a controlled gate with 1 control.
MimiqCircuitsBase.control
— Functioncontrol([numcontrols], gate)
Build a multicontrolled gate.
The number of controls can be omitted to be lazily evaluated later.
Examples
Standard examples, with all the arguments spefcified.
julia> control(1, GateX())
CX
julia> control(2, GateX())
C₂X
julia> control(3, GateCH())
C₄H
MimiqCircuitsBase.numcontrols
— Functionnumcontrols(control)
Number of controls of a given multicontrolled gate.
See also
MimiqCircuitsBase.numtargets
— Functionnumtargets(control)
Get the number of targets of a given multicontrolled gate.
Examples
numcontro
See also
MimiqCircuitsBase.Inverse
— TypeInverse(operation)
Inverse of the wrapped quantum operation.
The inversion is not performed right away, but only when the circuit is cached or executed.
Some simplifications are already carried out at construction, for example, Inverse(Inverse(op))
is simplified as Inverse(op)
.
Users should not use directly Inverse
but the inverse
method, which performs already all the simplifications.
See also inverse
, iswrapper
, Control
, Power
.
Examples
julia> Inverse(GateX())
X†
julia> Inverse(GateH())
H†
julia> Inverse(GateSX())
SX†
julia> Inverse(GateCSX())
CSX†
julia> Inverse(QFT(4))
QFT†
Decomposition
Decomposition of the inverse is carring out by inverting the decomposition of the wrapped operation.
julia> decompose(Inverse(GateCSX()))
2-qubit circuit with 3 instructions:
├── H @ q[2]
├── CU1(-1π/2) @ q[1], q[2]
└── H @ q[2]
MimiqCircuitsBase.Power
— TypePower(pow, operation)
Wraps an operation and raises it to the given power.
Some simplifications are already carried out at construction, for example Power(pow2, Power(pow1, op))
is simplified as Power(pow1 * pow2, op)
.
For allowing simplifications, always prefer rational powers, such as 1//2
over floating point ones, such as 0.5
.
Users should not use directly Power
but the power
method, which performs already all the simplifications. Gates should implement the _power
method instead.
See also power
, Inverse
, inverse
.
Example
julia> Power(GateZ(), 1//2)
S
julia> Power(GateZ(), 2)
Z^2
julia> Power(GateCH(), 1//2)
CH^(1//2)
julia> Power(GateCX(), 1//2)
CX^(1//2)
Decomposition
In the general case, if a decomposition is not known for a given operation and power, the Power
operation is not decomposed.
If the exponent is an integer, then the gate is decomposed by repeating it.
julia> decompose(Power(GateH(), 2))
1-qubit circuit with 2 instructions:
├── H @ q[1]
└── H @ q[1]
julia> decompose(Power(GateH(), 1//2))
1-qubit circuit with 1 instructions:
└── U(1.0471975511966005,-0.9553166181245096,2.1862760354652835,0.16991845472706107) @ q[1]
julia> decompose(Power(GateX(), 1//2)) # same as decomposing GateSX
1-qubit circuit with 4 instructions:
├── S† @ q[1]
├── H @ q[1]
├── S† @ q[1]
└── U(0,0,0,π/4) @ q[1]
MimiqCircuitsBase.Parallel
— TypeParallel(repeats, operation)
Wrapper that applies the same operation on multiple qubits.
If the operation is a N
-qubit operation, then the resulting operation is applied over N * repeats
qubits.
Examples
julia> Parallel(5, GateX())
⨷ ⁵ X
julia> Parallel(3, GateRX(λ))
⨷ ³ RX(λ)
julia> Parallel(2, Parallel(3, GateX()))
⨷ ² (⨷ ³ X)
Decomposition
A parallel is decomposed into a sequence of operation, one for each group of qubits.
julia> decompose(Parallel(2, GateX()))
2-qubit circuit with 2 instructions:
├── X @ q[1]
└── X @ q[2]
julia> decompose(Parallel(3, GateSWAP()))
6-qubit circuit with 3 instructions:
├── SWAP @ q[1:2]
├── SWAP @ q[3:4]
└── SWAP @ q[5:6]
MimiqCircuitsBase.numrepeats
— Functionnumrepeats(paralleloperation)
Get the number of repetitions of a parallel operation.
See also Parallel
.
Examples
julia> numrepeats(Parallel(5, GateX()))
5
julia> numrepeats(Parallel(3, GateSWAP()))
3
MimiqCircuitsBase.parallel
— Functionparallel(repeats, operation)
Build a parallel operation.
The resulting operation is applied over N * repeats
qubits.
MimiqCircuitsBase.IfStatement
— TypeIfStatement(op, bs::BitString)
Applies the provided operation only if the classical register matches the specified BitString
.
IfStatement
enables conditional operations in a quantum circuit based on the state of a classical register. If the classical register's state matches the BitString
, the operation (op
) is applied to the target qubits.
Arguments
op
: The quantum operation to apply, such asGateX()
or another gate.bs
: ABitString
object representing the target state of the classical register that triggersop
.
Examples
Basic Usage
julia> using MimiqCircuitsBase
# Define a condition as a BitString
julia> condition = BitString("01011")
5-bits BitString with integer value 26:
01011
# Apply GateX only if the condition is met
julia> if_statement = IfStatement(GateX(), condition)
IF(c==01011) X
# Add this conditional operation to a circuit
julia> c = Circuit()
julia> push!(c, if_statement, 1, 2, 3, 4, 5, 6)
1-qubit circuit with 1 instructions:
└── IF(c==01011) X @ q[1], c[2:6]
Decompositions
MimiqCircuitsBase.decompose
— Functiondecompose(operation)
decompose(circuit)
Decompose the given operation or circuit into a circuit of more elementary gates. If applied recursively, it will decompose the given object into a circuit of GateCX
and GateU
gates.
See also decompose!
.
MimiqCircuitsBase.decompose!
— Functiondecompose!(circuit, operation[, qtargets, ctargets])
In place version of decompose
.
It decomposes the given object, appending all the resulting operations to the given circuit. The optional qtargets
and ctargets
arguments can be used to map the qubits and classical bits of the decomposed operation to the ones of the target circuit.
Classical operations
MimiqCircuitsBase.Not
— Typestruct Not <: Operation{0,1,0}