Seeking advice on trying to read a moore neighbourhood for a 2D cellular automata in MATLAB for an epidemic simulator - matlab

I'm currently working on a code that makes use of a 2D cellular automata as an epidemic simulator in MATLAB. The main basic rule I'm trying to implement is that if any neighbour within a Moore Neighbourhood with a 1-cell radius is infected, the cell will become infected. But I can't seem to get a good code working for it.
Basically what I'm trying to do is say with for a cell with a one cell radius Moore neighbourhood, if any values in this neighbourhood = 2, then the initial cell will become 2.
I've tried using the forest fire code on the rosetta code as a basis for my code behaviour but it doesnt work very well. The rules don't really work that well when applying it to mine. I've tried using the mod function and a series of if loops to attach. I'll put in some code of each to give context.
This example doesn't really function well as an epidemic simulator to be honest.
matlab
clear; clc;
n = 200;
N = n/2;
E = 0.001; % Creating an arbitrary number for population exposed to
the disease but not infected
p = 1 + (rand(n,n)<E);
%p = ceil(rand(n,n)*2.12) - 1;
% ratio0 = sum(p(:)==0)/n^2;
% ratio1 = sum(p(:)==1)/n^2;
% ratio2 = sum(p(:)==2)/n^2;
% ratio3 = sum(p(:)==3)/n^2;
S = ones(3); S(2,2) = 0;
ff = 0.00000000002;
p(N,N) = 3;
%% Running the simulation for a set number of loops
colormap([1,1,1;1,0,1;1,0,0]); %Setting colourmap to Green, red and
grey
count = 0;
while(count<365) % Running the simulation with limited number of runs
count = count + 1;
image(p); pause(0.1); % Creating an image of the model
P = (p==1); % Adding empty cells to new array
P = P + (p==2).*((filter2(S,p==3)>0) + (rand(n,n)<ff) + 2); % Setting
2 as a tree, ignites based on proximity of trees and random
chance ff
P = P + (p==3); % Setting 3 as a burning tree, that becomes 1,
p = P;
end
second idea. this basically returns nothing
matlab
clear;clf;clc;
n = 200;
pos = mod((1:n),n) + 1; neg = mod((1:n)-2,n) + 1;
p = (ceil(rand(n,n)*1.0005));
for t = 1:365
if p(neg,neg) ==2
p(:,:) = 2;
end
if p(:,neg)==2
p(:,:) = 2;
end
if p(pos,neg)==2
p(:,:) = 2;
end
if p(neg,:)==2
p(:,:) = 2;
end
if p(pos,:)==2
p(:,:) = 2;
end
if p(neg,pos)==2
p(:,:) = 2;
end
if p(:,pos)==2
p(:,:) = 2;
end
if p(pos,pos)== 2
p(:,:) = 2;
end
image(p)
colormap([1,1,1;1,0,1])
end
third I tried using logic gates to see if that would work. I don't know if commas would work instead.
matlab
clear;clf;clc;
n = 200;
pos = mod((1:n),n) + 1; neg = mod((1:n)-2,n) + 1;
p = (ceil(rand(n,n)*1.0005));
%P = p(neg,neg) + p(:,neg) + p(pos,neg) + p(neg,:) + p(:,:) + p(pos,:)
+ p(neg,pos) + p(:,pos) + p(pos,pos)
for t=1:365
if p(neg,neg)|| p(:,neg) || p(pos,neg) || p(neg,:) || p(pos,:) ||
p(neg,pos) || p(:,pos) || p(pos,pos) == 2
p(:,:) = 2;
end
image(p)
colormap([1,1,1;1,0,1])
end
I expected the matrix to just gradually become more magenta but nothing happens in the second one. I get this error for the third.
"Operands to the || and && operators must be convertible to logical scalar values."
I just have no idea what to do!

