How do you use the numjac function in MATLAB? - matlab

The documentation online for this particular function is poor, and I was looking for an example on how to use it. It seems to take in 9+ arguments, but I'm not entirely sure what they even are. I am working on implementing function using the trapezoidal rule, however, I am missing the functions that compute the partial derivatives with respect to y and t. I believe that calculating one for t in MATLAB is another case, but here, I'm just trying to use MATLAB to compute it for y.
I'm using the following input initially:
func = #(t,y)(y.^2+y+t);
interval = [0 1];
y0 = 0;
[steps, derivY, derivJ, W, inverseW] = getTrapezoidalODEValues(func, interval, y0)
I set up the function like this:
function [h,J,T,W,iW] = getTrapezoidalODEValues(odefun,tspan,y0,options)
if (nargin==3)
options = odeset();
end
h = NaN; J(0) = NaN; T(0) = NaN; W(0) = NaN; iW = NaN;
[t,yy] = ode(odefun,tspan,y0,options);
[nstep,ndim] = size(yy);
d = 1/(2+sqrt(2));
for j=2:nsteps
h = t(j)-t(j-1);
I = eye(???,???); % identity matrix
quadpoly = ???; % the quadratic polynomial
J(j-1) = numjac(???); % <--partial derivative of odefun with respect to y
T(j-1) = ???; % partial derivative of odefun with respect to t
W(j-1) = I - h .* d .* J;
iW(j-1) = inv(W(j-1));
end
end

Related

How to plot and define with Matlab a function defined on different subintervals, which enters an ODE

I am trying to plot and then to use it with Matlab
in an ODE as coefficient, the function
f : [2,500] -> [0,1],
But I don't know how to write the code for the definition of the function, since it is given on different subintervals.
Below is an example that uses anonymous functions/function handles. It uses each region/condition and evaluates the boundaries numerically and stores them into variables Bounds_1 and Bounds_2. These boundaries are then used to truncate each signal by multiplying each section of the piecewise function by its corresponding condition which is a logical array. It's also good to note that this plot will almost be seen as an impulse since the bounds are really small. Alternatively, you can probably achieve the same results using the built-in piecewise() function but I think this method gives a little more insight. As i increases you'll see a plot that resembles more and more of an impulse. To plot this for multiple values or i this can be run in a for-loop.
clc;
i = 3;
Bounds_1 = [i - (1/i^2),i];
Bounds_2 = [i,i + (1/i^2)];
Bounds = [Bounds_1 Bounds_2];
Min = min(Bounds);
Max = max(Bounds);
f1 = #(x) (i^2.*x - i^3 + 1).*(Bounds_1(1) < x & x <= Bounds_1(2));
f2 = #(x) (-i^2.*x + i^3 + 1).*(Bounds_2(1) < x & x <= Bounds_2(2));
f = #(x) f1(x) + f2(x);
fplot(f);
xlim([Min-2 Max+2]);
ylim([0 1.1]);
Here is another solution. You can specify the steps along the x-axis withxstep. With xlower and xupper you can specify the range of the x-axis:
figure ; hold on;
xlabel('x'); ylabel('f(x)');
for i= 2:500
[f,x] = myfunction(0.5,i);
plot (x,f,'DisplayName',sprintf('%i',i));
end
% legend
function [f,x]=myfunction(xstep,i)
%xstep: specifies steps for the x values
% specify max range x \in = [xlower -> xupper]
xlower = -10;
xupper = 600;
x2 = (i-1/i^2): xstep: i;
f2 = i^2*x2 - i^3 + 1;
x3 = i+xstep:xstep:(1+1/i^2);
f3 = -i^2*x3 + i^3 +1;
x1 = xlower:xstep:(i-1/i^2);
f1 = 0*x1;
x4 = (i+1/i^2):xstep:xupper;
f4 = 0*x4;
f = [f1,f2,f3,f4];
x = [x1,x2,x3,x4];
end
Here is what I get
Besides, I am not exactly sure what you mean with ODE (ordinary differential equation) in f(x). For me it seems like an algebraic equation.

Unable to perform assignment because the size of the left side is 1-by-2 and the size of the right side is 2-by-2

