1function placement = warmStartPlacement(initSolver, sn)
2% PLACEMENT = WARMSTARTPLACEMENT(INITSOLVER, SN)
4% Integer job placement (nstations x nclasses) decided by the steady-state
5% solution of an auxiliary solver.
7% If the auxiliary solver
is a SolverCTMC, the exact stationary distribution
8% over the aggregate state space
is computed and the placement
is the mode of
9% that distribution (the most probable aggregate state). For any other network
10% solver, the steady-state mean queue lengths are used instead and rounded to
11% an integer placement that conserves each closed-
class population.
13% Only service stations (Queue/Delay) receive an initial population.
17if isa(initSolver,
'SolverCTMC')
18 placement = placementFromCtmcSteadyState(initSolver, M, K);
20 placement = placementFromMeanQLen(initSolver, sn, M, K);
24function placement = placementFromCtmcSteadyState(ctmcSolver, M, K)
25% Placement from the exact CTMC stationary distribution: solve the CTMC,
26% aggregate the stationary probabilities over the aggregate (per-station,
27% per-class job count) state space, and return the aggregate state of maximum
28% stationary probability.
29snc = ctmcSolver.getStruct();
30[Q,~,SSq,~,~,~,snc] = solver_ctmc(snc, ctmcSolver.getOptions());
31pi = ctmc_solve_reducible(Q);
33pi(pi < GlobalConstants.Zero) = 0;
35% Aggregate the stationary probability over identical aggregate states and
36% locate the mode of the aggregate distribution.
37[uRows, ~, ic] = unique(SSq, 'rows');
38aggrProb = accumarray(ic, pi);
39[~, bidx] = max(aggrProb);
40modeState = uRows(bidx, :);
42% Map the aggregate-state columns (nclasses per stateful station, in station
43% order) onto the placement matrix.
44placement = zeros(M, K);
46for i = 1:snc.nstations
47 ind = snc.stationToNode(i);
48 if ~snc.isstateful(ind)
51 isService = snc.nodetype(ind) == NodeType.Queue || snc.nodetype(ind) == NodeType.Delay;
62function placement = placementFromMeanQLen(initSolver, sn, M, K)
63% Placement from the steady-state mean queue lengths of a generic network
64% solver: floor the per-station means and distribute the residual closed-class
65% jobs by largest remainder so each closed population
is conserved.
66QN = initSolver.getAvgQLen();
67placement = zeros(M, K);
70 isClosed = isfinite(njobs);
73 eligible = false(1, M);
75 ind = sn.stationToNode(i);
76 eligible(i) = sn.nodetype(ind) == NodeType.Queue || sn.nodetype(ind) == NodeType.Delay;
83 fracs(i) = m - floors(i);
87 placement(i, r) = floors(i);
90 % Largest-remainder apportionment of the residual jobs.
91 residual = round(njobs) - sum(floors);
93 [bf, bi] = max(fracs);
95 % All remainders consumed: place the leftover jobs at the
96 % reference station so the population
is conserved.
97 refStation = sn.refstat(r);
98 if ~eligible(refStation)
99 refStation = find(eligible, 1);
101 placement(refStation, r) = placement(refStation, r) + residual;
105 placement(bi, r) = placement(bi, r) + 1;
107 residual = residual - 1;