Finding the Optimum Input for a Simulation in Matlab - matlab

I have the following simulation running in Matlab. For a period of 25 years, it simulates "Assets", which grow according to geometric brownian motion, and "Liabilities", which grow at a fixed rate of 7% each year. At the end of the simulation, I take the ratio of Assets to Liabilities, and the trial is successful if this is greater than 90%.
All inputs are fixed except for Sigma (the standard deviation). My goal is to find the lowest possible value of sigma that will result in a ratio of assets to liabilities > 0.9 for every year.
Is there anything in Matlab designed to solve this kind of optimization problem?
The code below sets up the simulation for a fixed value of sigma.
%set up inputs
nPeriods = 25;
years = 2016:(2016+nPeriods);
rate = Assumptions.Returns;
sigma = 0.15; %This is the input that I want to optimize
dt = 1;
T = nPeriods*dt;
nTrials = 500;
StartAsset = 81.2419;
%calculate fixed liabilities
StartLiab = 86.9590;
Liabilities = zeros(size(years))'
Liabilities(1) = StartLiab
for idx = 2:length(years)
Liabilities(idx) = Liabilities(idx-1)*(1 + Assumptions.Discount)
end
%run simulation
obj = gbm(rate,sigma,'StartState',StartAsset);
%rng(1,'twister');
[X1,T] = simulate(obj,nPeriods,'DeltaTime',dt, 'nTrials', nTrials);
Ratio = zeros(size(X1))
for i = 1:nTrials
Ratio(:,:,i)= X1(:,:,i)./Liabilities;
end
Unsuccessful = Ratio < 0.9
UnsuccessfulCount = sum(sum(Unsuccessful))

First make your simulation a function that takes sigma as the input:
function f = asset(sigma)
%set up inputs
nPeriods = 25;
years = 2016:(2016+nPeriods);
rate = Assumptions.Returns;
%sigma = %##.##; %This is the input of the function that I want to optimize
dt = 1;
T = nPeriods*dt;
nTrials = 500;
StartAsset = 81.2419;
%calculate fixed liabilities
StartLiab = 86.9590;
Liabilities = zeros(size(years))'
Liabilities(1) = StartLiab
for idx = 2:length(years)
Liabilities(idx) = Liabilities(idx-1)*(1 + Assumptions.Discount)
end
%run simulation
obj = gbm(rate,sigma,'StartState',StartAsset);
%rng(1,'twister');
[X1,T] = simulate(obj,nPeriods,'DeltaTime',dt, 'nTrials', nTrials);
Ratio = zeros(size(X1))
for i = 1:nTrials
Ratio(:,:,i)= X1(:,:,i)./Liabilities;
end
Unsuccessful = Ratio < 0.9
UnsuccessfulCount = sum(sum(Unsuccessful))
f = sigma + UnsuccessfulCount
end
Then you can use fminbnd (or fminsearch for multiple inputs) to find the minimized value of sigma.
Sigma1 = 0.001;
Sigma2 = 0.999;
optSigma = fminbnd(asset,Sigma1,Sigma2)

Related

Triangle Pulse with fourier transformation

