【问题标题】:How to solve multivariate equation systems programmatically?如何以编程方式求解多元方程组?
【发布时间】:2017-01-04 10:34:49
【问题描述】:

我正在尝试求解一个多元方程系统,这是一些 Java 代码的结果。在运行之前,无论是形式还是变量的数量都是未知的。一个例子是

(I) (e-a*d*e-b*d*e+2*b*d*f+2*b*d*e*g)/(-1+a*d+b*d)+f == 0

(II) e*g+((f+e*g)*a*d)/(-1+a*d+b*d)==0

(III) -e*h+((-f-e*g)*d)/(-1+a*d+b*d)==0

(IV) -e*j+((-f-e*g)*c)/(-1+a*d+b*d)==0

我尝试使用Symja,它只返回输入,而SymPy,它抛出一个错误

ZeroDivisionError: polynomial division

变量都来自区间[0,1],我需要所有的解决方案。 Mathematica 能够解决这个问题,但由于它是商业软件,我很遗憾不能在这个项目中使用它。

如果您有任何关于使用哪种软件的建议,我将不胜感激。我真的希望 SymPy 能够正常工作,但我不明白为什么它会抛出这个错误,我很感激你的想法。下面是 SymPy 错误的 MWE:

from sympy.solvers import solve
from sympy.abc import a,b,c,d,e,f,g,h,j

lst = a,b,c,d,e,f,g,h,j
sys = [(e-a*d*e-b*d*e+2*b*d*f+2*b*d*e*g)/(-1+a*d+b*d)+f,e*g+((f+e*g)*a*d)/(-1+a*d+b*d),-e*h+((-f-e*g)*d)/(-1+a*d+b*d),-e*j+((-f-e*g)*c)/(-1+a*d+b*d)]

solution = solve(sys, lst)
print solution

Mathematica 版本是:

eqn = {(e - a*d*e - b*d*e + 2*b*d*f + 2*b*d*e*g)/(-1 + a*d + b*d) + f == 0, e*g + ((f + e*g)*a*d)/(-1 + a*d + b*d) == 0, -e*h + ((-f - e*g)*d)/(-1 + a*d + b*d) == 0, -e*j + ((-f - e*g)*c)/(-1 + a*d + b*d) == 0};
Simplify[Solve[eqn, {a, b, c, d, e, f, g, h, j}]]

输出:

{{e -> 0, f -> 0},
{c -> (1 - 2 a d - 3 b d) j, f -> ((-1 + 2 a d + b d) e)/(-1 + 2 a d + 3 b d), g -> (a d)/(1 - 2 a d - 3 b d), h -> d/(1 - 2 a d - 3 b d)},
{a -> 0, c -> j - 3 b d j, f -> ((-1 + b d) e)/(-1 + 3 b d), g -> 0, h -> d/(1 - 3 b d)},
{a -> (1 - b d)/(2 d), c -> -2 b d j, f -> 0, g -> 1/4 - 1/(4 b d), h -> -(1/(2 b))}}

【问题讨论】:

  • 能贴出 Mathematica 表达式和解法吗?
  • 您是否尝试过乘以公分母?我猜这些工具提供了自动化的方法,但您可以手动操作,看看它们是否能解决结果。
  • @agentp 是的,我试过了,但没有帮助,SymPy 仍然抛出同样的错误

标签: java wolfram-mathematica sympy equation-solving symja


【解决方案1】:

请注意,您有 9 个变量和 4 个方程。因此,您可以消除四个变量——您需要告诉 Sympy 哪个。

以下代码首先将分母相乘,然后将a,b,c,d 消除:

import sympy as sy
from IPython.display import display  # for pretty printing

# sy.init_printing()  # LaTeX-like pretty printing for IPython

a, b, c, d, e, f, g, h, j = sy.symbols("a, b, c, d, e, f, g, h, j", real=True)
lst = a, b, c, d, e, f, g, h, j
sys0 = sy.Matrix([(e-a*d*e-b*d*e+2*b*d*f+2*b*d*e*g)/(-1+a*d+b*d)+f,
                  e*g+((f+e*g)*a*d)/(-1+a*d+b*d),
                  -e*h+((-f-e*g)*d)/(-1+a*d+b*d),
                  -e*j+((-f-e*g)*c)/(-1+a*d+b*d)])

# Denominator can be factored out:
den = a*d + b*d - 1
sys1 = sy.simplify(sys0*den).expand()
print("Factored out denominator:")
display(sys1)

# Elimnate four variables:
sol1 = sy.solve(sys1, a, b, c, d, dict=True)
print("Solutions:")
display(sol1)
print("Substituting back into the equation gives obviously 0, i.e.:")
display(sy.simplify(sys1.subs(sol1[0])).T)

print("The denominator != 0 results in:")
den1 = sy.simplify(den.subs(sol1[0]))
display(sy.solve(den1))

生成以下输出:

Factored out denominator:
Matrix([
[-a*d*e + a*d*f + 2*b*d*e*g - b*d*e + 3*b*d*f + e - f],
[                   2*a*d*e*g + a*d*f + b*d*e*g - e*g],
[              -a*d*e*h - b*d*e*h - d*e*g - d*f + e*h],
[              -a*d*e*j - b*d*e*j - c*e*g - c*f + e*j]])
Solutions:
[{d: 2*e*h/(4*e*g - e + 3*f),
  c: 2*e*j/(4*e*g - e + 3*f),
  a: g/h,
  b: (-e + f)/(2*e*h)}]
Substituting back into the equation gives obviously 0, i.e.:
Matrix([[0, 0, 0, 0]])
The denominator != 0 results in:
[{e: -f/g}]

