Source code for process_improve.experiments.designs_factorial
# (c) Kevin Dunn, 2010-2026. MIT License.
"""Various factorial designs."""
from process_improve.config import settings
from .structures import c, create_names, expand_grid
[docs]
def full_factorial(nfactors: int, names: list | None = None) -> list:
"""Create a full factorial (2^k) design for the case when there are `nfactors` [integer] number of factors.
The optional list of `names` can be provided. The entries in the list
should be strings. If not provided, the names will be created.
Raises
------
ValueError
If ``nfactors < 1`` (the empty design is undefined) or
``nfactors > settings.max_factors_combinatorial`` (SEC-19 #268:
a request for 2**40 rows is a memory-exhaustion attack, not a
legitimate design).
"""
nfactors = int(nfactors)
if nfactors < 1:
raise ValueError(f"nfactors must be >= 1; got {nfactors}.")
cap = settings.max_factors_combinatorial
if nfactors > cap:
raise ValueError(
f"nfactors={nfactors} exceeds the SEC-19 combinatorial cap of {cap}; "
f"a full factorial would require 2**{nfactors} rows. "
"Increase settings.max_factors_combinatorial if intentional."
)
if names is None:
names = create_names(nfactors)
# Expand the full factorial out into variables
return expand_grid(**dict(zip(names, [c(-1, +1)] * len(names), strict=False)))