Operations

MimiqCircuitsBase.hilbertspacedim — Function
hilbertspacedim(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

numqubits, numbits, Operation, AbstractGate

source
MimiqCircuitsBase.iswrapper — Function
iswrapper(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

isunitary, getoperation

source
MimiqCircuitsBase.numparams — Function
numparams(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

parnames, getparam

source
MimiqCircuitsBase.parnames — Function
parnames(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

numparams, getparam

source
MimiqCircuitsBase.qregsizes — Method
qregsizes(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

cregsizes, numqubits, numbits

source
MimiqCircuitsBase.GATES — Constant
GATES

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.

source
MimiqCircuitsBase.OPERATIONS — Constant
OPERATIONS

Phases and other unitaries

See GATES for a complete list unitary gates.

GateCustom, GateCustomDiagonal

For gate definitions and calls, see GateDecl and GateCall

Other circuits elements

Barrier, IfStatement

Modifiers

Control, Parallel, Power, Inverse

Non-unitary operations

Measure, MeasureX, MeasureY, MeasureZ, MeasureXX, MeasureYY, MeasureZZ, MeasurePauli, MeasureReset, MeasureResetX, MeasureResetY, MeasureResetZ, Reset, PrepareStateT

Classical bits (c-register) and complex variables (z-register) operations

Amplitude, Not, ExpectationValue, Multiply, Add, Pow

Entanglement and entropies

SchmidtRank, BondDim, VonNeumannEntropy

Algorithms or complex gate builders

See GENERALIZED for a complete list of generalized gates or algorithms.

source
MimiqCircuitsBase.show_mimiq_hierarchy — Function
show_mimiq_hierarchy()
show_mimiq_hierarchy([type])
show_mimiq_hierarchy([type, [module]])

Show an hierarchy of the MIMIQ type and its subtypes.

Note

Restrictted to type <: Operation types

julia> show_mimiq_hierarchy()
└── Operation
    ├── AbstractAnnotation
    │   ├── Detector
    │   ├── Lost
    │   ├── ObservableInclude
    │   ├── QubitCoordinates
    │   ├── Reloaded
    │   ├── ShiftCoordinates
    │   └── Tick
    ├── AbstractClassical
    │   ├── And
    │   ├── Not
    │   ├── Or
    │   ├── ParityCheck
    │   ├── SetBit0
    │   ├── SetBit1
    │   └── Xor
    ├── AbstractKrausChannel
    │   ├── AmplitudeDamping
    │   ├── Depolarizing
    │   ├── Depolarizing1
    │   ├── Depolarizing2
    │   ├── GeneralizedAmplitudeDamping
    │   ├── Kraus
    │   ├── MixedUnitary
    │   ├── PauliNoise
    │   ├── PauliX
    │   ├── PauliY
    │   ├── PauliZ
    │   ├── PhaseAmplitudeDamping
    │   ├── PrepareStateT
    │   ├── ProjectiveNoiseX
    │   ├── ProjectiveNoiseY
    │   ├── ProjectiveNoiseZ
    │   ├── Reset
    │   ├── ResetX
    │   ├── ResetY
    │   ├── ResetZ
    │   └── ThermalNoise
    ├── AbstractMeasurement
    │   ├── Measure
    │   ├── MeasurePauli
    │   ├── MeasureReset
    │   ├── MeasureResetX
    │   ├── MeasureResetY
    │   ├── MeasureResetZ
    │   ├── MeasureX
    │   ├── MeasureXX
    │   ├── MeasureY
    │   ├── MeasureYY
    │   ├── MeasureZ
    │   └── MeasureZZ
    ├── AbstractOperator
    │   ├── AbstractGate
    │   │   ├── Control
    │   │   │   ├── GateC3X
    │   │   │   ├── GateCCP
    │   │   │   ├── GateCCX
    │   │   │   ├── GateCH
    │   │   │   ├── GateCP
    │   │   │   ├── GateCRX
    │   │   │   ├── GateCRY
    │   │   │   ├── GateCRZ
    │   │   │   ├── GateCS
    │   │   │   ├── GateCSDG
    │   │   │   ├── GateCSWAP
    │   │   │   ├── GateCSX
    │   │   │   ├── GateCSXDG
    │   │   │   ├── GateCU
    │   │   │   ├── GateCX
    │   │   │   ├── GateCY
    │   │   │   └── GateCZ
    │   │   ├── Delay
    │   │   ├── Diffusion
    │   │   ├── GateCall
    │   │   ├── GateCustom
    │   │   ├── GateCustomDiagonal
    │   │   ├── GateDCX
    │   │   ├── GateECR
    │   │   ├── GateH
    │   │   ├── GateHXY
    │   │   ├── GateHXZ
    │   │   ├── GateHYZ
    │   │   ├── GateID
    │   │   ├── GateISWAP
    │   │   ├── GateP
    │   │   ├── GateR
    │   │   ├── GateRNZ
    │   │   ├── GateRX
    │   │   ├── GateRXX
    │   │   ├── GateRY
    │   │   ├── GateRYY
    │   │   ├── GateRZ
    │   │   ├── GateRZX
    │   │   ├── GateRZZ
    │   │   ├── GateSWAP
    │   │   ├── GateU
    │   │   ├── GateU1
    │   │   ├── GateU2
    │   │   ├── GateU3
    │   │   ├── GateX
    │   │   ├── GateXXminusYY
    │   │   ├── GateXXplusYY
    │   │   ├── GateY
    │   │   ├── GateZ
    │   │   ├── Inverse
    │   │   │   ├── GateISWAPDG
    │   │   │   ├── GateSDG
    │   │   │   ├── GateSXDG
    │   │   │   ├── GateSYDG
    │   │   │   └── GateTDG
    │   │   ├── Parallel
    │   │   ├── PauliString
    │   │   ├── PhaseGradient
    │   │   ├── PolynomialOracle
    │   │   ├── Power
    │   │   │   ├── GateS
    │   │   │   ├── GateSX
    │   │   │   ├── GateSY
    │   │   │   └── GateT
    │   │   ├── QFT
    │   │   └── RPauli
    │   ├── DiagonalOp
    │   ├── LossyOperator
    │   ├── Operator
    │   ├── Projector0
    │   ├── Projector00
    │   ├── Projector01
    │   ├── Projector1
    │   ├── Projector10
    │   ├── Projector11
    │   ├── ProjectorX0
    │   ├── ProjectorX1
    │   ├── ProjectorY0
    │   ├── ProjectorY1
    │   ├── ProjectorZ0
    │   ├── ProjectorZ1
    │   ├── RescaledGate
    │   ├── SigmaMinus
    │   └── SigmaPlus
    ├── Add
    ├── Amplitude
    ├── Barrier
    ├── Block
    ├── BondDim
    ├── Check
    ├── ExpectationValue
    ├── IfStatement
    ├── Loss
    ├── MeasureCheck
    ├── Multiply
    ├── Pow
    ├── ReadoutErr
    ├── Reload
    ├── Repeat
    ├── SchmidtRank
    ├── VonNeumannEntropy
    └── WhileStatement
source

Gates

MimiqCircuitsBase.RescaledGate — Type
RescaledGate(gate, m)

The operator $m \cdot U$: a gate $U$ whose matrix is multiplied by the scalar m.

The result is in general not unitary, so it is an operator rather than a gate. It is used to describe the terms of a mixed unitary channel, where each unitary $U_k$ is applied with probability $p_k$ and enters as the Kraus operator $\sqrt{p_k} U_k$.

m is a real number between 0 and 1, or a symbolic expression. getscale returns it and getoperation returns the gate.

Throws ArgumentError if m is numeric and outside $[0, 1]$.

Examples

julia> op = RescaledGate(GateX(), 0.5)
0.5 * X

julia> matrix(op)
2×2 Matrix{Float64}:
 0.0  0.5
 0.5  0.0

julia> getscale(op), getoperation(op)
(0.5, GateX())

julia> rescale(GateH(), 0.25)
0.25 * H

See also MixedUnitary, rescale.

source
MimiqCircuitsBase.rescale! — Function
rescale!(op, scale)

Multiply the operator op by scale in place and return it.

Only Operator and LossyOperator, which store their matrix, can be rescaled in place. Every other operation is an immutable value and throws an ArgumentError; use rescale, which returns a new operation.

Examples

julia> op = Operator([1 0; 0 1]);

julia> rescale!(op, 2) === op
true

julia> matrix(op)
2×2 Matrix{ComplexF64}:
 2.0+0.0im  0.0+0.0im
 0.0+0.0im  2.0+0.0im

julia> rescale!(Projector0(), 2)
ERROR: ArgumentError: Cannot rescale P₀ in place. Use `rescale` instead.
[...]
source
MimiqCircuitsBase.GateSY — Type
GateSY()

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 instruction:
└── 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:
├── U(0,0,π/2) @ q[1]
├── U(0,0,π/2) @ q[1]
├── U(π/2,0,π) @ q[1]
└── U(0,0,0,π/4) @ q[1]
source
MimiqCircuitsBase.GateSYDG — Type
GateSYDG()

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 instruction:
└── 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
source
MimiqCircuitsBase.MeasureXX — Type
MeasureXX()

The MeasureXX operation measures the joint parity of two qubits in the X-basis, that is the two-qubit Pauli operator $X \otimes X$. Its decomposition applies a controlled-X (CX) gate from the first qubit to the second and a Hadamard (H) gate on the first qubit. Together they map $X \otimes X$ to $Z$ on the first qubit, which is then measured. The H and CX gates are applied again afterwards to undo the basis change, so the qubits are left in the post-measurement state of the $X \otimes X$ measurement.

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.

See Also MeasureYY, MeasureZZ

Examples

julia> c = Circuit()
empty circuit

julia> push!(c, MeasureXX(), 1, 2, 1)
2-qubit, 1-bit circuit with 1 instruction:
└── MXX @ q[1:2], c[1]
source
MimiqCircuitsBase.MeasureYY — Type
MeasureYY()

The MeasureYY operation measures the joint parity of two qubits in the Y-basis, that is the two-qubit Pauli operator $Y \otimes Y$. Its decomposition applies an S gate to both qubits, a controlled-X (CX) gate from the first qubit to the second and a Hadamard (H) gate on the first qubit. Together they map $Y \otimes Y$ to $Z$ on the first qubit, which is then measured. The H and CX gates and an S† gate on both qubits are applied afterwards to undo the basis change, so the qubits are left in the post-measurement state of the $Y \otimes Y$ measurement.

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.

See Also MeasureXX, MeasureZZ

Examples

julia> c = Circuit()
empty circuit

julia> push!(c, MeasureYY(), 1, 2, 1)
2-qubit, 1-bit circuit with 1 instruction:
└── MYY @ q[1:2], c[1]
source
MimiqCircuitsBase.MeasureZZ — Type
MeasureZZ()

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.

See Also MeasureYY, MeasureXX

Examples

julia> c = Circuit()
empty circuit

julia> push!(c, MeasureZZ(), 1, 2, 1)
2-qubit, 1-bit circuit with 1 instruction:
└── MZZ @ q[1:2], c[1]
source
MimiqCircuitsBase.MeasurePauli — Type
MeasurePauli(pauli)

Pauli product measurement: projective measurement of the $N$-qubit observable $P = P_1 \otimes P_2 \otimes \dots \otimes P_N$, with each $P_i \in \{I, X, Y, Z\}$.

The instruction targets $N$ qubits and one classical bit. The state is projected onto the $+1$ or $-1$ eigenspace of $P$ and the bit records the outcome: 0 for $+1$, 1 for $-1$. Qubits marked I are targets of the instruction but are not measured.

To measure $-P$, measure $P$ and flip the bit with Not.

Arguments

Throws an ArgumentError if pauli is the identity, since there is nothing to measure.

See also PauliString, RPauli, MeasureZZ, MeasureXX, MeasureYY, pauli_based_computation.

Examples

Measure $X_1 Z_3$ on qubits 1 to 3 and store the outcome in bit 1. Qubit 2 is a target, but is left untouched:

julia> c = push!(Circuit(), MeasurePauli("XIZ"), 1, 2, 3, 1)
3-qubit, 1-bit circuit with 1 instruction:
└── MP(XIZ) @ q[1:3], c[1]

Decomposition

Each measured qubit is rotated to the Z basis (H for X, SDG then H for Y), CX gates collect the parity of the measured qubits on the last one, that qubit is measured, and the CX gates and rotations are undone:

julia> decompose_step(MeasurePauli("XZ"))
2-qubit, 1-bit circuit with 5 instructions:
├── H @ q[1]
├── CX @ q[1], q[2]
├── M @ q[2], c[1]
├── CX @ q[1], q[2]
└── H @ q[1]

Only H, S, SDG, CX and Measure appear, so QASMBasis decomposes it. StimBasis keeps it, as Stim measures Pauli products natively (MPP), and so does CliffordTBasis.

source

Wrappers

MimiqCircuitsBase.Control — Type
Control(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.

Note

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 57 instructions:
├── U(0,0,π/16) @ q[3]
├── CX @ q[3], q[4]
├── U(0,0,(-1//16)*π) @ q[4]
├── CX @ q[3], q[4]
├── U(0,0,π/16) @ q[4]
├── U(π/2,0,π) @ q[3]
├── CX @ q[2], q[3]
├── U(0,0,-1π/4) @ q[3]
├── CX @ q[1], q[3]
⋮   ⋮
├── CX @ q[2], q[4]
├── U(0,0,π/32) @ q[4]
├── CX @ q[2], q[4]
├── U(0,0,(-1//32)*π) @ q[4]
├── CX @ q[1], q[2]
├── U(0,0,π/32) @ q[1]
├── CX @ q[1], q[4]
├── U(0,0,(-1//32)*π) @ q[4]
├── CX @ q[1], q[4]
└── U(0,0,π/32) @ q[4]
Detail

Some decompositions have been overrided with optimized versions, to reduce the number of gates used.

source
MimiqCircuitsBase.control — Function
control([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
source
MimiqCircuitsBase.Inverse — Type
Inverse(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).

Warn

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 7 instructions:
├── U(π/2,0,π) @ q[2]
├── U(0,0,-1π/4) @ q[1]
├── CX @ q[1], q[2]
├── U(0,0,π/4) @ q[2]
├── CX @ q[1], q[2]
├── U(0,0,-1π/4) @ q[2]
└── U(π/2,0,π) @ q[2]
source
MimiqCircuitsBase.Power — Type
Power(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).

Note

A floating point exponent that is exactly a fraction with denominator at most 1000 is stored as that fraction, so Power(GateX(), 0.5) is GateSX(). Other floats, such as sqrt(2), are kept as they are.

Warn

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:
├── U(π/2,0,π) @ q[1]
└── U(π/2,0,π) @ q[1]

julia> decompose(Power(GateH(), 1//2))
1-qubit circuit with 1 instruction:
└── 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:
├── U(0,0,-1π/2) @ q[1]
├── U(π/2,0,π) @ q[1]
├── U(0,0,-1π/2) @ q[1]
└── U(0,0,0,π/4) @ q[1]
source
MimiqCircuitsBase.Parallel — Type
Parallel(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:
├── U(π,0,π) @ q[1]
└── U(π,0,π) @ q[2]

julia> decompose(Parallel(3, GateSWAP()))
6-qubit circuit with 9 instructions:
├── CX @ q[1], q[2]
├── CX @ q[2], q[1]
├── CX @ q[1], q[2]
├── CX @ q[3], q[4]
├── CX @ q[4], q[3]
├── CX @ q[3], q[4]
├── CX @ q[5], q[6]
├── CX @ q[6], q[5]
└── CX @ q[5], q[6]
source
MimiqCircuitsBase.numrepeats — Function
numrepeats(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
source
MimiqCircuitsBase.IfStatement — Type
IfStatement(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 as GateX() or another operation.
  • bs: A BitString object representing the target state of the classical register that triggers op.

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()
empty circuit

julia> push!(c, if_statement, 1, 2, 3, 4, 5, 6)
1-qubit, 6-bit circuit with 1 instructions:
└── IF(c==01011) X @ q[1], condition[2:6]

julia> push!(c, IfStatement(Measure(),BitString("010")),1,1,3,4,5)
1-qubit, 6-bit circuit with 2 instructions:
├── IF(c==01011) X @ q[1], condition[2:6]
└── IF(c==010) M @ q[1], c[1], condition[3:5]

julia> push!(c,IfStatement(Amplitude(BitString("01")),BitString("01")),1,2,1)
1-qubit, 6-bit, 1-vars circuit with 3 instructions:
├── IF(c==01011) X @ q[1], condition[2:6]
├── IF(c==010) M @ q[1], c[1], condition[3:5]
└── IF(c==01) Amplitude(bs"01") @ condition[1:2], z[1]
source
MimiqCircuitsBase.WhileStatement — Type
WhileStatement(op, bs::BitString)

Repeatedly applies the provided operation while the classical register matches the specified BitString.

WhileStatement is the loop counterpart of IfStatement. The body operation op is executed once for every iteration in which the classical register's state equals the BitString. For the loop to terminate, op must mutate at least one of the bits used in the condition (see allow_bit_aliasing — WhileStatement allows body bits to alias condition bits, which is the only way to make progress).

There is no built-in iteration cap: a non-terminating circuit is the user's responsibility, mirroring how every classical language treats while.

Arguments

  • op: The operation to apply each iteration.
  • bs: A BitString representing the condition. The loop runs as long as the selected condition bits match this pattern.

Examples

julia> using MimiqCircuitsBase

# Decrement c[1] until it reaches zero (assuming c[1] starts at 1)
julia> while_statement = WhileStatement(Not(), BitString("1"))
WHILE(c==1) X̲

julia> c = Circuit()
empty circuit

julia> push!(c, while_statement, 1, 1)
1-bit circuit with 1 instruction:
└── WHILE(c==1) X̲ @ c[1], condition[1]

See also IfStatement.

source
MimiqCircuitsBase.Repeat — Type
Repeat(repeats, operation)

Wrapper that applies the same operation multiple times, on the same qubits, bits, and variables.

Examples

julia> Repeat(5, GateX())
∏⁵ X

julia> Repeat(3, GateRX(λ))
∏³ RX(λ)

julia> Repeat(2, Repeat(3, GateX()))
∏² (∏³ X) 

Decomposition

A repeated operation is decomposed by repeating the same operation multiple times

julia> decompose(Repeat(2, GateX()))
1-qubit circuit with 2 instructions:
├── U(π,0,π) @ q[1]
└── U(π,0,π) @ q[1]

julia> decompose(Repeat(3, GateSWAP()))
2-qubit circuit with 9 instructions:
├── CX @ q[1], q[2]
├── CX @ q[2], q[1]
├── CX @ q[1], q[2]
├── CX @ q[1], q[2]
├── CX @ q[2], q[1]
├── CX @ q[1], q[2]
├── CX @ q[1], q[2]
├── CX @ q[2], q[1]
└── CX @ q[1], q[2]

Using repeat

The repeat function is a shorthand for creating a Repeat operation. The main difference between using repeat and Repeat is that the former tries to infer any simplification that can be done on the operation before creating a Repeat operation.

Warn

repeat doesn't always return a Repeat operation. For example, it can return a Power operation.

source

Classical operations

MimiqCircuitsBase.Not — Type
struct Not <: AbstractClassical{1}

Classical operation that flips a classical bit: 0 → 1 and 1 → 0.

Acts only on classical registers and performs a deterministic logical inversion.

Examples

julia> Not()
~

julia> push!(Circuit(), Not(),1)
1-bit circuit with 1 instruction:
└── c[1] = ~c[1]
source
MimiqCircuitsBase.Xor — Type
struct Xor{N} <: AbstractClassical{N}

Computes the bitwise XOR of N-1 classical bits and stores the result in the first given bit.

Examples

julia> Xor()
c[?1] = c[?2] ⊻ c[?3]

julia> push!(Circuit(), Xor(),1, 3, 4)
4-bit circuit with 1 instruction:
└── c[1] = c[3] ⊻ c[4]

julia> push!(Circuit(), Xor(5), 1, 3, 5, 8, 13)
13-bit circuit with 1 instruction:
└── c[1] = c[3] ⊻ c[5] ⊻ c[8] ⊻ c[13]

julia> push!(Circuit(), Xor(8), 1, 2, 3, 4, 5, 6, 7, 8)
8-bit circuit with 1 instruction:
└── c[1] = ⊻ @ c[2, 3, 4, 5, 6, 7, 8]
source
MimiqCircuitsBase.Or — Type
struct Or{N} <: AbstractClassical{N}

Computes the bitwise OR of N-1 classical bits and stores the result in the first given bit.

Examples

julia> Or()
c[?1] = c[?2] | c[?3]

julia> push!(Circuit(), Or(),1, 3, 4)
4-bit circuit with 1 instruction:
└── c[1] = c[3] | c[4]

julia> push!(Circuit(), Or(5), 1, 3, 5, 8, 13)
13-bit circuit with 1 instruction:
└── c[1] = c[3] | c[5] | c[8] | c[13]

julia> push!(Circuit(), Or(8), 1, 2, 3, 4, 5, 6, 7, 8)
8-bit circuit with 1 instruction:
└── c[1] = | @ c[2, 3, 4, 5, 6, 7, 8]
source
MimiqCircuitsBase.And — Type
struct And{N} <: AbstractClassical{N}

Computes the bitwise AND of N-1 classical bits and stores the result in the first given bit.

Examples

julia> And()
c[?1] = c[?2] & c[?3]

julia> push!(Circuit(), And(),1, 3, 4)
4-bit circuit with 1 instruction:
└── c[1] = c[3] & c[4]

julia> push!(Circuit(), And(5), 1, 3, 5, 8, 13)
13-bit circuit with 1 instruction:
└── c[1] = c[3] & c[5] & c[8] & c[13]

julia> push!(Circuit(), And(8), 1, 2, 3, 4, 5, 6, 7, 8)
8-bit circuit with 1 instruction:
└── c[1] = & @ c[2, 3, 4, 5, 6, 7, 8]
source
MimiqCircuitsBase.SetBit0 — Type
struct SetBit0 <: AbstractClassical{1}

Classical operation that sets a classical bit to 0. 0 → 0 and 1 → 0.

Examples

julia> SetBit0()
Set0

julia> push!(Circuit(), SetBit0(),1)
1-bit circuit with 1 instruction:
└── c[1] = 0
source
MimiqCircuitsBase.SetBit1 — Type
struct SetBit1 <: AbstractClassical{1}

Classical operation that sets a classical bit to 1. 0 → 1 and 1 → 1.

Examples

julia> SetBit1()
Set1

julia> push!(Circuit(), SetBit1(),1)
1-bit circuit with 1 instruction:
└── c[1] = 1
source
MimiqCircuitsBase.ParityCheck — Type
ParityCheck(N=3)

Deprecated alias of Xor.

ParityCheck(N) returns Xor(N), which computes the same parity of N-1 classical bits into the first bit, and emits a deprecation warning. No operation is ever of type ParityCheck.

Examples

julia> ParityCheck(5)
c[?1] = c[?2] ⊻ c[?3] ⊻ c[?4] ⊻ c[?5]
source