Overview¶
| Function | Description |
|---|---|
X | Creates a Pauli X operator for a specified qubit. |
Y | Creates a Pauli Y operator for a specified qubit. |
Z | Creates a Pauli Z operator for a specified qubit. |
commutator | Compute the commutator [A, B] = A B - B A of two Hamiltonians. |
| Class | Description |
|---|---|
Hamiltonian | Represents a quantum Hamiltonian as a sum of Pauli operator products. |
Pauli | Enum class for Pauli operators. |
PauliOperator | Represents a single Pauli operator acting on a specific qubit. |
Constants¶
PAULI_TO_CHAR:dict[Pauli, str]={Pauli.I: 'I', Pauli.X: 'X', Pauli.Y: 'Y', Pauli.Z: 'Z'}
Functions¶
X [source]¶
def X(index: int) -> HamiltonianCreates a Pauli X operator for a specified qubit.
Parameters:
| Name | Type | Description |
|---|---|---|
index | int | The index of the qubit. |
Returns:
Hamiltonian — A Pauli X Hamiltonian operator acting on the specified qubit.
Example:
>>> X0 = X(0)
>>> print(X0)
Hamiltonian((X0,): 1.0)Y [source]¶
def Y(index: int) -> HamiltonianCreates a Pauli Y operator for a specified qubit.
Parameters:
| Name | Type | Description |
|---|---|---|
index | int | The index of the qubit. |
Returns:
Hamiltonian — A Pauli Y Hamiltonian operator acting on the specified qubit.
Example:
>>> Y1 = Y(1)
>>> print(Y1)
Hamiltonian((Y1,): 1.0)Z [source]¶
def Z(index: int) -> HamiltonianCreates a Pauli Z operator for a specified qubit.
Parameters:
| Name | Type | Description |
|---|---|---|
index | int | The index of the qubit. |
Returns:
Hamiltonian — A Pauli Z Hamiltonian operator acting on the specified qubit.
Example:
>>> Z2 = Z(2)
>>> print(Z2)
Hamiltonian((Z2,): 1.0)commutator [source]¶
def commutator(a: Hamiltonian, b: Hamiltonian) -> HamiltonianCompute the commutator [A, B] = A B - B A of two Hamiltonians.
Iterates over the Pauli-string terms of a and b once and uses
the fact that two Pauli strings either commute ([P, Q] = 0) or
anticommute ([P, Q] = 2 P Q). Commuting pairs are skipped
entirely, so for sparse or nearly-commuting Hamiltonians this is
cheaper than expanding a * b - b * a and then cancelling.
The asymptotic cost is still O(|a| * |b|) Pauli-string pairs in
the worst case where every pair anticommutes.
The constant parts of a and b commute with every Pauli string
and with each other, so they contribute nothing to the commutator
and are ignored.
Parameters:
| Name | Type | Description |
|---|---|---|
a | Hamiltonian | The left operand of the commutator. |
b | Hamiltonian | The right operand of the commutator. |
Returns:
Hamiltonian — A new Hamiltonian equal to a * b - b * a.
Its num_qubits is the maximum of a.num_qubits and
b.num_qubits so the qubit register is preserved even
when the commutator collapses to zero on a subset of
qubits.
Example:
>>> from qamomile.observable.hamiltonian import X, Y, commutator
>>> commutator(X(0), Y(0))
Hamiltonian((Z0,): 2j)
>>> commutator(X(0), X(1))
Hamiltonian()Classes¶
Hamiltonian [source]¶
class HamiltonianRepresents a quantum Hamiltonian as a sum of Pauli operator products.
The Hamiltonian is stored as a dictionary where keys are tuples of PauliOperators and values are their corresponding coefficients.
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5)
>>> H.add_term((PauliOperator(Pauli.Z, 2),), 1.0)
>>> print(H.terms)
{(X0, Y1): 0.5, (Z2,): 1.0}Constructor¶
def __init__(self, num_qubits: int | None = None) -> NoneAttributes¶
constant: float | complexnum_qubits: int Calculates the number of qubits in the Hamiltonian.terms: dict[tuple[PauliOperator, ...], complex] Getter for the terms of the Hamiltonian.
Methods¶
add_term¶
def add_term(self, operators: tuple[PauliOperator, ...], coeff: float | complex)Adds a term to the Hamiltonian.
This method adds a product of Pauli operators with a given coefficient to the Hamiltonian. If the term already exists, the coefficients are summed.
Parameters:
| Name | Type | Description |
|---|---|---|
operators | Tuple[PauliOperator, ...] | A tuple of PauliOperators representing the term. |
coeff | Union[float, complex] | The coefficient of the term. |
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5)
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5j)
>>> print(H.terms)
{(X0, Y1): (0.5+0.5j)}copy¶
def copy(self) -> HamiltonianReturn an independent copy sharing no mutable state with self.
Produces a new Hamiltonian with the same terms, constant,
and declared _num_qubits. The underlying _terms dict
is fresh, so subsequent add_term / constant mutations
on either instance do not affect the other. PauliOperator
instances inside the term tuples are reused — they are
dataclass(frozen=True) values and safely shared.
Returns:
Hamiltonian — A shallow-cloned Hamiltonian instance.
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.Z, 0),), 1.0)
>>> H2 = H.copy()
>>> H2.add_term((PauliOperator(Pauli.X, 1),), 0.5)
>>> H.num_qubits # unchanged by H2's mutation
1identity¶
@classmethod
def identity(
cls,
coeff: float | complex = 1.0,
num_qubits: int | None = None,
) -> HamiltonianCreate a scalar times identity Hamiltonian.
remap_qubits¶
def remap_qubits(self, qubit_map: dict[int, int]) -> HamiltonianRemap qubit indices according to the given mapping.
This is used to translate Pauli indices (logical indices within an expval call) to physical qubit indices in the actual quantum circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
qubit_map | dict[int, int] | Mapping from logical index to physical index. e.g., {0: 5, 1: 3} maps logical index 0 → physical qubit 5 |
Returns:
Hamiltonian — New Hamiltonian with remapped qubit indices.
single_pauli¶
@classmethod
def single_pauli(cls, pauli: Pauli, index: int, coeff: float | complex = 1.0) -> HamiltonianCreate a single Pauli term Hamiltonian.
to_latex¶
def to_latex(self) -> strConverts the Hamiltonian to a LaTeX representation.
This function does not add constant term when we show the Hamiltonian. This function does not add $ symbols.
Returns:
str —
A LaTeX representation of the Hamiltonian.
import qamomile.core.operator as qm_o
import IPython.display as ipd
h = qm_o.Hamiltonian()
h += -qm_o.X(0) * qm_o.Y(1) - 2.0 * qm_o.Z(0) * qm_o.Z(1)
# Show the Hamiltonian in LaTeX at Jupyter Notebook
ipd.display(ipd.Latex("$" + h.to_latex() + "$"))to_numpy¶
def to_numpy(self) -> np.ndarrayConvert the Hamiltonian to a dense NumPy matrix.
Qubit 0 is mapped to the least-significant bit of computational-basis
indices, matching :meth:qamomile.linalg.HermitianMatrix.to_hamiltonian.
The returned array has shape (2**n, 2**n) where n is
:attr:num_qubits.
zero¶
@classmethod
def zero(cls, num_qubits: int | None = None) -> HamiltonianCreate a zero Hamiltonian.
Pauli [source]¶
class Pauli(enum.Enum)Enum class for Pauli operators.
Attributes¶
IXYZ
PauliOperator [source]¶
class PauliOperatorRepresents a single Pauli operator acting on a specific qubit.
Frozen so that Hamiltonian.copy() can share term operator
references across the original and the copy without risk of one
side mutating an operator the other still observes. None of the
existing callers mutate pauli or index after construction,
so freezing is a no-op behaviourally but makes the immutability
claim that Hamiltonian.copy()'s docstring relies on real.
Example:
>>> X0 = PauliOperator(Pauli.X, 0)
>>> print(X0)
X0Constructor¶
def __init__(self, pauli: Pauli, index: int) -> NoneAttributes¶
index: intpauli: Pauli
qamomile.observable.hamiltonian¶
This module provides the intermediate representation of Hamiltonian for quantum systems.
It defines classes and functions to create and manipulate Pauli operators and Hamiltonians, which are fundamental in quantum mechanics and quantum computing.
Key Components:
Pauli: An enumeration of Pauli operators (X, Y, Z, I).
PauliOperator: A class representing a single Pauli operator acting on a specific qubit.
Hamiltonian: A class representing a quantum Hamiltonian as a sum of Pauli operator products.
Usage:
from qamomile.operator.hamiltonian import X, Y, Z, Hamiltonian
Create Pauli operators¶
X0 = X(0) # Pauli X operator on qubit 0 Y1 = Y(1) # Pauli Y operator on qubit 1
Create a Hamiltonian¶
H = Hamiltonian() H.add_term((X0, Y1), 0.5) # Add term 0.5 * X0 * Y1 to the Hamiltonian H.add_term((Z(2),), 1.0) # Add term 1.0 * Z2 to the Hamiltonian
Access Hamiltonian properties¶
print(H.terms) print(H.num_qubits)
Features:
Factory methods for common Hamiltonians (zero, identity, single_pauli)
Iterator protocol for looping over terms
Qubit index remapping for circuit integration
Modern type annotations (PEP 604)
Overview¶
| Function | Description |
|---|---|
X | Creates a Pauli X operator for a specified qubit. |
Y | Creates a Pauli Y operator for a specified qubit. |
Z | Creates a Pauli Z operator for a specified qubit. |
commutator | Compute the commutator [A, B] = A B - B A of two Hamiltonians. |
multiply_pauli_same_qubit | Multiplies two Pauli operators acting on the same qubit. |
simplify_pauliop_terms | Simplifies a tuple of Pauli operators by combining operators acting on the same qubit. |
| Class | Description |
|---|---|
Hamiltonian | Represents a quantum Hamiltonian as a sum of Pauli operator products. |
Pauli | Enum class for Pauli operators. |
PauliOperator | Represents a single Pauli operator acting on a specific qubit. |
Constants¶
PAULI_TO_CHAR:dict[Pauli, str]={Pauli.I: 'I', Pauli.X: 'X', Pauli.Y: 'Y', Pauli.Z: 'Z'}
Functions¶
X [source]¶
def X(index: int) -> HamiltonianCreates a Pauli X operator for a specified qubit.
Parameters:
| Name | Type | Description |
|---|---|---|
index | int | The index of the qubit. |
Returns:
Hamiltonian — A Pauli X Hamiltonian operator acting on the specified qubit.
Example:
>>> X0 = X(0)
>>> print(X0)
Hamiltonian((X0,): 1.0)Y [source]¶
def Y(index: int) -> HamiltonianCreates a Pauli Y operator for a specified qubit.
Parameters:
| Name | Type | Description |
|---|---|---|
index | int | The index of the qubit. |
Returns:
Hamiltonian — A Pauli Y Hamiltonian operator acting on the specified qubit.
Example:
>>> Y1 = Y(1)
>>> print(Y1)
Hamiltonian((Y1,): 1.0)Z [source]¶
def Z(index: int) -> HamiltonianCreates a Pauli Z operator for a specified qubit.
Parameters:
| Name | Type | Description |
|---|---|---|
index | int | The index of the qubit. |
Returns:
Hamiltonian — A Pauli Z Hamiltonian operator acting on the specified qubit.
Example:
>>> Z2 = Z(2)
>>> print(Z2)
Hamiltonian((Z2,): 1.0)commutator [source]¶
def commutator(a: Hamiltonian, b: Hamiltonian) -> HamiltonianCompute the commutator [A, B] = A B - B A of two Hamiltonians.
Iterates over the Pauli-string terms of a and b once and uses
the fact that two Pauli strings either commute ([P, Q] = 0) or
anticommute ([P, Q] = 2 P Q). Commuting pairs are skipped
entirely, so for sparse or nearly-commuting Hamiltonians this is
cheaper than expanding a * b - b * a and then cancelling.
The asymptotic cost is still O(|a| * |b|) Pauli-string pairs in
the worst case where every pair anticommutes.
The constant parts of a and b commute with every Pauli string
and with each other, so they contribute nothing to the commutator
and are ignored.
Parameters:
| Name | Type | Description |
|---|---|---|
a | Hamiltonian | The left operand of the commutator. |
b | Hamiltonian | The right operand of the commutator. |
Returns:
Hamiltonian — A new Hamiltonian equal to a * b - b * a.
Its num_qubits is the maximum of a.num_qubits and
b.num_qubits so the qubit register is preserved even
when the commutator collapses to zero on a subset of
qubits.
Example:
>>> from qamomile.observable.hamiltonian import X, Y, commutator
>>> commutator(X(0), Y(0))
Hamiltonian((Z0,): 2j)
>>> commutator(X(0), X(1))
Hamiltonian()multiply_pauli_same_qubit [source]¶
def multiply_pauli_same_qubit(pauli1: PauliOperator, pauli2: PauliOperator) -> tuple[PauliOperator, complex]Multiplies two Pauli operators acting on the same qubit.
Parameters:
| Name | Type | Description |
|---|---|---|
pauli1 | PauliOperator | The first Pauli operator. |
pauli2 | PauliOperator | The second Pauli operator. |
Returns:
tuple[PauliOperator, complex] — tuple[PauliOperator, complex]: A tuple containing the resulting Pauli operator and the complex coefficient.
Raises:
ValueError— If the Pauli operators act on different qubits.
Example:
>>> X0 = PauliOperator(Pauli.X, 0)
>>> Y0 = PauliOperator(Pauli.Y, 0)
>>> Z0 = PauliOperator(Pauli.Z, 0)
>>> multiply_pauli_same_qubit(X0, Y0)
(Z0, 1j)simplify_pauliop_terms [source]¶
def simplify_pauliop_terms(term: tuple[PauliOperator, ...]) -> tuple[tuple[PauliOperator, ...], complex]Simplifies a tuple of Pauli operators by combining operators acting on the same qubit.
This function performs canonicalization by:
Multiplying Pauli operators on the same qubit using the Pauli algebra
Removing identity operators from the result
Tracking the accumulated phase factor from the multiplications
Parameters:
| Name | Type | Description |
|---|---|---|
term | tuple[PauliOperator] | A tuple of Pauli operators. |
Returns:
tuple[tuple[PauliOperator, ...], complex] — tuple[tuple[PauliOperator,...],complex]: A tuple containing the simplified Pauli operators and the phase factor.
Example:
>>> X0 = PauliOperator(Pauli.X, 0)
>>> Y0 = PauliOperator(Pauli.Y, 0)
>>> Z1 = PauliOperator(Pauli.Z, 1)
>>> simplify_pauliop_terms((X0, Y0, Z1))
((Z0, Z1), 1j)Classes¶
Hamiltonian [source]¶
class HamiltonianRepresents a quantum Hamiltonian as a sum of Pauli operator products.
The Hamiltonian is stored as a dictionary where keys are tuples of PauliOperators and values are their corresponding coefficients.
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5)
>>> H.add_term((PauliOperator(Pauli.Z, 2),), 1.0)
>>> print(H.terms)
{(X0, Y1): 0.5, (Z2,): 1.0}Constructor¶
def __init__(self, num_qubits: int | None = None) -> NoneAttributes¶
constant: float | complexnum_qubits: int Calculates the number of qubits in the Hamiltonian.terms: dict[tuple[PauliOperator, ...], complex] Getter for the terms of the Hamiltonian.
Methods¶
add_term¶
def add_term(self, operators: tuple[PauliOperator, ...], coeff: float | complex)Adds a term to the Hamiltonian.
This method adds a product of Pauli operators with a given coefficient to the Hamiltonian. If the term already exists, the coefficients are summed.
Parameters:
| Name | Type | Description |
|---|---|---|
operators | Tuple[PauliOperator, ...] | A tuple of PauliOperators representing the term. |
coeff | Union[float, complex] | The coefficient of the term. |
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5)
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5j)
>>> print(H.terms)
{(X0, Y1): (0.5+0.5j)}copy¶
def copy(self) -> HamiltonianReturn an independent copy sharing no mutable state with self.
Produces a new Hamiltonian with the same terms, constant,
and declared _num_qubits. The underlying _terms dict
is fresh, so subsequent add_term / constant mutations
on either instance do not affect the other. PauliOperator
instances inside the term tuples are reused — they are
dataclass(frozen=True) values and safely shared.
Returns:
Hamiltonian — A shallow-cloned Hamiltonian instance.
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.Z, 0),), 1.0)
>>> H2 = H.copy()
>>> H2.add_term((PauliOperator(Pauli.X, 1),), 0.5)
>>> H.num_qubits # unchanged by H2's mutation
1identity¶
@classmethod
def identity(
cls,
coeff: float | complex = 1.0,
num_qubits: int | None = None,
) -> HamiltonianCreate a scalar times identity Hamiltonian.
remap_qubits¶
def remap_qubits(self, qubit_map: dict[int, int]) -> HamiltonianRemap qubit indices according to the given mapping.
This is used to translate Pauli indices (logical indices within an expval call) to physical qubit indices in the actual quantum circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
qubit_map | dict[int, int] | Mapping from logical index to physical index. e.g., {0: 5, 1: 3} maps logical index 0 → physical qubit 5 |
Returns:
Hamiltonian — New Hamiltonian with remapped qubit indices.
single_pauli¶
@classmethod
def single_pauli(cls, pauli: Pauli, index: int, coeff: float | complex = 1.0) -> HamiltonianCreate a single Pauli term Hamiltonian.
to_latex¶
def to_latex(self) -> strConverts the Hamiltonian to a LaTeX representation.
This function does not add constant term when we show the Hamiltonian. This function does not add $ symbols.
Returns:
str —
A LaTeX representation of the Hamiltonian.
import qamomile.core.operator as qm_o
import IPython.display as ipd
h = qm_o.Hamiltonian()
h += -qm_o.X(0) * qm_o.Y(1) - 2.0 * qm_o.Z(0) * qm_o.Z(1)
# Show the Hamiltonian in LaTeX at Jupyter Notebook
ipd.display(ipd.Latex("$" + h.to_latex() + "$"))to_numpy¶
def to_numpy(self) -> np.ndarrayConvert the Hamiltonian to a dense NumPy matrix.
Qubit 0 is mapped to the least-significant bit of computational-basis
indices, matching :meth:qamomile.linalg.HermitianMatrix.to_hamiltonian.
The returned array has shape (2**n, 2**n) where n is
:attr:num_qubits.
zero¶
@classmethod
def zero(cls, num_qubits: int | None = None) -> HamiltonianCreate a zero Hamiltonian.
Pauli [source]¶
class Pauli(enum.Enum)Enum class for Pauli operators.
Attributes¶
IXYZ
PauliOperator [source]¶
class PauliOperatorRepresents a single Pauli operator acting on a specific qubit.
Frozen so that Hamiltonian.copy() can share term operator
references across the original and the copy without risk of one
side mutating an operator the other still observes. None of the
existing callers mutate pauli or index after construction,
so freezing is a no-op behaviourally but makes the immutability
claim that Hamiltonian.copy()'s docstring relies on real.
Example:
>>> X0 = PauliOperator(Pauli.X, 0)
>>> print(X0)
X0Constructor¶
def __init__(self, pauli: Pauli, index: int) -> NoneAttributes¶
index: intpauli: Pauli