def __getattr__(self, attr):
     if attr == 'size':
         if 'values' not in self.__dict__:
             raise FuncDesignerException('this distribution is unquantified yet thus it has no size yet')
         self.size = self.values.size
         return self.size
     elif attr == 'values':
         raise FuncDesignerException('this distribution is unquantified yet thus it has no array of possible values yet')
     elif attr == 'probabilities':
         raise FuncDesignerException('this distribution is unquantified yet thus it has no array of probabilities yet')            
     elif attr == 'Mean':
         self.Mean = (self.values * self.probabilities).sum()
         return self.Mean
     elif attr == 'Std':
         self.Std = o.sqrt(self.Var, attachConstraints = False)
         return self.Std
     elif attr == 'Var':
         self.Var = o.abs(o.sum((self.values)**2 * self.probabilities) - self.Mean**2)
         return self.Var
     elif attr == 'cdf':
         self.cdf = cdf(self)
         return self.cdf
     elif attr == 'pdf':
         self.pdf = pdf(self)
         return self.pdf
     elif attr == 'A':
         return self
     elif attr == 'ndim':
         return 1
     elif attr == 'shape':
         return (self.size, )
     else:
         raise AttributeError('incorrect attribute "%s" of FuncDesigner stochastic class' % attr)
Exemple #2
0
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
Exemple #3
0
    def plot(self):
        try:
            import pylab
        except:
            raise FuncDesignerException(
                'to plot you should have matplotlib installed')
        if self.distrib.distribType != 'continuous':
            raise FuncDesignerException(
                'you can use pdf for continuous distribution only')

        # Temporary, to omit same values or very close to zero division effects
        # TODO: rework it
        d2 = self.distrib.reduce(self.distrib.size - 1, inplace=False)
        d2.sort()
        vals, probs = d2.values, d2.probabilities
        cp = np.cumsum(probs)
        d_right = (cp[1:] - cp[:-1]) / (vals[1:] - vals[:-1])
        d = np.hstack((d_right[0], 0.5 * (d_right[1:] + d_right[:-1]),
                       (cp[-1] - cp[-2]) / (vals[-1] - vals[-2])))
        x, y = vals, d
        pylab.plot(x, y)
        x_l, x_u = x[0] - 0.05 * (x[-1] - x[0]), x[-1] + 0.05 * (x[-1] - x[0])
        pylab.xlim(x_l, x_u)
        My, my = np.max(y), np.min(y)
        d_y = My - my
        pylab.ylim(-0.05 * d_y, My + 0.05 * d_y)
        pylab.plot([x_l, x_u], [0, 0], color='g', linewidth=2)
        pylab.title(self._str)
        pylab.grid('on')
        pylab.show()
Exemple #4
0
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
Exemple #5
0
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')
        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)\
        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 __init__(self, _values=None, _probabilities=None, distribType = 'undefined', ppf = None, N = None, quantiles=None, Str = ''):
     Stochastic.__init__(self)
     self.distribType = distribType
     if Str != '':
         self._str = Str
     if ppf is not None:
         assert quantiles is None, 'quantiles in constructor are unimplemented yet'
 
         if N is None:
             self.quantified = False
                #r.__repr__ = lambda self: self._str
             self._yield_quantified = lambda k: stochasticDistribution(ppf(np.arange(1.0, float(k+1)) / (k+2)), [1.0/k]*k, Str = (self._str + ' quantified into %d points' % k), distribType = self.distribType)
             return
         else:
             if quantiles is None:
                 quantiles = np.arange(1, N+1) / float(N+2)
             else:
                 assert len(quantiles) == N, 'lenght of quantiles must be equal to number of points to be created'
             
             values = ppf(quantiles)
             probabilities = np.array([1.0/N]*N)
             self._str = Str + ' quantified into %d points' % N
     else:
         values = _values if type(_values) == np.ndarray else np.asfarray(_values)
         if _probabilities is None:
             raise FuncDesignerException('for assignment with this set of parameters you should provide probabilities as well')
         probabilities = _probabilities if type(_probabilities) == np.ndarray else np.asfarray(_probabilities)
     if np.any(probabilities < -1e-15):
         raise FuncDesignerException('probabilities cannot be negative')
     if values.size != probabilities.size:
         s = '''
         in stochastic distribution constructor lenght of values (got: %d) must be equal to lenght of probabilities (got: %d)
         ''' % (values.size, probabilities.size)
         raise FuncDesignerException(s)
     probabilitiesSum = np.sum(probabilities)
     Diff = np.abs(probabilitiesSum - 1)
     if Diff > 1e-7:
         p_sum_msg = 'probabilities sum differs too much: 1.0 expected, differrence = %e' % Diff
         raise FuncDesignerException(p_sum_msg)
     if Diff > 1e-10:
         # not inplace for more safety
         probabilities = probabilities / probabilitiesSum 
         
     #obj = asanyarray(values).view(self)
     self.values = values.copy()
     self.probabilities = probabilities.copy()
