# \[ANN\] Paulimorphic.jl (v0.1.0): Pauli-operator algebra, fermion-to-qubit encodings, and more

**URL:** <https://discourse.julialang.org/t/ann-paulimorphic-jl-v0-1-0-pauli-operator-algebra-fermion-to-qubit-encodings-and-more/139410>\
**Category:** Package Announcements\
**Tags:** package, announcement, quantum, physics\
**Created:** [September 12, 2026, 4:00pm UTC](https://discourse.julialang.org/t/ann-paulimorphic-jl-v0-1-0-pauli-operator-algebra-fermion-to-qubit-encodings-and-more/139410 "2026-09-12T16:00:35Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![frankwswang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frankwswang/32/18561_2.png) [@frankwswang](https://discourse.julialang.org/u/frankwswang)\
**Post date:** [September 12, 2026, 4:00pm UTC](https://discourse.julialang.org/t/ann-paulimorphic-jl-v0-1-0-pauli-operator-algebra-fermion-to-qubit-encodings-and-more/139410/1 "2026-09-12T16:00:35Z")

</div>

I’m happy to announce [Paulimorphic.jl](https://github.com/frankwswang/Paulimorphic.jl), a package for **constructing** , **transforming** , and **analyzing** Pauli operators. The Julia ecosystem already has a few well-established packages built on Pauli operators, e.g., [PauliStrings.jl](https://paulistrings.org/stable/), [PauliPropagation.jl](https://sparqlesim.github.io/PauliPropagation.jl/stable/), and [QuantumClifford.jl](https://qc.quantumsavory.org/stable/). Their use cases are mostly operator dynamics, circuit simulation, and error correction. Paulimorphic instead focuses on **representational manipulation and structural analysis of Pauli operators themselves** : both as observables in their own right and as encodings of other quantum many-body systems. Particularly, Paulimorphic provides fermion-to-qubit encodings (Jordan–Wigner, parity, and Bravyi–Kitaev) alongside graph-theoretic analysis of operator anticommutation structure. In other words, the package is designed for investigating the polymorphic character of Pauli operators, hence _Pauli-morphic_.

The main design choice for Paulimorphic is: Pauli strings (`PauliStr`) are stored in a bit-packed symplectic representation that includes **their Pauli-group phases** , and every `PauliSum` is kept in a **deterministic canonical form** (phases absorbed into coefficients, duplicates merged, terms sorted, no exact-zero coefficients) upon construction. This canonical-form representation makes relational operations such as equality checks and hashing, as well as interoperability with other packages, predictable.

As of version 0.1.0, Paulimorphic supports the following main features:

- **Operator algebra:** sums, scalar and operator products, Hermitian adjoints, commutation and anticommutation evaluation.
- **Multi-level data manipulation:** stamping, shifting, and pasting single-site operators; reframing and truncating Pauli sums.
- **Frustration-graph analysis backed by lightweight graph tools:** connected components, BFS, isomorphism detection, line graphs, and root-graph reconstruction.
- **Fermion-to-qubit encodings** : in both Majorana and Dirac forms, with validity checkers. Spin-sectored encodings with selectable operator ordering of Molecular electronic Hamiltonians are also supported.

Aside from these features, Paulimorphic can also be used with other Julia packages as a flexible Pauli-operator constructor.

## Working with the rest of the ecosystem

Let’s first construct a simple transverse-field Ising chain Hamiltonian

H = -J \sum\_{i=1}^{n-1} Z\_i Z\_{i+1} - h \sum\_{i=1}^{n} X\_i

as a `PauliSum` (assigned to `H`):

```julia
using Paulimorphic

n, J, h = 8, 1.0, 0.5

zz = [stamp!(PauliStr(n), i, symZ, 2) for i in 1:n-1] # ZᵢZᵢ₊₁
xs = [stamp!(PauliStr(n), i, symX) for i in 1:n] # Xᵢ
H = PauliSum([zz; xs], [fill(-J, n-1); fill(-h, n)]) # Canonical-form `PauliSum`

```

Then, handling the constructed objects in relevant packages takes only a few lines.

### Measurement grouping with [Graphs.jl](https://github.com/JuliaGraphs/Graphs.jl)

`getFrustrationInfo` returns the anticommutation (frustration) graph as a `Pair` of vertices and one-based edge index pairs, which can be used to directly construct a `Graphs.SimpleGraph`. A proper coloring of this graph partitions the Hamiltonian into mutually commuting groups:

```julia
using Graphs: SimpleGraph, add_edge!, greedy_color

terms, edges = getFrustrationInfo(H) # vertices => anticommuting pairs

g = SimpleGraph(length(terms))
for (i, j) in edges
    add_edge!(g, i, j)
end

coloring = greedy_color(g)
groups = [terms[coloring.colors .== c] for c in 1:coloring.num_colors]

```

### Operator dynamics with [PauliStrings.jl](https://github.com/nicolasloizeau/PauliStrings.jl)

Since a canonical `PauliSum` has already absorbed all phases into its coefficients, each string it holds forms a one-to-one mapping to a `PauliStrings.Operator`. Therefore, a Lanczos algorithm is immediately available:

```julia
import PauliStrings as PS

function to_ps_operator(h::PauliSum)
    op = PS.Operator(countSites(h))
    for (str, c) in collectTerms(h)
        op += c, replace(toString(str, denseString=true), 'I' => '1')
    end
    op
end

O = PauliSum([stamp!(PauliStr(n), i, symX) for i in 1:n], fill(1.0, n)) # Σᵢ Xᵢ
bs = PS.lanczos(to_ps_operator(H), to_ps_operator(O), 10, 2^12)

```

### Expectation-value estimation with [PauliPropagation.jl](https://github.com/MSRudolph/PauliPropagation.jl)

Similarly, `Paulimorphic.PauliSum` can be easily converted to `PauliPropagation.PauliSum`, which can then be propagated through a parametrized quantum circuit to evaluate its energy expectation value in the Heisenberg picture:

```julia
import PauliPropagation as PP

function to_pp_sum(h::PauliSum)
    nq = countSites(h)
    strs = map(collectTerms(h)) do (str, c)
        syms = Symbol.(collect(toString(str, denseString=true)))
        PP.PauliString(nq, syms, 1:nq, real(c))
    end
    PP.PauliSum(strs)
end

circuit = PP.hardwareefficientcircuit(n, 2)
thetas = 0.1 .* randn(PP.countparameters(circuit))
prop = PP.propagate(circuit, to_pp_sum(H), thetas)
energy = PP.overlapwithzero(prop)

```

## Moving forward

This is only the first release of the package, but I would appreciate feedback on the operator-algebra interface and any suggestions for additional functionality. I’m curious about what scenarios others may find structural analyses of Pauli operators useful for. Issues are welcome!

---

<div class="post-metadata">

**Author:** ![kahliburke](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kahliburke/32/208472_2.png) [@kahliburke](https://discourse.julialang.org/u/kahliburke)\
**Post date:** [September 13, 2026, 11:09am UTC](https://discourse.julialang.org/t/ann-paulimorphic-jl-v0-1-0-pauli-operator-algebra-fermion-to-qubit-encodings-and-more/139410/2 "2026-09-13T11:09:47Z")

</div>

Nice package … buuuudddy!

![weasel-paulyshore](https://global.discourse-cdn.com/julialang/original/3X/a/6/a695194ca7d44b6f7e49aa7864026e47cfec3c4a.gif)
