1classdef SolverFeatureSet < handle
2 % An auxiliary
class to specify the features supported by a solver.
4 % Copyright (c) 2012-2026, Imperial College London
8 list; % list of features
12 % Canonical feature-name registry; must stay identical to
13 % jar FeatureSet.java and python base.py SolverFeatureSet.FIELDS.
14 % It also lists the distributions that no solver supports as a service
15 % or arrival process (DiscreteSampler, DiscreteUniform, Empirical, GMM,
16 % MMDP, MMDP2, MMPP, MultivariateNormal, NegBinomial, Prior, Zipf):
17 % their names can still be emitted by getUsedLangFeatures, and an
18 % unregistered name
is invisible to SUPPORTS, which iterates this list,
19 % so the model would pass the support gate as if the distribution were
20 % absent. No solver declares them, hence a clean rejection instead.
21 fields = {
'ClassSwitch',...
53 'EmpiricalCdf',... % name declared by EmpiricalCDF.m, not the JSON wire type
75 'MultivariateNormal',...
79 'StatelessClassSwitcher',...
80 'CacheClassSwitcher',...
99 'RoutingStrategy_PROB', ...
100 'RoutingStrategy_RAND', ...
101 'RoutingStrategy_RROBIN', ...
102 'RoutingStrategy_WRROBIN', ...
103 'RoutingStrategy_JSQ', ...
104 'RoutingStrategy_SQ', ...
105 'RoutingStrategy_RL', ...
106 'SchedStrategy_INF', ...
107 'SchedStrategy_FCFS', ...
108 'SchedStrategy_FCFSPR', ...
109 'SchedStrategy_FCFSPI', ...
110 'SchedStrategy_FCFSPRIO', ...
111 'SchedStrategy_FCFSPRPRIO', ...
112 'SchedStrategy_FCFSPIPRIO', ...
113 'SchedStrategy_LCFS', ...
114 'SchedStrategy_LCFSPR', ...
115 'SchedStrategy_LCFSPI', ...
116 'SchedStrategy_LCFSPRIO', ...
117 'SchedStrategy_LCFSPRPRIO', ...
118 'SchedStrategy_LCFSPIPRIO', ...
119 'SchedStrategy_SEPT', ...
120 'SchedStrategy_LEPT', ...
121 'SchedStrategy_SJF', ...
122 'SchedStrategy_LJF', ...
123 'SchedStrategy_SRPT', ...
124 'SchedStrategy_SRPTPRIO', ...
125 'SchedStrategy_PSJF', ...
126 'SchedStrategy_FB', ...
127 'SchedStrategy_LRPT', ...
128 'SchedStrategy_SETF', ...
129 'SchedStrategy_FSP', ...
130 'SchedStrategy_PAS', ...
131 'SchedStrategy_OI', ...
132 'SchedStrategy_PS', ...
133 'SchedStrategy_DPS', ...
134 'SchedStrategy_GPS', ...
135 'SchedStrategy_PSPRIO', ...
136 'SchedStrategy_DPSPRIO', ...
137 'SchedStrategy_GPSPRIO', ...
138 'SchedStrategy_SIRO', ...
139 'SchedStrategy_HOL', ...
140 'SchedStrategy_EXT', ...
141 'SchedStrategy_POLLING', ...
142 'SchedStrategy_EDD', ...
143 'SchedStrategy_EDF', ...
144 'SchedStrategy_LPS', ...
145 'ReplacementStrategy_RR', ...
146 'ReplacementStrategy_FIFO', ...
147 'ReplacementStrategy_SFIFO', ...
148 'ReplacementStrategy_LRU', ...
149 'ReplacementStrategy_HLRU', ...
150 'ReplacementStrategy_CLIMB', ...
151 'ReplacementStrategy_QLRU', ...
154 'SelfLoopingClass', ...
157 'SignalType_NEGATIVE', ...
158 'SignalType_REPLY', ...
159 'SignalType_CATASTROPHE', ...
160 'SignalBatchRemoval', ...
161 'SignalRemovalPolicy', ...
163 'LoadDependence', ...
164 'ClassDependence', ...
165 'JointDependence', ...
178 'ActivityPrecedence_PRE_SEQ', ...
179 'ActivityPrecedence_POST_SEQ', ...
180 'ActivityPrecedence_PRE_AND', ...
181 'ActivityPrecedence_POST_AND', ...
182 'ActivityPrecedence_PRE_OR', ...
183 'ActivityPrecedence_POST_OR', ...
184 'SchedStrategy_REF'};
188 function self = SolverFeatureSet()
189 % SELF = SOLVERFEATURESET()
192 fields = SolverFeatureSet.fields;
193 for f=1:length(fields)
194 self.list.(fields{f})=
false;
198 function self = setTrue(self, feature)
199 % SELF = SETTRUE(FEATURE)
202 for c=1:length(feature)
203 self.setTrue(feature{c});
206 if ~strcmpi(feature,
'char') && isfield(self.list, feature)
207 % Unregistered names are ignored on purpose: unlike the jar,
208 % which curates every name it records, MNetwork.addNode
209 % feeds raw node and section
class names (Section,
210 % InputSection, ServiceSection, ClassSwitcher, ...) that
211 % denote no capability and that no solver declares, so
212 % registering them would reject every model. The corollary
213 %
is that a genuine capability name missing from FIELDS
is
214 % silently unenforced: keep FIELDS identical to jar
215 % FeatureSet.java and python SolverFeatureSet.FIELDS.
216 self.list.(feature) =
true;
221 function self = setFalse(self, feature)
222 % SELF = SETFALSE(FEATURE)
225 for c=1:length(feature)
226 self.setFalse(feature{c});
229 if isfield(self.list, feature) % see SETTRUE
230 self.list.(feature) =
false;
238 function [bool, reason] = supports(featSupportedList, featUsedList)
239 % [BOOL, REASON] = SUPPORTS(FEATSUPPORTEDLIST, FEATUSEDLIST)
241 % BOOL
is true when every feature used by the model
is supported.
242 % REASON
is a human-readable list of the offending feature names
243 % (empty when BOOL
is true),
for use in method-aware error messages.
249 fields = SolverFeatureSet.fields;
250 for f=1:length(fields)
251 if featUsedList.list.(fields{f}) > featSupportedList.list.(fields{f})
253 unsupported{end+1} = fields{f}; %#ok<AGROW>
258 if ~isempty(unsupported)
259 str=
'Some features are not supported by the chosen solver (feature: ';
260 for u=1:length(unsupported)
262 str = sprintf(
'%s%s',str,unsupported{u});
264 str = sprintf(
'%s, %s',str,unsupported{u});
267 str = sprintf(
'%s).\n',str);
269 % Preserve the historical side-effect warning
for the coarse
270 % (solver-level) callers that
do not consume REASON.
272 line_warning(mfilename,str);