簡體   English   中英

Sympy solve() 給出錯誤的結果

[英]Sympy solve() gives wrong results

我使用 Sympy solve() 函數來求解大量方程。 方程中的所有變量都定義為符號。 變量可以以字母 P 或 F 開頭。我使用 solve() 來表示一個特定的 P 變量(我觀察到的那個)只有 F 變量,所以我使用 solve() 用 F 變量替換所有其他 P 變量。 F 變量之前的系數之和理想情況下為 1 或幾乎為 1(例如:0.99)。

這會產生良好的結果,直到方程的數量變得非常大並且它們的長度變得非常大。 Sympy solve() 函數開始給我錯誤的結果。 系數的總和變為負數(例如 -7,...)。 看起來 solve() 函數在替換所有變量及其系數的任何結轉時遇到問題。

有沒有辦法糾正這個問題?

鏈接下的方程字典: 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)


...

我只是想將問題標記為已解決並提供對解決方案的參考。 在求解具有浮點系數的 n=385 線性方程時,請注意數值不穩定性 #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 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM