Hamiltonians

MimiqCircuitsBase.Hamiltonian — Type
Hamiltonian()

Constructs a quantum Hamiltonian composed of a sum of HamiltonianTerms.

The full Hamiltonian is expressed as:

\[H = \sum_j c_j \cdot P_j\]

where each term consists of a real coefficient cj and a Pauli string Pj acting on a subset of qubits.

See also: Hamiltonian, PauliString

Examples

julia> h = Hamiltonian()
empty hamiltonian

julia> push!(h, 1.0, PauliString("XX"), 1, 2)
2-qubit hamiltonian with 1 terms:
+
└── 1.0 * XX @ q[1:2]

julia> push!(h, 0.5, PauliString("Z"), 2)
2-qubit hamiltonian with 2 terms:
+
├── 1.0 * XX @ q[1:2]
└── 0.5 * Z @ q[2]
source
MimiqCircuitsBase.HamiltonianTerm — Type
HamiltonianTerm(coefficient, pauli, qubits...)

A single term in a quantum Hamiltonian consisting of a real coefficient and a tensor product of Pauli operators.

Each HamiltonianTerm represents an operator of the form:

\[H_j = c_j \cdot P_j = c_j \cdot \left(P^{(1)} \otimes P^{(2)} \otimes \dots \right)\]

where cj is a real-valued scalar and Pj is a Pauli string (e.g., "XZ") acting on specific qubits.

See also: Hamiltonian, PauliString

Examples

julia> HamiltonianTerm(0.5, PauliString("XZ"), 1, 2)
0.5 * XZ @ q[1:2]
source
MimiqCircuitsBase.add_terms! — Method
add_terms!(hamiltonian, terms::HamiltonianTerm...)

Append terms to hamiltonian, in order, and return it.

Examples

julia> h = Hamiltonian();

julia> add_terms!(h, HamiltonianTerm(1.0, pauli"XX", 1, 2), HamiltonianTerm(0.5, pauli"Z", 1))
2-qubit hamiltonian with 2 terms:
+
├── 1.0 * XX @ q[1:2]
└── 0.5 * Z @ q[1]

See also push!.

source
MimiqCircuitsBase.getcoefficient — Method
getcoefficient(term::HamiltonianTerm)

Return the coefficient of a Hamiltonian term.

Examples

julia> getcoefficient(HamiltonianTerm(0.5, pauli"XZ", 1, 2))
0.5
source
MimiqCircuitsBase.push_expval! — Method
push_expval!(circuit, hamiltonian, qubits...; firstzvar=...)

Pushes an expectation value estimation circuit for a given Hamiltonian.

This operation measures the expectation value of a Hamiltonian and stores the result in a Z-register, combining the contributions of individual Pauli term evaluations.

For each term $c_j P_j$, the circuit performs:

\[\langle \psi | c_j P_j | \psi \rangle\]

Examples

julia> h = Hamiltonian()
empty hamiltonian

julia> push!(h, 0.7, PauliString("X"), 1)
1-qubit hamiltonian with 1 terms:
+
└── 0.7 * X @ q[1]

julia> push!(h, -0.3, PauliString("Z"), 1)
1-qubit hamiltonian with 2 terms:
+
├── 0.7 * X @ q[1]
└── -0.3 * Z @ q[1]

julia> c = Circuit()
empty circuit

julia> push_expval!(c, h, 1)
1-qubit, 2-vars circuit with 5 instructions:
├── ⟨X⟩ @ q[1], z[1]
├── z[1] = 0.7 * z[1]
├── ⟨Z⟩ @ q[1], z[2]
├── z[2] = -0.3 * z[2]
└── z[1] = z[1] + z[2]
source
MimiqCircuitsBase.push_lietrotter! — Method
push_lietrotter!(circuit, qubits, hamiltonian, t, steps)

Adds a Lie-Trotter expansion of the Hamiltonian hamiltonian to the circuit circuit for the qubits qubits over time t with steps steps.

The Lie-Trotter expansion is a method for approximating the time evolution operator of a Hamiltonian. It is particularly useful for simulating quantum systems.

Examples

julia> h = Hamiltonian()
empty hamiltonian

julia> push!(h, 1.0, PauliString("XX"), 1, 2)
2-qubit hamiltonian with 1 terms:
+
└── 1.0 * XX @ q[1:2]

julia> c = Circuit()
empty circuit

