% Power output
power_output = MF_t.*difference.*e;
% POWER OUTPUT OPTIMIZATION USING - GOLDEN SEARCH METHOD
x_lower = 0.2;
x_upper = 1.4;
h = (x_upper - x_lower);
r = (sqrt(5) - 1)*0.5;
x2 = x_lower + (1+r)*h;
x3 = x_upper - (1+r)*h;
tol = 0.05;
count = 1;
while h>-tol
f2 = -power_output(x2)
f3 = -power_output(x3)
if f3<f2
x_lower = x2;
x_upper = x_upper;
h = (x_upper - x_lower);
x2 = x3;
x3 = x_upper - (1-r)*h;
elseif f2<f3
x_lower = x_lower;
x_upper = x3;
h = (x_upper - x_lower);
x3 = x2;
x2 = x_lower + (1-r)*h;
else
x_lower = x2;
x_upper = x3;
h = (x_upper - x_lower);
x2 = x_lower + (1+r)*h;
x3 = x_upper - (1+r)*h;
end
interval = x_upper - x_lower;
count = count + 1
if count > 100
break
end
end
answer = (x_upper + x_lower)/2
value = fanswer
Im trying to run this code, it's telling me that there is an error as my arrays f2 and f3 as "Array indices must be positive integers or logical values". I'm wondering would anyone know if taking the absolute values of my arrays will make my optimisation incorrect
The error message is quite informative in this case. You are trying to access the x2th element of f2. A quick calculation shows that on the first iteration x2 = 2.14. It is not possible to take the 2.14th element of f2 because this is is not an integer, and taking the absolute value will not help.
x2 is not an index, it is a value. On each iteration, the Golden Ratio search requires you to actually evaluate power_output with whatever variable set to x2. So, it looks like you need to do this calculation power_output = MF_t.*difference.*e with x=x2.
I want summation of 3 variables to always equal to a number, in this case 1, but I don't know how to make it happen. For example in the following problem I am trying to find maximum value of "resourceOut/maximumTime" which is a function of x1, x2, x3 but while finding the maximum I want x1, x2, x3 to be equal to 1. (xi is the inital guess value for x1, x2 and R can be any positive number.
function Resource(xi,R)
x = fminsearch(#relations, xi);
x(1)
x(2)
function goldenRatio = relations(xi)
x1 = xi(1);
x3 = xi(2);
x2 = 1 - x1 - x3;
x3 = 1 - x1 - x2;
x1 = 1 - x2 - x3;
R1 = R * x1 * 0.1;
R2 = R * x2 * 0.25;
R3 = R * x3 * 0.50;
T1 = ((((R1)^2)*100)^0.45+1800);
T2 = ((((R2)^2)*100)^0.45+1800);
T3 = ((((R3)^2)*100)^0.45+1800);
elapsedTimes =[T1 T2 T3];
resourceOut = R1 + R2 + R3;
maximumTime = max(elapsedTimes);
goldenRatio = -resourceOut/maximumTime;
end
end
Assume we have three equations:
eq1 = x1 + (x1 - x2) * t - X == 0;
eq2 = z1 + (z1 - z2) * t - Z == 0;
eq3 = ((X-x1)/a)^2 + ((Z-z1)/b)^2 - 1 == 0;
while six of known variables are:
a = 42 ;
b = 12 ;
x1 = 316190;
z1 = 234070;
x2 = 316190;
z2 = 234070;
So we are looking for three unknown variables that are:
X , Z and t
I wrote two method to solve it. But, since I need to run these code for 5.7 million data, it become really slow.
Method one (using "solve"):
tic
S = solve( eq1 , eq2 , eq3 , X , Z , t ,...
'ReturnConditions', true, 'Real', true);
toc
X = double(S.X(1))
Z = double(S.Z(1))
t = double(S.t(1))
results of method one:
X = 316190;
Z = 234060;
t = -2.9280;
Elapsed time is 0.770429 seconds.
Method two (using "fsolve"):
coeffs = [a,b,x1,x2,z1,z2]; % Known parameters
x0 = [ x2 ; z2 ; 1 ].'; % Initial values for iterations
f_d = #(x0) myfunc(x0,coeffs); % f_d considers x0 as variables
options = optimoptions('fsolve','Display','none');
tic
M = fsolve(f_d,x0,options);
toc
results of method two:
X = 316190; % X = M(1)
Z = 234060; % Z = M(2)
t = -2.9280; % t = M(3)
Elapsed time is 0.014 seconds.
Although, the second method is faster, but it still needs to be improved. Please let me know if you have a better solution for that. Thanks
* extra information:
if you are interested to know what those 3 equations are, the first two are equations of a line in 2D and the third equation is an ellipse equation. I need to find the intersection of the line with the ellipse. Obviously, we have two points as result. But, let's forget about the second answer for simplicity.
My suggestion it's to use the second approce,which it's the recommended by matlab for nonlinear equation system.
Declare a M-function
function Y=mysistem(X)
%X(1) = X
%X(2) = t
%X(3) = Z
a = 42 ;
b = 12 ;
x1 = 316190;
z1 = 234070;
x2 = 316190;
z2 = 234070;
Y(1,1) = x1 + (x1 - x2) * X(2) - X(1);
Y(2,1) = z1 + (z1 - z2) * X(2) - X(3);
Y(3,1) = ((X-x1)/a)^2 + ((Z-z1)/b)^2 - 1;
end
Then for solving use
x0 = [ x2 , z2 , 1 ];
M = fsolve(#mysistem,x0,options);
If you may want to reduce the default precision by changing StepTolerance (default 1e-6).
Also for more increare you may want to use the jacobian matrix for greater efficencies.
For more reference take a look in official documentation:
fsolve Nonlinear Equations with Analytic Jacobian
Basically giving the solver the Jacobian matrix of the system(and special options) you can increase method efficency.
I am a beginner at Matlab programming and with the Runge-Kutta method as well.
I'm trying to solve a system of coupled ODEs using a 4th-order Runge-Kutta method for my project work.
here is my problem...
G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;
syms n;
x2 = symfun(sym('x2(n)'),[n]);
x1 = symfun(sym('x1(n)'),[n]);
x3 = symfun(sym('x3(n)'),[n]);
x4 = symfun(sym('x4(n)'),[n]);
x5 = symfun(sym('x5(n)'),[n]);
k1 = [x2 * x1 *n *(1 - z * x2)*(x1 - n) - 2 * x3 * n *(1 - z * x2) - x4^2 * x2 *(1 - z * x2)- G *x3 *x2 ]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n];
k2 = [x2 * (1 - z * x2)*(x1 * x2 * ( x1 - 2 *n)*( x1 - n) + 2* x3 * n + x4^2 * x2 ) ]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n * (x1 - n)];
k3 = [x3 * x2 * (2 * n * x1 - n)^2 * ( 1 - z * x2) + G * x1 * (x1 - 2 *n)* (x1 - n) + x4^2 * G]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n * (x1 - n)];
k4 = [x4 * ( x1 + n)] ./ [n * (x1- n)];
k5 = - [x5] ./ [n * (x1- n)];
f = #(n,x) [k1; k2; k3; k4; k5];
[n,xa] = ode45(f,[0 1],[1-b 1/b 1-b 0.01 0.02]);
errors are
Error using odearguments (line 93)
#(N,X)[K1;K2;K3;K4;K5] returns a vector of length 1, but the length
of initial conditions vector is 5. The vector returned by
#(N,X)[K1;K2;K3;K4;K5] and the initial conditions vector must have
the same number of elements.
Error in ode45 (line 114)
[neq, tspan, ntspan, next, t0, tfinal, tdir, y0, f0, odeArgs,
odeFcn, ...
Please guide me how can I solve the above problem with fourth-order Runge-Kutta method...
The error stems from using symbolic functions (mixed with a function handle) with a numeric solver.
You need to create numeric functions for ode45 to function properly (I also replaced all of the [ and ] with ( and ) for grouping):
G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;
k1 = #(n,x) (x(2) * x(1)*n *(1 - z * x(2))*(x(1) - n) - 2 * x(3) * n *(1 - z * x(2)) - x(4)^2 * x(2) *(1 - z * x(2))- G *x(3) *x(2)) ./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n);
k2 = #(n,x) (x(2) * (1 - z * x(2))*(x(1) * x(2) * ( x(1) - 2 *n)*( x(1) - n) + 2* x(3) * n + x(4)^2 * x(2) )) ./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n * (x(1) - n));
k3 = #(n,x) (x(3) * x(2) * (2 * n * x(1) - n)^2 * ( 1 - z * x(2)) + G * x(1) * (x(1) - 2 *n)* (x(1) - n) + x(4)^2 * G)./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n * (x(1) - n));
k4 = #(n,x) (x(4) * (x(1) + n)) ./ (n * (x(1)- n));
k5 = #(n,x) - x(5) ./ (n * (x(1)- n));
f = #(n,x) [k1(n,x); k2(n,x); k3(n,x); k4(n,x); k5(n,x)];
[n,xa] = ode45(f,[0 1],[1-b 1/b 1-b 0.01 0.02]);
This runs for my install of Matlab.
However, the output is all NaNs since the function produce Infs; I may have introduced errors by replacing the brackets, but I don't know what the actual equations are so I'm going to leave that to you. :)
In general, you consult first the documentation. If not available, use the search engine of you choice, for instance https://www.google.de/search?q=matlab+ode45+example to find as first result https://de.mathworks.com/help/matlab/ref/ode45.html
There you find a multidimensional example
function dy = rigid(t,y)
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3);
dy(2) = -y(1) * y(3);
dy(3) = -0.51 * y(1) * y(2);
end
options = odeset('RelTol',1e-4,'AbsTol',[1e-4 1e-4 1e-5]);
[T,Y] = ode45(#rigid,[0 12],[0 1 1],options);
plot(T,Y(:,1),'-',T,Y(:,2),'-.',T,Y(:,3),'.')
that could be used as a blueprint. In the related page https://de.mathworks.com/help/matlab/math/ordinary-differential-equations.html they use a different syntax closer to yours for the van der Pol Equation in the first example
function dydt = vdp1(t,y)
dydt = [y(2); (1-y(1)^2)*y(2)-y(1)];
end
[t,y] = ode45(#vdp1,[0 20],[2; 0]);
plot(t,y(:,1),'-',t,y(:,2),'--')
title('Solution of van der Pol Equation, \mu = 1');
xlabel('time t');
ylabel('solution y');
legend('y_1','y_2')
Following these examples, rewrite your code as
G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;
function dotx = dxdn(n,x)
t1 = n*(x1-n)
t2 = x(2)*(1 - z * x(2))
den123 = ( G * x(3) - (x(1) - n)^2 * t2)
k1 = ( x(1)*t1*t2 - 2 * x(3) * n *(1 - z * x(2)) - x(4)^2 * t2- G *x(3) *x(2) ) / (den123*n);
k2 = ( t2*(x(1) * x(2) * ( x(1) - 2 *n)*( x(1) - n) + 2* x(3) * n + x(4)^2 * x(2) ) ) / (den123 * t1);
k3 = ( x(3) * (2 * n * x(1) - n)^2 * t2 + G * x(1) * (x(1) - 2 *n)* (x(1) - n) + x(4)^2 * G ) / (den123*t1);
k4 = ( x(4) * ( x(1) + n) ) / t1;
k5 = - x(5) / t1;
dotx = [k1; k2; k3; k4; k5];
end
[n,xa] = ode45(#dxdn,[0.001 1],[1-b; 1/b; 1-b; 0.01; 0.02]);
Because of the division by zero at n=0 you can not start the iteration in that singularity. In the code above, this is mitigated by starting with some (very) small positive n, you can also try starting with n=1e-8 or smaller. The slope will be very large in all components, so the integration may be slow, and the result might be not overly exact close to zero. For the correct handling of singular ODE ask in the math.stackexchange forum.
I have two lines y1 = -a1*x1 + c1 for theta =30 and y1 = -a2*x1 + c2 for theta = 45
is it possible to interpolate a equation for y1 for theta between 30 and 45 in matlab ? The lines are almost parallel to each other. Anyone has an easy way of doing this?
You can interpolate the coeff a and c:
w = (theta - 30) / (45 - 30 ); % w = 0 for theta = 30 and w = 1 for theta = 45
aTheta = a2 * w + a1 * ( 1 - w );
cTheat = c2 * w + c1 * ( 1 - w );
yTheta = -aTheta * x + cTheta * y;
x = 1:10;
a30 = 1;
a45 = 1.1;
c30 = 0;
c45 = 3;
y30 = -a1*x + c1;
y45 = -a2*x + c2;
Now to find y40 we can just interpolate the curve parameters (i.e. slope (a) and offset (c))
a40 = interp1([30,45], [a30, a45], 40);
c40 = interp1([30,45], [c30, c45], 40);
And now our interpolated y40 is
y40 = -a40*x + c40;
plot(x,y30,x,y45,x,y40);