def P(c, interpolate='auto'): if interpolate not in (True, False, 'auto'): raise FuncDesignerException( "in P() parameter interpolate must be True, False or 'auto'") if c is True: return 1.0 elif c is False: return 0.0 if not isinstance(c, BaseFDConstraint): raise FuncDesignerException( 'arg of FuncDesigner.P() must be True, False or FuncDesigner constraint' ) if (type(c.ub) == np.ndarray and c.ub.size != 1) or (type(c.lb) == np.ndarray and c.lb.size != 1): raise FuncDesignerException( 'stochastic constraints are unimplemented for vectorized API yet') if np.isfinite(c.ub) and c.lb == -np.inf: r = oofun(lambda x: f_quantile(x, c.ub, interpolate), c.oofun, d=lambda x: d_quantile(x, c.ub, interpolate)) elif np.isfinite(c.lb) and c.ub == np.inf: r = oofun(lambda x: 1.0 - f_quantile(x, c.lb, interpolate), c.oofun, d=lambda x: -d_quantile(x, c.lb, interpolate)) else: raise FuncDesignerException( 'stochastic constraints are implemented for case xor(isfinite(lb),isfinite(ub)) only for now' ) return r
def max(inp, *args, **kwargs): if type(inp) in (list, tuple, np.ndarray) \ and (len(args) == 0 or len(args) == 1 and not isinstance(args[0], oofun)) \ and not any([isinstance(elem, oofun) for elem in (inp if type(inp) in (list, tuple) else np.atleast_1d(inp))]): return np.max(inp, *args, **kwargs) assert len(args) == len(kwargs) == 0, 'incorrect data type in FuncDesigner max or not implemented yet' if isinstance(inp, oofun): f = lambda x: np.max(x) # def f(x): # print np.max(x) # return np.max(x) def d(x): df = inp.d(x) ind = np.argmax(x) return df[ind, :] def interval(domain, dtype): lb_ub, definiteRange = inp._interval(domain, dtype) tmp1, tmp2 = lb_ub[0], lb_ub[1] return np.vstack((np.max(np.vstack(tmp1), 0), np.max(np.vstack(tmp2), 0))), np.all(definiteRange, 0) r = oofun(f, inp, d = d, size = 1, _interval_ = interval) elif type(inp) in (list, tuple, ooarray): f = lambda *args: np.max([arg for arg in args]) def interval(domain, dtype): arg_inf, arg_sup, tmp, DefiniteRange = [], [], -np.inf, True for _inp in inp: if isinstance(_inp, oofun): #tmp1, tmp2 = _inp._interval(domain, dtype) lb_ub, definiteRange = _inp._interval(domain, dtype) tmp1, tmp2 = lb_ub[0], lb_ub[1] arg_inf.append(tmp1) arg_sup.append(tmp2) DefiniteRange = logical_and(DefiniteRange, definiteRange) elif tmp < _inp: tmp = _inp r1, r2 = np.max(np.vstack(arg_inf), 0), np.max(np.vstack(arg_sup), 0) r1[r1<tmp] = tmp r2[r2<tmp] = tmp return np.vstack((r1, r2)), DefiniteRange r = oofun(f, inp, size = 1, _interval_ = interval) def _D(point, *args, **kwargs): ind = np.argmax([(s(point) if isinstance(s, oofun) else s) for s in r.input]) return r.input[ind]._D(point, *args, **kwargs) if isinstance(r.input[ind], oofun) else {} r._D = _D else: return np.max(inp, *args, **kwargs) 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
def arcsinh(inp): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([arcsinh(elem) for elem in inp]) if hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(arcsinh(inp.values), inp.probabilities.copy())._update(inp) if not isinstance(inp, oofun): return np.arcsinh(inp) return oofun(st_arcsinh, inp, d = lambda x: Diag(1.0/np.sqrt(1+x**2)), vectorized = True, criticalPoints = False)
def exp(inp): if isinstance(inp, ooarray): return ooarray([exp(elem) for elem in inp]) if hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(exp(inp.values), inp.probabilities.copy())._update(inp) if not isinstance(inp, oofun): return np.exp(inp) return oofun(st_exp, inp, d = lambda x: Diag(np.exp(x)), vectorized = True, criticalPoints = False)
def ifThenElse(condition, val1, val2, *args, **kwargs): # for future implementation assert len(args) == 0 and len(kwargs) == 0 Val1 = atleast_oofun(val1)#fixed_oofun(val1) if not isinstance(val1, oofun) else val1 #if np.isscalar(val1): raise 0 Val2 = atleast_oofun(val2)#fixed_oofun(val2) if not isinstance(val2, oofun) else val2 if isinstance(condition, bool): return Val1 if condition else Val2 elif isinstance(condition, oofun): f = lambda conditionResult, value1Result, value2Result: value1Result if conditionResult else value2Result # !!! Don't modify it elseware function will evaluate both expressions despite of condition value r = oofun(f, [condition, val1, val2]) r.D = lambda point, *args, **kwargs: (Val1.D(point, *args, **kwargs) if isinstance(Val1, oofun) else {}) if condition(point) else \ (Val2.D(point, *args, **kwargs) if isinstance(Val2, oofun) else {}) r._D = lambda point, *args, **kwargs: (Val1._D(point, *args, **kwargs) if isinstance(Val1, oofun) else {}) if condition(point) else \ (Val2._D(point, *args, **kwargs) if isinstance(Val2, oofun) else {}) r.d = errFunc # TODO: try to set correct value from val1, val2 if condition is fixed # def getOrder(Vars=None, fixedVars=None, *args, **kwargs): # dep = condition.getDep() # if Vars is not None and dep.is return r else: raise FuncDesignerException('ifThenElse requires 1st argument (condition) to be either boolean or oofun, got %s instead' % type(condition))
def mean(arg, *args, **kw): if isinstance(arg, stochasticDistribution): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner mean() - it cannot handle additional arguments yet') r = arg.Mean elif isinstance(arg, oofun): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner mean() - it cannot handle additional arguments yet') if arg._isSum: r = o.sum([mean(elem) for elem in arg._summation_elements]) else: # def ff(x): # # TODO: same changes for std, var,other moments # #print (type(x), multiarray) # r = np.array([mean(xx) for xx in x.view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray) \ # else x if not isinstance(x, stochasticDistribution) else x.Mean # #if type(x) == np.ndarray: ## print ('!', x, r.shape) # return r r = oofun(f_mean, arg) # r = oofun(lambda x: np.array([mean(xx) for xx in (x.reshape(-1, 1) if x.ndim < 2 else x).view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray) \ # else x if not isinstance(x, stochasticDistribution) else x.Mean, arg) # TODO: move _D definition outside of the func def _D(*args, **kw): if not isinstance(arg, oofun): return {} res = arg._D(*args, **kw) res = dict([(key, elem.Mean if isinstance(elem, stochasticDistribution) else elem) for key, elem in res.items()]) return res r._D = _D else: r = np.mean(arg, *args, **kw) return r
def floor(inp): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([floor(elem) for elem in inp]) if not isinstance(inp, oofun): return np.floor(inp) r = oofun(lambda x: np.floor(x), inp, vectorized = True) r._D = lambda *args, **kwargs: raise_except('derivative for FD floor is unimplemented yet') r.criticalPoints = False#lambda arg_infinum, arg_supremum: [np.floor(arg_infinum)] return r
def abs(inp): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([abs(elem) for elem in inp]) if hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(abs(inp.values), inp.probabilities.copy())._update(inp) if not isinstance(inp, oofun): return np.abs(inp) return oofun(st_abs, inp, d = lambda x: Diag(np.sign(x)), vectorized = True, _interval_ = ZeroCriticalPointsInterval(inp, np.abs))
def __init__(self, func, _input, *args, **kwargs): oofun.__init__(self, func, _input, *args, **kwargs) #self.input = oofun_Involved.input BooleanOOFun._unnamedBooleanOOFunNumber += 1 self.name = 'unnamed_boolean_oofun_' + str(BooleanOOFun._unnamedBooleanOOFunNumber) self.oofun = oofun(lambda *args, **kw: asanyarray(func(*args, **kw), int8), _input, vectorized = True) # TODO: THIS SHOULD BE USED IN UP-LEVEL ONLY self.lb = self.ub = 1
def log2(inp): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([log2(elem) for elem in inp]) if hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(log2(inp.values), inp.probabilities.copy())._update(inp) if not isinstance(inp, oofun): return np.log2(inp) r = oofun(st_log2, inp, d = lambda x: Diag(INV_LOG_2/x), vectorized = True, _interval_ = log_interval(np.log2, inp)) r.attach((inp>1e-300)('log2_domain_zero_bound_%d' % r._id, tol=-1e-7)) return r
def sin(inp): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([sin(elem) for elem in inp]) elif hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(sin(inp.values), inp.probabilities.copy())._update(inp) elif not isinstance(inp, oofun): return np.sin(inp) return oofun(st_sin, inp, d = lambda x: Diag(np.cos(x)), vectorized = True, criticalPoints = TrigonometryCriticalPoints)
def arctanh(inp): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([arctanh(elem) for elem in inp]) if hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(arctanh(inp.values), inp.probabilities.copy())._update(inp) if not isinstance(inp, oofun): return np.arctanh(inp) r = oofun(st_arctanh, inp, d = lambda x: Diag(1.0/(1.0-x**2)), vectorized = True, criticalPoints = False) r.getDefiniteRange = get_box1_DefiniteRange r._interval_ = lambda domain, dtype: box_1_interval(inp, np.arctanh, domain, dtype, -np.inf, np.inf) return r
def arccosh(inp): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([arccosh(elem) for elem in inp]) if hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(arccosh(inp.values), inp.probabilities.copy())._update(inp) if not isinstance(inp, oofun): return np.arccosh(inp) r = oofun(st_arccosh, inp, d = lambda x: Diag(1.0/np.sqrt(x**2-1.0)), vectorized = True) F0, shift = 0.0, 1.0 r._interval_ = lambda domain, dtype: nonnegative_interval(inp, np.arccosh, domain, dtype, F0, shift) return r
def sign(inp): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([sign(elem) for elem in inp]) if hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(sign(inp.values), inp.probabilities.copy())._update(inp) if not isinstance(inp, oofun): return np.sign(inp) r = oofun(st_sign, inp, vectorized = True, d = lambda x: 0.0) r.criticalPoints = False return r
def tan(inp): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([tan(elem) for elem in inp]) if hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(tan(inp.values), inp.probabilities.copy())._update(inp) if not isinstance(inp, oofun): return np.tan(inp) # TODO: move it outside of tan definition def interval(*args): raise 'interval for tan is unimplemented yet' r = oofun(st_tan, inp, d = lambda x: Diag(1.0 / np.cos(x) ** 2), vectorized = True, interval = interval) return r
def cross(a, b): if not isinstance(a, oofun) and not isinstance(b, oofun): return np.cross(a, b) def aux_d(x, y): assert x.size == 3 and y.size == 3, 'currently FuncDesigner cross(x,y) is implemented for arrays of length 3 only' return np.array([[0, -y[2], y[1]], [y[2], 0, -y[0]], [-y[1], y[0], 0]]) r = oofun(lambda x, y: np.cross(x, y), [a, b], d=(lambda x, y: -aux_d(x, y), lambda x, y: aux_d(y, x))) r.getOrder = lambda *args, **kwargs: (a.getOrder(*args, **kwargs) if isinstance(a, oofun) else 0) + (b.getOrder(*args, **kwargs) if isinstance(b, oofun) else 0) return r
def __init__(self, func, _input, *args, **kwargs): oofun.__init__(self, func, _input, *args, **kwargs) #self.input = oofun_Involved.input # BooleanOOFun._unnamedBooleanOOFunNumber += 1 #self.name = 'unnamed_boolean_oofun_id_' + str(BooleanOOFun._unnamedBooleanOOFunNumber) self.name = 'unnamed_boolean_oofun_id_' + str(oofun._id) self.oofun = oofun( lambda *args, **kw: asanyarray(func(*args, **kw), int8), _input, vectorized=True) # TODO: THIS SHOULD BE USED IN UP-LEVEL ONLY self.lb = self.ub = 1
def P(c, interpolate = 'auto'): if interpolate not in (True, False, 'auto'): raise FuncDesignerException("in P() parameter interpolate must be True, False or 'auto'") if c is True: return 1.0 elif c is False: return 0.0 if not isinstance(c, BaseFDConstraint): raise FuncDesignerException('arg of FuncDesigner.P() must be True, False or FuncDesigner constraint') if (type(c.ub) == np.ndarray and c.ub.size != 1) or (type(c.lb) == np.ndarray and c.lb.size != 1): raise FuncDesignerException('stochastic constraints are unimplemented for vectorized API yet') if np.isfinite(c.ub) and c.lb == -np.inf: r = oofun(lambda x: f_quantile(x, c.ub, interpolate), c.oofun, d = lambda x: d_quantile(x, c.ub, interpolate)) elif np.isfinite(c.lb) and c.ub == np.inf: r = oofun(lambda x: 1.0 - f_quantile(x, c.lb, interpolate), c.oofun, d = lambda x: -d_quantile(x, c.lb, interpolate)) else: raise FuncDesignerException('stochastic constraints are implemented for case xor(isfinite(lb),isfinite(ub)) only for now') return r
def sum(inp, *args, **kwargs): if type(inp) == np.ndarray and inp.dtype != object: return np.sum(inp, *args, **kwargs) if isinstance(inp, ooarray) and inp.dtype != object: inp = inp.view(np.ndarray) cond_ooarray = isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]) if cond_ooarray and inp.size == 1: return np.asscalar(inp).sum() condIterableOfOOFuns = type(inp) in (list, tuple) or cond_ooarray if not isinstance(inp, oofun) and not condIterableOfOOFuns: return np.sum(inp, *args, **kwargs) if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): inp = inp.tolist() if condIterableOfOOFuns: d, INP, r0 = [], [], 0.0 for elem in inp: # TODO: mb use reduce() or something like that if not isinstance(elem, oofun): # not '+=' because size can be changed from 1 to another value r0 = r0 + np.asanyarray(elem) # so it doesn't work for different sizes continue INP.append(elem) if len(INP) == 0: return r0 r = oofun(lambda *args: sum_engine(r0, *args), INP, _isSum = True) r._summation_elements = INP if np.isscalar(r0) and r0 == 0.0 else INP + [r0] r.storedSumsFuncs = {} for inp in INP: Dep = [inp] if inp.is_oovar else inp._getDep() for v in Dep: if v not in r.storedSumsFuncs: r.storedSumsFuncs[v] = set() r.storedSumsFuncs[v].add(inp) # TODO: check for fixed inputs r.getOrder = lambda *args, **kw: sum_getOrder(INP, *args, **kw) R0 = np.tile(r0, (2, 1)) r._interval_ = lambda *args, **kw: sum_interval(R0, r, INP, *args, **kw) r.vectorized = True r_dep = r._getDep() r._D = lambda *args, **kw: sum_derivative(r, r0, INP, r_dep, *args, **kw) # r.isCostly = True return r else: return inp.sum(*args, **kwargs)#np.sum(inp, *args, **kwargs)
def arccos(inp): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([arccos(elem) for elem in inp]) if hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(arccos(inp.values), inp.probabilities.copy())._update(inp) if not isinstance(inp, oofun): return np.arccos(inp) r = oofun(st_arccos, inp, d = lambda x: Diag(-1.0 / np.sqrt(1.0 - x**2)), vectorized = True) r.getDefiniteRange = get_box1_DefiniteRange F_l, F_u = np.arccos((-1, 1)) r._interval_ = lambda domain, dtype: box_1_interval(inp, np.arccos, domain, dtype, F_l, F_u) r.attach((inp>-1)('arccos_domain_lower_bound_%d' % r._id, tol=-1e-7), (inp<1)('arccos_domain_upper_bound_%d' % r._id, tol=-1e-7)) return r
def std(arg, *args, **kw): if isinstance(arg, stochasticDistribution): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner std() - it cannot handle additional arguments yet') r = arg.Std elif isinstance(arg, oofun): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner std() - it cannot handle additional arguments yet') #r = oofun(lambda x: np.array([std(X[i]) for i in range() in (x.reshape(-1, 1) if x.ndim < 2 else x).view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray)\ r = oofun(f_std, arg) else: r = np.std(arg, *args, **kw) return r
def var(arg, *args, **kw): if isinstance(arg, stochasticDistribution): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner var() - it cannot handle additional arguments yet') r = arg.Var elif isinstance(arg, oofun): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner var() - it cannot handle additional arguments yet') #r = oofun(lambda x: np.array([var(xx) for xx in x.view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray)\ r = oofun(f_var, arg) else: r = np.std(var, *args, **kw) return r
def sqrt(inp, attachConstraints = True): if isinstance(inp, ooarray) and any([isinstance(elem, oofun) for elem in atleast_1d(inp)]): return ooarray([sqrt(elem) for elem in inp]) if hasStochastic and isinstance(inp, distribution.stochasticDistribution): return distribution.stochasticDistribution(sqrt(inp.values), inp.probabilities.copy())._update(inp) if not isinstance(inp, oofun): return np.sqrt(inp) # def fff(x): # print x # return np.sqrt(x) r = oofun(st_sqrt, inp, d = lambda x: Diag(0.5 / np.sqrt(x)), vectorized = True) F0 = 0.0 r._interval_ = lambda domain, dtype: nonnegative_interval(inp, np.sqrt, domain, dtype, F0) if attachConstraints: r.attach((inp>0)('sqrt_domain_zero_bound_%d' % r._id, tol=-1e-7)) return r
def dot(inp1, inp2): if not isinstance(inp1, oofun) and not isinstance(inp2, oofun): return np.dot(inp1, inp2) def aux_d(x, y): if y.size == 1: r = np.empty_like(x) r.fill(y) return Diag(r) else: return y r = oofun(lambda x, y: x * y if x.size == 1 or y.size == 1 else np.dot(x, y), [inp1, inp2], d=(lambda x, y: aux_d(x, y), lambda x, y: aux_d(y, x))) r.getOrder = lambda *args, **kwargs: (inp1.getOrder(*args, **kwargs) if isinstance(inp1, oofun) else 0) + (inp2.getOrder(*args, **kwargs) if isinstance(inp2, oofun) else 0) #r.isCostly = True return r
def categoricalAttribute(oof, attr): from ooFun import oofun L = len(oof.domain) if not hasattr(oof, 'aux_domain'): oof.aux_domain = copy.copy(oof.domain) ind_numeric = [j for j, elem in enumerate(oof.aux_domain[0]) if type(elem) not in (str, np.str_)] if len(ind_numeric): ind_first_numeric = ind_numeric[0] oof.aux_domain.sort(key = lambda elem: elem[ind_first_numeric]) oof.domain = np.arange(len(oof.domain)) ind = oof.fields.index(attr) dom = np.array([oof.aux_domain[j][ind] for j in range(L)]) f = lambda x: dom[int(x)] if type(x) != np.ndarray else dom[np.asarray(x, int)] r = oofun(f, oof, engine = attr, vectorized = True, domain = dom) r._interval_ = lambda domain, dtype: categorical_interval(r, oof, domain, dtype) return r
def var(arg, *args, **kw): if isinstance(arg, stochasticDistribution): if not len(args) == len(kw) == 0: raise FuncDesignerException( 'incorrect usage of FuncDesigner var() - it cannot handle additional arguments yet' ) r = arg.Var elif isinstance(arg, oofun): if not len(args) == len(kw) == 0: raise FuncDesignerException( 'incorrect usage of FuncDesigner var() - it cannot handle additional arguments yet' ) #r = oofun(lambda x: np.array([var(xx) for xx in x.view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray)\ r = oofun(f_var, arg) else: r = np.std(var, *args, **kw) return r
def var(arg, *args, **kw): if isinstance(arg, stochasticDistribution): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner var() - it cannot handle additional arguments yet') r = arg.Var elif isinstance(arg, oofun): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner var() - it cannot handle additional arguments yet') if is_prod_scalar(arg): multiplier, tmp = arg._fixed_part, arg._unfixed_part return multiplier**2 * var(tmp) #r = oofun(lambda x: np.array([var(xx) for xx in x.view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray)\ r = oofun(f_var, arg, engine = 'var', vectorized = True) else: r = np.var(var, *args, **kw) return r
def std(arg, *args, **kw): if isinstance(arg, stochasticDistribution): if not len(args) == len(kw) == 0: raise FuncDesignerException( 'incorrect usage of FuncDesigner std() - it cannot handle additional arguments yet' ) r = arg.Std elif isinstance(arg, oofun): if not len(args) == len(kw) == 0: raise FuncDesignerException( 'incorrect usage of FuncDesigner std() - it cannot handle additional arguments yet' ) #r = oofun(lambda x: np.array([std(X[i]) for i in range() in (x.reshape(-1, 1) if x.ndim < 2 else x).view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray)\ r = oofun(f_std, arg) else: r = np.std(arg, *args, **kw) return r
def std(arg, *args, **kw): if isinstance(arg, stochasticDistribution): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner std() - it cannot handle additional arguments yet') r = arg.Std elif isinstance(arg, oofun): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner std() - it cannot handle additional arguments yet') #r = oofun(lambda x: np.array([std(X[i]) for i in range() in (x.reshape(-1, 1) if x.ndim < 2 else x).view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray)\ if is_prod_scalar(arg): multiplier, tmp = arg._fixed_part, arg._unfixed_part return abs(multiplier) * std(tmp) r = oofun(f_std, arg, engine = 'std', vectorized = True) else: r = np.std(arg, *args, **kw) 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
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.asfarray(x) #if x.size != 1: #raise FuncDesignerException('for scipy_InterpolatedUnivariateSpline input should be oovar/oofun with output size = 1,other cases not implemented yet') return us.__call__(x, 1) def f(x): x = np.asfarray(x) #if x.size != 1: #raise FuncDesignerException('for scipy_InterpolatedUnivariateSpline input should be oovar/oofun with output size = 1,other cases not implemented yet') 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._nonmonotone_x = self._nonmonotone_x r._nonmonotone_y = self._nonmonotone_y diffX, diffY = np.diff(self._X), np.diff(self._Y) if (all(diffX >= 0) or all(diffX <= 0)) and (all(diffY >= 0) or all(diffY <= 0)) and self._k in (1, 3): r.criticalPoints = False elif self._k == 1: r._interval = lambda *args: spline_interval_analysis_engine(r, *args) else: def _interval(*args, **kw): raise FuncDesignerException(''' Currently interval calculations are implemented for sorted monotone splines with order 1 or 3 only''') r._interval = _interval 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
def categoricalAttribute(oof, attr): from ooFun import oofun L = len(oof.domain) if not hasattr(oof, 'aux_domain'): oof.aux_domain = copy.copy(oof.domain) ind_numeric = [ j for j, elem in enumerate(oof.aux_domain[0]) if type(elem) not in (str, np.str_) ] if len(ind_numeric): ind_first_numeric = ind_numeric[0] oof.aux_domain.sort(key=lambda elem: elem[ind_first_numeric]) oof.domain = np.arange(len(oof.domain)) ind = oof.fields.index(attr) dom = np.array([oof.aux_domain[j][ind] for j in range(L)]) f = lambda x: dom[int(x)] if type(x) != np.ndarray else dom[np.asarray( x, int)] r = oofun(f, oof, engine=attr, vectorized=True, domain=dom) r._interval_ = lambda domain, dtype: categorical_interval( r, oof, domain, dtype) return r
def mean(arg, *args, **kw): if isinstance(arg, stochasticDistribution): if not len(args) == len(kw) == 0: raise FuncDesignerException( 'incorrect usage of FuncDesigner mean() - it cannot handle additional arguments yet' ) r = arg.Mean elif isinstance(arg, oofun): if not len(args) == len(kw) == 0: raise FuncDesignerException( 'incorrect usage of FuncDesigner mean() - it cannot handle additional arguments yet' ) if arg._isSum: r = o.sum([mean(elem) for elem in arg._summation_elements]) else: # def ff(x): # # TODO: same changes for std, var,other moments # #print (type(x), multiarray) # r = np.array([mean(xx) for xx in x.view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray) \ # else x if not isinstance(x, stochasticDistribution) else x.Mean # #if type(x) == np.ndarray: ## print ('!', x, r.shape) # return r r = oofun(f_mean, arg) # r = oofun(lambda x: np.array([mean(xx) for xx in (x.reshape(-1, 1) if x.ndim < 2 else x).view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray) \ # else x if not isinstance(x, stochasticDistribution) else x.Mean, arg) # TODO: move _D definition outside of the func def _D(*args, **kw): if not isinstance(arg, oofun): return {} res = arg._D(*args, **kw) res = dict([(key, elem.Mean if isinstance( elem, stochasticDistribution) else elem) for key, elem in res.items()]) return res r._D = _D else: r = np.mean(arg, *args, **kw) return r
def mean(arg, *args, **kw): if isinstance(arg, stochasticDistribution): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner mean() - it cannot handle additional arguments yet') r = arg.Mean elif isinstance(arg, oofun): if not len(args) == len(kw) == 0: raise FuncDesignerException('incorrect usage of FuncDesigner mean() - it cannot handle additional arguments yet') if arg._isSum: r = o.sum([mean(elem) for elem in arg._summation_elements]) elif is_prod_scalar(arg): # TODO: rework it when np.prod(objects) will be fixed multiplier, tmp = arg._fixed_part, arg._unfixed_part return multiplier * mean(tmp) # elif arg._isProd: # tmp = [elem for elem in arg._prod_elements if isinstance(elem, oofun) and elem.hasStochasticVariables] else: # def ff(x): # # TODO: same changes for std, var,other moments # #print (type(x), multiarray) # r = np.array([mean(xx) for xx in x.view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray) \ # else x if not isinstance(x, stochasticDistribution) else x.Mean # #if type(x) == np.ndarray: ## print ('!', x, r.shape) # return r r = oofun(f_mean, arg, engine = 'mean', engine_monotonity = 0, vectorized = True) r.getOrder = arg.getOrder # r = oofun(lambda x: np.array([mean(xx) for xx in (x.reshape(-1, 1) if x.ndim < 2 else x).view(np.ndarray)]).view(multiarray) if isinstance(x, multiarray) \ # else x if not isinstance(x, stochasticDistribution) else x.Mean, arg) # TODO: move _D definition outside of the func def _D(*args, **kw): res = arg._D(*args, **kw) res = dict((key, elem.Mean if isinstance(elem, stochasticDistribution) else elem) for key, elem in res.items()) return res r._D = _D else: r = np.mean(arg, *args, **kw) return r
def integrator(func, domain, **kwargs): if not scipyInstalled: raise FuncDesignerException("to use scipy_integrate_quad you should have scipy installed, see scipy.org") # if not isinstance(domain, dict) or len(domain) != 1: # raise FuncDesignerException('currently integration domain must be of type Pythoon dict {integr_var:(val_from, val_to)} only') # integration_var = domain.keys()[0] # _from, _to = domain.values()[0] integration_var, a, b = domain if not isinstance(integration_var, oovar): raise FuncDesignerException("integration variable must be FuncDesigner oovar") a, b, func = atleast_oofun(a), atleast_oofun(b), atleast_oofun(func) def f(point=None): p2 = point.copy() # if integration_var not in p2: # p2[integration_var] = 0.0 # to ajust size, currently only R^1 is implemented # T = FuncDesignerTranslator(p2) 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") # vect_func = lambda x: func(T.vector2point(x)) # TODO: better handling of fixed variables return integrate.quad(vect_func, a(point), b(point), **kwargs)[0] # def aux_f(point): # point = oopoint(_point) # if a(point).size != b(point).size: raise FuncDesignerException('sizes of point-from and point-to must be equal') # if a(point).size != 1 or b(point).size != 1: raise FuncDesignerException('currently integration is implemented for single variable only') # dep = a._getDep() | b._getDep() | func._getDep() # involved_vars = set(point.keys()).add(integration_var) # if not dep.issubset(involved_vars): raise FuncDesignerException('user-provided point for integration has no information on some variables') # # p2 = point.copy() # if integration_var not in p2: # p2[integration_var] = 0.0 # to ajust size, currently only R^1 is implemented # T = FuncDesignerTranslator(p2) # vect_func = lambda x: func(T.vector2point(x)) # TODO: derivatives # !!!!!!!!!!!!! TODO: derivatives should not be zeros! Fix it! r = oofun(f, None) r.fun = lambda *args: f(point=r._Point) # TODO : use decorators here tmp_f = r._getFunc tmp_D = r._D def aux_f(*args, **kwargs): if isinstance(args[0], dict): r._Point = args[0] return tmp_f(*args, **kwargs) def aux_D(*args, **kwargs): raise FuncDesignerException("derivatives from scipy_quad are not implemented yet") if isinstance(args[0], dict): r._Point = args[0] return tmp_D(*args, **kwargs) r._getFunc = aux_f r._D = aux_D return r
def integrator(func, domain, **kwargs): if not scipyInstalled: raise FuncDesignerException( 'to use scipy_integrate_quad you should have scipy installed, see scipy.org' ) # if not isinstance(domain, dict) or len(domain) != 1: # raise FuncDesignerException('currently integration domain must be of type Pythoon dict {integr_var:(val_from, val_to)} only') #integration_var = domain.keys()[0] #_from, _to = domain.values()[0] integration_var, a, b = domain if not isinstance(integration_var, oovar): raise FuncDesignerException( 'integration variable must be FuncDesigner oovar') a, b, func = atleast_oofun(a), atleast_oofun(b), atleast_oofun(func) def f(point=None): p2 = point.copy() #if integration_var not in p2: #p2[integration_var] = 0.0 # to ajust size, currently only R^1 is implemented #T = FuncDesignerTranslator(p2) 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') #vect_func = lambda x: func(T.vector2point(x)) # TODO: better handling of fixed variables return integrate.quad(vect_func, a(point), b(point), **kwargs)[0] # def aux_f(point): # point = oopoint(_point) # if a(point).size != b(point).size: raise FuncDesignerException('sizes of point-from and point-to must be equal') # if a(point).size != 1 or b(point).size != 1: raise FuncDesignerException('currently integration is implemented for single variable only') # dep = a._getDep() | b._getDep() | func._getDep() # involved_vars = set(point.keys()).add(integration_var) # if not dep.issubset(involved_vars): raise FuncDesignerException('user-provided point for integration has no information on some variables') # # p2 = point.copy() # if integration_var not in p2: # p2[integration_var] = 0.0 # to ajust size, currently only R^1 is implemented # T = FuncDesignerTranslator(p2) # vect_func = lambda x: func(T.vector2point(x)) # TODO: derivatives # !!!!!!!!!!!!! TODO: derivatives should not be zeros! Fix it! r = oofun(f, None) r.fun = lambda *args: f(point=r._Point) # TODO : use decorators here tmp_f = r._getFunc tmp_D = r._D def aux_f(*args, **kwargs): if isinstance(args[0], dict): r._Point = args[0] return tmp_f(*args, **kwargs) def aux_D(*args, **kwargs): raise FuncDesignerException( 'derivatives from scipy_quad are not implemented yet') if isinstance(args[0], dict): r._Point = args[0] return tmp_D(*args, **kwargs) r._getFunc = aux_f r._D = aux_D return r
def hstack(tup): # overload for oofun[ind] c = [isinstance(t, (oofun, ooarray)) for t in tup] if any([isinstance(t, ooarray) for t in tup]): return ooarray(np.hstack(tup)) if not any(c): return np.hstack(tup) #an_oofun_ind = np.where(c)[0][0] f = lambda *x: np.hstack(x) # def d(*x): # # r = [elem.d(x[i]) if c[i] else None for i, elem in enumerate(tup)] # size = atleast_1d(r[an_oofun_ind]).shape[0] # r2 = [elem if c[i] else Zeros(size) for elem in r] # return r2 #= lambda *x: np.hstack([elem.d(x) if c[i] else elem for elem in tup]) # f = lambda x: x[ind] # def d(x): # Xsize = Len(x) # condBigMatrix = Xsize > 100 # if condBigMatrix and scipyInstalled: # r = SparseMatrixConstructor((1, x.shape[0])) # r[0, ind] = 1.0 # else: # if condBigMatrix and not scipyInstalled: self.pWarn(scipyAbsentMsg) # r = zeros_like(x) # r[ind] = 1 # return r def getOrder(*args, **kwargs): orders = [0]+[inp.getOrder(*args, **kwargs) for inp in tup] return np.max(orders) r = oofun(f, tup, getOrder = getOrder) #!!!!!!!!!!!!!!!!! TODO: sparse def _D(*args, **kwargs): # TODO: rework it, especially if sizes are fixed and known # TODO: get rid of fixedVarsScheduleID sizes = [(t(args[0], fixedVarsScheduleID = kwargs.get('fixedVarsScheduleID', -1)) if c[i] else np.asarray(t)).size for i, t in enumerate(tup)] tmp = [elem._D(*args, **kwargs) if c[i] else None for i, elem in enumerate(tup)] res = {} for v in r._getDep(): Temp = [] for i, t in enumerate(tup): if c[i]: temp = tmp[i].get(v, None) if temp is not None: Temp.append(temp if type(temp) != DiagonalType else temp.resolve(kwargs['useSparse'])) else: # T = next(iter(tmp[i].values())) # sz = T.shape[0] if type(T) == DiagonalType else np.atleast_1d(T).shape[0] Temp.append((Zeros if sizes[i] * np.asarray(args[0][v]).size > 1000 else np.zeros)((sizes[i], np.asarray(args[0][v]).size))) else: sz = np.atleast_1d(t).shape[0] Temp.append(Zeros((sz, 1)) if sz > 100 else np.zeros(sz)) rr = Vstack([elem for elem in Temp]) #print type(rr) res[v] = rr if not isspmatrix(rr) or 0.3 * prod(rr.shape) > rr.size else rr.toarray() #print type(res[v]) return res r._D = _D return r