LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
dist_scale_rate.m
1%{
2%{
3 % @file dist_scale_rate.m
4 % @brief Rate-scaled copy of a distribution, preserving its shape.
5%}
6%}
7
8function scaled = dist_scale_rate(distrib, factor)
9%{
10%{
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.
16 %
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.
22 %
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
26 % taken along.
27 %
28 % @fn dist_scale_rate(distrib, factor)
29 % @param distrib A Distribution object.
30 % @param factor Positive scaling factor for the rate.
31 % @return scaled A new Distribution of the same family with rate*FACTOR.
32%}
33%}
34
35if ~isa(distrib, 'Distribution')
36 line_error(mfilename, 'dist_scale_rate expects a Distribution object.');
37end
38if ~isnumeric(factor) || ~isscalar(factor) || ~isfinite(factor) || factor <= 0
39 line_error(mfilename, 'The scaling factor must be a positive finite scalar.');
40end
41
42switch class(distrib)
43 case 'Exp'
44 scaled = Exp(distrib.getParam(1).paramValue * factor);
45 case 'Erlang'
46 scaled = Erlang(distrib.getParam(1).paramValue * factor, ...
47 distrib.getParam(2).paramValue);
48 case 'HyperExp'
49 p = distrib.getParam(1).paramValue;
50 lambda1 = distrib.getParam(2).paramValue;
51 lambda2 = distrib.getParam(3).paramValue;
52 if isempty(lambda2)
53 % n-phase form: param2 holds the whole rate vector.
54 scaled = HyperExp(p, lambda1 * factor);
55 else
56 scaled = HyperExp(p, lambda1 * factor, lambda2 * factor);
57 end
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);
66 else
67 scaled = Coxian(distrib.getParam(1).paramValue * factor, ...
68 distrib.getParam(2).paramValue);
69 end
70 case 'APH'
71 scaled = APH(distrib.getParam(1).paramValue, ...
72 distrib.getParam(2).paramValue * factor);
73 case 'PH'
74 scaled = PH(distrib.getParam(1).paramValue, ...
75 distrib.getParam(2).paramValue * factor);
76 case 'MAP'
77 scaled = MAP(distrib.getParam(1).paramValue * factor, ...
78 distrib.getParam(2).paramValue * factor);
79 case 'MMPP2'
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);
86 case 'Det'
87 scaled = Det(distrib.getParam(1).paramValue / factor);
88 case 'Uniform'
89 scaled = Uniform(distrib.getParam(1).paramValue / factor, ...
90 distrib.getParam(2).paramValue / factor);
91 case 'Gamma'
92 % Gamma(shape, scale): the shape is dimensionless.
93 scaled = Gamma(distrib.getParam(1).paramValue, ...
94 distrib.getParam(2).paramValue / factor);
95 case 'Pareto'
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);
99 case 'Weibull'
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);
104 case 'Lognormal'
105 % X/factor is lognormal with mu - log(factor) and the same sigma.
106 scaled = Lognormal(distrib.getParam(1).paramValue - log(factor), ...
107 distrib.getParam(2).paramValue);
108 case 'NHPP'
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());
115 case 'Replayer'
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.']);
123 end
124 scaled = Replayer(distrib.data / factor);
125 case 'Immediate'
126 scaled = Immediate();
127 otherwise
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)));
132end
133end
Definition Station.m:245