# Compare formulas

Use equiv-profile normalization for cheap spelling comparison, and a CAS for true mathematical equivalence.

https://texform.dev/docs/compare-formulas

> **TeXForm handles spelling, not mathematics**
>
> TeXForm's role in formula comparison is the normalization layer, not the equivalence engine. It canonicalizes how a formula is written and stops there. Deciding whether two formulas are mathematically equal is a job for a computer algebra system, and layer 2 below shows how to hand off to one.

Comparing two LaTeX formulas usually means one of two different questions, and it helps to separate them. The cheap question is whether two formulas are the same up to spelling — `\cfrac{a}{b}` and `\frac{a}{b}` denote the same fraction written two ways. The expensive question is whether two formulas are mathematically equal — `x + x` and `2x` are equal but structurally different. TeXForm answers the first directly and is deliberately not in the business of answering the second.

**Layer 1 — spelling equality via the `equiv` profile.** Normalize both formulas under the `equiv` profile and compare the resulting strings. This profile canonicalizes equivalent spellings hard enough that surface differences collapse, so a string comparison resolves them with no extra dependencies.

**Python**

```python
import texform

equiv = texform.TransformEngine(profile="equiv")
corpus = texform.TransformEngine(profile="corpus")

def same_form(engine, a, b):
    return engine.normalize(a) == engine.normalize(b)

for a, b in [(r"\cfrac{a}{b}", r"\frac{a}{b}"), (r"\widehat{x}", r"\hat{x}"), (r"x + x", r"2x")]:
    print(f"{a!r:16} vs {b!r:14} equiv={same_form(equiv, a, b)} corpus={same_form(corpus, a, b)}")
```

```text
'\\cfrac{a}{b}'  vs '\\frac{a}{b}' equiv=True corpus=False
'\\widehat{x}'   vs '\\hat{x}'     equiv=True corpus=False
'x + x'          vs '2x'           equiv=False corpus=False
```

**JavaScript**

```js
import { TransformEngine } from 'texform';

const equiv = new TransformEngine({ profile: 'equiv' });
const corpus = new TransformEngine({ profile: 'corpus' });

const sameForm = (engine, a, b) =>
  engine.normalize(a) === engine.normalize(b);

for (const [a, b] of [['\\cfrac{a}{b}', '\\frac{a}{b}'], ['\\widehat{x}', '\\hat{x}'], ['x + x', '2x']]) {
  console.log(a, 'vs', b, 'equiv =', sameForm(equiv, a, b), 'corpus =', sameForm(corpus, a, b));
}
```

The `corpus` column is why `equiv` exists. `\cfrac` and `\widehat` are notation choices a training label should keep — `corpus` preserves the continued-fraction styling and the wide hat, so the two spellings stay distinct there. `equiv` deliberately discards that distinction (`ams/cfrac-to-frac` and `base/widehat-to-hat` are the rules doing it) because a comparison key should not care how wide the hat was.

The third row states the other boundary just as plainly: `x + x` and `2x` do not compare equal, because `equiv` normalizes form, not meaning. It never performs algebra — it will not factor, expand, or evaluate. Treat layer 1 as a fast, zero-dependency filter that resolves spelling differences and nothing more, and reach for `equiv` output as a comparison key or fingerprint rather than as a label you would show a reader.

**Layer 2 — mathematical equivalence via a CAS.** For the cases layer 1 reports as different, hand the normalized strings to a computer algebra system. The snippet below sketches the hookup with SymPy; a math-recognition evaluation harness such as Math-Verify wraps the same idea with parsing and timeout handling built in.

```python
# Illustrative — requires `pip install sympy antlr4-python3-runtime`.
import texform
from sympy.parsing.latex import parse_latex

engine = texform.TransformEngine(profile="equiv")

def math_equal(a, b):
    expr_a = parse_latex(engine.normalize(a))
    expr_b = parse_latex(engine.normalize(b))
    return (expr_a - expr_b).simplify() == 0

# math_equal(r"x + x", r"2x")  ->  True
```

Normalizing with `equiv` first does real work for the CAS: it removes the spelling variation a LaTeX parser would otherwise choke on, so the CAS only has to reason about genuine mathematical difference. For how the `equiv` profile canonicalizes and why it stops short of mathematical reasoning, see [Transforms](https://texform.dev/docs/transforms). For how this compares with string normalizers used in answer grading, see [How TeXForm compares](https://texform.dev/docs/comparison).

## Next steps [#next-steps]

- [Transforms](https://texform.dev/docs/transforms) — What each profile canonicalizes, and the rule levels behind the equiv target.

- [Rule reference](https://texform.dev/rules) — Every rule the equiv profile adds, with its level and fidelity.

- [Normalize a corpus](https://texform.dev/docs/normalize-a-corpus) — Apply one engine across a dataset when you are deduplicating at scale.

