Automatic exam and solution generation for engineering courses
Writing exams by hand in LaTeX is tedious and error-prone — copy formulas, plug in numbers, hope you didn't make a sign error in the solution, and repeat. ExamEngineer eliminates that entire class of mistakes. You write each equation once; the system computes numeric results, converts units, and typesets both the exam paper and the matching solution booklet automatically.
Built for day-to-day use at Technische Hochschule Deggendorf. In production use across multiple engineering modules in Mechanical Engineering & Mechatronics.





Problem library — browse and search problems by tag, topic, or keyword; each card shows credits, language, and quick-preview
problem.yaml ─┐ problem.yaml ─┤──▶ Python pipeline ──▶ exam.tex ──▶ exam.pdf exam.yaml ─┘ (SymPy + Pint) solution.tex ──▶ solution.pdf
Problems are defined as YAML files with typed content modules — variables, equations, display instructions, images, plots. An exam YAML simply lists which problems to include and sets header metadata. The Python pipeline loads everything, solves the equations symbolically, renders LaTeX via Jinja2 templates, and compiles to PDF with LuaLaTeX. One source, two outputs, zero manual arithmetic.
id: "impedance_001" title: "AC Circuit Impedance" language: "de" modules: - type: variables variables: R: { value: "10 ohm" } C: { value: "47 uF" } f: { value: "50 Hz" } - type: question credits: 3 question: "Calculate the impedance $Z$." modules: - type: unknowns unknowns: Z: { unit: "ohm" } - type: equation equation: "Z = R + 1/(j*2*pi*f*C)" show: solution # only appears in solution booklet
The system computes Z, formats it as a complex number with units, and places the full solution step in the solution booklet while showing only the question in the exam version.
Automatic solution generation
Equations are solved symbolically with SymPy and evaluated with full unit tracking via Pint. No manual calculations, no transcription errors. The same equation definition produces both the exam question and the worked solution.
Exam randomization
Define value ranges for each variable and constraints on computed results. The system generates valid random instances via rejection sampling — every student can receive a unique exam with guaranteed solvable, realistic numbers.
Reusable problem library
Problems are YAML building blocks. Once written, they can be dropped into any future exam. Variable values can be overridden per exam without modifying the original problem. The library grows with every semester.
Composable content modules
Each problem is assembled from typed modules: text, equations, variables, unknowns, images, function plots (pgfplots), code listings (minted), and raw LaTeX. No LaTeX knowledge required for everyday authoring.
Web-based frontend
All functions are available through a browser-based frontend — create and edit problems and exams, browse and search the library, and trigger PDF builds without touching the command line. A schema-assisted problem editor guides authoring and catches errors early. Problems and exams can be previewed as PDF directly in the browser before publishing. Built with Flask and HTMX.
Correction assistant
A grading helper lets instructors enter student results and pin wrong intermediate values. Downstream results recalculate automatically, making partial-credit grading faster and more consistent.
Incremental builds & validation
A Make-based build system only recompiles exams whose dependencies have changed. YAML inputs are validated against JSON schemas before processing — errors surface as plain-language messages, not Python tracebacks.
Multi-language & accessible typography
German and English, with locale-aware number formatting. Body text in Atkinson Hyperlegible Next and formulas in IBM Plex Math — optimized for readability under exam conditions.
| Component | Role |
|---|---|
| Python 3.12 | Core pipeline, symbolic computation (SymPy), unit handling (Pint), templating (Jinja2) |
| LuaLaTeX | PDF compilation via fontspec, minted (code), pgfplots (function plots) |
| Flask + HTMX | Web frontend for problem and exam authoring, library management, schema-assisted editing, PDF preview, and build triggering |
| JSON Schema | Validation of all YAML inputs before processing |
| GNU Make | Incremental, dependency-tracked builds with parallel compilation support |
In production use for multiple engineering modules at THD — Electrical Engineering, Mechatronics, and Mechanical Engineering. The problem library is continuously growing as legacy exams are migrated to the YAML format. ExamEngineer is being prepared for open-source release. If you teach engineering courses at a university and are looking for a better way to manage exams, I'd love to hear from you — early adopters who can bring additional problem types and field experience are especially welcome.
If you'd like to use ExamEngineer in your own courses or institution, I'm happy to help get you started.
Get in touch