Apply to my task
arXiv:2512.03272 ★ 82 Dec 2, 2025

Declarative Code Generation: When Symbolic Solvers Beat Chain-of-Thought

Key result

GPT-4o drops from 97% to 10% accuracy when a problem has millions of possible combinations. Logic puzzles, calculations with dozens of interdependent parameters, problems that require trying out options — the model starts hallucinating and contradicting itself. The reason: an LLM generates text token by token and can't backtrack. If it picks the wrong path, it keeps generating anyway, inventing facts to plug the logical holes. Symbolic solvers move the search for a solution out of text generation and into code: the model only translates the problem's conditions into Python or Prolog, and a library (SymPy for equations, Constraint for logic) systematically works through the options, backing up at dead ends. Accuracy on hard puzzles rises from 10% to 89%.

01

TL;DR

Symbolic solvers are a method where the LLM translates a problem into executable code (Python with libraries, or Prolog), and then a symbolic solver finds the answer. Instead of a long chain of thought, the model generates a structured program: each sentence of the problem is copied into a comment, followed by its formalization in code. The code runs, and the solver finds values that satisfy every condition.

Models handle simple problems just fine with CoT, but fall apart on problems with a huge search space. A 4×4 Zebra puzzle has millions of combinations — the model starts hallucinating, drawing contradictory conclusions, and skipping options. As difficulty grows, GPT-4o's accuracy drops from 97% (easy puzzles) to 10% (hard ones). The reason: CoT generates token by token with no backtracking mechanism — once the model picks the wrong path, it can't go back and try a different one.

Declarative code generation fixes this with two moves. First, it moves the search for a solution out of text generation and into a symbolic solver: the model only translates the conditions into a formal language, while a library (SymPy for equations, Constraint for logic) systematically works through the options with backtracking. Second, sentence-by-sentence translation: a dedicated one-shot example shows how to copy each sentence into a comment and immediately write the code for that sentence. That gives a precise formalization with no dropped conditions.

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

02

Method Blueprint

A single-step process in one prompt:

1. One-shot example: show how to translate a problem into declarative code
   Format: [problem sentence in a comment] → [code for that sentence]

2. Give your own problem → the model generates code in the same style

3. The code runs in a built-in interpreter (Code Interpreter in GPT-4)
   → the symbolic solver finds the answer

If the code has a syntax error, send the error back to the model and it fixes it (up to 10 attempts).

03

Example in Practice

Task: You're stress-testing a marketplace business idea. You need to work out unit economics with a pile of interdependent parameters: the platform fee depends on GMV, GMV depends on the number of sellers, the number of sellers depends on the marketing budget, but the marketing budget is capped by profit. A classic constraint satisfaction problem — lots of variables pulling on each other.

Prompt:

Here is an example of how to solve problems with interdependent parameters using Python and SymPy.

EXAMPLE:
Problem: Roger has 5 tennis balls. He buys 2 more cans of balls. Each can has 3 balls. How many balls does he have?

