How to express trigonometric equation in terms of of given trigonometric function?
This is a new version of my answer in response to the edited question (the first version is here).
It is based on the same idea, but the Weierstrass substitution rules are now generated by Mathematica (instead of entered by hand) and results with $\pm$ solutions are correctly returned.
First, generate the Weierstrass substitution rules
$TrigFns = {Sin, Cos, Tan, Csc, Sec, Cot};
(WRules = $TrigFns == (Through[$TrigFns[x]] /. x -> 2 ArcTan[t] //
TrigExpand // Together) // Thread)
Then, Partition[WRules /. Thread[$TrigFns -> Through[$TrigFns[x]]], 2] // TeXForm
returns
$$
\begin{align}
\sin (x)&=\frac{2 t}{t^2+1}\,, & \cos (x)&=\frac{1-t^2}{t^2+1}\,, \\
\tan (x)&=-\frac{2 t}{t^2-1}\,, & \csc (x)&=\frac{t^2+1}{2 t}\,, \\
\sec (x)&=\frac{-t^2-1}{t^2-1}\,, & \cot (x)&=\frac{1-t^2}{2 t} \ .
\end{align}
$$
Then, we invert the rules using
invWRules = #[[1]] -> Solve[#, t, Reals] & /@ WRules
which we can finally use in the convert
function:
convert[expr_, (trig : Alternatives@@$TrigFns)[x_]] :=
Block[{temp, t},
temp = expr /. x -> 2 ArcTan[t] // TrigExpand // Factor;
temp = temp /. (trig /. invWRules) // FullSimplify // Union;
Or @@ temp /. trig -> HoldForm[trig][x] /. ConditionalExpression -> (#1 &)]
Note that the final line has HoldForm
to prevent things like 1/Sin[x]
automatically being rewritten as Csc[x]
, etc...
Here are some test cases - it is straight forward to check that the answers are correct (but don't forget to use RelaseHold
):
In[6]:= convert[Sin[x], Cos[x]]
Out[6]= - Sqrt[1 - Cos[x]^2] || Sqrt[1 - Cos[x]^2]
In[7]:= convert[Sin[x]Cos[x], Tan[x]]
Out[7]= Tan[x]/(1 + Tan[x]^2)
In[8]:= convert[Sin[x]Cos[x], Cos[x]]
Out[8]= -Cos[x] Sqrt[1 - Cos[x]^2] || Cos[x] Sqrt[1 - Cos[x]^2]
In[9]:= convert[Sin[2x]Cos[x], Sin[x]]
Out[9]= -2 Sin[x] (-1 + Sin[x]^2)
In[10]:= convert[Sin[2x]Tan[x]^3, Cos[x]]
Out[10]= 2 (-2 + 1/Cos[x]^2 + Cos[x]^2)
A couple of quick thoughts about the above solution:
It assumes real arguments for the trig functions. It would be nice if it didn't do this and could be extended to hyperbolic trig and exponential functions.
When two solutions are given, it should return the domains of validity - or combine the appropriate terms using
Abs[]
.It should be extended to handle things like
convert[Sin[x], Cos[2x]]
.
If anyone feels like implementing any of these things, please feel free!
I would like to share more universal method I use in my scientific manipulations involving trigonomeric expressions of real arguments. It does not require any identities used by hand and is mathematically coincise.
The idea is to convert trigonometric expression to exponents, which in turn will play the role of monomials. Then you can use very powerful Groebner basis manipulation method. Let me ilustrate how it works in your simple cases. First define some help function which translates trigonometric expression to polynomials. The simplified version looks like
ExpToPoly[expr_] := Block[{ex = ExpandAll[TrigToExp[expr]]},
ReplaceRepeated[
ex, {Exp[Complex[0, a_Rational | a_Integer]*b_ + c_.] :>
Power[b, a]*Exp[c]}]]
Then input expresions you want to manipulate.
expr = Sin[x];
use = Cos[x];
Lets look how it is transformed to polynomial
ExpToPoly[TrigToExp[expr]]
I/(2 x) - (I x)/2
Now calculate Groebner base and solve the identity you find useful (in your simple cases actually you have no choise)
gb = GroebnerBasis[{myexpr - ExpToPoly[TrigToExp[expr]],
myuse - ExpToPoly[TrigToExp[use]]}, {myuse}, {x},
MonomialOrder -> EliminationOrder]
{-1 + myexpr^2 + myuse^2}
From which it follows
Solve[gb[[1]] == 0, myexpr] /. {myuse -> use}
{{myexpr -> -Sqrt[1 - Cos[x]^2]}, {myexpr -> Sqrt[1 - Cos[x]^2]}}
Lets look at one of simple transformation of previous answer.
expr1 = Sin[2 x] Tan[x]^3;
use = Cos[x];
gb1 = GroebnerBasis[{myexpr - ExpToPoly[TrigToExp[expr1]],
myuse - ExpToPoly[TrigToExp[use]]}, {myuse}, {x},
MonomialOrder -> EliminationOrder]
{2 - 4 myuse^2 - myexpr myuse^2 + 2 myuse^4}
Now in order to prevent automatic convertion to Sec[] function we Hold solved rezult:
Hold @@ (myexpr /. Solve[gb1[[1]] == 0, myexpr]) /. {myuse -> use}
Hold[(2 (1 - 2 Cos[x]^2 + Cos[x]^4))/Cos[x]^2]
This method can easily be extended to many variables, allows very complicated manipulations of trigonometric expressions (at least of real arguments). And most important: it is based on Groebner basis, so is always mathematically correct.
Just noted that, that using this approach you can easily convert to double, triple, etc... argument as was asked in the wish list:
expr = Sin[x];
use = Cos[2 x];
gb2 = GroebnerBasis[{myexpr - ExpToPoly[TrigToExp[expr]],
myuse - ExpToPoly[TrigToExp[use]]}, {myuse}, {x},
MonomialOrder -> EliminationOrder]
{-1 + 2 myexpr^2 + myuse}
The result being
Hold @@ (myexpr /. Solve[gb2[[1]] == 0, myexpr]) /. {myuse -> use}
Hold[-(Sqrt[1 - Cos[2 x]]/Sqrt[2]), Sqrt[1 - Cos[2 x]]/Sqrt[2]]