Source code for pyopus.optimizer.optfilter

"""
.. inheritance-diagram:: pyopus.optimizer.optfilter
    :parts: 1

**Filter support for constrained optimization
(PyOPUS subsystem name: FILT)**
"""

from ..misc.debug import DbgMsgOut, DbgMsg

__all__ = [ 'Filter' ]

[docs]class Filter(object): """ All points are stored in a dictionary with keys of the form (f,h). The value stored alongside (f,h) can be anything. A point (f,h) dominates (f0,h0) if * h<h0 and f<=f0 or * h<=h0 and f<f0 (f,h) is dominated by the filter if h>hmax. No point in the filter dominates any other point in the filter. hmax=0 results in extreme barrier behavior. """ def __init__(self, hmax=0.0, debug=0): self.debug=debug self.reset(hmax)
[docs] def reset(self, hmax=None): """ Resets the filter. Points are stored in a dictionary with h as key. Dictionary values are tuples of the form (f, misc). There can be only one point for every h0 value. """ self.points={} if hmax is not None: self.hmax=hmax else: self.hmax=0.0
[docs] def updateHmax(self, hmax): """ Updates hmax and purges points with h>hmax. """ self.hmax=hmax toDelete=[] for h0,value in self.points.items(): if h0>self.hmax: toDelete.append(h0) for h0 in toDelete: del self.points[h0]
[docs] def orderedHlist(self): """ Returns h values in increasing order. """ hlist=list(self.points.keys()) hlist.sort() return hlist
[docs] def orderedPoints(self): """ Returns the f and h values ordered by increasing h. """ hlist=list(self.points.keys()) hlist.sort() flist=[] for h in hlist: f,dummy=self.points[h] flist.append(f) return flist, hlist
[docs] def bestFeasible(self): """ Returns (f,h,misc) of the feasible point. Returns (None, None, None) if no such point exists. """ hlist=self.orderedHlist() if len(hlist)==0 or hlist[0]>0.0: return (None, None, None) else: (f0, misc0)=self.points[hlist[0]] return(f0, hlist[0], misc0)
[docs] def leastInfeasible(self): """ Returns (f,h,misc) of the infeasible point with lowest h. Returns (None, None, None) if no such point exists. """ hlist=self.orderedHlist() if len(hlist)==0: # Empty filter return (None, None, None) elif hlist[0]>0.0: # Filter with only infeasible points (f0, misc0)=self.points[hlist[0]] return(f0, hlist[0], misc0) elif len(hlist)==1: # Only feasible point return (None, None, None) else: # Feasible point and infesible points (f0, misc0)=self.points[hlist[1]] return(f0, hlist[1], misc0)
[docs] def mostInfeasible(self): """ Returns (f,h,misc) of the infeasible point with highest h. Returns (None, None, None) if no such point exists. """ hlist=self.orderedHlist() if len(hlist)==0: # Empty filter return (None, None, None) elif hlist[-1]==0.0: # Filter with only feasible point return (None, None, None) else: (f0, misc0)=self.points[hlist[-1]] return(f0, hlist[-1], misc0)
[docs] def position(self, f, h): """ Returns the position of h in the ordered list of h values. 0 ... feasible point 1 ... best infeasible point 2 ... second infeasible point ... Returns ``None`` if the point is not in the filter. """ hlist=self.orderedHlist() try: ii=hlist.index(h) except: # Empty filter or not found return None (f0, misc0)=self.points[h] if f!=f0: # Function value does not match return None if hlist[0]==0.0: # Have feasible point return ii else: # No feasible point in filter return ii+1
[docs] def accept(self, f, h, misc): """ Checks a point against the filter. If h>hmax the point does not dominate nor is dominated. Such a point is rejected. If filter is empty, a point is accepted. Such a point is considered to dominate filter. If point dominates any filter point it is accepted. Dominated filter points are deleted. If a point is dominated by any filter point it is rejected. If a point does not dominate nor is dominated it is accepted. Returns boolean tuple (dominates, dominated, accepted). """ if h>self.hmax: if self.debug>0: DbgMsgOut("FILT", "h>hmax, point rejected") # does not dominate, not dominated, rejected return (False, False, False) if len(self.points)==0: if self.debug>0: DbgMsgOut("FILT", "empty filter, point accepted") self.points[float(h)]=(f,misc) # dominates, not dominated, accepted return (True, False, True) # Go through all filter points, check if they are dominated by (f,h) # Make a list of dominated points dominated=[] for h0, value in self.points.items(): (f0, misc0)=value if self.dominates(f, h, f0, h0): dominated.append(h0) # Purge dominated points for h0 in dominated: del self.points[h0] # If at least one filter point was dominated, accept point if len(dominated)>0: self.points[float(h)]=(f,misc) if self.debug>0: DbgMsgOut("FILT", "dominates %d points, point accepted" % len(dominated)) # dominates, not dominated, accepted return (True, False, True) # Check if (f,h) is dominated by any filter point # If a point is equal to filter point, it should not be accepted. # Such a point is considered to be dominated by a filter point. for h0, value in self.points.items(): (f0, misc0)=value if self.dominates(f0, h0, f, h) or (f==f0 and h==h0): if self.debug>0: DbgMsgOut("FILT", "dominated by filter, point rejected") # does not dominate, dominated, rejected return (False, True, False) # Got to this point so (f,h) can be accepted self.points[float(h)]=(f,misc) if self.debug>0: DbgMsgOut("FILT", "does not dominate nor dominated by filter, point accepted") # does not dominate, not dominated, accepted return (False, False, True)
[docs] @staticmethod def dominates(f, h, f0, h0): """ Returns ``True`` if (f,h) dominates (f0,h0). """ if (h<h0 and f<=f0) or (h<=h0 and f<f0): return True else: return False