예제 #1
0
파일: eval_formula.py 프로젝트: xiaohr/dolo
def eval_formula(expr: str, dataframe=None, context=None):
    '''
    expr: string
        Symbolic expression to evaluate.
        Example: `k(1)-delta*k(0)-i`
    table: (optional) pandas dataframe
        Each column is a time series, which can be indexed with dolo notations.
    context: dict or CalibrationDict
    '''

    print("Evaluating: {}".format(expr))
    if context is None:
        dd = {}  # context dictionary
    elif isinstance(context, CalibrationDict):
        dd = context.flat.copy()
    else:
        dd = context.copy()

    # compat since normalize form for parameters doesn't match calib dict.
    for k in [*dd.keys()]:
        dd[stringify_symbol(k)] = dd[k]

    expr_ast = parse_string(expr).value
    variables = list_variables(expr_ast)
    nexpr = stringify(expr_ast)
    print(expr)
    print(variables)

    dd['log'] = log
    dd['exp'] = exp

    if dataframe is not None:

        import pandas as pd
        for (k, t) in variables:
            dd[stringify_symbol((k, t))] = dataframe[k].shift(t)
        dd['t'] = pd.Series(dataframe.index, index=dataframe.index)

    expr = to_source(nexpr)
    print(expr)
    print(dd.keys())
    res = eval(expr, dd)

    return res
예제 #2
0
def make_method(equations,
                arguments,
                constants,
                targets=None,
                rhs_only=False,
                definitions={},
                funname='anonymous'):

    compat = lambda s: s.replace("^", "**").replace('==', '=').replace(
        '=', '==')
    equations = [compat(eq) for eq in equations]

    if isinstance(arguments, list):
        arguments = OrderedDict([('arg_{}'.format(i), k)
                                 for i, k in enumerate(arguments)])

    ## replace = by ==
    known_variables = [a[0] for a in sum(arguments.values(), [])]
    known_definitions = [a for a in definitions.keys()]
    known_constants = [a[0] for a in constants]
    all_variables = known_variables + known_definitions
    known_functions = []
    known_constants = []

    if targets is not None:
        all_variables.extend([o[0] for o in targets])
        targets = [stringify(o) for o in targets]
    else:
        targets = ['_out_{}'.format(n) for n in range(len(equations))]

    all_symbols = all_variables  # + known_constants

    equations = [parse(eq) for eq in equations]
    definitions = {k: parse(v) for k, v in definitions.items()}

    defs_incidence = {}
    for sym, val in definitions.items():
        lvars = list_variables(val, vars=known_definitions)
        defs_incidence[(sym,
                        0)] = [v for v in lvars if v[0] in known_definitions]
    # return defs_incidence

    equations_incidence = {}
    to_be_defined = set([])
    for i, eq in enumerate(equations):
        cn = CountNames(all_variables, known_functions, known_constants)
        cn.visit(eq)
        equations_incidence[i] = cn.variables
        to_be_defined = to_be_defined.union(
            [a for a in cn.variables if a[0] in known_definitions])

    deps = []
    for tv in to_be_defined:
        ndeps = get_deps(defs_incidence, tv)
        deps.extend(ndeps)
    deps = [d for d in unique(deps)]

    new_definitions = OrderedDict()
    for k in deps:
        val = definitions[k[0]]
        nval = time_shift(val, k[1], all_variables)
        new_definitions[stringify(k)] = normalize(nval, variables=all_symbols)

    new_equations = []

    for n, eq in enumerate(equations):
        d = match(parse("_x == _y"), eq)
        if d is not False:
            lhs = d['_x']
            rhs = d['_y']
            if rhs_only:
                val = rhs
            else:
                val = ast.BinOp(left=rhs, op=Sub(), right=lhs)
        else:
            val = eq
        new_equations.append(normalize(val, variables=all_symbols))

    # preambleIndex(Num(x))
    preamble = []
    for i, (arg_group_name, arg_group) in enumerate(arguments.items()):
        for pos, t in enumerate(arg_group):
            sym = stringify(t)
            rhs = Subscript(value=Name(id=arg_group_name, ctx=Load()),
                            slice=Index(Num(pos)),
                            ctx=Load())
            val = Assign(targets=[Name(id=sym, ctx=Store())], value=rhs)
            preamble.append(val)

    for pos, p in enumerate(constants):
        sym = stringify(p)
        rhs = Subscript(value=Name(id='p', ctx=Load()),
                        slice=Index(Num(pos)),
                        ctx=Load())
        val = Assign(targets=[Name(id=sym, ctx=Store())], value=rhs)
        preamble.append(val)

    # now construct the function per se
    body = []
    for k, v in new_definitions.items():
        line = Assign(targets=[Name(id=k, ctx=Store())], value=v)
        body.append(line)

    for n, neq in enumerate(new_equations):
        line = Assign(targets=[Name(id=targets[n], ctx=Store())],
                      value=new_equations[n])
        body.append(line)

    for n, neq in enumerate(new_equations):
        line = Assign(targets=[
            Subscript(value=Name(id='out', ctx=Load()),
                      slice=Index(Num(n)),
                      ctx=Store())
        ],
                      value=Name(id=targets[n], ctx=Load()))
        body.append(line)

    from ast import arg, FunctionDef, Module
    from ast import arguments as ast_arguments

    f = FunctionDef(
        name=funname,
        args=ast_arguments(args=[arg(arg=a) for a in arguments.keys()] +
                           [arg(arg='p'), arg(arg='out')],
                           vararg=None,
                           kwarg=None,
                           kwonlyargs=[],
                           kw_defaults=[],
                           defaults=[]),
        body=preamble + body,
        decorator_list=[])

    mod = Module(body=[f])
    mod = ast.fix_missing_locations(mod)
    return mod
def test_list_variables():
    from dolang.symbolic import parse_string
    e = parse_string('sin(a(1)+b+f(1)+f(+4)+sin(a)+k*cos(a(0)))')
    list_variables(e)
    assert (list_variables(e) == [('a', 1), ('f', 1), ('f', 4), ('a', 0)])
    assert (list_variables(e, funs=['f']) == [('a', 1), ('a', 0)])
예제 #4
0
def test_list_variables():
    from dolang.symbolic import parse_string

    e = parse_string("sin(a(1)+b+f(1)+f(4)+sin(a)+k*cos(a(0)))")
    list_variables(e)
    assert list_variables(e) == [("a", 1), ("f", 1), ("f", 4), ("a", 0)]