1. Home
  2. Advanced Tools
  3. How the Solver Works
  1. Home
  2. Experimental Info - Recipes
  3. How the Solver Works

How the Solver Works

Uncountable’s Solver feature is a constraint optimization tool that adjusts ingredient amounts to satisfy one or more locked targets.

This article provides a high-level technical explanation of how the Solver interprets calculations, locks, and ingredient amounts, and why it behaves the way it does.


Solver-Compatible Calculations

The Solver only works with input calculations that follow a predictable, differentiable structure. These include:

  1. Weighted Sum / Weighted Average calculations
  2. Composite calculations (built only from weighted sums)

These calculation types behave linearly with respect to ingredient amounts, which allows the Solver to determine how changing each ingredient affects the final calculation.

If a calculation shows a lock icon in Solve Mode, it is Solver-compatible. If no lock appears, the Solver cannot use that calculation as a constraint.

Additionally, in the Edit Calculations modal, a green f(x) in the top right corner indicates a Solver compatible calculation and a red f(x) indicates a non-Solver compatible calculation.

Solver-compatible calculation (Weighted Sum)

Why only these types?

Because they create mathematical expressions with a clear relationship between ingredient amounts and the calculated value. This allows the Solver to compute how to adjust ingredients to reach a target.


Locked Calculations Become Constraints

When you type a new value into a calculation and lock it, you are adding a precise mathematical condition: “This calculation must equal this target value in the final recipe.”

Locked calculation on the recipe grid and in the Solver/Locks sidepanel

A locked calculation does not have to be an exact equality, either. As covered in Solver, you can lock a directional (fixed range) constraint instead—a minimum, a maximum, or a fixed range between two bounds—which the Solver treats as an inequality rather than a strict equality.

Decision Variables

Behind the scenes, the Solver builds a single vector of decision variables. Each variable represents either:

  • An unlocked ingredient quantity within a recipe step
  • A step-to-step relationship quantity, when the recipe workflow includes intermediate or multi-step relationships that can vary

Locked ingredients, fixed relationship quantities, and blank ingredient values are not treated as adjustable decision variables.


Column Calculations as Constraints

Column calculations represent ingredient-level contributions. When locked, they act as constraints for the overall solve.

  • Locking column values creates a constraint requiring all those row values to match their locked targets.
  • When locked, one constraint per ingredient row is added.
  • Column constraints combine with bottom calculations for complex solving.

Column solving is especially useful for setting percentage distributions or proportionality rules.

3 locked column calculation values = 3 Solver constraints

Locked vs. Unlocked Ingredients

Locked ingredient amounts must remain fixed. Unlocked ingredient amounts can be adjusted by the Solver and must have a starting value (cannot be blank). Solver solutions require enough unlocked ingredients (adjustable variables) to satisfy all locked constraints.

Locks on ingredients

Additional Constraint Types

Beyond locking calculations and ingredient amounts directly, the Solver/Locks side panel supports a few other constraint types that are useful in more advanced setups:

  • Ingredient Ratios — fix a proportional ratio between two or more ingredients (e.g., 1:1:2), so that adjusting one automatically scales the others to preserve the ratio.
  • Compounded Ingredient Quantity and Subcomponent locks — constrain an ingredient’s total quantity across all the parent ingredients it appears in, or constrain it within one specific parent, which is useful for multi-step and intermediate-based recipes.
  • Recipe Total, Weighted Sum, Weighted Average, and Composite Calculation constraints — constrain totals or calculated values directly, using the calculation structure to convert user-entered targets into solvable mathematical relationships.

These are covered in more detail in Advanced Solver Configuration.

Adding a rule in the Solver/Locks sidepanel

Constraint Types Reference

ConstraintWhat It DoesMathematical Form
Input VariableBounds on individual ingredient quantities, such as minimum, maximum, or fixed valuesxᵢ = / ≥ / ≤ value
Recipe TotalThe sum of all compounded inputs for final steps equals or stays within a targetΣ(compounded_xᵢ) = / ≥ / ≤ total
Weighted SumA linear combination of variables hits a targetΣ(cᵢ × compounded_xᵢ) = / ≥ / ≤ target
Weighted AverageA ratio, such as numerator / denominator, hits a target; the Solver linearizes the relationship to avoid direct divisionΣ(nᵢxᵢ) – target × Σ(dᵢxᵢ) = / ≥ / ≤ 0
Composite CalculationA multi-term numerator / denominator calculation with bias constants hits a target(Σnum + bias_n) – target × (Σden + bias_d) = 0
Ingredient RatioFixed proportional ratios between ingredient pairs or groupscᵢ × x[i+1] – c[i+1] × xᵢ = 0
Relationship VariableBounds on step-to-step relationship quantitiesSame as input variable constraints

Infeasible Problems

The Solver will report that a problem is “infeasible” if there are too many constraints competing for too few adjustable variables. To resolve this, you can remove constraints, loosen a fixed value into a range, or use the Tolerance Percent to give each constraint a percentage of flexibility.

Solver may also not be able to find a solution when:

  • A calculation is hidden but still has an active lock
  • A calculation is not solver-compatible
  • Constraints mathematically contradict one another
  • Column locks + calculation locks create implicit conflicts

Use the Solver/Locks side panel (Search Actions > “Solver/Locks”) to identify hidden or conflicting locks. Learn more.

Solver Statuses

StatusMeaning
OptimalSolution found
Optimal InaccurateSolution found, but may have numerical issues; accepted only if Accept Optimal Inaccurate Solutions is enabled
InfeasibleConstraints are contradictory or cannot all be satisfied with the available adjustable variables
Other non-optimalGeneric solver failure