Cells do not heal
I assume that
Infected is 2, non-infected is 1;
An infected cell remains infected;
A non-infected cell becomes infected if any neighbour is.
A simple way to achieve this is using 2-D convolution:
n = 200;
p = (ceil(rand(n,n)*1.0005));
neighbourhood = [1 1 1; 1 1 1; 1 1 1]; % Moore plus own cell
for t = 1:356
p = (conv2(p-1, neighbourhood, 'same')>0) + 1; % update
image(p), axis equal, axis tight, colormap([.4 .4 .5; .8 0 0]), pause(.1) % plot
end
Cells heal after a specified time
To model this, it is better to use 0 for a non-infected cell and a positive integer for an infected cell, which indicated how long it has been infected.
A cell heals after it has been infected for a specified number of iterations (but can immediately become infeced again...)
The code uses convolution, as the previous one, but now already infected cells need to be dealt with separately from newly infected cells, and so a true Moore neighbourhood is used.
n = 200;
p = (ceil(rand(n,n)*1.0005))-1; % 0: non-infected. 1: just infected
T = 20; % time to heal
neighbourhood = [1 1 1; 1 0 1; 1 1 1]; % Moore
for t = 1:356
already_infected = p>0; % logical index
p(already_infected) = p(already_infected)+1; % increase time count for infected
newly_infected = conv2(p>0, neighbourhood, 'same')>0; % logical index
p(newly_infected & ~already_infected) = 1; % these just became infected
newly_healed = p==T; % logical index
p(newly_healed) = 0; % these are just healed
image(p>0), axis equal, axis tight, colormap([.4 .4 .5; .8 0 0]), pause(.1) % plot
% infected / non-infected state
end

Related

How to remove lines that are on obstacles PRM example

