Mixture Designs for Formulation DoE
Mixture design formulation DoE explained: why components summing to 1 break factorial designs, what L-pseudocomponents do, and real CovaDOE simplex run.
Oliver Kraft
CovaSyn

You have four excipients and a fixed total. Every time you increase one, something else has to come down. Run that through a standard factorial and you get a design matrix full of blends that do not add up to 100 percent, and a model whose coefficients cannot be estimated because the columns are linearly dependent. Formulation is a mixture problem, not a factorial problem, and it needs a different design.
This article shows what changes, using real designs built with covadoe_create_design (mixture=true). Every run count and every coordinate below is verbatim tool output.
Why a factorial design fails on a formulation
In a factorial design each factor moves independently. Temperature and catalyst loading have nothing to do with each other, so a 2^3 design can visit all eight corners.
In a mixture, the components are constrained:
x1 + x2 + ... + xq = 1
That single equation removes one degree of freedom. Consequences a practitioner actually feels:
- You cannot change one component at a time. Increasing ethanol by 5 percent means decreasing something else by 5 percent. The "effect of ethanol" is never isolated from the thing it displaced.
- The design matrix is singular. A model with an intercept plus all q component terms cannot be fitted, because the component columns sum to a constant. This is why mixture models use the Scheffe form, which drops the intercept.
- The feasible region is a simplex, not a box. For three components it is a triangle, not a square. The corners of the square (for example 100 percent of everything) do not exist.
So the response is a function of the *proportions*, and the design has to live on the simplex.
The two workhorse simplex designs
Two design families cover most formulation work. Both were built here on a three-solvent topical vehicle: ethanol, water and propylene glycol, each with a formulation-realistic lower bound (ethanol at least 0.10, water at least 0.30, propylene glycol at least 0.10).
Simplex lattice
A {q, m} simplex lattice places points on a regular grid of the simplex, where m is the degree of the polynomial you intend to fit.
covadoe_create_design(design_type="simplex_lattice", mixture=true, degree=2) on those three components returned 6 runs: three pure vertices and three binary midpoints. That is exactly the number of terms in a Scheffe quadratic model for three components (3 linear + 3 binary), so the design is saturated. No error degrees of freedom unless you add replicates.
Raising the degree to 3 returned 10 runs on the same three components, which supports the special cubic model.
Simplex centroid
covadoe_create_design(design_type="simplex_centroid", mixture=true) on the same three components returned 7 runs: 3 vertices, 3 binary 50/50 blends, and the overall centroid at equal pseudocomponent proportions. The centroid is worth having - it sits in the middle of the formulation space where you will most likely operate, and it gives you one point to check lack of fit against.
Adding a fourth component (Tween 80, lower bound 0.05) took the simplex centroid to 15 runs: 4 vertices + 6 binary blends + 4 ternary blends + 1 overall centroid.
| Design (CovaDOE) | Components | Runs | What it estimates |
|---|---|---|---|
simplex_lattice, degree 2 | 3 | 6 | Scheffe quadratic (saturated) |
simplex_lattice, degree 3 | 3 | 10 | special cubic |
simplex_centroid | 3 | 7 | quadratic + centre check |
simplex_centroid | 4 | 15 | up to ternary blending terms |
extreme_vertices (auto) | 4, upper bounds active | 21 | quadratic in a truncated region |
All run counts above are the n_runs field returned by covadoe_create_design.
L-pseudocomponents: the part people skip
A real formulation is never a full simplex. You always have lower bounds: at least 30 percent water, at least 0.1 percent lubricant, a minimum API load. Those bounds cut a smaller simplex out of the big one. Running a lattice on the *full* simplex would put most of your runs in blends you are not allowed to make.
L-pseudocomponents fix this by rescaling. With lower bounds L_i and
R = 1 - sum(L_i)
the real proportion of component i is
x_i = L_i + R * z_i
where z is the pseudocomponent, and the z values themselves form a clean simplex summing to 1. You design in z, you run in x.
The tool does this for you and hands back both. In the three-solvent example the lower bounds were 0.10, 0.30 and 0.10, so sum(L) = 0.50 and R = 0.50. The simplex lattice run with pseudocomponent coordinates (0, 0.5, 0.5) came back as a real blend of ethanol 0.10, water 0.55, propylene glycol 0.35. Check it: 0.30 + 0.50 * 0.5 = 0.55. And 0.10 + 0.55 + 0.35 = 1.00.

