Z-register Operations

MimiqCircuitsBase provides a set of operations that manipulate the Z-register (complex-valued variables).

MimiqCircuitsBase.Add — Type
Add(N[, constant=0.0])

Sum several z-register variables (and optionally a constant) and assign the result to the first z-register variable given. The first target is the destination; the remaining N-1 targets are the inputs.

To accumulate into the destination instead of overwriting it, alias the destination as one of the inputs (z-variable aliasing is allowed for Add), e.g. push!(c, Add(3), 1, 1, 2) evaluates z[1] = z[1] + z[2].

Examples

julia> Add(3)
z[?1] = z[?2] + z[?3]

julia> Add(4)
z[?1] = z[?2] + z[?3] + z[?4]

julia> Add(4, 2.0)
z[?1] = 2.0 + z[?2] + z[?3] + z[?4]

julia> c = push!(Circuit(), Add(3), 1,2,3)
3-vars circuit with 1 instruction:
└── z[1] = z[2] + z[3]

julia> push!(c, Add(5), 1,2,3,4,5)
5-vars circuit with 2 instructions:
├── z[1] = z[2] + z[3]
└── z[1] = z[2] + z[3] + z[4] + z[5]

julia> push!(c, Add(5, 2.0), 1,2,3,4,5)
5-vars circuit with 3 instructions:
├── z[1] = z[2] + z[3]
├── z[1] = z[2] + z[3] + z[4] + z[5]
└── z[1] = 2.0 + z[2] + z[3] + z[4] + z[5]

julia> push!(Circuit(), Add(3), 1, 1, 2)  # accumulate via aliasing
2-vars circuit with 1 instruction:
└── z[1] = z[1] + z[2]
source
MimiqCircuitsBase.Multiply — Type
Multiply(N[, constant=1.0])

Multiply several z-register variables (and optionally a constant) and assign the result to the first z-register variable given. The first target is the destination; the remaining N-1 targets are the inputs.

To accumulate into the destination instead of overwriting it, alias the destination as one of the inputs (z-variable aliasing is allowed for Multiply), e.g. push!(c, Multiply(3), 1, 1, 2) evaluates z[1] = z[1] * z[2].

Examples

julia> Multiply(3)
z[?1] = z[?2] * z[?3]

julia> Multiply(4)
z[?1] = z[?2] * z[?3] * z[?4]

julia> Multiply(4, 2.0)
z[?1] = 2.0 * z[?2] * z[?3] * z[?4]

julia> c = push!(Circuit(), Multiply(4), 1,2,3,4)
4-vars circuit with 1 instruction:
└── z[1] = z[2] * z[3] * z[4]

julia> push!(c, Multiply(5, 2.0), 1,2,3,4,5)
5-vars circuit with 2 instructions:
├── z[1] = z[2] * z[3] * z[4]
└── z[1] = 2.0 * z[2] * z[3] * z[4] * z[5]

julia> push!(Circuit(), Multiply(3), 1, 1, 2)  # accumulate via aliasing
2-vars circuit with 1 instruction:
└── z[1] = z[1] * z[2]
source
MimiqCircuitsBase.Pow — Type
Pow(exp)

Exponentiate a Z-register variable.

Examples

julia> Pow(2.0)
z[?] = z[?]^2.0

julia> Pow(-2.0)
z[?] = z[?]^(-2.0)

julia> c = push!(Circuit(), Pow(2.0), 1)
1-vars circuit with 1 instruction:
└── z[1] = z[1]^2.0

julia> push!(c, Pow(-2.0), 1)
1-vars circuit with 2 instructions:
├── z[1] = z[1]^2.0
└── z[1] = z[1]^(-2.0)
source
MimiqCircuitsBase.ExpectationValue — Type
ExpectationValue(op)

Operation to compute and store expectation value of an Operator in a z-register.

An expectation value for a pure state $| \psi \rangle$ is defined as

\[\langle O \rangle = \langle \psi | O | \psi \rangle\]

where $O$ is an operator. With respect to a density matrix $\rho$ it's given by

\[\langle O \rangle = \mathrm{Tr}(\rho O).\]

However, when using quantum trajectories to solve noisy circuits, the expectation value is computed with respect to the pure state of each trajectory.

The argument op can be any gate or non-unitary operator.

Note

ExpectationValue is currently restricted to one and two qubit operators.

See also AbstractOperator, AbstractGate.

Examples

In push! the first argument corresponds to the qubit, and the second to the z-register

julia> ExpectationValue(GateX())
⟨X⟩

julia> c = push!(Circuit(), ExpectationValue(GateX()), 1, 1)
1-qubit, 1-vars circuit with 1 instruction:
└── ⟨X⟩ @ q[1], z[1]

julia> c = push!(Circuit(), ExpectationValue(SigmaPlus()), 1, 2)
1-qubit, 2-vars circuit with 1 instruction:
└── ⟨SigmaPlus(1)⟩ @ q[1], z[2]
source
MimiqCircuitsBase.Amplitude — Type
Amplitude(bs::BitString)

Operation to get amplitude of a state vector element.

The operation gets the quantum state's amplitude (which is a complex number) corresponding to the state defined by the bitstring bs in the computational basis and stores it in a z-register.

See BitString.

Examples

When defining a circuit, only the z-register to store the result needs to be specified.

julia> Amplitude(BitString("001"))
Amplitude(bs"001")

julia> c = push!(Circuit(),Amplitude(BitString("001")), 1)
1-vars circuit with 1 instruction:
└── Amplitude(bs"001") @ z[1]
source