Python: Algebraic List Simplification

Hi, I am trying to get the general conditions of a list in order to simplify it, for example, if I have a list:

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

is there any function that can give me the result:

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

What I basically want to do is algebraic reduction.

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

The only requirement for simplification is that all simplified terms must depend on the sum or remainder of K. In other words, everything should be a function of the linear combination K: [-KcKa + KDKa] ; [KcKaKF] ; [['-1','Kc','Ka'],['+1','KD','Ka']] .

I'm trying to use SymPy, but my problem is that the abbreviations come from other sources, so I never know what the characters will be. To use SymPy, you need to declare characters, right? Any idea on how I can solve this problem?

+6
source share
2 answers

I think you know what algebraic manipulations you want to do, but you hanged on getting the "K" characters from sympy? Sympy is very good at variable names. You can simply build the expression:

 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 

And then get a list of characters:

 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] 

Once you have a list of characters, it is trivial to grab those that start with "K" or not:

 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)) 
+1
source

First of all, convert your list to a SymPy expression:

 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 

Now expr is the SymPy expression you want to work with. If you just want to replace some values, use .subs:

Do not forget to specify the characters that you are going to use:

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

Then you can replace:

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

Otherwise, you can try to define a substitution rule for your variables. For example, put them in a dict:

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

You must replace the dots with a suitable expression containing the new variables. These new variables should represent combinations of your K constants.

For example: c1 = -Kc * Ka + KD * Ka, _c2 = ... _, then you invert these equations.

In your case, it seems that your expressions cannot be inverted correctly:

 >>> 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) [] 
0
source

All Articles