Source code for pyopus.problems.madsprob

# -*- coding: UTF-8 -*-
"""
.. inheritance-diagram:: pyopus.problems.madsprob
    :parts: 1
	
**Optimization test functions from papers on MADS. 
(PyOPUS subsystem name: MADSPROB)**

All test functions in this module are maps from :math:`R^n` to :math:`R`. 

The *nc* nonlinear constraints are of the form

.. math::
  cl \\leq c(x) \\leq ch
  
Beside linear constraints a problem can also have bounds of the form

.. math::
  xl \\leq x \\leq xh
  
This module is independent of PyOPUS, meaning that it can be taken as is 
and used as a module in some other package. It depends only on the :mod:`cpi` 
and the :mod:`mgh` module. 

The STYRENE and the MDO problem depend on the :mod:`_mads` module. 
HS114 and MAD6 depend on the :mod:`_lvns` module. 

References:

.. [mads]  Audet C., Dennis J.E. Jr., Mesh Adaptive Direct Search Algorithms 
           for Constrained Optimization. SIAM Journal on Optimization, 
           vol. 17, pp. 188-217, 2006. 

.. [madspsd] Audet C., Dennis Jr J.E., Le Digabel S., Parallel Space 
           Decomposition of the Mesh Adaptive Direct Search Algorithm. 
           SIAM Journal on Optimization, vol. 19, pp. 1150-1170, 2008. 

.. [madsort] Abramson M.A., Audet C., Dennis J.E. Jr., Le Digabel S.,
           ORTHO-MADS: A Deterministic MADS Instance with Orthogonal 
           Directions. SIAM Journal on Optimization, vol. 20, pp. 948-966, 
           2009.

.. [madspb] Audet C., Dennis J.E. Jr., A Progressive Barrier for 
           Derivative-Free Nonlinear Programming. SIAM Journal on 
           Optimization, vol. 20, pp. 445-472, 2009. 

.. [madsqm] Conn A.R., Le Digabel S., Use of Quadratic Models with Mesh 
           Adaptive Direct Search for Constrained Black Box Optimization. 
           Optimization Methods and Software, vol. 28, pp. 139-158, 2013. 

.. [madsvns] Audet C., Bechard V., Le Digabel S., Nonsmooth Optimization Through 
	   Mesh Adaptive Direct Search and Variable Neighbourhood Search. Journal 
	   of Global Optimization, vol 41, pp. 299-318, 2008. 
		
.. [ufo]   Lukšan L, et. al., UFO 2011 interactive system for univeral functional 
	   optimization. TR 1151 ICS, AS CR, 2011. 
"""

from .cpi import CPI, MemberWrapper, TestFunctionError
import numpy as np
from . import mgh

try:
	from ..misc.debug import DbgMsg
except:
	def DbgMsg(x, y):
		return x+": "+y

__all__ = [ 
	'MADSPROBsuite', 
	'SNAKE', 
	'DISK', 
	'CRESCENT', 
	'G2', 
	'B250', 
	'B500', 
	'DIFF2', 
	'UFO7_26', 
	'UFO7_29',
	'MADSPROB'
]

