def _getFuncCalcEngine(self, x, **kwargs): if hasattr(x, 'xf'): #return x.xf[self] if x.probType == 'MOP': s = 'evaluation of MOP result on arguments is unimplemented yet, use r.solutions' raise FuncDesignerException(s) return self._getFuncCalcEngine(x.xf, **kwargs) # essential for SP r = x.get(self, None) if r is not None: if isinstance(r, Stochastic): r = yield_stochastic(r, x, self) return r r = x.get(self.name, None) if r is not None: return r Tmp = getattr(x, '_dictOfStochVars', {}) r = Tmp.get(self, None) if r is not None: r = yield_stochastic(r, x, self) return r # check for fixed oovars dictOfFixedFuncs = getattr(x, 'dictOfFixedFuncs', {}) r = dictOfFixedFuncs.get(self, None) if r is not None: return r s = '''for oovar %s the point involved doesn't contain neither name nor the oovar instance. Maybe you try to get function value or derivative in a point where value for an oovar is missing or run optimization problem without setting initial value for this variable in start point ''' % self.name raise FuncDesignerException(s)
def __ge__(self, other): if self.dtype != object and (not isinstance(other, ooarray) or other.dtype != object): return self.view(ndarray) >= (other.view(ndarray) if isinstance( other, ooarray) else other) if isinstance( other, (ndarray, list, tuple)) and self.size > 1 and len(other) > 1: return ooarray([self[i] >= other[i] for i in range(self.size)]) if isscalar(other) or (isinstance(other, (ndarray, list, tuple)) and len(other) == 1): return ooarray([elem >= other for elem in self]) if isinstance(other, oofun): if 'size' in other.__dict__ and not isinstance(other.size, oofun): if other.size == self.size: return ooarray( [elem[i] >= other[i] for i in range(self.size)]) elif self.size == 1: return ooarray( [self[0] >= other[i] for i in range(other.size)]) else: FuncDesignerException( 'bug or yet unimplemented case in FD kernel') else: # !!! assunimg other.size = 1 return ooarray([elem >= other for elem in self]) raise FuncDesignerException('unimplemented yet')
def __call__(self, *args, **kwargs): #if self.dtype != object: return self.view(ndarray) # TODO: give different names for each element while assigning name to ooarray expected_kwargs = self.expected_kwargs #if not set(kwargs.keys()).issubset(expected_kwargs): #raise FuncDesignerException('Unexpected kwargs: should be in '+str(expected_kwargs)+' got: '+str(kwargs.keys())) for elem in expected_kwargs: if elem in kwargs: setattr(self, elem, kwargs[elem]) if len(args) > 1: raise FuncDesignerException( 'No more than single argument is expected') if len(args) == 0: if len(kwargs) == 0: raise FuncDesignerException( 'You should provide at least one argument') #return self if len(args) != 0 and isinstance(args[0], str): self.name = args[0] for i, elem in enumerate(self.view(ndarray)): if isinstance(elem, oofun): elem(self.name + '_' + str(i)) args = args[1:] if len(args) == 0: return self #tmp = asarray([asscalar(asarray(self[i](*args, **kwargs))) if isinstance(self[i], oofun) else self[i] for i in range(self.size)]) if self.size == 1 and type(self.item()) == oofun: return self.item()(*args, **kwargs) # TODO: get rid of self in args[0] if self._is_array_of_oovars and isinstance( args[0], dict) and self in args[0] and len(args) == 1 and len( kwargs) == 0: return args[0][self] Tmp = [ self[i](*args, **kwargs) if isinstance(self[i], oofun) else self[i] for i in range(self.size) ] tmp = asanyarray(Tmp) if np.any([isinstance(elem, multiarray) for elem in Tmp]): tmp = tmp.T.view(multiarray) if tmp.ndim == 2 or tmp.dtype != object: return tmp else: #tmp = tmp.flatten() return ooarray(tmp)
def d2(arg, v, **kw): #, *args, **kw): N = len(v) timestep = v[1] - v[0] if not all(abs(v[1:] - v[:-1] - timestep) < 1e-10): raise FuncDesignerException('unimplemented for non-uniform step yet') stencil = kw.get('stencil', 1) if stencil not in (1, ): raise FuncDesignerException('for d2 only stencil = 1 is implemented') if stencil == 1: r1 = arg[0] - 2 * arg[1] + arg[2] r2 = arg[0:N - 2] - 2 * arg[1:N - 1] + arg[2:N] r3 = arg[N - 1] - 2 * arg[N - 2] + arg[N - 3] return hstack((r1, r2, r3)) / timestep**2
def oovars(*args, **kw): if isPyPy: raise FuncDesignerException(''' for PyPy using oovars() is impossible yet. You could use oovar(size=n), also you can create list or tuple of oovars in a cycle, e.g. a = [oovar('a'+str(i)) for i in range(100)] but you should ensure you haven't operations like k*a or a+val in your code, it may work in completely different way (e.g. k*a will produce Python list of k a instances) ''') lb = kw.pop('lb', None) ub = kw.pop('ub', None) if len(args) == 1: if type(args[0]) in (int, int16, int32, int64): r = ooarray([oovar(**kw) for i in range(args[0])]) elif type(args[0]) in [list, tuple]: r = ooarray( [oovar(name=args[0][i], **kw) for i in range(len(args[0]))]) elif type(args[0]) == str: r = ooarray([oovar(name=s, **kw) for s in args[0].split()]) else: raise FuncDesignerException( 'incorrect args number for oovars constructor') else: r = ooarray([oovar(name=args[i], **kw) for i in range(len(args))]) if lb is not None: if np.isscalar(lb) or (isinstance(lb, np.ndarray) and lb.size == 1): for v in r.view(np.ndarray): v.lb = lb else: assert type(lb) in (list, tuple, ndarray) for i, v in enumerate(r): v.lb = lb[i] if ub is not None: if np.isscalar(ub) or (isinstance(ub, np.ndarray) and ub.size == 1): for v in r.view(np.ndarray): v.ub = ub else: assert type(ub) in (list, tuple, ndarray) for i, v in enumerate(r): v.ub = ub[i] r._is_array_of_oovars = True return r
def __call__(self, point): if not isinstance(point, dict): raise FuncDesignerException('argument should be Python dictionary') if not isinstance(point, ooPoint): point = ooPoint(point) r = ooSystemState([(elem, simplify(elem(point))) for elem in self.items]) # handling constraints #!!!!!!!!!!!!!!!!!!! TODO: perform attached constraints lookup only once if ooSystem wasn't modified by += or &= etc cons = self._getAllConstraints() activeConstraints = [] allAreFinite = all( [all(isfinite(asarray(elem(point)))) for elem in self.items]) for c in cons: val = c.oofun(point) if c(point) is False or any(isnan(atleast_1d(val))): activeConstraints.append(c) #_activeConstraints.append([c, val, max((val-c.ub, c.lb-val)), c.tol]) r.isFeasible = True if len( activeConstraints) == 0 and allAreFinite else False #r._activeConstraints = activeConstraints r.activeConstraints = activeConstraints return r
def OR(*args): Args = args[0] if len(args) == 1 and isinstance(args[0], (ndarray, list, tuple, set)) else args assert not isinstance(args[0], ndarray), 'unimplemented yet' Args2 = [] for arg in Args: if not isinstance(arg, OOFun): if arg is True: return True elif arg is False: continue raise FuncDesignerException(''' FuncDesigner logical OR currently is implemented for oofun instances or list/tuple/set on them only''') Args2.append(arg) if len(Args2) == 0: return False elif len(Args2) == 1: return Args2[0] r = ~AND([~elem for elem in Args2]) #r.fun = np.logical_or r.oofun = r return r
def decodeArgs(self, *args, **kwargs): hasStartPoint = False for arg in args: if isinstance(arg, str): self.matrixSLEsolver = arg elif isinstance(arg, dict): startPoint = args[0] hasStartPoint = True else: raise FuncDesignerException('incorrect arg type, should be string (solver name) or dict (start point)') if 'startPoint' in kwargs: startPoint = kwargs['startPoint'] hasStartPoint = True if not hasStartPoint: if hasattr(self, 'startPoint'): return # established from __init__ involvedOOVars = set() for Elem in self.equations: elem = Elem.oofun if Elem.isConstraint else Elem if elem.is_oovar: involvedOOVars.add(elem) else: involvedOOVars.update(elem._getDep()) startPoint = {} for oov in involvedOOVars: if isscalar(oov.size): startPoint[oov] = zeros(oov.size) else: startPoint[oov] = 0 self.startPoint = startPoint
def __add__(self, other): if isinstance(other, list): other = ooarray(other) if isinstance(other, ndarray) and other.size == 1: other = other.item() if isscalar(other) or (isinstance(other, ndarray) and other.size in (1, self.size)): # if isinstance(other, ndarray) and other.size != self.size: # assert other.size == 1 or self.size == 1, \ # 'ooarrays must be of same size or one of them has be of length 1' # N = PythonMax(self.size, other.size) # r = ooarray([self[i]+other[i] for i in range(N)]) # else: r = ooarray(self.view(ndarray) + other) elif isinstance(other, oofun): if self.dtype != object: r = self.view(ndarray) + other else: s = atleast_1d(self) r = ooarray([s[i] + other for i in range(self.size)]) elif isinstance(other, ndarray): if self.dtype != object: r = self.view(ndarray) + other.view(ndarray) elif self.size == 1: r = other + asscalar(self) else: # TODO: mb return mere ooarray(self.view(ndarray) + other) or ooarray(self.view(ndarray) + other.view(ndarray))? r = ooarray([self[i] + other[i] for i in range(self.size)]) else: raise FuncDesignerException('unimplemented yet') if isinstance(r, ndarray) and r.size == 1 and r.dtype in ( object, oofun, float, np.float64): # not sf.Point,todo: rework r = asscalar(r) return r
def distrib_err_fcn(*args, **kw): from FDmisc import FuncDesignerException raise FuncDesignerException(''' direct operations (like +, -, *, /, ** etc) on stochastic distributions are forbidden, you should declare FuncDesigner variables, define function(s) on them and then get new distribution via evaluating the obtained oofun(s) on a data point ''')
def __add__(self, other): if isinstance(other, list): other = ooarray(other) if isscalar(other) or (isinstance(other, ndarray) and other.size in (1, self.size)): r = ooarray(self.view(ndarray) + other) elif isinstance(other, oofun): if self.dtype != object: r = self.view(ndarray) + other else: s = atleast_1d(self) r = ooarray([s[i] + other for i in range(self.size)]) elif isinstance(other, ndarray): if self.dtype != object: r = self.view(ndarray) + other.view(ndarray) elif self.size == 1: r = other + asscalar(self) else: # TODO: mb return mere ooarray(self.view(ndarray) + other) or ooarray(self.view(ndarray) + other.view(ndarray))? r = ooarray([self[i] + other[i] for i in range(self.size)]) else: raise FuncDesignerException('unimplemented yet') if isinstance(r, ndarray) and r.size == 1: r = asscalar(r) return r
def sp_err(self, *args, **kw): raise FuncDesignerException(''' to use FuncDesigner stochastic programming you should have FuncDesigner with its stochastic module installed (this addon is commercial, free for research/educational small-scale problems only). Visit http://openopt.org/StochasticProgramming for more details. ''')
def AND(*args): from BooleanOOFun import BooleanOOFun Args = args[0] if len(args) == 1 and isinstance(args[0], (ndarray, tuple, list, set)) else args assert not isinstance(args[0], ndarray), 'unimplemented yet' Args2 = [] for arg in Args: if not isinstance(arg, OOFun): if arg is False: return False elif arg is True: continue raise FuncDesignerException( 'FuncDesigner logical AND currently is implemented for oofun instances only' ) Args2.append(arg) if len(Args2) == 0: return True elif len(Args2) == 1: return Args2[0] f = logical_and if len(Args2) == 2 else alt_AND_engine r = BooleanOOFun(f, Args2, vectorized=True) r.nlh = lambda *arguments: nlh_and(Args2, r._getDep(), *arguments) r.oofun = r return r
def nlh_and(_input, dep, Lx, Ux, p, dataType): nlh_0 = array(0.0) R = {} DefiniteRange = True elems_nlh = [(elem.nlh(Lx, Ux, p, dataType) if isinstance(elem, OOFun) \ else (0, {}, None) if elem is True else (inf, {}, None) if elem is False else raise_except()) for elem in _input] for T0, res, DefiniteRange2 in elems_nlh: DefiniteRange = logical_and(DefiniteRange, DefiniteRange2) for T0, res, DefiniteRange2 in elems_nlh: if T0 is None or T0 is True: continue if T0 is False or all(T0 == inf): return inf, {}, DefiniteRange if all(isnan(T0)): raise FuncDesignerException( 'unimplemented for non-oofun or fixed oofun input yet') if type(T0) == ndarray: if nlh_0.shape == T0.shape: nlh_0 += T0 elif nlh_0.size == T0.size: nlh_0 += T0.reshape(nlh_0.shape) else: nlh_0 = nlh_0 + T0 else: nlh_0 += T0 # debug # if not any(isfinite(nlh_0)): # return inf, {}, DefiniteRange # for T0, res, DefiniteRange2 in elems_nlh: #debug end T_0_vect = T0.reshape(-1, 1) if type(T0) == ndarray else T0 for v, val in res.items(): r = R.get(v, None) if r is None: R[v] = val - T_0_vect else: r += (val if r.shape == val.shape else val.reshape( r.shape)) - T_0_vect nlh_0_shape = nlh_0.shape nlh_0 = nlh_0.reshape(-1, 1) for v, val in R.items(): # TODO: check it #assert all(isfinite(val)) tmp = val + nlh_0 tmp[isnan(tmp)] = inf # when val = -inf summation with nlh_0 == inf R[v] = tmp return nlh_0.reshape(nlh_0_shape), R, DefiniteRange
def __init__(self, *args, **kwargs): BaseFDConstraint.__init__(self, *args, **kwargs) self.lb, self.ub = -inf, inf for key, val in kwargs.items(): if key in ['lb', 'ub', 'tol']: setattr(self, key, asfarray(val)) else: raise FuncDesignerException('Unexpected key in FuncDesigner constraint constructor kwargs')
def __init__(self, oofun_Involved, *args, **kwargs): BooleanOOFun.__init__(self, oofun_Involved._getFuncCalcEngine, (oofun_Involved.input if not oofun_Involved.is_oovar else oofun_Involved), *args, **kwargs) #oofun.__init__(self, lambda x: oofun_Involved(x), input = oofun_Involved) if len(args) != 0: raise FuncDesignerException('No args are allowed for FuncDesigner constraint constructor, only some kwargs') # TODO: replace self.oofun by self.engine self.oofun = oofun_Involved
def vect_func(x): p2[integration_var] = x tmp = func(p2) if np.isscalar(tmp): return tmp elif tmp.size == 1: return np.asscalar(tmp) else: FuncDesignerException( 'incorrect data type, probably bug in uncDesigner kernel')
def __init__(self, name=None, *args, **kwargs): if len(args) > 0: raise FuncDesignerException( 'incorrect args number for oovar constructor') if name is None: self.name = 'unnamed_' + str(oovar._unnamedVarNumber) oovar._unnamedVarNumber += 1 else: kwargs['name'] = name oofun.__init__(self, f_none, *args, **kwargs)
def _getFuncCalcEngine(self, x, **kwargs): #print x if hasattr(x, 'xf'): #return x.xf[self] if x.probType == 'MOP': s = 'evaluation of MOP result on arguments is unimplemented yet, use r.solutions' raise FuncDesignerException(s) return self._getFuncCalcEngine(x.xf, **kwargs) # essential for SP r = x.get(self, None) if r is not None: if isinstance(r, Stochastic): sz = getattr(x, 'maxDistributionSize', 0) if sz == 0: s = ''' if one of function arguments is stochastic distribution without resolving into quantified value (e.g. uniform(-10,10) instead of uniform(-10,10, 100), 100 is number of point to emulate) then you should evaluate the function onto oopoint with assigned parameter maxDistributionSize''' raise FuncDesignerException(s) if not r.quantified: r = r._yield_quantified(sz) r = r.copy() r.stochDep = {self: 1} r.maxDistributionSize = sz if r.size > sz: r.reduce(sz) tmp = getattr(x, '_p', None) if tmp is not None: r._p = tmp return r r = x.get(self.name, None) if r is not None: return r else: s = '''for oovar %s the point involved doesn't contain neither name nor the oovar instance. Maybe you try to get function value or derivative in a point where value for an oovar is missing or run optimization problem without setting initial value for this variable in start point ''' % self.name raise FuncDesignerException(s)
def __init__(self, equations, time, startPoint=None): #, **kw): self.equations = equations self.startPoint = startPoint self.time = time s = 'for DAE time must be dict of len 1 or array, ' if type(time) == dict: if len(time) != 1: raise FuncDesignerException(s + 'got dict of len ' + str(len(time))) self.timeInterval = asarray(next(iter(time.values()))) self.N = self.timeInterval.size else: if type(time) not in (list, tuple, ndarray): raise FuncDesignerException(s + 'got type %s insead ' + str(type(time))) self.N = len(time) self.timeInterval = time if self.N < 2: raise FuncDesignerException('lenght of time must be at least 2')
def plot(self, v, grid='on'): try: from pylab import plot, grid as Grid, show, legend except ImportError: raise FuncDesignerException( 'to plot DAE results you should have matplotlib installed') f, = plot(self.timeInterval, self.r(v)) legend([f], [v.name]) Grid(grid) show()
def scipy_InterpolatedUnivariateSpline(*args, **kwargs): if not scipyInstalled: raise FuncDesignerException( 'to use scipy_InterpolatedUnivariateSpline you should have scipy installed, see scipy.org' ) assert len(args) > 1 assert not isinstance(args[0], oofun) and not isinstance(args[1], oofun), \ 'init scipy splines from oovar/oofun content is not implemented yet' S = interpolate.InterpolatedUnivariateSpline(*args, **kwargs) return SplineGenerator(S, *args, **kwargs)
def mul_aux_d(x, y): Xsize, Ysize = Len(x), Len(y) if Xsize == 1: return Copy(y) elif Ysize == 1: return Diag(None, scalarMultiplier=y, size=Xsize) elif Xsize == Ysize: return Diag(y) else: raise FuncDesignerException( 'for oofun multiplication a*b should be size(a)=size(b) or size(a)=1 or size(b)=1' )
def d(arg, v, **kw): #, *args, **kw): N = len(v) # if len(args) == 1: # derivativeSide = args[0] # assert derivativeSide in ('left', 'right', 'both') # else: # derivativeSide = 'both' stencil = kw.get('stencil', 3) if stencil not in (2, 3): raise FuncDesignerException( 'for d1 only stencil = 2 and 3 are implemented') timestep = v[1] - v[0] if not all(abs(v[1:] - v[:-1] - timestep) < 1e-10): raise FuncDesignerException('unimplemented for non-uniform step yet') if stencil == 2: r1 = -3 * arg[0] + 4 * arg[1] - arg[2] r2 = (arg[2:N] - arg[0:N - 2]) / 2.0 r3 = 3 * arg[N - 1] - 4 * arg[N - 2] + arg[N - 3] return hstack((r1, r2, r3)) / timestep elif stencil == 3: r1 = -22 * arg[0] + 36 * arg[1] - 18 * arg[2] + 4 * arg[3] r2 = -22 * arg[1] + 36 * arg[2] - 18 * arg[3] + 4 * arg[ 4] # TODO: mb rework it? r3 = arg[0:N - 4] - 8 * arg[1:N - 3] + 8 * arg[3:N - 1] - arg[4:N] r4 = 22 * arg[N - 5] - 36 * arg[N - 4] + 18 * arg[N - 3] - 4 * arg[ N - 2] # TODO: mb rework it? r5 = 22 * arg[N - 4] - 36 * arg[N - 3] + 18 * arg[N - 2] - 4 * arg[N - 1] return hstack((r1, r2, r3, r4, r5)) / (12 * timestep) # if derivativeSide == 'both': # r = hstack((r1, r2, r3)) # elif derivativeSide == 'left': # r = hstack((r1, r2)) # else: # derivativeSide == 'right' # r = hstack((r2, r3)) return r
def __init__(self, equations, *args, **kwargsForOpenOptSLEconstructor): if len(args) > 0: FuncDesignerException('incorrect sle definition, too many args are obtained') if type(equations) not in [list, tuple, set]: raise FuncDesignerException('argument of sle constructor should be Python tuple or list of equations or oofuns') self.equations = equations try: from openopt import SLE except: s = "Currently to solve SLEs via FuncDesigner you should have OpenOpt installed; maybe in future the dependence will be ceased" raise FuncDesignerException(s) self.decodeArgs(*args, **kwargsForOpenOptSLEconstructor) if 'iprint' not in kwargsForOpenOptSLEconstructor.keys(): kwargsForOpenOptSLEconstructor['iprint'] = -1 self.p = SLE(self.equations, self.startPoint, **kwargsForOpenOptSLEconstructor) self.p._Prepare() self.A, self.b = self.p.C, self.p.d self.n = self.p.C.shape[0] self.decode = lambda x: self.p._vector2point(x)
def __call__(self, *args, **kwargs): expected_kwargs = self.expected_kwargs if not set(kwargs.keys()).issubset(expected_kwargs): raise FuncDesignerException('Unexpected kwargs: should be in '+str(expected_kwargs)+' got: '+str(kwargs.keys())) for elem in expected_kwargs: if elem in kwargs: setattr(self, elem, kwargs[elem]) if len(args) > 1: raise FuncDesignerException('No more than single argument is expected') if len(args) == 0: if len(kwargs) == 0: raise FuncDesignerException('You should provide at least one argument') return self if isinstance(args[0], str): self.name = args[0] return self elif hasattr(args[0], 'xf'): return self(args[0].xf) return self._getFuncCalcEngine(*args, **kwargs)
def solve(self, *args): # mb for future implementation - add **kwargsForOpenOptSLEconstructor here as well if len(args) > 2: raise FuncDesignerException('incorrect number of args, should be at most 2 (startPoint and/or solver name, order: any)') self.decodeArgs(*args) r = self.p.solve(matrixSLEsolver=self.matrixSLEsolver) if r.istop >= 0: return r else: R = {} for key, value in self.p.x0.items(): R[key] = value * nan r.xf = R r.ff = inf return r
def __iadd__(self, *args, **kwargs): assert len(kwargs) == 0, 'not implemented yet' self._changed = True if type(args[0]) in [list, tuple, set]: assert len(args) == 1 Args = args[0] else: Args = args for elem in Args: if not isinstance(elem, oofun): raise FuncDesignerException( 'ooSystem operation += expects only oofuns') self.items.update(set(Args)) return self
def XOR(*args): from BooleanOOFun import BooleanOOFun Args = args[0] if len(args) == 1 and isinstance(args[0], (ndarray, tuple, list, set)) else args assert not isinstance(args[0], ndarray), 'unimplemented yet' for arg in Args: if not isinstance(arg, OOFun): raise FuncDesignerException( 'FuncDesigner logical XOR currently is implemented for oofun instances only' ) #f = lambda *args: logical_xor(hstack([asarray(elem).reshape(-1, 1) for elem in args])) r = BooleanOOFun(f_xor, Args, vectorized=True) r.nlh = lambda *arguments: nlh_xor(Args, r._getDep(), *arguments) r.oofun = r # is it required? return r
def __call__(self, INP): us = self._un_sp if not isinstance(INP, oofun): raise FuncDesignerException( 'for scipy_InterpolatedUnivariateSpline input should be oovar/oofun,other cases not implemented yet' ) def d(x): X = np.asanyarray(x) r = Diag(us.__call__(X, 1).view(X.__class__)) return r def f(x): x = np.asanyarray(x) tmp = us.__call__(x.flatten() if x.ndim > 1 else x) return tmp if x.ndim <= 1 else tmp.reshape(x.shape) r = oofun(f, INP, d=d, isCostly=True, vectorized=True) r.engine_monotonity = self.engine_monotonity r.engine_convexity = self.engine_convexity if self.criticalPoints is not False: r._interval_ = lambda *args, **kw: spline_interval_analysis_engine( r, *args, **kw) r._nonmonotone_x = self._nonmonotone_x r._nonmonotone_y = self._nonmonotone_y else: r.criticalPoints = False def Plot(): print( 'Warning! Plotting spline is recommended from FD spline generator, not initialized spline' ) self.plot() def Residual(): print( 'Warning! Getting spline residual is recommended from FD spline generator, not initialized spline' ) return self.residual() r.plot, r.residual = Plot, Residual return r