Exemple #9
0
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 plot(self):
     try:
         import pylab
     except:
         raise FuncDesignerException('to plot you should have matplotlib installed')
     self.distrib.sort()
     x, y = self.distrib.values, np.cumsum(self.distrib.probabilities)
     if self.distrib.distribType == 'continuous':
         pylab.plot(x, y)
     elif self.distrib.distribType == 'discrete':
         X = np.hstack((x[0], np.vstack((x, x)).T.flatten(), x[-1]))
         Y = np.hstack((0.0, y[0], np.vstack((y, y)).T.flatten()))
         pylab.plot(X, Y)
     else:
         pylab.scatter(x, y, s=1)
     x_l, x_u = x[0]-0.05*(x[-1]-x[0]), x[-1]+0.05*(x[-1]-x[0])
     pylab.xlim(x_l, x_u)
     pylab.ylim(-0.05, 1.05)
     pylab.plot([x_l, x_u], [0, 0], color='g', linewidth = 2)
     pylab.plot([x_l, x_u], [1, 1], color='g', linewidth = 2)
     pylab.title(self._str)
     pylab.grid('on')
     pylab.show()        
Exemple #12
0
def mergeDistributions(d1, d2, operation):
    #assert isinstance(d1, stochasticDistribution), 'unimplemented yet'
    is_d1_stoch = isinstance(d1, stochasticDistribution)
    is_d2_stoch = isinstance(d2, stochasticDistribution)

    if is_d1_stoch and type(d2) == multiarray:
        #return np.array([mergeDistributions(d1, elem, operation) for elem in np.atleast_1d(d2)]).view(multiarray)
        return np.array([mergeDistributions(d1, elem, operation) for elem in \
                         (d2 if d2.ndim > 1 else d2.reshape(-1, 1)).view(np.ndarray)]).view(multiarray)

    if is_d2_stoch and type(d1) == multiarray:
        #return np.array([mergeDistributions(elem, d2, operation) for elem in np.atleast_1d(d1)]).view(multiarray)
        return np.array([mergeDistributions(elem, d2, operation) for elem in \
                         (d1 if d1.ndim > 1 else d1.reshape(-1, 1)).view(np.ndarray)]).view(multiarray)

    if is_d1_stoch and is_d2_stoch:
        if not hasattr(d1, 'stochDep') or not hasattr(d1, 'stochDep'):
            distrib_err_fcn()

    cond_same_stoch = is_d2_stoch and is_d1_stoch and set(
        d1.stochDep.keys()) == set(d2.stochDep.keys())
    if not is_d1_stoch or not is_d2_stoch or cond_same_stoch:
        if not is_d2_stoch:  # thus d1 is stoch
            d2 = np.asfarray(d2) if operation == operator.truediv \
            or (hasattr(operator, 'div')  and operation == operator.div) and not isinstance(d2, ooarray) else np.asanyarray(d2)
            #assert d2.size == 1, 'unimplemented for size > 1 yet'
            vals2 = d2.reshape(1, -1) if d2.size > 1 else d2
            vals1 = d1.values
            distribType = d1.distribType
        elif not is_d1_stoch:  # thus d2 is stoch
            d1 = np.asfarray(d1) if operation == operator.truediv \
            or (hasattr(operator, 'div')  and operation == operator.div) and not isinstance(d1, ooarray) else np.asanyarray(d1)
            assert d1.size == 1, 'unimplemented for size > 1 yet'
            vals1 = d1.reshape(1, -1) if d1.size > 1 else d1
            vals2 = d2.values
            distribType = d2.distribType
        else:  #cond_same_stoch
            vals1 = d1.values
            vals2 = d2.values
            distribType = d1.distribType if d1.distribType == d2.distribType else 'undefined'

        Vals = operation(vals1, vals2)

        r = stochasticDistribution(
            Vals.flatten(),
            d1.probabilities.copy()
            if is_d1_stoch else d2.probabilities.copy(), distribType)
        if is_d1_stoch and is_d2_stoch:
            r.stochDep = d1.stochDep.copy()
            for key, val in d2.stochDep.items():
                if key in r.stochDep:
                    r.stochDep[key] += val
                else:
                    r.stochDep[key] = val
        elif is_d1_stoch:
            r.stochDep = d1.stochDep.copy()
        else:
            if not is_d2_stoch:
                raise FuncDesignerException('bug in FuncDesigner kernel')
            r.stochDep = d2.stochDep.copy()
        #!!!!!!!!!!!! TODO: getOrder (for linear probs)

    else:

        def f(D1, D2):
            r = operation(
                          D1.reshape(-1, 1),
                          D2 if operation != operator.truediv \
                          or isinstance(D2, (oofun, ooarray)) \
                          or isinstance(D1, (oofun, ooarray))  \
                          else np.asfarray(D2) \
                          ).reshape(1, -1)
            return r

        distribType = d1.distribType if d1.distribType == d2.distribType else 'undefined'
        F = f(d1.values, d2.values)

        New = 1
        if New and np.all(d1.probabilities == d1.probabilities[0]) and np.all(
                d2.probabilities == d2.probabilities[0]):
            Probabilities = np.empty(d1.probabilities.size *
                                     d2.probabilities.size)
            Probabilities.fill(d1.probabilities[0] * d2.probabilities[0])
        else:
            Probabilities = (d1.probabilities.reshape(-1, 1) *
                             d2.probabilities.reshape(1, -1)).flatten()

        r = stochasticDistribution(F.flatten(), Probabilities, distribType)
        '''                                                     adjust stochDep                                                     '''
        if len(set(d1.stochDep.keys()) & set(d2.stochDep.keys())) != 0 and len(
                set(d1.stochDep.keys()) | set(d2.stochDep.keys())) > 1:
            #            print(d1.stochDep.keys())
            #            print(d2.stochDep.keys())
            #            print(set(d1.stochDep.keys()) | set(d2.stochDep.keys()))
            raise FuncDesignerException('''
            This stochastic function has structure that makes it impossible to handle in OpenOpt Suite yet.
            If gradient-based solver is involved, sometimes using derivative-free one instead (e.g. scipy_cobyla, de, bobyqa) can be successful
            ''')
        stochDep = d1.stochDep.copy()
        for key, val in d2.stochDep.items():
            if key in stochDep:
                stochDep[key] += val
            else:
                stochDep[key] = val
        r.stochDep = stochDep

    if is_d1_stoch:
        m1 = getattr(d1, 'maxDistributionSize', 0)
    else:
        m1 = 0
    if is_d2_stoch:
        m2 = getattr(d2, 'maxDistributionSize', 0)
    else:
        m2 = 0
    N = max((m1, m2))
    if N == 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)
    r = r.reduce(N)
    r.maxDistributionSize = N

    if is_d1_stoch and hasattr(d1, '_p'):
        r._p = d1._p
    elif is_d2_stoch and hasattr(d2, '_p'):
        r._p = d2._p


#    if operation == operator.mul:
#        r._is_product = True
#        r._product_elements = [self, other]
    return r
Exemple #13
0
 def engine(self):
     raise FuncDesignerException(
         'virtual method stochFunc.engine has not been overloaded')
Exemple #14
0
 def __xor__(self, other):
     raise FuncDesignerException('For function pow() use a**b, not a^b')