Optimization Objective = Closest Possible Formula

When more than one solution satisfies all constraints, the Solver chooses the one that is most similar to the original recipe.

Technically speaking, it minimizes the sum of squared changes to ingredient amounts (also known as an L2 norm or Euclidean distance minimization). This objective penalizes large changes more heavily than small ones.

Objective Types

Three objective types are available:

TypeFormulaMeaning
Defaultminimize Σ(xᵢ – x₀ᵢ)²Closest feasible point to original values
Proportionalminimize Σxᵢ – x₀ᵢ × (x_ref / x₀_ref)
Customminimize, maximize, or target a weighted-sum calculationUser-defined optimization of a specific calculation

When Optimize Mode is set to Optimize on Fail, the Solver adds a slack variable, ε ≥ 0, to the objective with a large penalty: base objective + 1000 × |ε|. This allows slight constraint violations when the problem is otherwise infeasible. When this slack variable is active, every constraint is softened by ±ε; for example, x = value becomes value – ε ≤ x ≤ value + ε.

Curve Solver (Curve Objective)

In addition to the default “stay close to the original recipe” objective, Uncountable can also run the Solver with a curve-matching objective (often referred to as the curve solver).

Adding a curve objective

At a high level, the curve solver:

  • Treats one curve as the target curve and another curve as the recipe-driven curve (often a calculated curve).
  • Adjusts the unlocked variables in the recipe (e.g., ingredient quantities, and in some setups process parameters) to make the recipe-driven curve match the target curve as closely as possible.
  • Uses an objective function based on the sum of squared differences between the curves’ y-values across x (often with additional configuration such as x-range weighting).

Step-by-step instructions for setting up an Aggregate Curve calculation and configuring a Curve Objective are covered in Advanced Solver Configuration.

Practical notes:

  • The curve solver still respects locks and constraints (locked calculations and locked ingredient values). If the curve match is impossible given the constraints, the solve may be infeasible or may use an optimize-on-fail behavior depending on settings.
  • Curve-based objectives usually require additional configuration (which curves to compare, and how to weight parts of the curve). If your results look “off,” check the curve selection and weighting assumptions.

Results

  • Solver avoids extreme or unintuitive adjustments
  • Changes are distributed across all unlocked ingredients
  • The solution feels “reasonable” to a formulator

For example, if changing one ingredient by 230 g and changing four ingredients 10-20g each are both possible solutions, the Solver will choose the second option.


Why Blank Ingredient Values Cannot Change

Solver requires a mathematical relationship between ingredient mass and calculated values. A blank value:

  • Represents no mass contribution
  • Has no differentiable effect on calculations
  • Cannot be modified within the optimization structure

Therefore, Solver always treats blank values as fixed, even if the lock icon is open. To allow Solver to adjust an ingredient, assign any placeholder amount (e.g., 0 or 1 g).


Normalization

After Solver finds ingredient amounts that satisfy all constraints, it performs a normalization step to ensure ingredient ratios and dependent calculations remain consistent if possible.

If it is not possible to satisfy all constraints while maintaining ingredient ratios, a banner will appear indicating “Ingredient ratios were modified by normalization”. This is expected behavior and indicates the Solver successfully balanced your constraints.


Post-Solve Cleanup

Once the Solver has found a solution, the raw numbers it returns go through two lightweight cleanup steps before they’re written back to your recipe:

  1. Aspect-enforced snapping — compensates for ordinary floating-point imprecision. If a value has an equality constraint of exactly 5.0, the underlying solver might technically return something like 4.9999999997; this step snaps it back to the clean target value (and similarly for ≥ / ≤ range bounds).
  2. Sanitization — rounds negligible residual values (e.g., 1e-20) down to zero, while preserving amounts that are actually meaningful.

This is why solved amounts generally come back as clean, sensible numbers rather than long floating-point strings.


Advanced Settings

In the Solver/Locks sidepanel, under Advanced Settings, have a range of additional settings available that allow users to adapt the solver behavior to their use case.

Accept Optimal Inaccurate Solutions

This is particularly useful when working with high precision starting values, but wanted to allow for slight flexibility in precision of solutions.

Allow Fallback Objectives

Enabling this will allow you to rank multiple objectives to attempt to use.

The available objectives are Default, Proportional, and Custom (allows user to specify a target calculation to optimize for).

Optimize Mode

When constraints cannot be met fully, you can choose “Reset on Fail” which will make no changes to ingredient values or “Optimize on Fail” which will meet the constraints as closely as possible, but not exactly. Behind the scenes, Optimize on Fail works by adding a small slack variable to the objective (with a large penalty attached) so that a near-miss solution can still be returned instead of a hard failure.

Tolerance Percent

Enables flexibility to all fixed value constraints of the percentage specified.

Epsilon Accuracy

This value overrides the default epsilon accuracy value (1e-5) used in the solver. Reducing this value can prevent degenerate solutions.

Values To Optimize

Users can choose whether to optimize ingredient values (standard) or process parameter values.

The Optimize Parameter Values option will treat all ingredient values as fixed and treat any process parameters involved in locked calculations as variables that the Solver can change.

Persisting Trend Arrows

By default, the up/down arrows that show which ingredients increased or decreased after a solve clear the next time you make an edit. This setting keeps those trend arrows visible so you can continue to reference the most recent solve’s changes.

Updated on August 18, 2026

Was this article helpful?

Related Articles