Skip to content

Designs

Design container

design

Design entity and metadata helpers.

Design dataclass

Design(matrix, factors=list(), model=None, metadata=dict())

A generated experimental design with run matrix, factors, and model.

The run matrix holds factor levels (natural or coded units depending on generation). Optional :class:~doekit.domain.factors.Factor objects and a :class:~doekit.domain.model.Model enable coding, model-matrix construction, and evaluation. Metadata carries design-kind tags (resolution, generators, etc.).

Prefer :meth:replace or constructing a new instance over mutating fields in place so callers keep stable references.

Parameters:

Name Type Description Default
matrix DataFrame

Run-by-factor table; column names are factor names.

required
factors list

Typed factor objects for encode/decode (may be empty).

list()
model Model

Model attached for matrix construction and evaluation.

None
metadata dict

Free-form tags (kind, resolution, generators, etc.).

dict()

Examples:

>>> import doekit as ed
>>> d = ed.full_factorial(2)
>>> d.n_runs, d.n_factors
(4, 2)

factor_names property

factor_names

Column names of the run matrix.

n_factors property

n_factors

Number of factor columns in matrix.

n_runs property

n_runs

Number of experimental runs (rows in matrix).

from_dict classmethod

from_dict(d)

Rebuild a :class:Design from a :meth:to_dict payload.

Parameters:

Name Type Description Default
d dict

Serialized design (schema doekit.Design/1).

required

Returns:

Type Description
Design

Restored design instance.

from_json classmethod

from_json(s)

Rebuild a :class:Design from a JSON string.

Parameters:

Name Type Description Default
s str

JSON from :meth:to_json.

required

Returns:

Type Description
Design

Restored design instance.

model_matrix

model_matrix()

Build the model matrix X from the run matrix and attached model.

Returns:

Type Description
(ndarray, shape(n_runs, n_params))

Model matrix in the units implied by matrix and model.

Raises:

Type Description
ValueError

When no model is attached.

replace

replace(**kwargs)

Return a new Design with selected fields replaced (copy-on-write).

Parameters:

Name Type Description Default
**kwargs

Fields to override (matrix, factors, model, metadata).

{}

Returns:

Type Description
Design

A new instance; the original is unchanged.

Examples:

>>> import doekit as ed
>>> d = ed.full_factorial(2)
>>> d2 = d.replace(metadata={"note": "copy"})
>>> d2.metadata["note"]
'copy'

to_dict

to_dict()

Serialize the design to a JSON-compatible dict.

Returns:

Type Description
dict

Schema doekit.Design/1 with matrix, factors, model, and metadata keys.

to_json

to_json(**kwargs)

Serialize the design to a JSON string.

Parameters:

Name Type Description Default
**kwargs

Forwarded to :func:json.dumps (e.g. indent=2).

{}

Returns:

Type Description
str

JSON representation of :meth:to_dict.

DesignMetadata

Bases: TypedDict

Known metadata keys; unknown keys remain allowed via plain dict merge.

get_kind

get_kind(metadata)

Return the design kind tag if present.

with_kind

with_kind(metadata, kind)

Return a copy of metadata with kind set.

Factorial

factorial

Full and fractional factorial designs.

  • full_factorial: every level combination (explicit or lazy iterator).
  • fractional_factorial: a real 2^(k-p) fraction from generators, with the defining relation, resolution and alias structure.

fractional_factorial

fractional_factorial(
    n_factors, generators, names=None, model=None
)

Build a real 2^(k-p) fractional factorial design.

Base factors form a full 2^(k-p) factorial at ±1; generated factors are products of base columns. Metadata includes defining relation, resolution, and alias classes.

Formulas

Generator D = ABC implies column D = A * B * C (element-wise product of ±1 columns). Defining relation from the group generated by generators under symmetric difference; resolution = length of shortest word ≠ I.

Parameters:

Name Type Description Default
n_factors int

Total number of factors k.

required
generators sequence of str

Definition of the p extra factors as products of the base factors, e.g. ["C=AB"] for 2^(3-1) or ["D=AB", "E=AC"] for 2^(5-2). Letters A, B, ... refer to the factors in order.

required
names sequence of str

Factor names; defaults to factor1..factorn.

None
model Model

Model to attach to the design.

None

Returns:

Type Description
Design

