Skip to the content.

ParSub - Agentic Math/Physics Research Tool

Tests PyPI Docker image Python License: MIT

ParSub Logo

ParSub reads the mathematics in a LaTeX document, works out what can be computed from it, and writes a ready-to-run Python script that evaluates, plots, solves, optimizes, integrates, differentiates or numerically verifies every formula it understands — producing publication-quality plots and data files.

paper.tex ──parse──► expressions ──analyze──► tasks ──generate──► generated_computation.py ──run──► plots/ + data/

🔬 Features

📦 Installation

Requires Python 3.9 or newer.

pip install parsub

From source (for development):

git clone https://github.com/PSubrat29/parsub.git
cd parsub
pip install -e ".[dev]"     # includes the test tools

🚀 Quick Start

Command line

# Try the built-in projectile-motion demo (analyze + run)
parsub demo --run

# Analyze a LaTeX file, then run the generated code
parsub analyze examples/projectile.tex --output-dir ./results
parsub run ./results/generated_computation.py

# ...or both in one step
parsub analyze examples/sample.tex -o ./results --run

parsub --help lists all commands and options (analyze, run, demo, version).

Python API

import parsub

# One call: parse, analyze and write generated_computation.py + analysis.json
result = parsub.analyze_latex(r"We plot $y = \sin(x) e^{-x/5}$", output_dir="./output")
for task in result.tasks:
    print(task["goal_type"], "-", task["description"])

# Run the generated script (results go next to it: ./output/plots and ./output/data)
process = parsub.run_generated_code(result.code_path)
print(process.stdout)

The individual stages are available too:

from parsub.parser.latex_parser import parse_latex_source
from parsub.analyzer.expression_analyzer import analyze_expressions
from parsub.generator.code_generator import generate_code_from_tasks

parsed = parse_latex_source(open("paper.tex", encoding="utf-8").read())
tasks = analyze_expressions(parsed["expressions"], {
    "goals": parsed["goals"],
    "methods": parsed["methods"],
    "assignments": parsed["assignments"],
})
code_file = generate_code_from_tasks(tasks, "./output")

REST API

parsub-api                                   # http://127.0.0.1:8000 (interactive docs at /docs)
# or: uvicorn parsub.api.main:app --host 0.0.0.0 --port 8000

curl -X POST http://127.0.0.1:8000/analyze \
  -H "Content-Type: application/json" \
  -d '{"latex_source": "\\begin{equation} E = mc^2 \\end{equation}", "output_dir": "api_results"}'

curl -X POST http://127.0.0.1:8000/run \
  -H "Content-Type: application/json" \
  -d '{"code_path": "api_results/generated_computation.py"}'

Endpoints: POST /analyze, POST /upload, POST /run, GET /execute/{path}, GET /download/{path}, GET /health. All files live inside one output root (PARSUB_OUTPUT_ROOT, default ./output); paths outside it are rejected.

Docker

The REST API is available as a ready-made image (no Python installation needed):

docker run -d --name parsub -p 8000:8000 -v parsub-data:/data ghcr.io/psubrat29/parsub:latest

Open http://localhost:8000/ for the interactive API documentation. Image tags, Docker Compose, configuration and where results are kept are described on the Docker page.

📊 Output

output/
├── generated_computation.py     # the generated, editable Python script
├── analysis.json                # what was extracted and why each task was chosen
├── plots/
│   ├── task_1_plot.png          # 1-D plots
│   ├── task_2_surface_plot.png  # 2-D surface plots
│   └── task_3_verification_plot.png
└── data/
    ├── task_1_plot_data.csv     # numerical data
    ├── task_3_verification.json # results (roots, extrema, integrals, identity checks, ...)
    └── summary.json             # status of every task

The generated script accepts --output-dir DIR, --timeout SECONDS (per task) and --tasks 1,3.

📚 Documentation

✅ Validation on a real paper

examples/sample.tex is a research note on generalized Bessel functions with 25 numbered equations. Running

parsub analyze examples/sample.tex -o results --run

converts every numbered equation except the generic definition (4) and runs 28 computations in about 90 seconds. Of the 22 numerical checks, 19 confirm the paper’s identities. Among them: the Gamma integral, both Beta-function forms, Kummer’s second transformation, the claim that the series (9) solves the differential equation (8), and every alternative form of w_α(z) and of the Bessel-Clifford function. The remaining three flag real problems:

Equation ParSub’s verdict Explanation
(6) does not hold Kummer’s first formula is misprinted; it should read ₁F₁(ε; ϱ; z) = eᶻ ₁F₁(ϱ−ε; ϱ; −z)
(22) does not hold the Laguerre index should be L_k^{(ϑ)}, not L_k^{(ϑ−1)} (equation (23) is correct)
w_α(0) = 0 holds except at α = 0 true for Re α > 0 only

Each finding was confirmed independently with mpmath. Details are in the validation report.

🧪 Running Tests

pip install -e ".[dev]"
pytest                      # all tests
pytest --cov=parsub         # with coverage
pytest tests/test_parser.py # one module

🔒 Privacy & Security

🛠️ Architecture

src/parsub/
├── parser/      # LaTeX walking (pylatexenc) and LaTeX → SymPy conversion
├── analyzer/    # goal detection, variable roles, sampling strategy
├── generator/   # code generation + runtime helpers embedded in generated scripts
├── core/        # shared parameter knowledge and the end-to-end pipeline
├── cli/         # `parsub` command (Typer + Rich)
└── api/         # REST API (FastAPI)

🤝 Contributing

Contributions are welcome! See CONTRIBUTING.md.

📄 License

ParSub is released under the MIT License. See LICENSE.

🙏 Acknowledgements


ParSub - Turning LaTeX mathematics into computational insights, automatically.