I have a basic exercise for telecommunications with matlab, and i must plot a triangle pulse with (-c,0) to (c,0) with c = 6 and Amplitude = 1 in a for loop for M pulses and approach the periodic pulse using N Fourier series terms. I can't find something on the internet that can help me so far.
A similar code for rect pulse that I made and works is this:
a = 1;
b = 3;
N = 1000;
t = linspace(a-2*a,b+2*b,N);
A = 1;
y = rect_pulse(A,a,b,t);
plot(t,y);
grid on
axis([a-2*a b+2*b 0 2*A]);
M = 5;
T=7;
t_new = linspace(a-2*a,b+(M-1)*T+2*b,N);
y_new = zeros(1,N);
for index = 1:1:M
temp_y = rect_pulse(A,a+(index-1)*T,b+(index-1)*T,t_new);
y_new = y_new + temp_y;
end
figure;
plot(t_new,y_new);
grid on;
axis([a-2*a b+(M-1)*T+2*b 0 2*A]);
Where rect_pulse is this:
function y = rect_pulse (A,a,b,t)
N=length(t);
y = zeros(1,N);
for index = 1:1:N
if(t(1,index)>=a) && (t(1,index)<=b)
y(1,index) = A;
end
end
And fourier series is this:
function y_fourier = fourier_series_rect_pulse(a,b,To,N,t)
y_fourier = 0;
wo = (2*pi)/To;
for n = -N:1:N
f_real = #(x) cos(n*wo*x);
f_imag = #(x) sin(n*wo*x);
cn = (1/To)*(quad(f_real,a,b)) - j*quad(f_imag,a,b));
y_fourier = y_fourier + cn*exp(j*n*wo*t);
end
y_fourier = real(y_fourier);
Any ideas how to make this in to triangle pulse?
This probably deviates significantly from your approach but if you're curious here is a script I came up with to generate a triangular pulse train that can be adjusted. This method, unfortunately, uses the fft() function which may or may not be off-limits in your case. Most of the script uses indexing and manipulating vectors. Additional spectral components may be seen due to the DC offset of the alternating triangular wave and the limited number of cycles available in the vector representation of the triangular wave.
Triangular Pulses and Fourier Transforms:
Triangular Pulse with Duty-Off Period:
Higher frequency spectral components present due to the abrupt corners that occur at the transition states of the triangle pulse and duty-off period.
%******************************************************%
%PROPERTIES THAT CAN BE CHANGED%
%******************************************************%
Plotting_Interval = 0.01; %0.01 seconds%
Pulse_Width = 1/20; %6 seconds%
Period = 1/20; %10 seconds (should be at least the pulse width)%
Start_Time = 0;
End_Time = Pulse_Width*1000; %(1000 pulses)%
%******************************************************%
if(Period < Pulse_Width)
Period = Pulse_Width;
end
Time_Vector = (Start_Time: Plotting_Interval: End_Time);
Points_Per_Unit_Time = 1/Plotting_Interval;
Half_Pulse = Pulse_Width/2;
Number_Of_Points = Pulse_Width/Plotting_Interval;
Rising_Slope = linspace(0,1,floor(Number_Of_Points/2) + 1);
Falling_Slope = 1 - Rising_Slope;
Triangular_Pulse = [Rising_Slope Falling_Slope(2:end)];
t = (0: Plotting_Interval: Pulse_Width);
Periodic_Triangular_Pulse = zeros(1,length(Time_Vector));
for Cycle = 1: +Period/Plotting_Interval: End_Time/Plotting_Interval
Periodic_Triangular_Pulse(1,Cycle:Cycle+length(Triangular_Pulse)-1) = Triangular_Pulse(1,1:end);
end
Periodic_Triangular_Pulse = Periodic_Triangular_Pulse(1,1:length(Time_Vector));
subplot(1,2,1); plot(Time_Vector,Periodic_Triangular_Pulse);
Triangle_Frequency = 1/Period;
title("Triangular Pulse Train " + num2str(Triangle_Frequency) + "Hz (first 10 cycles)");
axis([0 Period*10 0 1]);
xlabel("Time (s)"); ylabel("Amplitude");
Signal_Length = length(Periodic_Triangular_Pulse);
Fourier_Transform = fft(Periodic_Triangular_Pulse);
Fs = 1/Plotting_Interval;
P2 = abs(Fourier_Transform/Signal_Length);
P1 = P2(1:floor(Signal_Length/2)+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(Signal_Length/2))/Signal_Length;
subplot(1,2,2); plot(f,P1)
title("Single-Sided Fourier Transform");
xlabel("Frequency (Hz)"); ylabel("Magnitude");
Ran using MATLAB R2019b

Numerically solving a pde with changing domain in Matlab

