Reduce Solves An Equation That NSolve Doesn't

I expected that NSolve handles the largest range of equation types but that is not always the case.

testeqns = {2 (-Sqrt[3] Cos[p] - Sin[p]/2) (2 + Cos[p]/2 - 
        Sqrt[3] Sin[p]) + 
     2 (1 + 1/2 Sqrt[3] Cos[p] + Sin[p]) (Cos[p] - 
        1/2 Sqrt[3] Sin[p]) == 0, 
   2 (-Sqrt[3] Cos[p] - Sin[p]/2)^2 + 
     2 (-(1/2) Sqrt[3] Cos[p] - Sin[p]) (1 + 1/2 Sqrt[3] Cos[p] + 
        Sin[p]) + 2 (Cos[p] - 1/2 Sqrt[3] Sin[p])^2 + 
     2 (2 + Cos[p]/2 - Sqrt[3] Sin[p]) (-(Cos[p]/2) + 
        Sqrt[3] Sin[p]) <= 0};

In[107]:= NSolve[testeqns, p]

During evaluation of In[107]:= NSolve::nsmet: This system cannot be solved with the methods available to NSolve. >>

In[116]:= res = Reduce[testeqns, p]

Out[116]= ((C[1] | (-\[Pi] + 
       4 ArcTan[
         Root[11 + 4 #1 - 13 #1^2 + 28 #1^3 + 48 #1^4 - 4 #1^5 - 
            61 #1^6 - 28 #1^7 + 11 #1^8 &, 2]] + 4 \[Pi] C[1])/(
      2 \[Pi]) | (
      2 ArcTan[
         Root[11 + 4 #1 - 13 #1^2 + 28 #1^3 + 48 #1^4 - 4 #1^5 - 
            61 #1^6 - 28 #1^7 + 11 #1^8 &, 2]] + 
       2 \[Pi] C[1])/\[Pi]) \[Element] Integers && 
   p == 2 ArcTan[
       Root[11 + 4 #1 - 13 #1^2 + 28 #1^3 + 48 #1^4 - 4 #1^5 - 
          61 #1^6 - 28 #1^7 + 11 #1^8 &, 2]] + 2 \[Pi] C[1]) || (C[
     1] \[Element] Integers && 
   p == 2 ArcTan[
       Root[11 + 4 #1 - 13 #1^2 + 28 #1^3 + 48 #1^4 - 4 #1^5 - 
          61 #1^6 - 28 #1^7 + 11 #1^8 &, 2]] + 2 \[Pi] C[1])

Evaluating the Reduce result numerically and substituting it into testeqns shows that it is correct

1 Like

Try a compact domain, say, one period:

NSolve[Flatten@{testeqns, 0 <= p <= 2 Pi}, p]

(*  {{p -> 5.0513}}  *)

substituting Sin[p] → s and Cos[p] → c and adding the constraint s^2 + c^2 == 1 and making c and s the variables also allows NSolve to handle it. Curiously, adding the constraint 0 <= p <= 2 Pi greatly slows down Reduce.

Right, because, per documentation (Details, bullet item), “NSolve deals primarily with linear and polynomial equations.”

1 Like

I think NSolve couldn’t handle my original formulation due to the infinite number of solutions.

It’s because the first or “default” root Reduce finds is between -2 Pi and 0. Restricting to the interval [0, 2 Pi] apparently makes it go through a whole bunch of work to find the right branch. (Why, I can only speculate. Perhaps because of the inequality in testeqns. Obviously, it does not take the general solution and then restrict it to the specified domain as shown below.)

The following demonstration is really only possible in hindsight:

Reduce[testeqns, p];
Reduce[Flatten@{%, 0 <= p <= 2 Pi}, p]
(* Out:
   C[1] == 1 &&
    p == 2 ? + 2 ArcTan[Root[11 + 4 #1 - 13 #1^2 + 28 #1^3 + 48 #1^4 - 4 #1^5 - 61 #1^6 - 28 #1^7 + 11 #1^8 &, 2]]
*)

res = Reduce[Flatten@{testeqns, -2 Pi <= p <= 0}, p]
(* Out:  p == 2 ArcTan[Root[11 + 4 #1 - 13 #1^2 + 28 #1^3 + 48 #1^4 - 4 #1^5 - 61 #1^6 - 28 #1^7 + 11 #1^8 &, 2]] *)

You may have already explored this, but

Solve[testeqns, p, Method -> Reduce]

uses Reduce to solve the system. And

NSolve[testeqns, p, Reals]

returns the solution. (Note the Reals are only partially implied by the use of the inequality in testeqns. The terms could be complex that evaluate to a real number. So if you meant the equation to be over the Reals, then specifying the domain helps a lot in this case.)

Daniel,

I wonder if the Sin/Cos to polynomial trick, which is a common fallback when NSolve fails, ought to be an Method option. (It seems like NSolve might do it already in some cases, but evidently not in this one.)

When I do NSolve[…, Reals], I usually have to restrict the method to “UseSlicingHyperplanes” → False. Maybe that was fixed in 10.3.

Seeing as people are interested in this post (he said hopefully), here is the general problem I’m trying to solve:

eq = 2 (yc + b Cos[theta] Sin[phi] + 
       a Cos[phi] Sin[theta]) (b Cos[phi] Cos[theta] - 
       a Sin[phi] Sin[theta]) + 
    2 (-a Cos[theta] Sin[phi] - b Cos[phi] Sin[theta]) (xc + 
       a Cos[phi] Cos[theta] - b Sin[phi] Sin[theta]) == 0;

Reduce can handle it but gives an incredibly complicated solution with a lot of special cases, which I don’t know how to get rid of.
It’s too long to post here, but it does work.

res[{a_, b_, xc_, yc_, theta_}] = 
  Reduce[eq , phi] /. C[1] -> 1;

res[{1, 2, 2, 1, \[Pi]/3}] // N

phi == 5.0513 || phi == 8.92351 || 
 phi == 7.14976 - 0.847588 I || phi == 7.14976 + 0.847588 I

If I add conditions like a > 0 and b > 0 or Reals to Reduce, it doesn’t give a result in any reasonable time.

I’m not sure what all you would like to do, but maybe this will help. Change variables so that alpha == phi - theta and beta = phi + theta and deal with either alpha or beta, assuming theta is known. If theta is unknown, deal with both alpha and beta, since phi and theta may be recovered from them.

eq2 = TrigReduce[eq /. Equal -> Subtract] /. {phi - theta -> alpha, 
     phi + theta -> beta, 2 phi -> alpha + beta} // TrigExpand;
Collect[eq2, {Sin[alpha], Sin[beta], Cos[alpha], Cos[beta]}, Factor]
(* Out:
    -(a - b) yc Cos[alpha] + (a + b) yc Cos[
       beta] + (-(a - b) xc - (a - b) (a + b) Cos[beta]) Sin[
       alpha] + (-(a + b) xc - (a - b) (a + b) Cos[alpha]) Sin[beta]
*)

ans = Solve[eq, phi];
ans2 = Solve[eq2 == 0, alpha];

LeafCount /@ {ans, ans2}
(* Out:
    {2139101, 7973}
*)

At least the general solutions in ans2 are much smaller. They should be easier to deal with.

Thanks, that should help as theta is an input.