Selection operator and minimizing the fitness function in Genetic Algorithms - matlab

I'm developing a nurse rostering tool im matlab using genetic algorithms, without using GA toolbox.
The individual is a weekly schedule and is represented as a 2-d array with rows equals to the number of nurses and seven columns because it is a weekly schedule.
The fitness function takes the entire population and returns an array with size equal to the population size containing fitness values.
The fitness function should be minimized so the best schedule is the one having the lowest fitness value.
My fitness function is:
function fitness_values =Fitness_Function( thePopulation)
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
[Ar1 Ar2 popsize num_nur] = Return_Data( 0,0,0,0 );
[prev_sched OffArr]=Return_Data1(0,0);
constraints=cell(popsize,1);
fitness_values=zeros(popsize,1);
size=[1 7];
c1=zeros(popsize,1);
c1values=cell(popsize,1);
W1=0.25; %hard
W2=0.25; %hard
W3=0.25; %hard
W4=0.125; %soft
W5=0.125; %soft
for i=1: popsize
c1values{i}=zeros(size);
end
% Checking Constraint c1 (the difference between night and day shifts in
% each day of the schedule
for i=1:popsize
for j=1:7
day_sum=0;
night_sum=0;
for k=1:num_nur
if thePopulation{i}(k,j)==1
day_sum=day_sum+1;
elseif thePopulation{i}(k,j)==2
night_sum=night_sum+1;
end
end
abs_diff=abs(day_sum-night_sum);
c1values{i}(1,j)=abs_diff.^2;
end
c1(i)=sum(c1values{i}(1,:));
%celldisp(c1values);
%defining the array that will hold the result of multiplying the number of
%violations with the correspondig weight,a cell array where each cell
%containts num_nur rows and 4 columns for c2, c3,c4 and c5.
nurse_fitness=zeros(num_nur,1);
for in=1:popsize
constraints{in}=zeros(num_nur,4);
end
for j=1:num_nur
v2=0;
v3=0;
v4=0;
%check violations with the previous schedule(the last day of the
%previous schedule with the first day of the evaluated schedule
% c2
if prev_sched(j,7)==2 && thePopulation{i}(j,1)==1
v2=v2+1;
end
% c3
%check the last day of the previous schedule
if prev_sched(j,7)==1 && thePopulation{i}(j,1)==1 && thePopulation{i}(j,2)~=3
v3=v3+1;
%check the last 2 days of the previous schedule
elseif prev_sched(j,6)==1 &&prev_sched(j,7)==1 && thePopulation{i}(j,2)~=3
v3=v3+1;
end
%c4
%check the last day of the previous schedule
if prev_sched(j,7)==2 && thePopulation{i}(j,1)==3 &&thePopulation{i}(j,2)==1
v4=v4+1;
%check the last 2 days of the previous schedule
elseif prev_sched(j,6)==2 &&prev_sched(j,7)==3 && thePopulation{i}(j,2)==1
v4=v4+1;
end
%check violations of constraints c2,c3 and c4 in the
%evaluated schedule
for k=1:6
%check violations of c2 N->N or N->O (hard)
if thePopulation{i}(j,k)==2 && thePopulation{i}(j,k+1)==1
v2=v2+1;
end
end
%check violations of c3 D->D->O (hard)
for k=1:5
if thePopulation{i}(j,k)==1 && thePopulation{i}(j,k+1)==1 && thePopulation{i}(j,k+2)~=3
v3=v3+1;
end
%check violations of c4 N->O->N or N->O->O (soft)
if thePopulation{i}(j,k)==2 && thePopulation{i}(j,k+1)==3 && thePopulation{i}(j,k+2)==1
v4=v4+1;
end
end
constraints{i}(j,1)=v2*W2;
constraints{i}(j,2)=v3*W3;
constraints{i}(j,3)=v4*W4;
%check violations of c5 (perefrences of each nurse)
offdays=find(thePopulation{i}(j,:)==3);
%disp(offdays);
%disp(OffArr(j,:));
%find intersection between the perefreces and the days off in the
%schedule of each nurse
inters=intersect(offdays,OffArr(j,:));
num_inters=length(inters);
if(length(offdays)==1)
%for head nurse
if num_inters==1
constraints{i}(j,4)=0;
else
constraints{i}(j,4)=3*W5;
end
else
penalty=3-num_inters;
constraints{i}(j,4)=penalty*W5;
end
nurse_fitness(j)=sum(constraints{i}(j,:));
end
%calculating the fitness value for the whole schedule
fitness_values(i)=W1*c1(i)+sum(nurse_fitness);
end
end
I'll summarize how it works: it takes a cell array (the population) each cell contains a schedule represented as matrix having rows =number of nurses and 7 columns (weekly schedule),,the problem has 3 hard constraints and 2 soft constraints, so the fitness will check the violation of these constraints in each schedule,,the violation is penalized by multiplying the number of violations in each nurse with the corresponding wheight of the constraint so the final fitness value is the sum of penalty values of each nurse. finally the fitness value of the the evaluated schedule is saved in an array of fitness values (the same index where the evaluated scheule is stored in the population array).
My question is what is the suitable selection operator to select parents for crossover and mutation operators?

Points missing from your question:
what is the meaning of a value in the array of an "individual"?
what are the constraints that can be violated?
Does an "individual" mean both a Genotype and a Phenotype?
I think you could also illustrate these with a simple example, and for others' best understanding can you please use the GA terminology?
Up to this point I can only give a general answer. Generally I think it is better to search through non-violating individuals. What I would do is not to use a complicated fitting function. I would rather have the phenotype always a non-violating solution that can be quickly calculated from a (possibly violating) genotype. Maybe the genotype should not grasp the whole problem, just give a starting point for a simple allocating algorithm that does the phenotype.
If you have non-violating chromosomes, the mutations should be lightly affecting, leading to similar solutions. Your chromosomes will be potentially some sort of permutations and the mutations could be some transpositions on these. The crossover-born children should jump-away from the parent solutions, preserving some of their characteristics. For permutation-type chromosomes you can find standard crossover operators.

Related

Find sum distance to horizontal line for all points in Matlab

I have a scatter plot of approximately 30,000 pts, all of which lie above a horizontal line which I've visually defined in my plot. My goal now is to sum the vertical distance of all of these points to this horizontal line.
The data was read in from a .csv file and is already saved to the workspace, but I also need to check whether a value is NaN, and ignore these.
This is where I'm at right now:
vert_deviation = 0;
idx = 1;
while idx <= numel(my_data(:,5)) && isnan(idx) == 0
vert_deviation = vert_deviation + ((my_data(idx,5) - horiz_line_y_val));
idx = idx + 1;
end
I know that a prerequisite of using the && operator is having two logical statements I believe, but I'm not sure how to rewrite this loop in this way at the moment. I also don't understant why vert_deviation returns NaN at the moment, but I assume this might have to do with the first mistake I described...
I would really appreciate some guidance here - thank you in advance!
EDIT: The 'horizontal line' is a slight oversimplification - in reality the lower limit I need to find the distance to consists of 6 different line segments
I should have specified that the lower limit to which I need to calculate the distance for all scatterplot points varies for different x values (the horizontal line snippet was meant to be a simplification but may have been misleading... apologies for that)
I first modified the data I had already read into the workspace by replacing all NaNvalues with 0. Next, I wrote a while loop which defines the number if indexes to loop through, and defined an && condition to filter out any zeroes. I then wrote a nested if loop which checks what range of x values the given index falls into, and subsequently takes the delta between the y values of a linear line lower limit for that section of the plot and the given point. I repeated this for all points.
while idx <= numel(my_data(:,3)) && not(my_data(idx,3) == 0)
...
if my_data(idx,3) < upper_x_lim && my_data(idx,5) > lower_x_lim
vert_deviation = vert_deviation + (my_data(idx,4) - (m6 * (my_data(idx,5)) + b6))
end
...
m6 and b6 in this case are the slope and y intercept calculated for one section of the plot. The if loop is repeated six times for each section of the lower limit.
I'm sure there are more elegant ways to do this, so I'm open to any feedback if there's room for improvement!
Your loop doesn't exclude NaN values becuase isnan(idx) == 0 checks to see if the index is NaN, rather than checking if the data point is NaN. Instead, check for isnan(my_data(idx,5)).
Also, you can simplify your code using for instead of while:
vert_deviation = 0;
for idx=1:size(my_data,1)
if !isnan(my_data(idx,5))
vert_deviation = vert_deviation + ((my_data(idx,5) - horiz_line_y_val));
end
end
As #Adriaan suggested, you can remove the loop altogether, but it seems that the code in the OP is an oversimplification of the problem. Looking at the additional code posted, I guess it is still possible to remove the loops, but I'm not certain it will be a significant speed improvement. Just use a loop.

How can I incorporate a for loop into my genetic algorithm?

I'm doing a genetic algorithm that attempts to find an optimized solution over the course of 100 generations. My code as is will find 2 generations. I'm trying to find a way to add a for loop in order to repeat the process for the full duration of 100 generations.
clc,clear
format shorte
k=80;
mu=50;
s=.05;
c1=k+(4/3)*mu;
c2=k-(2/3)*mu;
for index=1:50 %6 traits generated at random 50 times
a=.005*rand-.0025;
b=.005*rand-.0025;
c=.005*rand-.0025;
d=.005*rand-.0025;
e=.005*rand-.0025;
f=.005*rand-.0025;
E=[c1,c2,c2,0,0,0;
c2,c1,c2,0,0,0;
c2,c2,c1,0,0,0;
0,0,0,mu,0,0;
0,0,0,0,mu,0;
0,0,0,0,0,mu];
S=[a;d;f;2*b;2*c;2*e];
G=E*S;
g=G(1);
h=G(2);
i=G(3);
j=G(4);
k=G(5);
l=G(6);
F=[(g-h)^2+(h-i)^2+(i-g)^2+6*(j^2+k^2+l^2)];
PI=((F-(2*s^2))/(2*s^2))^2; %cost function, fitness assessed
RP(index,:)=[a,b,c,d,e,f,PI]; %initial random population
end
Gen1=sortrows(RP,7,{'descend'}); %the initial population ranked
%for loop 1:100 would start here
children=zeros(10,6); %10 new children created from the top 20 parents
babysitter=1;
for parent=1:2:20
theta=rand(1);
traita=theta*Gen1(parent,1)+(1-theta)*Gen1(1+parent,1);
theta=rand(1);
traitb=theta*Gen1(parent,2)+(1-theta)*Gen1(1+parent,2);
theta=rand(1);
traitc=theta*Gen1(parent,3)+(1-theta)*Gen1(1+parent,3);
theta=rand(1);
traitd=theta*Gen1(parent,4)+(1-theta)*Gen1(1+parent,4);
theta=rand(1);
traite=theta*Gen1(parent,5)+(1-theta)*Gen1(1+parent,5);
theta=rand(1);
traitf=theta*Gen1(parent,6)+(1-theta)*Gen1(1+parent,6);
children(babysitter,:)=[traita,traitb,traitc,traitd,traite,traitf];
babysitter=babysitter+1;
end
top10parents=Gen1(1:10,1:6);
Gen1([11:50],:)=[]; %bottom 40 parents removed
for newindex=1:30 %6 new traits generated randomly 30 times
newa=.005*rand-.0025;
newb=.005*rand-.0025;
newc=.005*rand-.0025;
newd=.005*rand-.0025;
newe=.005*rand-.0025;
newf=.005*rand-.0025;
newgenes(newindex,:)=[newa,newb,newc,newd,newe,newf];
end
nextgen=[top10parents;children;newgenes]; %top 10 parents, the 10 new children, and the new 30 random traits added into one new matrix
for new50=1:50
newS=[nextgen(new50,1);nextgen(new50,4);nextgen(new50,6);2*nextgen(new50,2);2*nextgen(new50,3);2*nextgen(new50,5)];
newG=E*newS;
newg=newG(1);
newh=newG(2);
newi=newG(3);
newj=newG(4);
newk=newG(5);
newl=newG(6);
newF=[(newg-newh)^2+(newh-newi)^2+(newi-newg)^2+6*(newj^2+newk^2+newl^2)]; %von-Mises criterion
newPI=((newF-(2*s^2))/(2*s^2))^2; %fitness assessed for new generation
PIcolumn(new50,:)=[newPI];
end
nextgenwPI=[nextgen,PIcolumn]; %pi column added to nextgen matrix
Gen2=sortrows(nextgenwPI,7,{'descend'}) %generation 2 ranked
So my question is, how can I get the generations to count themselves in order to make the for loop work. I've searched for an answer and I've read that having matrices count themselves is not a good idea. However, I'm not sure how I could do this besides finding a way to make a genN matrix that counts upward in increments of 1 after the first generation. Any suggestions?
Thank you

Animated plot of infectious disease spread with for loop (Matlab)

I'm a beginner in Matlab and I'm trying to model the spread of an infectious disease using Matlab. However, I encounter some problems.
At first, I define the matrices that need to be filled and their initial status:
diseasematrix=zeros(20,20);
inirow=10;
inicol=10;
diseasematrix(inirow,inicol)=1; % The first place where a sick person is
infectionmatrix=zeros(20,20); % Infected people, initially all 0
healthymatrix=round(rand(20,20)*100); % Initial healthy population (randomly)
Rate=0.0001; % Rate of spread
Now, I want to make a plot where the spread of the disease is shown, using a for loop. But i'm stuck here...
for t=1:365
Zneighboursum=zeros(size(diseasematrix));
out_ZT = calc_ZT(Zneighboursum, diseasematrix);
infectionmatrix(t) = round((Rate).*(out_ZT));
diseasematrix(t) = diseasematrix(t-1) + infectionmatrix(t-1);
healthymatrix(t) = healthymatrix(t-1) - infectionmatrix(t-1);
imagesc(diseasematrix(t));
title(sprintf('Day %i',t));
drawnow;
end
This basically says that the infectionmatrix is calculated based upon the formula in the loop, the diseasematrix is calculated by adding up the sick people of the previous timestep with the infected people of the previous time. The healthy people that remain are calculated by substracting the healthy people of the previous time step with the infected people. The variable out_ZT is a function I made:
function [ZT] = calc_ZT(Zneighboursum, diseasematrix)
Zneighboursum = Zneighboursum + circshift(diseasematrix,[1 0]);
Zneighboursum = Zneighboursum + circshift(diseasematrix,[0 1]);
ZT=Zneighboursum;
end
This is to quantify the number of sick people around a central cell.
However, the result is not what I want. The plot does not evolve dynamically and the values don't seem to be right. Can anyone help me?
Thanks in advance!
There are several problems with the code:
(Rate).*(out_ZT) is wrong. Because first one is a scalar and
second is a matrix, while .* requires both to be matrices of the
same size. so a single * would work.
The infectionmatrix,
diseasematrix, healthymatrix are all 2 dimensional matrices and
in order to keep them in memory you need to have a 3 dimensional
matrix. But since you don't use the things you store later you can
just rewrite on the old one.
You store integers in the
infectionmatrix, because you calculate it with round(). That
sets the result always to zero.
The value for Rate was too low to see any result. So I increased it to 0.01 instead
(just a cautionary point) you haven't used healthymatrix in your code anywhere.
The code for the function is fine, so after debugging according to what I perceived, here's the code:
diseasematrix=zeros(20,20);
inirow=10;
inicol=10;
diseasematrix(inirow,inicol)=1; % The first place where a sick person is
infectionmatrix=zeros(20,20); % Infected people, initially all 0
healthymatrix=round(rand(20,20)*100); % Initial healthy population (randomly)
Rate=0.01;
for t=1:365
Zneighboursum=zeros(size(diseasematrix));
out_ZT = calc_ZT(Zneighboursum, diseasematrix);
infectionmatrix = (Rate*out_ZT);
diseasematrix = diseasematrix + infectionmatrix;
healthymatrix = healthymatrix - infectionmatrix;
imagesc(diseasematrix);
title(sprintf('Day %i',t));
drawnow;
end
There is several problems:
1) If you want to save a 3D matrix you will need a 3D vector:
so you have to replace myvariable(t) by myvariable(:,:,t);
2) Why did you use round ? if you round a value < 0.5 the result will be 0. So nothing will change in your loop.
3) You need to define the boundary condition (t=1) and then start your loop with t = 2.
diseasematrix=zeros(20,20);
inirow=10;
inicol=10;
diseasematrix(inirow,inicol)=1; % The first place where a sick person is
infectionmatrix =zeros(20,20); % Infected people, initially all 0
healthymatrix=round(rand(20,20)*100); % Initial healthy population (randomly)
Rate=0.01; % Rate of spread
for t=2:365
Zneighboursum=zeros(size(diseasematrix,1),size(diseasematrix,2));
out_ZT = calc_ZT(Zneighboursum, diseasematrix(:,:,t-1));
infectionmatrix(:,:,t) = (Rate).*(out_ZT);
diseasematrix(:,:,t) = diseasematrix(:,:,t-1) + infectionmatrix(:,:,t-1);
healthymatrix(:,:,t) = healthymatrix(:,:,t-1) - infectionmatrix(:,:,t-1);
imagesc(diseasematrix(:,:,t));
title(sprintf('Day %i',t));
drawnow;
end
IMPORTANT: circshift clone your matrix in order to deal with the boundary effect.

