在Python中计算复杂数学方程
有没有什么库或者方法可以简化计算方程式的过程呢?
下面有两个例子:
F = B * { [ a * b * sumOf (A / B ''' 对于所有 i ''' ) ] / [ sumOf(c * d * j) ] }
这里:
F = 从 i 到 j 的费用
B、a、b、c、d、j 都是以这种格式表示的向量:[ [zone_i, zone_j, cost_of_i_to_j], [..]]
这个公式应该会生成一个向量 F [ [1,2, F_1_2], ..., [i,j, F_i_j] ]
T_ij = [ P_i * A_i * F_i_j] / [ SumOf [ Aj * F_i_j ] // j = 1 到 j = n ]
这里:
n 是区域的数量
T = 向量 [ [1, 2, A_1_2, P_1_2], ..., [i, j, A_i_j, P_i_j] ]
F = 向量 [1, 2, F_1_2], ..., [i, j, F_i_j]
所以 P_i 是所有 P_i_j 的总和,而 Aj 是所有 P_j 的总和
我不太确定自己在找什么,也许是一个解析这些方程式的工具,或者是处理向量之间多重乘法和乘积的方法?
为了计算一些因素,比如 A_j,我用的是这个:
from collections import defaultdict
A_j_dict = defaultdict(float)
for A_item in TG: A_j_dict[A_item[1]] += A_item[3]
虽然这个方法可以正常工作,但我觉得这有点像是强行破解的方法,如果我们想添加更多的变量或参数,这样的方式就不太好维护了。你有什么推荐的数学方程解析器吗?
附注:这些方程是用来模拟旅行的。目前我用 Excel 来解决很多这些方程,但我觉得这个过程很繁琐。我更想转到 Python,这样可以直接从我们的数据库(postgres)中提取数据,并把结果输出到数据库里。这个部分我已经搞定了。现在我只是对如何评估这些方程感到困惑。
谢谢 :)
3 个回答
顺便提一下,有几个数学模块,比如nzmath和mpmath,它们的功能可比你想象的要多得多。
LL
这种任务的常见解决方案是使用 [NumPy][1]。
你的方程看起来和向量、矩阵方程很相似,所以使用 NumPy 的数组和矩阵会非常有帮助。
这里有一个基于你需求的例子:
T_ij = [ P_i * A_i * F_i_j] / [ SumOf [ Aj * F_i_j ] // j 从 1 到 n ]
其中: n 是区域的数量
T = 向量 [ [1, 2, A_1_2, P_1_2], ..., [i, j, A_i_j, P_i_j] ]
F = 向量 [1, 2, F_1_2], ..., [i, j, F_i_j]
所以 P_i 是所有 P_i_j 的总和,Aj 是所有 P_j 的总和
这可以通过以下方式计算:
import numpy as np
A = np.array([…]); P = np.array(…) # Vectors (1D arrays)
F = np.array([[…], […],…]) # 2D array
T = (P*A*F.T).T/np.dot(F, A)
你会看到最终结果以相当简洁的形式表达,这要归功于 NumPy。NumPy 的数组计算也非常快速。
你想要实现的目标其实非常适合用 NumPy 来完成。如果你准备好学习这个工具,我建议你去看看 [Numpy 教程][1]。
[1]: https://numpy.org/devdocs/user/quickstart.html要对两个维度相同的NumPy数组进行逐元素相乘,只需要用'A * B'。
In [1]: a = arange(50)
In [2]: b = ones(50) * 2
In [3]: a
Out[3]:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49])
In [4]: b
Out[4]:
array([ 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,
2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,
2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,
2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.])
In [5]: a * b
Out[5]:
array([ 0., 2., 4., 6., 8., 10., 12., 14., 16., 18., 20.,
22., 24., 26., 28., 30., 32., 34., 36., 38., 40., 42.,
44., 46., 48., 50., 52., 54., 56., 58., 60., 62., 64.,
66., 68., 70., 72., 74., 76., 78., 80., 82., 84., 86.,
88., 90., 92., 94., 96., 98.])
In [6]: (a * b).sum()
Out[6]: 2450.0
如果你能把事情用矩阵乘法的方式来写,就可以使用dot()
这个函数:
In [7]: A = arange(25).reshape((5,5))
In [8]: X = arange(5)
In [9]: A
Out[9]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]])
In [12]: dot(A, X) # Sum_j A[i,j] * X[j] for all i
Out[12]: array([ 30, 80, 130, 180, 230])
这应该能帮助你入门。