当系数未知(但仍然是实数)时如何求解 Python 中的线性方程组

How to solve a Linear System of Equations in Python When the Coefficients are Unknown (but still real numbers)

我不是程序员所以请放轻松!我有一个由 4 个线性方程和 4 个未知数组成的系统,我想我可以使用 python 来相对轻松地求解。然而,我的方程式不是“ 5x+2y+z-w=0 ”的形式,而是我有代数常数 c_i ,我不知道它的明确数值,例如“ c_1 x + c_2 y + c_3 z+ c_4w=c_5 " 将是我的四个方程之一。那么是否存在根据 c_i 给出 x,y,z,w 答案的求解器?

Numpy 有一个函数可以解决这个问题:numpy.linalg.solve

要构造矩阵,我们首先需要消化字符串,将其转化为系数和解的数组。

查找数字

首先我们需要编写一个函数,它接受一个字符串,如“c_1 3”和 returns 数字 3.0。根据您在输入字符串中所需的格式,您可以遍历此数组中的所有字符并在找到非数字字符时停止,或者您可以简单地拆分 space 并解析第二个字符串。以下是两种解决方案:

def find_number(sub_expr):

    """
    Finds the number from the format
    number*string or numberstring.

    Example:
    3x -> 3
    4*x -> 4
    """

    num_str = str()

    for char in sub_expr:
        if char.isdigit():
            num_str += char
        else:
            break

    return float(num_str)

或更简单的解决方案

def find_number(sub_expr):
    """
    Returns the number from the format "string number"
    """
    return float(sub_expr.split()[1])

Note: See edits

获取矩阵

现在我们可以用它把每个表达式分成两部分:解和用“=”表示的方程。然后等式被“+”拆分为sub_expressions 这样我们最终将字符串“3x+4y = 3”变成

sub_expressions = ["3x", "4y"]
solution_string = "3"

然后每个子表达式都需要输入到我们的 find_numbers 函数中。最终结果可以附加到系数和解矩阵:

def get_matrices(expressions):

    """
    Returns coefficient_matrix and solutions from array of string-expressions.
    """

    coefficient_matrix = list()
    solutions = list()

    last_len = -1

    for expression in expressions:

        # Note: In this solution all coefficients must be explicitely noted and must always be in the same order.
        # Could be solved with dicts but is probably overengineered.

        if not "=" in expression:
            print(f"Invalid expression {expression}. Missing \"=\"")
            return False

        try:
            c_string, s_string = expression.split("=")

            c_strings = c_string.split("+")
            solutions.append(float(s_string))

            current_len = len(c_strings)

            if last_len != -1 and current_len != last_len:
                print(f"The expression {expression} has a mismatching number of coefficients")
                return False

            last_len = current_len

            coefficients = list()

            for c_string in c_strings:
                coefficients.append(find_number(c_string))

            coefficient_matrix.append(coefficients)


        except Exception as e:
            print(f"An unexpected Runtime Error occured at {coefficient}")
            print(e)
            exit()

    return coefficient_matrix, solutions

现在让我们编写一个简单的主函数来测试这段代码:

# This is not the code you want to copy-paste
# Look further down.
from sys import argv as args

def main():
    expressions = args[1:]

    matrix, solutions = get_matrices(expressions)

    for row in matrix:
        print(row)

    print("")
    print(solutions)

if __name__ == "__main__":
    main()

让我们运行控制台中的程序!

user:$ python3 solve.py 2x+3y=4 3x+3y=2
[2.0, 3.0]
[3.0, 3.0]

[4.0, 2.0]

您可以看到程序正确识别了我们所有的号码

AGAIN: use the find_number function appropriate for your format

拼凑

现在只需将这些矩阵直接泵入 numpy 函数即可:

# This is the main you want
from sys import argv as args
from numpy.linalg import solve as solve_linalg

def main():
    expressions = args[1:]

    matrix, solutions = get_matrices(expressions)

    coefficients = solve_linalg(matrix, solutions)

    print(coefficients)

# This bit needs to be at the very bottom of your code to load all functions first.
# You could just paste the main-code here, but this is considered best-practice
if __name__ == '__main__':
    main()

现在让我们测试一下:

$ python3 solve.py x*2+y*4+z*0=20 x*1+y*1+z*-1=3 x*2+y*2+z*-3=3
[2. 4. 3.]

如您所见,程序现在为我们解决了这些功能。

出于好奇:数学作业?这感觉就像数学作业。

编辑:在所有测试中出现了一个拼写错误“c_string”而不是“c_strings”,这完全是运气。

编辑 2:经过进一步检查,我建议用“*”分隔子表达式:

def find_number(sub_expr):
    """
    Returns the number from the format "string number"
    """
    return float(sub_expr.split("*")[1])

这会产生相当可读的输入字符串