Private types and functions

MimiqCircuits.checkvalidinputsMethod
checkvalidinputs(ex, basenames)

Validate that the execution contains exactly one manifest (circuits.json OR optimize.json) AND always request.json. Throws an error if the inputs are invalid.

source
MimiqCircuitsBase.AbstractDAGCircuitType
abstract type AbstractDAGCircuit{T} <: AbstractCircuit{T} end

Abstract type for all the struct that needs to implement a DAG representation for their circuits. It simply serves as a middle man/type providing the method to build the DAG from the list of instructions.

source
MimiqCircuitsBase.DecomposeIteratorType
DecomposeIterator(source, basis; wrap=false, cache=nothing)

An iterator that yields instructions from recursive decomposition of source to the given basis. Performs depth-first decomposition. The basis argument can be a DecompositionBasis or a RewriteRule.

If wrap=true, non-terminal operations will be wrapped into GateDecl (for gates) or Block (for others) containing the full decomposition, rather than being flattened.

If cache is provided (a Dict{Operation,GateDecl}), wrapped GateDecls will be cached and reused when the same operation is encountered again.

See also eachdecomposed, decompose.

source
MimiqCircuitsBase.LazyExprType
LazyExpr(type, args)

Helps evaluating expressions lazily.

Evaluation occurs only then the LazyExpr is called with some arguments, and the arguments will be passed to the inner part of the expression.

source
MimiqCircuitsBase.RewriteRuleType
RewriteRule

Abstract type for single-step rewrite rules that transform one operation into a sequence of simpler operations.

A RewriteRule defines how to transform an operation, but not when to stop. For recursive decomposition to a target set of operations, see DecompositionBasis.

Interface

Subtypes must implement:

Examples

struct MyRewrite <: RewriteRule end

matches(::MyRewrite, ::GateToffoli) = true
matches(::MyRewrite, ::Operation) = false

function decompose_step!(builder, ::MyRewrite, op::GateToffoli, qt, ct, zt)
    # ... append decomposed instructions to builder
    return builder
end

See also CanonicalRewrite, DecompositionBasis.

source
Base.append!Method
append!(circuit1::AbstractCircuit{T}, circuit2::AbstractCircuit{T})

Append all instructions from circuit2 to circuit1.

Arguments

  • circuit1::AbstractCircuit{T}: The target circuit to which instructions will be appended.
  • circuit2::AbstractCircuit{T}: The circuit whose instructions will be appended.

Examples

```jldoctests julia> c=Circuit() empty circuit

julia> push!(c, GateX(), 1:4) # Applies X to all 4 targets 4-qubit circuit with 4 instructions: ├── X @ q[1] ├── X @ q[2] ├── X @ q[3] └── X @ q[4]

julia> c1 = Circuit() empty circuit

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

julia> append!(c,c1) 4-qubit circuit with 8 instructions: ├── X @ q[1] ├── X @ q[2] ├── X @ q[3] ├── X @ q[4] ├── H @ q[1] ├── H @ q[2] ├── H @ q[3] └── H @ q[4]

source
Base.deleteat!Method
deleteat!(circuit::AbstractCircuit{T}, index::Integer)
deleteat!(circuit::AbstractCircuit{T}, inds)

Remove the instruction(s) at the given index(es).

Arguments

  • circuit::AbstractCircuit{T}: The target circuit.
  • index: The index or collection of indices to remove.

Examples

julia> c = Circuit()
empty circuit

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

julia> deleteat!(c, 2)
3-qubit circuit with 2 instructions:
├── X @ q[1]
└── X @ q[3]
source
Base.insert!Method
insert!(c::Circuit, i::Integer, operation_type::Type{T}, targets...)

Insert a non-parametric operation of a specific type into the circuit at a given position.

Arguments

  • c::Circuit: The quantum circuit where the operation will be inserted.
  • i::Integer: The position (1-based index) in the circuit where the operation will be inserted.
  • operation_type::Type{T}: The type of the operation to apply.
  • targets: The target qubits, bits, or z-variables for the operation.

Errors

  • ArgumentError: Raised if the operation type is parametric (i.e., it requires parameters).

Examples

julia> c = Circuit()
empty circuit

julia> c=Circuit()
empty circuit

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

julia> insert!(c, 3, GateRX(π/2), 5)
5-qubit circuit with 5 instructions:
├── X @ q[1]
├── X @ q[2]
├── RX(π/2) @ q[5]
├── X @ q[3]
└── X @ q[4]
source
Base.insert!Method
insert!(circuit::AbstractCircuit{T}, index::Integer, instruction::T)

Insert an instruction into the circuit at the specified index.

Arguments

  • circuit::AbstractCircuit{T}: The quantum circuit where the instruction will be inserted.
  • index::Integer: The position at which the instruction will be inserted.
  • instruction::T: The instruction to insert.

Examples

```jldoctests julia> c=Circuit() empty circuit

