Hello, @cybervigilante! The problem is that the cube root operation (actually any integer root) does not represent a single value, but many at a time. For example, consider this simple case
ans = (-8) ^ (-1/3)
One naturally would expect the value of ans
to be -2
, but if you write N(ans)
, you will get 1.00000000000000 + 1.73205080756888*I
. In fact, there are three possible values for ans
, i.e. ans = -2
, ans = 1.00000000000000 + 1.73205080756888*I
and ans = 1.00000000000000 - 1.73205080756888*I
. These are the solutions to the equation $x^3 + 8 = 0$ en the set of complex numbers $\mathbb{C}$.
Sage is a mathematical software, and it tries to be as useful as possible. In your particular case, this implies giving one complex value for the cube root (since the real value can be mentally computed.) This is working against your intentions in your code: Sage doesn't know if $x$ is a complex or real variable,so it makes the most useful/general assumption: $x$ is complex. (Notice that, on the contrary, elevating to the third power does give a unique value.) As a consequence, in $\mathbb{C}$, you have $(x^{1/3})^3 = x$, but $(x^3)^{1/3}$ not necessarily being equal to $x$.
Now, consider your chunk of code:
a(x) = (2*x - 3) ^ (1/3) + 4
b(x) = ((x - 4) ^ 3 + 3) / 2
print(a(b(x)))
print(b(a(x)))
In this case, you have
$$b(a(x)) = ((a(x) - 4) ^ 3 + 3) / 2 = (((2x - 3) ^ {1/3} + 4 - 4)^3 + 3) / 2 = (((2x - 3) ^ {1/3})^3 + 3) / 2.$$
Since elevating to the third power gives a unique answer, regardless of whether the base is real or complex, you can basically simplify the cube root with the third power, so $b(a(x)) = (((2x - 3) + 3) / 2 = (2x - 3 + 3) / 2 = (2x)/2 = x$, as Sage has printed. However, in the other case, you have
$$a(b(x)) = (2a(x) - 3) ^ {1/3} + 4 = (2(((x - 4) ^ 3 + 3) / 2) - 3)^{1/3} + 4$$
$$~~~~= (((x - 4) ^ 3 + 3) - 3)^{1/3} + 4 = ((x - 4) ^ 3)^{1/3} + 4.$$
Now, this is where you will have problems. As mentioned above, the cube root has not a unique value, so Sage won't simplify the third power with the cube root, because, in that case, it should (randomly) choose one the three possibilities, which is a terrible mistake.
All of that being said, I believe you do want to work with reals in this particular case of the code in your question. (In contrast to the case of complex numbers, in the set of real numbers, $\mathbb{R}$, it IS A PROPERTY that $(x^3)^{1/3} = x$.) In order to do that, declare $x$ to be explicitly a real symbolic variable, as follows:
x = var('x', domain='real')
a(x) = (2*x - 3) ^ (1/3) + 4
b(x) = ((x - 4) ^ 3 + 3) / 2
print(a(b(x)))
print(b(a(x)))
In that case, both compositions give the result x
.
I hope this helps!
I understand I'm dealing with symbolic values, but why does b(x) simplify automatically but a(x) does not?