Skip to content

Add representation-independent PauliString class#37

Open
AlbertLee125 wants to merge 6 commits into
mainfrom
Pauli_String
Open

Add representation-independent PauliString class#37
AlbertLee125 wants to merge 6 commits into
mainfrom
Pauli_String

Conversation

@AlbertLee125

Copy link
Copy Markdown
Collaborator

Summary

This PR introduces a representation-independent PauliString class and integrates it into the Python Hamiltonian implementation.

Changes to common/pauli_string.py

  • Added an immutable and hashable PauliString value type.
  • Added construction from dense strings and sparse representations.
  • Added conversion to dense strings, sparse tuples, and sparse dictionaries.
  • Added validation for operators, qubit indices, duplicate indices, and qubit counts.
  • Canonicalized sparse operators by sorting indices and removing identity entries.
  • Added readable str and repr output.

Changes to analysis/hamiltonian.py

  • Updated conversion helpers to delegate to PauliString.
  • Changed LinearCombinationOfPauliStrings to store canonical PauliString keys internally.
  • Added validation for dense-string lengths and input formats.
  • Combined coefficients for equivalent sparse Pauli strings.
  • Updated dense and sparse getters to convert from the canonical representation.
  • Updated energy shifting to use a canonical identity PauliString.
  • Added return_as="objects" to Hamiltonian.get_all_pauli_strings().
  • Preserved the existing string and tuple APIs for backward compatibility.

Issue

Closes #36: Create Pauli string class.

This centralizes Pauli-string conversion and validation while reducing the need for callers to track the active representation manually.

Testing

  • 375 Python tests passed.
  • Added tests for construction, conversion, validation, hashing, canonicalization, printing, and Hamiltonian integration.
  • Julia was not changed or tested.

Copilot AI review requested due to automatic review settings June 21, 2026 05:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a representation-independent PauliString value type and updates the Python Hamiltonian implementation to use canonical PauliString keys internally, while preserving existing dense-string and sparse-tuple public APIs.

Changes:

  • Introduces qhat.common.pauli_string.PauliString with dense/sparse construction, conversion, validation, and canonicalization.
  • Refactors LinearCombinationOfPauliStrings and Hamiltonian.get_all_pauli_strings() to store/return canonical PauliString objects (with a new return_as="objects" option).
  • Expands test coverage for PauliString behavior and Hamiltonian integration (including combining equivalent sparse keys).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
common/pauli_string.py Adds the new immutable, hashable PauliString class with canonical sparse storage and conversions.
common/tests/test_pauli_string.py Adds unit tests for PauliString construction, conversions, validation, hashing, and canonicalization.
analysis/hamiltonian.py Refactors Pauli conversion helpers and Hamiltonian/LCPS internals to use canonical PauliString keys; adds return_as="objects".
analysis/tests/test_pauli_hamiltonian.py Updates and adds tests for new canonicalization behavior and return_as="objects" API.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread analysis/hamiltonian.py Outdated
Comment on lines +49 to +52
try:
return PauliString.from_dense(dense_pauli).to_sparse()
except ValueError as exc:
raise ValueError(f"Invalid character in dense pauli string: \"{dense_pauli}\".") from exc
Comment thread common/pauli_string.py
num_qubits = _validate_num_qubits(num_qubits)
return cls(
num_qubits=num_qubits,
_operators=_normalize_sparse(operators, num_qubits),

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonblocking: from_sparse() validates and normalizes here, then __post_init__() repeats both operations on the resulting tuple. LinearCombinationOfPauliStrings invokes this path for every sparse term, so large Hamiltonian loads do twice the validation and sorting work. Consider letting __post_init__() normalize the raw input once, or adding a private constructor for already-normalized data.

Comment thread common/pauli_string.py
return self.to_dense()

def __repr__(self) -> str:
return f"PauliString.from_dense({self.to_dense()!r})"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonblocking: These user-facing string representations are new behavior, and dictionaries display PauliString keys through __repr__, but the tests do not assert either method. Add focused assertions for str() and repr() so accidental output changes are caught.

Comment thread analysis/hamiltonian.py
# -- If return_as == "strings": The Pauli string is encoded as a character string, where
# each character is a Pauli matrix, explicitly including identity entries. For example,
# assuming 6 qubits, "XIIZII".
# -- If return_as == "objects": Keys are immutable PauliString instances that can provide

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonblocking: return_as="objects" and PauliString add public API surface, but neither analysis/README.md nor common/README.md explains how to import, construct, convert, or request these objects. Add a short usage example so users can discover the representation-independent path without reading implementation comments.

@AlbertLee125 AlbertLee125 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

  1. Blocking issues: None.
  2. Nonblocking issues: Avoid duplicate sparse normalization; add coverage for the new string representations; document the new PauliString and return_as="objects" API.
  3. Questions: None.
  4. Tests run and outcomes: 62 targeted tests passed; the documented common suite passed (171); the documented analysis suite passed (204, with one pre-existing PytestReturnNotNoneWarning); exhaustive dense/sparse round trips through four qubits, pickle, sparse permutation invariance, InteractionOperator conversions, and canonical LCPS output checks passed. All current GitHub Actions jobs also pass.
  5. Merge recommendation: Merge-ready; the inline items are nonblocking. GitHub does not allow the PR author account to submit APPROVE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create Pauli string class

2 participants