jaxsr.rsm#

Response Surface Methodology (RSM) for JAXSR.

Provides classical DOE design generators, coded-variable handling, and surface geometry analysis (canonical form, stationary point).

The ResponseSurface convenience class wraps SymbolicRegressor and layers RSM-specific functionality on top — including design generation, ANOVA, canonical analysis, and contour plotting — while still allowing jaxsr to discover non-polynomial models when the data support it.

jaxsr.rsm.factorial_design(levels: int | list[int], n_factors: int | None = None, bounds: list[tuple[float, float]] | None = None) ndarray#

Generate a full factorial design.

Parameters:
  • levels (int or list of int) – Number of levels per factor. If a single int, all factors use the same number of levels.

  • n_factors (int, optional) – Number of factors. Required when levels is a scalar.

  • bounds (list of (float, float), optional) – If provided, the design is scaled from coded to natural units.

Returns:

X – Design matrix of shape (n_runs, n_factors).

Return type:

np.ndarray

Examples

>>> factorial_design(levels=3, n_factors=2)
array([[-1., -1.],
       [-1.,  0.],
       ...])
jaxsr.rsm.fractional_factorial_design(n_factors: int, resolution: int = 3, bounds: list[tuple[float, float]] | None = None) ndarray#

Generate a 2-level fractional factorial design.

Uses a Hadamard-like construction. For k factors at resolution III the design has 2^p runs where p is chosen so that 2^p >= k + 1.

Parameters:
  • n_factors (int) – Number of factors.

  • resolution (int) – Minimum resolution (III, IV, or V). Higher resolution avoids confounding main effects with low-order interactions.

  • bounds (list of (float, float), optional) – If provided, the design is scaled from coded to natural units.

Returns:

X – Design matrix of shape (n_runs, n_factors) with entries in {-1, +1} (or natural units if bounds given).

Return type:

np.ndarray

jaxsr.rsm.central_composite_design(n_factors: int, alpha: str | float = 'rotatable', center_points: int = 1, bounds: list[tuple[float, float]] | None = None) ndarray#

Generate a Central Composite Design (CCD).

A CCD consists of:

  • A 2^k factorial cube (corners at +/-1).

  • 2k axial (star) points at +/-alpha along each axis.

  • Center point(s) at the origin.

Parameters:
  • n_factors (int) – Number of factors k.

  • alpha (str or float) –

    Axial distance. Special values:

    • "rotatable" — alpha = (2^k)^{1/4} for rotatability.

    • "face" — alpha = 1 (face-centered, all points within the cube).

    • A float for a custom distance.

  • center_points (int) – Number of center-point replicates.

  • bounds (list of (float, float), optional) – If provided, the design is scaled from coded to natural units.

Returns:

X – Design matrix of shape (n_runs, n_factors).

Return type:

np.ndarray

Examples

>>> ccd = central_composite_design(3, alpha="face", center_points=3)
>>> ccd.shape
(17, 3)
jaxsr.rsm.box_behnken_design(n_factors: int, center_points: int = 1, bounds: list[tuple[float, float]] | None = None) ndarray#

Generate a Box-Behnken design.

A Box-Behnken design avoids extreme corners (no point where all factors are simultaneously at their high or low levels), making it useful when those combinations are infeasible.

Parameters:
  • n_factors (int) – Number of factors (must be >= 3).

  • center_points (int) – Number of center-point replicates.

  • bounds (list of (float, float), optional) – If provided, the design is scaled from coded to natural units.

Returns:

X – Design matrix of shape (n_runs, n_factors).

Return type:

np.ndarray

Raises:

ValueError – If n_factors < 3.

jaxsr.rsm.encode(X: ndarray, bounds: list[tuple[float, float]]) ndarray#

Convert natural-unit variables to coded [-1, +1] variables.

Parameters:
  • X (array-like of shape (n, k)) – Design points in natural units.

  • bounds (list of (low, high)) – Natural-unit bounds for each factor.

Returns:

X_coded – Coded design matrix.

Return type:

np.ndarray

jaxsr.rsm.decode(X_coded: ndarray, bounds: list[tuple[float, float]]) ndarray#

Convert coded [-1, +1] variables to natural units.

Parameters:
  • X_coded (array-like of shape (n, k)) – Design points in coded units.

  • bounds (list of (low, high)) – Natural-unit bounds for each factor.

Returns:

X – Design matrix in natural units.

Return type:

np.ndarray

class jaxsr.rsm.CanonicalAnalysis(stationary_point: ~numpy.ndarray, stationary_response: float, eigenvalues: ~numpy.ndarray, eigenvectors: ~numpy.ndarray, nature: str, b_vector: ~numpy.ndarray, B_matrix: ~numpy.ndarray, warnings: list[str] = <factory>)#

Bases: object

Result of canonical analysis on a fitted quadratic surface.

Parameters:
  • stationary_point (np.ndarray) – Location of the stationary point (coded or natural units).

  • stationary_response (float) – Predicted response at the stationary point.

  • eigenvalues (np.ndarray) – Eigenvalues of the B matrix (second-order coefficient matrix).

  • eigenvectors (np.ndarray) – Corresponding eigenvectors (columns).

  • nature (str) – Classification: "minimum", "maximum", or "saddle".

  • b_vector (np.ndarray) – First-order coefficient vector.

  • B_matrix (np.ndarray) – Second-order coefficient matrix (symmetric).

  • warnings (list of str) – Diagnostic messages.

stationary_point: ndarray#
stationary_response: float#
eigenvalues: ndarray#
eigenvectors: ndarray#
nature: str#
b_vector: ndarray#
B_matrix: ndarray#
warnings: list[str]#
jaxsr.rsm.canonical_analysis(model: SymbolicRegressor, bounds: list[tuple[float, float]] | None = None) CanonicalAnalysis#