How can I sorting the values in the jumping columns?

I have a matrices 25x600 and some columns contains positive and negative values. I want the output like this [+ + - -] (four values 2 positive and 2 negative). I am guaranteed to always have two positive values immediately before the transition and two negative values immediately after. my attempting was as follow :
My attempt was as follows:
clc;
clear all;
close all;
%%
data=[-0.0059972;-0.004994;-0.0029881;2.0868e-05;
0.0030299;0.013059;0.033115;0.063196;0.093273;0.1935;0.39385;0.69423;0.99448;1.9950;3.99550;6.99550;9.9957;19.9961;39.99620;69.9960;
99.99530;199.99810;399.99140;699.98860;1000.03130]
for r=1:600
lam=data(:,r);
N_lam = length(lam);
%%
for j=1:N_lam
kk=0;
r1=0;
if(sign(lam(j))==1)
kk=kk+1;
lampos(kk)=lam(j);
if (length(lampos(kk))>3 &length(lamneg(r1))>2)
break
end
else
r1=r1+1;
lamneg(r1)=lam(j);
end
end
cc{r}=[lampos lamneg];
end
Any help would be greatly appreciated.
The find function may be useful here, as it can help you to locate the locations where the function changes from positive to negative. The following locates the index ind of the last negative value of data (assumed here to be a 1D vector) before it rises above zero:
num_rises = 1;
ind = find(data(1:end-1)<=0 & data(2:end)>0, num_dips, 'first')
As such, for each column, you would be interested in the values of ind-1,ind, negative values, and ind+1,ind+2 for the positive values.
It was also unclear to me how many sets of these 4 values were of interest to you. To find more regions where the data dips below the origin, change the value of num_dips to suit your needs.

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.