1function [runtime, sruntime, results] = iterate(self, options)
2% ITERATE Perform LN solver iteration with optional MOL hierarchical approach
4% [RUNTIME, SRUNTIME, RESULTS] = ITERATE(OPTIONS)
6% For
'mol' method: Uses LQNS-style Method of Layers with nested iteration:
7% - Outer loop: Iterate on host (processor) layers until convergence
8% - Inner loop: Iterate on task layers until convergence (host demands fixed)
10% For other methods (
'default',
'moment3'): Uses flat iteration over all layers
13 options = self.options;
16line_debug(
'LN solver iterate starting: method=%s, nlayers=%d', self.options.method, self.nlayers);
18if ~strcmp(self.options.method,
'mol')
19 % Use parent implementation
for default/moment3
20 line_debug(
'Using parent EnsembleSolver iterate method');
21 [runtime, sruntime, results] = iterate@EnsembleSolver(self, options);
25line_debug(
'Using MOL (Method of Layers) iteration');
27%% MOL (Method of Layers) implementation
29E = getNumberOfModels(self);
31sruntime = zeros(1, E);
35% Get MOL configuration parameters
36mol_task_inner_max = self.options.config.mol_task_inner_max;
37mol_task_inner_tol = self.options.config.mol_task_inner_tol;
38mol_host_outer_tol = self.options.config.mol_host_outer_tol;
39mol_min_steps = self.options.config.mol_min_steps;
41% Initialize MOL iteration state
42self.mol_it_host_outer = 0;
44it = 0; % Total iteration counter
for results indexing
46%% First iteration: analyze ALL layers to initialize results
48if self.options.verbose
49 line_printf(
'\nMOL Initialization: Analyzing all layers');
54% Analyze all layers (host + task) in first iteration
56 [results{it, e}, solverTime] = self.analyze(it, e);
57 sruntime(it, e) = solverTime;
59self.results = results;
61% Full post-update after initial pass
64if self.options.verbose
65 line_printf(
' Done.\n');
68%% OUTER LOOP: Host (processor) layer iteration
69while (self.mol_it_host_outer < mol_min_steps || delta_host > mol_host_outer_tol) ...
70 && self.mol_it_host_outer < self.options.iter_max
72 self.mol_it_task_inner = 0;
75 % INNER LOOP: Task layer iteration (host layer demands kept FIXED)
76 while delta_task > mol_task_inner_tol && self.mol_it_task_inner < mol_task_inner_max
77 self.mol_it_task_inner = self.mol_it_task_inner + 1;
80 if self.options.verbose
81 line_printf(
'\nMOL Outer %d, Inner %d: ', self.mol_it_host_outer + 1, self.mol_it_task_inner);
85 sruntime(it, 1:E) = 0;
87 % Analyze TASK layers only (host demands remain fixed)
88 for e = self.taskLayerIndices
89 [results{it, e}, solverTime] = self.analyze(it, e);
90 sruntime(it, e) = solverTime;
93 % Copy host layer results from previous iteration (keeping them fixed)
94 for e = self.hostLayerIndices
95 results{it, e} = results{it-1, e};
98 self.results = results;
101 delta_task = self.computeTaskDelta();
103 % Update metrics and TASK layer demands only (not host layer demands)
104 self.updateMetrics(it);
105 self.updateThinkTimes(it);
106 if self.options.config.interlocking
107 self.updatePopulations(it);
109 % updateLayers updates service times - only refresh task layer solvers
110 self.updateLayers(it);
111 self.updateRoutingProbabilities(it);
113 % Reset only TASK layer solvers (keep host layers unchanged)
114 for e = self.taskLayerIndices
115 self.ensemble{e}.refreshChains();
116 switch self.solvers{e}.name
117 case {
'SolverMVA',
'SolverNC'}
118 self.ensemble{e}.refreshRates();
120 self.ensemble{e}.refreshProcesses();
122 self.solvers{e}.reset();
125 if self.options.verbose
126 line_printf(
'Task delta=%.6f', delta_task);
130 self.mol_it_host_outer = self.mol_it_host_outer + 1;
133 if self.options.verbose
134 line_printf(
'\nMOL Outer %d: Analyzing host layers... ', self.mol_it_host_outer);
138 sruntime(it, 1:E) = 0;
140 % Analyze HOST layers
141 for e = self.hostLayerIndices
142 [results{it, e}, solverTime] = self.analyze(it, e);
143 sruntime(it, e) = solverTime;
146 % Copy task layer results from previous iteration
147 for e = self.taskLayerIndices
148 results{it, e} = results{it-1, e};
151 self.results = results;
154 delta_host = self.computeHostDelta();
156 % Update metrics and HOST layer demands
157 self.updateMetrics(it);
158 self.updateThinkTimes(it);
159 if self.options.config.interlocking
160 self.updatePopulations(it);
162 self.updateLayers(it);
163 self.updateRoutingProbabilities(it);
165 % Reset HOST layer solvers (update their demands
for next outer iteration)
166 for e = self.hostLayerIndices
167 self.ensemble{e}.refreshChains();
168 switch self.solvers{e}.name
169 case {
'SolverMVA',
'SolverNC'}
170 self.ensemble{e}.refreshRates();
172 self.ensemble{e}.refreshProcesses();
174 self.solvers{e}.reset();
177 if self.options.verbose
178 line_printf(
'Host delta=%.6f (%d inner iters)\n', ...
179 delta_host, self.mol_it_task_inner);
186if self.options.verbose
187 line_printf(
'\nMOL Summary: %d outer iterations, total runtime: %.3fs\n', ...
188 self.mol_it_host_outer, runtime);