Perform canonical analysis on a fitted quadratic model.

Extracts the first-order vector b and second-order matrix B from the model’s expression, computes the stationary point x_s = -0.5 B^{-1} b, and classifies the surface via the eigenvalues of B.

The analysis works directly with whatever basis terms the model selected. If the model is not purely quadratic (e.g. it includes log(x) terms), a warning is emitted and only the quadratic portion is analysed.

Parameters:
  • model (SymbolicRegressor) – A fitted model.

  • bounds (list of (float, float), optional) – Factor bounds. If provided, the stationary point is reported in natural units; otherwise in the model’s native units.

Return type:

CanonicalAnalysis

class jaxsr.rsm.ResponseSurface(n_factors: int, bounds: list[tuple[float, float]], factor_names: list[str] | None = None, max_degree: int = 2, include_interactions: bool = True, max_terms: int | None = None, strategy: str = 'greedy_forward', allow_transcendental: bool = False, feature_types: list[str] | None = None, categories: dict[int, list] | None = None)#

Bases: object

Convenience class combining DOE design, fitting, and RSM analysis.

Wraps SymbolicRegressor and adds:

  • Design generation (CCD, Box-Behnken, factorial).

  • Coded / natural variable bookkeeping.

  • ANOVA on the fitted model.

  • Canonical analysis (stationary point, eigenvalues, classification).

  • Contour plotting.

The model is fitted using jaxsr’s symbolic regression, so it may discover that a simpler or non-polynomial expression is more parsimonious. Canonical analysis gracefully handles this by warning and analysing only the quadratic portion.

Parameters:
  • n_factors (int) – Number of input factors.

  • bounds (list of (float, float)) – Natural-unit bounds for each factor.

  • factor_names (list of str, optional) – Human-readable factor names.

  • max_degree (int) – Maximum polynomial degree for the basis library (default 2 for classical RSM; set to 3 if you want cubic terms too).

  • include_interactions (bool) – Include interaction terms (default True).

  • max_terms (int, optional) – Maximum number of terms the regressor may select.

  • strategy (str) – Feature-selection strategy (default "greedy_forward").

  • allow_transcendental (bool) – If True, also add ["log", "exp", "sqrt", "inv"] to the basis library so jaxsr can discover non-polynomial models.

Examples

>>> rs = ResponseSurface(
...     n_factors=3,
...     bounds=[(300, 500), (1, 10), (0.01, 0.5)],
...     factor_names=["T", "P", "C"],
... )
>>> X = rs.ccd(center_points=3)
>>> y = run_experiments(X)
>>> rs.fit(X, y)
>>> print(rs.model.expression_)
>>> print(rs.anova())
>>> print(rs.canonical())
ccd(alpha: str | float = 'rotatable', center_points: int = 1) ndarray#

Generate a Central Composite Design in natural units.

Parameters:
  • alpha (str or float) – "rotatable", "face", or a custom float.

  • center_points (int) – Number of center-point replicates.

Returns:

X – Design matrix in natural units.

Return type:

np.ndarray

box_behnken(center_points: int = 1) ndarray#

Generate a Box-Behnken design in natural units.

Parameters:

center_points (int) – Number of center-point replicates.

Returns:

X

Return type:

np.ndarray

factorial(levels: int = 2) ndarray#

Generate a full factorial design in natural units.

Parameters:

levels (int) – Number of levels per factor.

Returns:

X

Return type:

np.ndarray

fractional_factorial(resolution: int = 3) ndarray#

Generate a fractional factorial design in natural units.

Parameters:

resolution (int) – Minimum resolution (3, 4, or 5).

Returns:

X

Return type:

np.ndarray

fit(X: ndarray | Array, y: ndarray | Array) ResponseSurface#

Fit the response-surface model.

Parameters:
  • X (array-like of shape (n, n_factors)) – Input data in natural units.

  • y (array-like of shape (n,)) – Observed responses.

Return type:

self

anova(anova_type: str = 'sequential')#

Run ANOVA on the fitted model.

See jaxsr.uncertainty.anova() for details.

canonical() CanonicalAnalysis#

Perform canonical analysis (stationary point, eigenvalues).

The stationary point is returned in natural units.

predict(X: ndarray | Array) Array#

Predict response at new points (natural units).

encode(X: ndarray) ndarray#

Convert natural units to coded [-1, +1] variables.

decode(X_coded: ndarray) ndarray#

Convert coded [-1, +1] variables to natural units.

plot_contour(factors: tuple[int, int] = (0, 1), fixed: dict[int, float] | None = None, n_grid: int = 50, levels: int = 15, ax=None, figsize: tuple[int, int] = (8, 6), filled: bool = True, show_design: bool = True)#

Plot 2D contour of the response surface.

Parameters:
  • factors ((int, int)) – Indices of the two factors to vary.

  • fixed (dict, optional) – {factor_index: value} for held-constant factors (natural units). Factors not in factors or fixed default to their midpoint.

  • n_grid (int) – Grid resolution per axis.

  • levels (int) – Number of contour levels.

  • ax (matplotlib Axes, optional) – If None, a new figure is created.

  • figsize (tuple) – Figure size.

  • filled (bool) – If True, use filled contours; otherwise contour lines only.

  • show_design (bool) – If True and the model has training data, overlay the design points.

Returns:

ax

Return type:

matplotlib Axes

plot_surface(factors: tuple[int, int] = (0, 1), fixed: dict[int, float] | None = None, n_grid: int = 50, ax=None, figsize: tuple[int, int] = (10, 8))#

Plot 3D surface of the response.

Parameters are the same as plot_contour() except there are no levels or filled options.

Returns:

ax

Return type:

matplotlib 3D Axes

summary() str#

Return a text summary of the fitted response surface.