I'm solving this system of equations with Mathematica:
roots = Solve[
k1*A*N - k2*C == 0 && k3*B*N - k4*D == 0 && N0 - C - D - N == 0 &&
A0 - C - A == 0 && B0 - D - B == 0 && k1 >= 0 && k2 >= 0 &&
k3 >= 0 && k4 >= 0 && A >= 0 && B >= 0 && N >= 0 && C >= 0 &&
D >= 0 && A0 >= 0 && B0 >= 0 && N0 >= 0, {A, B, C, D, N}, Reals,
Method -> Reduce]
the solutions in roots
contain ConditionalExpression
and Root
objects. Plugging in values to roots
gives the correct answers:
roots /. {A0 -> 100, B0 -> 100 , N0 -> 50, k1 -> 0.1, k2 -> 0.1,
k3 -> 0.1, k4 -> 0.1}
yields: {{A -> 75.1652, B -> 75.1652, C -> 24.8348, D -> 24.8348, N -> 0.330403}}
however I want to get the full expression of the (real) solutions, without Root
objects. But when I use ToRadicals
it doesn't preserve the solutions. Plugging in:
ToRadicals[roots] /. {A0 -> 100, B0 -> 100 , N0 -> 50, k1 -> 0.1,
k2 -> 0.1, k3 -> 0.1, k4 -> 0.1}
gives imaginary solutions:
{{A -> -7.58604*10^13 - 8.17902*10^11 I,
B -> 7.58604*10^13 + 8.17902*10^11 I,
C -> 7.58604*10^13 + 8.17902*10^11 I,
D -> -7.58604*10^13 - 8.17902*10^11 I, N -> -1. - 1.42109*10^-14 I}}
which aren't the solutions I'm looking for. Is there a way to get the full expression of the correct solution? Assuming here that all the constraints are met (i.e., all variables are positive reals). Thanks.
Root
objects? That's what I don't understand. The result ofroots /. {A0 -> 100, B0 -> 100 , N0 -> 50, k1 -> 0.1, k2 -> 0.1, k3 -> 0.1, k4 -> 0.1}
is perfectly correct. $\endgroup$Root
objects do not have the same issues with numeric (in)stability of evaluation as radical reformulations.One will not, for example, encounter a near-vanishing denominator in numerically evaluating aRoot
object after parameter substitution. $\endgroup$Root
objects, after substitution of parameters, are handled by validated methods for root isolation and refinement. I do not know what might be the analog in Python. Given that you know there will be only one positive solution, you might try finding the largest root of the derivative (a cubic) numerically, then giving a larger value as a starting point for Newton iterations. How to find that root of the derivative? Work recursively. Two more derivatives brings it to linear. Granted, this is a bit of code to put in place. But it is fairly low-level and should run fast. $\endgroup$