Code:
```python
from sympy import symbols, Eq, solve

# Roger has 5 tennis balls
initial_balls = 5

# He buys 2 more cans of balls. Each can has 3 balls
cans = 2
balls_per_can = 3
bought_balls = cans * balls_per_can

# How many balls does he have?
total = initial_balls + bought_balls
print(total)

Now solve my problem the same way:

The marketplace takes a 15% fee on GMV up to $500K/month, 12% on GMV of $500K–1M, and 10% above $1M. A seller's average order is $40, and each seller makes 50 sales/month. Acquiring one seller costs $100. The starting marketing budget is $6,000. At what fee and how many sellers do we turn a profit in the first month?


**Result:**

The model will generate Python code with a variable for each parameter and equations for the links between them. Code Interpreter runs the code — SymPy finds the values at which every condition holds. You get an exact calculation: how many sellers you need, what GMV will be, which fee tier applies, and what the profit comes out to.

## Why It Works

**An LLM generates text token by token and can't backtrack.** If, while solving a Zebra puzzle, the model assumed "a Norwegian lives in the first house" and 10 steps later that led to a contradiction, it can no longer go back and try "a Swede lives in the first house." The model keeps generating text linearly, often contradicting itself or inventing facts to "plug" a logical hole.

**LLMs are great at translating natural language into structured code.** Pretraining on millions of code examples gives the model a feel for how text maps to formal constructs. The declarative style (sentence → code) is even easier for the model than the imperative one — no need to invent an algorithm, just mirror the facts.

**The method uses the model for translation and the solver for search.** The model does what it's good at — turning text into code. The symbolic solver does what it's good at — systematic search with backtracking. When SymPy or the Constraint library hits a dead end, it automatically steps back and tries other variable values. That's a **mechanical** guarantee of exhaustive search, unlike probabilistic text generation.

**Control knobs:**

- **One-shot vs zero-shot:** Zero-shot gives you imperative code with gaps. One-shot with a declarative example dramatically improves quality — the model copies the "comment + code" pattern.

- **Number of retries on error:** Prolog needs more attempts (the model saw less of it in training); for Python 1-2 is enough. Cap the retries if you're saving tokens.

- **Library choice:** SymPy for numeric equations and algebra, Constraint for logic problems with discrete variables. You can specify explicitly which one to use.

## Prompt Template

Here is an example of how to solve problems with interdependent parameters using Python and {library}.

EXAMPLE: Problem: {a simple problem of the same type}

Code:

from {library} import ...

# {first sentence of the problem}
{code for the first sentence}

# {second sentence of the problem}
{code for the second sentence}

# {the problem's question}
{code that prints the answer}

Now solve my problem the same way:

{your problem}


**Where:**
- `{library}` — `sympy` for math equations, `constraint` for logic problems
- `{a simple problem of the same type}` — a toy example (like the tennis balls one above)
- `{your problem}` — your real problem

**Important:** In the example, every sentence of the problem must be copied into a comment, immediately followed by its code. Don't write abstract steps — copy the problem text verbatim.

🚀 **Quick start** — paste into the chat:

Here is a declarative code generation pattern for problems with interdependent parameters. Adapt it to my problem: {description of your problem}.

[paste the template above]


The LLM will ask about the problem type (equations or logic), ask for a simpler example for the one-shot, and clarify what the output should contain — because it needs to figure out which library to use and how to structure the code. It will take the "sentence → comment + code" pattern and apply it to your problem.

## Limitations

> ⚠️ **Implicit semantics:** If the rules are hidden in the meaning of words, the method fails. "The older brother is taller than the younger one" is easy to miss when translating to code, while CoT picks it up from context.

> ⚠️ **Simple problems:** On basic arithmetic, symbolic solvers **lose** to CoT. GPT-4o scored 95% on GSM8K with CoT and 90% with code. The overhead of generating and running code doesn't pay off.

> ⚠️ **Small models write poor code:** CodeLlama-13B scored 22% with CoT and 43% with code — better, but still weak. You need GPT-4o/Claude-class models for reliable generation.

> ⚠️ **Sensitivity to how the example is written:** If the one-shot example is written imperatively (with loops and conditionals) instead of declaratively, quality drops. Make sure the example is sentence-to-sentence.

## How They Tested It

The team tested the hypothesis on five datasets of different types. **Arithmetic:** GSM8K (grade-school math), GSM-Reversed (the same problem, but asking for an intermediate value instead of the answer), GSM-Hard (numbers swapped for huge ones — up to 7 digits). **Logical entailment:** EntailmentBank — you have to build an inference tree from facts to a hypothesis. **Constraint satisfaction:** ZebraLogic — puzzles from 2×2 to 6×6 houses with various attributes.

They compared three approaches: **CoT prompting** (ordinary reasoning), **zero-shot code** (just "solve it in Python"), and **one-shot declarative code** (with a sentence-to-sentence translation example). They tested on GPT-4o and the small CodeLlama-13B model, using greedy decoding for reproducibility.

**The key result turned out to be nonlinear:** On simple arithmetic (GSM8K), CoT wins — 94.6% vs 92.6% for code. On hard arithmetic (GSM-Hard with big numbers), code pulls ahead — 78% vs 69%. On **Zebra puzzles the gap is dramatic:** CoT solves 87-88% of easy puzzles, code solves 96-97%. On hard puzzles CoT gets 11-12%, code gets **62-72%**. 

The researchers dug deeper and found **three typical CoT errors on hard problems:** (1) **Partial deduction** — the model draws one conclusion where several are available, then gets stuck; (2) **Wrong deduction** — it generates a fact that contradicts the conditions to "force-fit" a solution; (3) **Misinterpretation** — it loses a condition while reading the problem.

Symbolic solvers don't make those mistakes — they mechanically check every option via backtracking. But they **require an exact formalization**, and if the model skipped an implicit rule while translating to code, the solver won't save you.

A curious finding: **even the small CodeLlama-13B with declarative prompting beat GPT-4o with CoT** on hard Zebra puzzles. 20% vs 11-12%. This shows the "formalize + run a solver" pattern can compensate for a model's weak reasoning.

## Adaptations and Extrapolations

### 🔧 Technique: imperative code → declarative code

If the model generates code with loops and conditionals instead of a direct translation, **explicitly ask for the declarative style:**

Don't write loops or conditionals. Copy each sentence of the problem into a comment, immediately followed by the code for that sentence. Use only variable and equation declarations.


This matters especially for Prolog — the model tends to generate redundant predicates if you don't steer it.

### 🔧 Extrapolation: a hybrid approach for mixed-nature problems

Some problems contain **both implicit semantics and constraint satisfaction**. For example: "Three friends are going to the movies. Jake doesn't like action movies. Mike won't go without Emma. Emma wants a comedy or a drama. What are the options?"

Ask the model to **first extract the constraints explicitly via CoT, then translate them into code:**

Step 1: List every constraint explicitly, interpreting the meaning of each sentence.

Step 2: Translate each constraint into Python code with the constraint library:

from constraint import Problem, AllDifferentConstraint

[code]

```

