history - Optimizer evaluation trace¶

 History Collection of traces. Trace Value trace.

Log of progress through a computation.

Each cycle through a computation, a process can update its history, adding information about the number of function evaluations, the total time taken, the set of points evaluated and their values, the current best value and so on. The process can use this history when computing the next set of points to evaluate and when checking if the termination conditions are met. Any values that may be useful outside the computation, e.g., for logging or for updating the user, should be recorded. In the ideal case, the history is all that is needed to restart the process in case of a system crash.

History consists of a set of traces. The content of the traces themselves is provided by the computation, but various stake holders can use them. For example, the user may wish to log the set of points that have been evaluated and their values using the system logger and an optimizer may require a certain amount of history to calculate the next set of values.

New traces are defined using History.provides(). For example, the following adds traces for ‘value’ and ‘point’ to the history, and requires the value on the two previous cycles in order to do its work:

>>> from bumps.history import History
>>> h = History(value=2, point=0) # keep two values and zero points


Initially the history is empty:

>>> print(len(h.value))
0


After three updates we see that only two values are kept.

>>> h.update(value=2.6, point=[1,1,1])
>>> h.update(value=1, point=[1,0.5,1])
>>> h.update(value=0.5, point=[1,0.5,0.9])
>>> print(h.value)
Trace value: 0.5, 1
>>> print(len(h.value))
2


Since the required length of ‘point’ is zero no values are kept:

>>> print(h.point[0])
Traceback (most recent call last):
...
IndexError: point has not accumulated enough history


A history consumer can override this, and require a certain length of a trace. Then future values will be preserved:

>>> h.requires(point=1)
>>> h.update(value=0.25, point=[1,0.5,0.92])
>>> print(h.point[0])
[1, 0.5, 0.92]


Traces are independent of each other. A new trace can be added to the history and updated separately from the existing traces. This can be handy if there are separate sources of history though it may be difficult to keep the in sync. The following adds a ‘step’ to the existing history, initialized to 15, without changing ‘value’ or ‘point’:

>>> h.provides(step=2) # keep two steps
>>> h.update(step=15) # initialize step to 15
>>> print(h.step)
Trace step: 15


Traces may be used as accumulators, with the delta added to the existing value before being stored in the trace. For example:

>>> h.accumulate(step=1)
>>> print(h.step)
Trace step: 16, 15


Within bumps, history is used by monitors, with bumps.fitters.MonitorRunner managing updates to history and feeding them to the fit progress monitors.

class bumps.history.History(**kw)[source]

Bases: object

Collection of traces.

Provided traces can be specified as key word arguments, name=length.

accumulate(**kw)[source]

Extend the given traces with the provided values. The traced value will be the old value plus the new value.

clear()[source]

Clear history, removing all traces

provides(**kw)[source]

Raises AttributeError if trace is already provided or if the trace name matches the name of one of the history methods.

requires(**kw)[source]

restore(state)[source]

Restore history to the state returned by a call to snapshot

snapshot()[source]

Return a dictionary of traces { ‘name’: [v[n], v[n-1], …, v[0]] }

update(**kw)[source]

Extend the given traces with the provided values. The traced values are independent. Use accumulate if you want to add the new value to the previous value in the trace.

class bumps.history.Trace(keep=1, name='trace')[source]

Bases: object

Value trace.

This is a stack-like object with items inserted at the beginning, and removed from the end once the maximum length keep is reached.

len(trace) returns the number of items in the trace trace[i] returns the ith previous element in the history trace.requires(n) says how much history to keep trace.put(value) stores value trace.accumulate(value) adds value to the previous value before storing state = trace.snapeshot() returns the values as a stack, most recent last trace.restore(state) restores a snapshot

Note that snapshot/restore uses lists to represent numpy arrays, which may cause problems if the trace is capturing lists.

accumulate(value)[source]
put(value)[source]

Add an item to the trace, shifting off from the beginning when the trace is full.

requires(n)[source]

Set the trace length to be at least n.

restore(state)[source]

Restore a trace from a captured snapshot.

Lists are converted to numpy arrays.

snapshot()[source]

Capture state of the trace.

Numpy arrays are converted to lists so that the trace can be easily converted to json.