所以得到的身份是:

-f/g != e  # denominator - only false, if f,e=0 since f,g,e>=0
a = g/h
b = (-e + f)/(2*e*h)
c = 2*e*j/(4*e*g - e + 3*f)
d = 2*e*h/(4*e*g - e + 3*f)

据我所知,Sympy 还不能处理多元不等式(尽管我希望被证明是错误的)。但是结果很简单,可以手动完成:

 0 <= g <= h
 0 <= f-e <= 2*e*h
 0 <= 2*e*j <= 4*e*g - e + 3*f
 0 <= 2*e*h <= 4*e*g - e + 3*f
 0 <= e,f,g,h,j <= 1

f,e=0 的情况同样有效。可以通过检查sys0.subs(e,0).diff(f)不依赖f来验证。

【讨论】:

  • 非常好的方法。
  • 对于这个特定的系统来说,这确实是一个不错的方法。不幸的是,方程的结构在运行前是未知的。这意味着所有具有公分母的方程的这种情况是一种伪影,在其他情况下可能会有所不同。因此,我看不出如何将此解决方案扩展为以编程方式工作。
  • @berndibus 如果您对方程的结构一无所知或知之甚少,根据我的经验,这种方法是有问题的(尤其是对于极端情况)。在 Mathematica(以及 Sympy)中,我通常会等待半小时或更长时间,以查看 Solve[] 是否提出了有效的解决方案。请注意,Mathematica 并未在您的示例中提供 all 解决方案 - Reduce[] 会更合适。如果您确定,您的方程表现良好,您 80% 的解决方案可能是像我在解决方案中所做的那样消除前四个变量。
【解决方案2】:

如果这个问题被关闭,这里是 Mathematica 版本的尝试。然而,它目前缺乏将变量限制在区间 [0,1] 内的条件。

Solve[{
  (e - a d e - b d e + 2 b d f + 2 b d e g)/(-1 + a d + b d) + f == 0,
   e g + ((f + e g) a d)/(-1 + a d + b d) == 0,
  -e h + ((-f - e g) d)/(-1 + a d + b d) == 0,
  -e j + ((-f - e g) c)/(-1 + a d + b d) == 0
  },
 {a, b, c, d, e, f, g, h, j}]

【讨论】:

  • 我已将 Mathematica 版本添加到我的问题中,但我无法使用 Mathematica 解决我的问题,因为它是商业软件。
  • 您没有添加任何将变量限制在区间 [0,1] 内的条件,因此猜测这与您对 SymPy(或其他软件)的要求无关。
  • 这很好,但我认为可以在第二步中限制它,主要任务是解决问题。如果可以直接做就更好了。
【解决方案3】:

好的,我能够使用 SAGE 自己解决问题,并提供与 Mathematica 相同的输出。

sage: a,b,c,d,e,f,g,h,j = var('a,b,c,d,e,f,g,h,j')
sage: qe = [(e-a*d*e-b*d*e+2*b*d*f+2*b*d*e*g)+f*(-1+a*d+b*d),e*g*(-1+a*d+b*d)+((f+e*g)*a*d),-e*h*(-1+a*d+b*d)+((-f-e*g)*d),-e*j*(-1+a*d+b*d)+((-f-e*g)*c)]
sage: print(solve(qe,a,b,c,d,e,f,g,h,j, solution_dict=True))

给出输出

[{g: r5, j: r7, b: r2, d: r4, e: 0, h: r6, c: r3, f: 0, a: r1},
{g: r12, j: r14, b: r8, d: r10, e: r11, h: r13, c: r9, f: -r11*r12, a: -(r10*r8 - 1)/r10},
{g: r15*r18, j: r19, b: -1/6*(4*r15*r16*r18 - r16 + 3*r17)*(4*r15*r16*r18^2/(4*r15*r16*r18 - r16 + 3*r17) + 2*r16*r18/(4*r15*r16*r18 - r16 + 3*r17) - r18)/(r16*r18^2), d: 2*r16*r18/(4*r15*r16*r18 - r16 + 3*r17), e: r16, h: r18, c: 2*r16*r19/(4*r15*r16*r18 - r16 + 3*r17), f: r17, a: r15},
{g: r20*r23, j: 0, b: -1/6*(4*r20*r21*r23 - r21 + 3*r22)*(4*r20*r21*r23^2/(4*r20*r21*r23 - r21 + 3*r22) + 2*r21*r23/(4*r20*r21*r23 - r21 + 3*r22) - r23)/(r21*r23^2), d: 2*r21*r23/(4*r20*r21*r23 - r21 + 3*r22), e: r21, h: r23, c: 0, f: r22, a: r20},
{g: -2*r24*r27 - 1, j: 0, b: r24, d: r25, e: r26, h: r27, c: 0, f: 2*r24*r26*r27 + r26, a: -(r24*r25 - 1)/r25},
{g: 0, j: r30, b: r29, d: 0, e: r31, h: 0, c: r30, f: r31, a: r28},
{g: 0, j: 0, b: r33, d: 0, e: r34, h: 0, c: 0, f: r34, a: r32},
{g: -1, j: 0, b: 0, d: r35, e: r36, h: r37, c: 0, f: r36, a: 1/r35},
{g: r40, j: 0, b: 0, d: r38, e: r39, h: 2*r38*r40 + r38, c: 0, f: r39, a: r40/(2*r38*r40 + r38)},
{g: -1/2, j: 0, b: -1/2*(r41 - r42)/(r41*r43), d: -2/3*r41*r43/(r41 - r42), e: r41, h: r43, c: 0, f: r42, a: -1/2/r43}]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多