Make matlab code more efficient - matlab

Just started to code in matlab because I am studying the book An Introduction to Financial Option Valuation by Higham. One of the example codeblocks he gives (this is the source) is:
V = zeros(M,1);
Vanti = zeros(M,1);
for i = 1:M
samples = randn(N,1);
% standard Monte Carlo
Svals = S*cumprod(exp((r-0.5*sigma^2)*Dt+sigma*sqrt(Dt)*samples));
Smax = max(Svals);
if Smax < B
V(i) = exp(-r*T)*max(Svals(end)-E,0);
end
% antithetic path
Svals2 = S*cumprod(exp((r-0.5*sigma^2)*Dt-sigma*sqrt(Dt)*samples));
Smax2 = max(Svals2);
V2 = 0;
if Smax2 < B
V2 = exp(-r*T)*max(Svals2(end)-E,0);
end
Vanti(i) = 0.5*(V(i) + V2);
end
I am trying to get this loop more efficient, so I am trying to remove the for loop. This is what I wrote so far:
V = zeros(M,1);
Vanti = zeros(M,1);
samples = randn(N,M);
Svals = S*cumprod(exp((r-0.5*sigma^2)*Dt+sigma*sqrt(Dt)*samples));
Svals2 = S*cumprod(exp((r-0.5*sigma^2)*Dt-sigma*sqrt(Dt)*samples));
Send = Svals(end,:);
Send2 = Svals2(end,:);
Smax = max(Svals);
Smax2 = max(Svals2);
V2 = zeros(M,1);
for i = 1:M
if Smax(i) < B
V(i) = exp(-r*T)*max(Send(i)-E,0);
end
if Smax2(i) < B
V2(i) = exp(-r*T)*max(Send2(i)-E,0);
end
end
Vanti = 0.5*(V + V2);
aM = mean(V); bM = std(V);
conf = [aM - 1.96*bM/sqrt(M), aM + 1.96*bM/sqrt(M)]
aManti = mean(Vanti); bManti = std(Vanti);
confanti = [aManti - 1.96*bManti/sqrt(M), aManti + 1.96*bManti/sqrt(M)]
toc
This already made the code significantly quicker, because there aren't any randn variables generated inside the loop. I don't know however, how I am able to remove the other part of the loop. Is it even possible?

Related

How to manually code 1-norm regression as a matlab function, using the below algorithm