The fractional design, carrying in metadata the generators, defining_relation, resolution and aliases (alias classes).

Raises:

Type Description
ValueError

When generators are inconsistent with n_factors or reference unknown base factors.

Examples:

>>> import doekit as ed
>>> d = ed.fractional_factorial(3, ["C=AB"])
>>> d.metadata["resolution"]
'III'

full_factorial

full_factorial(levels, names=None, model=None, lazy=False)

Build a full factorial design (all level combinations).

The Cartesian product uses the first factor varying fastest (standard DoE ordering). Pass lazy=True to stream rows without materializing the full matrix.

Parameters:

Name Type Description Default
levels int or dict or list of list

An integer (n two-level factors), a dict {name: [levels]} or a list of level lists.

required
names sequence of str

Factor names; defaults to factor1..factorn.

None
model Model

Model to attach to the design.

None
lazy bool

If True, return a row iterator instead of materializing the matrix.

False

Returns:

Type Description
Design or iterator of dict

The full factorial design, or a row iterator when lazy=True.

Examples:

>>> import doekit as ed
>>> d = ed.full_factorial(2)
>>> d.n_runs, d.n_factors
(4, 2)

Screening

screening

Screening designs: Plackett-Burman, fold and a PB check.

Plackett-Burman designs from Hadamard matrices via Sylvester and Paley I/II, covering multiples-of-4 orders at the minimum number of runs. Every constructed matrix is validated as Hadamard before use; if an order is not constructible by these methods the next one is used.

fold

fold(design)

Duplicate a design by appending its sign-reflected mirror (foldover).

Every interaction aliased with a main effect is de-confounded, raising the resolution of fractional factorials.

Parameters:

Name Type Description Default
design Design

The design to fold.

required

Returns:

Type Description
Design

Folded design with 2N runs.

Examples:

>>> import doekit as ed
>>> d = ed.full_factorial(2)
>>> ed.fold(d).n_runs == 2 * d.n_runs
True

is_plackett_burman

is_plackett_burman(design, tol=1e-08)

Check whether a matrix satisfies Plackett-Burman defining properties.

Requires the three defining PB properties (entrywise, not aggregate):

  1. entries are +/-1 (balanced two-level design);
  2. each column sums to zero (D.sum(axis=0) == 0);
  3. columns are entrywise orthogonal: D^T D = N I.
Formulas

Orthogonality: D^T D = N I where N is the number of runs.

Parameters:

Name Type Description Default
design Design or array - like

The design (or its matrix) to check.

required
tol float

Absolute tolerance for the zero-sum and orthogonality checks.

1e-8

Returns:

Type Description
bool

Whether all three properties hold.

Examples:

>>> import doekit as ed
>>> ed.is_plackett_burman(ed.plackett_burman(4))
True

plackett_burman

plackett_burman(n_factors, names=None, model=None)

Build a Plackett-Burman screening design for n_factors factors.

Uses the smallest constructible Hadamard matrix (Sylvester/Paley) with N-1 >= n_factors. Returns N runs; surplus columns beyond n_factors are dummy factors (possible alias sinks).

Formulas

Design columns are zero-sum: sum_j d_ij = 0; orthogonality: D^T D = N I (Hadamard property).

Parameters:

Name Type Description Default
n_factors int

Number of real factors to screen.

required
names list of str

Names of the real factors; defaults to factor1..factorn.

None
model Model

Model to attach; defaults to a no-intercept main-effects model.

None

Returns:

Type Description
Design

Plackett-Burman design with order, factors and dummy_factors in metadata.

Examples:

>>> import doekit as ed
>>> d = ed.plackett_burman(4)
>>> d.n_runs >= 4
True

Definitive screening

definitive

Definitive Screening Designs (DSD), Jones & Nachtsheim (2011).

In 2*m+1 runs (for m factors) they allow you to:

  • estimate all main effects free of bias from two-factor interactions and curvature (main effects orthogonal to the second-order terms);
  • estimate quadratic effects of all factors (3 levels: -1, 0, +1);
  • project onto response surfaces in the few active factors without additional experiments.

Construction: given a conference matrix C of order m (zero diagonal, +/-1 off-diagonal, C^T C = (m-1) I), the DSD is::

[[ C ],
 [-C ],
 [ 0 ]]

