solving non-linear equations using scipy - scipy

I'm trying to solve the following equation:
Where a list of A_e/A* values are given, and gamma=1.2, how should I solve this equation such that a list of M_e is returned corresponding to a list of A_e/A* values?
I thought about using scipy.optimize.newton, but it seems like this is not the right approach
def expr(x):
result = np.arange(1,1.25,step=0.004)-((1/x)*((2/(1.2+1))*(1+((1.2-1)/2)*x**2))**((1.2+1)/(2*1.2-1)))
return result.any()
scipy.optimize.newton(expr,1.1)
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_4660/3619719442.py in <module>
----> 1 scipy.optimize.newton(expr,1.1,x1=1.2)
D:\Softwares\Anaconda\lib\site-packages\scipy\optimize\zeros.py in newton(func, x0, fprime, args, tol, maxiter, fprime2, x1, rtol, full_output, disp)
338 " Failed to converge after %d iterations, value is %s."
339 % (itr + 1, p1))
--> 340 raise RuntimeError(msg)
341 warnings.warn(msg, RuntimeWarning)
342 p = (p1 + p0) / 2.0
RuntimeError: Tolerance of 0.09999999999999987 reached. Failed to converge after 1 iterations, value is 1.2.
I used x to denote M_e, and I replaced Ae/A* with a list of values--np.arange(1,1.25,step=0.004) But, I guess the newton's method can only return 1 scalar value, but I defined the function with a sweeping list of Ae/A* values. How should I fix this?

