LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
getTranReward.m
1function [Rt, t, names] = getTranReward(self, rewardName)
2% GETTRANREWARD Get transient expected reward metrics over time
3%
4% [RT, T, NAMES] = GETTRANREWARD(SELF) returns transient expected rewards
5% for all defined rewards
6%
7% [RT, T, NAMES] = GETTRANREWARD(SELF, REWARDNAME) returns the transient
8% expected reward for a specific named reward
9%
10% This method computes the transient expected reward E[r(X(t))] for each
11% time point t, where X(t) is the system state at time t and r is the
12% reward function. The computation uses the transient probability
13% distribution pi_t(s) from CTMC uniformization:
14%
15% E[r(X(t))] = sum_s pi_t(s) * r(s)
16%
17% OUTPUTS:
18% Rt - Cell array {nRewards x 1} where each Rt{r} is a struct with:
19% .t - Time vector [nTimePoints x 1]
20% .metric - Expected reward at each time [nTimePoints x 1]
21% .name - Reward name string
22% Or a single struct if rewardName is specified
23% t - Time vector [nTimePoints x 1]
24% names - Cell array of reward names, or single string if rewardName specified
25%
26% Example:
27% model = Network('example');
28% % ... model setup ...
29% model.setReward('QLen', @(state) state.at(queue, class1));
30% solver = SolverCTMC(model, 'timespan', [0, 10]);
31% [Rt, t, names] = solver.getTranReward();
32% plot(t, Rt{1}.metric);
33%
34% Copyright (c) 2012-2026, Imperial College London
35% All rights reserved.
36
37if nargin < 2
38 rewardName = [];
39end
40
41options = self.getOptions;
42
43% Validate timespan
44if ~isfield(options, 'timespan') || ~isfinite(options.timespan(2))
45 line_error(mfilename, 'getTranReward requires a finite timespan. Use SolverCTMC(model, ''timespan'', [0, T]).');
46end
47
48sn = self.model.getStruct(true);
49
50% Validate that rewards are defined
51if isempty(sn.reward)
52 line_error(mfilename, 'No rewards defined. Use model.setReward(name, @(state) ...) before calling getTranReward.');
53end
54
55nRewards = length(sn.reward);
56
57% Get transient probabilities and state space
58[InfGen, StateSpace, StateSpaceAggr, ~, ~, ~, sn] = solver_ctmc(sn, options);
59
60% Compute initial state probability
61state = [];
62for ist = 1:sn.nnodes
63 if sn.isstateful(ist)
64 isf = sn.nodeToStateful(ist);
65 state = [state, zeros(1, size(sn.space{isf}, 2) - length(sn.state{isf})), sn.state{isf}];
66 end
67end
68
69nstates = size(InfGen, 1);
70pi0 = zeros(1, nstates);
71
72state0 = matchrow(StateSpace, state);
73if state0 == -1
74 line_error(mfilename, 'Initial state not contained in the state space.');
75end
76pi0(state0) = 1;
77
78% Compute transient probabilities
79[pit, t] = ctmc_transient(InfGen, pi0, options.timespan(1), options.timespan(2), options.stiff, [], options.timestep);
80pit(pit < GlobalConstants.Zero) = 0;
81
82% Build index maps for RewardState
83nodeToStationMap = containers.Map('KeyType', 'int32', 'ValueType', 'int32');
84classToIndexMap = containers.Map('KeyType', 'int32', 'ValueType', 'int32');
85
86for ind = 1:sn.nnodes
87 if sn.isstation(ind)
88 nodeToStationMap(int32(ind)) = sn.nodeToStation(ind);
89 end
90end
91
92for r = 1:sn.nclasses
93 classToIndexMap(int32(r)) = r;
94end
95
96% Build reward vectors (one per reward definition)
97R = zeros(nRewards, nstates);
98names = cell(nRewards, 1);
99for r = 1:nRewards
100 names{r} = sn.reward{r}.name;
101 rewardFn = sn.reward{r}.fn;
102
103 for s = 1:nstates
104 % Create RewardState for this state row
105 stateRow = StateSpaceAggr(s, :);
106 rewardState = RewardState(stateRow, sn, nodeToStationMap, classToIndexMap);
107
108 % Try calling with RewardState (new API, single argument)
109 try
110 R(r, s) = rewardFn(rewardState);
111 catch ME
112 % If that fails, try backward compatibility with @(state, sn) signature
113 try
114 R(r, s) = rewardFn(StateSpaceAggr(s, :), sn);
115 catch
116 rethrow(ME);
117 end
118 end
119 end
120end
121
122% Compute transient expected rewards: E[r(X(t))] = pit * R'
123Rt = cell(nRewards, 1);
124for r = 1:nRewards
125 reward_t = pit * R(r, :)';
126
127 metricVal = struct();
128 metricVal.t = t;
129 metricVal.metric = reward_t;
130 metricVal.name = names{r};
131 Rt{r} = metricVal;
132end
133
134% Filter to specific reward if requested
135if ~isempty(rewardName)
136 rewardName = char(rewardName);
137 idx = find(strcmp(names, rewardName));
138 if isempty(idx)
139 line_error(mfilename, 'Reward "%s" not found. Available rewards: %s', ...
140 rewardName, strjoin(names, ', '));
141 end
142 Rt = Rt{idx};
143 names = names{idx};
144end
145
146end