Changeset 602 for branches


Ignore:
Timestamp:
12/04/12 16:08:04 (3 years ago)
Author:
mmckerns
Message:

added "with_constraint(target)" form of decorator;
nested now preserves function signature, added proxify which does not;
added "quadratic_equality(condition)" form of penalty;
added proxify for penalties which also doesn't preserve function signature

Location:
branches/decorate
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • branches/decorate/penalty.py

    r599 r602  
    11from numpy import inf, log 
    2 def quadratic_equality(k=100, h=5): 
     2def quadratic_equality(condition=lambda x:0., args=None, kwds=None, k=100, h=5): 
    33    """apply a quadratic penalty if the given equality constraint is violated 
    44 
     
    88the condition f(x) is satisfied when f(x) == 0.0 
    99    """ 
     10    if args is None: args=() 
     11    if kwds is None: kwds={} 
    1012    _n = [0] 
    1113    def iter(i=None): 
     
    1618        return _n[0] 
    1719    def dec(f): 
    18         def func(x, *args, **kwds): 
    19             pf = f(x, *args, **kwds) 
     20        def func(x, *argz, **kwdz): 
     21            pf = condition(x, *args, **kwds) 
    2022            _k = k * pow(h,_n[0]) 
    21             return float(_k)*pf**2 
     23            return float(_k)*pf**2 + f(x, *argz, **kwdz) 
    2224        func.iter = iter 
    2325        func._get_iter = get_iter 
     
    2527    return dec 
    2628 
    27 def barrier_inequality(k=100, h=5): 
     29def barrier_inequality(condition=lambda x:0., args=None, kwds=None, k=100, h=5): 
    2830    """apply a infinite barrier if the given inequality constraint is violated, 
    2931and a logarithmic penalty if the inequality constraint is satisfied 
     
    3537the condition f(x) is satisfied when f(x) <= 0.0 
    3638    """ 
     39    if args is None: args=() 
     40    if kwds is None: kwds={} 
    3741    _n = [0] 
    3842    def iter(i=None): 
     
    4347        return _n[0] 
    4448    def dec(f): 
    45         def func(x, *args, **kwds): 
    46             pf = f(x, *args, **kwds) 
     49        def func(x, *argz, **kwdz): 
     50            pf = condition(x, *args, **kwds) 
    4751            if pf > 0:  # inequality constraint is violated 
    4852                return inf 
    4953            # inequality constraint is satisfied 
    5054            _k = k * pow(h,_n[0]) 
    51             return -.5/_k*log(-pf) #XXX: use 2*k or k=200 ? 
     55            return -.5/_k*log(-pf) + f(x, *argz, **kwdz) #XXX: use 2*k or k=200? 
    5256        func.iter = iter 
    5357        func._get_iter = get_iter 
     
    5559    return dec 
    5660 
    57 def quadratic_inequality(k=100, h=5): 
     61def quadratic_inequality(condition=lambda x:0., args=None, kwds=None, k=100, h=5): 
    5862    """apply a quadratic penalty if the given inequality constraint is violated 
    5963 
     
    6367the condition f(x) is satisfied when f(x) <= 0.0 
    6468    """ 
     69    if args is None: args=() 
     70    if kwds is None: kwds={} 
    6571    _n = [0] 
    6672    def iter(i=None): 
     
    7177        return _n[0] 
    7278    def dec(f): 
    73         def func(x, *args, **kwds): 
    74             pf = f(x, *args, **kwds) 
     79        def func(x, *argz, **kwdz): 
     80            pf = condition(x, *args, **kwds) 
    7581            _k = k * pow(h,_n[0]) 
    76             return float(2*_k)*max(0., pf)**2 #XXX: use 2*k or k=200 ? 
     82            return float(2*_k)*max(0., pf)**2 + f(x, *argz, **kwdz) #XXX: use 2*k or k=200? 
    7783        func.iter = iter 
    7884        func._get_iter = get_iter 
     
    8086    return dec 
    8187 
    82 def lagrange_inequality(k=20, h=5): 
     88def lagrange_inequality(condition=lambda x:0., args=None, kwds=None, k=20, h=5): 
    8389    """apply a quadratic penalty if the given inequality constraint is violated 
    8490 
     
    8995the condition f(x) is satisfied when f(x) <= 0.0 
    9096    """ 
     97    if args is None: args=() 
     98    if kwds is None: kwds={} 
    9199    _n = [0] 
    92100    def iter(i=None): 
     
    97105        return _n[0] 
    98106    def dec(f): 
    99         def func(x, *args, **kwds): 
    100             pf = f(x, *args, **kwds) 
     107        def func(x, *argz, **kwdz): 
     108            pf = condition(x, *args, **kwds) 
    101109            beta = 0.; _k = k 
    102110            for i in range(_n[0]): 
     
    104112                _k *= h 
    105113            mpf = max(-beta/(2.*_k), pf) 
    106             return float(_k)*mpf**2 + beta*mpf 
     114            return float(_k)*mpf**2 + beta*mpf + f(x, *argz, **kwdz) 
    107115        func.iter = iter 
    108116        func._get_iter = get_iter 
     
    110118    return dec 
    111119 
    112 def lagrange_equality(k=20, h=5): 
     120def lagrange_equality(condition=lambda x:0., args=None, kwds=None, k=20, h=5): 
    113121    """apply a quadratic penalty if the given equality constraint is violated 
    114122 
     
    119127the condition f(x) is satisfied when f(x) = 0.0 
    120128    """ 
     129    if args is None: args=() 
     130    if kwds is None: kwds={} 
    121131    _n = [0] 
    122132    def iter(i=None): 
     
    127137        return _n[0] 
    128138    def dec(f): 
    129         def func(x, *args, **kwds): 
    130             pf = f(x, *args, **kwds) 
     139        def func(x, *argz, **kwdz): 
     140            pf = condition(x, *args, **kwds) 
    131141            lam = 0.; _k = k 
    132142            for i in range(_n[0]): 
    133143                lam += 2.*_k*pf 
    134144                _k *= h 
    135             return float(_k)*pf**2 + lam*pf 
     145            return float(_k)*pf**2 + lam*pf + f(x, *argz, **kwdz) 
    136146        func.iter = iter 
    137147        func._get_iter = get_iter 
     
    141151 
    142152#################################################### 
    143 def penalize(penalty=lambda x:0.0): 
    144     """ ... """ 
     153def proxify(penalty=lambda x:0.0): 
     154    """penalize a function with another function: y = f(x) to y' = f(x) + p(x) 
     155     
     156This is useful, for example, in penalizing a cost function where the constraints 
     157are violated; thus, the satisfying the constraints will be preferred at every 
     158cost function evaluation. 
     159 
     160This function does not preserve decorated function signature, but passes args 
     161and kwds to the inner function.  The decorated function should require a 
     162single parameter as input. 
     163    """ 
    145164    def dec(f): 
    146165        def func(x, *args, **kwds): 
    147             return f(x, *args, **kwds) + penalty(x) 
     166            return f(x) + penalty(x, *args, **kwds) 
     167        return func 
     168    return dec 
     169 
     170def penalize(penalty=lambda x:0.0, args=None, kwds=None): #XXX: *args, **kwds ? 
     171    """penalize a function with another function: y = f(x) to y' = f(x) + p(x) 
     172     
     173This is useful, for example, in penalizing a cost function where the constraints 
     174are violated; thus, the satisfying the constraints will be preferred at every 
     175cost function evaluation. 
     176    """ 
     177    if args is None: args=() 
     178    if kwds is None: kwds={} 
     179    def dec(f): 
     180        def func(x, *argz, **kwdz): 
     181            return f(x, *argz, **kwdz) + penalty(x, *args, **kwds) 
    148182        return func 
    149183    return dec 
  • branches/decorate/test_penalty.py

    r600 r602  
    55 
    66  from mystic.math.measures import mean, spread 
    7   @quadratic_equality() 
    8   def mean_constraint(x): 
    9     return mean(x) - 5.0 
     7  def mean_constraint(x, target): 
     8    return mean(x) - target 
    109 
    11   @quadratic_equality() 
    12   def range_constraint(x): 
    13     return spread(x) - 5.0 
     10  def range_constraint(x, target): 
     11    return spread(x) - target 
    1412 
    15   @penalize(penalty=range_constraint)#XXX: @quadratic_equality(range_constraint) 
    16   @penalize(penalty=mean_constraint) #XXX: @quadratic_equality(mean_constraint) 
     13  @quadratic_equality(condition=range_constraint, kwds={'target':5.0}) 
     14  @quadratic_equality(condition=mean_constraint, kwds={'target':5.0}) 
    1715  def cost(x):                       #XXX: def penalty(x): return x 
    1816    return abs(sum(x) - 5.0)         #XXX: # ...then give penalty to solver 
  • branches/decorate/test_wrapper.py

    r600 r602  
    2020  from mystic.math.measures import impose_mean 
    2121 
    22   @nested(inner=impose_mean) 
    23   def mean_then_squared(x): #FIXME: doesn't preserve function signature 
     22  def impose_constraints(x, mean, weights=None): 
     23    return impose_mean(mean, x, weights) 
     24 
     25  @nested(inner=impose_constraints, kwds={'mean':5.0}) 
     26  def mean_then_squared(x): 
     27    return [i**2 for i in x] 
     28 
     29  from numpy import array 
     30  x = array([1,2,3,4,5]) 
     31  assert mean_then_squared(x) == [i**2 for i in impose_mean(5,x)] 
     32 
     33 
     34def test_proxified_constraint(): 
     35 
     36  from mystic.math.measures import impose_mean 
     37 
     38  @proxify(inner=impose_mean) 
     39  def mean_then_squared(x): #XXX: proxy doesn't preserve function signature 
    2440    return [i**2 for i in x] 
    2541 
     
    3854    return x 
    3955 
    40   @nested(inner=impose_constraints) 
    41   def constrained_squared(x): #FIXME: doesn't preserve function signature 
     56  @nested(inner=impose_constraints, kwds={'mean':5.0, 'spread':50.0}) 
     57  def constrained_squared(x): 
     58    return [i**2 for i in x] 
     59 
     60  from numpy import array 
     61  x = array([1,2,3,4,5]) 
     62  y = impose_spread(50.0, impose_mean(5.0,x)) 
     63  assert constrained_squared(x) == [i**2 for i in y] 
     64 
     65 
     66def test_proxified_constraints(): 
     67 
     68  from mystic.math.measures import impose_mean, impose_spread 
     69 
     70  def impose_constraints(x, mean=0.0, spread=1.0): 
     71    x = impose_mean(mean, x) 
     72    x = impose_spread(spread, x) 
     73    return x 
     74 
     75  @proxify(inner=impose_constraints) 
     76  def constrained_squared(x): #XXX: proxy doesn't preserve function signature 
    4277    return [i**2 for i in x] 
    4378 
     
    188223  from mystic.math.measures import mean, spread 
    189224  from mystic.math.measures import impose_mean, impose_spread 
    190   def mean_constraint(x): 
    191     return impose_mean(5.0, x) 
    192  
    193   def range_constraint(x): 
    194     return impose_spread(5.0, x) 
    195  
    196   @nested(inner=range_constraint)  #XXX: @with_range(5.0) 
    197   @nested(inner=mean_constraint)   #XXX: @with_mean(5.0) 
     225  def mean_constraint(x, mean=0.0): 
     226    return impose_mean(mean, x) 
     227 
     228  def range_constraint(x, spread=1.0): 
     229    return impose_spread(spread, x) 
     230 
     231  @nested(inner=range_constraint, kwds={'spread':5.0})  #XXX: @with_range(5.0) 
     232  @nested(inner=mean_constraint, kwds={'mean':5.0})     #XXX: @with_mean(5.0) 
    198233  def constraints(x): 
    199234    return x 
     
    216251  test_nested() 
    217252  test_nested_constraint() 
     253  test_proxified_constraint() 
    218254  test_nested_constraints() 
     255  test_proxified_constraints() 
    219256  test_monitored() 
    220257  test_counted() 
  • branches/decorate/wrapper.py

    r598 r602  
    22#     compare against the originals for restrictions 
    33 
    4 def nested(inner=lambda x:x): 
     4def nested(inner=lambda x:x, args=None, kwds=None): #XXX: *args, **kwds ? 
    55    """nest a function within another function: convert y = f(x) to y' = f(c(x)) 
    66 
     
    88thus, the constraints will be enforced at every cost function evaluation. 
    99    """ 
    10     def dec(f): 
    11         def func(*args, **kwds): #FIXME: doesn't preserve function signature 
     10    if args is None: args=() 
     11    if kwds is None: kwds={} 
     12    def dec(f): 
     13        def func(x, *argz, **kwdz): 
     14            return f(inner(x, *args, **kwds), *argz, **kwdz) 
     15        return func 
     16    return dec 
     17 
     18 
     19def proxify(inner=lambda x:x): 
     20    """nest a function within another function: convert y = f(x) to y' = f(c(x)) 
     21 
     22This is useful, for example, in nesting constraints in a cost function; 
     23thus, the constraints will be enforced at every cost function evaluation. 
     24 
     25This function does not preserve decorated function signature, but passes args 
     26and kwds to the inner function.  The decorated function should require a 
     27single parameter as input. 
     28    """ 
     29    def dec(f): 
     30        def func(*args, **kwds): 
    1231            return f(inner(*args, **kwds)) 
    1332        return func 
Note: See TracChangeset for help on using the changeset viewer.