The C/-C fold makes the linear effects (odd functions) orthogonal to the quadratics and interactions (even functions). Here the conference matrices are generated by the Paley construction (order q+1 with q prime), covering orders 4, 6, 8, 12, 14, 18, 20, 24, ....

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.

definitive_screening

definitive_screening(factors, extra_center=0, model=None)

Build a Definitive Screening Design (DSD) for the given factors.

In 2*m+1 runs (for m factors) estimates main effects free of two-factor interactions and curvature, supports quadratic terms, and projects onto active-factor RSM without extra runs (Jones & Nachtsheim, 2011).

Formulas

From conference matrix C (zero diagonal, C^T C = (m-1) I):

DSD = [C; -C; 0] stacked vertically.

Parameters:

Name Type Description Default
factors int or dict or sequence of Factor

An integer (m factors coded in -1/0/+1), a dict {name: (low, high)} or a list of :class:Factor (the matrix is decoded to natural units using low -> -1, mid -> 0, high -> +1).

required
extra_center int

Number of additional center points.

0
model Model

Model to attach; defaults to a main-effects model with intercept.

None

Returns:

Type Description
Design

DSD in 2*m0+1 runs, where m0 is the smallest constructible conference order >= m. When m0 > m surplus columns are dropped (phantom factors). metadata carries conference_order, n_center and phantom_factors.

Raises:

Type Description
ValueError

If fewer than 2 factors are given.

Examples:

>>> import doekit as ed
>>> d = ed.definitive_screening(4)
>>> d.n_factors
4

Response surface

response_surface

Response-surface designs: Box-Behnken and Central Composite.

Classic constructions (Box & Behnken; Central Composite) with:

  • factors that accept a natural range and decode the matrix to real units;
  • a configurable number of center points.

box_behnken

box_behnken(factors, center=None, model=None)

Build a Box-Behnken response-surface design.

Three-level design on the edges of the hypercube (no corner runs), requiring at least three factors. Center points improve pure-error estimation.

Parameters:

Name Type Description Default
factors int or dict or sequence of Factor

An integer (coded columns) or factors with a natural range (the matrix is decoded to real units).

required
center int

Number of center points; defaults to the classical suggestion for the given number of factors.

None
model Model

Model to attach; defaults to a full quadratic model.

None

Returns:

Type Description
Design

Box-Behnken design (requires >= 3 factors).

Raises:

Type Description
ValueError

If fewer than 3 factors are given.

Examples:

>>> import doekit as ed
>>> d = ed.box_behnken(3)
>>> d.n_factors
3

central_composite

central_composite(
    factors,
    center=(4, 4),
    alpha="orthogonal",
    face="circumscribed",
    model=None,
)

Build a Central Composite design (CCD).

Combines a factorial block, star (axial) points, and center replicates. alpha controls axial distance; face selects inscribed, faced, or circumscribed placement.

Formulas

Rotatable: alpha = 2^(k/4); orthogonal and faced rules as in Box & Wilson.

Parameters:

Name Type Description Default
factors int or dict or sequence of Factor

An integer (coded columns) or factors with a natural range (decoded).

required
center sequence of int

Center points (nc_factorial, nc_star).

(4, 4)
alpha ('orthogonal', 'rotatable', 'faced')

Star-distance rule.

"orthogonal"
face ('circumscribed', 'inscribed', 'faced')

Placement of the factorial/star blocks.

"circumscribed"
model Model

Model to attach; defaults to a full quadratic model.

None

Returns:

Type Description
Design

CCD with alpha_value, alpha, face and center in metadata (requires >= 2 factors).

Raises:

Type Description
ValueError

If fewer than 2 factors are given.

Examples:

>>> import doekit as ed
>>> d = ed.central_composite(2)
>>> d.n_factors
2

Random / space-filling

random_design

Random designs: sampling from distributions and Latin Hypercube.

Uses scipy.stats for independent draws and scipy.stats.qmc for Latin Hypercube Sampling.

latin_hypercube

latin_hypercube(
    factors, n, optimize=False, seed=None, model=None
)

Build a Latin Hypercube design (space-filling sample).

Each factor is stratified into n equal-probability intervals with one sample per interval. Optional discrepancy minimization improves coverage.

Parameters:

Name Type Description Default
factors int or sequence of Factor

An integer (columns in [0, 1)) or continuous/discrete factors (scaled to their natural range).

