I report on the SSE of individuals in an evolving population.

Construct an instance of me with a Population. Then you can call the instance (as many times as you like) with an Individual to report on its SSE compared to the best one I've reported on thus far.

ParameterscomplaintCallbackSet to a callable that accepts an Individual instance and the result of a callback function that may complain about the individual whose values and SSE were reported to it.
See Also__call__.
Class Variable minDiff The minimum fractional difference between a new best individual's SSE and that of the previous best individual for a report to be filed about the new one. The default is 0.02, or at least a 2% improvement required.
Method __init__ Reporter(population, complaintCallback=None)
Method abort Tells me not to wait for any pending or future callbacks to run.
Method addCallback Call this to register a new callback.
Method isEquivSSE Returns True if the SSE of individual iBetter is not significantly different than that of individual iWorse.
Method runCallbacks Queues up a report for the supplied Individual i, calling each of my registered callbacks in turn.
Method waitForCallbacks Returns a Deferred that fires when all reporting callbacks currently queued up have been completed.
Method newBest Registers and reports a new best Individual. Calling this method is the only safe way to update iBest.
Method msgRatio Returns None if iNum is better (lower SSE) than iDenom. Otherwise returns the rounded integer ratio of numerator SSE divided by denominator SSE.
Method progressChar Logs the supplied ASCII character sym to the current console/log line.
Method __call__ Files a report on the Individual i, perhaps vs. another individual iOther.
minDiff =
The minimum fractional difference between a new best individual's SSE and that of the previous best individual for a report to be filed about the new one. The default is 0.02, or at least a 2% improvement required.
def __init__(self, population, complaintCallback=None):

Reporter(population, complaintCallback=None)

def abort(self):

Tells me not to wait for any pending or future callbacks to run.

def addCallback(self, func, *args, **kw):

Call this to register a new callback.

The supplied func must accept as arguments (1) a 1-D Numpy array of values from a new best Individual, (2) the value of my report counter, and (3) the individual's SSE, followed by any other arguments and keywords you provide.

I will run all the callbacks whenever I report on an Individual with an SSE that is lower than any of the other Individuals I've reported on up to that point.

def isEquivSSE(self, iBetter, iWorse):

Returns True if the SSE of individual iBetter is not significantly different than that of individual iWorse.

What is "significant" is defined by my minDiff attribute.

def runCallbacks(self, i, iPrevBest=None):

Queues up a report for the supplied Individual i, calling each of my registered callbacks in turn.

If any callback complains about the report by returning a result (deferred or immediate) that is not None, processes the complaint and then gives the individual a worst-possible SSE.

Default processing is to enter the debugger so the user can figure out what the callback was complaining about. But if my complaintCallback is set to a callable (must accept the individual and the complainer's returned result as its two args), that will be called instead of the debugger.

If the callback had an error, it is logged, processing of any further callbacks is halted, and I get aborted.

ParametersiPrevBestSet to the previous best individual to allow for it to be restored to its rightful place if a callback complains about i.
def waitForCallbacks(self):

Returns a Deferred that fires when all reporting callbacks currently queued up have been completed.

def newBest(self, i, force=False):

Registers and reports a new best Individual. Calling this method is the only safe way to update iBest.

If the new individual's SSE is not merely equivalent to the last one (or if force is set True), triggers a run of callbacks with the best individual's 1-D array of values and the integer report count for any callbacks that have been registered via my addCallback method. The primary use of this is displaying a plot of the current best set of parameters.

If a callback run is currently in progress, another will be done as soon as the current one is finished. That next run will refer to whatever is the best individual at the time. A rapid flurry of calls to newBest will only callbacks necessary to ensure that the best individual has been referenced in a callback run.

ParametersforceSet True to force i to be considered the best, even if it's not. Caution: Don't use unless you're certain i is better than (or the same as) my iBest.
def msgRatio(self, iNum, iDenom, bogus_char='!', noProgress=False):

Returns None if iNum is better (lower SSE) than iDenom. Otherwise returns the rounded integer ratio of numerator SSE divided by denominator SSE.

iNum is automatically better if the SSE of iDenom is bogus, meaning None, np.nan, or infinite. That is, unless its own SSE is also bogus, in which case a ratio of zero is returned. If iNum has a bogus SSE but iDenom does not, a very high ratio is returned; a bogus evaluation got successfully challenged, and that's very significant.

iNum is not considered better if its SSE is "equivalent" to that of iDenom, meaning that a call to isEquivSSE determines that the two individuals have SSEs with a fractional difference less than my minDiff attribute. For example, if iDenom has an SSE=100.0, returns 1 if iNum has an SSE between 101.1 and 149.9. If its SSE is between 150.0 and 249.9, the return value will be 2.

A slightly better but "equivalent" iDenom results in a return value of 0. (Not None.) With an iDenom SSE of 100.0, and iNum SSE of 100.9, is considered equivalent to iDenom and 0 will be returned.

Logs a progress character:

  • ? if either iNum or iDenom evaluates as boolean False. (This should only happen if there was a fatal error during evaluation and shutdown is imminent.)
  • The character supplied with the bogus_char keyword (defaults to "!") if iNum has a bogus SSE but iDenom does not. (Successful challenge because parent had error, or bogus new population candidate.)
  • % if iNum has a bogus SSE and so does iDenom. (Everybody's fucked up.)
  • # if iDenom has a bogus SSE but iNum does not. (Failed challenge due to error.)
  • X if iNum is better than iDenom, indicating a failed challenge.
  • The digit 0 if iNum is worse than iDenom (challenger) but with an equivalent SSE.
  • A digit from 1-9 if iNum is worse than iDenom (challenger), with the digit indicating how much better (lower) the SSE of iDenom is than that of iNum. (A digit of "9" only indicates that the ratio was at least nine and might be much higher.)
def progressChar(self, sym=None):

Logs the supplied ASCII character sym to the current console/log line.

If the number of symbols logged to the current line reaches my line-length limit, a newline is inserted. To reset the count of symbols logged to the current line, call this method with no symbol provided.

def __call__(self, i, iOther=None, noProgress=False, force=False):

Files a report on the Individual i, perhaps vs. another individual iOther.

The type of report depends on whether one or two individuals are supplied. In any event, if the report results in my iBest being replaced with a better individual, I will run any callbacks registered with me.

One individual

With just i supplied and not iOther, the report is a lower-is-better SSE comparison between i and my current best individual iBest.

If there isn't yet a best individual, then i automatically becomes my first iBest and a progress character of "*" is printed or logged.

If there already is a best individual, i only takes over as iBest if it has a lower SSE, in which case the progress character is "!". Otherwise the progress character indicates how much worse i is than iBest, and is "#" if evaluation of i produced an error.

With this call pattern, nothing is returned.

Two individuals

When iOther is supplied, I call msgRatio with iOther vs i to get the rounded improvement ratio (0-9) of how much better i is than other, i.e., how much lower its SSE is. I then print or log a progress character that indicates how much better i is than iOther.

Unless, of course, i is actually worse than iOther (higher SSE), in which case the progress character is "X", denoting a failed challenge and the ratio will be None.

If i is also better than my iBest, then there will be an additional progress character of "+", and a small bonus added to my Population object's replacements score, equivalent to a rounded improvement ratio of 1.

With this call pattern, the rounded improvement ratio is returned, or None if i was worse than iOther.

ParametersnoProgressSet True to suppress printing/logging a progress character.
forceSet True to force callbacks to run even if the reported SSE is considered equivalent to the previous best one.
See AlsonewBest, progressChar, and msgRatio.
API Documentation for ade, generated by pydoctor at 2022-11-17 13:13:22.