# solving a system of equations, depending on only a subset of variables

i have a set of equations like this

x,z, xm, xs, zs, z2, d1, d2, em, es =var('x z xm xs zs z2 d1 d2 em es')

equations = [
d1 == sqrt(xm*xm + zs*zs),
d2 == sqrt(z2*z2 + xs*xs),
xm + xs == x,
zs + z2 == z,
(xm/zs)/(xs/z2) == (em/es)
]

from sympy import *
from sympy.solvers import solve

#solve(equations, [xs,xm])
sol = solve(equations, [d1,d2])


and get this solution:

︡{d1: sqrt(xm**2 + zs**2), d2: sqrt(xs**2 + z2**2)}


which is correct, of course.

But i would like to get a solution based only on em, es, zs, x and z, eliminating xm, xs and z2.

How can I get it to do that?

edit retag close merge delete

Sort by » oldest newest most voted

Let's see:

x,z, xm, xs, zs, z2, d1, d2, em, es =var('x z xm xs zs z2 d1 d2 em es')
equations = [d1 == sqrt(xm*xm + zs*zs),
d2 == sqrt(z2*z2 + xs*xs),
xm + xs == x,
zs + z2 == z,
(xm/zs)/(xs/z2) == (em/es)]
E1=[u.subs(equations[2].solve(xm)).simplify_full() for u in equations]
E2=[u.subs(E1[3].solve(z2)).simplify_full() for u in E1]
E3=[u.subs(E2[4].solve(xs)).simplify_full() for u in E2]
E3
[d1 == sqrt((2*(em*es - es^2)*z*zs^3 + (em^2 - 2*em*es + es^2)*zs^4 + (em^2*x^2 + es^2*z^2)*zs^2)/(es^2*z^2 + 2*(em*es - es^2)*z*zs + (em^2 - 2*em*es + es^2)*zs^2)),
d2 == sqrt((es^2*x^2*z^2 + es^2*z^4 - 2*(em^2 - 3*em*es + 2*es^2)*z*zs^3 + (em^2 - 2*em*es + es^2)*zs^4 + (es^2*x^2 + (em^2 - 6*em*es + 6*es^2)*z^2)*zs^2 - 2*(es^2*x^2*z - (em*es - 2*es^2)*z^3)*zs)/(es^2*z^2 + 2*(em*es - es^2)*z*zs + (em^2 - 2*em*es + es^2)*zs^2)),
x == x,
z == z,
em/es == em/es]


Note that maxima.eliminate is supposed to do that (but fails lamentably...).

Note, two hours later : (that's what called in french "l'esprit de l'escalier"...):

Of course, you can get the desired result trivially by solving for the variables to eliminate as well as for the desired variables :

solve(equations,[d1, d2, xm, xs, z2])
[[d1 == sqrt((2*(em*es - es^2)*z*zs^3 + (em^2 - 2*em*es + es^2)*zs^4 + (em^2*x^2 + es^2*z^2)*zs^2)/(es^2*z^2 + 2*(em*es - es^2)*z*zs + (em^2 - 2*em*es + es^2)*zs^2)),
d2 == sqrt(z^2 - 2*z*zs + zs^2 + (es*x*z - es*x*zs)^2/(es*z + (em - es)*zs)^2),
xm == em*x*zs/(es*z + (em - es)*zs),
xs == (es*x*z - es*x*zs)/(es*z + (em - es)*zs),
z2 == z - zs]]


The variables to be eliminated do not figure indeed in the solutions for the desired variables...

I should sleep more...

"L'esprit de l'escalier" strikes again :

You can get "cleaner" solutionns with :

solve(equations,[d1, d2, xm, xs, z2], algorithm="sympy", solution_dict=False)
[{xm: em*x*zs/(es*z + em*zs - es*zs),
d2: sqrt(es^2*x^2*(z - zs)^2/(es*z + em*zs - es*zs)^2 + (z - zs)^2),
d1: sqrt(em^2*x^2*zs^2/(es*z + em*zs - es*zs)^2 + zs^2),
z2: z - zs,
xs: es*x*(z - zs)/(es*z + em*zs - es*zs)}]

more

So you basically solve the system of equation, by telling sage what to do, and use it to not make stupid manual mistakes when transforming equations?

( 2019-03-18 10:25:16 -0500 )edit

That's basically what using a CAS amounts to... It won't usually think for you. The attempt at maxima.eliminate shows that it is n ot as easy as one might think.

Note : you have 8 variables and 5 equations. you want to eliminate 3 variables, leaving you with 5 varianbles, two equations and 3 tautologies... You might reconsider your formulation.

( 2019-03-18 12:43:50 -0500 )edit

yes, and i could live with that (CAS just eliminating manual srew ups).

( 2019-03-18 15:43:39 -0500 )edit

I get a traceback when i try to use your solution. is there something wrong with my code? (see above link)

( 2019-03-18 17:27:31 -0500 )edit

Depending on your applications, a direct use of elimination theory might be more insightful. One can write your equations entirely in terms of polynomials if we allow ourselves to clear denominators and express things in terms of $d1^2,d2^2$:

R.<d1, d2, xm, xs, zs, z2, x, y, z, em, es>=PolynomialRing(QQ)
equations = [
d1^2- (xm*xm + zs*zs),
d2^2- (z2*z2 + xs*xs),
xm + xs - x,
zs + z2 - z,
(xm*z2)*es - em*zs*xs]
I=R.ideal(equations)


We can then determine which relations exist between these variables that do not involve $xm,xs,z2$:

d1rel=I.elimination_ideal([xm,xs,z2,d2]).gens(); assert len(d1rel) == 1
assert d1rel[0].coefficient(d1) == 0
d1sqr = - d1rel[0].coefficient({d1:0})/d1rel[0].coefficient({d1:2})

d2rel=I.elimination_ideal([xm,xs,z2,d1]).gens(); assert len(d2rel) == 1
assert d2rel[0].coefficient(d2) == 0
d2sqr = - d2rel[0].coefficient({d2:0})/d2rel[0].coefficient({d2:2})


(by specifying d2 as one of the variables to eliminate, we know we'll get relations that do NOT involve d2). We can easily test that we only find one relation, that it is of degree 2 in d1 and that it does not mention d1 linearly. So we can easily get the value of d1^2 out of that. Same thing for d2)

It looks like for your example, symbolics are just fine -- and perhaps a bit better, since they don't necessarily multiply out every polynomial. For more involved elimination problems, however, direct use of groebner-basis based methods becomes indispensible.

more

very interesting, i was not aware that that was possible. thank you, i will look more into that.

( 2019-03-18 15:44:39 -0500 )edit