required
n int

Number of runs to sample.

required
optimize bool

If True, use scipy's discrepancy-minimizing variant (better space coverage).

False
seed int

Seed for the sampler.

None
model Model

Model to attach to the design.

None

Returns:

Type Description
Design

Latin Hypercube design with metadata['kind']='LatinHypercube'.

Examples:

>>> import doekit as ed
>>> d = ed.latin_hypercube(3, n=10, seed=0)
>>> d.n_runs, d.n_factors
(10, 3)

random_design

random_design(factors, n, seed=None, model=None)

Generate n random experimental runs.

Draws independently from scipy.stats distributions (dict spec) or uniform/choice sampling over factor ranges and levels.

Parameters:

Name Type Description Default
factors dict or sequence of Factor

Either a dict {name: dist} of scipy.stats distributions (uses .rvs), or a list of :class:Factor (uniform over the range, or a choice of levels).

required
n int

Number of runs to sample.

required
seed int

Seed for the random generator.

None
model Model

Model to attach to the design.

None

Returns:

Type Description
Design

Random design with metadata['kind']='RandomDesign'.

Examples:

>>> import doekit as ed
>>> d = ed.random_design(ed.as_factors(2), n=5, seed=0)
>>> d.n_runs
5

Mixture

mixture

Mixture designs on the simplex (Scheffé lattice / centroid).

simplex_centroid

simplex_centroid(factors, model=None)

Build a simplex-centroid design (pure blends through overall centroid).

For q components, includes every point with equal proportions among any non-empty subset of components (2^q - 1 runs). Covers vertices, edge midpoints, face centroids, and the overall centroid.

Formulas

For subset S of size r: x_i = 1/r if i in S, else 0.

Parameters:

Name Type Description Default
factors int, dict, or sequence of Factor

Mixture components (q >= 2).

required
model Model

Defaults to Scheffé quadratic.

None

Returns:

Type Description
Design

Centroid design with proportions summing to 1 per row.

Raises:

Type Description
InapplicableDesign

When fewer than two mixture components.

Examples:

>>> import doekit as ed
>>> d = ed.simplex_centroid(3)
>>> d.n_runs == 2**3 - 1
True

simplex_lattice

simplex_lattice(factors, degree=2, model=None)

Build a {q, m}-simplex lattice design (Scheffé).

Places runs at lattice points where each proportion is a multiple of 1/m on the (q-1)-simplex. Lower bounds on components shift the lattice within the feasible simplex.

Formulas

Lattice points: x_i = k_i / m with k_i >= 0 and sum_i k_i = m.

Parameters:

Name Type Description Default
factors int, dict, or sequence of Factor

Mixture components (q). An int names them x1..xq.

required
degree int

Lattice order m (proportions are multiples of 1/m).

2
model Model

Defaults to Scheffé linear (m=1) or quadratic (m>=2).

None

Returns:

Type Description
Design

Rows are proportions summing to 1; metadata kind='SimplexLattice'.

Raises:

Type Description
ValueError

When degree < 1 or lower bounds sum to more than 1.

InapplicableDesign

When fewer than two mixture components.

Examples:

>>> import doekit as ed
>>> d = ed.simplex_lattice(3, degree=2)
>>> d.n_runs > 0 and abs(d.matrix.sum(axis=1) - 1.0).max() < 1e-9
True

Split-plot

split_plot

Minimal split-plot design generation (whole-plot / subplot structure).

split_plot_design

split_plot_design(
    whole_plot,
    subplot,
    *,
    n_whole_plots=None,
    whole_plot_reps=1,
    model=None,
    seed=None,
)

Build a simple split-plot design (whole-plot / subplot structure).

Whole-plot (hard-to-change) factor combinations define plots; within each plot, all subplot factor combinations are run. Plot identity is stored in column whole_plot_id for mixed-model analysis (fit_mixed_model(..., groups="whole_plot_id")).

Parameters:

Name Type Description Default
whole_plot factor spec

Hard-to-change factors (int / dict / sequence of Factor).

required
subplot factor spec

Easy-to-change factors within a plot.

required
n_whole_plots int

If set, sample this many whole-plot level combinations (with replacement across the WP factorial); default = full WP factorial times whole_plot_reps.

None
whole_plot_reps int