I am not sure if what I have done so far is correct, and I need help with the iterative step as I don't understand what is going on in the algorithm. Here is my code. Help to finish this would be much appreciated. Thank you
function x_opt = out(A,b)
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
b_vect = b';
m = size(A,1);
n = size(1,A);
set_B = 1:n;
set_B_Comp = n+1:m;
M = inv(A(set_B, :));
is_opt = 0;
x_temp = M*b_vect(set_B);
h = A*x_temp - b_vect;
y_vect = zeros(m, 1);
y_vect(set_B_Comp) = sign(h(set_B_Comp));
y_vect(set_B) = -inv(A(set_B, :))*(A(set_B_Comp, :))'*y_vect(set_B_Comp);
abs_y_B = abs(y_vect(set_B));
if all(abs_y_B <= 1)
x_opt = x_temp;
...
else
all_index_y_vect_more_than_1 = find(abs(y_vect) >= 1);
set_B_index_y_vect_more_than_1 = intersect(set_B, all_index_y_vect_more_than_1);
s = set_B_index_y_vect_more_than_1(1);
y_s = y(s)
t_vect = zeros(m, 1);
temp = inv(A(set_B,:));
t_vect(set_B_Comp) = -(sign(y_s))*(y(set_B_Comp)).*(A(set_B_Comp, :)*temp(:, s));
cur_min = h(set_B_Comp(1))/t_vect(set_B_Comp(1)) + 1;
cur_r = set_B_Comp(1);
for j = set_B_Comp
h_j = h(j);
t_j = t_vect(j);
temp1 = abs(h_j)/t_j;
if (temp1 < cur_min) && (temp1 > 0)
cur_min = temp1;
cur_r = j;
end
end
r = cur_r;
set_B_new = union(setdiff(set_B, s), r);
set_B_Comp_new = setdiff(1:m,set_B_new);
x_new = inv(A(set_B_new, :))*b_vect(set_B_new);
end
x_opt = x_temp;
end
I don't understand what's going on in your algorithm either. It's written without comments or explanations.
However, you can model your problem as a convex optimization problem. A formulation in Python using cvxpy is then quite simple and readable:
#!/usr/bin/env python3
import cvxpy as cp
import numpy as np
# Coefficient of regularization
alpha = 1e-4
# Dimensionality
N = 400
d = 20
# Synthetic data
A = np.random.randn(N, d)
b = np.random.randn(N)
# Define and solve the CVXPY problem.
x = cp.Variable(d)
objective = cp.sum_squares(A # x - b) + alpha * cp.norm1(x)
prob = cp.Problem(cp.Minimize(objective))
optval = prob.solve()
# Print result.
print("Optimal value ", optval)
print("The optimal x is")
print(x.value)
print("The norm of the residual is ", cp.norm(A # x - b, p=2).value)
and gives
Optimal value 328.41957961297607
The optimal x is
[-0.02041302 -0.16156503 0.07215877 0.00505087 0.01188415 -0.01029848
-0.0237066 0.0370556 0.02205413 0.00137185 0.04055319 -0.01157271
0.00369032 0.06349145 0.07494259 -0.04172275 0.04376864 0.02698337
-0.04696984 0.05245699]
The norm of the residual is 18.122348149231115

How can it be that a function is outputing a vector with 38 elements and Simulink takes it as one element?

In the Simulink model below my interpreted function output is a vector with 38 elements. I have two functions that have the same outputs one of them works perfectly (desiredtrajectory_sim.m) but the other one doesn't (desiredtrajectory.m).
Any suggestions. thanks
Here is the Simulink model
function [desired_state] = desiredtrajectory_sim(in)
t = in(1);
Sf = [ 1; 2; pi/4];
dSf = [0;0;0];
Pf = [ 0.1*t; 0; 0.5*sin(0.03*pi*t) + 2; 0; 0.01*pi*t ; 0];
dPf = [ 0.1; 0; 0.5*0.03*pi*cos(0.03*pi*t); 0; 0.01*pi; 0];
pf = Sf(1); qf = Sf(2); betaf = Sf(3);
xf = Pf(1); yf = Pf(2); zf = Pf(3);
phif = Pf(4); thetaf = Pf(5); psif = Pf(6);
rf = sqrt(pf^2 + qf^2 - 2*pf*qf*cos(betaf));
h1 = sqrt(0.5*(pf^2 + qf^2 - 0.5*rf^2));
h2 = sqrt(0.5*(rf^2 + pf^2 - 0.5*qf^2));
h3 = sqrt(0.5*(qf^2 + rf^2 - 0.5*pf^2));
alpha1 = acos((4*(h1^2+h2^2)-9*pf^2)/(8*h1*h2));
alpha2 = acos((4*(h1^2+h3^2)-9*qf^2)/(8*h1*h3));
Rot = RPYtoRot_ZXY(phif, thetaf, psif);
r1 = Rot*[2/3*h1;0;0];
r2 = Rot*[2/3*h2*cos(alpha1);2/3*h2*sin(alpha1);0];
r3 = Rot*[2/3*h3*cos(alpha2);-2/3*h3*sin(alpha2);0];
pos_des1 = [xf;yf;zf] + r1;
pos_des2 = [xf;yf;zf] + r2;
pos_des3 = [xf;yf;zf] + r3;
omega = [0 -sin(psif) cos(thetaf)*cos(psif);...
0 -cos(psif) cos(thetaf)*sin(psif);...
1 0 -sin(thetaf)]*dPf(4:6);
vel_des1 = dPf(1:3) + cross(omega, r1);
vel_des2 = dPf(1:3) + cross(omega, r2);
vel_des3 = dPf(1:3) + cross(omega, r3);
acc_des = [0;0;0];
desired_state1 = [pos_des1;vel_des1;acc_des];
desired_state2 = [pos_des2;vel_des2;acc_des];
desired_state3 = [pos_des3;vel_des3;acc_des];
desired_state = [desired_state1;desired_state2;desired_state3; psif; 0; Pf;
Sf]
size(desired_state)
end
Here is the Simulink block and the error message
As you can notice the bus gives just one element compared to the previous one which gives 38 elements, although they have the same output.
function [desired_state] = desiredtrajectory(in)%(t, pos)
tm= in(1)
pos = in(2:10);
syms t xf yf zf phif thetaf psif pf qf betaf
rf = sqrt(pf^2+qf^2-2*pf*qf*cos(betaf));
h1 = sqrt(0.5*(pf^2+qf^2-0.5*rf^2));
h2 = sqrt(0.5*(rf^2+pf^2-0.5*qf^2));
h3 = sqrt(0.5*(qf^2+rf^2-0.5*pf^2));
alf1 = acos((4*(h1^2+h2^2)-9*pf^2)/(8*h1*h2));
alf2 = acos((4*(h1^2+h3^2)-9*qf^2)/(8*h1*h3));
Rot = RPYtoRot_ZXY(phif, thetaf, psif);
eps = [Rot*[2/3;0;0]+[xf;yf;zf]
Rot*[2/3*h2*cos(alf1);2/3*h2*sin(alf1);0]+[xf;yf;zf]
Rot*[2/3*h2*cos(alf2);-2/3*h3*sin(alf2);0]+[xf;yf;zf]];
X = [ xf yf zf phif thetaf psif pf qf betaf];
Sf = [ 1; 2; pi/4];
dSf = [0;0;0];
Pf = [ 0.1*t; 0; 0.5*sin(0.03*pi*t) + 2; 0; 0.01*pi*t ; 0];
dPf = [ 0.1; 0; 0.5*0.03*pi*cos(0.03*pi*t); 0; 0.01*pi; 0];
qd = [Pf; Sf];
qddot = [dPf; dSf];
jac = jacobian(eps,X);
%%%%%%%%%%%%%
pf = Sf(1); qf = Sf(2); betaf = Sf(3);
xf = Pf(1); yf = Pf(2); zf = Pf(3);
phif = Pf(4); thetaf = Pf(5); psif = Pf(6);
x1=pos(1);
y1=pos(2);
z1=pos(3);
x2=pos(4);
y2=pos(5);
z2=pos(6);
x3=pos(7);
y3=pos(8);
z3=pos(9);
qpf=[(x1+x2+x3)/3;...
(y1+y2+y3)/3;...
(z1+z2+z3)/3;...
atan2((2*z1/3-z2/3-z3/3),(2*y1/3-y2/3-y3/3)); ...
-atan2((2*z1/3-z2/3-z3/3),(2*x1/3-x2/3-x3/3)); ...
atan2((2*y1/3-y2/3-y3/3),(2*x1/3-x2/3-x3/3))];
qsf=[sqrt((x1-x2)^2+(y1-y2)^2+(z1-z2)^2); ...
sqrt((x1-x3)^2+(y1-y3)^2+(z1-z3)^2); ...
acos((pf^2+qf^2-rf^2)/(2*pf*qf))];
q = [qpf;qsf];
%%%%%%%%%%%%%
%%%pos_desired%%%%%%%
pos_des = eval(eps);
pos_des =subs(pos_des,t,tm);
jacval = eval(jac);
qd = eval(qd);%subs(qd,t,tm);
q = eval(q);
qe = qd - q;
qddot = eval(qddot);%subs(qddot,t,tm);
kappa=0.2*eye(9);
qrefdot = qddot + kappa*qe;
vel_des = jacval*qrefdot;
vel_des = subs(vel_des,t,tm);
acc_des = zeros(3,1);
yaw = 0;
yawdot = 0;
% =================== Your code ends here ===================
desired_state1 = [pos_des(1:3);vel_des(1:3);acc_des];
desired_state2 = [pos_des(4:6);vel_des(4:6);acc_des];
desired_state3 = [pos_des(7:9);vel_des(7:9);acc_des];
Pf = subs(Pf,t,tm);
Sf = subs(Sf,t,tm);
format short
digits(3);
desired_state = vpa([desired_state1;desired_state2;desired_state3; psif; 0;
Pf; Sf])
size(desired_state)
end
The second image shows that the output of the second function is a scalar - the dimension at the output of the block is 1 - not 38 as you believe it is.
That is, your functions do not give the same output as you believe they do.
The error is because the Selector blocks expect their inputs to be dimension 38, and they are not.
To determine why what you believe is happening is not actually what is happening, you could use the editor to set a break point in the m-code, run the model, then step through the code to determine why it gives a scalar output when you expect it to do otherwise.
Another approach would be to run your functions from the MATLAB Command Line with fake input data. Something like
tmp = desiredtrajectory(randn(10,1))
would be appropriate here.
The answer is that desiredtrajectory outputs desired_state, which is a symbolic variable. Yes it contains a 38 element vector, but Simulink treats the object itself is a scalar.
The real problem though is that you can't propagate a symbolic variable down a Simulink signal. You need the output to be a numeric vector.
One way to overcome this is to put the line
desired_state = double(desired_state);
at the end of your file to cast the symbolic object to a double, which will have 38 elements.
(However it's not clear why you are using symbolic math in the first place, and I'd suggest it would be better, and is certainly more efficient, if you didn't use it.)

Why do I get such a bad loss in my implementation of k-Nearest Neighbor?

I'm trying to implement k-NN in matlab. I have a matrix of 214 x's that have 9 columns of attributes with the 10th column being the label. I want to measure loss with a 0-1 function on 10 cross-validation tests. I have the following code:
function q3(file)
data = knnfile(file);
loss(data(:,1:9),'KFold',data(:,10))
losses = zeros(25,3);
new_data = data;
new_data(:,10) = [];
sdd = std(new_data);
meand = mean(new_data);
for s = 1:214
for q = 1:9
new_data(s,q) = (new_data(s,q) - meand(q)) / sdd(q);
end
end
new_data = [new_data data(:,10)];
for k = 1:25
loss1 = 0;
loss2 = 0;
for j = 0:9
index = floor(214/10)*j+1;
curd1 = data([1:index-1,index+21:end],:);
curd2 = new_data([1:index-1,index+21:end],:);
for l = 0:20
c1 = knn(curd1,k,data(index+l,:));
c2 = knn(curd2,k,new_data(index+l,:));
loss1 = loss1 + (c1 ~= data(index+l,10));
loss2 = loss2 + (c2 ~= new_data(index+l,10));
end
end
losses(k,1) = k;
losses(k,2) = 100*loss1/210;
losses(k,3) = 100*loss2/210;
end
function cluster = knn(Data,k,x)
distances = zeros(193,2);
for i = 1:size(Data,1)
row = Data(i,:);
d = norm(row(1:size(row,2)-1) - x(1:size(x,2)-1));
distances(i,:) = [d row(10)];
end
distances = sortrows(distances,1);
cluster = mode(distances(1:k,2));
I'm getting 40%+ loss with almost no correlation to k and I'm sure that something here is wrong but I'm not quite sure.
Any help would be appreciated!

Using Fast Fourier Transform on matlab?

I am having some difficulty in solving a simple 2D Poisson equation in Matlab using spectral methods in one direction on finite difference in the other.
I am obtaining a scaled version of the correct answer but can't work out why although I think it has something to do with the wavenumber.
Any help would be greatly appreciated, the code can be seen below.
N = 32;
x = ((0:N-1)/N)*2*pi;
y = ((0:N-1)/N)*2*pi;
dx = 2*pi/N;
k = fftshift(-N/2:N/2-1);
[X,Y] = meshgrid(x,y);
f = (-2)*cos(X).*sin(Y);
f_comparison = cos(X).*sin(Y);
checker = 10;
u = zeros(N,N);
u_new = zeros(N,N);
f_hat = fftn(f);
while checker > 1*10^(-7);
u_new_hat = fftn(u_new);
for aa = 1:N
for a = 1:N
q1 = a+1;
q2 = a-1;
if q2 == 0
q2 = N;
end
if q1 == N+1
q1 = 1;
end
denom = ((dx^2)*((k(aa))^2))+2;
u_new_hat(a,aa) = (1/denom)*((u_new_hat(q1,aa))+(u_new_hat(q2,aa))-((f_hat(a,aa))*(dx^2)));
end
end
u_new = real(ifftn(u_new_hat));
for aa = 1:N
for a = 1:N
u_checker(a,aa) = abs(u_new(a,aa)-u(a,aa));
end
end
compare = max(u_checker);
checker = max(compare);
for aa = 1:N
for a = 1:N
u(a,aa) = u_new(a,aa);
end
end
end
%calculate scaling discrepency
ddd = f_comparison./u;

Matlab. Create a loop to change variable size with each iteration

I am currently trying to run a script that calls a particular function, but want to call the function inside a loop that halfs one of the input variables for roughly 4 iterations.
in the code below the function has been replaced for another for loop and the inputs stated above.
the for loop is running an Euler method on the function, and works fine, its just trying to run it with the repeated smaller step size im having trouble with.
any help is welcomed.
f = '3*exp(-x)-0.4*y';
xa = 0;
xb = 3;
ya = 5;
n = 2;
h=(xb-xa)/n;
x = xa:h:xb;
% h = zeros(1,4);
y = zeros(1,length(x));
F = inline(f);
y(1) = ya;
for j = 1:4
hOld = h;
hNew = hOld*0.5;
hOld = subs(y(1),'h',hNew);
for i = 1:(length(x)-1)
k1 = F(x(i),y(i));
y(i+1,j+1) = y(i) + h*k1;
end
end
disp(h)
after your comment, something like this
for j = 1:4
h=h/2;
x = xa:h:xb;
y = zeros(1,length(x));
y(1) = ya;
for i = 1:(length(x)-1)
k1 = F(x(i),y(i));
y(i+1,j+1) = y(i) + h*k1;
end
end