Changelog#
[1.0.0]#
Added#
Advanced Experimental Designer (
AdvExpDesigner) — a new design engine that drops into aCampaignasdesigner=:Continuous factors with configurable spacing (linear/geometric/logarithmic/explicit levels) and non-uniform sampling bias, drawn via stratified LHS
Conditional subparameters — hierarchical/nested factors (e.g. buffer type → pH range) with per-level frequency weights
D-optimal design optimization with parallel candidate search, seven quality metrics (D-/A-optimality, condition number, space-filling, continuous/categorical/mixed correlation), and category-correlation minimization for orthogonal categoricals
extend_design()for design augmentation / sequential DOEBuilt-in visualization: histograms, mixed-correlation heatmap, quality-evolution bars, and PCA / MDS / UMAP embeddings
Characterization tasks — a new campaign task type (
task="characterization") for level-set estimation: mapping which regions of the parameter space pass a threshold, rather than maximizing a response:thresholdattribute onTarget; task-aware acquisition defaults onCampaign/BayesianOptimizerBoundary-seeking “straddle” acquisitions:
STR,RANDSTR(single-target) andMSTR,JAREX(multi-target)CharacterizationEvaluator— posterior pass/fail classification, a 4-level confidence ladder (mean/70%/95% CI), joint multi-target metrics, sample-size planning, ground-truth scoring (confusion matrix / Jaccard), and largest-feasible-hypercube searchplot_2d_response_map(pass/fail, confidence, and continuous modes)
Unified RNG control (
RNGManager) — coordinates numpy, torch, and Pythonrandombehind a single seed, serialized into campaign/optimizer state so a saved-and-loaded campaign reproduces exactly. OneRNGManagercan be shared across a campaign, optimizer, and designer;obsidian.USE_OLD_RNG_CONTROLrestores legacy global-seeding behavior.Custom acquisition function registry — acquisition functions are now defined as rich registry entries (implementation + hyperparameter parser + modalities + task types + constraint support). New
acquisition_function_register(...)lets users plug in their own;RandomSampling(RS) is now a real implementation.Classical response-surface & n-level DOE —
central_composite_DOE(CCD, with rotatable/faced/custom alpha and unit-cube inscribing) andfactorial_DOE_n_level(3+ level factorials); CCD exposed viaExpDesigner.initialize(method="CCD").Restartable designers — both
ExpDesignerandAdvExpDesignergainsave_state()/load_state(), persisted with the campaign.Multi-response plotting:
response_id/response_idson parity/factor/surface/progress plots, reference-point overlay and custom objective onfactor_plot, confidence bands and raw-data overlay onsurface_plot, andX_suggestoverlay onoptim_progress.Support for Python 3.10–3.12.
Modified#
More robust surrogate fitting — multi-restart GP fitting with best-of-N selection is now the default (
max_attempts=5);fit()exposes optimizer/multi-start controls and prior-sampling initialization.Optimizers can be saved/loaded unfitted (config + RNG only);
save_stateno longer requires a fitted model.suggest()gainsoptim_options(passed through to BoTorch/scipy) and per-callmanual_seed;fit()gainsfit_options;maximize()accepts anacquisitionargument; Random Search now respects fixed discrete features.evaluate()now emits a standardized-prediction column per target.
Fixed#
Logit transform — fit now runs only on training data (not on every call, which broke for single-row inputs); degenerate/constant/all-NaN data is handled gracefully instead of producing NaN/inf, out-of-
[0,1]inputs raise a clear error, and unfitted scalers raiseUnfitError.
Removed#
Dash web app (
obsidian/dash,app.py) and the[app]extra — Obsidian is now a library package.
[0.8.6]#
Added#
Improved methods for fitting PyTorch surrogates, including auto-stopping by parameter value norm
Modified#
Greatly reduced the number of samples for DNN posterior, speeding up optimization
Stabilized the mean estimate of ensemble surrogates by avoiding resampling
Disabled root caching for ensemble surrogates during optimization
Increased the maximum length of a category name to 32 characters
Bug fix for incorrect symmetry in correlation calculation of calc_ofat_ranges
OFAT range calcs and plots now respect minimum targets and not just maximum
[0.8.5]#
Added#
More optional outputs for verbose settings
Parameters in ParamSpace can also be indexed by name
Parameters now have search_space property, to modify the optimizer search space from the full space
Continuous parameters have search_min/search_max; Discrete parameters have search_categories
Constraints are now defined by Constraint class
Input constraints can now be included in ParamSpace, and serialized from there
Output constraints can now be included in Campaign, and serialized from there
New interface class IParamSpace to address circular import issues between ParamSpace and Constraint
Modified#
Optimizer and Campaign X_space attributes are now assigned using setter
Optimizer.maximize() appropriately recognizes fixed_var argument
Removed#
Torch device references and options (GPU compatibility may be re-added)
[0.8.4]#
Added#
Campaign X_best method
Optimizer X_best_f attribute(s)
Sequence of colors “color_list” to branding
Informative hoverdata for MDS plot
Created Product_Objective and Divide_Objective
Modified#
Switched all usages of X_ref = X_space.mean() to optimizer.X_best_f
Refactored mpl “visualize_inputs” as plotly “visualize_inputs” for better interactivity
Text formatting for some plotly hoverdata
[0.8.3]#
Added#
Default values for NParEGO scalarization_weights
SHAP PDP ICE plots now work with categorical values
Added scikit-learn to dependencies, for MDS
Added MDS plot
Modified#
SHAP PDP ICE plots must now have color and x-axis indices that are distinct
[0.8.2]#
Added#
Project metadata properly captured on PyPI based on changes in pyproject.toml
[0.8.1]#
Modified#
Fixed infobar on dash app
Better handling of X_space on dash app
Bug fixes for optim_progress
Improved color and axes of parity_plot
[0.8.0]#
Added#
Major improvements to testing and numerous small bug fixes to improve code robustness
Code coverage > 90%
New method for asserting equivalence of state_dicts during serialization
Modified#
Objective PyTests separated
Constraint PyTests separated
[0.7.13]#
Added#
Campaign.Explainer now added to PyTests
Docstrings and typing to Explainer methods
Campaign.out property to dynamically capture measured responses “y” or objectives as appropriate
Campaign.evaluate method to map optimizer.evaluate method
DNN to PyTests
Modified#
Fixed SHAP explainer analysis and visualization functions
Changed SHAP visualization colors to use obsidian branding
Moved sensitivity method from campaign.analysis to campaign.explainer
Moved Explainer testing from optimizer pytests to campaign pytests
Generalized plotting function MOO_results and renamed optim_progress
Campaign analysis and plotting methods fixed for multi-response campaigns
Greatly increased the number of samples used for DNNPosterior, increasing the stability of posterior predictions
Removed#
Removed code chunks regarding unused optional inputs to PDP ICE function imported from SHAP GitHub
[0.7.12]#
Added#
More informative docstrings for optimizer.bayesian, optimizer.predict, to explain choices of surrogate models and aq_funcs
Modified#
Renamed aq_func hyperparameter “Xi_f” to “inflate”
Moved default aq_func choices for single/multi into aq_defaults of acquisition.config
Fixed and improved campaign analysis methods
[0.7.11]#
Added#
Documentation improvements
Modified#
Naming conventions for modules (config, utils, base)
Import order convention for modules
[0.7.10]#
Added#
First (working) release on PyPI
[0.7.6]#
Added#
Added DNN surrogate model using EnsemblePosterior. Requires PosteriorList and IndexSampler during optimization
Added EHVI and NIPV aq_funcs
Added discarding of NaN X value and Y values
Target transforms now ignore NaN values
Quantile prediction to optimizer.predict() and surrogate.predict() to better suit non-GP models and non-normal distributions
Modified#
Generalized surrogate_botorch fitting for models which are not GPs
Generalized torch.dtype using global variable for import obsidian.utils.TORCH_DTYPE
Improved some tensor.repeat() using tensor.repeat_interleave()
Switched EI, NEI, and qNEHVI to Log-EI versions based on BoTorch warning
Dropped “q” from qNEHVI / qNParEGO names
Simplified surrogate model loading in BO_optimizer
Changed name of surrogate.args/kwargs to surrogate.hps
Corrected typing in target transforms
Removed#
Thompson sampling aq_func
[0.7.5]#
Modified#
Removed explainer from campaign attributes
Updated “features objectives” to operate on real space instead of scaled space; virtually no speed difference and tensor grads not needed
Improvements to campaign object and explainer object features
Switched all GenericMC and GenericMOMC objectives to custom objectives to simplify SOO vs MOO, and enable serialization
Added set_objective to campaign, and objective serialization
Bug fix for surrogate.save_state() with train_Y
Marked GPflat + categorical space test as an expected fail in pytest
Minor bug fixes and test improvements to improve coverage
[0.7.4]#
Modified#
Bug fix for qMean, made sure objective is used
Set up basic validation tests for parameters package
[0.7.3]#
Modified#
Moved plotting dependencies to main build
Updated Contributing section
Minor modifications to main Readme
Moved jupyterlab from docs to dev group
Removed#
docs/readme.md; moved contents to CONTRIBUTING
[0.7.2]#
Added#
Added imported members to sphinx-autodoc results using all at module level
Included readme on main docs page, removed redundant link
Modified#
Various cosmetic changes to autodoc and autosummary options
Shortened object names on TOC tree for readability
Removed autosummary from package and subpackage-level autodoc. Automated only at module level with templates
Split subpackages into regular and “shallow” templates, to expose different meaningful levels on the toctree
Updated sphinx theme with more preferred navigation features
Removed#
Unused dependencies from pyproject.toml
[0.7.1]#
Modified#
Evaluate now does not calculate aq_func by default, to speed up evaluation of objective
Bug fixes for optimizer.evaluate() under fringe tests
Updated license to GPLv3 on Readme
Removed Merck references and updated branding
[0.7.0]#
Added#
optimizer.evaluate() to handle y_predict, f_predict, o_predict, and a_predict independently of optimize.suggest()
Modified#
Regardless of q_batch, evaluate aq functions on each sample individually, then as a joint sample
Made sure that X_baseline accepted X_pending
Made sure that ref_point and f_best in aq_hps are now based on objectives, not raw responses
Removed#
Removed o_dim and optim_type from optimizer.attrs to better support stateless operation
No longer calculate hypervolume or pareto front on raw responses; only after considering objectives
Removed y_pareto from optimizer.attrs
Temporarily removed campaign._analyze due to bugs with_hv
[0.6.11]#
Added#
Added plotting module to test coverage
Reloading/fitting f_train in optimizer.load_state
Added default_campaign.json to test directory, for faster testing using pre-fit objects
Added matplotlib plotting library
Can now provide X_pending to suggest, so that users can manually do iterative suggestions
Modified#
Various plotting bug fixes
Ensure that paramspace encode/unit_map return double dtypes
[0.6.10]#
Added#
Added getitem to ParamSpace to enable X_space[idx]
Modified#
Overhaul of all encode/decode and map/demap functions using a decorator to handle robust typing
Bug fix for SHAP_explain resulting from object dtypes with new encode functions
[0.6.9]#
Added#
Added notebook tutorials to docs
repr method for Target
Modified#
Bug fixes in factor_plot with X_ref provided
Fixed bug where categorical encoding wouldn’t work if all categories were numerical strings
Changed categorical OH-encode separator from _to ^ and protected against usage in X_names
[0.6.8]#
Modified#
Dash app updates with module refactoring
Minor refactoring of param_space discrete handling
Replaced assert statements with appropriate Python base exceptions, added custom obsidian exceptions as necessary
Moved benchmark module to obsidian.experiment
Removed#
Removed deprecated examples
[0.6.7]#
Added#
Dev capabilities for document generation using sphinx
Module docstrings
[0.6.6]#
Modified#
Overhaul of class and method docstrings
Removed#
Removed parameter.type and replaced with isinstance checking and class.name loading
[0.6.5]#
Added#
Custom exception handling
Composite objectives
Utopian point support for SOO and MOO
Bounded target support for SOO and MOO
Bounding for only selected targets in multi-output scenarios
Modified#
Completed refactored weighted MOO to separate out component parts of scalarization, utopian distance, norming, and bounding
Greatly simplified the structure of aq_kwargs based on the above
Removed#
weightedMOO acquisition function
Dynamic reference point utility
[0.6.4]#
Added#
More custom objectives
Modified#
Switched default single-objective aq from EI to NEI
Removed#
Simplex sampling of weights for weightedMOO; if weights aren’t provided, even weights are used
[0.6.3]#
Modified#
Moved “explain” functionality to base optimizer
Added backup exceptions to catch fit_gpytorch
Enabled multi-output objectives to expand single-response models (e.g. using X features)
Enabled single-output objectives to condense multi-response models (e.g. scalarization)
Updated demo notebooks
Fixed error with calling campaign._profile_max after every fit
Removed#
Redundant objective formulations
Removed GPFlex model, which is now redundant with multi-output objective
[0.6.2]#
Modified#
Updated all plotly plotting methods for new optimizer methods
Updated typing and enabled multi-objective on custom aq functions
[0.6.1]#
Modified#
Added new features to campaign object
Moved “seed” kwarg to ExpDesigner.init, consistent with BayesianOptimizer
Added hypervolume and pareto calculations (incl. pf_distance) to base optimizer
Fixed bug with target_transforms sharing hyperparameters because of bad initialization
[0.6.0]#
Added#
Task parameters and multi-task learning
Added “index” objective to select tasks for optimization in multi-task learning
Fixed bugs related to torch dtype mismatches
[0.5.7]#
Modified#
Fixed cat_dims specification for surrogate models so that they do not include ordinal params
Overhauled f_transform approach to avoid scikit-learn and be more customizable
Enforced abstractmethods on various classes
[0.5.7]#
Modified#
Fixed cat_dims specification for surrogate models so that they do not include ordinal params
Overhauled f_transform approach to avoid scikit-learn and be more customizable
Enforced abstractmethods on various classes
[0.5.6]#
Modified#
Added utopian point subtraction to all scalarization methods, made optional also
Moved PI_bounded weightedMOO to its own objective called “boundedMOO”
Fixed error where default hyperparameters were being written back to objects outside of the optimizer
Fixed bugs with new parameter types in experiment design modules
Added pytest parametrization to improve scope of tests
Added pytest attributes (slow, fast) to manage speed
[0.5.5]#
Modified#
Fixed bug with _fixed_features generation when fixed_var is specified
Updated all MOO custom aq functions to match current BoTorch patterns
Removed#
PI_bounded acquisition function, due to various issues. MOO_weighted with PI_bounded+weights scalarization does work
[0.5.4]#
Modified#
Added Param_Discrete_Numeric class (parent Param_Discrete)
Added Param_Observational subclass to parent Continuous class which can be used for fitting but avoid optimization
[0.5.3]#
Modified#
Implemented checks and validation to enforce the order of X, y, and targets across ParamSpace, Optimizer, Surrogate as appropriate
Note: Only Optimizer can handle extraneous or re-ordered columns, but they will be processed before passing to Surrogate
[0.5.2]#
Modified#
Fixed input/output constraints
Added de/transformation to output constraints (applied to target samples)
Added de/transformation to input constraints (applied to coefficients and RHS)
Implemented a de/transform map for ParamSpace in order to handle constraints in the encoded input space
Implemented a non-linear input constraint which keeps the range of one dimension in a joint optimization < 1% of the max-min
[0.5.1]#
Added#
Constrained multi-objective example notebook
Allowed optimizer.suggest() on a subset of fit responses
Enabled optimizer.maximize() for multi-response models based on the above
Added custom multi-output objective class
Fixed constraints specification, as we were using output constraints. Added input constraints to TODO
Added parameter name to lb/ub labels in optimizer.predict() to avoid index issues
Modified#
Custom constraints are now specified as a constructor, so that parameters can be added and a callable is returned
[0.5.0]#
Added#
New object-oriented design for several classes:
CampaignParameterParamSpaceTargetObjectiveandConstraint