Metropolis algorithm in MATLAB -->> error with function handles - matlab

i have a piece of metropolis algorithm:
mB=5.79*10^(-9); %Bohr magnetone in eV*G^-1
kB=0.86*10^(-4); %Boltzmann in eV*K^-1
%system parameters
L=60; %side square grid
L2=L*L; % total number grid position
Tstep=5; %step in temperature change (K)
Maxstep=10; %max number of steps
nmcs=5; % cycle numberof Metropolis algorithm
magnet=NaN(1,Maxstep);%store magnetization in "monte carlo images" of sample
%Creation initial point arrangement of magnetic spins
%Outer parameters
H=100000; %Gauss
T=20; % Kelvin
%Energy alteration in spin-reverse
de =# (i,j) (2*mB*H).*mlat(i,j);
%Metropolis probability
pmetro=# (i,j) exp(-de(i,j)./(kB*T));
%Creation and display of initial lattice
mlat=2*round(rand(L,L))-1;
mtotal=sum(mlat(:))./L2
% Alteration of system with time
for ii=1:Maxstep
for imc=1:nmcs
for i=1:L
for j=1:L
if pmetro(i,j)>=1
mlat(i,j)=-mlat(i,j);
elseif rand<pmetro(i,j)
mlat(i,j)=-mlat(i,j);
end
end
end
end
magnet(:,ii)=sum(mlat(:))./L2;
%figure(ii);
%pcolor(mlat);
% shading interp;
end
m1=mean(magnet)
error=std(magnet) ./sqrt(numel(magnet))
fprintf('Temperature = %d K',T)
figure(13)
plot(magnet(1,:),'b.')
axis([0 10 0 0.5])
grid on
xlabel('i (Configuration) ')
ylabel('M/(N*mB)')
Now,the problem is in figure(13).The values it gives me are around zero (0.05,0.02..).It supposes to give me values around 0.3..
Generally,the graph its ok,It gives me the right "shape"(it has points) but as i said around zero.
I really don't know how to put this post in order to be understood.Maybe i have some mistake in the "magnet"matrix ,i don't know.
Anyway,i don't demand from anybody to check it thoroughly ,i am just asking if with a quick look anyone can help.
ΕDIT--->> Also,sometimes when i run the program ,it gives me :
Undefined function or method 'mlat'
for input arguments of type 'double'.
Error in ==> #(i,j)(2*mB*H).*mlat(i,j)
Error in ==>
#(i,j)exp(-de(i,j)./(kB*T))
Error in ==> metropolis at 39
if pmetro(i,j)>=1
EDIT--->>> I found the "mistake" .In my code in the loops where i have the function "pmetro" i replaced it with the "exp(-(2*mB*H).*mlat(i,j)./(kB*T))" and the program worked just fine!!!
Why it didn't work with calling the "pmetro"??How can i overcome this?Is there a problem with function handles in loops?
Blockquote

I very strongly suggest that you try writing code without using any function handles until you're really familiar with Matlab.
The line
de =# (i,j) (2*mB*H).*mlat(i,j);
is what causes your problems. In Matlab, when you define a function handle that refers to, say, an array, the function handle will use the array as it was at the time of definition. In other words, even though mlat changes inside your loop, mlat(i,j) inside the function de is always the same. In fact, you cannot even run this code unless you have previously defined mlat in the workspace.
You should therefore rewrite the main loop as follows
for iStep = 1:maxStep
for imc = 1:mcs
pmetro = $some function of mlat - this can be calculated using the
entire array as input
%# for each element in mlat (and thus pmetro), decide whether
%# you have to switch the spin
switchIdx = pmetro > 1 | pmetro < rand(size(mlat));
mlat(switchIdx) = -mlat(switchIdx);
end
$calculate magnetization$
end
Also, note that there is a command mean to take the average. No need to sum and then divide by the number of elements.

Related

Matlab implementation of Perceptron - can't seem to fix plotting

