Release notes#
Release notes for the published versions of nextnano optimizers.
Unreleased#
breaking:
EvolutionPlotteris gone.OptimizationPlotterdraws every optimizer’s run, and the newOptimizationPlotter.from_optimizerreplacesEvolutionPlotter.from_evolutionfor all three of them:OptimizationPlotter.from_optimizer(evolution).plot_all(). A log records the run and not which optimizer wrote it, so the subclass only ever knew the evolution wording because the caller had picked the class.figures drawn through an optimizer are unchanged:
Evolution.plot_all()still titles its progress figure Evolution progress and calls an iteration a generation. Plotting a log directly words itself neutrally, as it already did forLocalOptimizerandBayesianOptimization; passiteration_labelandprogress_titleto say otherwise.EvolutionPlotter.from_evolutionno longer fills the Pareto highlights from theEvolutionobject when the run’s log summary does not carry them. Every plotted value comes from the log. A completed run’s figures are unchanged — its summary carries the front — while a run that raised before writing its summary draws its figures with the final population scattered and no front emphasized on top.Evolution.plot_allnow reports a run it cannot plot the way the other two optimizers already did: on a log holding no evaluated candidate — a run whose first generation failed — it raisesRuntimeErrorsaying so rather thanIndexErrorfrom inside the plotting layer, and beforerunhas produced a log it raisesRuntimeErrorrather thanAttributeError.Evolution.setup_plottingandEvolution.plot_allare the same methods the other two optimizers use, so the three document and behave alike. The figures are unchanged, andEvolution’s API page now lists them.an
Evolutionplotted withoutsetup_plottingnow labels its parameter axes with the input-variable names from itsIO, asLocalOptimizerandBayesianOptimizationalready did, instead ofparam1,param2, … This applies to the figures and to the live window alike, andsetup_plotting(param_names=[...])still overrides it. The objectives keepfitness1,fitness2, … — a multi-objective run has no names for them anywhere, so name them yourself withsetup_plotting(fitness_names=[...]).
Version 0.13.0 (October 12th 2026)#
every run now writes into a folder of its own, named after the input file and the optimizer —
{input_file_name}_evolution/,{input_file_name}_optimization/,{input_file_name}_bayesian/— created in the output directory configured in nextnanopy.the three optimizers accept
output_dirto create that folder somewhere other than the configured output directory:Evolution(io, metric, bounds, output_dir="runs").IO.run_simulationacceptsstart_index, which numbers the generated input files — and so the simulation output foldersnextnanopynames after them — from the given index, zero-padded to five digits:input_file_stem="sim", start_index=1yieldssim_00001,sim_00002plot_all()now saves the figures. With nosave_dirthey are written into afiguressubfolder of the run’s folder; previously the default drew them without saving anything.the saved figures are named after what they show —
progress,paretoandinputs— instead of after the run’s log (Simulation_2026_10_08_153958_progress.png). The folder is what identifies the run, so plotting two runs into onesave_dirof your own now leaves only the figures of the last.breaking:
save_dir="next_to_log"is no longer saves the figures next to a logs. It is an ordinary relative directory name like any other string, so code still passing it writes the figures into./next_to_log/rather than next to the log.
Version 0.12.0 (September 24th, 2026)#
a
LocalOptimizerrun now writes the same.log/.json/.dattrio asEvolutionandBayesianOptimization, in the same JSON schema: onegen{n}key per function evaluation, one candidate per key, plus asummarysection carrying the champion, the initial guess, the method and what scipy returned. A single scipy iteration covers several evaluations — a finite-difference gradient costs one simulation per input variable on top of the iterate — so the evaluation, not the iteration, is what the log records.LocalOptimizergainschampion_xandchampion_f: the best evaluated candidate, which is not always the pointOptimizeResult.xreports, since a method may take a final step that does not improve the metric.LocalOptimizer.runacceptslive_progress=True: the progress viewer opens during the run and closes with it, as it already did forEvolutionandBayesianOptimization.LocalOptimizer.setup_plottingandLocalOptimizer.plot_alldraw a local run for its own shape: the function evaluations (labelled evaluations, drawn as a connected line) and the best-so-far, without the mean/median/min-max curves that would each summarize a single evaluation. The axis counts function evaluations rather than scipy iterations, which is what the log records.plot_allon a log holding no evaluated candidate — a run whose first simulation failed — raisesRuntimeErrorsaying so, rather thanIndexErrorfrom inside the plotting layer. Applies toLocalOptimizerandBayesianOptimization.
Version 0.11.0 (September 23rd, 2026)#
breaking:
Optimizeris nowLocalOptimizerand wraps onlyscipy.optimize.minimize. Root finding (optimization_method="root"/"root_scalar") is gone, and with it both constructor arguments that selected the method:LocalOptimizer(nextnanoio, metric)now takes exactly two arguments.breaking:
LocalOptimizer.set_targetis gone. Fold the target into the metric — an extraction function returningabs(value - target)— so the objective is the distance to the target and the minimizer drives it to zero.breaking:
set_optimization_parametersis gone;runtakes the arguments instead —optimizer.run(x0=[10.0], bounds=[(5, 20)], method="Nelder-Mead"), forwarded toscipy.optimize.minimize.breaking:
run_optimizationis gone.runis the single entry point and returns thescipy.optimize.OptimizeResult.breaking:
validate_optimizationis gone. A non-scalar metric, or anx0whose length does not match the input variables, raisesValueErrorfromrun.breaking: the
nextnano_optimizers.bayesianmodule is gone.BayesianOptimizationis imported fromnextnano_optimizers.optimizer, the one module that now provides all three optimizers.breaking: the
IO.output_datafilesproperty is now the methodIO.load_output_datafiles(): it reads and parses the output files from disk on every call, which an attribute access should not do.breaking:
IO.get_targetis gone; it only returned the output datafiles. UseIO.load_output_datafiles().breaking: a number of methods that were public but are only ever called by an optimizer during its own run have become internal, so that what the documentation lists is what you are meant to call. Nothing used to set up or drive a run is affected.
the example input files are updated for nextnano++ 3.0.0.
Version 0.10.0 (August 28th, 2026)#
BayesianOptimization.runacceptslive_progress=True: the progress viewer opens during the run and closes with it, as it already did forEvolution.Bayesian runs are plotted for their own shape: the trial values (labelled samples, drawn as a connected line) and the best-so-far, without the mean/median/min-max curves that would each summarize a single evaluation.
new
OptimizationPlotter, the optimizer-agnostic base ofEvolutionPlotter: use it to plot any run’s log, Bayesian included.progress curves can be relabelled and restyled per run (
series_labels,series_specs), and the surrounding wording set withiteration_label,progress_titleandpopulation_label.breaking: the plotter’s
summary,n_params,n_obj,param_names,fitness_names,n_failedandn_limitedmoved onto itsrunattribute —plotter.n_objis nowplotter.run.n_obj.
Version 0.9.0 (August 7th, 2026)#
BayesianOptimization.runaccepts atarget: the run stops early once the objective drops to or below it, instead of always exhausting thetrialsbudget.
Version 0.8.1 (August 5th, 2026)#
support python 3.14.
Version 0.8.0 (July 29th, 2026)#
Bayesian optimization gains
setup_plotting, matchingEvolution: configure the result figures once (param_names,fitness_names,progress_series,fitness_limits) andplot_alldraws with it.plot_allacceptsfig_formatto save the figures as pdf/svg/jpg/… (any format matplotlib supports); defaults to png.
Version 0.7.0 (July 24th, 2026)#
progress plot “best” curve is now the best-so-far (running best over generations), not the per-generation best.
live progress viewer closes when the run finishes, and shows a placeholder until the first generation completes.
integer ticks on the excluded-evaluations progress panel.
experimental Bayesian optimization (Ax-based), opt-in via
pip install nextnano_optimizers[bayesian].
Version 0.6.0 (July 21st, 2026)#
improve failed simulation error handling.
the package is renamed to nextnano_optimizers.
Version 0.5.3 (July 10th, 2026)#
bugfixes.
Version 0.5.2 (July 9th, 2026)#
progress plot in separate process.
Version 0.5.1 (July 9th, 2026)#
fitness limits for plotting.
choice of series for progress plotting.
other small adjustments in plotting.
Version 0.5.0 (July 8th, 2026)#
live progress and evolution results plotting.
improved keep_pareto handling.
Version 0.4.3 (July 7th, 2026)#
bugfixes.
Version 0.4.2 (July 7th, 2026)#
bugfixes.
Version 0.4.0 (May 4th, 2026)#
support multiple simulations per fitness via sweeps.
adapt Metric API to support multiple simulations.
Version 0.3.3 (April 10th, 2026)#
bug fixes.
Version 0.3.2 (April 7th, 2026)#
bug fixes.
Version 0.3.1#
bug fixes.
Version 0.3.0#
switch from pygmo to pymoo.
Version 0.2.0#
bug fixes.
improved output.
Version 0.1.12#
bug fixes.
added champion to evolution.
extra: data generation for ML.
added clean-up of input files after simulation.
Version 0.1.11#
extraction function in evolution is now strictly enforced to return
numpy.array.
Version 0.1.10#
added
non_execution_penaltytoEvolution.run(..., non_execution_penalty=number), wherenumberis the fitness assigned to the candidates without successful execution of the input file. Ifnon_execution_penaltyis not specified, an execution error of the input file leads to an error of theEvolution.added the
Simulation*.jsonhistory file. The file duplicates theSimulation*.loginfo, but saves it in a more computer readable format.added the
Simulation*.dathistory file in column format: (idx, generation, param1, param2, … paramn, fitness1, …, fitnessk).
Version 0.1.9#
added
algorithm_kwargs,Evolution.run(..., algorithm_kwargs={'cr': 0.95, ...}).added the initial guess feature to evolution,
Evolution.run(..., initial_guess=[solution_guess1, solution_guess2, ...]). The length of the initial guess should be equal to or less than the size of theEvolution.