mixle.doe.factorial module¶
Classical factorial, screening, and response-surface experiment designs.
These complement the space-filling generators in mixle.doe.designs with the structured “named”
designs of classical DOE: two-level fractional factorials and Plackett-Burman screening designs, and
the central-composite and Box-Behnken response-surface designs.
Every generator takes per-dimension bounds (a sequence of (low, high) pairs, one per factor)
and returns a (n_runs, d) array. The design is built in coded units – two-level factors at
-1 / +1, response-surface axial/centre points relative to that – then mapped into bounds
so -1 -> low, +1 -> high, 0 -> the midpoint. Pass coded=True to get the raw
coded matrix instead (the natural input to the analysis routines in mixle.doe.analysis).
bounds is a hard requirement only for the factorial cube itself: central_composite()’s
rotatable/orthogonal axial points are placed by a design-theory property, not clamped to bounds,
and routinely extend past them on purpose – see its docstring and central_composite_point_kinds().
fractional_factorial()’s generator-string aliasing is likewise published, not just used
internally, via generator_alias_structure().
- fractional_factorial(bounds, generators, *, coded=False)[source]
Two-level fractional factorial
2**(k-p)from pyDOE-style generator strings.generatorsnames one column per factor as a product of base factors, e.g."a b c ab ac"– a2**(5-2)design whose factorsd, eare deliberately aliased asd = ab,e = ac. Base factors are the distinct single letters; each token is the elementwise product of its letters, optionally negated with a leading-. The number of tokens must equallen(bounds).Rejects a
generatorsspec that collapses a factor to a constant column (repeated letters cancelling entirely, e.g."aa") or that aliases two of the named factors with each other (two tokens whose reduced letter-words are identical or exact opposites, e.g. tokens"a"and"-a") – both silently produced a degenerate design with no diagnostic before (MXR-080-0179). This does not affect the intentional aliasing a fractional design is built on: a compound token like"ab"is fine and expected, it just cannot repeat another factor’s own word. Usegenerator_alias_structure()to see which factors are aliased with which interaction.Returns a
(2**k, d)design (k= number of base factors) mapped intobounds– or the raw coded+/-1matrix ifcoded=True.
- generator_alias_structure(generators, *, max_order=2)[source]
Return signed defining words and complete alias chains through
max_order.The result is a JSON-friendly record with:
factor_labelsmapping every public positional factor name to its source token;base_factorsmapping each latent generator letter to its named factor and sign;generatorsexpressing every compound generator using those public factor names;defining_relationsand the complete generateddefining_groupas signed words; andalias_setsfor the identity and every effect through the requested interaction order.
A word record has an integer
sign(+1or-1) and afactorslist. For example,"a b ab"definesI = +x0:x1:x2; through order two,x0is aliased with+x1:x2andx2with+x0:x1. Negated base or compound tokens propagate their signs through every relation and alias. This supplies the actual confounding structure rather than only repeating the compound generator fragments (MXR-080-1477).Every latent base letter must have one named singleton token so aliases can be mapped unambiguously to the positional
xNlabels used bymixle.doe.analysis. The generator syntax is otherwise validated exactly likefractional_factorial().
- plackett_burman(bounds, *, coded=False)[source]
Plackett-Burman two-level screening design for
len(bounds)factors.Returns
Nruns whereNis the smallest multiple of four that is at leastd + 1(so the design is saturated or near-saturated, ideal for screening many factors in few runs). ForNa power of two the design is a Hadamard matrix (a resolution-III fractional factorial); forNin{12, 20, 24}a known cyclic generator is used; otherwiseNis rounded up to the next power of two so a design always exists. Main effects are mutually orthogonal but aliased with two-factor interactions – use it to find the few large effects, then follow up with a fuller design.
- central_composite(bounds, *, center=4, alpha='rotatable', coded=False)[source]
Central-composite design (CCD) for fitting a full second-order response surface.
A CCD stacks three parts, in this row order (see
central_composite_point_kinds()to recover which output row is which): the2**dtwo-level factorial corners (estimate linear and interaction terms),2*daxial / star points at distancealphaon each axis (estimate the pure-quadratic curvature), andcenterreplicates at the centre (estimate pure error and curvature).alphasets the axial distance:"rotatable"(default) –alpha = (2**d)**0.25, so prediction variance depends only on distance from the centre;"orthogonal"– the value making the second-order terms orthogonal (depends oncenter);"face"(a face-centred CCD / CCF) –alpha = 1, keeping every run inside the cube;a positive, finite float – used directly.
boundsdefines the factorial cube (-1/+1map to each factor’slow/high): the factorial-corner and centre rows are therefore always exactly withinbounds. Axial points sit at coded distancealphaon a single axis, and for"rotatable"/"orthogonal"that distance is normally greater than 1 – a mathematical requirement of the rotatability/orthogonality property, not a clamp tobounds– so those rows routinely fall outsideboundson purpose. Onlyalpha="face"(or a numericalpha <= 1) guarantees every row stays withinbounds(MXR-080-0179); usecentral_composite_point_kinds()to tell the row kinds apart programmatically when that distinction matters to the caller.Returns
(2**d + 2*d + center, d)rows mapped intobounds(or coded ifcoded=True).
- central_composite_point_kinds(bounds, *, center=4)[source]
Row-kind labels for
central_composite()’s output, in the same row order.Returns a length-
(2**d + 2*d + center)string array of"factorial"/"axial"/"center"entries."factorial"and"center"rows are always exactly withinbounds;"axial"rows are guaranteed withinboundsonly whencentral_composite()was called withalpha="face"(or a numericalpha <= 1) – see its docstring for why rotatable/ orthogonal axial points routinely extend pastboundson purpose (MXR-080-0179). Pass the samecenterused in the matchingcentral_composite()call so the lengths line up, e.g.:design = central_composite(bounds, center=4, alpha="rotatable") kinds = central_composite_point_kinds(bounds, center=4) in_bounds_rows = design[kinds != "axial"]
- box_behnken(bounds, *, center=None, coded=False)[source]
Box-Behnken response-surface design (3 levels per factor, no corner runs).
For every pair of factors it runs the four
(+/-1, +/-1)combinations with all other factors at the centre, pluscentercentre replicates. Unlike a CCD it never sets all factors to an extreme at once (no cube corners), which is useful when those combinations are expensive or infeasible, and it needs only three levels per factor. Every row is always withinbounds(no analogue of a CCD’s rotatable axial points here). Requiresd >= 3.Returns
(4 * C(d, 2) + center, d)rows mapped intobounds(or coded ifcoded=True).