That way CoT handles the semantics and the solver handles the combinatorics.

04

Resources

When Do Symbolic Solvers Enhance Reasoning in Large Language Models? — Zhiyuan He (University College London), Dingmin Wang (University of Oxford). NeurIPS 2025 Workshop: Efficient Reasoning.

Datasets used: GSM8K, GSM-Reversed, GSM-Hard, EntailmentBank, ZebraLogic. Libraries: SymPy (symbolic math), python-constraint (constraint satisfaction), Prolog with clpr (constraint logic programming over reals).

Research digest

Key result

GPT-4o drops from 97% to 10% accuracy when a problem has millions of possible combinations. Logic puzzles, calculations with dozens of interdependent parameters, problems that require trying out options — the model starts hallucinating and contradicting itself. The reason: an LLM generates text token by token and can't backtrack. If it picks the wrong path, it keeps generating anyway, inventing facts to plug the logical holes. Symbolic solvers move the search for a solution out of text generation and into code: the model only translates the problem's conditions into Python or Prolog, and a library (SymPy for equations, Constraint for logic) systematically works through the options, backing up at dead ends. Accuracy on hard puzzles rises from 10% to 89%.

Principle

Don't make the model search for the solution through step-by-step reasoning (Chain-of-Thought) — hand the search off to a symbolic solver. The model translates the problem into structured code; the solver does the mechanical search. Format: copy each sentence of the problem into a comment, then write the code for that sentence. Declarative style — you just mirror the facts, you don't invent an algorithm. A dedicated example with a single problem (one-shot prompting) shows the "sentence → comment + code" pattern, and the model copies that structure onto your problem.

Why it works

LLMs are great at translating natural language into code (pretraining on millions of examples) but bad at searching through options in text generation. A symbolic solver has a built-in backtracking mechanism — when SymPy or the Constraint library hits a contradiction, it automatically rolls back and tries other variable values. That's a mechanical guarantee of exhaustive search versus probabilistic text generation. For 4×4 Zebra puzzles the search space is millions of combinations. CoT gives GPT-4o 10% accuracy; symbolic solvers give 89%. The paradox: on simple arithmetic (GSM8K), code loses to CoT — 90% vs 95%. The overhead of generating and running code doesn't pay off when the problem is trivial.

When to apply

