3 % @file dist_scale_rate.m
4 % @brief Rate-scaled copy of a distribution, preserving its shape.
8function scaled = dist_scale_rate(distrib,
factor)
11 % @brief Returns a
new distribution whose rate
is FACTOR times the rate of
12 % DISTRIB, i.e. the time-scaled variable X/FACTOR. The scaling
is
13 % exact: every moment of order n
is divided by FACTOR^n, so the mean
14 %
is divided by FACTOR
while the SCV, the skewness and the whole
15 % shape of the distribution are preserved.
17 % The scaled
object is rebuilt from the parameters of the original,
18 % rather than by rescaling its Markovian representation, so that the
19 % parameter list stays coherent with the distribution family. Solvers
20 % that serialize the model (JMT, LDES) read the parameters, and would
21 % otherwise
export the unscaled process.
23 % This
is the perturbation primitive of the finite-difference branch
24 % of getSensitivityTable: scaling the rate at a station-
class by
25 % (1+h)
is exactly the perturbation the derivative d(.)/d(rate)
is
28 % @fn dist_scale_rate(distrib,
factor)
29 % @param distrib A Distribution
object.
31 % @
return scaled A
new Distribution of the same family with rate*FACTOR.
35if ~isa(distrib,
'Distribution')
36 line_error(mfilename, 'dist_scale_rate expects a Distribution
object.');
39 line_error(mfilename, 'The scaling
factor must be a positive finite scalar.');
44 scaled = Exp(distrib.getParam(1).paramValue *
factor);
46 scaled = Erlang(distrib.getParam(1).paramValue *
factor, ...
47 distrib.getParam(2).paramValue);
49 p = distrib.getParam(1).paramValue;
50 lambda1 = distrib.getParam(2).paramValue;
51 lambda2 = distrib.getParam(3).paramValue;
53 % n-phase
form: param2 holds the whole rate vector.
54 scaled = HyperExp(p, lambda1 *
factor);
56 scaled = HyperExp(p, lambda1 *
factor, lambda2 *
factor);
58 case {
'Coxian',
'Cox2'}
59 % Completion probabilities are dimensionless and are left untouched;
60 % only the phase rates carry the time scale. A Cox2
is a two-phase
61 % Coxian and
is rebuilt as one, its own constructor being a fit.
62 if length(distrib.params) == 3
63 scaled = Coxian(distrib.getParam(1).paramValue *
factor, ...
64 distrib.getParam(2).paramValue *
factor, ...
65 distrib.getParam(3).paramValue);
67 scaled = Coxian(distrib.getParam(1).paramValue *
factor, ...
68 distrib.getParam(2).paramValue);
71 scaled = APH(distrib.getParam(1).paramValue, ...
72 distrib.getParam(2).paramValue *
factor);
74 scaled = PH(distrib.getParam(1).paramValue, ...
75 distrib.getParam(2).paramValue *
factor);
77 scaled = MAP(distrib.getParam(1).paramValue *
factor, ...
78 distrib.getParam(2).paramValue *
factor);
80 % Every rate of the modulating chain and of the arrival process
is
81 % scaled, which time-scales the whole process.
82 scaled = MMPP2(distrib.getParam(1).paramValue *
factor, ...
83 distrib.getParam(2).paramValue *
factor, ...
84 distrib.getParam(3).paramValue *
factor, ...
85 distrib.getParam(4).paramValue *
factor);
87 scaled = Det(distrib.getParam(1).paramValue /
factor);
89 scaled = Uniform(distrib.getParam(1).paramValue /
factor, ...
90 distrib.getParam(2).paramValue /
factor);
92 % Gamma(shape, scale): the shape
is dimensionless.
93 scaled = Gamma(distrib.getParam(1).paramValue, ...
94 distrib.getParam(2).paramValue /
factor);
96 % Pareto(shape, scale): the scale
is the minimum of the support.
97 scaled = Pareto(distrib.getParam(1).paramValue, ...
98 distrib.getParam(2).paramValue /
factor);
100 % Weibull params are (1) the scale alpha and (2) the shape r, while
101 % the constructor takes (shape, scale).
102 scaled = Weibull(distrib.getParam(2).paramValue, ...
103 distrib.getParam(1).paramValue /
factor);
106 scaled = Lognormal(distrib.getParam(1).paramValue - log(
factor), ...
107 distrib.getParam(2).paramValue);
109 % A piecewise-constant intensity
is time-scaled by lambda(t) ->
110 %
factor*lambda(
factor*t), which
is the schedule with its rates scaled
111 % up and its breakpoints compressed. The time-average rate, which
is
112 % what sn.rates carries for an NHPP,
is then scaled by
factor.
113 scaled = NHPP(distrib.getBreakpoints() /
factor, ...
114 distrib.getRates() *
factor, distrib.isCyclic());
116 % A trace
is scaled sample by sample. A file-backed Replayer
is left
117 % alone: rescaling it means writing a new trace file, which a
118 % sensitivity sweep must not do behind the caller's back.
119 if isempty(distrib.data)
120 line_error(mfilename, ['Rate scaling
is not defined for a ', ...
121 'file-backed Replayer: the trace
is the parameter. Pass the ', ...
122 'samples as an array, Replayer(data), to differentiate it.']);
124 scaled = Replayer(distrib.data /
factor);
126 scaled = Immediate();
128 line_error(mfilename, sprintf(['Rate scaling
is not defined for a %s ', ...
129 'process. Supported: Exp, Erlang, HyperExp, Coxian, Cox2, APH, PH, ', ...
130 'MAP, MMPP2, Det, Uniform, Gamma, Pareto, Weibull, Lognormal, NHPP, ', ...
131 'Replayer, Immediate.'], class(distrib)));