the code tries to implement the Euler's method and improve Euler's method to second order differential equations but there is a dimensionality error with the ys values array which store the values of y and dy
f=#(x,y) [y(2); (2/x)*y(2)-(2/x^2)*y(1)]; % function through a function handle
x0 = 1; y0 = [4,9]; xf=2; % IC
% Improve and Euler's Method
[xs,ys] = ode45(f,[x0,xf],y0);
[xsi1,ysi1] = Ieuler(f,[x0,xf],y0,0.1);
[xse1,yse1] = euler(f,[x0,xf],y0,0.1);
[xsi2,ysi2] = Ieuler(f,[x0,xf],y0,0.5);
[xse2,yse2] = euler(f,[x0,xf],y0,0.5);
% plotting all solutions
plot(xsi1,ysi1(:,1),'-b','LineWidth',1.5); hold on;
plot(xse1,yse1(:,1),'-r','LineWidth',1.5); hold on;
plot(xsi2,ysi2(:,1),'-g','LineWidth',1.5); hold on;
plot(xse2,yse2(:,1),'-k','LineWidth',1.5); hold on;
plot(xs,ys(:,1),'-b','LineWidth',1.5); hold on;
axis([0 xf -0.1 4]); xlabel('x');ylabel('y')
In the second part of the code are the constructed function to implement Euler's method
%Function calls
% function: Euler's Method implementation
function [xs,ys] = euler(f,xv,y0,h)
x0 = xv(1); X = xv(2);
N = (X-x0)/h;
xs = zeros(N+1,1); ys = zeros(N+1,length(y0));
x = x0; y = y0;
xs(1) = x; ys(1,:) = y';
for i = 1:N
s1 = f(x,y); %evaluate direction field at current point
y= y+s1*h; %find new y
x = x+h;
xs(i+1) = x; ys(i+1,:) = y'; %store y(1), y(2) in a row array
end
end
% function: Improved Euler's Method implementation
function [xs,ys] = Ieuler(f,xv,y0,h)
x0 = xv(1); X = xv(2);
N = (X-x0)/h;
xs = zeros(N+1,1); ys = zeros(N+1,length(y0));
x = x0; y = y0;
xs(1) = x; ys(1,:) = y';
for i = 1:N
s1 = f(x,y); %evaluate direction field at current point
yE= y+s1*h; %find Euler value yE
s2 = f(x+h,yE); %evalute direction field at Euler point
y = y + h*((s1+s2)/2); *%find new y*
x = x+h;
xs(i+1) = x; ys(i+1,:) = y'; *%store y(1), y(2) in a row array*
end
end
Unable to perform assignment because the size of the left side is 1-by-2 and the
size of the right side is 2-by-2.
Error in Untitled>Ieuler (line 63)
xs(i) = x; ys(i,:) = y';
Error in Untitled (line 20)
[xsi1,ysi1] = Ieuler(f,[x0,xf],y0,0.1);
stop writing several logic lines (terminated with a ;) in one text
line. It is not even clear, which command causes the error, since
there are two in this line! (BTW, it is this ys(i+1,:) = y';)
strip your code. You should provide a minimal reproducible example
(its not an art contest... and as the error occurs in Ieuler the rest is not necessary).
your error is: that your function handle ´f´ returns a vector, but y is an array => you'll get a matrix, which you want to assign to an array ys(i+1,:) = y' (for whatever reason you are transposing this). solution: let f return an array: f=#(x,y) [y(2), (2/x)*y(2)-(2/x^2)*y(1)]; (note the comma) or transpose its return value s1 = f(x,y).'; (its good practice to use the .' for non-complex transpositions -- for clarity.
Advice: have a look how to debug in MATLAB. You probably could have tracked this down by placing a breakpoint just before the line where the error occurs (or even activate Pause on Errors) and checking the dimensions.

Producing nonlinear function to be optimized in MATLAB

I am attempting to minimize this nonlinear function
using the BFGS optimization method in MATLAB. However, I am having a terrible time figuring out how to code the function for n=500. I have tried these variations with no luck:
1)
S_symsum = #(x) (100*(x(2*(1:250))-x(2*(1:250)-1)^2)^2+(1-x(2*(1:250)-1))^2);
2)
k = 1:N/2;
V = (100*(x(2*k)-x(2*k-1).^2).^2+(1-x(2*k-1)).^2);
f = sum(V);
3)f = symsum(100*(x(2*k)-x(2*k-1).^2).^2+(1-x(2*k-1)).^2,k,1,500)
EDIT: As the BFGS method necessitates, I will need to be able to take the gradient of the function f at each iterate. So, the function formulation will need to hold this property
I use N = 10 for illustration, just change it to 500 for your optimization.
% given length of x, here N
N = 10;
% supposed x is a row vector
x = sym('x', [1,N]);
f = 0;
for i = 1:N/2
f = f + 100.*(x(2*i) - (x(2*i-1)).^2) + (1-x(2*i-1)).^2;
end
% gradient
% to compute gradient, use syms function type
g = gradient(f);
% for evaluating the function or the gradient use function handle
feval = matlabFunction(f, 'vars', {x});
geval = matlabFunction(g, 'vars', {x});