Replicates of each whole-plot combination when n_whole_plots is None.

1
model Model

Defaults to main effects of all treatment factors (no plot id).

None
seed int

RNG seed when sampling whole plots.

None

Returns:

Type Description
Design

Matrix includes treatment columns plus whole_plot_id.

Raises:

Type Description
InapplicableDesign

When whole_plot or subplot is empty or factor types are unsupported.

ValueError

When factor names overlap or n_whole_plots < 1.

Examples:

>>> import doekit as ed
>>> d = ed.split_plot_design(whole_plot=1, subplot=2)
>>> "whole_plot_id" in d.matrix.columns
True

Optimal

optimal

Optimal design: KL-exchange (D-optimal) and Fedorov (generic criterion).

  • choice of criterion (D/A/I/...);
  • KL-exchange for D-optimality and Fedorov for generic criteria;
  • multi-start (n_starts) to escape local optima;
  • all criteria of the final design are reported.

The seed-growth phase adds candidates greedily by largest prediction variance.

fedorov_exchange

fedorov_exchange(
    model_matrix,
    experiments,
    criterion_fn,
    n_restarts_rows=None,
    max_iterations=1000,
    tolerance=1e-09,
    rng=None,
    moment_matrix=None,
)

Run Fedorov exchange for a generic optimality criterion.

Tries swapping each design row for each candidate and applies the best swap until there is no improvement. Works with any registered criterion (D, A, I, etc.).

Parameters:

Name Type Description Default
model_matrix (ndarray, shape(N, p))

Model matrix of the candidate set.

required
experiments int

Number of runs to select.

required
criterion_fn callable

Criterion function fn(X) (or fn(X, moment_matrix) for I).

required
n_restarts_rows int

Unused placeholder kept for signature compatibility.

None
max_iterations int

Maximum number of exchange iterations.

1000
tolerance float

Minimum gain required to accept a swap.

1e-9
rng Generator

Random generator for the initial selection.

None
moment_matrix ndarray

Region moment matrix passed to the criterion (used by I-optimality).

None

Returns:

Type Description
list of int

Indices of the selected rows into model_matrix.

kl_exchange

kl_exchange(
    model_matrix,
    experiments,
    design_k=None,
    candidates_l=None,
    seed_design_size=2,
    max_iterations=1000,
    tolerance=1e-09,
    rng=None,
)

Run KL-exchange to select a D-optimal subset of rows.

Greedy seed growth by maximum leverage, then pairwise exchanges between low-leverage design rows and high-leverage candidates that improve the D-efficiency determinant criterion.

Formulas

Exchange gain uses leverage h_ii = x_i' (X'X)^-1 x_i; a swap is accepted when the KL delta exceeds 1 (Cook & Nachtsheim exchange for D-optimality).

Parameters:

Name Type Description Default
model_matrix (ndarray, shape(N, p))

Model matrix of the candidate set; the returned indices refer to its rows.

required
experiments int

Number of runs to select.

required
design_k int

Sizes of the exchange pools (worst design rows / best candidates).

None
candidates_l int

Sizes of the exchange pools (worst design rows / best candidates).

None
seed_design_size int

Size of the initial random seed before greedy growth.

2
max_iterations int

Maximum number of exchange iterations.

1000
tolerance float

Ridge and stopping tolerance.

1e-9
rng Generator

Random generator for the seed selection.

None

Returns:

Type Description
list of int

Indices of the selected rows into model_matrix.

optimal_design

optimal_design(
    candidates,
    n_runs,
    model=None,
    criterion="D",
    algorithm=None,
    n_starts=1,
    seed=None,
    tolerance=1e-09,
    report=None,
    **kl_kwargs,
)

Select n_runs optimal runs from a candidate set.

Supports D/A/T/G/E/I criteria via KL-exchange (D only) or Fedorov exchange. Multi-start restarts escape local optima; final criteria scores are stored in metadata.

Formulas

