This question and answer was inspired by this closed as duplicate question.
One possible definition of the n
-th order root of x
is the number y
, such that y^n == x
. That means, for example, that both 1
and -1
are square roots of 1
. After looking at the request in the OP of the linked question (have f[z] := Sqrt[z]
return {-1, 1}
) I thought it would be nice, to have a parser, that handles this kind of thing on the fly for a more general case.
Here's an example of desired output:
parse[x^(1/2)+y^(1/2)] (* Assume for the moment, that x and y are positive *)
(* {Sqrt[x] + Sqrt[y], Sqrt[x] - Sqrt[y], -Sqrt[x] + Sqrt[y], -Sqrt[x] - Sqrt[y]} *)
That is, as x^(1/2)
has two possible solutions, as does y^(1/2)
, there are four possible combinations. If I consider an expression like x^(1/2) + y^(1/3)
, then I'd like to get a list of 6 solutions.
This much - capturing all branches of integer roots - I have managed to achieve, as shown in my answer.
What I'm looking for is a) a better coding style; b) generalization to a wider class of functions; c) see below.
Clarification for (b): I would, for example, like to have Log
be reinterpreted as {Log[x], Log[x] + 2 Pi I, Log[x] + 4 Pi I}
. Realizing, that Log
has an infinite number of branches, it is of course necessary to stop somewhere. Perhaps allow an option to be passed, saying "I want the branches from m
to n
" or something akin to that.
Regarding point (c): consider the expression Sqrt[x] + Sqrt[x]
. For the sake of this question it is not the same as 2 Sqrt[x]
. Indeed, I would expect here to be three or four (doubly degenerate zero) results: {-2 Sqrt[x], 0, 0, 2 Sqrt[x]}
EDIT 13.08.15
Jens found the question somewhat unclear. I suppose, it's due to the mathematical considerations distracting him, such as my last point where I claim Sqrt[x] + Sqrt[x]
is not always 2 Sqrt[x]
. I'll try to present an alternative formulation of my question that doesn't have anything to do with mathematics, but is purely a task on expression-manipulation.
Suppose, we have an expression which contains, among other things, two, three or even more parameters. Let's call them a
, b
, and c
. I do not know, how deeply a
, b
and c
may be nested, at which level, etc.
Let's introduce a function called values
:
values[a] = {a1, a2, a3}
values[b] = {b1, b2, b3}
values[c] = {c1, c2, c3}
I want to transform
expression[{a_, b_, c_}, vars___]
to
expression[#, vars___] &/@ Tuples[{values[a], values[b], values[c]}].
BUT, and this is a very important "but" that complicates things, I don't have expression
explicitly defined. All I have, is the actual form of the expression. For example, it may be something like
expr = (a + b)/c
In that case I can do
expr /. Thread /@ (Cases[expr, a | b | c, Infinity] -> # & /@
Tuples[values /@ Cases[expr, a | b | c, Infinity]])
and get
{(a1 + b1)/c1, (a1 + b1)/c2, (a1 + b1)/c3, (a1 + b2)/c1, (a1 + b2)/c2, (a1 + b2)/c3, (a1 + b3)/c1, (a1 + b3)/c2, (a1 + b3)/c3, (a2 + b1)/c1, (a2 + b1)/c2, (a2 + b1)/c3, (a2 + b2)/c1, (a2 + b2)/c2, (a2 + b2)/c3, (a2 + b3)/c1, (a2 + b3)/c2, (a2 + b3)/c3, (a3 + b1)/c1, (a3 + b1)/c2, (a3 + b1)/c3, (a3 + b2)/c1, (a3 + b2)/c2, (a3 + b2)/c3, (a3 + b3)/c1, (a3 + b3)/c2, (a3 + b3)/c3}
However, if my expression looks like
expr = (a + b)/a
I would want to get exactly the same result as above, but with c1, c2, c3
replaced with a1, a2, a3
respectively. How would be a nice way to force Mathematica to treat every new occurrence of a
(or any other expression for which values
has a DownValue
) as a completely new variable?
Sqrt
is defined to be one particular inverse function with a branch cut on the negative real axis. You can define other inverse functions by changing the branch cut, see here, but then they are different functions unless you extend the domain. Therefore,Sqrt[x] + Sqrt[x] == 2 Sqrt[x]
is always true. Any parser that violates this will lead to big trouble. It's safer to stick withReduce
if you want multiple roots. $\endgroup$Sqrt[x]+Sqrt[x]
example, it's perfectly fine to reinterpret it asparse[Sqrt[x]+Sqrt[y]]/.y->x
. I imagine, what you're trying to tell me, is that if I choose one branch forSqrt[x]
I must necessarily choose the same one forSqrt[y]
? What about combining roots of different powers then? The concept of consistency then becomes somewhat ambiguous. $\endgroup$Reduce
, combined with a formulation that avoids abusing the notation for inverse function in the first place. $\endgroup$Reduce
though... I'm looking through the docs right now, but I don't see a straighforward way to utilize it. Maybe you could offer some minimal example? $\endgroup$