Performance of Wolfram Mathematica InverseFunction - performance

given the constants
mu = 20.82;
ex = 1.25;
kg1 = 1202.76;
kp = 76.58;
kvb = 126.92;
I need to invert the function
f[Vpx_,Vgx_] := Vpx Log[1 + Exp[kp (1/mu + Vgx/(Vpx s[Vpx]))]];
where
s[x_] := 1 + kvb/(2 x^2);
so that I get a function of two variables, the second one being Vgx.
I tried with
t = InverseFunction[Function[{Vpx, Vgx}, f[Vpx, Vgx]], 1, 2];
tested with t[451,-4]
It takes so much time that every time I try it I stop the evaluation.
On the other side, working with only one variable, everything works:
Vgx = -4;
t = InverseFunction[Function[{Vpx}, f[Vpx,Vgx]]];
t[451]
It's my fault? the method is inappropriate? or it's a limitation of Wolfram Mathematica?
Thanks
Teodoro Marinucci
P.S. For everyone interested it's a problem related to the Norman Koren model of triodes.

As I said in my comment, my guess is that InverseFunction first tries to solve symbolically for the inverse, e.g. Solve[Function[{Vpx, Vgx}, f[Vpx, Vgx]][X, #2] == #1, X], which takes a very long time (I didn't let it finish). However, I came across a system option that seems to turn this off and produce a function:
With[{opts = SystemOptions["ExtendedInverseFunction"]},
Internal`WithLocalSettings[
SetSystemOptions["ExtendedInverseFunction" -> False],
t = InverseFunction[Function[{Vpx, Vgx}, f[Vpx, Vgx]], 1, 2],
SetSystemOptions[opts]
]];
t[451, -4]
(* 199.762 *)
A couple of notes:
According to the documentation, InverseFunction with exact input should produce an exact answer. Here some of the parameters are approximate (floating-point) real numbers, so the answer above is a numerical approximation.
The actual definition of t depends on f. If f changes, then a side effect will be that t changes. If that is not something you explicitly want, then it is probably better to define t this way:
t = InverseFunction[Function[{Vpx, Vgx}, Evaluate#f[Vpx, Vgx]], 1, 2]

As my late Theoretical Physics professor said, "a simple and beautiful solution is likely to be true".
Here is the piece of code that works:
mu = 20.82; ex = 1.25; kg1 = 1202.76; kp = 76.58; kvb = 126.92;
Ip[Vpx_, Vgx_] = Power[Vpx/kp Log[1 + Exp[kp (1/mu + Vgx/Sqrt[kvb + Vpx^2])]], ex] 2/kg1;
Vp[y_, z_] := x /. FindRoot[Ip[x, z] == y, {x, 80}]
The "real" amplification factor of a tube is the partial derivative of Ip[Vpx, Vgx] by respect to Vgx, with give Vpx. I would be happier if could use the Derivative, but I'm having errors.
I'll try to understand why, but for the moment the definition
[CapitalDelta]x = 10^-6;
[Micro][Ipx_, Vgx_] := Abs[Vp[Ipx, Vgx + [CapitalDelta]x] - Vp[Ipx, Vgx]]/[CapitalDelta]x
works well for me.
Thanks, it was really the starting point of the FindRoot the problem.

Related

Wolfram Mathematica Solve command for a nonlinear system of equations

I am trying to solve a nonlinear system of equations by using the Solve (and NSolve) command, but the evaluation get stuck.
For a very similar system, basically the same but with the derivatives of the equations I get no problems. I define the functions I need, write the equations, define the variables, define the solutions through the Solve command, and, once obtained with another system the initial values, I try to solve the system with NSolve.
Defining the functions:
a[x_] := A (1 - ms[x])
b[x_]:=2 ((ArcSinh[nn[x]/ms[x]] ms[x]^3 + nn[x] ms[x] Sqrt[nn[x]^2 + ms[x]^2])/(8 \[Pi]^2) + (ArcSinh[pp[x]/ms[x]] ms[x]^3 + pp[x] ms[x] Sqrt[pp[x]^2 + ms[x]^2])/(8 \[Pi]^2))
where A is a constant. Here I deleted some multiplicative constants to simplify the problem.
Then I have the equations:
eq1[x_]:= B a[x] + C a[x]^2 + D a[x]^3 - F b[x]
eq2[x_]:= pp[x]^3 - nn[x]^3
eq3[x_]:= G - (pp[x]^3 + nn[x]^3)
eq4[x_]:= Sqrt[nn[x]^2 + ms[x]^2] - Sqrt[pp[x]^2 + ms[x]^2] - Sqrt[m + ee[x]^2] + H (pp[x]^3 - nn[x]^3)
where B, C, D, G, m and H are constants. Here too, I deleted some multiplicative constants, to simplify the code for you.
Finally, I define the variables:
Var = {ee[x], pp[x], nn[x], ms[x]}
then solve the system "implicitly":
Sol =
Solve[{eq1[x] == 0, eq2[x] == 0, eq3[x] == 0, eq4[x] == 0}, Var]
(N.B: it is here that the code get stuck!!!! Despite, as I said, with a similar system with derivatives of the equations, everything work fine.)
and make a list of the equations:
eqs =
Table[Var[[i]] == (Var[[i]] /. Sol[[1]]), {i, Length[Var]}];
To conclude, after having obtained the initial conditions, I would try to solve the system:
system0 = Flatten[{eqs, ee[xi] == eei, pp[xi] == ppi, nn[xi] == nni, ms[xi] == msi}];
sol0 = NSolve[system0, {ee, kpp, nn, ms}, {x, xi, xf}, Flatten[{MaxSteps -> 10^4, MaxStepFraction -> 10^-2, WorkingPrecision -> 30, InterpolationOrder -> All}, 1]];
where I previously set xi = 10^-8 and xf = 10.
Trying to be more clear, when I try to evaluate the system through the Solve command, the evaluation continues indefinitely and I cannot understand why, where is the mistake. Despite a similar system with the derivative of the previous equations and NSolve replaced with NDSolve, works without any problem, and the execution of the "equivalent" line (Sol = Solve[{eq1[x] == 0, eq2[x] == 0, eq3[x] == 0, eq4[x] == 0}, Core]) is extremely fast (~1 sec).
Any help to understand where I am wrong is welcome, as well any suggestion to solve numerically this kind of system of equations.
Trying to be more clear, when I try to evaluate the system through the Solve command, the evaluation continues indefinitely and I cannot understand why, where is the mistake. Despite a similar system with the derivative of the previous equations and NSolve replaced with NDSolve, works without any problem, and the execution of the "equivalent" line (Sol = Solve[{eq1[x] == 0, eq2[x] == 0, eq3[x] == 0, eq4[x] == 0}, Core]) is extremely fast (~1 sec).
Any help to understand where I am wrong is welcome, as well any suggestion to solve numerically this kind of system of equations.

Integral changes variable subscripts

I have been away from Mathematica for quite a while and am trying to fix some old notebooks from v4 that are no longer working under v11. I'm also a tad rusty.
I am attempting to use functional minimization to fit a polynomial of variable degree to an arbitrary function (F) given a starting guess (ao) and domain of interest (d). Note that while F is arbitrary, its nature is such that the integral of the product of F and a polynomial (or F^2) can always be evaluated algebraically.
For the sake of example, I'll use the following inputs:
ao = { 1, 2, 3, 4 }
d = { -1, 1 }
F = Sin[x]
To do so, I create an array of 'indexed' variables
polyCoeff = Array[a,Length[a],0]
Result: polycoeff = {a[0], a[1], a[2], a[3]}
I then create the polynomial itself using the following
genPoly[{},x_] := 0
genPoly[a_List,x_] := First[a] + x genPoly[Rest[a],x]
poly = genPoly[polyCoeff,x]
Result: poly = a[0] + x (a[1] + x (a[2] + x a[3]))
I then define my objective function as the integral of the square of the error of the difference between this poly and the function I am attempting to fit:
Q = Integrate[ (poly - F[x])^2, {x, d[[1]],d[[2]]} ]
result: Q = 0.545351 - 2. a[0.]^2 + 0.66667 a[1.]^2 + .....
And this is where things break down. poly looks just as I expected: a polynomial in x with coefficients that look like a[0], a[1], a[2], ... But, Q is not exactly what I expected. I expected and got a new polynomial. But not the coefficients contained a[0.], a[1.], a[2.], ...
The next step is to create the initial guess for FindMinimum
init = Transpose[{polyCoeff,ao}]
Result: {{a[0],1},{a[1],2},{a[3],3},{a[4],4}}
This looks fine.
But when I make the call to FindMinimum, I get an error because the coefficients passed in the objective (a[0.],a[1.],...) do not match those passed in the initial guess (a[0],a[1],...).
S = FindMinimum[Q,init]
So I think my question is how do I keep Integrate from changing the arguments to my coefficients? But, I am open to other approaches as well. Keep in mind though that this is "legacy" work that I really don't want to have to completely revamp.
Thanks much for any/all help.

Plotting the solution to an equation with Mathematica

I have a function f(x,t) and I'd like to plot the function of the solution x(t) of f(x(t),t)=0 using Mathematica. How can I do it?
Mathematica is often quite different to other programming languages I can use. Normally, I would try something looking like:
Create arrays X, T
For t in T do
solve (numerically) f(x,t)=0, append the solution to X
Plot X
However, I don't know really well how to use loops in Mathematica yet, and the same for arrays, so I'm having serious problems doing this.
Is there some rapid, direct way of solving this problem with Mathematica? If not, could somebody please help me out with this?
Also, does anybody have a better title for the question?
Edit: Following the suggestion of #LutzL, I would try something like the following:
Table[FindRoot[f[x,t]==0,{x,x_0}],{t,start,stop,step}]
Would this work correctly?
I still have a problem, because my function f(x,t) is highly nonlinear, and thus i would like to input a good starting point for every t. Specifically, I know the solution for t=0 and I would like to use for time step t_{n+1} the solution for t_n. Is there a way to do this?
Edit 2: I solved the problem the following way:
tmax = 10; nsteps = 100*tmax;
thrust = {v/2 - g}; angle = {Pi/2};
For[i = 1, i <= nsteps, i++,
sol = {thr, \[Theta]} /.
FindRoot[{eq1[i*tmax/nsteps],
eq2[i*tmax/nsteps]}, {{thr, Last[thrust]}, {\[Theta],
Last[angle]}}]; AppendTo[thrust, sol[[1]]];
AppendTo[angle, sol[[2]]]];
ListPlot[Table[{i*tmax/nsteps, thrust[[i + 1]]}, {i, 0, nsteps}]]
ListPlot[Table[{i*tmax/nsteps, angle[[i + 1]]/Pi}, {i, 0, nsteps}]]
where eq1 and eq2 are my equations and thrust and angle are the solutions
A way to do it would be to create a list and then to plot it.
You have x(0) and you want x(t) for t>0. You can use the expression Szabolcs provides:
root(t_NumericQ, x0_):= Module[{z}, z = z /. FindRoot[f[z, t] == 0, {z, x0}]]
And then you compute and plot a list.
list[tin_, tend_, tstep_, x0_] := Module[{z = x0, t = tin}, lis = {};
While[t < tend, z = root[t, z]; lis = Append[lis, {t, z}]; t = t + tstep; ];
ListPlot[lis]]
Or you can change the last line for a x=Interpolation[lis] and x[t] will be an interpolation function for the solution x(t)
Moreover you can test whether other solutions for x(t) are possible replacing root[t,z] for RandomReal[{x_1,x_2}] where x_1and x_2 are in the range of the x space you want to explore.

Set::write error when using For loop

Solving a complicated formula f(u,v)==0, where
I assign some constant value to u and then solve v.
I can solve it without for-loop, but encounter errors by adding For[] enclosing the codes,
where saying
Set::write: Tag Times in "Solve[] with exact coefficients solns is Protected.
A simple example to illustrate my idea:
For[ i = 1, i < 5, i++,
f = x^2 + y^2 - 10;
x = i;
eqn = (f == 0);
soln = Solve[eqn, y]
]
will get error:
Set::write: "Tag Times in (-9+y^2) is Protected."
Only when I add For[ ] at the outside of the code
(inner 4-line code works fine without for loop)
So it seems that there is an variable assignment permission issue in the for loop
How can I avoid it?
I no longer have Mathematica 7 installed, and your code runs (although with no printed output...) on Mathematica 10. Based on the error message, it sounds like you need to Clear[f] before trying to reassign it.
For[i = 1, i < 5, i++,
Clear[f];
f = x^2 + y^2 - 10;
x = i;
eqn = (f == 0);
soln = Solve[eqn, y];
Print[soln]
]
However, you're still really mixing things up. Consider what happens with your code as the loop executes. First it starts with i=1 and says:
Clear[f] -- or don't, this isn't the only issue
f = x^2 + y^2 - 10 -- This gives me an expression with symbols x and y
x=i -- This sets x=1 since i=1 already
At this point, the expression for f has become y^2 - 9`. Next time it comes around, it will repeat:
f = x^2 + y^2 - 10 -- But x is no longer a symbol!! So now it still treats x=1...
This becomes a nightmare. I could try to hack your code into working with the fewest changes (e.g. make it Clear[f,x] or something), but that's not really the best advice I can give.
A better overall construction would be something like:
Eqn[x_,y_]=(x^2+y^2-10==0);
For[i=1,i<5,i++,
Print[Solve[Eqn[i,y],y]];
];
Your function f is a function, so you should make it a function like f[x_,y_]=something. Better yet, just make the entire equation into a function as above. That way, you never actually modify the values of x or y and don't get caught with issues in your loop.
And before you use this new code I've given you, clear everything or just quit the Kernel.

How do you work out Conditional Probabilities in Mathematica. Is it possible?

Can Mathematica do Bayes Rule conditional probability calculations, without doing the calculation manually? If so how?
I have been searching both the Mathemtaica doco and the web for a hint but cannot find anything. I am not after how to do Bayes Rule manually via Mathematica, I want to know if there is a way to define the conditional probabilities and calculate other ones automagically.
So to use the toy example assuming Bernoulli distributions
P(Cancer+) = 0.01
P(Cancer-) = 0.99
P(Test+|Cancer+) = 0.9
P(Test-|Cancer+) = 0.1
P(Test+|Cancer-) = 0.2
P(Test-|Cancer-) = 0.8
Is it possible to work out
P(Cancer+|Test+) = 0.0434
So using the below.
Print["P(C+) = ", PCancerT=BernoulliDistribution[0.01]];
Print["P(C-) = ", PCancerF=BernoulliDistribution[0.99]];
Print[]
Print["P(T+|C+) = ", PTestTGivenCancerT=BernoulliDistribution[0.9]];
Print["P(T-|C+) = ", PTestFGivenCancerT=BernoulliDistribution[0.1]];
Print["P(T+|C-) = ", PTestTGivenCancerF=BernoulliDistribution[0.2]];
Print["P(T-|C-) = ", PTestFGivenCancerF=BernoulliDistribution[0.8]];
Print[]
Print["P(T+,C+) = ", PTestTAndCancerT = Probability[vCT&&vTTCT,{vCT\[Distributed]PCancerT,vTTCT\[Distributed]PTestTGivenCancerT}]];
Print["P(T-,C+) = ", PTestFAndCancerT = Probability[vCT&&vTFCF,{vCT\[Distributed]PCancerT,vTFCF\[Distributed]PTestFGivenCancerT}]];
Print["P(T+,C-) = ", PTestTAndCancerF = Probability[vCF&&vTTCF,{vCF\[Distributed]PCancerF,vTTCF\[Distributed]PTestTGivenCancerF}]];
Print["P(T-,C-) = ", PTestFAndCancerF = Probability[vCF&&vTTCF,{vCF\[Distributed]PCancerF,vTTCF\[Distributed]PTestFGivenCancerF}]];
Print[]
Print["P(C+|T+) = ?"];
Print["P(C+|T-) = ?"];
Print["P(C-|T+) = ?"];
Print["P(C-|T-) = ?"];
I can work out the joint probabilities by defining all the probability tables manually, but is there a way to get Mathematica to do the heavy lifting?
Is there a way to define and calculate these kind of conditional probabilities?
Many thanks for any assistance, even it its “You can’t... stop trying” :)
PS : was this an attempt at doing something along these lines? Symbolic Conditional Expectation in Mathematica
Actually... I worked this out symbolically in the past, and it covers a lot of simple (unchained) probabilities. I guess it wouldn't be that hard to add chaining(see below). You're welcome to reply with augmentation. The symbolic approach is far more flexible than working with Bernoulli distributions and creating a proc for Bayes theorem and thinking about the right way to apply it every time.
NOTE: The functions are not bound, like in the post above ((0 < pC < 1) && (0 < pTC < 1) && (0 < pTNC < 1)) because sometimes you want "unweighted" results, which produce numbers outside of 0-1 range, then you can bring back into the range by dividing by some normalizing probability or product of probabilities. If you do want to add bounds for error checking, do this:
P[A_ /;0<=A<=1] := some_function_of_A;
use Esc+cond+Esc to enter \\[Conditioned] symbol in Mathematica.
Remove[P];
Unprotect#Intersection;
Intersection[A_Symbol, B_Symbol] := {A, B}
Intersection[A_Not, B_Symbol] := {A, B}
Intersection[A_Symbol, B_Not] := {A, B}
P[Int_List/; Length#Int == 2] := P[Int[[2]] \[Conditioned] Int[[1]]] P[Int[[1]]]
(*// P(B) given knowledge of P(A) //*)
P[B_, A_] := If[NumericQ#B, B,
P[B \[Conditioned] A] P[A] + P[B \[Conditioned] Not#A] P[Not#A]]
P[Not#B_, A_: 1] := If[NumericQ#A, 1 - P[B], 1 - P[B, A]]
P[A_ \[Conditioned] B_] := P[A \[Intersection] B]/P[B, A]
P[Not#A_ \[Conditioned] B_] := 1 - P[A \[Conditioned] B];
You then use it as such:
P[Cancer]=0.01;
Don't need "not cancer" since P[!Cancer] yields 0.99 (Esc+not+Esc types a very pretty logical not symbol, but Not[A], !A or \[Not]A work just fine too)
P[Test \[Conditioned] Cancer] = 0.9
P[Test \[Conditioned] ! Cancer] = 0.2
again: P[!Test \\[Conditioned] Cancer] will be 1-P[Test \\[Conditioned] Cancer] by definition, unless you override it.
Now let's query this model:
P[Test, Cancer]
P[!Test, Cancer]
returns
0.207
0.793
and
P[Cancer \[Conditioned] Test]
P[!Cancer \[Conditioned] Test]
P[Cancer \[Conditioned] !Test]
P[!Cancer \[Conditioned] !Test]
returns
0.0434783
0.956522
0.00126103
0.998739
I guess it would be a nice idea to define P(B|A1,A2,A3,...,An), anyone up for coding the chain rule using NestList or something like it? I didn't need it for my project, but it wouldn't be that difficult to add, should someone need it.
I wouldn't complicate the issue with Print statements and BernoulliDistributions. You know the probabilities, so the simplest thing to do is to calculate them directly, but perhaps using vectors to get P(B), and using the fact that pr(cancer) = 1-pr(not cancer) and so on.
Bayes' Theorem states that P(A|B)=(P(A ⋂ B))/(P(B))
The intersection is calculated as the conditional probability (test given cancer) times the probability of cancer.
So something like the following should work:
conditionalProb[pC_, pTC_, pTNC_] /;
(0 < pC < 1) && (0 < pTC < 1) && (0 < pTNC < 1) :=
(pTC * pC)/({pTC, pTNC}.{pC, 1 - pC})
conditionalProb[0.01, 0.9, 0.2]
0.0434783
And yes, the Probability functionality in version 8 does allow you to calculate conditional probabilities "automagically", but for a problem like this with Bernoulli-distributed events, it's overkill.

Resources