|
33 | 33 | # with implicit denominators lambdas, betas & phis, resp. |
34 | 34 | # (except after setup, when beta is cast to double and downscaled), |
35 | 35 | lambdas = 16; # no. of divisions of capacity share, lambda, if lambdaSum=1 |
36 | | -betas = 400; # no. of divisions of normalized burst delay, beta, if betaSum=1 |
37 | | -phis = 8; # no. of divisions of phase shift, phi, in 360deg |
| 36 | +betas = 32; # no. of divisions of normalized burst delay, beta, if betaSum=1 |
| 37 | +phis = 4; # no. of divisions of phase shift, phi, in 360deg |
38 | 38 | smidgen = 0.123456789; # To avoid unrealistic degree of exact phase lock |
39 | 39 |
|
40 | 40 |
|
41 | 41 | # set qt_mode to true(1) to produce one time series of the queue |
42 | 42 | # set qt_mode to false(1) to scan parameter space and produce marking statistics |
43 | 43 | qt_mode = false(1); |
44 | 44 | if (qt_mode) |
45 | | - i_lambda = 1; # index of lambda to plot if in qt_mode |
46 | | - i_beta = 2; # index of beta to plot if in qt_mode |
| 45 | + i_lambda = 2; # index of lambda to plot if in qt_mode |
| 46 | + i_beta = 6; # index of beta to plot if in qt_mode |
47 | 47 | i_phi = 1; # index of phi to plot if in qt_mode |
48 | 48 | endif |
49 | 49 |
|
|
193 | 193 | # t : current time |
194 | 194 | # i_head : which flow is at the head of the queue |
195 | 195 | # t_burst[2] : start time of next burst from each flow |
196 | | - # i_next_burst : which burst is next |
| 196 | + # i_bnxt : which burst is next |
197 | 197 |
|
198 | 198 | # Time is scanned in two passes: |
199 | 199 | # 1) to find where the q will be shortest |
|
238 | 238 | # Whether q=0 at the start or end of the min phase shift from freq to rare |
239 | 239 | # depends on whether the freq burst is large enough to keep the queue |
240 | 240 | # busy over t_delta_min. |
241 | | - # In each case, i_next_burst and i_head are pointed to the flow that |
| 241 | + # In each case, i_bnxt and i_head are pointed to the flow that |
242 | 242 | # bursts at the origin and the time until the next burst for each flow, |
243 | 243 | # t_burst[2], is set. |
244 | 244 | if (t_delta_min4 < t_delta_min5) |
| 245 | + ## ToDo: Try using ranges |
245 | 246 | # q=0 at freq burst before min phase shift |
246 | | - t_burst(i_freq) = 0; |
247 | | - t_burst(i_rare) = t_delta(1,i_4); |
248 | | - if (t_burst(i_rare) <= 0) # <= for robustness |
249 | | - [~, i_head] = min(beta(:,j)); |
250 | | - else |
| 247 | + t_burst{i_freq} = 0 : ti(i,j,i_freq) : t_max(i,j); |
| 248 | + t_burst{i_rare} = t_delta(1,i_4) : ti(i,j,i_rare) : t_max(i,j) ... |
| 249 | + + t_delta(1,i_4); # Past t_max to prevent overflow |
| 250 | +## t_burst(i_freq) = 0; |
| 251 | +## t_burst(i_rare) = t_delta(1,i_4); |
| 252 | + if (t_burst{i_rare}(1) > 0) |
251 | 253 | i_head = i_freq; |
| 254 | + else |
| 255 | + # Tie-break if initial bursts coincide |
| 256 | + [~, i_head] = min(beta(:,j)); |
252 | 257 | endif |
253 | | - i_next_burst = i_head; |
254 | 258 | else |
| 259 | + ## ToDo: Try using ranges |
255 | 260 | # q=0 at rare burst after min phase shift |
256 | | - t_burst(i_rare) = 0; |
257 | | - t_burst(i_freq) = ti(i,j,i_freq) - t_delta(1,i_5); # >= 0 |
258 | | - i_next_burst = i_head = i_rare; |
| 261 | + t_burst{i_rare} = 0 : ti(i,j,i_rare) : t_max(i,j); |
| 262 | + t_burst{i_freq} = ti(i,j,i_freq) - t_delta(1,i_5) ... # >= 0 |
| 263 | + : ti(i,j,i_freq) : t_max(i,j) ... |
| 264 | + + ti(i,j,i_freq) - t_delta(1,i_5); # Past t_max to prevent overflow |
| 265 | +## t_burst(i_rare) = 0; |
| 266 | +## t_burst(i_freq) = ti(i,j,i_freq) - t_delta(1,i_5); # >= 0 |
| 267 | + i_head = i_rare; |
259 | 268 | endif |
260 | | - t_next_burst = 0; |
| 269 | + i_bnxt = i_head; |
| 270 | + i_tb = ones(2,1); |
| 271 | +## t_next_burst = 0; |
261 | 272 |
|
262 | 273 | # #2 time scan |
263 | 274 | t = 0; |
|
271 | 282 | # * qt_out(:,4) : which flow is at the head of the q; 0:1 means q(1:2); |
272 | 283 | # * qt_out(:,5) : whether queue is above threshold (q>=1) after t. |
273 | 284 | while (t < t_max(i,j)) |
274 | | - |
275 | 285 | # The contributions from each flow to the queue are piecewise linear |
276 | 286 | # between 'events', where an 'event' is a discontinuity in one of the |
277 | 287 | # contributions or when the queue crosses the marking threshold |
|
281 | 291 | # Check whether combined q falls below threshold |
282 | 292 | # before head q empties or burst arrives |
283 | 293 | if ( (ott) && ... |
284 | | - ( ((t_next_empty <= t_next_burst) && (q_xs <= q(i_head))) || ... |
285 | | - ((t_next_empty > t_next_burst) && (q_xs <= t_next_burst - t)) ... |
| 294 | + ( ((t_next_empty <= t_burst{i_bnxt}(i_tb(i_bnxt))) && (q_xs <= q(i_head))) || ... |
| 295 | + ((t_next_empty > t_burst{i_bnxt}(i_tb(i_bnxt))) && (q_xs <= t_burst{i_bnxt}(i_tb(i_bnxt)) - t)) ... |
286 | 296 | ) ... |
287 | 297 | ) |
288 | 298 | # Combined queue has fallen below threshold before any other event |
|
292 | 302 | q(i_head) -= q_xs; |
293 | 303 | qt_mode && (qt_out(++i_event,:) = [t, q(1), q(2), i_head-1, ott]); |
294 | 304 | ott = 0; |
295 | | - # The earlier condition (q_xs <= t_next_burst - t) could have been |
| 305 | + # The earlier condition (q_xs <= t_burst{i_bnxt}(i_tb(i_bnxt)) - t) could have been |
296 | 306 | # changed to < to suppress the following qt_out in the case when it |
297 | 307 | # seems redundant when q drains exactly to the threshold just |
298 | 308 | # before a burst. But, for robustness, if (q==1) ott=0, even if q |
|
309 | 319 | endif |
310 | 320 | endif |
311 | 321 | else |
312 | | - if ((q(i_head) > 0) && (t_next_empty <= t_next_burst)) |
| 322 | + if ((q(i_head) > 0) && (t_next_empty <= t_burst{i_bnxt}(i_tb(i_bnxt)))) |
313 | 323 | # q(i_head) has emptied (defer any simultaneous burst to next event) |
314 | 324 | t = t_next_empty; |
315 | 325 | if (ott) |
|
326 | 336 | # No need to update i_other - not read elsewhere |
327 | 337 | else |
328 | 338 | # Both q's empty |
329 | | - i_head = i_next_burst; |
| 339 | + i_head = i_bnxt; |
330 | 340 | endif |
331 | 341 | qt_mode && (qt_out(++i_event,:) = [t, q(1), q(2), i_head-1, ott]); |
332 | 342 | else |
333 | 343 | # Burst has arrived |
334 | 344 | if (q(i_head) > 0) |
335 | 345 | # Drain head queue since last event |
336 | | - q(i_head) -= t_next_burst - t; # resulting q(i_head) will be >0 |
| 346 | + q(i_head) -= t_burst{i_bnxt}(i_tb(i_bnxt)) - t; # resulting q(i_head) will be >0 |
337 | 347 | if (ott) |
338 | 348 | # Add to p_e |
339 | | - p(k, i_head, 2) += t_next_burst - t; |
| 349 | + p(k, i_head, 2) += t_burst{i_bnxt}(i_tb(i_bnxt)) - t; |
340 | 350 | endif |
341 | 351 | q_xs = sum(q) - 1; |
342 | 352 | endif |
343 | | - t = t_next_burst; |
| 353 | + t = t_burst{i_bnxt}(i_tb(i_bnxt)); |
344 | 354 | qt_mode && (qt_out(++i_event,:) = [t, q(1), q(2), i_head-1, ott]); |
345 | 355 | ## ToDo: more elegantly, increment t to pre-determined matrix |
346 | | - if (t >= t_max(i,j) - 8*eps(t_max(1,j))) |
| 356 | +## if (i_tb(i_bnxt) >= size(t_burst{i_bnxt},2)) |
| 357 | + # The precision of t is 1 eps 'cos it is assigned from a range. |
| 358 | + # However, an octave bug loses another eps when within a script |
| 359 | + # The alternative of testing for the end of the vector led to very |
| 360 | + # complex code |
| 361 | + if (t >= t_max(i,j) - 2*eps(t)) |
| 362 | +## if (t >= t_max(i,j) - 8*eps(t_max(1,j))) |
347 | 363 | break |
348 | 364 | endif |
349 | 365 | # Add burst to tail |
350 | 366 | # but first check whether combined queue rises above threshold |
351 | | - delta_q = beta(i_next_burst,j); |
352 | | - if ( (ott == 0) && (q_xs + beta(i_next_burst,j) > 0) ) |
| 367 | + delta_q = beta(i_bnxt,j); |
| 368 | + if ( (ott == 0) && (q_xs + beta(i_bnxt,j) > 0) ) |
353 | 369 | # Take care! if (q_xs + beta == tiny), e.g tiny = 1.1102e-16 |
354 | 370 | # after q incremented as below, q_xs = (sum(q) - 1) == 0; |
355 | | - q(i_next_burst) -= q_xs; |
| 371 | + q(i_bnxt) -= q_xs; |
356 | 372 | delta_q += q_xs; |
357 | 373 | qt_mode && (qt_out(++i_event,:) = [t, q(1), q(2), i_head-1, ott]); |
358 | 374 | ott = 1; |
359 | 375 | endif |
360 | | - q(i_next_burst) += delta_q; |
| 376 | + q(i_bnxt) += delta_q; |
361 | 377 | if (ott) |
362 | 378 | # Add to p_s |
363 | | - p(k, i_next_burst, 1) += delta_q; |
| 379 | + p(k, i_bnxt, 1) += delta_q; |
364 | 380 | endif |
365 | 381 | qt_mode && (qt_out(++i_event,:) = [t, q(1), q(2), i_head-1, ott]); |
366 | 382 | # Prepare for next burst |
367 | 383 | # Set t_burst for next burst from this flow |
368 | 384 | ## ToDo: increment a pointer along a range for precision |
369 | | - t_burst(i_next_burst) += ti(i,j,i_next_burst); |
| 385 | +## if (i_tb(i_bnxt) >= size(t_burst{i_bnxt},2)) |
| 386 | + # Earlier size test prevents overflow here |
| 387 | +## # Reached end of one flow's bursts without reaching t_max |
| 388 | +## # Force the next burst index to point to the other flow |
| 389 | +## i_bnxt = !(i_bnxt-1) + 1; |
| 390 | +## else |
| 391 | + i_tb(i_bnxt)++; |
| 392 | +## t_burst(i_bnxt) += ti(i,j,i_bnxt); |
370 | 393 | # Calc arrival time and flow id of next burst, handling tie if nec. |
371 | | - [t_next_burst, i_next_burst] = min(t_burst); |
372 | | - if (t_burst(1) == t_burst(2)) |
373 | | - [~, i_next_burst] = min(beta(:,j)); |
| 394 | + [~, i_bnxt] = min([t_burst{1}(i_tb(1)), t_burst{2}(i_tb(2))]); |
| 395 | +## [t_next_burst, i_bnxt] = min(t_burst); |
| 396 | + if (t_burst{1}(i_tb(1)) == t_burst{2}(i_tb(2))) |
| 397 | + [~, i_bnxt] = min(beta(:,j)); |
374 | 398 | endif |
| 399 | +## endif |
375 | 400 | endif |
376 | 401 | endif |
377 | 402 | endwhile |
|
465 | 490 | ## i_rare |
466 | 491 | ## i_head |
467 | 492 | ## i_other |
468 | | -## i_next_burst |
| 493 | +## i_bnxt |
469 | 494 | ## |
470 | 495 | ## # Time intervals |
471 | 496 | ## t |
|
0 commit comments