Changeset 850


Ignore:
Timestamp:
12/28/15 19:03:26 (5 months ago)
Author:
mmckerns
Message:

added linear_equality and linear_inequality penalties

File:
1 edited

Legend:

Unmodified
Added
Removed
  • mystic/mystic/penalty.py

    r776 r850  
    9292    return dec 
    9393 
     94def linear_equality(condition=lambda x:0., args=None, kwds=None, k=100, h=5): 
     95    """apply a linear penalty if the given equality constraint is violated 
     96 
     97penalty is p(x) = pk*abs(f(x)), with pk = k*pow(h,n) and n=0 
     98where f.iter() can be used to increment n = n+1 
     99 
     100the condition f(x) is satisfied when f(x) == 0.0 
     101    """ 
     102    if args is None: args=() 
     103    if kwds is None: kwds={} 
     104    _n = [0] # current penalty iteration 
     105    _f = [lambda x:0.] # decorated function 
     106    _y = [] # stored results 
     107    def error(x): 
     108        rms = condition(x, *args, **kwds)**2 
     109        if hasattr(_f[0], 'error'): rms += _f[0].error(x)**2 
     110        return rms**0.5 
     111    def iter(i=None): 
     112        if i is None: _n[0] += 1 
     113        else: _n[0] = i 
     114        if hasattr(_f[0], 'iter'): _f[0].iter(i) 
     115        return 
     116    def iteration(): 
     117        return _n[0] 
     118    def store(x,i=None): #XXX: couple to 'iter' as {n:y} ? 
     119        if hasattr(_f[0], 'store'): _f[0].store(x,i) 
     120        return 
     121    def stored(i=None): # can take a slice 
     122        if i is None: return _y[:] 
     123        try: return _y[i] 
     124        except IndexError: return 0.0 
     125    def clear(): 
     126        _n[0] = 0 
     127        [_y.pop() for i in range(len(_y))] 
     128        if hasattr(_f[0], 'clear'): _f[0].clear() 
     129        return 
     130    def dec(f): 
     131        _f[0] = f 
     132        def func(x, *argz, **kwdz): 
     133            pf = condition(x, *args, **kwds) 
     134            _k = k * pow(h,_n[0]) 
     135            return float(_k)*abs(pf) + f(x, *argz, **kwdz) 
     136        func.iter = iter 
     137        func.iteration = iteration 
     138        func.store = store 
     139        func.clear = clear 
     140        func.stored = stored 
     141        func.error = error 
     142        return func 
     143    return dec 
     144 
    94145def uniform_equality(condition=lambda x:0., args=None, kwds=None, k=inf, h=5): 
    95146    """apply a uniform penalty if the given equality constraint is violated 
     
    292343            _k = k * pow(h,_n[0]) 
    293344            return float(2*_k)*max(0., pf)**2 + f(x, *argz, **kwdz) #XXX: use 2*k or k=200? 
     345        func.iter = iter 
     346        func.iteration = iteration 
     347        func.store = store 
     348        func.clear = clear 
     349        func.stored = stored 
     350        func.error = error 
     351        return func 
     352    return dec 
     353 
     354def linear_inequality(condition=lambda x:0., args=None, kwds=None, k=100, h=5): 
     355    """apply a linear penalty if the given inequality constraint is violated 
     356 
     357penalty is p(x) = pk*abs(f(x)), with pk = 2k*pow(h,n) and n=0 
     358where f.iter() can be used to increment n = n+1 
     359 
     360the condition f(x) is satisfied when f(x) <= 0.0 
     361    """ 
     362    if args is None: args=() 
     363    if kwds is None: kwds={} 
     364    _n = [0] # current penalty iteration 
     365    _f = [lambda x:0.] # decorated function 
     366    _y = [] # stored results 
     367    def error(x): 
     368        rms = max(0., condition(x, *args, **kwds))**2 
     369        if hasattr(_f[0], 'error'): rms += _f[0].error(x)**2 
     370        return rms**0.5 
     371    def iter(i=None): 
     372        if i is None: _n[0] += 1 
     373        else: _n[0] = i 
     374        if hasattr(_f[0], 'iter'): _f[0].iter(i) 
     375        return 
     376    def iteration(): 
     377        return _n[0] 
     378    def store(x,i=None): #XXX: couple to 'iter' as {n:y} ? 
     379        if hasattr(_f[0], 'store'): _f[0].store(x,i) 
     380        return 
     381    def stored(i=None): # can take a slice 
     382        if i is None: return _y[:] 
     383        try: return _y[i] 
     384        except IndexError: return 0.0 
     385    def clear(): 
     386        _n[0] = 0 
     387        [_y.pop() for i in range(len(_y))] 
     388        if hasattr(_f[0], 'clear'): _f[0].clear() 
     389        return 
     390    def dec(f): 
     391        _f[0] = f 
     392        def func(x, *argz, **kwdz): 
     393            pf = condition(x, *args, **kwds) 
     394            _k = k * pow(h,_n[0]) 
     395            return float(2*_k)*abs(max(0., pf)) + f(x, *argz, **kwdz) #XXX: use 2*k or k=200? 
    294396        func.iter = iter 
    295397        func.iteration = iteration 
Note: See TracChangeset for help on using the changeset viewer.