Designs¶
Design generators. Every design is constructed from
Factor objects and produces a pandas
design matrix from generate_design().
Factorial aliasing and blocking¶
Source: factorial_aliasing_blocking.dot
Regular two-level fractions and regular factorial blocks both use treatment words and algebra over $\mathrm{GF}(2)$, but they solve different problems. A fractional factorial deliberately omits treatment combinations, so its defining relation determines which treatment effects are aliased. Resolution and the word-length pattern summarize how severe those aliases are, and foldover can add runs when a particular ambiguity matters.
Blocking keeps the full factorial treatment set but partitions it into
restricted groups. The independent block generators produce a block-defining
subgroup; treatment effects in that subgroup are intentionally confounded with
blocks. FactorialDesign.block_structure() exposes that choice explicitly, and
run-order randomization then occurs within blocks rather than destroying the
restriction.
Base¶
industrialstats.designs.base ¶
Base class for all experimental designs.
Factor
dataclass
¶
Represents an experimental factor.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Name of the factor as it appears in the design matrix. |
levels |
list[str | float | int]
|
Supported discrete levels for the factor. |
factor_type |
str
|
Either |
ExperimentalDesign ¶
Bases: ABC
Abstract base class for experimental designs.
Subclasses must implement :meth:generate_design and :meth:validate_design
to provide bespoke construction and integrity checks for the experiment.
Initialise the design container.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Human-readable label describing the design. |
required |
Source code in src/industrialstats/designs/base.py
is_balanced
property
¶
Indicate whether the design is balanced across categorical factors.
Returns:
| Type | Description |
|---|---|
bool
|
|
Examples:
design_efficiency
property
¶
Compute baseline efficiency metrics for the design.
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Dictionary containing efficiency statistics such as the run fraction, replication factor, balance index, and the proportion of missing data. |
Examples:
>>> from industrialstats.designs.factorial import FactorialDesign
>>> design = FactorialDesign([Factor("A", [0, 1])], randomize=False)
>>> design.generate_design()
>>> metrics = design.design_efficiency
>>> sorted(metrics.keys())
['balance_index', 'missing_rate', 'replication_factor', 'run_fraction']
generate_design
abstractmethod
¶
validate_design
abstractmethod
¶
add_factor ¶
add_factor(factor: Factor) -> None
Add a factor to the design.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factor
|
Factor
|
Factor description to register. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Source code in src/industrialstats/designs/base.py
randomize ¶
Randomise the run order of the experiment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int | None
|
Optional random seed used to create deterministic shuffles. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the design matrix has not been generated. |
References
Montgomery, D.C. (2017). Design and Analysis of Experiments, 9th ed., Wiley.
Examples:
>>> from industrialstats.designs.factorial import FactorialDesign
>>> design = FactorialDesign({"A": [1, -1], "B": [1, -1]})
>>> design.generate_design()
>>> design.randomize(seed=42)
>>> design.design_matrix[["RunOrder", "A", "B"]].head()
RunOrder A B
0 1 1 -1
1 2 -1 1
Source code in src/industrialstats/designs/base.py
to_csv ¶
Export design to a CSV file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Destination file path. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no design matrix is available. |
Source code in src/industrialstats/designs/base.py
to_excel ¶
Export the design to an Excel workbook with optional metadata.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path to the output workbook ( |
required |
include_metadata
|
bool
|
Whether to include a summary worksheet. |
True
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If no design matrix exists or the extension is invalid. |
OSError
|
If the workbook cannot be written to disk. |
Examples:
>>> from industrialstats.designs.factorial import FactorialDesign
>>> design = FactorialDesign([Factor("A", ["Low", "High"])], randomize=False)
>>> design.generate_design()
>>> design.to_excel("factorial_design.xlsx")
Source code in src/industrialstats/designs/base.py
to_json ¶
Serialise the design to a JSON document suitable for APIs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Destination path ending with |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the design matrix is missing or the extension is invalid. |
OSError
|
If writing the JSON file fails. |
Examples:
>>> from industrialstats.designs.factorial import FactorialDesign
>>> design = FactorialDesign([Factor("A", [1, -1])], randomize=False)
>>> design.generate_design()
>>> design.to_json("design.json")
Source code in src/industrialstats/designs/base.py
clone ¶
clone() -> ExperimentalDesign
Create and return a deep copy of the design instance.
Returns:
| Type | Description |
|---|---|
ExperimentalDesign
|
Deep copy of |
Examples:
>>> from industrialstats.designs.factorial import FactorialDesign
>>> design = FactorialDesign([Factor("A", [0, 1])], randomize=False)
>>> design.generate_design()
>>> clone = design.clone()
>>> clone is design
False
>>> clone.design_matrix.equals(design.design_matrix)
True
Source code in src/industrialstats/designs/base.py
merge_with ¶
merge_with(other_design: ExperimentalDesign) -> ExperimentalDesign
Merge the design with another compatible design.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other_design
|
ExperimentalDesign
|
Design whose runs will be appended to this design. |
required |
Returns:
| Type | Description |
|---|---|
ExperimentalDesign
|
Deep copy of the current design containing runs from both designs. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If either design lacks a generated design matrix or the factor metadata is incompatible. |
Examples:
>>> from industrialstats.designs.factorial import FactorialDesign
>>> factors = [Factor("A", [0, 1])]
>>> d1 = FactorialDesign(factors, randomize=False)
>>> _ = d1.generate_design()
>>> d2 = FactorialDesign(factors, randomize=False)
>>> _ = d2.generate_design()
>>> merged = d1.merge_with(d2)
>>> merged.run_count
4
Source code in src/industrialstats/designs/base.py
compare_to ¶
compare_to(other_design: ExperimentalDesign) -> dict[str, Any]
Compare this design with another design.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other_design
|
ExperimentalDesign
|
Design to compare against. |
required |
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Summary of differences such as run count and factor sets. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If either design lacks a generated matrix. |
Source code in src/industrialstats/designs/base.py
summary ¶
Return summary information about the design.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Key characteristics of the design. |
Source code in src/industrialstats/designs/base.py
Full factorial¶
industrialstats.designs.factorial ¶
Full factorial experimental designs with statistically defined blocking.
FactorialDesign ¶
FactorialDesign(factors: list[Factor], replicates: int = 1, center_points: int = 0, randomize: bool = True, blocks: int | None = None, seed: int | None = None, block_generators: list[str] | None = None, allow_main_effect_confounding: bool = False)
Bases: FactorialDesign
Full factorial design with regular blocking for two-level experiments.
Create a full factorial design.
Source code in src/industrialstats/designs/factorial.py
generate_design ¶
Generate the full factorial design and apply regular blocking.
Source code in src/industrialstats/designs/factorial.py
validate_design ¶
Validate the factorial design and its optional block structure.
Source code in src/industrialstats/designs/factorial.py
model_terms ¶
Return hierarchical factorial terms through max_order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_order
|
int | None
|
Highest interaction order to include. |
None
|
Returns:
| Type | Description |
|---|---|
list[str]
|
Ordered effect names such as |
Source code in src/industrialstats/designs/factorial.py
degrees_of_freedom ¶
Calculate factorial degrees of freedom for a hierarchical model.
For a term involving factors in a set S, the term degrees of freedom
are the product prod(len(levels_j) - 1 for j in S). With
max_order=None the model is saturated over the factorial treatment
combinations. A finite max_order gives a truncated hierarchical model;
omitted higher-order treatment variation remains in Error together
with replication and center-point residual degrees of freedom.
Source code in src/industrialstats/designs/factorial.py
model_structure ¶
Describe a saturated or truncated hierarchical factorial model.
Source code in src/industrialstats/designs/factorial.py
calculate_effects ¶
Calculate canonical two-level factorial effects.
Factor levels are coded according to their declared order: the first
level is -1 and the second is +1. The returned factorial effect
is twice the corresponding coefficient in a regression using these
coded columns and their products.
Source code in src/industrialstats/designs/factorial.py
block_structure ¶
Return generators, defining contrasts, and block diagnostics.
Source code in src/industrialstats/designs/factorial.py
blocking_scheme ¶
Reassign an existing design using regular treatment contrasts.
Source code in src/industrialstats/designs/factorial.py
Fractional factorial¶
industrialstats.designs.fractional_factorial ¶
Fractional factorial design implementation.
FractionalFactorialDesign ¶
FractionalFactorialDesign(factors: list[Factor], fraction: str = '1/2', generators: list[str] | None = None, resolution: int | None = None, replicates: int = 1, randomize: bool = True)
Bases: ExperimentalDesign
Two-level fractional factorial design.
This class generates regular two-level fractional factorial designs for
three to fifteen factors and automatically selects minimum aberration
generator strings for the most common fractions (:math:1/2, :math:1/4,
:math:1/8, and :math:1/16). The implementation mirrors the confounding
analysis strategy described in :mod:industrialstats.designs.README by
constructing the defining relation of the design and deriving alias chains
through linear algebra over :math:\mathrm{GF}(2).
Notes
- All factors must be two-level factors with exactly two entries in
Factor.levels. - Fraction denominators must be powers of two; the numerator is assumed to be one.
- When
generatorsare not supplied, the class performs a constrained search for generator sets that maximise the design resolution and, as a tie-breaker, minimise the word-length pattern (the minimum aberration criterion of Montgomery and Wu & Hamada). - Alias structures reported by :meth:
alias_structureinclude all factorial effects, not only main effects and two-factor interactions.
References
Montgomery, D. C. (2017). Design and Analysis of Experiments (9th ed.).
Wiley.
Wu, C. F. J., & Hamada, M. S. (2009). Experiments: Planning, Analysis, and
Optimization (2nd ed.). Wiley.
Groemping, U. (2014). "R package FrF2 for creating and analysing 2-level
factorial designs". Journal of Statistical Software, 56(1).
Xu, H. (2005). "A catalogue of three-level and four-level fractional
factorial designs with minimum aberration". Technometrics, 47(3).
NIST/SEMATECH (2012). e-Handbook of Statistical Methods, Chapter 5.3.
"FrF2" R package documentation for catlg52 (minimum aberration tables).
"Montgomery" Chapter 8 examples on foldover strategies.
"NIST foldover guidance" on mitigating aliasing.
"Xu & Wu (2001)" alias chain construction using defining relations.
Examples:
>>> from industrialstats.designs.base import Factor
>>> factors = [Factor(name, [-1, 1]) for name in "ABCDEFG"]
>>> design = FractionalFactorialDesign(factors, fraction="1/8")
>>> design.generators
['A*B*C', 'A*B*D', 'A*C*D']
>>> metrics = design.resolution_analysis()
>>> metrics["resolution"]
4
>>> alias = design.alias_structure()
>>> alias["A"][:3]
['A', 'A:B:C:F:G', 'A:B:D:E:G']
>>> design.foldover_options()[0]["type"]
'full'
Initialize fractional factorial design.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factors
|
list[Factor]
|
Factors in the experiment. Must all have two levels. |
required |
fraction
|
str
|
Fraction of the full design, e.g. |
'1/2'
|
generators
|
list[str]
|
Generator strings using factor names. |
None
|
resolution
|
int
|
Desired design resolution (for reference only). |
None
|
replicates
|
int
|
Number of replicates. |
1
|
randomize
|
bool
|
Whether to randomize run order. |
True
|
Source code in src/industrialstats/designs/fractional_factorial.py
calculate_resolution ¶
Return the design resolution and its word-length pattern.
Source code in src/industrialstats/designs/fractional_factorial.py
verify_resolution ¶
Check that the design resolution meets minimum.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the design resolution is undefined or below |
Source code in src/industrialstats/designs/fractional_factorial.py
generate_design ¶
Generate fractional factorial design matrix.
Source code in src/industrialstats/designs/fractional_factorial.py
validate_design ¶
Validate fractional factorial parameters.
alias_structure ¶
Return alias chains for all factorial effects.
The alias chains are computed by applying the defining relation of the design to every factorial effect. Each entry contains the canonical effect (lexicographically smallest mask) followed by the remaining members of its alias class.
Source code in src/industrialstats/designs/fractional_factorial.py
resolution_analysis ¶
Analyze design resolution and clarity.
Source code in src/industrialstats/designs/fractional_factorial.py
foldover_options ¶
Suggest foldover strategies with supporting metadata.
Foldover proposals follow Montgomery's guidance: a full foldover adds a replicate with all signs reversed, while partial foldovers target problematic columns. The suggestions focus on breaking aliases for main effects with the longest alias chains.
Source code in src/industrialstats/designs/fractional_factorial.py
Completely randomized design¶
industrialstats.designs.crd ¶
Completely Randomized Design (CRD) implementation.
CompletelyRandomizedDesign ¶
CompletelyRandomizedDesign(treatments: list[str], replicates: int, seed: int | None = None, response_variables: list[str] | None = None)
Bases: ExperimentalDesign
Completely Randomized Design (CRD).
This is the simplest experimental design where treatments are randomly assigned to experimental units without any restrictions or blocking.
Initialize CRD.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
treatments
|
list of str
|
Names of treatment levels. |
required |
replicates
|
int
|
Number of replicates per treatment. |
required |
seed
|
int
|
Random seed for reproducible run ordering. |
None
|
response_variables
|
list of str
|
Names of response variables measured in the experiment. |
None
|
Source code in src/industrialstats/designs/crd.py
generate_design ¶
Generate the CRD design matrix.
Returns:
| Type | Description |
|---|---|
DataFrame
|
Design matrix with randomized run order. |
Source code in src/industrialstats/designs/crd.py
validate_design ¶
Validate CRD parameters.
Source code in src/industrialstats/designs/crd.py
n_runs ¶
degrees_of_freedom ¶
Calculate degrees of freedom for CRD analysis.
Source code in src/industrialstats/designs/crd.py
expected_mean_squares ¶
efficiency_vs_rcbd ¶
Calculate relative efficiency compared to RCBD.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
block_variance
|
float
|
Estimated variance between blocks. |
required |
error_variance
|
float
|
Estimated experimental error variance. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Relative efficiency (> 1 means CRD is more efficient). |
Source code in src/industrialstats/designs/crd.py
sample_size_calculation ¶
Calculate required sample size per treatment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
effect_size
|
float
|
Expected effect size (Cohen's |
required |
alpha
|
float
|
Type I error rate. Defaults to 0.05. |
0.05
|
power
|
float
|
Desired statistical power. Defaults to 0.8. |
0.8
|
Returns:
| Type | Description |
|---|---|
int
|
Required number of replicates per treatment. |
Source code in src/industrialstats/designs/crd.py
create_data_collection_sheet ¶
Create a data collection sheet for the experiment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response_variables
|
list of str
|
Names of response variables to include. Defaults to the design's
stored |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Data collection sheet with empty response columns. |
Source code in src/industrialstats/designs/crd.py
summary_statistics ¶
Calculate summary statistics for multiple responses.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
Experimental data with results. |
required |
response_columns
|
list of str
|
Names of response variable columns to analyze. |
required |
Returns:
| Type | Description |
|---|---|
dict of pandas.DataFrame
|
Mapping of response names to summary statistics by treatment. |
Source code in src/industrialstats/designs/crd.py
Randomized complete block design¶
industrialstats.designs.rcbd ¶
Randomized Complete Block Design implementation.
RandomizedCompleteBlockDesign ¶
RandomizedCompleteBlockDesign(treatments: list[str], blocks: list[str], blocking_factor: str = 'Block', seed: int | None = None)
Bases: ExperimentalDesign
Randomized Complete Block Design.
Initialize RCBD.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
treatments
|
list of str
|
List of treatment names or levels. |
required |
blocks
|
list of str
|
Names of blocking levels. |
required |
blocking_factor
|
str
|
Column name for blocks in the design matrix. Defaults to |
'Block'
|
seed
|
int
|
Random seed for reproducibility. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If fewer than two treatments or blocks are provided. |
Source code in src/industrialstats/designs/rcbd.py
generate_design ¶
Generate RCBD matrix with proper randomization.
Each block contains all treatments exactly once. Blocks are internally
randomized using :func:pandas.DataFrame.sample with an offset seed so
that seed + i controls the shuffling of the i-th block. The
combined design matrix is returned with a leading RunOrder column.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int
|
Random seed for reproducible shuffling. If |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Randomized design matrix with columns |
See Also
industrialstats.designs.base.ExperimentalDesign.randomize Generic randomization utility for arbitrary designs. efficiency_vs_crd Compute relative efficiency against a completely randomized design.
Examples:
>>> rcbd = RandomizedCompleteBlockDesign(
... treatments=["A", "B", "C"], blocks=["B1", "B2"], seed=123
... )
>>> dm = rcbd.generate_design()
>>> dm.head()
RunOrder Block Treatment
0 1 B1 B
1 2 B1 C
2 3 B1 A
References
.. [1] Montgomery, D.C. (2017). Design and Analysis of Experiments. 9th ed. Wiley.
Source code in src/industrialstats/designs/rcbd.py
validate_design ¶
efficiency_vs_crd ¶
Calculate relative efficiency compared to CRD.
Source code in src/industrialstats/designs/rcbd.py
missing_plot_analysis ¶
Analyze impact of missing plots.
Source code in src/industrialstats/designs/rcbd.py
latin_square_option ¶
Generate Latin Square if conditions allow.
Source code in src/industrialstats/designs/rcbd.py
Screening¶
industrialstats.designs.screening ¶
Screening designs such as Plackett-Burman and definitive screening.
PlackettBurmanDesign ¶
PlackettBurmanDesign(factors: list[Factor], randomize: bool = True, seed: int | None = None)
Bases: ExperimentalDesign
Plackett--Burman screening design for two-level factors.
The implemented Hadamard catalogue contains Sylvester orders and the
standard 12- and 20-run Plackett--Burman base designs together with all
powers-of-two doublings of those bases. For k factors, the constructor
selects the smallest supported run size N satisfying N > k.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factors
|
list of Factor
|
Factors to include in the design. Each factor must have two levels. |
required |
randomize
|
bool
|
If |
True
|
seed
|
int
|
Random seed for deterministic run-order shuffling. |
None
|
Source code in src/industrialstats/designs/screening.py
is_supported_run_size
classmethod
¶
Return whether n_runs belongs to the implemented PB catalogue.
Source code in src/industrialstats/designs/screening.py
supported_run_sizes
classmethod
¶
Return implemented Plackett--Burman run sizes up to max_runs.
Source code in src/industrialstats/designs/screening.py
run_size_for_factors
classmethod
¶
Return the smallest implemented run size able to hold n_factors.
Source code in src/industrialstats/designs/screening.py
run_size ¶
generate_design ¶
Generate the design matrix.
Source code in src/industrialstats/designs/screening.py
foldover ¶
Create a foldover design to de-alias main effects.
Returns:
| Type | Description |
|---|---|
DataFrame
|
Foldover design matrix appended to the existing design. |
Source code in src/industrialstats/designs/screening.py
validate_design ¶
Validate the design parameters and main-effect orthogonality.
Source code in src/industrialstats/designs/screening.py
DefinitiveScreeningDesign ¶
DefinitiveScreeningDesign(factors: list[Factor], randomize: bool = True, seed: int | None = None)
Bases: ExperimentalDesign
Conference-matrix definitive screening design for three-level factors.
This implementation follows the conference-matrix construction of Xiao, Lin, and Bai (2012). It uses the smallest Paley conference order large enough for the requested number of factors, takes the required columns, appends their foldover, and adds one center run.
For m factors, let q be the smallest supported value, either 1 or
an odd prime, satisfying q + 1 >= m. The design then has
2 * (q + 1) + 1 runs. Consequently, designs are minimal 2m + 1
constructions when m = q + 1 and may contain additional runs when a
larger conference order is required.
Factor columns are returned in coded levels -1, 0, 1. Three-level
factors are interpreted as quantitative/continuous for the statistical
construction even when legacy Factor metadata leaves factor_type
at its default value. Mixed continuous/two-level categorical DSDs are not
yet implemented.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factors
|
list of Factor
|
Factors to include; each must have exactly three levels. |
required |
randomize
|
bool
|
If |
True
|
seed
|
int
|
Random seed controlling the shuffle. |
None
|
References
.. [1] Jones, B., Nachtsheim, C. J. (2011). A Class of Three-Level Designs for Definitive Screening in the Presence of Second-Order Effects. Journal of Quality Technology, 43(1), 1-15. .. [2] Xiao, L., Lin, D. K. J., Bai, F. (2012). Constructing Definitive Screening Designs Using Conference Matrices. Journal of Quality Technology, 44(1), 2-8.
Source code in src/industrialstats/designs/screening.py
generate_design ¶
Generate the coded definitive screening design matrix.
Source code in src/industrialstats/designs/screening.py
validate_design ¶
Validate both inputs and defining algebraic DSD properties.
Source code in src/industrialstats/designs/screening.py
Response surface¶
industrialstats.designs.response_surface ¶
Response surface methodology (RSM) designs.
This module implements the :class:ResponseSurfaceDesign class for constructing
central composite and Box–Behnken designs used in process optimization.
ResponseSurfaceDesign ¶
ResponseSurfaceDesign(factors: list[Factor], design_type: str = 'CCD', alpha: float | None = None, center_points: int = 5)
Bases: ExperimentalDesign
Response surface design for optimization studies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factors
|
list[Factor]
|
Continuous factors (must be 2-level for coding). |
required |
design_type
|
str
|
|
'CCD'
|
alpha
|
float
|
Alpha value for axial points (CCD only). If |
None
|
center_points
|
int
|
Number of center point replicates. Defaults to |
5
|
Examples:
Generate a Box-Behnken design with three factors and one center point::
>>> factors = [
... Factor("A", [-1, 1]),
... Factor("B", [-1, 1]),
... Factor("C", [-1, 1]),
... ]
>>> design = ResponseSurfaceDesign(factors, design_type="BBD", center_points=1)
>>> design.generate_design().shape[0]
13
Initialize response surface design.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factors
|
list[Factor]
|
Continuous factors (must be 2-level for coding). |
required |
design_type
|
str
|
|
'CCD'
|
alpha
|
float
|
Alpha value for axial points (CCD only). If |
None
|
center_points
|
int
|
Number of center point replicates. Defaults to |
5
|
Source code in src/industrialstats/designs/response_surface.py
generate_design ¶
Generate response surface design matrix.
Source code in src/industrialstats/designs/response_surface.py
validate_design ¶
Validate response surface design parameters.
Source code in src/industrialstats/designs/response_surface.py
n_runs ¶
Calculate total number of runs.
Source code in src/industrialstats/designs/response_surface.py
design_properties ¶
Calculate design properties (rotatability, orthogonality, etc.).
Source code in src/industrialstats/designs/response_surface.py
prediction_variance ¶
Calculate prediction variance at specified points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prediction_points
|
list[list[float]]
|
Points in coded units where prediction variance is calculated. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Prediction variances. |
Source code in src/industrialstats/designs/response_surface.py
response_surface_analysis ¶
Fit response surface model and analyze results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response_data
|
list[float]
|
Response values for each design point. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Analysis results including coefficients, model fit, and optimum. |
Source code in src/industrialstats/designs/response_surface.py
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | |
steepest_ascent ¶
steepest_ascent(model_results: dict[str, Any], start_point: dict[str, float] | None = None, step_length: float = 0.5, n_steps: int = 10, direction: str = 'ascent', visualize: bool = False, plot_factors: tuple[str, str] | None = None) -> dict[str, Any]
Compute the steepest ascent/descent path for the fitted surface.
This routine follows the gradient-based approach described by Box and Draper [1]_ to generate an ordered sequence of points in the direction of the largest increase (or decrease) in the response. Steps are taken in coded units and converted back to actual factor levels for reporting.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_results
|
dict[str, Any]
|
Output from :meth: |
required |
start_point
|
dict[str, float] | None
|
Starting location in actual units. If omitted, the design centre is used. |
None
|
step_length
|
float
|
Length of each step in coded units once the gradient
direction is normalised. Defaults to |
0.5
|
n_steps
|
int
|
Number of steps to compute along the path. Defaults to
|
10
|
direction
|
str
|
Direction of movement relative to the gradient. Defaults
to |
'ascent'
|
visualize
|
bool
|
Whether to return a contour plot overlay. Defaults to
|
False
|
plot_factors
|
tuple[str, str] | None
|
Pair of factor names to use on the contour plot. When
|
None
|
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Dictionary with keys |
Raises:
| Type | Description |
|---|---|
ValueError
|
If an invalid direction is provided or the gradient is zero. |
Examples:
>>> factors = [Factor("x1", [-1, 1]), Factor("x2", [-1, 1])]
>>> design = ResponseSurfaceDesign(factors)
>>> dm = design.generate_design()
>>> y = dm["x1"] * -2 + dm["x2"]
>>> results = design.response_surface_analysis(y.tolist())
>>> path = design.steepest_ascent(results, n_steps=3)
>>> list(path["path"]["Step"])
[0, 1, 2, 3]
References
Box, G. E. P., & Draper, N. R. (2007). Response Surfaces, Mixtures, and Ridge Analyses (2nd ed.). Wiley.
Source code in src/industrialstats/designs/response_surface.py
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 | |
ridge_analysis ¶
ridge_analysis(model_results: dict[str, Any], radii: Sequence[float], constraints: Sequence[Callable[[ndarray], float]] | None = None, penalty_weight: float = 100.0, visualize: bool = False, plot_factors: tuple[str, str] | None = None) -> dict[str, Any]
Perform ridge analysis for constrained optimisation.
Ridge analysis seeks the best point on a hypersphere of radius r in
coded units by solving the Lagrangian system (B + λI) x = -0.5 b for
each candidate radius [1]_. Optional inequality constraints g_i(x) ≤ 0
are enforced through quadratic penalties to discourage infeasible
solutions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_results
|
dict[str, Any]
|
Output from :meth: |
required |
radii
|
sequence of float
|
Radii in coded units at which to evaluate the ridge solution. |
required |
constraints
|
sequence of callable
|
Functions mapping a coded point to a real value. Positive values are
treated as violations and penalised. Defaults to |
None
|
penalty_weight
|
float
|
Penalty scaling factor applied to squared constraint violations.
Defaults to |
100.0
|
visualize
|
bool
|
When |
False
|
plot_factors
|
tuple[str, str]
|
Factor names to use for the visualisation. Defaults to the first two factors. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary containing the ridge solutions ( |
References
.. [1] Box, G. E. P., & Draper, N. R. (2007). Response Surfaces, Mixtures, and Ridge Analyses (2nd ed.). Wiley.
Source code in src/industrialstats/designs/response_surface.py
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 | |
canonical_analysis ¶
Carry out canonical analysis of the fitted response surface.
Canonical analysis diagonalises the quadratic form to reveal the surface curvature and nature of the stationary point (minimum, maximum, saddle, or ridge) following Box and Draper [1]_. Eigenvectors define the canonical directions while eigenvalues quantify curvature along each axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_results
|
dict[str, Any]
|
Output from :meth: |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Summary including the stationary point in coded and actual units, eigenvalues/eigenvectors, surface classification, and 95 % confidence ellipsoid axes for the optimum when degrees of freedom are available. |
References
.. [1] Box, G. E. P., & Draper, N. R. (2007). Response Surfaces, Mixtures, and Ridge Analyses (2nd ed.). Wiley.
Source code in src/industrialstats/designs/response_surface.py
915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 | |
multiple_response_optimization ¶
multiple_response_optimization(response_models: dict[str, dict[str, Any]], weights: dict[str, float] | None = None, desirability_functions: dict[str, Callable[[float], float]] | None = None, constraint_functions: Sequence[Callable[[ndarray], float]] | None = None, grid_resolution: int = 25, search_radius: float = 1.5, penalty_weight: float = 50.0, weight_perturbation: float = 0.15) -> dict[str, Any]
Simultaneously optimise multiple responses.
The optimisation proceeds by evaluating fitted response models on a lattice in the coded factor space, computing desirability functions for each response, and aggregating them using weighted geometric means. A Pareto frontier of feasible points is additionally identified, and weight sensitivity analysis perturbs the supplied weights to study robustness.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response_models
|
dict[str, dict[str, Any]]
|
Mapping from response name to model results produced by
:meth: |
required |
weights
|
dict[str, float]
|
Importance weights for each response. If omitted, equal weights are assigned. |
None
|
desirability_functions
|
dict[str, callable]
|
Custom desirability functions mapping response values to |
None
|
constraint_functions
|
sequence of callable
|
Inequality constraints |
None
|
grid_resolution
|
int
|
Number of grid points per factor in the coded space. Defaults to
|
25
|
search_radius
|
float
|
Extent of the coded search space ( |
1.5
|
penalty_weight
|
float
|
Penalty multiplier for constraint violations. Defaults to |
50.0
|
weight_perturbation
|
float
|
Relative perturbation applied to weights during the sensitivity
analysis. Defaults to |
0.15
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary containing the best compromise solution, Pareto frontier, and weight sensitivity study. |
References
.. [1] Box, G. E. P., & Draper, N. R. (2007). Response Surfaces, Mixtures, and Ridge Analyses (2nd ed.). Wiley.
Source code in src/industrialstats/designs/response_surface.py
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 | |
contour_data ¶
contour_data(coefficients: dict[str, float], factor1: str, factor2: str, grid_size: int = 20) -> tuple[ndarray, ndarray, ndarray]
Generate contour plot data for two factors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coefficients
|
dict[str, float]
|
Model coefficients from :func: |
required |
factor1
|
str
|
Name of the first factor for the plot. |
required |
factor2
|
str
|
Name of the second factor for the plot. |
required |
grid_size
|
int
|
Grid resolution. Defaults to |
20
|
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray, ndarray]
|
|
Source code in src/industrialstats/designs/response_surface.py
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 | |
Optimal designs¶
industrialstats.designs.optimal ¶
Optimal experimental designs using algorithmic approaches.
OptimalDesign ¶
OptimalDesign(factors: list[Factor], n_runs: int, criterion: str = 'D', model_terms: list[str] | None = None)
Bases: ExperimentalDesign
Generate optimal experimental designs using exchange algorithms.
Supports D-optimal, A-optimal, G-optimal, and I-optimal criteria.
Initialize optimal design.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factors
|
list[Factor]
|
Experimental factors. |
required |
n_runs
|
int
|
Number of experimental runs. |
required |
criterion
|
str
|
Optimality criterion ( |
'D'
|
model_terms
|
list[str]
|
Model terms to include. Defaults to main effects and interactions. |
None
|
Source code in src/industrialstats/designs/optimal.py
generate_candidate_set ¶
Generate candidate set of all possible design points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grid_density
|
int
|
Number of levels for continuous factors. Defaults to |
5
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Candidate set of design points. |
Source code in src/industrialstats/designs/optimal.py
generate_design ¶
generate_design(max_iterations: int = 1000, random_start: bool = True, n_random_starts: int = 5, improvement_threshold: float = 1e-06) -> DataFrame
Generate optimal design using coordinate exchange algorithm.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_iterations
|
int
|
Maximum number of exchange iterations. Defaults to |
1000
|
random_start
|
bool
|
Whether to use random starting design. Defaults to |
True
|
n_random_starts
|
int
|
Number of random starts to try. Defaults to |
5
|
improvement_threshold
|
float
|
Minimum improvement in the criterion required to continue
iterations. Defaults to |
1e-06
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Optimal design matrix. |
Source code in src/industrialstats/designs/optimal.py
validate_design ¶
Validate optimal design parameters.
Source code in src/industrialstats/designs/optimal.py
design_efficiency ¶
Calculate design efficiency metrics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reference_design
|
DataFrame
|
Reference design for comparison. Defaults to an orthogonal design. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Efficiency metrics. |
Source code in src/industrialstats/designs/optimal.py
prediction_variance_map ¶
prediction_variance_map(factor1: str, factor2: str, grid_size: int = 20) -> tuple[ndarray, ndarray, ndarray]
Generate prediction variance map for two factors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factor1
|
str
|
First factor name. |
required |
factor2
|
str
|
Second factor name. |
required |
grid_size
|
int
|
Grid resolution. Defaults to |
20
|
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray, ndarray]
|
X, Y, Z arrays for contour plotting. |
Source code in src/industrialstats/designs/optimal.py
augment_design ¶
Augment existing design with additional runs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
additional_runs
|
int
|
Number of additional runs to add. |
required |
current_data
|
DataFrame
|
Current experimental data. If |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Augmented design. |
Source code in src/industrialstats/designs/optimal.py
design_diagnostics ¶
Calculate design diagnostics and properties.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Diagnostic metrics for the current design. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the design has not been generated. |
Source code in src/industrialstats/designs/optimal.py
CustomOptimalDesign ¶
CustomOptimalDesign(factors: list[Factor], n_runs: int, criterion_function: Callable[[ndarray], float], criterion_name: str = 'Custom')
Bases: OptimalDesign
Custom optimal design with user-defined criterion function.
Initialize custom optimal design.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factors
|
list[Factor]
|
Experimental factors. |
required |
n_runs
|
int
|
Number of experimental runs. |
required |
criterion_function
|
Callable[[ndarray], float]
|
Function that takes the model matrix |
required |
criterion_name
|
str
|
Name for the custom criterion. Defaults to |
'Custom'
|
Source code in src/industrialstats/designs/optimal.py
Advanced designs¶
industrialstats.designs.advanced ¶
Advanced experimental designs.
SplitPlotDesign ¶
SplitPlotDesign(whole_plot_factors: list[Factor], sub_plot_factors: list[Factor], replicates: int = 1, randomize: bool = True, seed: int | None = None)
Bases: ExperimentalDesign
Split-plot design with explicit whole-plot experimental units.
The design handles hard-to-change whole-plot factors and easier-to-change sub-plot factors. Each replicate of a whole-plot treatment combination is a distinct whole-plot experimental unit. Randomization is restricted so whole plots are randomized as units and sub-plots are randomized only within their parent whole plot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
whole_plot_factors
|
list[Factor]
|
Factors applied to whole plots (hard-to-change factors). |
required |
sub_plot_factors
|
list[Factor]
|
Factors applied within whole plots (easy-to-change factors). |
required |
replicates
|
int
|
Number of independent whole-plot replicates for each whole-plot
treatment combination. Defaults to |
1
|
randomize
|
bool
|
Whether to randomize whole-plot order and sub-plot order within each
whole plot. Defaults to |
True
|
seed
|
int
|
Random seed for reproducible restricted randomization. |
None
|
Examples:
Generate a split-plot design with one whole-plot factor and one sub-plot factor::
>>> from industrialstats.designs.base import Factor
>>> from industrialstats.designs.advanced import SplitPlotDesign
>>> wp = [Factor("Oven", [1, 2])]
>>> sp = [Factor("Temperature", [150, 200, 250])]
>>> design = SplitPlotDesign(wp, sp, seed=123)
>>> design.generate_design().head()
RunOrder StdOrder Replicate WholePlot SubPlot Oven Temperature
0 1 4 1 2 1 2 150
1 2 6 1 2 3 2 250
2 3 5 1 2 2 2 200
3 4 1 1 1 1 1 150
4 5 3 1 1 3 1 250
Source code in src/industrialstats/designs/advanced.py
generate_design ¶
Generate the split-plot design matrix.
Returns:
| Type | Description |
|---|---|
DataFrame
|
Generated design matrix with explicit |
Source code in src/industrialstats/designs/advanced.py
n_whole_plots ¶
Return the number of independent whole-plot experimental units.
n_runs ¶
Return the total number of sub-plot experimental runs.
Source code in src/industrialstats/designs/advanced.py
validate_design ¶
Validate split-plot design parameters.
Source code in src/industrialstats/designs/advanced.py
MixtureDesign ¶
MixtureDesign(factors: list[Factor], order: int = 2, constraints: list[Callable[[ndarray], bool]] | None = None, randomize: bool = False, seed: int | None = None)
Bases: ExperimentalDesign
Simplex-lattice mixture design.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factors
|
list[Factor]
|
Mixture components. Must contain at least three continuous factors. |
required |
order
|
int
|
Simplex-lattice degree :math: |
2
|
constraints
|
list[Callable[[ndarray], bool]]
|
Constraint functions applied to candidate mixtures. Each function
receives an array of component proportions and returns |
None
|
randomize
|
bool
|
Whether to randomize run order. Defaults to |
False
|
seed
|
int
|
Random seed for reproducible randomization. |
None
|
Examples:
Generate a simplex-lattice design for a three-component mixture::
>>> from industrialstats.designs.base import Factor
>>> from industrialstats.designs.advanced import MixtureDesign
>>> comps = [
... Factor("A", [], "continuous"),
... Factor("B", [], "continuous"),
... Factor("C", [], "continuous"),
... ]
>>> design = MixtureDesign(comps, order=2)
>>> design.generate_design()
A B C
0 1.0 0.0 0.0
1 0.0 1.0 0.0
2 0.0 0.0 1.0
3 0.5 0.5 0.0
4 0.5 0.0 0.5
5 0.0 0.5 0.5
References
.. [1] Cornell, J. A. (2011). Experiments with Mixtures.
Source code in src/industrialstats/designs/advanced.py
generate_design ¶
Generate the mixture design matrix.
Source code in src/industrialstats/designs/advanced.py
plot_simplex ¶
Plot mixture design points for three components.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ax
|
Axes
|
Axes object to plot on. Created if |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
Axes containing the simplex plot. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the design has not been generated or the number of factors is not three. |