Exemple #1
0
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))
Exemple #2
0
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
Exemple #3
0
    def __init__(self, equations, startPoint, *args, **kwargs):
        if len(args) > 2:  
            raise FuncDesignerException('incorrect ode definition, too many args are obtained')
        
        if not isinstance(equations, dict):
            raise FuncDesignerException('1st argument of ode constructor should be Python dict')

        if not isinstance(startPoint, dict):
            raise FuncDesignerException('2nd argument of ode constructor should be Python dict')
      
        if len(args) == 2:
            print("""
            FuncDesigner warning: you're using obsolete ode() API, 
            now time should be passed as 3rd argument {timeVariable: times}
            or just array of times if equations are time-independend""")
            timeVariable, times = args[0], args[1]
        else:
            if len(args) != 1 or type(args[0]) not in (dict, list, tuple, ndarray):
                raise FuncDesignerException('3rd argument of ode constructor must be dict {timeVariable:array_of_times} or just array_of_times')
            if type(args[0]) == dict:
                if len(args[0]) != 1:
                    raise FuncDesignerException('in time argument dict has to have exactly 1 entry')
                timeVariable, times = list(args[0].items())[0]
                if not isinstance(timeVariable, oovar):
                    raise FuncDesignerException('incorrect time variable, must be FuncDesigner oofun')
            else:
                times = args[0]
                timeVariable = None

        self.timeVariable = timeVariable

        if timeVariable is not None and timeVariable in equations:
            raise FuncDesignerException("ode: differentiation of a variable by itself (time by time) is treated as a potential bug and thus is forbidden")

        if not (isinstance(times, (list, tuple)) or (isinstance(times, ndarray) and times.ndim == 1)): 
            raise FuncDesignerException('incorrect user-defined time argument, must be Python list or numpy array of time values')
        self.times = times
        self._fd_func, self._startPoint, self._timeVariable, self._times, self._kwargs = equations, startPoint, timeVariable, times,  kwargs
        
        startPoint = startPoint.copy()#dict((key, val) for key, val in startPoint.items())
        if timeVariable is not None:
            startPoint[timeVariable] = times[0]
        y0 = []
        Funcs = []
        
        # setting oovar.size is risky - it can affect code written after the ode is solved
        # thus Point4TranslatorAssignment is used instead
        Point4TranslatorAssignment = {}
        
        for v, func in equations.items():
            func = atleast_oofun(func)
#            if not isinstance(func,  oofun):
#                func = fixed_oofun(func)
            if not isinstance(v, oovar):
                raise FuncDesignerException('ode: dict keys must be FuncDesigner oovars, got "%s" instead' % type(v))
            startFVal = asarray(func(startPoint))
            y0.append(asarray(startPoint[v]))
            Funcs.append(func)
            Point4TranslatorAssignment[v] = startFVal
            
            if startFVal.size != asarray(startPoint[v]).size or (hasattr(v, 'size') and isscalar(v.size) and startFVal.size != v.size):
                raise FuncDesignerException('error in user-defined data: oovar "%s" size is not equal to related function value in start point' % v.name)
        
        self.y0 = hstack(y0)
        self.varSizes = [y.size for y in y0]
        ooT = FuncDesignerTranslator(Point4TranslatorAssignment)
        self.ooT = ooT
        def func(y, t): 
            tmp = dict(ooT.vector2point(y))
            if timeVariable is not None:
                tmp[timeVariable] = t
            r = hstack([func(tmp) for func in Funcs])
            return r
        self.func = func
        
        
        _FDVarsID = _getDiffVarsID()
        def derivative(y, t):
#            print('d')
            tmp = dict(ooT.vector2point(y))
            if timeVariable is not None:
                tmp[timeVariable] = t
            r = []
            for func in Funcs:
                tt = func.D(tmp, fixedVarsScheduleID = _FDVarsID)
                if timeVariable is not None:
                    tt.pop(timeVariable, None)
                r.append(ooT.pointDerivative2array(tt))
            return vstack(r)
        self.derivative = derivative
        self.Point4TranslatorAssignment = Point4TranslatorAssignment
Exemple #4
0
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