# -*- coding: UTF-8 -*-
"""
.. inheritance-diagram:: pyopus.problems.karmitsa
:parts: 1
**Large scale nonsmooth test functions (Karmitsa set)
(PyOPUS subsystem name: KARMITSA)**
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:`_karmitsa` modules.
.. [karmitsa] Karmitsa N.: Test Problems for Large-Scale Nonsmooth
Minimization, Technical report B.4/2007,
University of Jyvaskyla, Jyvaskyla, 2007.
"""
from . import _karmitsa
import os
import numpy as np
from .cpi import CPI, MemberWrapper, TestFunctionError
try:
from ..misc.debug import DbgMsg
except:
def DbgMsg(x, y):
return x+": "+y
__all__ = [ 'LSNSU', 'LSNSB', 'LSNSI' ]
[docs]class LSNSU(CPI):
"""
Unconstrained problems from the Karmitsa test suite. Problems 10 and 11
were added by Á. Bűrmen.
* *name* - problem name
* *number* - problem number (0-11)
* *n* - problem dimension
Attributes:
* :attr:`name` - problem name
* :attr:`n` - number of variables
* :attr:`initial` - initial values of variables
* :attr:`fmin` - best known minimum
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 cpi and
the _karmitsa modules.
"""
fminTab=[
0.0,
0.0,
np.NaN,
np.NaN,
np.NaN,
0.0,
0.0,
np.NaN,
0.0,
0.0,
0.0,
np.NaN
]
names=[
"GeneralizedMAXQ",
"GeneralizedMXHILB",
"ChainedLQ",
"ChainedCB3I",
"ChainedCB3II",
"ActiveFaces",
"GeneralizedBrown2",
"ChainedMifflin2",
"ChainedCrescentI",
"ChainedCrescentII",
"GeneralizedL1HILB",
"GeneralizedWatson"
]
"List of all function names"
functionNumber=dict(zip(names, range(len(names))))
def __init__(self, name=None, number=None, n=2):
if number is None and name is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Must specify name or number."))
if number is not None and name is not None:
raise TestFunctionError(DbgMsg("KARMITSA", "Name and number cannot be specified at the same time."))
if number is not None:
self.number=number
if number<0 or number>11:
raise TestFunctionError(DbgMsg("KARMITSA", "Bad problem number."))
self.name=self.names[number]
if name is not None:
if name not in self.functionNumber:
raise TestFunctionError(DbgMsg("KARMITSA", "Function not found."))
self.number=self.functionNumber[name]
self.name=name
self.n=n
self.initial=_karmitsa.startxu(self.number, self.n)
if self.initial is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Problem selection error."))
if self.number==2:
self.fmin=-(self.n-1)*2.0**0.5
elif self.number==3:
self.fmin=2.0*(self.n-1)
elif self.number==4:
self.fmin=2.0*(self.n-1)
elif self.number==7:
if self.n==50:
self.fmin=-34.795
elif self.n==200:
self.fmin=-140.86
elif self.n==1000:
self.fmin=-706.55
else:
self.fmin=None
else:
self.fmin=self.fminTab[self.number]
[docs] def f(self, x):
"""
Returns the value of the function at *x*.
"""
if x.size!=self.n:
raise TestFunctionError(DbgMsg("KARMITSA", "Bad function argument."))
dat=_karmitsa.funcu(self.number, x)
if dat is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Evaluation failed."))
(f,g)=dat
return f
[docs] def cpi(self):
"""
Returns the common problem interface.
Subgradient is not supported.
xmin is also not available.
See the :class:`CPI` class for more information.
"""
itf=self.prepareCPI(self.n, m=0)
itf['name']=self.name
itf['x0']=self.initial
itf['f']=MemberWrapper(self, 'f')
# Gradient is not supported
# itf['g']=MemberWrapper(self, 'g')
if 'fmin' in self.__dict__:
itf['fmin']=self.fmin
return self.fixBounds(itf)
[docs]class LSNSB(CPI):
"""
Bound constrained problems from the Karmitsa test suite.
* *name* - problem name
* *number* - problem number (0-9)
* *n* - problem dimension
* *feasible* - 0=initial point unchanged, 1=feasible, 2=strictly feasible, default=1
Attributes:
* :attr:`name` - problem name
* :attr:`n` - number of variables
* :attr:`xl` - lower bounds on variables
* :attr:`xh` - upper bounds on variables
* :attr:`initial` - initial values of variables
* :attr:`fmin` - best known minimum
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 cpi and
the _karmitsa modules.
"""
fminTab=[
0.0,
0.0,
np.NaN,
np.NaN,
np.NaN,
0.0,
0.0,
np.NaN,
0.0,
0.0
]
names=[
"GeneralizedMAXQ",
"GeneralizedMXHILB",
"ChainedLQ",
"ChainedCB3I",
"ChainedCB3II",
"ActiveFaces",
"GeneralizedBrown2",
"ChainedMifflin2",
"ChainedCrescentI",
"ChainedCrescentII",
]
"List of all function names"
functionNumber=dict(zip(names, range(len(names))))
def __init__(self, name=None, number=None, n=2, feasible=1):
if number is None and name is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Must specify name or number."))
if number is not None and name is not None:
raise TestFunctionError(DbgMsg("KARMITSA", "Name and number cannot be specified at the same time."))
if number is not None:
self.number=number
if number<0 or number>9:
raise TestFunctionError(DbgMsg("KARMITSA", "Bad problem number."))
self.name=self.names[number]
if name is not None:
if name not in self.functionNumber:
raise TestFunctionError(DbgMsg("KARMITSA", "Function not found."))
self.number=self.functionNumber[name]
self.name=name
self.n=n
x0=_karmitsa.startxb(self.number, self.n)
if x0 is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Problem selection error."))
(bt, xl, xh)=_karmitsa.bounds(self.number, self.n)
self.xl=np.where(bt==3, -np.Inf, xl)
self.xh=np.where(bt==1, np.Inf, xh)
# Project to feasible region
if feasible==1:
x0=np.where(x0<self.xl, xl, x0)
x0=np.where(x0>self.xh, xh, x0)
elif feasible==2:
feas=1e-4
x0=np.where(x0<=self.xl, xl+feas, x0)
x0=np.where(x0>=self.xh, xh-feas, x0)
self.initial=x0
if self.number==2:
self.fmin=-(self.n-1)*2.0**0.5
elif self.number==3:
self.fmin=2.0*(self.n-1)
elif self.number==4:
self.fmin=2.0*(self.n-1)
elif self.number==7:
if self.n==50:
self.fmin=-34.795
elif self.n==200:
self.fmin=-140.86
elif self.n==1000:
self.fmin=-706.55
else:
self.fmin=None
else:
self.fmin=self.fminTab[self.number]
[docs] def f(self, x):
"""
Returns the value of the function at *x*.
"""
if x.size!=self.n:
raise TestFunctionError(DbgMsg("KARMITSA", "Bad function argument."))
dat=_karmitsa.funcb(self.number, x)
(f,g)=dat
if dat is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Evaluation failed."))
return f
[docs] def cpi(self):
"""
Returns the common problem interface.
Subgradient is not supported.
xmin is also not available.
See the :class:`CPI` class for more information.
"""
itf=self.prepareCPI(self.n, m=0)
itf['name']=self.name
itf['xlo']=self.xl
itf['xhi']=self.xh
itf['x0']=self.initial
itf['f']=MemberWrapper(self, 'f')
# Gradient is not supported
# itf['g']=MemberWrapper(self, 'g')
if 'fmin' in self.__dict__:
itf['fmin']=self.fmin
return self.fixBounds(itf)
[docs]class LSNSI(CPI):
"""
Inequality constrained problems from the Karmitsa test suite.
* *name* - function name
* *number* - function number (0-9)
* *cname* - constraint name
* *cnumber* - constraint number (0-7)
* *n* - problem dimension
Attributes:
* :attr:`name` - problem name
* :attr:`fname` - function name
* :attr:`cname` - constraint name
* :attr:`n` - number of variables
* :attr:`m` - number of constraints
* :attr:`cl` - lower bounds on constraint functions
* :attr:`ch` - upper bounds on constraint functions
* :attr:`initial` - initial values of variables
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 cpi and
the _karmitsa modules.
"""
names=[
"GeneralizedMAXQ",
"GeneralizedMXHILB",
"ChainedLQ",
"ChainedCB3I",
"ChainedCB3II",
"ActiveFaces",
"GeneralizedBrown2",
"ChainedMifflin2",
"ChainedCrescentI",
"ChainedCrescentII",
]
"List of all function names"
cnames=[
"TridiagonalI",
"TridiagonalII",
"MAD1I",
"MAD1II",
"ModifiedMAD1I",
"ModifiedMAD1II",
"P20I",
"P20II",
]
"List of all constraint names"
functionNumber=dict(zip(names, range(len(names))))
constraintNumber=dict(zip(cnames, range(len(cnames))))
def __init__(self, name=None, number=None, cname=None, cnumber=None, n=10):
if number is None and name is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Must specify function name or number."))
if number is not None and name is not None:
raise TestFunctionError(DbgMsg("KARMITSA", "Function name and number cannot be specified at the same time."))
if cnumber is None and cname is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Must specify constraint name or number."))
if cnumber is not None and cname is not None:
raise TestFunctionError(DbgMsg("KARMITSA", "Constraint name and number cannot be specified at the same time."))
if number is not None:
self.fnumber=number
if number<0 or number>9:
raise TestFunctionError(DbgMsg("KARMITSA", "Bad function number."))
self.fname=self.names[number]
if name is not None:
if name not in self.functionNumber:
raise TestFunctionError(DbgMsg("KARMITSA", "Function not found."))
self.fnumber=self.functionNumber[name]
self.fname=name
if cnumber is not None:
self.cnumber=cnumber
if cnumber<0 or cnumber>7:
raise TestFunctionError(DbgMsg("KARMITSA", "Bad constraint number."))
self.cname=self.cnames[cnumber]
if cname is not None:
if cname not in self.constraintNumber:
raise TestFunctionError(DbgMsg("KARMITSA", "Constraint not found."))
self.cnumber=self.constraintNumber[cname]
self.cname=cname
self.name=self.fname+"_"+self.cname
self.n=n
dat=_karmitsa.xinit3(self.fnumber, self.cnumber, self.n)
if dat is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Problem selection error."))
(x0,m)=dat
self.initial=x0
self.m=m
self.cl=np.zeros(m)
self.cl.fill(-np.Inf)
self.ch=np.zeros(m)
[docs] def f(self, x):
"""
Returns the value of the function at *x*.
"""
if x.size!=self.n:
raise TestFunctionError(DbgMsg("KARMITSA", "Bad function argument."))
dat=_karmitsa.funci(self.fnumber, x)
if dat is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Function evaluation failed."))
(f,g)=dat
return f
[docs] def c(self, x):
"""
Returns the value of the constraints at *x*.
"""
if x.size!=self.n:
raise TestFunctionError(DbgMsg("KARMITSA", "Bad function argument."))
dat=_karmitsa.cineq(self.fnumber, self.cnumber, x)
if dat is None:
raise TestFunctionError(DbgMsg("KARMITSA", "Constraint evaluation failed."))
(c,J)=dat
return c
[docs] def cpi(self):
"""
Returns the common problem interface.
Subgradient is not supported.
xmin is also not available.
See the :class:`CPI` class for more information.
"""
itf=self.prepareCPI(self.n, self.m)
itf['name']=self.name
itf['x0']=self.initial
itf['f']=MemberWrapper(self, 'f')
itf['c']=MemberWrapper(self, 'c')
# Gradient is not supported
# itf['g']=MemberWrapper(self, 'g')
if 'fmin' in self.__dict__:
itf['fmin']=self.fmin
itf['clo']=self.cl
itf['chi']=self.ch
return self.fixBounds(itf)