Ask Your Question

Using solve() to find positive real solutions to a complex equation

asked 2012-05-15 19:25:20 -0500

TSchwenn gravatar image

I need solve() to return only positive real solutions to a symbolic complex equation, but it fails to find a useful solution:

sage: var('x, y', domain='positive')
sage: z = 1/(i*x + 1/(i*y + 1))
sage: Equation = z == 2
sage: solve(Equation, x, y)
([x == (-I*y + 1)/(2*y - 2*I)], [1])

I want solutions in the form [x == foo, y == bar]. Splitting Equation into real and imaginary components does the trick:

sage: Equation = [z.real() == 2, z.imag() == 0]
sage: solve(Equation, x, y)
[[x == (-1/2), y == -1], [x == (1/2), y == 1]]

But why is that reformulation necessary to produce useful results? Isn't it equivalent to the original Equation?

Also, why does solve() ignore my variables' domain='positive' clause? Solve also ignores positive x and y assumptions:

sage: assume(x>0)
sage: assume(y>0)
sage: solve(Equation, x, y)
[[x == (-1/2), y == -1], [x == (1/2), y == 1]]

And it bugs out when positive x & y clauses are added to Equation:

sage: Equation.append(x>0, y>0)
sage: solve([Equation, x>0], x, y)
[[0 < x, [1/((y^2 + 1)*(1/(y^2 + 1)^2 + (x - y/(y^2 + 1))^2)) == 2, -(x - y/(y^2 + 1))/(1/(y^2 + 1)^2 + (x - y/(y^2 + 1))^2) == 0, x > 0, y > 0]]]
edit retag flag offensive close merge delete



To address one of your questions, but not the main one: Maxima's solve, as is probably mentioned elsewhere on this site, explicitly does not take assumptions into account. The idea is that the variables in solve are like dummy variables in integration, and so should not do this. In Sage we try very weakly to take this into account, but it's a process that has a way to go.

kcrisman gravatar imagekcrisman ( 2012-05-17 17:16:14 -0500 )edit

Please clarify the "should not do this" part. What's the _this_?

TSchwenn gravatar imageTSchwenn ( 2012-05-17 18:59:38 -0500 )edit

So like when you do the integral from 0 to x of t^2 dt, it didn't really matter what the name of the variable t was, and one shouldn't take any outside info into account because it is just a dummy because I was lazy. I could even do the integral from 0 to x of x^2 dx, though we tell our students not to because of the ambiguity. Similarly, Maxima treats variables in "solve" that way. It's not really a big deal, but at least makes it more clear why it's not a big priority for them to change the behavior. We would like to do more of it in Sage, but there are only limited resources of people who know enough about how Maxima and Sage work in this area, and they are more focused on extending our capabilities to more symbolic ...(more)

kcrisman gravatar imagekcrisman ( 2012-05-18 07:18:39 -0500 )edit

Is there any kind of workaround to at least remove automatically the complex solutions from the solutions so the don't mix with real roots? For example i was trying to make a list of real solutions of an equation and half of the list finally came out to be complex numbers.

Cosmos gravatar imageCosmos ( 2012-07-07 11:06:57 -0500 )edit

You could postprocess your list of solutions by trying to do `float(x)` for each of them. If that raised an error, then I guess it wasn't real! We do this for the `exclude` option for plotting, for instance.

kcrisman gravatar imagekcrisman ( 2012-07-12 14:26:38 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2016-06-07 21:35:16 -0500

Here's a way to see why the explicit split into real and imaginary parts is necessary. If the variables are given to solve as a list,

var('x, y')
z = 1/(i*x + 1/(i*y + 1))
Equation = z == 2
solve(Equation, [x, y])

[[x == (-I*r1 + 1)/(2*r1 - 2*I), y == r1]]

then it's clear that solve is returning a fully complex answer with a dummy variable r1. With references to this dummy variable and the result of solve, one can then find solutions that make the imaginary part of x zero:

var('x, y, r1')
z = 1/(i*x + 1/(i*y + 1))
Equation = z == 2
f = solve(Equation, [x, y])
solve( imaginary(f[0][0].rhs()), r1 )

[r1 == -1, r1 == 1]

With an additional reference to this second result, the desired solution form can be achieved with nested lists:

var('x, y, r1')
z = 1/(i*x + 1/(i*y + 1))
Equation = z == 2
f = solve(Equation, [x, y])
g = solve( imaginary(f[0][0].rhs()), r1 )
[[f[0][i].subs(g[j]) for i in (0,1)] for j in (0,1)]

[[x == (-1/2), y == -1], [x == (1/2), y == 1]]

Here's a link to a live example.

edit flag offensive delete link more

Your Answer

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

Add Answer

Question Tools



Asked: 2012-05-15 19:25:20 -0500

Seen: 2,749 times

Last updated: Jun 07 '16