【问题标题】:How to solve a Linear System of Equations in Python When the Coefficients are Unknown (but still real numbers)当系数未知(但仍然是实数)时,如何在 Python 中求解线性方程组
【发布时间】:2021-02-04 17:12:25
【问题描述】:

我不是程序员,所以请放轻松!我有一个由 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 答案的求解器?

【问题讨论】:

  • 我建议你看看sympynumpy。即使您在列表中有系数,逻辑也将保持不变。
  • @Pygirl 哦,真的吗?生病检查一下,然后谢谢。
  • 您想找到 c_i 值作为 x,y,z 的函数吗?
  • @Filipe sympy 工作得很好,谢谢 :) 干杯老兄!

标签: python linear-algebra equation solver equation-solving


【解决方案1】:

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

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

寻找数字

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

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])

注意:查看编辑

获取矩阵

现在我们可以使用它将每个表达式分成两部分:解决方案和由“=”组成的方程。然后等式被“+”分割成子表达式,这样我们就可以把字符串“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

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

# 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]

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

再次:使用适合您格式的 find_number 函数

把碎片放在一起

这些矩阵现在只需要直接输入到 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])

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    • 2022-06-10
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    相关资源
    最近更新 更多