Optimizes the chosen criterion (see :func:~doekit.domain.criteria.d_criterion etc.); D-optimality uses KL-exchange on det(X'X)^(1/p).

Parameters:

Name Type Description Default
candidates Design

The candidate set (e.g. from random_design or full_factorial).

required
n_runs int

Number of runs to select.

required
model Model

Model to optimize; taken from candidates.model if omitted.

None
criterion ('D', 'A', 'T', 'G', 'E', 'I')

Optimality criterion.

"D"
algorithm ('kl', 'fedorov')

"kl" (D only) or "fedorov" (any criterion); defaults to KL for D and Fedorov otherwise.

"kl"
n_starts int

Number of independent restarts; the best design is returned.

1
seed int

Seed controlling all restarts.

None
tolerance float

Ridge and stopping tolerance.

1e-9
report (None, bool, str, Path or dict)

If not None, a design-quality HTML report is generated and its path is stored in result.metadata["report_path"].

None
**kl_kwargs

Extra keyword arguments forwarded to :func:kl_exchange.

{}

Returns:

Type Description
Design

Optimal subset with criterion, algorithm, selected_rows and all final criteria in metadata.

Raises:

Type Description
ValueError

If no model is available, or algorithm is unknown.

Examples:

>>> import doekit as ed
>>> cand = ed.random_design(ed.as_factors(2), n=50, seed=0)
>>> cand.model = ed.Model.main_effects(["factor1", "factor2"])
>>> opt = ed.optimal_design(cand, n_runs=8, seed=0)
>>> opt.n_runs
8

Criteria

criteria

Optimality criteria over the model matrix X (N x p).

Default numerical tolerance 1e-9. Convention: larger is better for every function, so that optimal_design always maximizes the chosen criterion.

CriterionContext dataclass

CriterionContext(moment_matrix=None, tolerance=None)

Optional extras a criterion may need (e.g. I-optimality moments).

a_criterion

a_criterion(model_matrix, tolerance=TOLERANCE)

A-optimality score for a model matrix (larger is better).

Penalizes the average variance of coefficient estimates. Inverse of the trace of the variance-covariance matrix, normalized by run count.

Formulas

score = p / tr((X'X)^-1) / N

where p is the number of parameters and N the number of runs.

Parameters:

Name Type Description Default
model_matrix (ndarray, shape(N, p))

Model matrix X in coded units.

required
tolerance float

Ridge added to X'X before inversion.

1e-9

Returns:

Type Description
float

A-optimality score; 0.0 when X'X is singular.

Examples:

>>> import doekit as ed
>>> d = ed.full_factorial(3)
>>> X = ed.Model.main_effects(d.factor_names).matrix(d.matrix)
>>> ed.a_criterion(X) > 0.9
True

all_criteria

all_criteria(model_matrix, context=None)

Evaluate every registered criterion on a design matrix.

Convenience wrapper for reporting; each entry is scored via :func:score_criterion so I-optimality receives region moments from context when provided.

Parameters:

Name Type Description Default
model_matrix (ndarray, shape(N, p))

Model matrix of the design.

required
context CriterionContext

Shared context (tolerance, moment matrix for I).

None

Returns:

Type Description
dict

Mapping {"D": score, "A": score, ...} with one float per criterion.

Examples:

>>> import doekit as ed
>>> from doekit.domain.criteria import all_criteria
>>> d = ed.full_factorial(3)
>>> X = ed.Model.main_effects(d.factor_names).matrix(d.matrix)
>>> sorted(all_criteria(X)) == ["A", "D", "E", "G", "I", "T"]
True

d_criterion

d_criterion(model_matrix, tolerance=TOLERANCE)

D-optimality score for a model matrix (larger is better).

Normalizes the information matrix by N before taking the geometric mean of eigenvalues. Used by exchange algorithms and design comparison.

Formulas

score = det((X'X) / N)^(1/p)

where N is the number of runs and p is the number of parameters. Equivalent to maximizing det(X'X)^(1/p) / N.

Parameters:

Name Type Description Default
model_matrix (ndarray, shape(N, p))

Model matrix X in coded units.

required
tolerance float

Ridge added to X'X before the determinant (via :func:info_matrix).

1e-9

Returns:

Type Description
float

D-optimality score; 0.0 when X'X is singular or non-positive.

Examples:

>>> import doekit as ed
>>> d = ed.full_factorial(3)
>>> X = ed.Model.main_effects(d.factor_names).matrix(d.matrix)
>>> ed.d_criterion(X) > 0.9
True

e_criterion

e_criterion(model_matrix, tolerance=0.0)

E-optimality score for a model matrix (larger is better).

Maximizes the smallest eigenvalue of the normalized information matrix, guarding against near-singular directions in parameter space.

Formulas

score = min(eig(X'X)) / N

Parameters:

Name Type Description Default
model_matrix (ndarray, shape(N, p))

Model matrix X in coded units.

required
tolerance float

Ridge added to X'X before eigenvalues are computed.

0.0

Returns:

Type Description
float

E-optimality score (smallest eigenvalue of X'X / N).

Examples:

>>> import doekit as ed
>>> d = ed.full_factorial(3)
>>> X = ed.Model.main_effects(d.factor_names).matrix(d.matrix)
>>> ed.e_criterion(X) > 0
True

g_criterion

g_criterion(model_matrix, tolerance=TOLERANCE)

G-optimality score for a model matrix (larger is better).

Minimizes the maximum prediction variance over design points (equivalence theorem links G- and D-optimality under regularity).

Formulas

score = p / max(diag(H))

where H = X (X'X)^-1 X' is the hat matrix and p the number of parameters. max(diag(H)) is the maximum leverage among design rows.

Parameters:

Name Type Description Default
model_matrix (ndarray, shape(N, p))

Model matrix X in coded units.

required
tolerance float

Ridge added to X'X before inversion.

1e-9

Returns:

Type Description
float

G-optimality score; 0.0 when X'X is singular.

Examples:

>>> import doekit as ed
>>> d = ed.full_factorial(3)
>>> X = ed.Model.main_effects(d.factor_names).matrix(d.matrix)
>>> ed.g_criterion(X) > 0.9
True

get_criterion

get_criterion(name)

Look up a criterion function by name.

Parameters:

Name Type Description Default
name str

Criterion key: "D", "A", "T", "G", "E", or "I" (case-insensitive).

required

Returns:

Type Description
callable

The registered criterion function.

Raises:

Type Description
UnknownCriterionError

When name is not a registered criterion.

Examples:

>>> from doekit.domain.criteria import get_criterion
>>> import doekit as ed
>>> fn = get_criterion("D")
>>> fn is ed.d_criterion
True

i_criterion

i_criterion(
    model_matrix, moment_matrix=None, tolerance=TOLERANCE
)

I-optimality score for a model matrix (larger is better).

Minimizes average prediction variance over a region; the score is the reciprocal of that mean variance.

Formulas

mean_var = tr((X'X)^-1 W) with W = (R'R) / n_R

where R is the region moment matrix (defaults to X when omitted). score = 1 / mean_var.

Parameters:

Name Type Description Default
model_matrix (ndarray, shape(N, p))

Model matrix X of the selected design.

required
moment_matrix ndarray

Model matrix R evaluated on a region sample (required for true I-optimality; defaults to X when omitted).

None
tolerance float

Ridge added to X'X before inversion.

1e-9

Returns:

Type Description
float

I-optimality score; 0.0 when X'X is singular.

Examples:

>>> import doekit as ed
>>> d = ed.full_factorial(3)
>>> X = ed.Model.main_effects(d.factor_names).matrix(d.matrix)
>>> ed.i_criterion(X) > 0
True

info_matrix

info_matrix(X, tolerance)

Return the (Tikhonov-regularized) information matrix X'X + tol*I.

inv_info

inv_info(X_sel, tolerance)

Inverse of the ridge-regularized information matrix of selected rows.

leverage

leverage(Xr, Minv)

Return x' M^-1 x per row (unscaled prediction variance).

score_criterion

score_criterion(fn, model_matrix, context=None)

Invoke a criterion with a uniform (X, context) contract.

Legacy callables that only accept X (or X, moment_matrix=... for I) are adapted here so search/evaluation never special-case signatures.

t_criterion

t_criterion(model_matrix, tolerance=0.0)

T-optimality score for a model matrix (larger is better).

Rewards designs with large total information (trace of X'X), normalized per parameter and run.

Formulas

score = tr(X'X) / N / p

Parameters:

Name Type Description Default
model_matrix (ndarray, shape(N, p))

Model matrix X in coded units.

required
tolerance float

Ridge added to X'X (usually zero for T).

0.0

Returns:

Type Description
float

T-optimality score.

Examples:

>>> import doekit as ed
>>> d = ed.full_factorial(3)
>>> X = ed.Model.main_effects(d.factor_names).matrix(d.matrix)
>>> ed.t_criterion(X) > 0
True