└── main.m /main.m: -------------------------------------------------------------------------------- 1 | clear all 2 | close all 3 | clc 4 | 5 | %% GPU config - if want to run some code block into GPU. (NOT FULLY IMPLEMENTED) 6 | %gpu = gpuDevice; 7 | %gpu(1); 8 | 9 | 10 | %% Main configuration values for this simulation 11 | 12 | dataset.nodeNo = 50; %Number of nodes 13 | dataset.nodePosition(1,:) = [1 50 50]; %(Sender node fixed position) 14 | dataset.nodePosition(2,:) = [2 900 900]; %(Receiver node fixed position) 15 | dataset.NeighborsNo = 5; 16 | dataset.range = 250; %Tolerance distance to became neighbor of one node (Euclidean distance based) 17 | dataset.atenuationFactor = 1.8; %Atenuation factor in freespace - ranges from 1.8 to 4 due environment 18 | dataset.minEnergy = 80; % Mw - Miliwatts (70% energy) 19 | dataset.maxEnergy = 100; % Mw - Miliwatts (Full energy (100%) - 1 mAh charge capacity within 1 Volt energy) 20 | dataset.energyconsumptionperCicle = 0.35; 21 | dataset.energyrecoveryperCicle = 0.2; 22 | dataset.energyfactor = 0.001; 23 | STenergy=10000; 24 | packet=0; 25 | iterationcounter=1; 26 | 27 | % Node position sortition 28 | 29 | for a = 3 : dataset.nodeNo 30 | 31 | dataset.nodeId = a; 32 | garbage.x = randi([1 900]); %Xpos sortition 33 | garbage.y = randi([1 900]); %Ypos sortition 34 | dataset.nodePosition(a,:) = [dataset.nodeId garbage.x garbage.y]; %NodeID, X and Y position into nodePosition table 35 | 36 | end 37 | 38 | % Euclidean Distance calc from one node to all others 39 | 40 | for i = 1 : dataset.nodeNo 41 | for j = 1: dataset.nodeNo 42 | garbage.x1 = dataset.nodePosition(i,2); 43 | garbage.x2 = dataset.nodePosition(j,2); 44 | garbage.y1 = dataset.nodePosition(i,3); 45 | garbage.y2 = dataset.nodePosition(j,3); 46 | 47 | dataset.euclidiana(i,j) = sqrt( (garbage.x1 - garbage.x2) ^2 + (garbage.y1 - garbage.y2)^2 ); 48 | 49 | end 50 | end 51 | 52 | % Edges matrix definition due "range" variable value 53 | 54 | dataset.weights = lt(dataset.euclidiana,dataset.range); 55 | 56 | % Graph construction 57 | 58 | G=graph(dataset.weights,'omitselfloops'); %Graph creation based on adjacency matrix (Edges matrix) built above 59 | 60 | % Euclidean distance extraction for all existente end-to-end formed by 61 | % "distance tolerance" (range variable value) 62 | 63 | for a = 1 : height(G.Edges) 64 | garbage.s = G.Edges.EndNodes(a,1); 65 | garbage.t = G.Edges.EndNodes(a,2); 66 | garbage.Z(a,:) = dataset.euclidiana(garbage.s,garbage.t); 67 | end 68 | G.Edges.Euclidiana = garbage.Z(:,1); 69 | 70 | %Initial energy sortition (from 70% to 100% - minEnergy and maxEnergy variable valeu) 71 | 72 | [dataset.nodePosition(:,4)] = dataset.maxEnergy -(dataset.maxEnergy-dataset.minEnergy)*rand(dataset.nodeNo,1); 73 | dataset.nodePosition(1:2,4)=STenergy; 74 | 75 | %All "G" (Graph object) based nodes degree to use as "node processing 76 | %status overload" (more connections, busier!) 77 | 78 | for a = 1: length(dataset.nodePosition(:,1)) 79 | 80 | dataset.nodePosition(a,5) = degree(G,dataset.nodePosition(a,1)); 81 | 82 | end 83 | 84 | % Pathloss calc of each Edges based in a freespace (1.8 factor) 85 | 86 | [G.Edges.Pathloss] = (10*dataset.atenuationFactor)*log10(G.Edges.Euclidiana); 87 | 88 | %End points coordinates and energy migration to G object 89 | 90 | for a = 1 : height(G.Edges) 91 | garbage.Sourcenode = G.Edges.EndNodes(a,1); 92 | garbage.Targetnode = G.Edges.EndNodes(a,2); 93 | G.Edges.SourcenodeXpos(a) = dataset.nodePosition(garbage.Sourcenode,2); 94 | G.Edges.SourcenodeYpos(a) = dataset.nodePosition(garbage.Sourcenode,3); 95 | G.Edges.TargetnodeXpos(a) = dataset.nodePosition(garbage.Targetnode,2); 96 | G.Edges.TargetnodeYpos(a) = dataset.nodePosition(garbage.Targetnode,3); 97 | G.Edges.ActiveEdge(a) = 1; 98 | end 99 | 100 | % Graph objects plot 101 | 102 | figure('units','normalized','innerposition',[0 0 1 1],'MenuBar','none') 103 | subplot(1,1,1) %1,3,1 (Line number,collumn number, graph id) - if you want to show more than 1 graph in same windows 104 | garbage.Xmax = 1500; 105 | garbage.Xmin = 0; 106 | garbage.Ymax = 1500; 107 | garbage.Ymin = 0; 108 | p = plot(G,'XData',(dataset.nodePosition(:,2)),'YData',(dataset.nodePosition(:,3))); 109 | line(dataset.nodePosition(1:2,2),dataset.nodePosition(1:2,3),'color','green','marker','o','linestyle','none','markersize',50) 110 | garbage.ax = gca; 111 | garbage.ax.XAxis.TickValues = 0:100:1000; 112 | garbage.ax.YAxis.TickValues = 0:100:1000; 113 | grid on 114 | hold on 115 | title(['Original WSN | ','Nodes number: ',num2str(dataset.nodeNo),' | Nodes range: ', num2str(dataset.range)]) 116 | pause(2) 117 | 118 | %Creation of some stuff needed 119 | garbage.deadnodelist=[]; 120 | garbage.deadnodeneighbors=[]; 121 | 122 | %% finding routes 123 | 124 | % Finding shortest path route 125 | G2 = shortestpathtree(G,1,2); 126 | 127 | 128 | %% Initialize patch existance test for loops 129 | 130 | fileID = fopen('report-noACO-simulation.txt','w'); %Open file to collect data to external file 131 | fprintf(fileID,'%6s %20s %20s %20s %20s\r\n','|NodeNo|','|No ACO Scene|','|Hops|','|Packets sent|','|Dead node|'); 132 | 133 | while ~isempty(G2.Edges) 134 | G2 = shortestpathtree(G,1,2); 135 | iterationcounter=iterationcounter+1; 136 | % Test if there is connection between node 1 and 2. If not, terminate! 137 | if isempty(G2.Edges) 138 | break 139 | end 140 | 141 | %Find edges found by shorthestpathtree in main G object 142 | for a = 1 : height(G2.Edges) 143 | source = G2.Edges.EndNodes(a,1); 144 | target = G2.Edges.EndNodes(a,2); 145 | garbage.edgesrow(a,:) = findedge(G,source,target); 146 | end 147 | 148 | %Find nodes involved in routing event 149 | garbage.routingnodes = unique(G2.Edges.EndNodes); 150 | garbage.routepath = shortestpath(G,1,2); 151 | 152 | %Construct localization dataset to nodes involved in routing event for plot effects 153 | for a = 1 : length(garbage.routingnodes) 154 | garbage.b=garbage.routingnodes(a,1); 155 | dataset.routingnodesPosition(a,:)=dataset.nodePosition(garbage.b,:); 156 | end 157 | 158 | %Find nodes not involved in routing to energy increase 159 | [garbage.Outroutenodes, garbage.Outroutenodesidx] = setdiff(dataset.nodePosition(:,1),garbage.routingnodes(:,1),'stable'); 160 | 161 | %Code block for energy usage (decrease) and packet send count 162 | while min(dataset.nodePosition(:,4))>0 163 | for a = 1 : length(garbage.routingnodes) 164 | node=garbage.routingnodes(a,1); 165 | dataset.nodePosition(node,4)=dataset.nodePosition(node,4)-dataset.energyconsumptionperCicle^rand()+dataset.energyrecoveryperCicle^rand(); 166 | packet=packet+1; 167 | 168 | end 169 | 170 | % for c = 1 : length(garbage.Outroutenodesidx) 171 | % rechargeblenode=garbage.Outroutenodesidx(c,1); 172 | % dataset.nodePosition(rechargeblenode,4)=dataset.nodePosition(rechargeblenode,4)+dataset.energyrecoveryperCicle*dataset.energyfactor*rand(); 173 | % b=1; 174 | % end 175 | %line(dataset.nodePosition(1:2,2),dataset.nodePosition(1:2,3),'color','green','marker','o','linestyle','none','markersize',100) 176 | end 177 | 178 | %Find dead node ID to discorver its neighbors and disable relative edges 179 | [garbage.deadnoderow] = find(dataset.nodePosition(:,4)<=0); 180 | for a = 1 : length(garbage.deadnoderow) 181 | deadnode=garbage.deadnoderow(a,1); 182 | for b = 1 : height(G.Edges) 183 | if ismember(G.Edges.EndNodes(b,1),deadnode) == 1 || ismember(G.Edges.EndNodes(b,2),deadnode) == 1 184 | G.Edges.ActiveEdge(b)=0; 185 | deadnode; 186 | pause(2) 187 | end 188 | end 189 | end 190 | garbage.deadnodelist(length(garbage.deadnodelist)+1,1)=deadnode; 191 | [garbage.deadedgerow]=find(G.Edges.ActiveEdge==0); 192 | 193 | %Mark node energy as NaN 194 | [garbage.deaddatasetnoderow]=find(dataset.nodePosition(:,4)<=0); 195 | for a = 1 : length(garbage.deaddatasetnoderow) 196 | b=garbage.deaddatasetnoderow(a,1); 197 | dataset.nodePosition(b,4)=NaN; 198 | end 199 | 200 | %Get number of hops between source and destination for this routing 201 | %session 202 | hopsnumber=length(garbage.routingnodes); 203 | 204 | %Informative section in command line - If need to disable plot loop to increase 205 | %processing speed 206 | 207 | msg=['Without ACO - Scene #: ',num2str(iterationcounter),' | Hops : ',num2str(hopsnumber),' | Packets sent: ', num2str(packet),' | Dead node: ', num2str(deadnode),' | Routing nodes: ', num2str(garbage.routepath)]; 208 | disp(msg) 209 | 210 | %plot for every dead edges iteration's result 211 | figure('units','normalized','innerposition',[0 0 1 1],'MenuBar','none') 212 | p = plot(G,'XData',(dataset.nodePosition(:,2)),'YData',(dataset.nodePosition(:,3))); 213 | line(dataset.nodePosition(1:2,2),dataset.nodePosition(1:2,3),'color','green','marker','o','linestyle','none','markersize',50) 214 | garbage.ax = gca; 215 | garbage.ax.XAxis.TickValues = 0:100:1000; 216 | garbage.ax.YAxis.TickValues = 0:100:1000; 217 | hold on 218 | 219 | %Plot all dead nodes in red 220 | for a = 1 : length(garbage.deadnodelist) 221 | garbage.b=garbage.deadnodelist(a,1); 222 | scatter(dataset.nodePosition(garbage.b,2),dataset.nodePosition(garbage.b,3),'MarkerFaceColor','red'); 223 | end 224 | 225 | %Title for every iteration's result 226 | title(['WSN shortest path: ',num2str(iterationcounter),' |hops: ',num2str(hopsnumber),' |Packets sent: ',num2str(packet),' |Dead node: ',num2str(deadnode),' |Router nodes: ', num2str(garbage.routepath)]) 227 | grid on 228 | pause(2) 229 | 230 | %Colect data to append to a external file for later usage - file open 231 | %command line in the begining 232 | 233 | report1=[dataset.nodeNo;iterationcounter;hopsnumber;packet;deadnode]; 234 | fprintf(fileID,'%6.0f %20.0f %20.0f %20.0f %20.0f\r\n',report1); 235 | 236 | %Remove dead edges from graph 237 | G = rmedge(G,garbage.deadedgerow(:,1)); 238 | 239 | %Mark nodes involved in route with green color 240 | scatter(dataset.routingnodesPosition(:,2),dataset.routingnodesPosition(:,3),'MarkerFaceColor','green'); 241 | pause(0.2) 242 | 243 | %Clear router nodes position to avoid erroneous plot 244 | clear dataset.routingnodesPosition 245 | end 246 | 247 | fclose(fileID); %Close external data collector file 248 | 249 | %Plot all dead nodes in red 250 | for a = 1 : length(garbage.deadnodelist) 251 | garbage.b=garbage.deadnodelist(a,1); 252 | scatter(dataset.nodePosition(garbage.b,2),dataset.nodePosition(garbage.b,3),'MarkerFaceColor','red'); 253 | end 254 | 255 | %Title for the last plot 256 | title(['WSN shortest path: ',num2str(iterationcounter),' |hops: ',num2str(hopsnumber),' |Packets sent: ',num2str(packet),' |Dead node: ',num2str(deadnode),' |Router nodes: ', num2str(garbage.routepath),'{\color{red} - ALL ROUTES UNAVAILABLE}']) 257 | 258 | %Message if there is no path between source and target even in the first iteration 259 | disp('NO ROUTES BETWEEN SOURCE (NODE1) AND TARGET (NODE2)') 260 | 261 | %% ANOTAÇÕES IMPORTANTES 262 | --------------------------------------------------------------------------------