How to convert this code into function in MATLAB so I may just use it by calling it

% Code slightly modified from Signals and Systems by Lathi MS2P4 pg 232.
How can I make this code a function? So that I can just "call" it to use it. Instead of pasting this whole thing over and over. This is just a convolution animation of two functions.
figure(1) % Create figure window and make visible on screen
x = #(t) cos(2*pi*3*t).* u(t);
h = #(t) u(t)-u(t-1);
dtau = 0.005;
tau = -1:dtau:4;
ti = 0;
tvec = -1:0.1:5;
y = NaN*zeros(1,length(tvec)); % Pre-allocate memory
for t = tvec,
ti = ti + 1; % Time index
xh = x(t-tau).*h(tau);
lxh = length(xh);
y(ti) = sum(xh.*dtau); % Trapezoidal approximation of integral
subplot(2,1,1)
plot(tau,h(tau),'k-',tau,x(t-tau),'k--',t,0,'ok')
axis([tau(1) tau(end) -2.0 2.5])
patch([tau(1:end-1);tau(1:end-1);tau(2:end);tau(2:end)],...
[zeros(1,lxh-1);xh(1:end-1);xh(2:end);zeros(1,lxh-1)],...
[0.8 0.8 0.8],'edgecolor','none')
xlabel('\tau')
legend('h(\tau)','x(t-\tau)','t','h(\tau)x(t-\tau)')
c = get(gca,'children');
set(gca,'children',[c(2);c(3);c(4);c(1)]);
subplot(2,1,2)
plot(tvec,y,'k',tvec(ti),y(ti),'ok')
xlabel('t')
ylabel('y(t) = \int h(\tau)x(t-\tau) d\tau')
axis([tau(1) tau(end) -1.0 2.0])
grid
drawnow
% pause
end
You can use Matlab's function , as described here
So, you have to write on the top "function yourFunctionName" and then you can call it using its name, yourFunctionName in this case.
Here is what worked with your exact code, a straightforward function definition and the addition of u(t) that was missing from the OP:
figure(1) % figure window outside function
u = #(t)heaviside(t); % define step function
x = #(t) cos(2*pi*3*t).* u(t);
h = #(t) u(t)-u(t-1);
dtau = 0.005;
convol_anime(x, h, dtau); % pass function handles + parameters
where you have already defined:
function convol_anime(x, h, dtau)
tau = -1:dtau:4; ti = 0; tvec = -1:0.1:5;
y = nan*zeros(1,length(tvec));
...

Error using fmincon (line 300) A must have 'n' column(s)

I'm getting the error "Error using fmincon (line 300) A must have 'n' column(s)." when trying to solve the following optimisation code. I think there is an error in the definition of the constraints. Someone had the same problem http://goo.gl/35MeC but unfortunately I don't read chinese!!
The objective is to find the optimal values of the array Y subject to constraints on Y and on its integral IntY. To understand better the nature of the problem, each value of Y represent the value of a variable in a successive time step, and the objective function to minimise is basically a cost of interactions.
function [Y, IntY] = optTest()
% inputs of the problem
TS = 10; % number of time steps
YMin = -0.1; % minimum value of Y
YMax = 0.2; % maximum value of Y
IntYMin = 0.1; % min value of the integral of Y
IntYMax = 0.9; % max value of the integral of Y
IntYInit = 0.2; % initial value of the integral of Y
Prices = PricesFun(TS);
% use of function 'fmincon', preparation of the inputs
% x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub)
A = [tril(ones(TS))*1;tril(ones(TS))*-1];
b = [ones(TS,1)*(IntYInit-IntYMin);ones(TS,1)*(IntYMax-IntYInit)];
lb = ones(TS,1)*YMax;
ub = ones(TS,1)*YMin;
Y0 = ones(TS)*IntYInit;
Y = fmincon(#(x) costFun(x, Prices),Y0,A,b,[],[],lb,ub);
IntY = cumsum(Y);
function cost = costFun(x, Prices)
cost = sum(x*Prices);
function P = PricesFun(TS)
x = linspace(1,TS,TS);
pi = 3.1415;
P = 2 + sin(x/TS*4*pi);
The code above is self contained, if you want to try, you have just to paste it in matlab and call the function:
[Y, IntY] = optTest();
Your initial guess Y0 is what defines the number of variables involved in the optimization. You are inputting a TS x TS square matrix for Y0, which would require TS*TS linear constraints. Given that you're using column vectors for lb and ub, I assume you meant to create Y0 as a column vector as well, or Y0 = ones(TS,1)*IntYInit;