I have the following code to generate a PRM map that will be used for A* application. There exist 2 problems with the code
It keeps the blue lines representing the original PRM where lines can cross over obstacles. I don't want to keep the blue lines but I couldn't find the way to remove them.
The green lines are going over obstacles even though they shouldn't
The code is as follows
clc;
clear all;
close all;
seed = 123512;
rng(seed);
xaxis = 100;
yaxis = 100;
obstacles = false(xaxis,yaxis);
[X,Y] = meshgrid(1:xaxis,1:yaxis);
obstacles(50:75,50:75) = true;
obstacles(25:35,30:40) = true;
obstacles(25:35,60:80) = true;
figure;
imshow(~obstacles,"InitialMagnification",1000);
axis([0 xaxis 0 yaxis]);
axis xy;
axis on;
%PRM PARAMETERS
max_nodes_connect = 4;
max_connect_len = 40;
segments = 1;
max_nodes_grid = 30;
skipped = 0;
%PRM ALGO
nodes = 0; %Counter
map = zeros(size(obstacles)); %generate map
map(obstacles) = 1; %put the obstacles
Graph_connections = Inf(max_nodes_grid,max_nodes_connect + 1); %rows = # nodes cols = ID and neighbors
while (nodes < max_nodes_grid)
node_x = randi(xaxis);
node_y = randi(yaxis);
if(map(node_y,node_x)==1 || map(node_y,node_x)==2)
continue;
end
nodes = nodes + 1; %a valid node generated
map(node_y,node_x) = 2; %2 means there exists a node at that location
hold on
scatter(node_x,node_y,"red","filled")
%NODES TO CONNECT
nodes_to_connect = [];
distances = [];
for i= 1:numel(Graph_connections(:,1))
if(Graph_connections(i,1)==Inf)
break
end
[row,col] = ind2sub(size(map),Graph_connections(i,1));
%Check if within range
if(norm([node_y,node_x]-[row,col])>max_connect_len)
continue;
end
line_on_obstacle = check_obstacle(map,node_x,node_y,row,col);
%Check if obstacle thru line HAS TO BE WRITTEN
if(line_on_obstacle)
disp("Check Obstacle: " + line_on_obstacle);
skipped = skipped + 1;
continue;
end
nodes_to_connect = [nodes_to_connect, Graph_connections(i,1)];
distances = [distances; [Graph_connections(i,1),norm([node_y,node_x]-[row,col])]];
end
Graph_connections(nodes,1) = sub2ind(size(map),node_y,node_x);
if(size(distances)>0)
sorted_distances = sortrows(distances,2);
for i = 1:min(max_nodes_connect,size(sorted_distances,1))
Graph_connections(nodes,i+1) = sorted_distances(i,1);
[row,col] = ind2sub(size(map),sorted_distances(i,1));
if(line_on_obstacle==false)
disp("Line is not on obstacle")
hold on
plot([node_x,col],[node_y,row],"green","LineWidth",1.5);
continue;
else
disp("Line is on obstacle: " + [node_x,col] + " " + [node_y,row]);
break;
end
end
disp("==========================")
end
end
function on_line = check_obstacle(map,node_x,node_y,row,col)
on_line = 0;
my_line = line([node_x,col],[node_y,row]);
line_spacing = max(abs(my_line.XData(1) - my_line.XData(2))+1,abs(my_line.XData(1) - my_line.XData(2))+1);
x_coordinates_line = round(linspace(my_line.XData(1),my_line.XData(2),line_spacing));
y_coordinates_line = round(linspace(my_line.YData(1),my_line.YData(2),line_spacing));
for i = 1:line_spacing
if(map(x_coordinates_line(i),y_coordinates_line(i))==1)
disp("ON OBSTACLE: " + x_coordinates_line(i) + " " + y_coordinates_line(i));
on_line = true;
break;
end
end
end
The check_obstacle function is used to check if the points on the line are in the boundaries of obstacles. What am I missing here?
close all;clear all;clc
format short
nx=100;ny=100; % grid size
[X,Y]=meshgrid(1:nx,1:ny);
Nobst=3 % amount obstacles
Nnet=30 % amount net points
Dmax=100 % net segment max length
% OBSTACLES
% define obstacles.
% Following are as defined in question
P1=[50 50; 75 50; 75 75; 50 75; 50 50];
P2=[25 30; 25 40; 35 40; 35 30; 25 30];
P3=[25 60; 25 80; 35 80;35 60;25 60];
% obstacle points all in one array
Pobst=[P1(:);P2(:);P3(:)];
Pobst=reshape(Pobst,[size(P1,1),size(P1,2),Nobst]);
% plot obstacles
hp=[]
figure(1)
ax=gca
hp=patch(squeeze(Pobst(:,1,:)),squeeze(Pobst(:,2,:)),[.5 .5 .5])
axis([1 nx 1 ny]);grid on
hp.EdgeAlpha=0;
ax.DataAspectRatio=[1 1 1]
hold(ax,'on')
% obstacle segments list : [x1 y1 x2 y2 d(X1,Y1)]
Lobst1=[]
for k=2:1:size(P1,1)
Lobst1=[Lobst1; [P1(k-1,:) P1(k,:) ((P1(k-1,1)-P1(k,1))^2+(P1(k-1,2)-P1(k,2))^2)^.5]];
end
Lobst2=[]
for k=2:1:size(P2,1)
Lobst2=[Lobst2; [P2(k-1,:) P2(k,:) ((P2(k-1,1)-P2(k,1))^2+(P2(k-1,2)-P2(k,2))^2)^.5]];
end
Lobst3=[]
for k=2:1:size(P3,1)
Lobst3=[Lobst3; [P3(k-1,:) P3(k,:) ((P3(k-1,1)-P3(k,1))^2+(P3(k-1,2)-P3(k,2))^2)^.5]];
end
Lobst=[Lobst1;Lobst2;Lobst3]
%% NETWORK
% all grid points outside obstacles
[in1,on1]=inpolygon(X(:),Y(:),P1(:,1),P1(:,2));
[in2,on2]=inpolygon(X(:),Y(:),P2(:,1),P2(:,2));
[in3,on3]=inpolygon(X(:),Y(:),P3(:,1),P3(:,2));
Xout=X(~in1 & ~in2 & ~in3);Yout=Y(~in1 & ~in2 & ~in3);
% plot(ax,Xout,Yout,'og','LineStyle','none') % check
% choose Nnet points outside obstacles
nP2=randi([1 numel(Xout)],Nnet,1);
Pnet=[Xout(nP2) Yout(nP2)];
plot(ax,Pnet(:,1),Pnet(:,2),'or','LineStyle','none')
% net segments list [x1 y1 x2 y2 d(X2,Y2) 0/1] 6th column [0 1] 1: draw 0: do not draw
nLnet=nchoosek([1:size(Pnet,1)],2);
Lnet=[Pnet(nLnet(:,1),1) Pnet(nLnet(:,1),2) ... % segment 1st point
Pnet(nLnet(:,2),1) Pnet(nLnet(:,2),2) ... % segment 2nd point
((Pnet(nLnet(:,1),1)-Pnet(nLnet(:,1),2)).^2+(Pnet(nLnet(:,2),1)+Pnet(nLnet(:,2),2)).^2).^.5 ... % segment length
ones(size(nLnet,1),1)];
% check all net links are plotted
for k=1:1:size(Lnet,1)
plot(ax,[Lnet(k,1) Lnet(k,3)],[Lnet(k,2) Lnet(k,4)],'b');
hold(ax,'on')
end
% remove segments longer than Dmax
Lnet=sortrows(Lnet,5,'descend');
[~,n1]=max(Lnet(:,5)<=Dmax);
Lnet(1:n1-1,:)=[];
for k=1:1:size(Lnet,1)
plot(ax,[Lnet(k,1) Lnet(k,3)],[Lnet(k,2) Lnet(k,4)],'r');
hold(ax,'on')
end
%%
Redrawing and NOT removing net segments longer than Dmax
close all
hp=[]
figure(1)
ax=gca
hp=patch(squeeze(Pobst(:,1,:)),squeeze(Pobst(:,2,:)),[.5 .5 .5])
axis([1 nx 1 ny]);grid on
hp.EdgeAlpha=0;
ax.DataAspectRatio=[1 1 1]
hold(ax,'on')
plot(ax,Pnet(:,1),Pnet(:,2),'or','LineStyle','none')
Lnet=[Pnet(nLnet(:,1),1) Pnet(nLnet(:,1),2) ... % segment 1st point
Pnet(nLnet(:,2),1) Pnet(nLnet(:,2),2) ... % segment 2nd point
((Pnet(nLnet(:,1),1)-Pnet(nLnet(:,1),2)).^2+(Pnet(nLnet(:,2),1)+Pnet(nLnet(:,2),2)).^2).^.5 ... % segment length
ones(size(nLnet,1),1)];
% check what pair segments intersect
for k2=1:1:size(Lnet,1)
allclear=ones(1,size(Lobst,1));
% allclear=zeros(1,size(Lobst,1));
for k1=1:1:size(Lobst,1)
% segments are contained in lines : check lines intersect
x1o=Lobst(k1,1);y1o=Lobst(k1,2);x2o=Lobst(k1,3);y2o=Lobst(k1,4);
x1n=Lnet(k2,1);y1n=Lnet(k2,2);x2n=Lnet(k2,3);y2n=Lnet(k2,4);
x1=x1o;x2=x2o;y1=y1o;y2=y2o;
x3=x1n;x4=x2n;y3=y1n;y4=y2n;
% t1 : x parameter
t1=((x1-x3)*(y3-y4)-(y1-y3)*(x3-x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4));
xp=x1+t1*(x2-x1); % xp : crossing x coordinage
% u1 : y parameter
u1=-((x1-x2)*(y1-y3)-(y1-y2)*(x1-x3))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4));
yp=y1+t1*(y2-y1); % yp : crossing y coordinate
% checks
plot(ax,x1o,y1o,'c*');plot(ax,x2o,y2o,'c*');plot(ax,[x1o x2o],[y1o y2o],'c')
plot(ax,x1n,y1n,'m*');plot(ax,x2n,y2n,'m*'); % plot(ax2,[x1n x2n],[y1n y2n],'m')
m1o=(y2o-y1o)/(x2o-x1o); % slopes
m2n=(y2n-y1n)/(x2n-x1n) ;
if (t1>=0 && t1<=1 && u1>=0 && u1<=1) && ...
(xp>=0 || xp<=nx || yp>=0 || yp<=ny)
allclear(k1)=0; % then do not plot this segment
end
end
if sum(allclear)==size(Lobst,1) %k2-th net segment hits no obstacles
plot(ax,x1n,y1n,'m*');plot(ax,x2n,y2n,'m*');plot(ax,[x1n x2n],[y1n y2n],'m')
elseif sum(allclear)~=size(Lobst,1)
Lnet(k2,end)=0;
end
end
Comments
1.- Note I have added format short because with format long there is decimal accretion right at the bottom of a few intersection points, that believe it or not, cause some false results.
2.- I like Torsen's explanation to find line segment intersections available here.
3.- There are faster ways to implement the main loop, but I make it go through all net-segment vs obstacle-element in case you may need it this way, to for instance count hits.
4.- There's also room for improvement in the way Lobst is generated.
5.- These lines
x1=x1o;x2=x2o;y1=y1o;y2=y2o;
x3=x1n;x4=x2n;y3=y1n;y4=y2n;
it's just an easy way to plug in formulation to already written lines, reducing amount variables is also left for next version.

