fit.runner¶
Module for running parameter optimizations.
The optimization runs either serial or in parallel. The parallel optimization
runs in a pool of sbmlsim.parallel which belongs to the fit (worker_pool):
one worker process per core, and every repeat of the fit goes to the worker
which is free. The pool is stopped after the fit, so the workers do not keep the
initialized problem, and it is started again, a few times, when a worker dies.
A worker cannot start workers of its own, so the workers of a fit go either to
its repeats or to the population of differential evolution, see split_cores:
a fit of differential evolution with fewer repeats than workers runs them one
after another, and every repeat evaluates the members of its population on all
workers (PopulationPool), so a single global optimization uses every core.
The OptimizationProblem is pickled and sent to the workers, so it must be
picklable: every worker initializes it once and runs repeats on it. The start
values are created by the runner, so a fit with a seed gives the same result
for any number of workers.
The runner only optimizes. Its result carries the fitted parameters and the
settings of the fit, and sbmlsim.fit.report.FitReport turns them into figures
and reports, see sbmlsim.fit.parameters.
TotalTimeColumn
¶
Bases: ProgressColumn
The estimated total runtime, ~ H:MM:SS behind the elapsed time.
The estimate is estimate_total_time with the workers field of the
task, so it is corrected for the runs a pool processes at once.
WorkerDied
¶
Bases: PoolError
A task failed because its worker died while it ran, see FitPool.run.
Attributes:
| Name | Type | Description |
|---|---|---|
alone |
whether the task ran alone on the pool when its worker died, so it killed the worker itself; otherwise it was one of the tasks in flight at a crash after the restarts were spent, and which of them killed the worker is not known. |
Initialize the failure of a task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
what happened. |
required |
alone
|
bool
|
whether the task ran alone on the pool. |
False
|
FitPool
dataclass
¶
The workers of a fit: a pool and the problem its tasks run on.
Attributes:
| Name | Type | Description |
|---|---|---|
executor |
ProcessPoolExecutor
|
the pool, see |
token |
str
|
identifies the fit in the caches of the workers. |
problem |
OptimizationProblem
|
the problem, pickled into every task as its definition. |
settings |
FitSettings
|
the settings the workers initialize the problem with. |
n_cores |
int
|
the number of workers. |
preload |
Sequence[str]
|
the modules the forkserver imports, see |
restarts |
int
|
how often the pool was started again after a crash, for the
cap |
stopped |
bool
|
whether the workers are stopped, e.g. after a crash with no
task left or by |
start
¶
Start new workers, if they are stopped; no restart after a crash.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
if the workers do not start, see
|
run
¶
Run the tasks and hand out their results as they finish.
At most n_cores tasks are in flight, the next is submitted when one
finishes, so a crash implicates only the tasks which were running. A
worker which dies breaks the whole pool; it is started again and the
tasks which were running, the suspects, are run again one at a time, so
a task fails only if it breaks the pool while it runs alone. Then the
remaining tasks run again at full width. After MAX_POOL_RESTARTS
restarts the tasks which were running at a crash fail without a second
run. A pool which is found broken when a task is submitted is started
again the same way, with no suspect if nothing was running; after
MAX_POOL_RESTARTS restarts with no suspect and no result in between
the run ends there. If the pool cannot be started again, or the run
ends, the tasks which did not run fail with a PoolError. A task which
fails because its worker died fails with WorkerDied, which tells
whether it ran alone. A crash which leaves no task to run stops the
pool and marks it stopped, so the next call starts new workers
without counting a crash; stopped workers are started at the start of
a call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
function
|
Callable[..., Any]
|
called in the worker as
|
required |
tasks
|
Mapping[int, dict[str, Any]]
|
the tasks by their key. |
required |
timeout
|
float | None
|
seconds without any result after which the tasks which are
running or waiting fail, |
None
|
deadline
|
float | None
|
the time of |
None
|
Yields:
| Type | Description |
|---|---|
Generator[tuple[int, Any]]
|
The key of a task and its result, or the exception which failed it. |
PopulationPool
dataclass
¶
Evaluates the population of differential evolution on the workers of a fit.
It is the PopulationEvaluator of a run, see
OptimizationProblem.optimize_run: every member is a task of the pool,
_worker_cost, so at most one member per worker is in flight and a worker
takes the next member when it is free; the run gets the costs as they
finish and returns them to scipy in the order of the members. The workers
initialize the problem once per fit, see worker_problem, so the runs of a
fit share them; start initializes them before the budget of a run.
A member whose worker dies runs again alone on a new pool, see
FitPool.run, and the cap MAX_POOL_RESTARTS counts per generation, so
crashes spread over a fit lose no member. A member which kills its worker
when it runs alone is a failed simulation, its cost is infinite. Members
which fail together, once the restarts of a generation are spent, end the
run with a PoolError: which of them killed the worker is not known, and
an infinite cost for all of them would make the result depend on the
timing of the crashes. Any other error of a worker ends the run with that
error, as in a serial run. The members which are not evaluated at the
deadline of the run are given up. After a deadline, an error or an
interrupt the workers are stopped, so no member which is still in flight
holds them, and the next generation, or the next run, starts new ones.
Attributes:
| Name | Type | Description |
|---|---|---|
pool |
FitPool
|
the workers of the fit. |
warmed |
ProcessPoolExecutor | None
|
the pool whose workers initialized the problem, see |
start
¶
Start the workers and initialize the problem in every one of them.
One task per worker initializes the problem, which the members of the
run then find initialized; it runs before the budget of a run, see
OptimizationProblem._optimize_single. A worker which takes a second
task before another started initializes the problem with its first
member instead. A worker which fails to initialize the problem fails
the members of the run with that error, so the failure is left to them.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
if the workers do not start. |
resolve_n_cores
¶
Resolve the number of worker processes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_cores
|
int | None
|
requested number of workers, |
required |
Returns:
| Type | Description |
|---|---|
int
|
Number of workers, at least one and at most the number of available cores. |
split_cores
¶
Split the workers of a fit between its runs and a population.
The workers of a fit are the processes of one pool, and a worker cannot
start workers of its own, so a run is either a task of the pool or it
evaluates the members of its population on the pool, never both. The runs
are the tasks as long as there are as many of them as workers or more:
every worker optimizes a run of its own, without waiting for the others.
Differential evolution with fewer runs than workers runs its runs one after
another instead, and every run evaluates the members of its population on
all workers (PopulationPool), so a single global optimization uses every
core; the polishing of the best member at the end evaluates its steps on
the workers one after another. Least squares runs its runs in parallel only.
A population is evaluated on the workers only if it is updated once per
generation, updating="deferred" (the default of the fit, see
OptimizationProblem.optimizer_arguments), and its objective is not
vectorized. The result of a seed is the same either way: a run evaluates
every generation together, in its worker or on all workers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
algorithm
|
OptimizationAlgorithmType
|
optimization algorithm. |
required |
size
|
int
|
number of runs. |
required |
n_cores
|
int
|
number of workers, see |
required |
kwargs
|
Mapping[str, Any]
|
additional arguments of the optimizer. |
required |
Returns:
| Type | Description |
|---|---|
int
|
The workers of the runs and the workers of the population of a run; |
int
|
one of them is one, both are one for a serial fit. |
estimate_total_time
¶
Estimate the total runtime from the runs which are done.
The runs are handed to the workers in batches of workers, so the time of
a batch is what the elapsed time measures: the estimate is the time per
batch times the number of batches. With a single worker this is the mean
time per run times the number of runs. The rate of the progress bar is
not used, it is measured over a window of seconds and a run takes minutes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
elapsed
|
float
|
seconds since the start. |
required |
completed
|
float
|
runs which are done. |
required |
total
|
float
|
runs in total. |
required |
workers
|
int
|
runs which are processed at once. |
1
|
Returns:
| Type | Description |
|---|---|
float | None
|
The estimated total runtime in seconds, |
float | None
|
is done. |
optimization_progress
¶
Show the progress of the optimization runs on the console.
The bar shows the count, the elapsed time and the estimated total runtime,
see TotalTimeColumn.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
description
|
str
|
text in front of the progress bar. |
required |
size
|
int
|
total number of optimization runs. |
required |
enabled
|
bool
|
show the progress, a plain context without display if |
True
|
unit
|
str
|
what is counted, behind the count. |
'runs'
|
workers
|
int
|
runs which are processed at once, for the estimate. |
1
|
Yields:
| Type | Description |
|---|---|
Generator[Progress | None]
|
The progress with a single task, or |
run_optimization
¶
run_optimization(
problem,
settings=None,
size=5,
algorithm=LEAST_SQUARE,
seed=None,
n_cores=1,
serial=False,
show_progress=True,
timeout=None,
runs_dir=None,
sampling=UNIFORM,
provenance=None,
indices=None,
**kwargs,
)
Run the optimization of the problem.
The runner executes the given OptimizationProblem size times, every
repeat starting from its own sample of the parameters, and returns the
OptimizationResult with the fitted parameters and the settings of the fit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
problem
|
OptimizationProblem
|
problem to optimize (picklable); it does not have to be
initialized, |
required |
settings
|
FitSettings | None
|
settings of the fit, the defaults of |
None
|
size
|
int
|
number of optimizations. |
5
|
algorithm
|
OptimizationAlgorithmType
|
optimization algorithm to use. |
LEAST_SQUARE
|
seed
|
int | None
|
random seed (for sampling of the start values). |
None
|
n_cores
|
int | None
|
number of workers, |
1
|
serial
|
bool
|
run the optimization in a serial fashion (debugging), whatever
|
False
|
show_progress
|
bool
|
show the progress of the runs on the console. |
True
|
timeout
|
float | None
|
seconds a single optimization may run, no limit if |
None
|
runs_dir
|
Path | None
|
directory the single runs are written to while the fit runs,
so a fit which is interrupted or crashes leaves the runs which
finished; they are read back with
|
None
|
sampling
|
SamplingType
|
sampling of the start values, see |
UNIFORM
|
provenance
|
FitProvenance | None
|
what the fit runs with, see |
None
|
indices
|
Sequence[int] | None
|
the repeats which run, all |
None
|
kwargs
|
Any
|
additional arguments for the optimizer, i.e., for
|
{}
|
Returns:
| Type | Description |
|---|---|
OptimizationResult
|
OptimizationResult with the fits of the repeats. A repeat which failed |
OptimizationResult
|
is part of the result and carries its message. A fit which is |
OptimizationResult
|
interrupted (Ctrl-C) after some repeats finished returns these. |
Raises:
| Type | Description |
|---|---|
ValueError
|
if a bound or a start value does not suit the scale of
its parameter or the algorithm, if every worker of a parallel
fit failed, or if the indices are invalid, see |
TypeError
|
if |
KeyboardInterrupt
|
if the fit is interrupted (Ctrl-C) before a repeat finished, there is no result to keep. |
worker_problem
¶
Get the initialized problem of a fit in a worker process.
A worker resolves the data of the problem of a fit once and keeps it under
the token of the fit, see sbmlsim.parallel.worker_cache, so the repeats
and the scans of a profile a worker runs share one initialization. The
workers would report the same messages about the data, once per core, so
only their errors are shown; the runner reports the problem itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token
|
str
|
identifies the fit, see |
required |
problem
|
OptimizationProblem
|
the problem, its definition as it is pickled into a task. |
required |
settings
|
FitSettings
|
the settings of the fit. |
required |
Returns:
| Type | Description |
|---|---|
OptimizationProblem
|
The initialized problem. |
Raises:
| Type | Description |
|---|---|
PoolError
|
if the worker could not initialize the problem, with the
error of the initialization; a |
worker_pool
¶
Start the workers of a fit and stop them after it.
The pool belongs to the fit and is not the kept pool of
sbmlsim.parallel.pool: its workers keep the initialized problem, which a
kept pool would keep after the fit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
problem
|
OptimizationProblem
|
the problem of the fit. |
required |
settings
|
FitSettings
|
the settings of the fit. |
required |
n_cores
|
int
|
the number of workers. |
required |
Yields:
| Type | Description |
|---|---|
Generator[FitPool]
|
The workers of the fit. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
if the workers do not start, e.g. in a script without
the guard, see |