newton works for scalar functions, and you are turning it into a vector function. Since you want the zero for different Ae values, include the Ae parameter in the function definition, then call newton several times (you can use the args keyword):
def expr(x, a):
result = a-((1/x)*((2/(1.2+1))*(1+((1.2-1)/2)*x**2))**((1.2+1)/(2*1.2-1)))
return result
[newton(expr, .01, args=(a,)) for a in np.arange(1,1.25,step=0.004)]
>>[0.9999999999999992, 0.9944379739232752,0.9889506795317498, 0.9835363421148852, ...

Related

Too many indices for array error - scipy.intergate.solve_ivp(method = Radau) gives error

I am supposed to solve a ODE as follows:
def dHdt(t, H):
if H>H_p(t) and data2_sleep(t)>0:
return -0.323*24
elif H>H_p(t) and data2_sleep(t)==0:
return 0.116*24
elif H<=H_m(t) and data2_sleep(t)>0:
return -0.278*24
elif H<=H_m(t) and data2_sleep(t)==0:
return 0.150*24
elif H<=H_p(t) and H>H_m(t) and data2_sleep(t) > 0:
return -0.274*24
elif H<=H_p(t) and H>H_m(t) and data2_sleep(t) == 0:
return 0.096*24
where H_*p, H_m, data2_*sleep are objects that are results of interpolation using scipy.interp1d .
For the solver, I used solve_ivp but methods as 'RK45' or 'LSODA' were not giving good results (by which I mean , I have a approximate solution at hand and comparing with it , results differ a lot. Moreover, another solver odeint can do much better job except it also is unstable I think) and wanted to use stiff solvers as Radau and BDF but when running below
H_new = solve_ivp(dHdt, t_span = [0, 50], y0 = [H0], method = 'Radau', t_eval = t_span)
I get the following error
IndexError Traceback (most recent call last)
<ipython-input-107-6595d5c7194d> in <module>
----> 1 H_new = solve_ivp(dHdt, t_span = [0, 50], y0 = [H0], method = 'Radau', t_eval = t_span)
5 frames
/usr/local/lib/python3.8/dist-packages/scipy/integrate/_ivp/common.py in _dense_num_jac(fun, t, y, f, h, factor, y_scale)
325 h_vecs = np.diag(h)
326 f_new = fun(t, y[:, None] + h_vecs)
--> 327 diff = f_new - f[:, None]
328 max_ind = np.argmax(np.abs(diff), axis=0)
329 r = np.arange(n)
IndexError: too many indices for array: array is 0-dimensional, but 1 were indexed
indeed H0 is a single number but in the dHdt there is no indexing and indexing issue is raised by solver itself. (Also, only those stiff solvers make this error but if you change method to RK45 or etc it works).
What do you think is the reason for this error?
Turns out for Radau and some solvers output must be in brackets,[]. For other solvers it is okay not to.

comparing MATLAB fmincon and ga (genetic algorithm) results: issue with ga

I have a fairly complex optimization problem set up that I've solved through fmincon by calling it like this
myfun = #(x5) 0.5 * (norm(C*x5 - d))^2 + 0.5 * (timeIntervalMeanGlobal * powerAbsMaxMaxGlobal * sum(x5(28:128),1))^2;
[x5, fval] = fmincon(myfun, initialGuess, -A, b, Aeq, beq, lb, []);
The components are far to long to print here, but here are the dimensions
C: 49 x 128
x5: 128 x 1
d: 49 x 1
timeIntervalMeanGlobal, powerAbsMaxMaxGlobal: constants
initialGuess: 128 x 1
A: 44541 x 128
b: 44541 x 1
Aeq: 24 x 128
beq: 24 x 1
lb: 128 x 1
This works in code, but I don't get results that I'm completely happy with. I'd like to compare it with the built in ga function in MATLAB, which is called in a similar way, but I get an error when I try to run it like this
[x5, fval] = ga(myfun, nvars, -A, b, Aeq, beq, lb, []);
where nvars = 128. There's a long list of about 8 errors starting with
??? Error using ==> mtimes
Inner matrix dimensions must agree.
and ending with
Caused by:
Failure in user-supplied fitness function evaluation. GA cannot continue.
Can someone please instruct me on how to call ga properly, and give insight on why this error might occur with the ga call when the same code doesn't cause an error with fmincon? I've tried all the MATLAB help files and examples with a few different permutations of this but no better luck. Thanks.
UPDATE: I think I found the problem but I don't know how to fix it. The ga documentation says "The fitness function should accept a row vector of length nvars". In my case, myfun is the fitness function, but x5 is a column vector (so is lb). So while mathematically I know that C*x5 = d is the same as x5'*C' = d' even for non-square matrices, I can't formulate the problem that way for the ga solver. I tried - it makes it past the fitness function but then I get the error
The number of rows in A must be the same as the length of b.
Any thoughts on how to get this problem in the right format for the solver? Thanks!
Got it! I just had to manipulate the fitness function to make it use x5 as a row vector even though it's a column vector in all the constraints
myfun = #(x5) 0.5 * (norm(x5 * C' - d'))^2 + 0.5 * (timeIntervalMeanGlobal * powerAbsMaxMaxGlobal * sum(x5(28:128)))^2;
Phew!

How to use quadgk function in matlab as a function handle?

I am trying to solve a double integral where I am solving both inner as well as outer integral with quadgk function.
% The integrand is of course a function of both x and y
integrand = #(x,y) (phi(j,y,X) - phi(j,x,X))*(phi(i,y,X) - phi(i,x,X))/abs(y-x)^(2*s+1)
% The inner integral is a function of x, and integrates over y
inner = #(x) quadgk(#(y)integrand(x,y), x-lambda, x+lambda)
% The inner integral is integrated over x to yield the value of the double integral
dblIntegral = quadgk(inner, -(1+lambda), 1+lambda)
and I am getting this following error:
integrand = #(x,y)(phi(j,y,X)-phi(j,x,X))*(phi(i,y,X)-phi(i,x,X))/abs(y-x)^(2*s+1)
inner = #(x)quadgk(#(y)integrand(x,y),x-lambda,x+lambda)
??? Error using ==> quadgk at 108
A and B must be scalar floats.
Error in ==> #(x)quadgk(#(y)integrand(x,y),x-lambda,x+lambda)
Error in ==> quadgk>evalFun at 344
fx = FUN(x);
Error in ==> quadgk>f1 at 362
[y,too_close] = evalFun(tt);
Error in ==> quadgk>vadapt at 258
[fx,too_close] = f(x);
Error in ==> quadgk at 197
[q,errbnd] = vadapt(#f1,interval);
Error in ==> frational_laplacian at 29
dblIntegral = quadgk(inner, -(1+lambda), 1+lambda)
You're getting that problem because internally quadgk evaluates the passed function using a vector of values. This means that in the line
dblIntegral = quadgk(inner, -(1+lambda), 1+lambda)
the function inner is being called with x being a vector. quadgk requires that a and b (in this case x±lambda) be scalars, so you get the error you've been seeing. If you want to ensure that inner always gets a scalar as input, you can use
dblIntegral = quadgk(#(x)arrayfun(inner,x), -(1+lambda), 1+lambda)

Why do these errors appear? quad2d, dblquad

I have a huge function to integrate:
syms x y
f=(228155022448185.*(cos((2.*pi).*y)./exp(131738205584307./(35184372088832*x)) - 1)*(cos((8.*pi).*y)/exp(131738205584307./(8796093022208*x)) - 1)*(cos((8.*pi).*y)/exp(131738205584307./(8796093022208.*x)) + cos((18.*pi).*y)/exp(1185643850258763./(35184372088832.*x)) - 2))/((18014398509481984. *(x.^2)).*exp(x. * ((1981232555272083.*(y.^2))/2251799813685248 - y./16 + 1./16)))
I need to integrate it (x:[0,inf) and y:[0,1]), but I receive an error for quad2d and dblquad.
quad2d(quadfun,0,100,0,1)
??? Error using ==> quad2d>tensor at 350
Integrand output size does not match the input size.
Error in ==> quad2d at 164
[Qsub,esub] = tensor(thetaL,thetaR,phiB,phiT);
and
dblquad(quadfun,0,100,0,1)
??? Error using ==> dblquad>innerintegral at 74
Inputs must be floats, namely single or double.
Error in ==> quad at 76
y = f(x, varargin{:});
Error in ==> dblquad at 53
Q = quadf(#innerintegral, ymin, ymax, tol, trace, intfcn, ...
Could you explain why these errors appear? And how can I fix it?
The quad function family doesn't work with symbolic math. Instead, you can either:
Use symbolic integration with int. To compute a double integral, invoke int twice consecutively, each time with a different integration variable.
Define an equivalent regular function that accepts non-symbolic parameters and pass its handle to quad. I'd do it with an anonymous function -- just start your definition with f = #(x, y) instead of f =, and that's it (also remember that f is a function handle now, so you don't need to write the ampersat (#) when passing it around).

why isn't the result a scalar?

i'm stuck with this error:
In an assignment A(I) = B, the number of elements in B and I must be the same.
yres(1)=((u - uc).^2) + ((y - yc).^2) -(d.^2);
i don't understand, why this won't get a skalar?since the elements are all scalar. what should be changed to get a scalar?
best regards
edit: thanks sloede, all inputs are scalar, but i still get this error
In an assignment A(I) = B, the number of elements in B and I must be the
same.
Error in myfun (line 7)
yres(1)=sqrt(((u - uc).^2) + ((y - yc).^2) ) -d;
Error in fsolve (line 241)
fuser = feval(funfcn{3},x,varargin{:});
Error in modfsolve (line 26)
x= fsolve(#myfun,x0,options,uc,d,spacing_amplitude,spacing_width);
Caused by:
Failure in initial user-supplied objective function evaluation. FSOLVE
cannot continue.*
The "." before an operator means that the following operation should be applied element-wise and not on the vector as a whole. Thus
a = b.^2
will give you as a result all elements of b squared and saved back to a. Therefore, in your code statement above, if any of u, uc, y, yc, d are not scalar but a vector, your result will be a vector as well.
Otherwise there seems to be nothing wrong with your code.
read the documentation of fsolve: http://www.mathworks.nl/help/toolbox/optim/ug/fsolve.html
it states:
fun
The nonlinear system of equations to solve. fun is a function that accepts a vector x and returns a vector F, the nonlinear equations evaluated at x.
Obviously your function myfun doesn't handle vector input.
You can solve this by adding the following construction inside your function (and of course change it to your needs/your parameters):
function out = myfun(in)
if ~isscalar(in)
% assuming it's a matrix or vector
out = reshape(arrayfun(#myfun,in(:)),size(in));
else
% your actual function execution statements
out = dostuffon(in);
end
end
or properly vectorize your function (if that's possible)