Sympysolve()给出错误的结果

时间:2019-07-01 11:28:24

标签: python sympy solver

我使用Sympysolve()函数来求解大量方程。方程式中的所有变量均定义为符号。变量可以以字母P或F开头。我使用Solve()仅用F变量表示一个特定的P变量(我观察到的变量),因此我使用Solve()用F变量替换所有其他P变量。 F变量之前的系数总和最好为1或几乎为1(例如:0.99)。

这将产生良好的结果,直到方程式数量及其长度变得相当大的某个点为止。在那里,Sympy resolve()函数开始给我错误的结果。系数的总和为负(例如-7,...)。看来resolve()函数遇到了替换所有结余所有变量及其系数的问题。

是否可以解决此问题?

链接https://drive.google.com/open?id=1VBQucrDU-o1diCd6i4rR3MlRh95qycmK下的方程式字典

    import json
    from sympy import Symbol, Add, Eq, solve


    # Get data

    # data from link above
    with open("C:\\\\Test\\dict.json") as f:
        equations = json.load(f)

    comp =[]
    expressions = []

    for p, equation_components in equations.items():
        p = Symbol(p)
        comp.append(p)
        expression = []
        for name, multiplier in equation_components.items():
            if type(multiplier) == float or type(multiplier) == int: 
                expression.append(Symbol(name) * multiplier)
            else:
                expression.append(Symbol(name) * Symbol(multiplier))
        expressions.append(Eq(p, Add(*expression)))


    # Solution for variable P137807


    print("Solving...")

    # Works for slice :364 !!!!!
    solutions = solve(expressions[:364], comp[:364], simplify=False, rational=False)

    # Gives wrong results for slice :366 and above !!!!!
    # solutions = solve(expressions[:366], comp[:366], simplify=False, rational=False)

    vm_symbol = Symbol("P137807")

    solution_1 = solutions[vm_symbol]

    print("\n")
    print("Solution_1:")
    print(solution_1)
    print("\n")



    #Sum of coefficients

    list_sum = []


    for i in solution_1.args:
        if str(i.args[1]) != "ANaN":
            list_sum.append(i.args[0])
    coeff_sum = sum(list_sum)

    print("Sum:")
    print(coeff_sum)


...

1 个答案:

答案 0 :(得分:0)

我只是想将问题标记为已解决并提供对解决方案的参考。 Please look at numerical instability when solving n=385 linear equations with Float coefficients #17136

对我有用的解决方案是使用以下求解器而不是 Sympy solve() 函数:

def ssolve(eqs, syms):
    """return the solution of linear system of equations
    with symbolic coefficients and a unique solution.

    Examples
    ========

    >>> eqs=[x-1,x+2*y-z-2,x+z+w-6,2*y+z+x-2]
    >>> v=[x,y,z,w]
    >>> ssolve(eqs, v)
    {x: 1, z: 0, w: 5, y: 1/2}
    """
    from sympy.solvers.solveset import linear_coeffs
    v = list(syms)
    N = len(v)
    # convert equations to coefficient dictionaries
    print('checking linearity')
    d = []
    v0 = v + [0]
    for e in [i.rewrite(Add) for i in eqs]:
        co = linear_coeffs(e, *v)
        di = dict([(i, c) for i, c in zip(v0, co) if c or not i])
        d.append(di)
    print('forward solving')
    sol = {}
    impl = {}
    done = False
    while not done:
        # check for those that are done
        more = set([i for i, di in enumerate(d) if len(di) == 2])
        did = 0
        while more:
            di = d[more.pop()]
            c = di.pop(0)
            x = list(di)[0]
            a = di.pop(x)
            K = sol[x] = -c/a
            v.remove(x)
            changed = True
            did += 1
            # update everyone else
            for j, dj in enumerate(d):
                if x not in dj:
                    continue
                dj[0] += dj.pop(x)*K
                if len(dj) == 2:
                    more.add(j)
        if did: print('found',did,'definitions')
        # solve implicitly for the next variable
        dcan = [i for i in d if len(i) > 2]
        if not dcan:
            done = True
        else:
            # take shortest first
            di = next(ordered(dcan, lambda i: len(i)))
            done = False
            x = next(ordered(i for i in di if i))
            c = di.pop(x)
            for k in di:
                di[k] /= -c
            impl[x] = di.copy()
            di.clear()
            v.remove(x)
            # update everyone else
            for j, dj in enumerate(d):
                if x not in dj:
                    continue
                done = False
                c = dj.pop(x)
                for k in impl[x]:
                    dj[k] = dj.get(k, 0) + impl[x][k]*c
    have = set(sol)
    sol[0] = 1
    while N - len(have):
        print(N - len(have), 'to backsub')
        for k in impl:
            if impl[k] and not set(impl[k]) - have - {0}:
                sol[k] = sum(impl[k][vi]*sol[vi] for vi in impl[k])
                impl[k].clear()
                have.add(k)
    sol.pop(0)
    return sol