mimiqcircuits.hamiltonian

Hamiltonian class and utilities.

Functions

push_expval(self, hamiltonian, *qubits[, ...])

Push an expectation value estimation circuit for a given Hamiltonian.

push_lietrotter(self, h, qubits, t, steps)

Apply a Lie-Trotter expansion of the Hamiltonian h to the circuit self for the qubits qubits over total time t with steps steps.

push_suzukitrotter(self, h, qubits, t, steps)

Apply Suzuki-Trotter expansion of the Hamiltonian h to the circuit self for the qubits qubits over time t with steps steps.

push_yoshidatrotter(self, h, qubits, t, steps)

Apply Yoshida-Trotter expansion of the Hamiltonian h to the circuit self for the qubits qubits over time t with steps steps.

Classes

Hamiltonian([terms])

A quantum Hamiltonian composed of multiple Pauli terms.

HamiltonianTerm(coefficient, pauli, qubits)

Single term in a quantum Hamiltonian.

class mimiqcircuits.hamiltonian.HamiltonianTerm(coefficient, pauli, qubits)[source]

Bases: object

Single term in a quantum Hamiltonian.

A HamiltonianTerm represents a single tensor product of Pauli operators acting on a subset of qubits, scaled by a real-valued coefficient.

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

where \(c_j\) is a real coefficient and \(P_j\) is a Pauli string such as X, YZ, etc.

Parameters:
  • coefficient (float) – The scalar multiplier for this term.

  • pauli (PauliString) – The Pauli operator string (e.g., “XY”).

  • qubits (tuple) – The tuple of qubit indices this term acts on.

Raises:

ValueError – If any qubit index is negative.

Examples

>>> from mimiqcircuits import *
>>> HamiltonianTerm(0.5, PauliString("XZ"), (0, 1))
0.5 * XZ @ q[0,1]
__init__(coefficient, pauli, qubits)[source]
get_operation()[source]
get_coefficient()[source]
get_qubits()[source]
class mimiqcircuits.hamiltonian.Hamiltonian(terms=None)[source]

Bases: object

A quantum Hamiltonian composed of multiple Pauli terms.

This class models a Hamiltonian of the form:

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

where each term is a HamiltonianTerm consisting of a coefficient and a Pauli string.

- `push(...)`

Add a term by specifying its components.

- `add_terms(...)`

Add a HamiltonianTerm object.

- `num_qubits()`

Total number of qubits this Hamiltonian acts on.

- `saveproto(...)`

Save to protobuf format.

- `loadproto(...)`

Load from protobuf.

Examples

>>> from mimiqcircuits import *
>>> h = Hamiltonian()
>>> h.push(1.0, PauliString("XX"), 0, 1)
2-qubit Hamiltonian with 1 terms:
└── 1.0 * XX @ q[0,1]
>>> h.push(1.0, PauliString("YY"), 0, 1)
2-qubit Hamiltonian with 2 terms:
├── 1.0 * XX @ q[0,1]
└── 1.0 * YY @ q[0,1]
>>> print(h)
2-qubit Hamiltonian with 2 terms:
├── 1.0 * XX @ q[0,1]
└── 1.0 * YY @ q[0,1]
__init__(terms=None)[source]
add_terms(term)[source]
push(coefficient, pauli, *qubits)[source]
num_terms()[source]
num_qubits()[source]
saveproto(file)[source]
static loadproto(file)[source]
matrix()[source]

Return the symbolic matrix representation of the Hamiltonian using symengine.

evaluate(d)[source]

Evaluate the symbolic coefficients of each term using the substitution dictionary d.

Parameters:

d (dict) – Dictionary mapping symbols (e.g., {‘theta’: 0.5}) to values.

Returns:

A new Hamiltonian with evaluated (numerical or partially symbolic) coefficients.

Return type:

Hamiltonian

mimiqcircuits.hamiltonian.push_expval(self, hamiltonian, *qubits, firstzvar=None)[source]

Push 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 individual Pauli term evaluations.

For each term \(c_j P_j\), the circuit performs:

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

and sums the contributions in a new z-register.

Parameters:
  • hamiltonian (Hamiltonian) – The Hamiltonian to evaluate.

  • qubits (int) – The qubit mapping to use.

  • firstzvar (int, optional) – Index of the first Z-register to use.

Returns:

The modified circuit.

Return type:

Circuit

Examples

>>> from mimiqcircuits import *
>>> c = Circuit()
>>> h = Hamiltonian()
>>> h.push(1.0, PauliString("ZZ"), 0, 1)
2-qubit Hamiltonian with 1 terms:
└── 1.0 * ZZ @ q[0,1]
>>> c.push_expval(h, 1, 2)
3-qubit, 1-zvar circuit with 3 instructions:
├── ⟨ZZ⟩ @ q[1:2], z[0]
├── z[0] *= 1.0
└── z[0] += 0.0

See also

ExpectationValue, Multiply, Add

mimiqcircuits.hamiltonian.push_lietrotter(self, h, qubits, t, steps)[source]

Apply a Lie-Trotter expansion of the Hamiltonian h to the circuit self for the qubits qubits over total time t with steps steps.

The Lie-Trotter expansion is a first-order approximation of the time evolution operator for a Hamiltonian composed of non-commuting terms. It decomposes the exponential of a sum of operators into a product of exponentials:

\[e^{-i H t} \approx \left[ \prod_{j=1}^m e^{-i c_j P_j \Delta t} \right]^n\]
where:
  • \(H = \sum_{j=1}^m c_j P_j\) is the Hamiltonian

  • \(P_j\) are Pauli strings

  • \(\Delta t = t / n\) is the time step size

  • \(n\) is the number of steps

