Metadata-Version: 2.4
Name: daifreed
Version: 0.1.0
Summary: Compute Dai-Freed anomalies in particle physics (implementing arXiv:1808.00009)
Author: Chris Murphy
License-Expression: MIT
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: sympy>=1.9
Requires-Dist: mpmath>=1.2
Dynamic: license-file

# daifreed

A Python library to compute **Dai-Freed anomalies** in particle physics,
implementing the results of

> I. García-Etxebarria and M. Montero,
> *Dai-Freed anomalies in particle physics*, [arXiv:1808.00009](https://arxiv.org/abs/1808.00009).

Dai-Freed anomaly cancellation is a refinement of ordinary anomaly cancellation.
For a 4d fermion theory with symmetry group `G`, the anomaly is a homomorphism
`η : Ω₅^struct(BG) → U(1)`, and freedom requires `exp(2πi η_Y) = 1` on **every**
closed 5-manifold `Y` — not just mapping tori. The strategy (paper §2.2) is:

1. Compute the bordism group `Ω₅^struct(BG)`; if it vanishes there is no anomaly.
2. Otherwise, evaluate `η` on generators, via the Bahri–Gilkey eta-invariant
   formulas for lens spaces / spherical space forms, or the closed-form
   cancellation conditions derived from them.

## Installation
```bash
uv add daifreed
# or
pip install daifreed
```
or, install from the source code to add a new model or run tests:
```bash
git clone git@gitlab.com:chris-w-murphy/dai-freed.git
cd dai-freed/
# if you need to install `uv` run:
# curl -LsSf https://astral.sh/uv/install.sh | sh
uv sync --all-extras  # creates a venv
```

## What it computes

| Module                    | Contents                                                                                         |
|---------------------------|--------------------------------------------------------------------------------------------------|
| `daifreed.eta`            | Exact η-invariants of lens spaces (eqs. 2098, 2401) and spherical space forms (2071/2074)        |
| `daifreed.conditions`     | Closed-form conditions: `spin_zn` (2114–2116), `spinc_zn` (2422–2425), `local_u1`, `z3_triality` |
| `daifreed.bordism`        | `Ω_d(pt)` (Table 3132), `Ω_d^Spin(BG)` (Table 2941), and the AHSS for `BSU(n)`                   |
| `daifreed.topological_sc` | The `Z₄` / topological-superconductor mod-16 constraint                                          |
| `daifreed.ibanez_ross`    | Ibañez–Ross constraints and their comparison to Dai-Freed                                        |
| `daifreed.models`         | Ready-made spectra: Standard Model, MSSM, baryon triality, proton hexality                       |

Every η-invariant is returned as an **exact** `sympy.Rational` (the anomaly phase
is `exp(2πi η)`). The default SymPy backend is authoritative; an optional mpmath
fast path (`backend="mpmath"`) is available and agrees with it.

## Using it with your own model

The workflow is two steps: **(1) encode your spectrum, (2) call the checker that
matches your theory's spacetime structure and symmetry.**

**Step 1 — encode the spectrum.** A model is a `Spectrum` of chiral (right-moving
Weyl) `Fermion`s; each carries a dict of integer charges, a `multiplicity`
(identical copies), and a `spin` (`1/2` default, or `3/2` for a gravitino):

```python
from daifreed.spectrum import Fermion, Spectrum

model = Spectrum([
    Fermion({"q": 1, "Z5": 1}, multiplicity=2, name="psiA"),
    Fermion({"q": -1, "Z5": 4}, multiplicity=2, name="psiB"),
    Fermion({"q": 3, "Z5": 2}, name="psiC"),           # multiplicity defaults to 1
    Fermion({"q": -3, "Z5": 3}, name="psiD"),
])
```

Two helpers matter for realistic models:

- `spec.with_symmetry("X", fn)` — derive a charge from existing ones, e.g.
  `spec.with_symmetry("X", lambda f: -2*f.charges["Y"] + 5*f.charges["B-L"])`.
- `spec.scaled(k)` — replicate for `k` generations.

**Step 2 — call the checker for your setup.** Each returns a result that is truthy
when anomaly-free and carries `.residuals` (what must vanish):

| Your situation                                      | Call                                                           |
|-----------------------------------------------------|----------------------------------------------------------------|
| Discrete ℤₙ (n odd), Spin manifolds                 | `spin_zn(spec, n, label="Z5")`                                 |
| ℤ₃ specifically (proton triality, …)                | `z3_triality(spec, label="Z3")`                                |
| Discrete ℤₙ inside a U(1) / Spin^c                  | `spinc_zn(spec, n, s_label="Z5", q_label="q")`                 |
| Continuous U(1) (perturbative)                      | `local_u1(spec, label="q")`                                    |
| ℤ₄ / topological superconductor (Spin^{ℤ₄}, mod 16) | `topological_superconductor(spec, label="Z4")`                 |
| Mixed ℤ₄–gauge (S¹×S⁴)                              | `mixed_z4_gauge_anomaly(spec, "Z4", "index")`                  |
| Ibañez–Ross comparison                              | `ibanez_ross(spec, n, ...)` / `embeds_in_anomaly_free_u1(...)` |
| "Can this group even have an anomaly?"              | `omega_spin_BG("SU(5)", 5)`, `is_anomaly_free("Spin(10)")`     |

```python
from daifreed.conditions import spin_zn
r = spin_zn(model, 5, label="Z5")
r.is_free      # True -> anomaly-free  (bool(r) works too, so `if r: ...`)
r.residuals    # {'cubic (L^3(n))': 0, 'linear (K3xL^1(n))': 0}
```

Which checker you want is dictated by *what you gauged*: a plain Spin structure + a
discrete ℤₙ → `spin_zn`; a gauged U(1) (so spacetime is Spin^c) → `spinc_zn`; a ℤ₄
whose ℤ₂ is fermion parity (Spin^{ℤ₄}) → `topological_superconductor` (put a gravitino
in as `spin=Fraction(3, 2)`); a non-abelian gauge group → check `is_anomaly_free(...)`
first (a vanishing bordism group means no Dai-Freed anomaly at all).

If your case isn't covered by a canned checker, drop to the engine and evaluate `η`
directly on the relevant generator — e.g. a ℤₙ Spin fermion of charge `s` on the lens
space `L^k(n)` is `eta_spin_lens(s, n, k)`, a general spherical space form
`S^{2k-1}/τ(G)` is `eta_general(...)` — then require the spectrum sum to be
`≡ 0 (mod 1)`.

## Reproducing the paper

```python
from daifreed import models
from daifreed.bordism import is_anomaly_free
from daifreed.conditions import local_u1, z3_triality
from daifreed.topological_sc import topological_superconductor
from daifreed.eta import eta_spinc_lens
import sympy as sp

# --- The Standard Model and GUTs are Dai-Freed anomaly-free (§3.4) ----------
assert is_anomaly_free("SU(5)")     # Ω₅^Spin(BSU(5)) = 0
assert is_anomaly_free("Spin(10)")  # ... hence the SM (⊂ SU(5)) too

# X = -2Y + 5(B-L) is a local-anomaly-free U(1) (Σq = Σq³ = 0), which forces
# the number of fermions per generation to be a multiple of 16 (§4.3):
sm = models.standard_model(generations=1)
assert sm.total_multiplicity() == 16
assert local_u1(sm, "X").is_free

# --- Topological superconductor: 16 fermions ⇒ mod-16 anomaly-free ----------
assert topological_superconductor(sm, "Z4").is_free          # SM: 16 Majorana fermions
assert topological_superconductor(models.mssm(1), "Z4").is_free  # MSSM: 16+12+4=32

# --- Baryon triality has a mod-9 anomaly, needs 3 generations (§4.2) --------
assert not z3_triality(models.baryon_triality(1)).is_free     # one generation: anomalous
assert z3_triality(models.baryon_triality(3)).is_free         # three generations: OK

# --- η(L¹(n)) = -s/n mod 1  (Bahri-Gilkey, eq. 2466) ------------------------
assert eta_spinc_lens(2, 1, 5, 1) == sp.Rational(3, 5)        # = -2/5 mod 1
```

## Testing

```bash
uv run pytest
```

The suite reproduces each headline claim of the paper: SM/GUT anomaly-freedom,
the baryon-triality mod-9 anomaly and its 3-generation cancellation, the
Standard-Model / MSSM mod-16 count, the `η(L¹(n)) = -s/n` identity, the agreement
of the closed-form `spin_zn` conditions with the two bordism generators
`L³(n)` and `K3 × L¹(n)`, and the Ibañez–Ross counterexample (eq. 2498) that
satisfies Ibañez–Ross but fails the stronger Dai-Freed conditions.

## Scope

The library covers the exact η-invariant engine, the closed-form conditions, the
tabulated bordism groups, and a *documented* Atiyah–Hirzebruch computation for
`BSU(n)`. A fully general spectral-sequence engine (arbitrary `BG`) is out of
scope — those computations are done by hand in the paper.