Problems with a huge search space → logic puzzles (Zebra, sudoku), unit economics with 10+ interdependent parameters, constraint problems where many variables affect one another. Especially when plain CoT gives contradictory conclusions or hallucinations. NOT a fit for simple arithmetic or problems solvable in 2-3 steps — there CoT is faster and more accurate.

Mini recipe

1. Pick a library: SymPy for math equations and algebra, Constraint for logic problems with discrete variables (who lives where, what color the house is) 2. Build a template example: take a trivial problem of the same type (like "Roger has 5 balls"). Translate it into code declaratively: copy each sentence of the problem into a comment, followed by the code for that sentence. No loops or conditionals — just facts 3. Give the model the pattern: show the example, then your problem with the phrase "solve it the same way." The model will copy the sentence-by-sentence structure 4. Allow error fixing: if the code has a syntax error, send the error text back to the model and it will fix it (up to 10 attempts for Prolog, 1-2 for Python)

Examples

[BAD]: `Solve the logic puzzle: The Norwegian lives in the first house. The green house is to the right of the white one. Coffee is drunk in the green house... [20 conditions]. Who owns the zebra?` → the model will reason step by step via CoT, get tangled in contradictions, and hallucinate an answer [GOOD]: `Here is an example of how to solve logic puzzles using Python and the constraint library: EXAMPLE: Problem: Roger has 5 balls. He buys 2 cans of 3 balls each. How many balls does he have? Code: ```python from sympy import symbols, Eq, solve # Roger has 5 tennis balls initial = 5 # He buys 2 cans of 3 balls each cans = 2 balls_per_can = 3 bought = cans * balls_per_can # How many balls does he have? total = initial + bought print(total) ``` Now solve my problem the same way: [paste all 20 conditions of the zebra puzzle]` → the model translates each condition into a constraint, and the library finds the single solution that satisfies all of them

In plain words

In Plain Words: 2512.03272

In Plain Words

When Do Symbolic Solvers Enhance Reasoning inLargeLanguageModels?

LLMs choke on complex logic because they're doomed optimists who never look back. When an LLM solves a problem, it generates text token by token, in a straight line. If halfway through the model takes the wrong branch of reasoning, it can't hit Ctrl+Z, return to the fork, and try another path. Instead it frantically bends the answer to fit its own mistakes, spawning hallucinations and contradictions. What you get is confident nonsense that looks logical and crumbles at the first check.

It's like assembling a complicated IKEA wardrobe without instructions while super-gluing every piece in place. If you mixed up the left and right panels at the very start, you'll end up with "spare" bolts and just hammer them in so the thing stays upright. Symbolic solvers change the rules of the game: they turn the model from a hapless builder into an architect who only draws the blueprint, while a flawlessly precise algorithm does the actual "building."

The core idea: the model no longer tries to produce the answer as text. Instead, it translates the problem's conditions into executable code (Python or Prolog). Each sentence of the problem becomes a comment, with a strict math formula or logical constraint underneath. Then a symbolic solver like SymPy takes over. It doesn't guess — it mechanically works through the options, and when it hits a dead end it "rolls back" on its own and looks for another path. That gives you a rock-solid guarantee that the logic holds.

The method was tested on math puzzles, but it's a perfect fit for any business where everything hinges on a pile of variables. Picture unit economics: taxes depend on revenue, revenue depends on marketing, and marketing is capped by a budget that itself depends on profit. An ordinary LLM gets tangled in those links within three sentences. But make it dump those dependencies into code, and a symbolic solver will find the one correct set of numbers. SEO for meaning gives way to GEO for logic: what matters isn't "reasoning eloquently" but formalizing the rules precisely.

The bottom line: stop demanding the impossible from models — they're lousy mathematicians but excellent translators. Use the model as an interface between human language and code, and hand the grunt work of computation to classic algorithms. One good example in the prompt (one-shot), and the model starts producing clean scripts instead of dubious essays. Whoever grasps that AI is just the "head" and the "calculator" should be external stops getting garbage out.

ArXiv ID: 2512.03272 | Generated: 2026-01-02 17:02 | Nova Research

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on Declarative Code Generation: When Symbolic Solvers Beat Chain-of-Thought arXiv:2512.03272

Sign in to apply this study New accounts get 50 free credits.