1function runtime = runAnalyzer(self, options)
7 options = self.getOptions;
9line_debug(options,
'LQNS: starting (method=%s, multiserver=%s)', options.method, options.config.multiserver);
11% Resolve
the execution backend before choosing
the temp dir. options.config.container:
12%
'' -> native binary; fall back to Docker only
if lqns
is missing
13%
'auto'/
true-> prefer Docker when a local imperialqore/lqns image exists
14%
'<image>' -> use
the named image
if present locally
15% Docker sidesteps
the MATLAB libstdc++/GLIBCXX clash noted below and pins a
16% reproducible lqns version, so tests opt into
'auto'.
18useRemote = isfield(options.config,
'remote') && options.config.remote;
19if isunix && ~useRemote
21 if isfield(options.config,
'container')
22 reqContainer = options.config.container;
24 if isempty(reqContainer) && ~SolverLQNS.hasLocalBinary()
25 % Native lqns absent: transparently fall back to a Docker image.
26 reqContainer = 'auto';
28 if ~isempty(reqContainer)
29 dockerImage = SolverLQNS.getDockerImage(reqContainer);
33% Snap-confined Docker cannot bind-mount
the system temp dir; stage
the model
34% under HOME when dispatching through Docker so
the volume mount
is visible.
35dirpath = lineTempName('lqns', ~isempty(dockerImage));
36filename = [dirpath,filesep,'model.lqnx'];
37self.model.writeXML(filename);
39%self.runAnalyzerChecks(options);
40Solver.resetRandomGeneratorSeed(options.seed);
49multiserver_praqma = '';
54 switch options.config.multiserver
56 multiserver_praqma='-Pmultiserver=conway';
58 multiserver_praqma='-Pmultiserver=rolia';
60 multiserver_praqma='-Pmultiserver=zhou';
62 multiserver_praqma='-Pmultiserver=suri';
64 multiserver_praqma='-Pmultiserver=reiser';
66 multiserver_praqma='-Pmultiserver=schmidt';
68 multiserver_praqma='-Pmultiserver=rolia';
73 % switch options.method
74 % case {
'default',
'lqns'}
75 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' --iteration-limit=',num2str(options.iter_max),
' -Pstop-on-message-loss=false -x ',filename]);
77 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' --iteration-limit=',num2str(options.iter_max),
' -Playering=srvn -Pstop-on-message-loss=false -x ',filename]);
79 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' --iteration-limit=',num2str(options.iter_max),
' -Pmva=exact -Pstop-on-message-loss=false -x ',filename]);
81 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' --iteration-limit=',num2str(options.iter_max),
' -Playering=srvn -Pmva=exact -Pstop-on-message-loss=false -x ',filename]);
82 %
case {
'sim',
'lqsim'}
83 % cmd=[
'lqsim ',verbose,
' ',multiserver_praqma,
' -A ',num2str(options.samples),
',3 -Pstop-on-message-loss=false -x ',filename]);
84 %
case {
'lqnsdefault'}
85 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -x ',filename]);
87 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' --iteration-limit=',num2str(options.iter_max),
' -Pstop-on-message-loss=false -x ',filename]);
90 % --iteration-limit seems faulty as of 6.2.27
93 case {
'default',
'lqns'}
94 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Pstop-on-message-loss=false -x ',filename];
96 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Playering=srvn -Pstop-on-message-loss=false -x ',filename];
98 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Pmva=exact -Pstop-on-message-loss=false -x ',filename];
99 case {
'srvn.exactmva'}
100 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Playering=srvn -Pmva=exact -Pstop-on-message-loss=false -x ',filename];
102 cmd=[
'lqsim ',verbose,
' ',multiserver_praqma,
' -A ',num2str(options.samples),
',3 -Pstop-on-message-loss=false -x ',filename];
104 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -x ',filename];
106 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Pstop-on-message-loss=false -x ',filename];
109 switch options.method
110 case {
'default',
'lqns'}
111 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Pstop-on-message-loss=false -x ',filename,
' 2>&1'];
113 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Playering=srvn -Pstop-on-message-loss=false -x ',filename,
' 2>&1'];
115 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Pmva=exact -Pstop-on-message-loss=false -x ',filename,
' 2>&1'];
116 case {
'srvn.exactmva'}
117 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Playering=srvn -Pmva=exact -Pstop-on-message-loss=false -x ',filename,
' 2>&1'];
119 cmd=[
'lqsim ',verbose,
' ',multiserver_praqma,
' -A ',num2str(options.samples),
' -Pstop-on-message-loss=false -x ',filename,
' 2>&1'];
121 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -x ',filename,
' 2>&1'];
123 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Pstop-on-message-loss=false -x ',filename,
' 2>&1'];
127 switch options.method
128 %
case {
'default',
'lqns'}
129 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -i ',num2str(options.iter_max),
' -Pstop-on-message-loss=false -x ',filename]);
131 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -i ',num2str(options.iter_max),
' -Playering=srvn -Pstop-on-message-loss=false -x ',filename]);
133 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -i ',num2str(options.iter_max),
' -Pmva=exact -Pstop-on-message-loss=false -x ',filename]);
135 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -i ',num2str(options.iter_max),
' -Playering=srvn -Pmva=exact -Pstop-on-message-loss=false -x ',filename]);
136 %
case {
'sim',
'lqsim'}
137 % cmd=[
'lqsim ',verbose,
' ',multiserver_praqma,
' -A ',num2str(options.samples),
',3 -Pstop-on-message-loss=false -x ',filename]);
138 %
case {
'lqnsdefault'}
139 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -x ',filename]);
141 % cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -i ',num2str(options.iter_max),
' -Pstop-on-message-loss=false -x ',filename]);
142 case {
'default',
'lqns'}
143 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Pstop-on-message-loss=false -x ',filename];
145 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Playering=srvn -Pstop-on-message-loss=false -x ',filename];
147 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Pmva=exact -Pstop-on-message-loss=false -x ',filename];
148 case {
'srvn.exactmva'}
149 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Playering=srvn -Pmva=exact -Pstop-on-message-loss=false -x ',filename];
151 %cmd=[
'lqsim ',verbose,
' ',multiserver_praqma,
' -Pstop-on-message-loss=false -x ',filename];
152 cmd=[
'lqsim ',verbose,
' ',multiserver_praqma,
' -A ',num2str(options.samples),
' -Pstop-on-message-loss=false -x ',filename];
154 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -x ',filename];
156 cmd=[
'lqns ',verbose,
' ',multiserver_praqma,
' -Pstop-on-message-loss=false -x ',filename];
159if ~isempty(dockerImage)
160 % Rewrite
the local invocation to run inside
the container. The temp dir
161 %
is bind-mounted at
the same absolute path so
the model/result file paths
162 % embedded in cmd resolve unchanged; --user matches
the host uid/gid so
the
163 % .lqxo output stays host-owned and rmdir cleanup succeeds. The image
's
164 % 'lqns
' is a REST wrapper, so call the real 'lqns.original
' binary.
165 [~, hostUid] = unix('id -u
'); hostUid = strtrim(hostUid);
166 [~, hostGid] = unix('id -g
'); hostGid = strtrim(hostGid);
167 dockerPrefix = ['docker run --rm --user
', hostUid, ':
', hostGid, ...
168 ' -v
', dirpath, ':
', dirpath, ' -w
', dirpath, ' ', dockerImage, ' '];
169 if strncmp(cmd, 'lqns
', 5)
170 cmd = [dockerPrefix, 'lqns.original
', cmd(6:end)];
171 elseif strncmp(cmd, 'lqsim
', 6)
172 cmd = [dockerPrefix, 'lqsim
', cmd(7:end)];
177% line_printf('\nLQNS model: %s
',filename);
178 line_printf('\nLQNS command: %s\n
',cmd);
181% Check for remote execution
183 line_debug(options, 'LQNS:
using remote execution at %s
', options.config.remote_url);
185 line_printf('\nUsing remote LQNS at: %s\n
', options.config.remote_url);
187 self.runRemoteLQNS(filename, options);
189 line_debug(options, 'LQNS:
using local execution, command: %s
', cmd);
192 % MATLAB prepends its bundled runtime libraries to LD_LIBRARY_PATH before
193 % spawning child processes. Its libstdc++ (e.g. GLIBCXX_3.4.28 in R2024a)
194 % is older than the one lqns/lqsim require (GLIBCXX_3.4.29+), so the
195 % binaries abort with a "version `GLIBCXX_...' not found
" error before
196 % writing their .lqxo output. That later surfaces as a FileNotFoundException
197 % in parseXMLResults. Strip LD_LIBRARY_PATH for the child so it resolves the
198 % system libstdc++ instead of MATLAB's.
199 if isunix && isempty(dockerImage)
200 cmd = ['env -u LD_LIBRARY_PATH ', cmd];
204self.parseXMLResults(filename);