I'm trying to implement a changing domain into my Matlab code which solves a pde numerically. In the given problem, I am modelling the baking of bread. It is a 1D problem where there is a single heat source from above. I am using the heat diffusion equation and for a fixed domain, I have provided my code below which solves it. However, I need to also model the rising of the bread, so over time my domain, 'L' in my code, changes. I am told that I can assume it changes linearly over an hour and that the bread initially fills 80% of the tin. What suggestions do you guys have for how I can account for the rising?
close all
clear all
clc
Tend = 3600; %Time to end after
dt = 1; %Time step size
Nstep = (Tend/dt)+1; %Number of time points
M = 1000; %Number of x points
dx = 1/M; %Size of the x steps
L = 1; %Length of domain
x = [0:dx:L]; %Creating the x points
kdiff = 2.7e-4; %Diffusion constant value
R = kdiff*dt/(dx*dx);
for i = 1:M+1
u(i,1) = 20;
end
for n = 1:Nstep
DIG(1) = 1;
b(1) = 200; %Boundry condition
DIG(M+1) = 1;
LF(1) = 0;
RT(1) = 0;
LF(M+1) = -1; %Insulated boundry
RT(M+1) = 0;
b(M+1) = 0; %Boundry condition
for m = 2:M
DIG(m) = 2+(2/R);
LF(m) = -1;
RT(m) = -1;
b(m) = u(m+1,n) + u(m-1,n) + (-2 + (2/R))*u(m,n);
end
u(:,n+1) = tdma(LF,DIG,RT,b,M+1);
end
plot(x,u(:,1:600:end)

Stochastic gradient descent algorithm in MATLAB

I'm trying to implement stochastic gradient descent in MATLAB, but I'm going wrong somewhere. I think that maybe the way I am checking for convergence is incorrect (I wasn't quite sure how to update the estimator with each iteration), but I'm not sure. I've been trying just to fit basic linear data, but I'm getting results that are pretty far off and I'm hoping to get some help. Would someone be able to point out where I'm going wrong, and why this isn't working correctly?
Thanks!
Here is the data set up and general code:
clear all;
close all;
clc
N_features = 2;
d = 100;
m = 100;
X_train = 10*rand(d,1);
X_test = 10*rand(d,1);
X_train = [ones(d,1) X_train];
X_test = [ones(d,1) X_test];
y_train = 5 + X_train(:,2) + 0.5*randn(d,1);
y_test = 5 + X_test(:,2) + 0.5*randn(d,1);
gamma = 0.01; %learning rate
[sgd_est_train,sgd_est_test,SSE_train,SSE_test,w] = stoch_grad(d,m,N_features,X_train,y_train,X_test,y_test,gamma);
figure(1)
plot(X_train(:,2),sgd_est_train,'ro',X_train(:,2),y_train,'go')
figure(2)
plot(X_test(:,2),sgd_est_test,'bo',X_test(:,2),y_test,'go')
and the function that actually implements the SGD is:
% stochastic gradient descent
function [sgd_est_train,sgd_est_test,SSE_train,SSE_test,w] = stoch_grad(d,m,N_features,X_train,y_train,X_test,y_test,gamma)
epsilon = 0.01; %convergence criterion
max_iter = 10000;
w0 = zeros(N_features,1); %initial guess
w = zeros(N_features,1); %for convenience
x = zeros(d,1);
z = zeros(d,1);
for jj=1:max_iter;
for kk=1:d;
x = X_train(kk,:)';
z = gamma*((w0'*x-y_train(kk))*x);
w = w0 - z;
end
if norm(w0-w,2)<epsilon
break;
else
w0 = w;
end
end
sgd_est_test = zeros(m,1);
sgd_est_train = zeros(d,1);
for ll=1:m;
sgd_est_test(ll,1) = w'*X_test(ll,:)';
end
for ii=1:d;
sgd_est_train(ii,1) = w'*X_train(ii,:)';
end
SSE_test = sum((sgd_est_test - y_test).^2);
SSE_train = sum((sgd_est_train - y_train).^2);
end
I tried lowering the learning rate at 0.001 and resulted to this:
Which tells me that your algorithm produces an estimation of the form y=ax instead of y=ax + b (for some reason ignores the constant term) and also you need to lower the learning rate in order to converge.

integral2Calc>integral2t/tensor & Warning: Reached the maximum number of function evaluations (10000)

I am trying to do a set of integrations for a particular value of psi and theta. These integrations are then combined into a formula to give P. The idea is then to do this for a set of psi and theta from 0 to pi/2 and then plot the results of P against a function of theta and psi.
I get two errors, firstly
integral2Calc>integral2t/tensor
not sure how to change the integral to make it the right dimensions to psi no longer being a scalar.
I also get Warning: Reached the maximum number of function evaluations (10000) for i3, is this a serious error, (as in has the integration not been computed) I tried changing the type of integration or changing the error tolerance and this seemed to have no effect on removing the actual error..
eta = input('Enter Dielectric Constant 1.5-4: ');
sdev = input('Enter STD DEV (roughness) maybe 0.1: ');
psi = [0:0.01:pi/2];
theta = [0:0.01:pi/2];
r = sqrt((sin(psi)).^2+(sin(theta).*(cos(psi))).^2);
calpha = (cos(theta+dtheta)).*(cos(psi+dpsi));
rp01 = calpha-sqrt(eta-1+((calpha).^2));
rp02 = calpha+sqrt(eta-1+((calpha).^2));
rperp = (rp01./rp02).^2;
rp11 = ((eta.*calpha)-sqrt(eta-1+((calpha).^2)));
rp12 = ((eta.*calpha)+sqrt(eta-1+((calpha).^2)));
rpar = (rp11./rp12).^2;
qthingy1 = ((sin(psi+dpsi)).^2)-((sin(theta+dtheta)).^2).*((cos(psi+dpsi)).^2);
qthingy2 = ((sin(psi+dpsi)).^2)+((sin(theta+dtheta)).^2).*((cos(psi+dpsi)).^2);
qthingy = qthingy1./qthingy2;
wthingy1 = (sin(2*(psi+dpsi))).*(sin(theta+dtheta));
wthingy2 = ((sin(psi+dpsi)).^2)+(sin((theta+dtheta)).^2).*((sin(psi+dpsi)).^2);
wthingy = wthingy1./wthingy2;
roughness = (cos(psi)./(2*pi*(sdev.^2))).*exp(-((cos(psi).*dtheta).^2+(dpsi).^2)/(2*sdev.^2));
fun = matlabFunction((rpar+rperp).*roughness,'vars',{dtheta,dpsi});
fun2 = matlabFunction(roughness,'vars',{dtheta,dpsi});
fun3 = matlabFunction((rpar+rperp).*roughness.*qthingy,'vars',{dtheta,dpsi});
fun4 = matlabFunction((rpar+rperp).*roughness.*wthingy,'vars',{dtheta,dpsi});
thetamax = (pi/2) - theta;
psimax = (pi/2) - psi;
A = integral2(fun2,-pi/2,pi/2,-pi/2,pi/2);
i1 = (integral2(fun,-pi/2,thetamax,-pi/2,psimax))./A;
q = 2 - i1;
i2 = (integral2(fun3,-pi/2,thetamax,-pi/2,psimax))./A;
i3 = (integral2(fun4,-pi/2,thetamax,-pi/2,psimax))./A;
P = sqrt(i2.^2+i3.^2)./i1
plot(P, r);

How to use Neural network for non binary input and output

I tried to use the modified version of NN back propagation code by Phil Brierley
(www.philbrierley.com). When i try to solve the XOR problem it works perfectly. but when i try to solve a problem of the form output = x1^2 + x2^2 (ouput = sum of squares of input), the results are not accurate. i have scaled the input and ouput between -1 and 1. I get different results every time i run the same program (i understand its due to random wts initialization), but results are very different. i tried changing learning rate but still results converge.
have given the code below
%---------------------------------------------------------
% MATLAB neural network backprop code
% by Phil Brierley
%--------------------------------------------------------
clear; clc; close all;
%user specified values
hidden_neurons = 4;
epochs = 20000;
input = [];
for i =-10:2.5:10
for j = -10:2.5:10
input = [input;i j];
end
end
output = (input(:,1).^2 + input(:,2).^2);
output1 = output;
% Maximum input and output limit and scaling factors
m1 = -10; m2 = 10;
m3 = 0; m4 = 250;
c = -1; d = 1;
%Scale input and output
for i =1:size(input,2)
I = input(:,i);
scaledI = ((d-c)*(I-m1) ./ (m2-m1)) + c;
input(:,i) = scaledI;
end
for i =1:size(output,2)
I = output(:,i);
scaledI = ((d-c)*(I-m3) ./ (m4-m3)) + c;
output(:,i) = scaledI;
end
train_inp = input;
train_out = output;
%read how many patterns and add bias
patterns = size(train_inp,1);
train_inp = [train_inp ones(patterns,1)];
%read how many inputs and initialize learning rate
inputs = size(train_inp,2);
hlr = 0.1;
%set initial random weights
weight_input_hidden = (randn(inputs,hidden_neurons) - 0.5)/10;
weight_hidden_output = (randn(1,hidden_neurons) - 0.5)/10;
%Training
err = zeros(1,epochs);
for iter = 1:epochs
alr = hlr;
blr = alr / 10;
%loop through the patterns, selecting randomly
for j = 1:patterns
%select a random pattern
patnum = round((rand * patterns) + 0.5);
if patnum > patterns
patnum = patterns;
elseif patnum < 1
patnum = 1;
end
%set the current pattern
this_pat = train_inp(patnum,:);
act = train_out(patnum,1);
%calculate the current error for this pattern
hval = (tanh(this_pat*weight_input_hidden))';
pred = hval'*weight_hidden_output';
error = pred - act;
% adjust weight hidden - output
delta_HO = error.*blr .*hval;
weight_hidden_output = weight_hidden_output - delta_HO';
% adjust the weights input - hidden
delta_IH= alr.*error.*weight_hidden_output'.*(1-(hval.^2))*this_pat;
weight_input_hidden = weight_input_hidden - delta_IH';
end
% -- another epoch finished
%compute overall network error at end of each epoch
pred = weight_hidden_output*tanh(train_inp*weight_input_hidden)';
error = pred' - train_out;
err(iter) = ((sum(error.^2))^0.5);
%stop if error is small
if err(iter) < 0.001
fprintf('converged at epoch: %d\n',iter);
break
end
end
%Output after training
pred = weight_hidden_output*tanh(train_inp*weight_input_hidden)';
Y = m3 + (m4-m3)*(pred-c)./(d-c);
% Testing for a new set of input
input_test = [6 -3.1; 0.5 1; -2 3; 3 -2; -4 5; 0.5 4; 6 1.5];
output_test = (input_test(:,1).^2 + input_test(:,2).^2);
input1 = input_test;
%Scale input
for i =1:size(input1,2)
I = input1(:,i);
scaledI = ((d-c)*(I-m1) ./ (m2-m1)) + c;
input1(:,i) = scaledI;
end
%Predict output
train_inp1 = input1;
patterns = size(train_inp1,1);
bias = ones(patterns,1);
train_inp1 = [train_inp1 bias];
pred1 = weight_hidden_output*tanh(train_inp1*weight_input_hidden)';
%Rescale
Y1 = m3 + (m4-m3)*(pred1-c)./(d-c);
analy_numer = [output_test Y1']
plot(err)
This is the sample output i get for problem
state after 20000 epochs
analy_numer =
45.6100 46.3174
1.2500 -2.9457
13.0000 11.9958
13.0000 9.7097
41.0000 44.9447
16.2500 17.1100
38.2500 43.9815
if i run once more i get different results. as can be observed for small values of input i get totally wrong ans (negative ans not possible). for other values accuracy is still poor.
can someone tell what i am doing wrong and how to correct.
thanks
raman