Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

qamomile.observable

Overview

FunctionDescription
XCreates a Pauli X operator for a specified qubit.
YCreates a Pauli Y operator for a specified qubit.
ZCreates a Pauli Z operator for a specified qubit.
commutatorCompute the commutator [A, B] = A B - B A of two Hamiltonians.
ClassDescription
HamiltonianRepresents a quantum Hamiltonian as a sum of Pauli operator products.
PauliEnum class for Pauli operators.
PauliOperatorRepresents a single Pauli operator acting on a specific qubit.

Constants

Functions

X [source]

def X(index: int) -> Hamiltonian

Creates a Pauli X operator for a specified qubit.

Parameters:

NameTypeDescription
indexintThe 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) -> Hamiltonian

Creates a Pauli Y operator for a specified qubit.

Parameters:

NameTypeDescription
indexintThe 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) -> Hamiltonian

Creates a Pauli Z operator for a specified qubit.

Parameters:

NameTypeDescription
indexintThe 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) -> Hamiltonian

Compute 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:

NameTypeDescription
aHamiltonianThe left operand of the commutator.
bHamiltonianThe 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 Hamiltonian

Represents 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) -> None
Attributes
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:

NameTypeDescription
operatorsTuple[PauliOperator, ...]A tuple of PauliOperators representing the term.
coeffUnion[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) -> Hamiltonian

Return 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
1
identity
@classmethod
def identity(
    cls,
    coeff: float | complex = 1.0,
    num_qubits: int | None = None,
) -> Hamiltonian

Create a scalar times identity Hamiltonian.

remap_qubits
def remap_qubits(self, qubit_map: dict[int, int]) -> Hamiltonian

Remap 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:

NameTypeDescription
qubit_mapdict[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) -> Hamiltonian

Create a single Pauli term Hamiltonian.

to_latex
def to_latex(self) -> str

Converts 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.ndarray

Convert 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) -> Hamiltonian

Create a zero Hamiltonian.


Pauli [source]

class Pauli(enum.Enum)

Enum class for Pauli operators.

Attributes

PauliOperator [source]

class PauliOperator

Represents 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)
X0
Constructor
def __init__(self, pauli: Pauli, index: int) -> None
Attributes

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:

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:

Overview

FunctionDescription
XCreates a Pauli X operator for a specified qubit.
YCreates a Pauli Y operator for a specified qubit.
ZCreates a Pauli Z operator for a specified qubit.
commutatorCompute the commutator [A, B] = A B - B A of two Hamiltonians.
multiply_pauli_same_qubitMultiplies two Pauli operators acting on the same qubit.
simplify_pauliop_termsSimplifies a tuple of Pauli operators by combining operators acting on the same qubit.
ClassDescription
HamiltonianRepresents a quantum Hamiltonian as a sum of Pauli operator products.
PauliEnum class for Pauli operators.
PauliOperatorRepresents a single Pauli operator acting on a specific qubit.

Constants

Functions

X [source]
def X(index: int) -> Hamiltonian

Creates a Pauli X operator for a specified qubit.

Parameters:

NameTypeDescription
indexintThe 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) -> Hamiltonian

Creates a Pauli Y operator for a specified qubit.

Parameters:

NameTypeDescription
indexintThe 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) -> Hamiltonian

Creates a Pauli Z operator for a specified qubit.

Parameters:

NameTypeDescription
indexintThe 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) -> Hamiltonian

Compute 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:

NameTypeDescription
aHamiltonianThe left operand of the commutator.
bHamiltonianThe 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:

NameTypeDescription
pauli1PauliOperatorThe first Pauli operator.
pauli2PauliOperatorThe second Pauli operator.

Returns:

tuple[PauliOperator, complex] — tuple[PauliOperator, complex]: A tuple containing the resulting Pauli operator and the complex coefficient.

Raises:

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:

  1. Multiplying Pauli operators on the same qubit using the Pauli algebra

  2. Removing identity operators from the result

  3. Tracking the accumulated phase factor from the multiplications

Parameters:

NameTypeDescription
termtuple[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 Hamiltonian

Represents 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) -> None
Attributes
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:

NameTypeDescription
operatorsTuple[PauliOperator, ...]A tuple of PauliOperators representing the term.
coeffUnion[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) -> Hamiltonian

Return 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
1
identity
@classmethod
def identity(
    cls,
    coeff: float | complex = 1.0,
    num_qubits: int | None = None,
) -> Hamiltonian

Create a scalar times identity Hamiltonian.

remap_qubits
def remap_qubits(self, qubit_map: dict[int, int]) -> Hamiltonian

Remap 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:

NameTypeDescription
qubit_mapdict[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) -> Hamiltonian

Create a single Pauli term Hamiltonian.

to_latex
def to_latex(self) -> str

Converts 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.ndarray

Convert 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) -> Hamiltonian

Create a zero Hamiltonian.


Pauli [source]
class Pauli(enum.Enum)

Enum class for Pauli operators.

Attributes

PauliOperator [source]
class PauliOperator

Represents 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)
X0
Constructor
def __init__(self, pauli: Pauli, index: int) -> None
Attributes