Nested for loop error or indexing error in MATLAB

I have created this code from scratch. I want to make a plot and/or histogram of my "Observed" and "State" (these are 2 matrices). Some problem occurs at the 200th iteration, where my State matrix just becomes all 0's, there is no data being input into the State matrix. Can anyone troubleshoot the code? My possible states are {1,2,3}.
UPDATE:
When I adjust my n value, it adjusts how much of length T it will fill. So, n=5, only runs for 1/5 of T and n=1, run for entire length of T. I need an nxT matrix at the end (5X1000). The problem lies in the way I setup my for loops.
I still cannot solve the error though.
%Initialize A,pi,T
N = 3; # of states
%A is transition prob matrix
A = [.99,.005,.005;.005,.990,.005;.005,.005,.990];
%pi is initial state vector
pi = [1/3,1/3,1/3];
%T is # of observations per simulation
T = 1000;
%n is # of simulations
n = 5;
%Allocate space for the state matrix
State = zeros(n,T);
Observe = zeros(n,T);
%Create dummy emission matrix, must be row stochastic
B = ones(n,T)./T;
%loop over # of simulations
for i=1:1:n
x = rand(1);
if x <= (1/3)
State(i,1) = 1;
elseif x > (1/3) && x <= (2/3)
State(i,1) = 2;
else
State(i,1) = 3;
end
if State(i,1) == 1
b = -1;
elseif State(i,1) == 2
b = 0;
else
b = 1;
end
Observe(i,1)= normrnd(b,1);
for k=2:1:T
%Possible state 1,2,3
State(k) = randsample(N, 1, true, A(State(k-1),:));
if State == 1
c = -1;
elseif State == 2
c = 0;
else
c = 1;
end
Observe(i,k)= normrnd(c,1);
end
end
State(k) = randsample(N, 1, true, A(State(k-1),:));
This line is missing index (i) in position 1 inside State(k-1). It should be:
State(i,k) = randsample(N, 1, true, A(State(i,k-1),:));

