# Solving complex equations

I feel like I am missing a basic, but key point when using Mathematica's Solve or Reduce.

Assuming[Element[{a, b, zr, zi}, Reals],
Solve[a + I b == zr + I zi, zi]
]


reduces to

{{zi -> b + I (-a + zr)}}


I can't really phrase the question better, but I was expecting zi -> b.

Along the same lines, how do I get Solve[a + I b == z, b] to return b -> Im[z]?

-

Unless I'm mistaken, the reason why this doesn't work is that Solve and Reduce do not have an Assumptions option, so Assuming has no effect on them.

### Using Reduce

We can tell Reduce that these variables are all real-valued like this:

Reduce[a + I b == zr + I zi && Element[{a, b, zr, zi}, Reals], zi]

(* ==> (zr | b) \[Element] Reals && a == zr && zi == b *)


### Using Solve

There's a note in the documentation:

Solve[expr && vars \[Element] Reals, vars, Complexes] solves for real values of variables, but function values are allowed to be complex.

However, Solve[a + I b == zr + I zi && (a | b | zr | zi) \[Element] Reals, zi, Complexes] returns {} which means that there are no solutions. Why does this happen? zi has a real value only if a == zr, so in general (for arbitrary a, zr values) there is no real solution for zi. The main difference between Reduce and Solve is that Reduce will try to generate those specific conditions under which a solution exists while Solve does not.

### Why doesn't Assuming work?

Generally, Assuming works by setting $Assumptions temporarily: In[1]:=$Assumptions
Out[1]= True

In[2]:= Assuming[x > 0, $Assumptions] Out[2]= x > 0  It will have an effect on functions that have an Assumptions option. These functions have Assumptions ->$Assumptions as a default setting:

In[3]:= Options[Integrate]
Out[3]= {Assumptions :> $Assumptions, GenerateConditions -> Automatic, PrincipalValue -> False} In[4]:= Options[Simplify] Out[4]= {Assumptions :>$Assumptions, ComplexityFunction -> Automatic,
ExcludedForms -> {}, TimeConstraint -> 300,
TransformationFunctions -> Automatic, Trig -> True}


It will not have an effect on functions that do not have this option:

In[5]:= Options[Solve]
Out[5]= {Cubics -> True, GeneratedParameters -> C,
InverseFunctions -> Automatic, MaxExtraConditions -> 0,
Method -> Automatic, Modulus -> 0, Quartics -> True,
VerifySolutions -> Automatic, WorkingPrecision -> \[Infinity]}

In[6]:= Options[Reduce]
Out[6]= {Backsubstitution -> False, Cubics -> False,
GeneratedParameters -> C, Method -> Automatic, Modulus -> 0,
Quartics -> False, WorkingPrecision -> \[Infinity]}


I could imagine though that Solve or Reduce make internal use of some function that does take $Assumptions into account. I do not know if this is the case or not, but I doubt that generally $Assumptions would have an effect on them.

-
Not all functions with Assumtion Option do have the default Assumptions->$Assumptions. AFAIK the only one which doesn't is PowerExpand with default Assumptions->True. So Assuming works only for Functions having the default option Assumptions->$Assumptions. –  Peter Breitfeld May 8 '12 at 9:51
@PeterBreitfeld Thanks for pointing that out! I checked the docs and they say: "You can specify default assumptions for PowerExpand using Assuming." It doesn't work though unless I use Assumptions -> $Assumptions. – Szabolcs May 8 '12 at 11:11 I think WRI has thougt about the Assumptions option of PowerExoand. I wrote the default were True, but it is Automatic. Look what Power[(a b)^n,Assumptions->#]&/@{Automatic,True} does. $Assumptions defaults to True, so Assumptions->$Assumptions is not appropriate for PowerExpand – Peter Breitfeld May 8 '12 at 11:26 For both expamples ComplexExpand gives the desired result: Solve[ComplexExpand[Im[#]] & /@ (a + I b == zr + I zi)]  {{b->zi}} Solve[ComplexExpand[Im[#], z] & /@ (a + I b == z)]  {{b->Im(z)}} Edit Well, here's a more complicated variant for the case then all parameters are real. In particular for a and b from your example. Constants in the equation should not be floating point numbers and E. If you need E in equaion it could be changed to some other not used transcendent constant like EulerGamma. Floating point numbers can be included with Rationalize. var = a; params = {b, zr, zi}; eqn = a + I b == (zr + I Sqrt[3] zi)^-2; rules = Table[params[[k]] -> E^\[Pi]^k, {k, Length[params]}]; Re[var /. Solve[{eqn /. rules}, var]] /. E^Plus[a$__] :> Times @@ (a$/. k$_. \[Pi]^l$_. :> params[[l$]]^k\$) // Simplify


{(zr - 3*zi)/(2*(3*zi + zr)^2)}

-
But this implies apriori knowledge of the solution - if I wanted to solve for a instead, I'd have to rewrite it. –  noe May 8 '12 at 6:09

You may like more to use Reduce in this case. Try this:

Reduce[a + I b == zr + I zi && Element[{a, b, zr, zi}, Reals], b]

(zr | zi) \[Element] Reals && a == zr && b == zi

-

If you have equations with only real variables, then I found it's best to split them in a list of Real and Imaginary Parts:

reImToList[expr_] := (ComplexExpand[{Re[#], Im[#]} & /@ ComplexExpand[expr]])


Then for the OP question:

eq=a + I b == zr + I zi
Solve[reImToList[eq], {zi, zr}]

(* {{zi -> b, zr -> a}} *)


This works for more complicated cases as well, e.g. the following will not give the desired result:

gl = a + b I == 1/(c + d I)
Solve[gl, {c, d}]
ComplexExpand[gl]
Solve[%, {c, d}]


But splitting will work easily:

reImToList[gl];
Solve[%, {c, d}]

(* {{c -> a/(a^2 + b^2), d -> -(b/(a^2 + b^2))}} *)

-