[docs]class MADSPROB(CPI): """ Base class for the test functions The fesible initial point can be obtained from the :attr:`initial` member. The infeasible initial point is in the :attr:`initialinf` member. If any of these two points is not given, it is set to ``None``. The full name of the problem is in the :attr:`name` member. The :attr:`n` member holds the dimension of the problem. :attr:`nc` is the number of nonlinear constraints. The best known minimum value of the function is in the :attr:`fmin` member. If this value is unknown it is set to ``None``. Objects of this class are callable. The calling convention is ``object(x, gradients)`` where *x* is the input values vector and *gradients* is a boolean flag specifying whether the gradients should be evaluated. The values of the auxiliary functions and their gradients are stored in the :attr:`fi` and :attr:`J` members. The values of the cobnstraints and the corresponding Jacobian are stored in the :attr:`ci` and :attr:`J` members. This creates an instance of the CRESCENT function and evaluates the function and the constraints along with the gradient and the constraint Jacobian at the feasible initial point:: from pyopus.optimizer.madsprob import CRESCENT cr=CRESCENT(n=10) (f, g, c, Jc)=cr.fgcjc(cr.initial) """ name=None "The name of the test function" def __init__(self, n, m=1, nc=0): self.n=n self.nc=nc self.initial=None self.initialinf=None self.fmin=None # No bounds by default self.xl=np.ones(n) self.xl.fill(-np.Inf) self.xh=np.ones(n) self.xh.fill(np.Inf) # Equality constraint of the form =0 by default self.cl=np.zeros(nc) self.ch=np.zeros(nc) self.fi=np.zeros(m) self.J=np.zeros([m,n]) self.ci=np.zeros(nc) self.Jc=np.zeros([nc,n]) def __call__(self, x, gradients=False): self.fi=None self.ci=None if gradients: self.J=None self.Jc=None def freductor(self): # Return the first auxiliary function by default return self.fi[0]*1.0 def greductor(self): # Return the gradient of the first auxiliary function by default return self.J[0,:]*1.0
[docs] def f(self, x): """ Returns the value of the test function at *x*. """ self(x) return self.freductor()
[docs] def g(self, x): """ Returns the value of the gradient at *x*. """ self(x, True) return self.greductor()
[docs] def c(self, x): """ Returns the value of the constraints at *x*. """ self(x) return self.ci*1.0
[docs] def fc(self, x): """ Returns the value of teh function and constraints at *x*. """ self(x) return self.freductor(), self.ci*1.0
[docs] def cjc(self, x): """ Returns the constraint Jacobian at *x*. """ self(x, True) return self.Jc*1.0
[docs] def cpi(self): """ Returns the common problem interface. xmin is not available. See the :class:`CPI` class for more information. """ itf=self.prepareCPI(self.n, m=self.nc) itf['name']=self.name itf['x0']=self.initial itf['f']=MemberWrapper(self, 'f') itf['c']=MemberWrapper(self, 'c') itf['g']=MemberWrapper(self, 'g') itf['cg']=MemberWrapper(self, 'cjc') if 'fmin' in self.__dict__: itf['fmin']=self.fmin itf['xlo']=self.xl itf['xhi']=self.xh itf['clo']=self.cl itf['chi']=self.ch return self.fixBounds(itf)
[docs]class SNAKE(MADSPROB): """ SNAKE test function (n=2, nc=2). Published as the first problem in section 4.1 of [madspb]_. See the :class:`MADSPROB` class for more details. """ name="SNAKE" def __init__(self): MADSPROB.__init__(self, n=2, nc=2) self.initial=np.array([0.0, 0]) self.initialinf=np.array([0.0, -10]) self.fmin=0.08098 self.cl[0]=-np.Inf self.ch[0]=0 self.cl[1]=0 self.ch[1 ]=np.Inf def __call__(self, x, gradient=False): self.fi[0]=((x[0]-20)**2+(x[1]-1)**2)**0.5 self.ci[0]=np.sin(x[0])-0.1-x[1] self.ci[1]=np.sin(x[0])-x[1] if gradient: self.J[0,0]=(x[0]-20)/self.fi[0] self.J[0,1]=(x[1]-1)/self.fi[0] self.Jc[0,0]=np.cos(x[0]) self.Jc[0,1]=-1.0 self.Jc[1,0]=np.cos(x[0]) self.Jc[1,1]=-1.0
[docs]class DISK(MADSPROB): """ DISK test function (n=arbitrary, nc=1). Also referred to a the Hypersphere problem. Published as the first problem in section 4.2 of [madspb]_ or as the first problem in section 5.3 of [mads]_. See the :class:`MADSPROB` class for more details. """ name="DISK" def __init__(self, n=10): MADSPROB.__init__(self, n=n, nc=1) self.initial=np.zeros(n) self.initialinf=np.ones(n)*2 self.fmin=-3**0.5*n self.cl[0]=-np.Inf self.ch[0]=0.0 def __call__(self, x, gradient=False): self.fi[0]=x.sum() self.ci[0]=(x**2).sum()-3*self.n if gradient: self.J[0,:]=1.0 self.Jc[0,:]=2*x
[docs]class CRESCENT(MADSPROB): """ CRESCENT test function (n=arbitrary, nc=2). Published as the first problem in section 4.3 of [madspb]_. See the :class:`MADSPROB` class for more details. """ name="CRESCENT" def __init__(self, n=10): MADSPROB.__init__(self, n=n, nc=2) self.initial=np.zeros(n) self.initial[0]=n+0.1 self.initialinf=np.zeros(n) self.initialinf[0]=n self.initialinf[-1]=-n self.fmin=1.0-n self.cl[0]=-np.Inf self.ch[0]=0.0 self.cl[1]=0.0 self.ch[1]=np.Inf def __call__(self, x, gradient=False): self.fi[0]=x[-1] self.ci[0]=((x-1.0)**2).sum()-self.n**2 self.ci[1]=((x+1.0)**2).sum()-self.n**2 # One row contains derivatives wrt n dimensions (has n columns) # There is one row per component (m or nc in total) if gradient: self.J[:,:]=0.0 self.J[0,-1]=1.0 self.Jc[0,:]=2*(x-1.0) self.Jc[1,:]=2*(x+1.0)
[docs]class G2(MADSPROB): """ G2 test function (n=arbitrary, nc=1). Published as problem A in section 5.2 of [madspsd]_. See the :class:`MADSPROB` class for more details. """ name="G2" def __init__(self, n=10): MADSPROB.__init__(self, n=n, nc=2) self.initial=np.ones(n)*5 self.initialinf=None if n==10: self.fmin=-0.803619 self.xl[:]=0.0 self.xh[:]=10.0 self.cl[0]=-np.Inf self.ch[0]=0.0 self.cl[1]=-np.Inf self.ch[1]=0.0 def __call__(self, x, gradient=False): ii=np.arange(self.n) cv=np.cos(x) den2=((ii+1)*x**2).sum() self.fi[0]=((cv**4).sum()-2*(cv**2).prod())/den2**0.5 self.ci[0]=-x.prod()+0.75 self.ci[1]=x.sum()-7.5*self.n if gradient: for i in ii: self.J[0,i]=( ( 4*np.cos(x[i])**3*(-np.sin(x[i])) -2*cv.prod()*cv[:i].prod()*cv[i+1:].prod()*(-np.sin(x[i])) )/den2**0.5 -( ((cv**4).sum()-2*(cv**2).prod())/den2* 0.5/den2**0.5*(i+1)*x[i]*2 ) ) self.Jc[0,i]=-x[:i].prod()*x[i+1:].prod() self.Jc[1,:]=1.0 def freductor(self): if self.fi[0]<0: return self.fi[0] else: return -self.fi[0] def greductor(self): if self.fi[0]<0: return self.J[0,:]*1.0 else: return -self.J[0,:]*1.0
[docs]class B250(MADSPROB): """ B250 test function (n=60, nc=1). Mentioned as problem B in section 5.2 of [madspsd]_. Rewritten from C++ source obtained from the NOMAD test problems collection. See the :class:`MADSPROB` class for more details. """ name="B250" def __init__(self): MADSPROB.__init__(self, n=60, nc=1) self.initial=np.array([ 0.25, 0.85, 0.25, 0.85, 0.25, 0.85, 0.25, -0.35, 0.85, 0.25, 0.85, 0.85, -0.35, -0.35, 0.25, 0.825, 0.125, 0.825, 0.825, 0.125, 0.825, 0.825, 0.825, -0.575, -0.575, 0.825, 0.125, 0.825, 0.125, 0.125, 0.125, 0.125, 0.125, 0.125, -0.575, 0.125, 0.825, 0.125, -0.575, 0.825, -0.575, 0.825, 0.825, 0.125, 0.825, 0.9, 1.78, 0.9, 0.02, 0.9, 0.9, 0.9, 0.02, 0.9, 0.9, 0.9, 0.9, 0.02, 0.9, 1.78 ]) self.initialinf=None self.xl[:15]=-0.5 self.xh[:15]=1.0 self.xl[15:45]=-0.75 self.xh[15:45]=1.0 self.xl[45:]=-0.2 self.xh[45:]=2.0 self.cl[0]=250.0 self.ch[0]=np.inf self.func1=mgh.PenaltyII(n=15) self.func2=mgh.Trigonometric(n=30) self.func3=mgh.BrownAlmostLinear(n=15) self.func4=mgh.BroydenBanded(n=15) self.func5=mgh.BroydenTridiagonal(n=30) self.func6=mgh.DiscreteBoundaryValue(n=15) def __call__(self, x, gradient=False): self.func1(x[:15], gradient) self.func2(x[15:45], gradient) self.func3(x[45:], gradient) self.func4(x[:15], gradient) self.func5(x[15:45], gradient) self.func6(x[45:], gradient) self.fi[0]=( (self.func1.fi**2).sum() +(self.func2.fi**2).sum() +(self.func3.fi**2).sum() ) self.ci[0]=( (self.func4.fi**2).sum() +(self.func5.fi**2).sum() +(self.func6.fi**2).sum() ) if gradient: self.J[0,:15]=2*np.dot(self.func1.J.T, self.func1.fi) self.J[0,15:45]=2*np.dot(self.func2.J.T, self.func2.fi) self.J[0,45:]=2*np.dot(self.func3.J.T, self.func3.fi) self.Jc[0,:15]=2*np.dot(self.func4.J.T, self.func4.fi) self.Jc[0,15:45]=2*np.dot(self.func5.J.T, self.func5.fi) self.Jc[0,45:]=2*np.dot(self.func6.J.T, self.func6.fi)
[docs]class B500(B250): """ B500 test function (n=60, nc=1). Mentioned as problem B in section 5.2 of [madspsd]_. Rewritten from C++ source obtained from the NOMAD test problems collection. See the :class:`MADSPROB` class for more details. """ name="B500" def __init__(self): B250.__init__(self) self.initial=np.array([ 0.2500000000000000000000000, 0.2500000000000000000000000, -0.0500000000000000000108420, -0.0500000000000000000108420, 0.8500000000000000000216840, -0.3500000000000000000216840, 0.8500000000000000000216840, 0.5500000000000000000108420, 1.0000000000000000000000000, -0.3500000000000000000216840, 1.0000000000000000000000000, -0.0500000000000000000108420, 0.8500000000000000000216840, -0.3500000000000000000216840, -0.0500000000000000000108420, -0.5749999999999999999891580, -0.2249999999999999999945790, -0.7500000000000000000000000, 0.8249999999999999999891580, -0.5749999999999999999891580, 0.4749999999999999999945790, -0.7500000000000000000000000, 1.0000000000000000000000000, 0.8249999999999999999891580, -0.2249999999999999999945790, -0.7500000000000000000000000, 0.8249999999999999999891580, -0.2249999999999999999945790, 0.4749999999999999999945790, -0.2249999999999999999945790, -0.7500000000000000000000000, 0.4749999999999999999945790, -0.2249999999999999999945790, 0.8249999999999999999891580, -0.2249999999999999999945790, -0.2249999999999999999945790, -0.2249999999999999999945790, 0.4749999999999999999945790, 0.4749999999999999999945790, 0.1250000000000000000000000, -0.2249999999999999999945790, 0.4749999999999999999945790, 0.8249999999999999999891580, 0.4749999999999999999945790, 1.0000000000000000000000000, 0.8999999999999999999783160, -0.2000000000000000000433681, 1.7799999999999999999739791, 0.8999999999999999999783160, -0.2000000000000000000433681, 1.7799999999999999999739791, 1.3400000000000000000303577, 0.0199999999999999999284427, 1.7799999999999999999739791, -0.2000000000000000000433681, 1.7799999999999999999739791, 0.4599999999999999999533793, 0.8999999999999999999783160, 1.3400000000000000000303577, 0.4599999999999999999533793 ]) self.cl[0]=500.0 self.ch[0]=np.Inf
[docs]class DIFF2(MADSPROB): """ DIFF2 test function (n=2, nc=0). Published as the problem (4.1) in [madsqm]_. See the :class:`MADSPROB` class for more details. """ name="DIFF2" def __init__(self): MADSPROB.__init__(self, n=2, nc=0) # Intial point is not given, so we use (-100, -100) self.initial=np.array([-90.0, -90.0]) self.fmin=-2e-4 self.xl[0]=-100.0 self.xh[0]=100.0 self.xl[1]=-100.0 self.xh[1]=100.0 def __call__(self, x, gradient=False): self.fi[0]=np.abs(x[0]-x[1])-1e-6*(x[0]+x[1]) if gradient: if x[0]>x[1]: self.J[0,0]=1.0-1e-6 self.J[0,1]=-1.0-1e-6 else: self.J[0,0]=-1.0-1e-6 self.J[0,1]=1.0-1e-6
[docs]class UFO7_26(MADSPROB): """ Problem from UFO manual (n, nc=int(3*(n-2)/2)). Published as the first problem in section 7.26 of [ufo]_. See the :class:`MADSPROB` class for more details. """ name="UFO7_26" def __init__(self, n=10): nc=int(3*(n-2)/2) MADSPROB.__init__(self, n=n,nc=nc) self.initial=np.zeros(n) self.xl=np.zeros(n) self.xh=np.zeros(n) self.xl.fill(-np.Inf) self.xh.fill(np.Inf) self.cl=np.zeros(nc) self.ch=np.zeros(nc) self.cl.fill(-np.Inf) def __call__(self, x, gradient=False): self.fi[0]=( x[0:-3]**2+x[1:-2]**2+2*x[2:-1]**2+x[3:]**2 -5*x[0:-3]-5*x[1:-2]-21*x[2:-1]+7*x[3:] ).sum() for k in range(self.nc): j=2*(k//3+1) j1=j-1 if k%3==0: self.ci[k]=x[j1-1]**2+x[j1]**2+x[j1+1]**2+x[j1+2]**2+x[j1-1]-x[j1]+x[j1+1]-x[j1+2]-8.0 elif k%3==1: self.ci[k]=x[j1-1]**2+2*x[j1]**2+x[j1+1]**2+2*x[j1+2]**2-x[j1-1]-x[j1+2]-10.0 else: self.ci[k]=2*x[j1-1]**2+x[j1]**2+x[j1+1]**2+2*x[j1-1]-x[j1]-x[j1+2]-5.0 if gradient: raise TestFunctionError(DbgMsg("MADSPROB", "Gradient not implemented."))
[docs] def cpi(self): """ Returns the common problem interface. xmin is not available. See the :class:`CPI` class for more information. """ itf=MADSPROB.cpi(self) itf['g']=None itf['cg']=None return itf
[docs]class UFO7_29(MADSPROB): """ Problem from UFO manual (n, nc=n-2). Published as the first problem in section 7.29 of [ufo]_. See the :class:`MADSPROB` class for more details. """ name="UFO7_29" def __init__(self, n=10): nc=n-2 MADSPROB.__init__(self, n=n,nc=nc) self.initial=np.zeros(n) self.initial[0::2]=-1.2 self.initial[1::2]=1.0 self.xl=np.zeros(n) self.xh=np.zeros(n) self.xl.fill(-np.Inf) self.xh.fill(np.Inf) self.cl=np.zeros(nc) self.ch=np.zeros(nc) self.ch.fill(np.Inf) def __call__(self, x, gradient=False): self.fi[0]=( 10*np.abs(x[0:-1]**2-x[1:])+np.abs(x[0:-1]-1.0) ).sum() for ii in range(self.nc): self.ci[ii]=( 3*x[ii+1]**3+2*x[ii+2]-5.0 +np.sin(x[ii+1]-x[ii+2])*np.sin(x[ii+1]+x[ii+2]) +4*x[ii+1]-x[ii]*np.exp(x[ii]-x[ii+1]) -3.0-2.0 ) if gradient: raise TestFunctionError(DbgMsg("MADSPROB", "Gradient not implemented."))
[docs] def cpi(self): """ Returns the common problem interface. xmin is not available. See the :class:`CPI` class for more information. """ itf=MADSPROB.cpi(self) itf['g']=None itf['cg']=None return itf
MADSPROBsuite=[ # Nonlinearly constrained problems SNAKE, DISK, CRESCENT, G2, # nonsmooth objective B250, B500, DIFF2, UFO7_26, UFO7_29, ] """ A list holding references to all function classes in this module. """ try: from . import _mads __all__.append("MDO") __all__.append("STYRENE")
[docs] class MDO(CPI): """ A multidisciplinary design optimization problem - maximization of aircraft range. Warning - possible memory leaks and crashes the c++ code is not cleaned up. Published in [madsvns]_. """ def __init__(self, eps=1e-12, maxiter=100): self.name="MDO" self.n=10 self.nc=10 self.eps=eps self.maxiter=maxiter self.cl=np.zeros(10) self.ch=np.zeros(10) self.cl.fill(-np.Inf) self.ch.fill(1e-14) self.xl=np.array([0.10, 0.75, 0.75, 0.1, 0.01, 30000, 1.4, 2.5, 40, 500]) self.xh=np.array([0.40, 1.25, 1.25, 1.0, 0.09, 60000, 1.8, 8.5, 70, 1500]) self.initial=np.array([0.4, 1, 0.872, 0.4433, 0.05, 45000, 1.728, 3.196, 62.68, 1000]) self.initialinf=np.array([0.4, 0.75, 0.75, 0.189296875, 0.09, 57000, 1.4, 2.5, 70, 1500]) self.fmin=-3964.0
[docs] def fc(self, x): """ Returns the value of the function and the constraints at *x*. """ return _mads.mdo_wrap(x, self.eps, self.maxiter)
[docs] def cpi(self): """ Returns the common problem interface. xmin, f, and c are not available. Only fc is available. See the :class:`CPI` class for more information. """ itf=self.prepareCPI(self.n, m=self.nc) itf['name']=self.name itf['x0']=self.initial itf['fc']=MemberWrapper(self, 'fc') itf['xlo']=self.xl itf['xhi']=self.xh itf['clo']=self.cl itf['chi']=self.ch return self.fixBounds(itf)
[docs] class STYRENE(CPI): """ An engineering optimization problem - styrene process optimization Warning - possible memory leaks and crashes the c++ code is not cleaned up. Published in [madsvns]_. """ def __init__(self): self.name="STYRENE" self.n=8 self.nc=11 self.cl=np.zeros(11) self.ch=np.zeros(11) self.cl.fill(-np.Inf) self.ch.fill(1e-14) self.xl=np.zeros(8) self.xh=np.ones(8)*100.0 self.initial=np.array([54.0, 66, 86, 8, 29, 51, 32, 15]) self.initialinf=None self.fmin=-3.35
[docs] def fc(self, x): """ Returns the value of the function and the constraints at *x*. """ return _mads.sty_wrap(x)
[docs] def cpi(self): """ Returns the common problem interface. xmin, f, and c are not available. Only fc is available. See the :class:`CPI` class for more information. """ itf=self.prepareCPI(self.n, m=self.nc) itf['name']=self.name itf['x0']=self.initial itf['fc']=MemberWrapper(self, 'fc') itf['xlo']=self.xl itf['xhi']=self.xh itf['clo']=self.cl itf['chi']=self.ch return self.fixBounds(itf)
MADSPROBsuite.append(MDO) MADSPROBsuite.append(STYRENE) except: pass try: from . import _lvns __all__.append("MAD6_mod") __all__.append("HS114_mod") # Eliminate x7 and x6 from MAD6 to get a n=5 dimensional problem
[docs] class MAD6_mod(CPI): """ Modification of the MAD6 problem from the :mod:`lvns` module. The MAD6 problem has 7 variables. One of them has an equality constraint imposed (x7). There is also a linear equality constraint involving x4 and x6. This modification eliminates x6 and x7 resulting in a problem with 5 variables and no equality constraint. Published in [madsort]_. """
[docs] def setup(self): """ Initializes the binary implementation of the function. After this function is called no other function from the same test set may be created or initialized because that will change the internal variables and break the function. Returns an info structure. """ return _lvns.eild22(5)
def __init__(self): self.name="MAD6_mod" info=self.setup() self.n=info['n']-2 self.m=info['m'] self.nc=info['nc']-2 self.initial=np.array([0.5, 1.0, 1.5, 2.0, 2.5]) self.fmin=0.10183089 # Initial point # -x4+x6=1 ... x6=1+x4 ... x6=1+2=3 # x7=3.5 # Constraints (equality) # -x4+x6=1.0 ... x6=1.0+x4 # x7=3.5 # Elimination (constraints) # -x5+x6>=0.4 ... -x5+(1+x4)>=0.4 ... x4-x5>=-0.6 # -x6+x7>=0.4 ... -(1.0+x4)+3.5>=0.4 ... -x4>=-2.1 ... x4<=2.1 # Bounds self.xl=np.array([0.4, -np.Inf, -np.Inf, -np.Inf, -np.Inf]) self.xh=np.array([np.Inf, np.Inf, np.Inf, 2.1, np.Inf]) # Constraints self.cl=np.array([0.4, 0.4, 0.4, 0.4, -0.6]) self.ch=np.array([np.Inf, np.Inf, np.Inf, np.Inf, np.Inf]) # Jacobian self.Jc=np.array([ [-1.0, 1.0, 0.0, 0.0, 0.0], [ 0.0,-1.0, 1.0, 0.0, 0.0], [ 0.0, 0.0,-1.0, 1.0, 0.0], [ 0.0, 0.0, 0.0,-1.0, 1.0], [ 0.0, 0.0, 0.0, 1.0,-1.0] ])
[docs] def fc(self, x): """ Returns the value of the function and the constraints at *x*. """ xx=np.hstack((x,1.0+x[3],3.5)) f=_lvns.tafu22(5, xx).max() c=np.dot(self.Jc, x.reshape((self.n,1))).reshape((self.nc)) return (f,c)
[docs] def cpi(self): """ Returns the common problem interface. xmin, f, and c are not available. Only fc is available. See the :class:`CPI` class for more information. """ itf=self.prepareCPI(self.n, m=self.nc) itf['name']=self.name itf['x0']=self.initial itf['fc']=MemberWrapper(self, 'fc') itf['setup']=MemberWrapper(self, 'setup') itf['xlo']=self.xl itf['xhi']=self.xh itf['clo']=self.cl itf['chi']=self.ch return self.fixBounds(itf)
# Eliminate x5 from HS114 to get a n=9 dimensional problem
[docs] class HS114_mod(CPI): """ Modification of the HS114 problem from the :mod:`lvns` module. The HS114 problem has 10 variables. One linear equality constraint links x1, x4, and x5. This modification eliminates x5 resulting in a problem with 9 variables and no equality constraint. Published in [madsort]_. """
[docs] def setup(self): """ Initializes the binary implementation of the function. After this function is called no other function from the same test set may be created or initialized because that will change the internal variables and break the function. Returns an info structure. """ return _lvns.eild22(11)
def __init__(self): self.name="HS114_mod" info=self.setup() self.n=info['n']-1 self.m=info['m'] self.nc=info['nc']-1 self.initial=np.hstack((info['x0'][:4], info['x0'][5:])) self.fmin=-1768.8070 # Constraints (equality) # 1.22 x4 - x1 - x5 = 0 ... x5 = 1.22 x4 - x1 # Initial point # x5 = 1.22 x4 - x1 = 1973.56 # Bounds bt=info['bt'] if bt.shape[0]==0: # No bounds vector given, infinite bounds self.xl=np.zeros(self.n) self.xl.fill(-np.Inf); self.xh=np.zeros(self.n) self.xh.fill(np.Inf); else: self.xl=info['xl'] self.xh=info['xh'] # No bound self.xl=np.where(bt==0, -np.Inf, self.xl) self.xh=np.where(bt==0, np.Inf, self.xh) # Lower bound only self.xh=np.where(bt==1, np.Inf, self.xh) # Upper bound only self.xl=np.where(bt==2, -np.Inf, self.xl) self.xl=np.hstack((self.xl[:4], self.xl[5:])) self.xh=np.hstack((self.xh[:4], self.xh[5:])) # Constraints ct=info['ct'] self.cl=info['cl'] self.ch=info['ch'] # No constraint self.cl=np.where(ct==0, -np.Inf, self.cl) self.ch=np.where(ct==0, np.Inf, self.ch) # Lower bound only self.ch=np.where(ct==1, np.Inf, self.ch) # Upper bound only self.cl=np.where(ct==2, -np.Inf, self.cl) self.cl=self.cl[:-1] self.ch=self.ch[:-1] self.Jc=info['Jc']
[docs] def fc(self, x): """ Returns the value of the function and the constraints at *x*. """ xx=np.hstack((x[:4], 1.22*x[3]-x[0], x[4:])) f=_lvns.tafu22(11, xx).max() c=np.dot(self.Jc, xx.reshape((self.n+1,1))).reshape((self.nc+1))[:-1] return (f,c)
[docs] def cpi(self): """ Returns the common problem interface. xmin, f, and c are not available. Only fc is available. See the :class:`CPI` class for more information. """ itf=self.prepareCPI(self.n, m=self.nc) itf['name']=self.name itf['x0']=self.initial itf['fc']=MemberWrapper(self, 'fc') itf['setup']=MemberWrapper(self, 'setup') itf['xlo']=self.xl itf['xhi']=self.xh itf['clo']=self.cl itf['chi']=self.ch return self.fixBounds(itf)
MADSPROBsuite.append(MAD6_mod) MADSPROBsuite.append(HS114_mod) except: pass