Every one of the 6 lattice runs and all 7 centroid runs sum to exactly 1.00 in real units. The coded_runs block in the tool response is the pseudocomponent design; runs is what the lab weighs out.
Why this matters practically: fit your model in pseudocomponents. Coefficients are then on a comparable scale and the design is well conditioned. Translate back to real proportions only for the manufacturing instruction.
When lower bounds are not enough: extreme vertices
Lower bounds alone keep the region a simplex, just a smaller one. Add *upper* bounds and the region stops being a simplex - it becomes an irregular polytope, and a lattice no longer fits it.
This shows up in the tool output. A four-component immediate-release blend was requested as simplex_lattice:
- API 0.10 to 0.40
- Lactose 0.30 to 0.70
- MCC 0.10 to 0.40
- Croscarmellose sodium 0.02 to 0.08
covadoe_create_design returned design_type: "extreme_vertices" with 21 runs and n_vertices: 12. It did not build the lattice that was asked for, because with active upper bounds the lattice points would fall outside the feasible region. The design instead enumerates the 12 corners of the constrained polytope and adds edge and interior points.
Two things to take from that:
1. Check the returned `design_type`, not the one you requested. The tool silently upgrades the method when your constraints demand it. That is the right behaviour, but you should notice it, because 21 runs is a different conversation with your lab than 6. 2. The disintegrant range drives a lot of the run count. A component with a narrow window (0.02 to 0.08 here) still generates its own vertices. If you do not need to model it, hold it fixed and take it out of the mixture.
What a mixture design does not tell you
- It says nothing about process factors. Compression force, granulation time and drying temperature are not mixture components. If they matter, you need a crossed mixture-process design (
covadoe_create_designacceptsprocess_factorsalongsidemixture=true) or a separate process study. A pure mixture design will attribute process variation to blend composition. - A saturated design has no error estimate. The 6-run
{3,2}lattice fits the quadratic model exactly. R-squared will look excellent and mean nothing. Add replicate centre points or extra interior runs if you want lack of fit and pure error. - Interpolation only. The model is valid inside the constrained region you designed on. Extrapolating past the vertices is not supported by the data, and the pseudocomponent rescaling makes that easy to forget.
- The design is not the answer. It is a run list. The model quality, optimum and design space come from fitting the measured responses afterwards, with residual diagnostics, and they are only as good as the assay.
- Blending behaviour can be sharply non-linear. Phase separation, precipitation on dilution and percolation thresholds do not respect quadratic models. Screen the vertices early so you find the failures before you commit the full design.
Frequently asked questions
What is a mixture design in DoE?
A mixture design is an experimental design where the factors are proportions of components that must sum to a constant, usually 1 or 100 percent. Because the components are not independent, the feasible region is a simplex rather than a box, and the model is fitted in Scheffe form without an intercept. Typical designs are the simplex lattice, the simplex centroid and, when upper bounds apply, extreme vertices.
How is a mixture design different from a factorial design?
In a factorial design each factor varies independently, so you can change one at a time and estimate its isolated effect. In a mixture design the components sum to a constant, so increasing one necessarily decreases another. That constraint makes the design matrix singular for an ordinary intercept model, removes one degree of freedom, and restricts the design region to a simplex instead of a hypercube.
What are L-pseudocomponents?
L-pseudocomponents rescale a bounded mixture region so it becomes a full simplex again. With lower bounds L_i and R = 1 - sum(L_i), each real proportion is x_i = L_i + R * z_i, where z is the pseudocomponent. You build and fit the design in z, which is well conditioned, and convert back to x for the actual formulation. CovaDOE returns both: coded_runs are pseudocomponents, runs are real proportions.
How many runs does a simplex design need?
It depends on the number of components and the model degree. Built with covadoe_create_design, a three-component simplex lattice of degree 2 needs 6 runs, degree 3 needs 10 runs, and a three-component simplex centroid needs 7 runs. A four-component simplex centroid needs 15. Adding active upper bounds pushed the same four-component case to a 21-run extreme vertices design with 12 vertices.
When should I use extreme vertices instead of a simplex lattice?
Use extreme vertices when your components have upper bounds as well as lower bounds, or when you have additional linear constraints such as a fixed filler ratio. Those constraints turn the feasible region into an irregular polytope where lattice points would fall outside the allowed space. CovaDOE detects this and returns design_type: "extreme_vertices" even if a simplex lattice was requested.
Can I include process variables like compression force?
Not in the mixture part. Process variables are independent factors and belong in a crossed mixture-process design, where a mixture design is run at each combination of process settings. covadoe_create_design supports this via process_factors with mixture=true. Run counts multiply quickly, so screen the process factors separately first and carry only the significant ones into the crossed design.
Related reading
- Central composite vs Box-Behnken: which design, when
- Definitive screening designs explained
- DoE power analysis before you run the experiment
- ICH Q8 design space, NOR and PAR explained
Build and inspect your own simplex design on the CovaSyn free tier before you weigh out a single gram.
Tools for this topic
Use these in your AI agent right away.
- CovadoeDesign of Experiments, RSM, templates.
