1function [infGen, eventFilt, syncInfo, stateSpace, nodeStateSpace] = getSymbolicGenerator(self,invertSymbol)
2% [INFGEN, EVENTFILT, SYNCINFO, STATESPACE, NODESTATESPACE] = GETSYMBOLICGENERATOR(INVERTSYMBOL)
4% Symbolic infinitesimal generator, with each
event filtration normalized by
5% its minimum positive rate and scaled by a symbolic variable x1, ..., xE.
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.
15% Copyright (c) 2012-2026, Imperial College London
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']);
36[~, F] = getGenerator(self);
37[stateSpace, nodeStateSpace] = getStateSpace(self);
39eventFilt = cell(1, length(F));
41 infGen = sym(zeros(n));
43 % Coefficient bookkeeping: the symbolic generator
is a sum of numeric
44 % matrices scaled by the
event symbols, so it
is assembled numerically and
46 infGenTerms = cell(1, length(F));
47 symbols = cell(1, length(F));
51 minF = min(min(F{e}(F{e}>0)));
56 eventFilt{e} = F{e} / sym([
'x',num2str(e)],
'real');
58 eventFilt{e} = F{e} * sym([
'x',num2str(e)],
'real');
60 infGen = infGen + eventFilt{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)];
71 infGen = ctmc_makeinfgen(infGen);
73 infGen = SolverCTMC.symbolicEntries(infGenTerms, symbols, invertSymbol, n);
75syncInfo = self.getStruct.sync;