LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
getSymbolicGenerator.m
1function [infGen, eventFilt, syncInfo, stateSpace, nodeStateSpace] = getSymbolicGenerator(self,invertSymbol)
2% [INFGEN, EVENTFILT, SYNCINFO, STATESPACE, NODESTATESPACE] = GETSYMBOLICGENERATOR(INVERTSYMBOL)
3%
4% Symbolic infinitesimal generator, with each event filtration normalized by
5% its minimum positive rate and scaled by a symbolic variable x1, ..., xE.
6%
7% Two backends produce it. With the Symbolic Math Toolbox, INFGEN and the
8% entries of EVENTFILT are sym matrices, as they have always been. Without it,
9% the same matrices are returned as cell arrays of expression strings built
10% through the line-sage-rest service (see SAGE.m), which is what the JAR and
11% native Python return as well. The generator is linear in the symbols, so no
12% computer algebra is needed to assemble it either way; solving with it does,
13% see getSymbolicSolution.
14%
15% Copyright (c) 2012-2026, Imperial College London
16% All rights reserved.
17
18if nargin<2
19 invertSymbol = false;
20end
21if isdeployed
22 infGen = [];
23 eventFilt = [];
24 syncInfo = [];
25 stateSpace = [];
26 nodeStateSpace = [];
27 return
28end
29
30useSym = SAGE.hasSymbolicToolbox();
31if ~useSym && ~SAGE.isAvailable(SolverCTMC.symbolicBackend(self))
32 line_error(mfilename, ['This method requires MATLAB''s Symbolic Toolbox or a ' ...
33 'symbolic backend. Start one with: docker run -d -p 8080:8080 imperialqore/line-sage-rest:latest']);
34end
35
36[~, F] = getGenerator(self);
37[stateSpace, nodeStateSpace] = getStateSpace(self);
38n = size(F{1},1);
39eventFilt = cell(1, length(F));
40if useSym
41 infGen = sym(zeros(n));
42else
43 % Coefficient bookkeeping: the symbolic generator is a sum of numeric
44 % matrices scaled by the event symbols, so it is assembled numerically and
45 % printed at the end.
46 infGenTerms = cell(1, length(F));
47 symbols = cell(1, length(F));
48end
49for e = 1:length(F)
50 F{e} = full(F{e});
51 minF = min(min(F{e}(F{e}>0)));
52 if ~isempty(minF)
53 F{e} = F{e} / minF;
54 if useSym
55 if invertSymbol
56 eventFilt{e} = F{e} / sym(['x',num2str(e)],'real');
57 else
58 eventFilt{e} = F{e} * sym(['x',num2str(e)],'real');
59 end
60 infGen = infGen + eventFilt{e};
61 else
62 eventFilt{e} = F{e};
63 % ctmc_makeinfgen is linear, so the symbolic generator is the sum
64 % of the per-event terms scaled by their symbols.
65 infGenTerms{e} = ctmc_makeinfgen(F{e});
66 symbols{e} = ['x',num2str(e)];
67 end
68 end
69end
70if useSym
71 infGen = ctmc_makeinfgen(infGen);
72else
73 infGen = SolverCTMC.symbolicEntries(infGenTerms, symbols, invertSymbol, n);
74end
75syncInfo = self.getStruct.sync;
76end