Ask Your Question

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

asked 2019-03-17 23:31:36 +0200

stockh0lm gravatar image

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 flag offensive close merge delete

2 Answers

Sort by » oldest newest most voted

answered 2019-03-18 15:40:18 +0200

Emmanuel Charpentier gravatar image

updated 2019-03-18 20:00:33 +0200

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]
[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)}]
edit flag offensive delete link 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?

stockh0lm gravatar imagestockh0lm ( 2019-03-18 16:25:16 +0200 )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.

Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2019-03-18 18:43:50 +0200 )edit

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

Thank you for your great answer.

stockh0lm gravatar imagestockh0lm ( 2019-03-18 21:43:39 +0200 )edit

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

stockh0lm gravatar imagestockh0lm ( 2019-03-18 23:27:31 +0200 )edit

answered 2019-03-18 20:56:09 +0200

nbruin gravatar image

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]

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.

edit flag offensive delete link more


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

stockh0lm gravatar imagestockh0lm ( 2019-03-18 21:44:39 +0200 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2019-03-17 23:31:36 +0200

Seen: 216 times

Last updated: Mar 18 '19