julia> c=Circuit() empty circuit

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

julia> insert!(c, 2, Instruction(GateH(), 1)) 4-qubit circuit with 5 instructions: ├── X @ q[1] ├── H @ q[1] ├── X @ q[2] ├── X @ q[3] └── X @ q[4]

source
Base.insert!Method
insert!(circuit1::AbstractCircuit{T}, index::Integer, circuit2::AbstractCircuit{T})

Insert all instructions from circuit2 into circuit1 at the specified index.

Arguments

  • circuit1::AbstractCircuit{T}: The target circuit where instructions will be inserted.
  • index::Integer: The position at which the instructions from circuit2 will be inserted.
  • circuit2::AbstractCircuit{T}: The circuit whose instructions will be inserted.

Examples

```jldoctests julia> c = Circuit() empty circuit

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

julia> c1 = Circuit() empty circuit

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

julia> insert!(c,1,c1) 4-qubit circuit with 8 instructions: ├── H @ q[1] ├── H @ q[2] ├── H @ q[3] ├── H @ q[4] ├── X @ q[1] ├── X @ q[2] ├── X @ q[3] └── X @ q[4]

julia>

source
Base.push!Method
push!(circuit::Circuit, operation::Operation, targets::Vararg{Int})

Add an operation to the circuit with the specified qubit, bit, or zvar targets.

This function allows you to push quantum operations onto a circuit, specifying the exact qubits, classical bits, or zvars (if applicable) that the operation acts on.

Arguments

  • circuit::Circuit: The quantum circuit to which the operation will be added.
  • operation::Operation{N,M,L}: The operation to apply. It works on N qubits, M classical bits, and L zvars.
  • targets::Vararg{Any,K}: The target qubits, bits, or zvars for the operation.

Throws

  • ArgumentError: If the wrong number of targets is provided.
  • ArgumentError: If any targets are invalid or not distinct.

Examples

julia> c=Circuit()
empty circuit

julia> push!(c, GateCX(), [1, 2], 3)  # Adds `CX @ q1, q3` and `CX @ q2, q3`
3-qubit circuit with 2 instructions:
├── CX @ q[1], q[3]
└── CX @ q[2], q[3]

julia> push!(c, GateX(), 1:4)         # Applies X to all 4 targets
4-qubit circuit with 6 instructions:
├── CX @ q[1], q[3]
├── CX @ q[2], q[3]
├── X @ q[1]
├── X @ q[2]
├── X @ q[3]
└── X @ q[4]

julia> push!(c, GateH(), 8)
8-qubit circuit with 7 instructions:
├── CX @ q[1], q[3]
├── CX @ q[2], q[3]
├── X @ q[1]
├── X @ q[2]
├── X @ q[3]
├── X @ q[4]
└── H @ q[8]
source
Base.push!Method
push!(circuit::Circuit, operation_type::Type{T}, targets...)

Add an operation of a specific type to the circuit with the given targets.

Arguments

  • circuit::Circuit: The quantum circuit to which the operation will be added.
  • operation_type::Type{T}: The type of the operation to apply.
  • targets: The target qubits, bits, or zvars for the operation.

Errors

  • ArgumentError: Raised if the operation type requires parameters (i.e., it is a parametric operation), but none were provided.

Examples

julia> c = Circuit()
empty circuit

julia> push!(c, GateRX(π/2), 1:4)
4-qubit circuit with 4 instructions:
├── RX(π/2) @ q[1]
├── RX(π/2) @ q[2]
├── RX(π/2) @ q[3]
└── RX(π/2) @ q[4]
source
Base.push!Method
push!(circuit::AbstractCircuit{T}, instruction::T)

Add an instruction to the circuit.

Arguments

  • circuit::AbstractCircuit{T}: The quantum circuit to which the instruction will be added.
  • instruction::T: The instruction to add.

Examples

julia> c=Circuit()
empty circuit

julia> push!(c, Instruction(GateX(),1)) 
1-qubit circuit with 1 instruction:
└── X @ q[1]

julia> push!(c, Instruction(GateCX(),1, 2))
2-qubit circuit with 2 instructions:
├── X @ q[1]
└── CX @ q[1], q[2]
source
MimiqCircuitsBase._csd_decompositionMethod
_csd_decomposition(U::AbstractMatrix)

Perform Cosine-Sine Decomposition (CSD) on a unitary matrix U. Returns (L0, L1, R0, R1, theta) such that:

\[U = \begin{pmatrix} L_0 & 0 \\ 0 & L_1 \end{pmatrix} \begin{pmatrix} C & -S \\ S & C \end{pmatrix} \begin{pmatrix} R_0 & 0 \\ 0 & R_1 \end{pmatrix}\]

where $C = \operatorname{diag}(\cos(\theta))$ and $S = \operatorname{diag}(\sin(\theta))$. $L_0, L_1, R_0, R_1$ are unitary matrices of half size. $\theta$ is a vector of angles.

source
MimiqCircuitsBase._extract_variablesMethod
_extract_variables(gate::Operation) -> Union{Tuple, Nothing}

Extract symbolic variables from a gate's parameters in order.

Examples

@variables θ
gate = GateRX(θ)
vars = _extract_variables(gate)  # Returns: (θ,)

@variables a b c
gate = GateU(a, 0.1, c)
vars = _extract_variables(gate)  # Returns: (a, nothing, c)

gate = GateRX(0.4)
vars = _extract_variables(gate)  # Returns: (nothing,)
source
MimiqCircuitsBase._qsd_decompositionMethod
_qsd_decomposition(U::AbstractMatrix)

Perform Quantum Shannon Decomposition (QSD) on an N-qubit unitary $U$. Returns (Circuit, Phase) where Circuit implements $U \cdot e^{-i \cdot \text{Phase}}$.

source
MimiqCircuitsBase._validate_rule_gate_paramsMethod
_validate_rule_gate_params(gate::Operation)

Validate that a rule gate's parameters are either concrete values or single symbolic variables. Throws an error if any parameter is a complex symbolic expression.

source
MimiqCircuitsBase._zyz_decompositionMethod
_zyz_decomposition(U::AbstractMatrix)

Decompose a single qubit unitary matrix U into angles θ, ϕ, λ, γ such that U is equivalent to GateU(θ, ϕ, λ, γ).

Returns a tuple (θ, ϕ, λ, γ).

source
MimiqCircuitsBase.applyparamsMethod
applyparams(source::Operation, relation::Pair)

Evaluates a relation by extracting parameter values from a source operation and substituting them into the target expression.

A relation has the form variables => target where:

  • variables: A single symbolic variable or a tuple of symbolic variables (e.g., θ or (a, b, c))
  • target: An operation using these variables (e.g., Depolarizing1(θ / π))

Parameters are matched by position: the i-th variable gets the i-th parameter from source. Variables in the left side must be simple symbolic variables, not expressions.

Arguments

  • source: Fully evaluated operation with concrete parameters (e.g., GateRX(0.4))
  • relation: A Pair of variables => target (e.g., θ => Depolarizing1(θ / π))

Returns

The evaluated target operation with all symbolic variables substituted

Examples

Single parameter

@variables θ
source = GateRX(0.4)
relation = θ => Depolarizing1(θ / π)
result = applyparams(source, relation)
# Result: Depolarizing1(0.4 / π) ≈ Depolarizing1(0.127)

Multiple parameters

@variables a b c
source = GateU(0.5, 0.3, 0.2)
relation = (a, b, c) => Depolarizing1((a^2 + b^2 + c^2) / (3π^2))
result = applyparams(source, relation)
# Result: Depolarizing1((0.5^2 + 0.3^2 + 0.2^2) / (3π^2))

Using subset of parameters

@variables a b
source = GateU(0.5, 0.3, 0.2)
relation = (a, b) => Depolarizing1(a + b)
result = applyparams(source, relation)
# Result: Depolarizing1(0.8)
# Third parameter (0.2) is ignored

Complex expressions in target

@variables θ
source = GateRX(π/4)
relation = θ => AmplitudeDamping(sin(θ)^2 * 0.01)
result = applyparams(source, relation)
# Result: AmplitudeDamping(0.005)

Invalid: Expression in variable list

@variables a b
source = GateU(0.5, 0.3, 0.2)
relation = (a, b + 1) => Depolarizing1(a)
result = applyparams(source, relation)
# Throws: ArgumentError - left side must be simple variables
Note

Variables on the left must be simple symbolic variables (not expressions)

Note

Number of variables must not exceed number of source parameters

source
MimiqCircuitsBase.axis_angle_to_su2Method
axis_angle_to_su2(axis::Vector{Float64}, θ::Float64) -> Matrix{ComplexF64}

Construct an SU(2) matrix from rotation axis and angle. U = cos(θ/2)·I + i·sin(θ/2)·(n·σ)

source
MimiqCircuitsBase.exponentMethod
exponent(poweroperation)

Exponent associated with a power operation

Examples

julia> MimiqCircuitsBase.exponent(power(GateH(), 2))
2

julia> MimiqCircuitsBase.exponent(GateSX())
1//2
source
MimiqCircuitsBase.extract_rotation_axisMethod
extract_rotation_axis(U::Matrix{ComplexF64}) -> Vector{Float64}

Extract the rotation axis n from an SU(2) matrix U = exp(iθ n·σ/2). Returns a unit vector in R³. If U ≈ I, returns [0, 0, 1].

source
MimiqCircuitsBase.find_nearest_in_netMethod
find_nearest_in_net(U::Matrix{ComplexF64}, cache::SKCacheEntry) -> Vector{AbstractGate}

Find the gate sequence in the ε-net that best approximates U. Handles the SU(2) double cover (U and -U represent the same rotation).

source
MimiqCircuitsBase.find_orthogonal_axesMethod
find_orthogonal_axes(n::Vector{Float64}) -> Tuple{Vector{Float64}, Vector{Float64}}

Find two orthonormal vectors v, w that are perpendicular to n, such that (v, w, n) form a right-handed coordinate system.

source
MimiqCircuitsBase.gc_decomposeMethod
gc_decompose(Δ::Matrix{ComplexF64}) -> Tuple{Matrix{ComplexF64}, Matrix{ComplexF64}}

Decompose an SU(2) matrix Δ (close to identity) into matrices V and W such that the group commutator [V, W] = V W V† W† approximates Δ.

This is the balanced group commutator construction from Dawson-Nielsen. For Δ representing a rotation by angle θ, V and W will be rotations by angle ≈ √θ around carefully chosen axes.

Mathematical Background

For small rotations, if V = exp(iφ v·σ/2) and W = exp(iφ w·σ/2), then [V,W] ≈ exp(i φ² (v×w)·σ/2) to leading order.

To achieve [V,W] ≈ Δ = exp(iθ n·σ/2):

  • Choose φ ≈ √θ
  • Choose v, w perpendicular to each other such that v×w ∝ n
source
MimiqCircuitsBase.get_pi_factor_or_nothingMethod
get_pi_factor_or_nothing(val) -> Union{Int, Nothing}

Check if val is a multiple of π/4 and return the factor k ∈ {0,1,...,7}.

Returns nothing if val is symbolic or not a multiple of π/4.

source
MimiqCircuitsBase.isCPTPMethod
isCPTP(krauschannel)

Whether the Kraus channel is Completely Positive, and Trace Preserving.

If the Kraus operators fulfill $\sum_k E_k^\dagger E_k = I$ then the quantum operation is CPTP. If $\sum_k E_k^\dagger E_k < I$, then it's not CPTP.

Currently, all noise channels are CPTP.

source
MimiqCircuitsBase.isterminalMethod
isterminal(basis::DecompositionBasis, op::Operation) -> Bool

Return true if op is terminal in the given basis.

Terminal operations are not decomposed further—they represent the target instruction set that decompose reduces circuits to.

Examples

isterminal(CanonicalBasis(), GateU())   # true
isterminal(CanonicalBasis(), GateH())   # false (will be decomposed)

See also DecompositionBasis, decompose.

source
MimiqCircuitsBase.matrix_to_pointMethod
matrix_to_point(U::Matrix) -> Vector{Float64}

Map an SU(2) matrix to a point in R⁴ (the 3-sphere S³).

For SU(2), a matrix [[a, -b], [b, a]] is determined by its first column [a, b]. We map this to [Re(a), Im(a), Re(b), Im(b)] ∈ S³.

source
MimiqCircuitsBase.numqbzMethod
numqbz(insts::Vector{<:Instruction})
numqbz(c::AbstractCircuit) -> Int

Compute the highest index of qubit targets, bit targets and zvar targets in the given vector of instructions or circuit.

Examples

julia> c = Circuit()
empty circuit

julia> push!(c, Measure(), 1:2, 1:2)
2-qubit, 2-bit circuit with 2 instructions:
├── M @ q[1], c[1]
└── M @ q[2], c[2]

julia> numqbz(c)
(2, 2, 0)
source
MimiqCircuitsBase.operator_norm_distanceMethod
operator_norm_distance(U::Matrix, V::Matrix) -> Float64

Compute the operator norm distance ||U - V||. For SU(2) matrices, this equals 2·sin(θ/2) where θ is the geodesic distance.

source
MimiqCircuitsBase.replacesMethod
replaces(rule::AbstractNoiseRule) -> Bool

Return whether the noise instruction replaces the original instruction. Default is false (noise is added alongside). Override for specific rule types.

source
MimiqCircuitsBase.simplify_sequenceMethod
simplify_sequence(gates, basis_gates) -> Vector{AbstractGate}

Simplify a gate sequence. If basis is standard Clifford+T, use algebraic rules. Otherwise, use generic inverse cancellation.

source
MimiqCircuitsBase.sk_approximateFunction
sk_approximate(U::Matrix{ComplexF64}, depth::Int, basis_gates::Vector{<:AbstractGate}; ...) -> Vector{AbstractGate}

Approximate an SU(2) matrix using the Solovay-Kitaev algorithm.

source
MimiqCircuitsBase.to_su2Method
to_su2(U::AbstractMatrix) -> Matrix{ComplexF64}

Project a 2×2 unitary matrix to SU(2) by removing the global phase.

source
MimiqLink.geturiFunction
geturi(connection_type, uri)
geturi(connection)
geturi(connection, parts...)

Get the URI for API calls through a specific connection or service.

source
MimiqLink.printrequestsMethod
printrequests(conn; kwargs...)

Print the list of requests on the MIMIQ Cloud Services.

Keyword arguments

  • status: filter by status. Can be NEW, RUNNING, ERROR, CANCELED, DONE.
  • userEmail: filter by user email.
  • limit: limit the number of requests to retrieve. Can be [10, 50, 100, 200].
  • page: page number to retrieve.
source
MimiqLink.requestsMethod
requests(conn; kwargs...)

Retrieve the list of requests on the MIMIQ Cloud Services.

Note

It is only possible to retrieve the requests that the user has permissions to see. This is often limited to the requests that the user has created, for normal users, and to all organization requests, for organization administrators.

Keyword arguments

  • status: filter by status. Can be NEW, RUNNING, ERROR, CANCELED, DONE.
  • userEmail: filter by user email.
  • limit: limit the number of requests to retrieve. Can be [10, 50, 100, 200].
  • page: page number to retrieve.
source
MimiqLink.stopexecutionMethod
stopexecution(conn, req)

Stop the execution of a request.

If the job is NEW, it will be immediately canceled. If it is RUNNING, a stop signal will be sent to the executor.

source