Private types and functions
MimiqCircuits.checkvalidinputs — Method
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.
MimiqCircuitsBase.SK_BASIC_GATES — Constant
Basic gates for the ε-net.
MimiqCircuitsBase.AbstractDAGCircuit — Type
abstract type AbstractDAGCircuit{T} <: AbstractCircuit{T} endAbstract 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.
MimiqCircuitsBase.BreadthFirstIterator — Type
BreadthFirstIteratorIterator that traverses the AbstractCircuit in a breadth-first topological order (layer by layer). This uses Kahn's algorithm with a FIFO queue.
MimiqCircuitsBase.DecomposeIterator — Type
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.
MimiqCircuitsBase.DepthFirstIterator — Type
DepthFirstIteratorIterator that traverses the AbstractCircuit in a depth-first topological order.
MimiqCircuitsBase.LazyArg — Type
LazyArg()Placeholder for a lazy argument in a LazyExpr.
MimiqCircuitsBase.LazyExpr — Type
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.
MimiqCircuitsBase.RewriteRule — Type
RewriteRuleAbstract 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:
matches(rule, op): Returntrueif this rule can transformop.decompose_step!(builder, rule, op, qtargets, ctargets, ztargets): Append the transformed instructions tobuilder.
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
endSee also CanonicalRewrite, DecompositionBasis.
MimiqCircuitsBase.UnexpectedSymbolics — Type
UnexpectedSymbolics(sym, expr)Error to be thrown when a unexpected symbolics is present in an expression.
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]
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]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]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]
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 fromcircuit2will 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>
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]
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]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]MimiqCircuitsBase._append_multiplexed_ry! — Method
_append_multiplexed_ry!(circ, angles, target, controls)Appends a multiplexed Ry rotation on target controlled by controls. angles has length 2^k where k = length(controls).
MimiqCircuitsBase._append_multiplexed_rz! — Method
_append_multiplexed_rz!(circ, angles, target, controls)Multiplexed Rz implementation.
MimiqCircuitsBase._append_multiplexed_unitary! — Method
_append_multiplexed_unitary!(circ, U0, U1, control, targets)Appends decomposition of $\operatorname{diag}(U_0, U_1)$ to circ. Returns the common global phase offset.
MimiqCircuitsBase._csd_decomposition — Method
_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.
MimiqCircuitsBase._displaypi — Method
Rewrite number in units of π, if number is rational multiple of π.
MimiqCircuitsBase._extract_variables — Method
_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,)MimiqCircuitsBase._matrix_hash — Method
Create a hash for an SU(2) matrix based on discretized elements.
MimiqCircuitsBase._qsd_decomposition — Method
_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}}$.
MimiqCircuitsBase._validate_rule_gate_params — Method
_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.
MimiqCircuitsBase._zyz_decomposition — Method
_zyz_decomposition(U::AbstractMatrix)Decompose a single qubit unitary matrix U into angles θ, ϕ, λ, γ such that U is equivalent to GateU(θ, ϕ, λ, γ).
Returns a tuple (θ, ϕ, λ, γ).
MimiqCircuitsBase.applyparams — Method
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: APairof 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 ignoredComplex 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 variablesMimiqCircuitsBase.axis_angle_to_su2 — Method
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·σ)
MimiqCircuitsBase.exponent — Method
exponent(poweroperation)Exponent associated with a power operation
Examples
julia> MimiqCircuitsBase.exponent(power(GateH(), 2))
2
julia> MimiqCircuitsBase.exponent(GateSX())
1//2MimiqCircuitsBase.extract_rotation_angle — Method
extract_rotation_angle(U::Matrix{ComplexF64}) -> Float64Extract the rotation angle θ from an SU(2) matrix U = exp(iθ n·σ/2). Returns θ ∈ [0, 2π].
MimiqCircuitsBase.extract_rotation_axis — Method
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].
MimiqCircuitsBase.find_nearest_in_net — Method
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).
MimiqCircuitsBase.find_orthogonal_axes — Method
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.
MimiqCircuitsBase.gc_decompose — Method
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
MimiqCircuitsBase.generate_epsilon_net — Function
generate_epsilon_net(basis_gates, max_depth, max_points, min_dist) -> (points, gate_sequences)Generate an ε-net over SU(2) using Breadth-First Search.
MimiqCircuitsBase.get_pi_factor_or_nothing — Method
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.
MimiqCircuitsBase.get_sk_cache — Method
get_sk_cache(basis_gates; max_depth, max_points, min_dist) -> SKCacheEntryGet or initialize the Solovay-Kitaev lookup tables.
MimiqCircuitsBase.invert_sequence — Method
invert_sequence(gates) -> Vector{AbstractGate}Return the inverse of a gate sequence: (g₁ g₂ ... gₙ)† = gₙ† ... g₂† g₁†
MimiqCircuitsBase.isCPTP — Method
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.
MimiqCircuitsBase.isidentity — Method
isidentity(operation)Check if the given operation is equivalent to an isidentity.
MimiqCircuitsBase.isterminal — Method
isterminal(basis::DecompositionBasis, op::Operation) -> BoolReturn 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.
MimiqCircuitsBase.matrix_to_point — Method
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³.
MimiqCircuitsBase.numqbz — Method
numqbz(insts::Vector{<:Instruction})
numqbz(c::AbstractCircuit) -> IntCompute 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)
MimiqCircuitsBase.operator_norm_distance — Method
operator_norm_distance(U::Matrix, V::Matrix) -> Float64Compute the operator norm distance ||U - V||. For SU(2) matrices, this equals 2·sin(θ/2) where θ is the geodesic distance.
MimiqCircuitsBase.replaces — Method
replaces(rule::AbstractNoiseRule) -> BoolReturn whether the noise instruction replaces the original instruction. Default is false (noise is added alongside). Override for specific rule types.
MimiqCircuitsBase.sequence_to_matrix — Method
sequence_to_matrix(gates) -> Matrix{ComplexF64}Compute the unitary matrix for a gate sequence.
MimiqCircuitsBase.simplify_sequence — Method
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.
MimiqCircuitsBase.sk_approximate — Function
sk_approximate(U::Matrix{ComplexF64}, depth::Int, basis_gates::Vector{<:AbstractGate}; ...) -> Vector{AbstractGate}Approximate an SU(2) matrix using the Solovay-Kitaev algorithm.
MimiqCircuitsBase.sk_approximate_memoized — Method
sk_approximate_memoized(U::Matrix{ComplexF64}, depth::Int; ...) -> Vector{AbstractGate}Memoized version of sk_approximate.
MimiqCircuitsBase.to_su2 — Method
to_su2(U::AbstractMatrix) -> Matrix{ComplexF64}Project a 2×2 unitary matrix to SU(2) by removing the global phase.
MimiqLink.DEFAULT_INTERVAL — Constant
const DEFAULT_INTERVAL
Default refresh interval for tokens (in seconds)
MimiqLink.Tokens — Type
struct TokensStore access and refresh tokens
MimiqLink.deletefiles — Method
deletefiles(conn, req)Delete the uploaded and result files associated with a request.
MimiqLink.geturi — Function
geturi(connection_type, uri)
geturi(connection)
geturi(connection, parts...)Get the URI for API calls through a specific connection or service.
MimiqLink.printrequests — Method
printrequests(conn; kwargs...)Print the list of requests on the MIMIQ Cloud Services.
Keyword arguments
status: filter by status. Can beNEW,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.
MimiqLink.refresh — Method
refresh(tokens, uri)
Refresh the tokens at the given uri / instance of MIMIQ.
MimiqLink.requests — Method
requests(conn; kwargs...)Retrieve the list of requests on the MIMIQ Cloud Services.
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 beNEW,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.
MimiqLink.stopexecution — Method
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.