简体   繁体   中英

Solve system of 2 equations in python

I have a set of two equations with three unknowns that has some conditions. x, y and z must all be larger than zero. How can I solve this? There is only one solution and I already know it, but I want to know how to get to it correctly.

This is the equations:

100 = x + y + z

100 = 10x +2.5y + 0.5z

Need to find x, y and z. They are integers and positive.

This is the code I have that does not work:

from sympy import symbols, Eq, solve
x, y, z = symbols('x y z')
eq1 = Eq(x + y + z, 100)
eq2 = Eq(x*10 + y*2.5 + z*0.5, 100)
#eq3 = x, y, z must all be larger than zero and integers
solution = solve((eq1,eq2), (x,y,z))
solution

In sympy if you want to find integer solutions to equations then you should use diophantine . It doesn't handle systems of equations but you can put the solution from one equation into the other and call diophantine again:

In [69]: eq1 = x + y + z - 100

In [70]: eq2 = 10*x + 5*y/2 + z/2 - 100

In [71]: sol = diophantine(eq1, t, syms=[x, y, z])

In [72]: sol
Out[72]: {(t₀, t₀ + t₁, -2⋅t₀ - t₁ + 100)}

In [73]: [xt, yt, zt], = sol

In [74]: eq3 = eq2.subs({x:xt, y:yt, z:zt})

In [75]: eq3
Out[75]: 
23⋅t₀            
───── + 2⋅t₁ - 50
  2              

In [76]: t1, t2 = eq3.free_symbols

In [77]: [t1s, t2s], = diophantine(eq3, z, syms=[t1, t2])

In [78]: rep = {t1:t1s, t2:t2s}

In [79]: (xt.subs(rep), yt.subs(rep), zt.subs(rep))
Out[79]: (4⋅z₀ - 100, 500 - 19⋅z₀, 15⋅z₀ - 300)

The solution here is in terms of an integer parameter z0. This gives the set of solutions to the two equations but you also have the requirement that x, y, z are positive which constrains the possible values of z0:

In [80]: ineqs = [s.subs(rep) > 0 for s in [xt, yt, zt]]

In [81]: ineqs
Out[81]: [4⋅z₀ - 100 > 0, 500 - 19⋅z₀ > 0, 15⋅z₀ - 300 > 0]

In [82]: solve(ineqs)
Out[82]: 
               500
25 < z₀ ∧ z₀ < ───
                19

In [83]: 500/19
Out[83]: 26.31578947368421

We see that z needs to be 26 which gives a unique solution for x , y and z :

In [84]: z, = ineqs[0].free_symbols

In [85]: (xt.subs(rep).subs(z, 26), yt.subs(rep).subs(z, 26), zt.subs(rep).subs(z, 26))
Out[85]: (4, 6, 90)

You did not explicitly state it but according to your comment x,y and z should be integers. This complicates matters a bit. This is now an example of a mixed integer programming (MIP) problem. You could take a look at the following package for solving this in python: mip

The downside of solving MIP's is that they are NP hard. But for this small example this should not matter.

This type of problem can be solved by Z3py , a SAT/SMT solver:

from z3 import Ints, solve

x, y, z = Ints('x y z')
sol = solve(x + y + z == 100, x * 100 + y * 25 + z * 5 == 1000, x > 0, y > 0, z > 0)
print(sol)

Output: [z = 90, y = 6, x = 4] .

Note that in general, Z3 only looks for one solution. To find subsequent solutions, a clause needs to be added to prohibit the already found solutions. (In this case there seems to be only one solution.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM