【问题标题】:Python: List algebraic simplificationPython:列表代数化简
【发布时间】:2016-07-03 10:17:26
【问题描述】:

您好,我正在尝试获取列表的常用术语以简化它,例如,如果我拥有的列表是:

List=[['1','A1','B1','Kc','Ka'],['1','A1','B1','D2','Kc','Ka'],
['-1','A1','B1','D1','Kc','Ka'],['1','A1','B1','D1','KD','Ka'],
['-1','B1','D1','C1','Kc','Ka','KF'],['1','B1','D1','F1','Kc','Kz','Kl']]    

有什么功能可以给我结果:

List_output=[['A1', 'B1', [['D1', [['KD', 'Ka'],
['-1', 'Ka', 'Kc']]], ['Ka', 'Kc'], ['D2', 'Ka', 'Kc']]],
['B1', 'D1', [['F1', 'Kc', 'Kl', 'Kz'], ['-1', 'C1', 'KF', 'Ka', 'Kc']]]]

我基本上想做的是代数归约。

(A1 B1 Kc Ka + A1 B1 D2 Kc Ka - A1 B1 D1 Kc Ka + A1 B1 D1 KD Ka -
B1 D1 C1 Kc Ka KF + B1 D1 F1 Kc Kz Kl ) ->
A1B1[D1[-KcKa + KDKa] + D2KcKa +KcKa] + B1D1[-C1[KcKaKF] + F1[KcKzKl]]  

简化的唯一要求是所有简化的项都需要依赖于 K 的总和或其余部分。换句话说,一切都需要是 K 的线性组合的函数:[-KcKa + KDKa][KcKaKF]; [['-1','Kc','Ka'],['+1','KD','Ka']].

我正在尝试使用 SymPy,但我遇到的问题是要减少的术语来自其他地方,所以我永远不知道符号会是什么。要使用 SymPy,您需要声明符号,对吗?知道如何解决这个问题吗?

【问题讨论】:

  • 一个非常有趣的问题。您对解决方案是否有任何要求以某种方式达到最优,或者任何好的简化工作都有效?
  • 您的问题没有唯一的解决方案:子表达式可能以不止一种等价方式被分解。
  • 唯一的要求是所有简化都需要依赖于 K 的总和或其余部分。换句话说,一切都需要是 K 的线性组合的函数
  • @user3671704 请编辑您的问题以包含此要求。
  • 是不是和化学反应速度有关系? (只是猜测)

标签: python list sympy simplify


【解决方案1】:

我想你知道你想要做什么样的代数运算,但是你对从 sympy 中获取“K”符号感到困惑? Sympy 非常擅长猜测变量名。您可以构造表达式:

In [1]: import sympy

In [2]: List=[['1','A1','B1','Kc','Ka'],['1','A1','B1','D2','Kc','Ka'],['-1','A
   ...: 1','B1','D1','Kc','Ka'],['1','A1','B1','D1','KD','Ka'],['-1','B1','D1',
   ...: 'C1','Kc','Ka','KF'],['1','B1','D1','F1','Kc','Kz','Kl']]    

In [3]: expression = sympy.Add(*[sympy.Mul(*[sympy.S(y) for y in x]) for x in L
   ...: ist] )

In [4]: expression
Out[4]: A1*B1*D1*KD*Ka - A1*B1*D1*Ka*Kc + A1*B1*D2*Ka*Kc + A1*B1*Ka*Kc - B1*C1*D1*KF*Ka*Kc + B1*D1*F1*Kc*Kl*Kz

然后得到符号列表:

In [5]: all_symbols = [x for x in expression.atoms() if type(x)==sympy.Symbol]

In [6]: all_symbols
Out[6]: [Kc, B1, KF, A1, Kz, Ka, D1, C1, F1, D2, KD, Kl]

一旦您有了符号列表,就可以轻松获取以“K”开头的符号,或者不要:

In [7]: solvefor = [x for x in all_symbols if str(x)[0]!="K"]

In [8]: solvefor
Out[8]: [B1, A1, D1, C1, F1, D2]

In [9]: sympy.horner(expression, wrt=solvefor)
Out[9]: B1*(A1*(D1*(KD*Ka - Ka*Kc) + D2*Ka*Kc + Ka*Kc) + D1*(-C1*KF*Ka*Kc + F1*Kc*Kl*Kz))

【讨论】:

    【解决方案2】:

    首先,将您的列表转换为 SymPy 表达式:

    In [1]: List=[['1','A1','B1','Kc','Ka'],['1','A1','B1','D2','Kc','Ka'],['-1','A1','B1','D1','Kc','Ka'],['1','A1','B1','D1','KD','Ka'],['-1','B1','D1','C1','Kc','Ka','KF'],['1','B1','D1','F1','Kc','Kz','Kl']]
    
    In [2]: list_add_mul = sympify(List)
    
    In [4]: expr = Add(*map(lambda x: Mul(*x), list_add_mul))
    
    In [5]: expr
    Out[5]: 
    A₁⋅B₁⋅D₁⋅KD⋅Ka - A₁⋅B₁⋅D₁⋅Ka⋅Kc + A₁⋅B₁⋅D₂⋅Ka⋅Kc + A₁⋅B₁⋅Ka⋅Kc - B₁⋅C₁⋅D₁⋅KF⋅K
    a⋅Kc + B₁⋅D₁⋅F₁⋅Kc⋅Kl⋅Kz
    

    现在 expr 是您要使用的 SymPy 表达式。如果你只是想替换一些值,使用 .subs:

    记得定义你要使用的符号:

    >>> var("Ka, Kc, Kz")
    

    然后你可以替换:

    In [6]: expr.subs({Ka: 25.0, Kc: 7.0, Kz: 3.5})
    Out[6]: 
    25.0⋅A₁⋅B₁⋅D₁⋅KD - 175.0⋅A₁⋅B₁⋅D₁ + 175.0⋅A₁⋅B₁⋅D₂ + 175.0⋅A₁⋅B₁ - 175.0⋅B₁⋅C₁
    ⋅D₁⋅KF + 24.5⋅B₁⋅D₁⋅F₁⋅Kl
    

    否则,您可以尝试为变量定义替换规则。例如,将它们放在 dict 中:

    {
        Ka: ... ,
        Kc: ... ,
        KD: ... ,
        KF: ... ,
    }
    

    您应该将 dots 替换为包含新变量的合适表达式。这些新变量应该代表您的 K 常量的组合。

    例如:c1 = -Kc*Ka + KD*Ka, _c2 = ... _ 那么你将这些等式取反。

    在您的情况下,您的表达式似乎无法正确反转:

    >>> solve([Eq(-Kc*Ka + KD*Ka, c1 ), Eq(Kc*Ka*KF, c2), Eq(-Kc*Ka + KD*Ka, c3), Eq(Kc*Ka*KF, c4)], Ka, Kc, KD, KF)
    []
    

    【讨论】:

    • 我做了所有的步骤,但是当我尝试 expr.subs({Ka: 25.0, Kc: 7.0, Kz: 3.5}) 命令时,我得到了:name 'Ka' is not defined
    • 您需要定义所有要使用的变量。我已经更新了答案。
    猜你喜欢
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-17
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多