This method is particularly useful for simulating quantum systems and time-evolving quantum states in quantum algorithms such as VQE or QAOA.

See also

push_suzukitrotter(), GateDecl

Examples

>>> from mimiqcircuits import *
>>> c = Circuit()
>>> h = Hamiltonian()
>>> h.push(1.0, PauliString("ZZ"), 0, 1)
2-qubit Hamiltonian with 1 terms:
└── 1.0 * ZZ @ q[0,1]
>>> c.push_lietrotter(h, (0, 1), t=1.0, steps=3)
2-qubit circuit with 3 instructions:
├── trotter(0.3333333333333333) @ q[0:1]
├── trotter(0.3333333333333333) @ q[0:1]
└── trotter(0.3333333333333333) @ q[0:1]
mimiqcircuits.hamiltonian.push_suzukitrotter(self, h, qubits, t, steps, order=2)[source]

Apply Suzuki-Trotter expansion of the Hamiltonian h to the circuit self for the qubits qubits over time t with steps steps.

The Suzuki-Trotter expansion approximates the time evolution operator of a quantum Hamiltonian using a sequence of exponentiated subterms. This is particularly useful for simulating quantum systems where the Hamiltonian is composed of non-commuting parts.

The expansion performed is a 2k-th order expansion according to the Suzuki construction.

The second-order expansion is given by:

\[e^{-i H t} \approx \left[ \prod_{j=1}^{m} e^{-i \frac{\Delta t}{2} H_j} \prod_{j=m}^{1} e^{-i \frac{\Delta t}{2} H_j} \right]^n\]

where the Hamiltonian \(H\) is a sum of terms:

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

and the Trotter step size is:

\[\Delta t = \frac{t}{n}\]

Higher-order expansions follow the Suzuki recursion relation:

\[S_{2k}(\lambda) = [S_{2k-2}(p_k \lambda)]^2 \cdot S_{2k-2}((1 - 4p_k)\lambda) \cdot [S_{2k-2}(p_k \lambda)]^2\]

with:

\[p_k = \left(4 - 4^{1/(2k - 1)}\right)^{-1}\]

See also

push_lietrotter(), GateDecl

Examples

>>> from mimiqcircuits import *
>>> c = Circuit()
>>> h = Hamiltonian()
>>> h.push(1.0, PauliString("XX"), 0, 1)
2-qubit Hamiltonian with 1 terms:
└── 1.0 * XX @ q[0,1]
>>> c.push_suzukitrotter(h, (0, 1), t=1.0, steps=5, order=2)
2-qubit circuit with 5 instructions:
├── suzukitrotter_2(0.2) @ q[0:1]
├── suzukitrotter_2(0.2) @ q[0:1]
├── suzukitrotter_2(0.2) @ q[0:1]
├── suzukitrotter_2(0.2) @ q[0:1]
└── suzukitrotter_2(0.2) @ q[0:1]
mimiqcircuits.hamiltonian.push_yoshidatrotter(self, h, qubits, t, steps, order=4)[source]

Apply Yoshida-Trotter expansion of the Hamiltonian h to the circuit self for the qubits qubits over time t with steps steps.

The Yoshida-Trotter expansion approximates the time evolution operator of a quantum Hamiltonian using a symmetric composition of second-order Trotter formulas. This technique improves accuracy by canceling higher-order error terms in the Baker–Campbell–Hausdorff expansion.

The Yoshida expansion performed is a 2k-th order expansion using the symmetric structure:

\[S_{2(k+1)}(t) = S_{2k}(w_1 \cdot t) \cdot S_{2k}(w_2 \cdot t) \cdot S_{2k}(w_1 \cdot t)\]

where the weights are:

\[w_1 = \frac{1}{2 - 2^{1/(2k+1)}}, \quad w_2 = -\frac{2^{1/(2k+1)}}{2 - 2^{1/(2k+1)}}\]

and the base case is the standard second-order Strang splitting:

\[S_2(\Delta t) = \prod_{j=1}^{m} e^{-i \Delta t H_j / 2} \prod_{j=m}^{1} e^{-i \Delta t H_j / 2}\]

This method is particularly useful for simulating quantum systems where the Hamiltonian is composed of non-commuting parts, and is a computationally efficient alternative to full recursive Suzuki methods.

See also

push_suzukitrotter(), GateDecl

Parameters:
  • h (Hamiltonian) – The Hamiltonian object.

  • qubits (tuple) – Tuple of qubit indices.

  • t (float) – Total simulation time.

  • steps (int) – Number of Trotter steps to apply.

  • order (int) – Desired even expansion order (must be ≥ 2 and even).

Returns:

The modified circuit.

Return type:

Circuit

Examples

>>> from mimiqcircuits import *
>>> c = Circuit()
>>> h = Hamiltonian()
>>> h.push(1.0, PauliString("XY"), 0, 1)
2-qubit Hamiltonian with 1 terms:
└── 1.0 * XY @ q[0,1]
>>> h.push(0.5, PauliString("Z"), 0)
2-qubit Hamiltonian with 2 terms:
├── 1.0 * XY @ q[0,1]
└── 0.5 * Z @ q[0]
>>> c.push_yoshidatrotter(h, (0, 1), t=1.0, steps=3, order=4)
2-qubit circuit with 3 instructions:
├── yoshida_4(0.3333333333333333) @ q[0:1]
├── yoshida_4(0.3333333333333333) @ q[0:1]
└── yoshida_4(0.3333333333333333) @ q[0:1]