`ade.history.History(object)`

class documentation

Part of `ade.history`

(View In Hierarchy)
I maintain a roster of the parameter values and SSEs of
*Individual* objects that a `Population`

has had
and possibly replaced.

Parameters | N_max | The most records I can have in my roster. When the roster is full, adding a
non-duplicative Individual will bump the highest-SSE one currently
in the roster to make room. The default of 1500 seems like a sensible
compromise between reasonably compact `.dat` file size and
informative plots. |

Instance Variable | names | A sequence of my individuals' parameter names, supplied as the sole constructor argument. |

Instance Variable | X | A 2-D Numpy array of SSEs (first column) and parameter values (remaining columns) of one individual. |

Instance Variable | K | A list of indices to rows of X, each entry in the list corresponding
to a row of X. |

Instance Variable | Kp | A set of the values (not indices) of K that are for individuals
currently in the population. |

Instance Variable | Kn | A set of the values (not indices) of K that are for individuals who
never were in the population. |

Instance Variable | kr | A dict containing row indices, keyed by the hashes of Individual
instances. |

Method | __init__ | `History(names, N_max=None)` |

Method | __getstate__ | For storage-efficient pickling. |

Method | __setstate__ | For unpickling. |

Method | shutdown | Undocumented |

Method | __len__ | My length is the number of records in my roster. |

Method | __getitem__ | Access the SSE and parameter values corresponding to index k of
my K list. |

Method | __iter__ | I iterate over 1-D Numpy arrays of parameter values in ascending order of the SSEs they resulted in. |

Method | clear | Call to have me return to a virginal state with no SSE+values
combinations recorded or considered for removal, an empty population, and
an N_total of zero. |

Method | value_vs_SSE | Obtains a 1-D Numpy array of the SSEs of my individuals and matching 1-D
Numpy arrays for each of the parameter values in names. |

Method | kkr | Returns (1) the index k of my K list where the row index
of the new record should appear in my X array, and (2) that row
index kr. |

Method | add | Adds the SSE and parameter values of the supplied individual i to
my roster, unless it has an SSE of `inf` , in which case it is
ignored. |

Method | purge | Purges my history of the record at row index kr. |

Method | notInPop | Call this with an integer row index or an Individual instance
that was added via `add` to remove its row
of my X array from being considered part of the current
population. |

Method | purgePop | Purges the history of all members of the current population. (Presumably, they will get added back again after re-evaluation.) |

Method | _initialize | Undocumented |

*K*that are for individuals who never were in the population.

My length is the number of records in my roster.

**Note**: Immediate result, not locked! Mostly for unit testing.

Access the SSE and parameter values corresponding to index *k* of
my *K* list.

**Note**: Immediate result, not locked! Mostly for unit testing.

I iterate over 1-D Numpy arrays of parameter values in ascending order of the SSEs they resulted in.

**Note**: Immediate result, not locked! Mostly for unit testing.

Call to have me return to a virginal state with no SSE+values
combinations recorded or considered for removal, an empty population, and
an *N_total* of zero.

Returns a `Deferred`

that fires when the lock has been
acquired and everything is cleared.

Obtains a 1-D Numpy array of the SSEs of my individuals and matching 1-D
Numpy arrays for each of the parameter values in *names*.

Waits to acquire the lock and then calls `Analysis.value_vs_SSE`

on my instance *a*, returning a `Deferred`

that fires with
the eventual result.

Returns (1) the index *k* of my *K* list where the row index
of the new record should appear in my *X* array, and (2) that row
index *kr*.

First, index *k* is obtained, by seeing where the *K* list
points to a record with an SSE closest but above the new one. Then each row
index in the *K* list is examined to see if the previous row of my
*X* array is unallocated. If so, that is the row index for the new
record. Otherwise, is the next row of my *X* array is unallocated,
that is used instead. If both adjacent rows of *X* are already
allocated, the next row index in the *K* list is examined.

If there are no row indices in *K* that point to a row of *X*
with an unallocated adjacent row, the row index is determined to be the
current length of *k*.

**Note**: With the original for-loop Python, the search for an
unallocated row was very CPU intensive when you get a big history
accumulated::

# Pick a row index for the new record for kr in self.K: if kr > 0 and kr-1 not in self.K: return k, kr-1 if kr < N-1 and kr+1 not in self.K: return k, kr+1 return k, N

The reason is that the list was being searched for an item with every iteration, twice!

The optimized version does this same thing with much more efficiently,
by creating a local (array) copy of *K* and sorting it in place. Then
only adjacent elements needs to be inspected with each iteration. (It may
be just as fast with a local sorted list instead of a Numpy array.)

def add(self, i, neverInPop=False):

Adds the SSE and parameter values of the supplied individual *i* to
my roster, unless it has an SSE of `inf`

, in which case it is
ignored.

If the roster is already full, bumps the record deemed most expendable
before adding a record for *i*. That determination is made by a call
to my `ClosestPairFinder`

instance *cpf*.

Returns a `Deferred`

that fires with the row index of the new
record when it has been written, or `None`

if no record was
written.

Parameters | neverInPop | Set `True` to have the individual added without ever having been
part of the population. |

Purges my history of the record at row index *kr*.

Removes the row index from my *K* list and has my *cpf*
instance of `ClosestPairFinder`

disregard the row, because it's now gone.

**Note**: Does not remove the index from the values of my *kr*
dict, as that is a time-consuming process and the caller can likely just
clear the whole thing anyhow.

Call this with an integer row index or an *Individual* instance
that was added via `add`

to remove its row
of my *X* array from being considered part of the current
population.