This is my first go with ML (and Matlab) and I'm following "Learning From Data" by Yaser S. Abu-Mostafa.
I'm trying to implement the Perceptron algorithm, after trying to go through the pseudocode, using other people's solutions I can't seem to fix my problem (I went through other threads too).
The algorithm separates the data fine, it works. However, I want to plot a single line, but it seems as it separates them in a way so the '-1' cluster is divided to a second cluster or more.
This is the code:
iterations = 100;
dim = 3;
X1=[rand(1,dim);rand(1,dim);ones(1,dim)]; % class '+1'
X2=[rand(1,dim);1+rand(1,dim);ones(1,dim)]; % class '-1'
X=[X1,X2];
Y=[-ones(1,dim),ones(1,dim)];
w=[0,0,0]';
% call perceptron
wtag=weight(X,Y,w,iterations);
% predict
ytag=wtag'*X;
% plot prediction over origianl data
figure;hold on
plot(X1(1,:),X1(2,:),'b.')
plot(X2(1,:),X2(2,:),'r.')
plot(X(1,ytag<0),X(2,ytag<0),'bo')
plot(X(1,ytag>0),X(2,ytag>0),'ro')
legend('class -1','class +1','pred -1','pred +1')
%Why don't I get just one line?
plot(X,Y);
The weight function (Perceptron):
function [w] = weight(X,Y,w_init,iterations)
%WEIGHT Summary of this function goes here
% Detailed explanation goes here
w = w_init;
for iteration = 1 : iterations %<- was 100!
for ii = 1 : size(X,2) %cycle through training set
if sign(w'*X(:,ii)) ~= Y(ii) %wrong decision?
w = w + X(:,ii) * Y(ii); %then add (or subtract) this point to w
end
end
sum(sign(w'*X)~=Y)/size(X,2); %show misclassification rate
end
I don't think the problem is in the second function but I added it regardless
I'm pretty sure the algorithm separates it to more than one cluster but I can't tell why most of the learning I've done so far was math and theory and not actual coding so I'm probably missing something obvious..

Passing matrix to another function, storing element

I am having a problem, I have a function popmesh1 that calculates a matrix P( , ). I then use sens_analysis to store a element of that matrix and continue. How do I output P( , ) so that it is kept track of? I keep getting that the matrix is size (0,0). Also, how do I pass the matrix into another function? Sorry to post whole code, I want to concrete and clear, I'm pretty new to MATLAB
function pdemeshpop(varargin)
global par;
global re;
global P;
global par_n;
global a1;
clc
clear
%INIITIALIZE MESH:- Can change time and age for refining of mesh
time=linspace(0,800,4000);
age=linspace(0,time(end),4000);
dt=time(2)-time(1);
dtao=dt;
P=zeros(length(time),9); % State matrix over time.
P1=zeros(length(time),length(age)); % Mesh for population of P1mod.
prodrev=zeros(length(time),length(age));
p1tot=zeros(length(time));
p2tot=zeros(length(time));
f=zeros(length(time));
A_1=zeros(length(time),1);
%Parameters
G=log(2)/30; %This growth rate had been set to nthroot(2,20), but I think it should be log(2)/20 for a doubling time of 20 mins. Units 1/min
R=.75; %Reduction in growth rate due to viral production, range from 0.5-0.75
global A_s; %Number of virus produced each minute from one cell? Units 1/min
A_s = 35; %Source for this?
global re;
re = varargin(1); %Reduction in efficiency of virus production in P1mod
c=1.5e9; %Concentration of cells in saturated culture. Units 1/cm^3 Source: http://bionumbers.hms.harvard.edu/bionumber.aspx?&id=100984&ver=2
K=3e-11; %Adsorption rate. Units cm^3/min. Source: Tzagoloff, H., and D. Pratt. 1964. The initial steps in infection with coliphage M13. Virology 24:372?380.
i = 1; %Is flipping of switch induced or not induced? if i==1 then switch is induced.
if i==1
S_i=0.5; %S_i is probability that a switch will flip during a timestep in a p1ori cell. Units pure number (a probablility). Ranges from 0 to 1.
elseif i==0
S_i= 0.005;
end
%IC and BC implementation for the 9 dependent variables <<<10?
P0=zeros(9,1);
P0(1)=100; %Initial concentration of senders. Units: cells/ml.
P0(2)=10000; %Initial concentration of primary receivers. Units: cells/ml.
P0(3)=10000; %Initial concentration of secondary receivers. Units: cells/ml.
%The loop below covers the initial conditions and BC of t=0,all ages
for i=1:9
P(1,i)=P0(i);
end
%Iterative solution
for m=1:length(time)-1 % m is timestep
%Simplifications
p1tot(m)=P(m,2)+P(m,4)+P(m,6);
p2tot(m)=P(m,3)+P(m,5)+P(m,7);
f(m)=1-(P(m,1)+p1tot(m)+p2tot(m))/c;
%Senders
P(m+1,1)=dt*(P(m,1)*G*R*f(m))+P(m,1);
%Primary Receivers
P(m+1,2)=dt*((P(m,2)*G*f(m))-K*(P(m,8)+P(m,9))*P(m,2))+P(m,2);
%Secondary Receivers
P(m+1,3)=dt*((P(m,3)*G*f(m))-K*(P(m,8)+P(m,9))*P(m,3))+P(m,3);
%Primary Original
P(m+1,4)=dt*((P(m,4)*G*f(m))+K*P(m,8)*P(m,2)-S_i*P(m,4))+P(m,4);
%Secondary Original
P(m+1,5)=dt*((P(m,5)*G*f(m))+K*P(m,8)*P(m,3))+P(m,5);
for n=1:m
t=(m-1)*dt; %Why not t=m*dt?
tao=(n-1)*(dtao);%Determines current age basket
prodrev(m,n)=rate(t-tao); %Calculates corresponding rate of production of phage (reversed)
%Primary Modified
if n==1
P1(m+1,n)=dt*(K*P(m,2)*P(m,9)+S_i*P(m,4)); %Left hand side boundary (New cells at age zero)
else
P1(m+1,n)=dt*(-((P1(m,n)-P1(m,n-1))/dtao)+P1(m,n)*G*R*f(m))+P1(m,n);
end
end
P(m+1,6)=sum(P1(m+1,:)); %phi1mod
%Secondary Modified
P(m+1,7)=dt*((P(m,7)*G*f(m))+K*P(m,9)*P(m,3))+P(m,7);
%Original
P(m+1,8)=dt*(A_s*P(m,1))+P(m,8);
if m<2
A_1(m)=0;
else
convolution(m,:)=prodrev(m,:).*P1(m,:);
%A_1(m)=dtao*trapz(conv(prod1(m,:), P1(m,:)));
A_1(m)=dtao*trapz([convolution(m,:) 0]);
%A_1 obtained by convolving the discrete vectors of P1 and prod1
%then finding the area under the curve
end
%Modified
P(m+1,9)=dt*A_1(m)+P(m,9);
end
P1;
end
function prod=rate(tao)
%Function generates production rate values of the infected cells based on their age
global A_s;
global re;
a=re*A_s; %Max production rate
ageofcell=tao;
if ageofcell<=10
prod=0;
elseif ageofcell<=50
prod=(a/40)*(ageofcell-10);
else
prod=a;
end
end
and my other code that calls the above function, and that I want to pass P(time(length),7) to:
function sens_analysis
global par;
global re;
global par_n;
global P;
time=linspace(0,800,4000);
pdemeshpop_final_re_sens;
re_0 = re;
par = re;
s_nom_ss = a1;
delta = 0.05;
par_n = par*(1+delta);
pdemeshpop_final_re_sens_par(par_n); % similar to pdemeshpop_final_re_sens
s_pert_ss = P(length(time),7);
abs_sens = (s_pert_ss - s_nom_ss)/(delta*re_0);
rel_sens = abs_sens*(re_value/s_nom_ss);
end
Again, sorry to post whole code, felt it was a necessary evil. The global variables might also be unnecessary. Could be something obvious. I might need to store P first somehow. Can someone please explain this carefully? Thank you!
At the beginning of function pdemeshpop you have a clear statement which is erasing from your workspace the variables declared by the global statements. Comment out that clear statement and you'll circumvent that problem.
The first thing I noticed in your code is that you use global variables. In general this is not recommended if it can be avoided. Consider giving them as input to your functions instead, either separately or in a struct.
Of course the clear is removing your variables, but in general if you want to see what is happening, try placing some breakpoints in your code. That allows you to inspect all existing variables. With f10 you can then step through the code and see how everything goes on.
Furthermore, I would always recommend you to use dbstop if error, this way you can efficiently deal with the errors that you will encounter.

Improper assignment with rectangular empty matrix 0

???Improper assignment with rectangular empty matrix
Error in task3, 18
y(:,1)=log(r);
The error persists and I don't know what to do.
The script is given below
function task3
time=xlsread('Kinetics_data.xls','B3:B82');
Conc=xlsread('Kinetics_data.xls','C3:C82');
CAo=0.050;
CBo=0.0406;
h=0.5;
n=length(Conc);
%Calculate the reaction rate using the forward difference equation and
%eliminate outliners if necessary.
global CA CB
t=time(2:n-1);
CA=Conc(2:n-1);
CB=CBo-(CAo-CA);
r=(-Conc(3:n)+Conc(1:n-2))/(2*h);
y(:,1)=log(r);
X(:,1)=ones(size(CA));
X(:,2)=log(CA);
X(:,3)=log(CB);
[b bint resid residint stats]=regress(y,X);
b;
bint;
k=exp(b(1));
kint=exp(bint(1,:));
b(1)=k;
% Set initial guess of parameter value.
m0=b;
% Set lower and upper bounds for the parameters
ub=[2.981770068869469 1.515475186852946 0.914563691229481];
lb=[1.354032677809809 0.938815382572068 0.753329300963922];
options=optimset('TolX',1e-16,'TolFun',1e-16,'MaxFunEval',4000,'MaxIter',4000);
[m,residn,resid,exiflage,output,lamda,Jacob]=lsqcurvefit(#ratefun,m0,t,r,lb,ub,options)
end
Hint
I can easily reproduce your error by setting $n=0$ at the top of your script so think about the reason why $n=0$ in your case (further hint: check your excel file for the range of the data)

need explanation about a matlab code snippet about moran process

I am new to Matlab. I was reading this code snippet, but in some parts (marked with asterisks) I don't understand what it means, so if anybody could help would be very much appreciated
function [A1nmb] = moran(initsize, popsize)
% MORAN generates a trajectory of a Moran type process
% which gives the number of genes of allelic type A1 in a population
% of haploid individuals that can exist in either type A1 or type A2.
% The population size is popsize and the initial number of type A1
% individuals os initsize.
% Inputs: initsize - initial number of A1 genes
% popsize - the total population size (preserved)
if (nargin==0)
initsize=10;
popsize=30;
end
A1nmb=zeros(1,popsize);
A1nmb(1)=initsize;
**lambda = inline('(x-1).*(1-(x-1)./N)', 'x', 'N');
mu = inline('(x-1).*(1-(x-1)./N)', 'x', 'N');**
x=initsize;
i=1;
while (x>1 & x<popsize+1)
if (lambda(x,popsize)/(lambda(x,popsize)+mu(x,popsize))>rand)
x=x+1;
A1nmb(i)=x;
else
x=x-1;
A1nmb(i)=x;
end;
i=i+1;
end;
nmbsteps=length(A1nmb);
***rate = lambda(A1nmb(1:nmbsteps-1),popsize) ...
+mu(A1nmb(1:nmbsteps-1),popsize);***
**jumptimes=cumsum(-log(rand(1,nmbsteps-1))./rate);**
jumptimes=[0 jumptimes];
stairs(jumptimes,A1nmb);
axis([0 jumptimes(nmbsteps) 0 popsize+1]);
The first line you marked
lambda = inline('(x-1).*(1-(x-1)./N)', 'x', 'N');
creates something called an inline function. It is equivalent to defining a mathematical function. Example:
y = inline('x^2')
would allow you to do
>> y(2)
4
This immediately explains the second line you marked.
rate = lambda(A1nmb(1:nmbsteps-1),popsize) ...
+mu(A1nmb(1:nmbsteps-1),popsize);
will compute the value of the function lambda(x,N) at x = A1nmb(1:nmbsteps-1) and N = popsize.
I will say immediately here that you should take a look at anonymous functions, a different format used to accomplish the same as inline. Only, anonymous functions are generally better supported, and usually a lot faster than inline functions.
Then, for the final line,
jumptimes = cumsum(-log(rand(1,nmbsteps-1))./rate);
is a nested command. rand will create a matrix containing pseudorandom numbers, log is the natural logarithm ("ln"), and cumsum creates a new matrix, where all the elements in the new matrix are the cumulative sum of the elements in the input matrix.
You will find the commands doc and help very useful. Try typing
doc cumsum
or
help inline
on the Matlab command prompt. Try that again with the commands forming the previous statement.
As a general word of advice: spend an insane lot of time reading through the documentation. Really, for each new command you encounter, read about it and play with it in a sandbox until you feel you understand it. Matlab only becomes powerful if you know all its commands, and there are a lot to get to know.
It defines an inline function object. For example this
lambda = inline('(x-1).*(1-(x-1)./N)', 'x', 'N')
defines lambda as a function with 2 variables. When you call lambda(A,n) Matlab simply expands the function you define in the first string. Thus lambda(A,n) using the variables you provide in the function call. lambda(A,n) would will evaluate to:
(A-1).*(1-(A-1)./n)
it just expands the function using the parameters you supply. Take a look at this link for more specific details http://www.mathworks.co.uk/help/techdoc/ref/inline.html
The cumsum function just returns the cumulative sum of a matrix along a particular dimension. Say we call cumsum on a vector X, then the value at element i in the result is equal to the sum of elements in X from index 1 to i. For example X = [1 2 1 3] we would get
AA = cumsum(X);
we would have
AA = [1 3 5 8]
See this link for more details and examples http://www.mathworks.co.uk/help/techdoc/ref/cumsum.html

nlfilter taking same values twice

I used nlfilter for a test function of mine as follows:
function funct
clear all;
clc;
I = rand(11,11);
ld = input('Enter the lag = ') % prompt for lag distance
A = nlfilter(I, [7 7], #dirvar);
% Subfunction
function [h] = dirvar(I)
c = (size(I)+1)/2
EW = I(c(1),c(2):end)
h = length(EW) - ld
end
end
The function works fine but it is expected that nlfilter progresses element by element, but in first two iterations the values of EW will be same 0.2089 0.4162 0.9398 0.1058. But then onwards for all iterations the next element is selected, for 3rd it is 0.4162 0.9398 0.1058 0.1920, for 4th it is 0.9398 0.1058 0.1920 0.5201 and so on. Why is it so?
This is nothing to worry about. It happens because nlfilter needs to evaluate your function to know what kind of output to create. So it uses feval once before starting to move across the image. The output from this feval call is what you see the first time.
From the nlfilter code:
% Find out what output type to make.
rows = 0:(nhood(1)-1);
cols = 0:(nhood(2)-1);
b = mkconstarray(class(feval(fun,aa(1+rows,1+cols),params{:})), 0, size(a));
% Apply fun to each neighborhood of a
f = waitbar(0,'Applying neighborhood operation...');
for i=1:ma,
for j=1:na,
x = aa(i+rows,j+cols);
b(i,j) = feval(fun,x,params{:});
end
waitbar(i/ma)
end
The 4th line call to eval is what you observe as the first output from EW, but it is not used to anything other than making the b matrix the right class. All the proper iterations happen in the for loop below. This means that the "duplicate" values you observe does not affect your final output matrix, and you need not worry.
I hope you know what the length function does? It does not give you the Euclidean length of a vector, but rather the largest dimension of a vector (so in your case, that should be 4). If you want the Euclidean length (or 2-norm), use the function norm instead. If your code does the right thing, you might want to use something like:
sz = size(I,2);
h = sz - (sz+1)/2 - ld;
In your example, this means that depending on the lag you provide, the output should be constant. Also note that you might want to put semicolons after each line in your subfunction and that using clear all as the first line of a function is useless since a function will always be executed in its own workspace (that will however clear persistent or global variables, but you don't use them in your code).