Reason for Index exceeds matrix dimension error (matlab)?

I'm solving a tsp optimization problem with heuristics, and the following code works for all euclidian tsplib instances excluding the a280 instance that gives me the "Index exceeds matrix dimension" error and I can't figure out why?
I put comments so the code is understandable hopefully easily. The error happens at the before-last line of code i = mod(si(selected_edge)-1,n)+1;
n = size(a280,1); % n number of nodes
distances = dist(a280,a280');
savings = zeros(n);
lengths_obtained = [];
depot = 1 % depot is the central node
%% Test n number of solutions where each node is selected to be the depot
for depot = 1:n
%% Compute the matrix of savings of each pair of nodes
for i = 1:n
if i == depot
continue;
end
savings(i,(i+1):n)=distances(i,depot)+distances(depot,(i+1):n)-distances(i,(i+1):n);
end
%% Initialisation steps
minParent = 1:n;
% Rank the savings s(i,j) and list them in descending order of
% magnitude.
[~,si] = sort(savings(:),'descend');
si = si(1:fix(end/2));
% Setting cache
Nodes_depot = zeros(1,n); % binary vector, 1 if node i is disconnected from the depot, 0 otherwise
Nodes_depot(depot) = 1;
Nodes_depot_count = n-1;
degrees = zeros(1,n); % number of edges linking a node
selected_edge = 1;
pairs_of_nodes = zeros(n,2); % listing the couples (i,j) of nodes linked together
currentEdgeCount = 1;
%% Pair nodes as long as more than 2 nodes are still connected to the depot
while Nodes_depot_count>2
% Start with the edge (i,j) generating the topmost amount of
% savings.
i = mod(si(selected_edge)-1,n)+1;
j = floor((si(selected_edge)-1)/n)+1;
if Nodes_depot(i) == 0 && Nodes_depot(j)==0 && (minParent(i)~=minParent(j)) && i~=j && i~=depot && j~=depot
degrees(i) = degrees(i)+1;
degrees(j) = degrees(j)+1;
pairs_of_nodes(currentEdgeCount,:) = [i,j];
if minParent(i) < minParent(j)
minParent(minParent == minParent(j)) = minParent(i);
else
minParent(minParent == minParent(i)) = minParent(j);
end
currentEdgeCount = currentEdgeCount + 1;
% Removing i and/or j if they now are paired with two other
% nodes from partial tour.
if degrees(i) == 2
Nodes_depot(i) = 1;
Nodes_depot_count = Nodes_depot_count - 1;
end
if degrees(j) == 2
Nodes_depot(j) = 1;
Nodes_depot_count = Nodes_depot_count - 1;
end
end
selected_edge = selected_edge + 1;
end
If someone can push me in the right directions would be greatly appreciated. Thanks!!

Error in FDM for a coupled PDEs

Here is the code which is trying to solve a coupled PDEs using finite difference method,
clear;
Lmax = 1.0; % Maximum length
Wmax = 1.0; % Maximum wedth
Tmax = 2.; % Maximum time
% Parameters needed to solve the equation
K = 30; % Number of time steps
n = 3; % Number of space steps
m =30; % Number of space steps
M = 2;
N = 1;
Pr = 1;
Re = 1;
Gr = 5;
maxn=20; % The wave-front: intermediate point from which u=0
maxm = 20;
maxk = 20;
dt = Tmax/K;
dx = Lmax/n;
dy = Wmax/m;
%M = a*B1^2*l/(p*U)
b =1/(1+M*dt);
c =dt/(1+M*dt);
d = dt/((1+M*dt)*dy);
%Gr = gB*(T-T1)*l/U^2;
% Initial value of the function u (amplitude of the wave)
for i = 1:n
if i < maxn
u(i,1)=1.;
else
u(i,1)=0.;
end
x(i) =(i-1)*dx;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for j = 1:m
if j < maxm
v(j,1)=1.;
else
v(j,1)=0.;
end
y(j) =(j-1)*dy;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for k = 1:K
if k < maxk
T(k,1)=1.;
else
T(k,1)=0.;
end
z(k) =(k-1)*dt;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Value at the boundary
%for k=0:K
%end
% Implementation of the explicit method
for k=0:K % Time loop
for i=1:n % Space loop
for j=1:m
u(i,j,k+1) = b*u(i,j,k)+c*Gr*T(i,j,k+1)+d*[((u(i,j+1,k)-u(i,j,k))/dy)^(N-1)*((u(i,j+1,k)-u(i,j,k))/dy)]-d*[((u(i,j,k)-u(i,j-1,k))/dy)^(N-1)*((u(i,j,k)-u(i,j-1,k))/dy)]-d*[u(i,j,k)*((u(i,j,k)-u(i-1,j,k))/dx)+v(i,j,k)*((u(i,j+1,k)-u(i,j,k))/dy)];
v(i,j,k+1) = dy*[(u(i-1,j,k+1)-u(i,j,k+1))/dx]+v(i,j-1,k+1);
T(i,j,k+1) = T(i,j,k)+(dt/(Pr*Re))*{(T(i,j+1,k)-2*T(i,j,k)+T(i,j-1,k))/dy^2-Pr*Re{u(i,j,k)*((T(i,j,k)-T(i-1,j,k))/dx)+v(i,j,k)*((T(i,j+1,k)-T(i,j,k))/dy)}};
end
end
end
% Graphical representation of the wave at different selected times
plot(x,u(:,1),'-',x,u(:,10),'-',x,u(:,50),'-',x,u(:,100),'-')
title('graphs')
xlabel('X')
ylabel('Y')
But I am getting this error
Subscript indices must either be real positive integers or logicals.
I am trying to implement this
with boundary conditions
Can someone please help me out!
Thanks
To be quite honest, it looks like you started with something that's way over your head, just typed everything down in one go without thinking much, and now you are surprised that it doesn't work...
In the future, please break down problems like these into waaaay smaller chunks that you can individually plot, check, test, etc. Better yet, try simpler problems first (wave equation, heat equation, ...), gradually working your way up to this.
I say this so harshly, because there were quite a number of fairly basic things wrong with your code:
you've used braces ({}) and brackets ([]) exactly as they are written in the equation. In MATLAB, braces are a constructor for a special container object called a cell array, and brackets are used to construct arrays and matrices. To group things like in the equation, you always have to use parentheses (()).
You had quite a number of parentheses wrong, which became apparent when I re-grouped and broke up those huge unintelligible lines into multiple lines that humans can actually read with understanding
you forgot to take the absolute values in the 3rd and 4th terms of u
you looped over k = 0:K and j = 1:m and then happily index everything with k and j-1. MATLAB is 1-based, meaning, the first element of anything is element 1, and indexing with 0 is an error
you've initialized 3 vectors u, v and T, but then index those in the loop as if they are 3D arrays
Now, I've managed to come up with the following code, which runs OK and at least more or less agrees with the equations shown. But I think it still doesn't make much sense because I get only zeros out (except for the initial values).
But, with this feedback, you should be able to correct any problems left.
Lmax = 1.0; % Maximum length
Wmax = 1.0; % Maximum wedth
Tmax = 2.; % Maximum time
% Parameters needed to solve the equation
K = 30; % Number of time steps
n = 3; % Number of space steps
m = 30; % Number of space steps
M = 2;
N = 1;
Pr = 1;
Re = 1;
Gr = 5;
maxn = 20; % The wave-front: intermediate point from which u=0
maxm = 20;
maxk = 20;
dt = Tmax/K;
dx = Lmax/n;
dy = Wmax/m;
%M = a*B1^2*l/(p*U)
b = 1/(1+M*dt);
c = dt/(1+M*dt);
d = dt/((1+M*dt)*dy);
%Gr = gB*(T-T1)*l/U^2;
% Initial value of the function u (amplitude of the wave)
u = zeros(n,m,K+1);
x = zeros(n,1);
for i = 1:n
if i < maxn
u(i,1)=1.;
else
u(i,1)=0.;
end
x(i) =(i-1)*dx;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
v = zeros(n,m,K+1);
y = zeros(m,1);
for j = 1:m
if j < maxm
v(1,j,1)=1.;
else
v(1,j,1)=0.;
end
y(j) =(j-1)*dy;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
T = zeros(n,m,K+1);
z = zeros(K,1);
for k = 1:K
if k < maxk
T(1,1,k)=1.;
else
T(1,1,k)=0.;
end
z(k) =(k-1)*dt;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Value at the boundary
%for k=0:K
%end
% Implementation of the explicit method
for k = 2:K % Time loop
for i = 2:n % Space loop
for j = 2:m-1
u(i,j,k+1) = b*u(i,j,k) + ...
c*Gr*T(i,j,k+1) + ...
d*(abs(u(i,j+1,k) - u(i,j ,k))/dy)^(N-1)*((u(i,j+1,k) - u(i,j ,k))/dy) - ...
d*(abs(u(i,j ,k) - u(i,j-1,k))/dy)^(N-1)*((u(i,j ,k) - u(i,j-1,k))/dy) - ...
d*(u(i,j,k)*((u(i,j ,k) - u(i-1,j,k))/dx) +...
v(i,j,k)*((u(i,j+1,k) - u(i ,j,k))/dy));
v(i,j,k+1) = dy*(u(i-1,j,k+1)-u(i,j,k+1))/dx + ...
v(i,j-1,k+1);
T(i,j,k+1) = T(i,j,k) + dt/(Pr*Re) * (...
(T(i,j+1,k) - 2*T(i,j,k) + T(i,j-1,k))/dy^2 - Pr*Re*(...
u(i,j,k)*((T(i,j,k) - T(i-1,j,k))/dx) + v(i,j,k)*((T(i,j+1,k) - T(i,j,k))/dy))...
);
end
end
end
% Graphical representation of the wave at different selected times
figure, hold on
plot(x, u(:, 1), '-',...
x, u(:, 10), '-',...
x, u(:, 50), '-',...
x, u(:,100), '-')
title('graphs')
xlabel('X')
ylabel('Y')

MeanShift Clustering on dataset

I have a numeric dataset and I want to cluster data with a non-parametric algorithm. Basically, I would like to cluster without specifying the number of clusters for the input. I am using this code that I accessed through the MathWorks File Exchange network which implements the Mean Shift algorithm. However, I don't Know how to adapt my data to this code as my dataset has dimensions 516 x 19.
function [clustCent,data2cluster,cluster2dataCell] =MeanShiftCluster(dataPts,bandWidth,plotFlag)
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
%perform MeanShift Clustering of data using a flat kernel
%
% ---INPUT---
% dataPts - input data, (numDim x numPts)
% bandWidth - is bandwidth parameter (scalar)
% plotFlag - display output if 2 or 3 D (logical)
% ---OUTPUT---
% clustCent - is locations of cluster centers (numDim x numClust)
% data2cluster - for every data point which cluster it belongs to (numPts)
% cluster2dataCell - for every cluster which points are in it (numClust)
%
% Bryan Feldman 02/24/06
% MeanShift first appears in
% K. Funkunaga and L.D. Hosteler, "The Estimation of the Gradient of a
% Density Function, with Applications in Pattern Recognition"
%*** Check input ****
if nargin < 2
error('no bandwidth specified')
end
if nargin < 3
plotFlag = true;
plotFlag = false;
end
%**** Initialize stuff ***
%[numPts,numDim] = size(dataPts);
[numDim,numPts] = size(dataPts);
numClust = 0;
bandSq = bandWidth^2;
initPtInds = 1:numPts
maxPos = max(dataPts,[],2); %biggest size in each dimension
minPos = min(dataPts,[],2); %smallest size in each dimension
boundBox = maxPos-minPos; %bounding box size
sizeSpace = norm(boundBox); %indicator of size of data space
stopThresh = 1e-3*bandWidth; %when mean has converged
clustCent = []; %center of clust
beenVisitedFlag = zeros(1,numPts,'uint8'); %track if a points been seen already
numInitPts = numPts %number of points to posibaly use as initilization points
clusterVotes = zeros(1,numPts,'uint16'); %used to resolve conflicts on cluster membership
while numInitPts
tempInd = ceil( (numInitPts-1e-6)*rand) %pick a random seed point
stInd = initPtInds(tempInd) %use this point as start of mean
myMean = dataPts(:,stInd); % intilize mean to this points location
myMembers = []; % points that will get added to this cluster
thisClusterVotes = zeros(1,numPts,'uint16'); %used to resolve conflicts on cluster membership
while 1 %loop untill convergence
sqDistToAll = sum((repmat(myMean,1,numPts) - dataPts).^2); %dist squared from mean to all points still active
inInds = find(sqDistToAll < bandSq); %points within bandWidth
thisClusterVotes(inInds) = thisClusterVotes(inInds)+1; %add a vote for all the in points belonging to this cluster
myOldMean = myMean; %save the old mean
myMean = mean(dataPts(:,inInds),2); %compute the new mean
myMembers = [myMembers inInds]; %add any point within bandWidth to the cluster
beenVisitedFlag(myMembers) = 1; %mark that these points have been visited
%*** plot stuff ****
if plotFlag
figure(12345),clf,hold on
if numDim == 2
plot(dataPts(1,:),dataPts(2,:),'.')
plot(dataPts(1,myMembers),dataPts(2,myMembers),'ys')
plot(myMean(1),myMean(2),'go')
plot(myOldMean(1),myOldMean(2),'rd')
pause
end
end
%**** if mean doesnt move much stop this cluster ***
if norm(myMean-myOldMean) < stopThresh
%check for merge posibilities
mergeWith = 0;
for cN = 1:numClust
distToOther = norm(myMean-clustCent(:,cN)); %distance from posible new clust max to old clust max
if distToOther < bandWidth/2 %if its within bandwidth/2 merge new and old
mergeWith = cN;
break;
end
end
if mergeWith > 0 % something to merge
clustCent(:,mergeWith) = 0.5*(myMean+clustCent(:,mergeWith)); %record the max as the mean of the two merged (I know biased twoards new ones)
%clustMembsCell{mergeWith} = unique([clustMembsCell{mergeWith} myMembers]); %record which points inside
clusterVotes(mergeWith,:) = clusterVotes(mergeWith,:) + thisClusterVotes; %add these votes to the merged cluster
else %its a new cluster
numClust = numClust+1 %increment clusters
clustCent(:,numClust) = myMean; %record the mean
%clustMembsCell{numClust} = myMembers; %store my members
clusterVotes(numClust,:) = thisClusterVotes;
end
break;
end
end
initPtInds = find(beenVisitedFlag == 0); %we can initialize with any of the points not yet visited
numInitPts = length(initPtInds); %number of active points in set
end
[val,data2cluster] = max(clusterVotes,[],1); %a point belongs to the cluster with the most votes
%*** If they want the cluster2data cell find it for them
if nargout > 2
cluster2dataCell = cell(numClust,1);
for cN = 1:numClust
myMembers = find(data2cluster == cN);
cluster2dataCell{cN} = myMembers;
end
end
This is the test code I am using to try and get the Mean Shift program to work:
clear
profile on
nPtsPerClust = 250;
nClust = 3;
totalNumPts = nPtsPerClust*nClust;
m(:,1) = [1 1];
m(:,2) = [-1 -1];
m(:,3) = [1 -1];
var = .6;
bandwidth = .75;
clustMed = [];
%clustCent;
x = var*randn(2,nPtsPerClust*nClust);
%*** build the point set
for i = 1:nClust
x(:,1+(i-1)*nPtsPerClust:(i)*nPtsPerClust) = x(:,1+(i-1)*nPtsPerClust:(i)*nPtsPerClust) + repmat(m(:,i),1,nPtsPerClust);
end
tic
[clustCent,point2cluster,clustMembsCell] = MeanShiftCluster(x,bandwidth);
toc
numClust = length(clustMembsCell)
figure(10),clf,hold on
cVec = 'bgrcmykbgrcmykbgrcmykbgrcmyk';%, cVec = [cVec cVec];
for k = 1:min(numClust,length(cVec))
myMembers = clustMembsCell{k};
myClustCen = clustCent(:,k);
plot(x(1,myMembers),x(2,myMembers),[cVec(k) '.'])
plot(myClustCen(1),myClustCen(2),'o','MarkerEdgeColor','k','MarkerFaceColor',cVec(k), 'MarkerSize',10)
end
title(['no shifting, numClust:' int2str(numClust)])
The test script generates random data X. In my case. I want to use the matrix D of size 516 x 19 but I am not sure how to adapt my data to this function. The function is returning results that are not agreeing with my understanding of the algorithm.
Does anyone know how to do this?