julia> push_lietrotter!(c, (1, 2), h, 1.0, 3)
2-qubit circuit with 3 instructions:
├── trotter(0.333333…) @ q[1:2]
├── trotter(0.333333…) @ q[1:2]
└── trotter(0.333333…) @ q[1:2]
source
MimiqCircuitsBase.push_suzukitrotter! — Function
push_suzukitrotter!(circuit, qubits, hamiltonian, t, steps)

Adds a Suzuki-Trotter expansion of the Hamiltonian hamiltonian to the circuit circuit for the qubits qubits over time t with steps steps.

The Suzuki-Trotter expansion is a method for approximating the time evolution operator of a Hamiltonian. It is particularly useful for simulating quantum systems.

The expansion performed is a $n$th-order expansion according to the Suzuki construction.

The second-order expansion is given by:

\[\mathrm{e} = \mathrm{e}^{-\imath t H} \approx \left[\prod_{j=1}^{m} \mathrm{e}^{-\imath\frac{\Delta t}{2} H_j} \prod_{j=m-1}^{1} \mathrm{e}^{-\imath\frac{\Delta t}{2} H_j}\right)\right]^k\]

where the Hamiltonian H can be expressed as a sum of m terms H_j:

\[H = \sum_{j=1}^{m} H_j\]

and $\Delta t = t / n_\text{steps}$.

Higher orders are derived from the Suzuki recursion relation

\[S_{2k}(\lambda) = [S_{2k−2}(p_k \lambda)]^2 \, S_{2k−2}((1 − 4p_k)\lambda)[S_{2k−2}(p_k\lambda)]^2 \qquad p_k = (4 - 4^{1/(2k-1)})^{-1}\]

Examples

julia> h = Hamiltonian()
empty hamiltonian

julia> push!(h, 1.0, PauliString("XX"), 1, 2)
2-qubit hamiltonian with 1 terms:
+
└── 1.0 * XX @ q[1:2]

julia> c = Circuit()
empty circuit

julia> push_suzukitrotter!(c, (1, 2), h, 1.0, 5, 2)
2-qubit circuit with 5 instructions:
├── suzukitrotter_2(0.2) @ q[1:2]
├── suzukitrotter_2(0.2) @ q[1:2]
├── suzukitrotter_2(0.2) @ q[1:2]
├── suzukitrotter_2(0.2) @ q[1:2]
└── suzukitrotter_2(0.2) @ q[1:2]
source
MimiqCircuitsBase.push_yoshidatrotter! — Function
push_yoshidatrotter!(circuit, qubits, hamiltonian, t, steps, order)

Adds a Yoshida-type symmetric composition of second-order Suzuki-Trotter expansions to the circuit for the qubits qubits, approximating the time evolution under the Hamiltonian over total time t, using steps steps and a given even order.

The Yoshida composition recursively constructs higher-order integrators of order 2, 4, 6, ... based on symmetric products of lower-order evolutions:

\[S_{2(k+1)}(t) = S_{2k}(w₁·t) ⋅ S_{2k}(w₂·t) ⋅ S_{2k}(w₁·t)\]

where the weights w₁ and w₂ = 1 - 2w₁ are chosen to cancel higher-order error terms. Specifically, they are:

\[w₁ = 1 / (2 - 2^(1 / (2k + 1))) w₂ = -2^(1 / (2k + 1)) / (2 - 2^(1 / (2k + 1)))\]

This method improves the accuracy of the approximation to the time evolution operator exp(-i * t * H) by nesting second-order symmetric expansions with non-uniform time scaling.

Note

The order must be an even number (2, 4, 6, ...). Internally, order 2 uses a standard second-order Suzuki-Trotter step.

See also: push_suzukitrotter!, GateDecl

Examples

julia> h = Hamiltonian()
empty hamiltonian

julia> push!(h, 1.0, PauliString("XX"), 1, 2)
2-qubit hamiltonian with 1 terms:
+
└── 1.0 * XX @ q[1:2]

julia> c = Circuit()
empty circuit

julia> push_yoshidatrotter!(c, (1, 2), h, 1.0, 5, 4)
2-qubit circuit with 5 instructions:
├── yoshidatrotter_4(0.2) @ q[1:2]
├── yoshidatrotter_4(0.2) @ q[1:2]
├── yoshidatrotter_4(0.2) @ q[1:2]
├── yoshidatrotter_4(0.2) @ q[1:2]
└── yoshidatrotter_4(0.2) @ q[1:2]
source