LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
WorkflowActivity.m
1classdef WorkflowActivity < Element
2 % A computational activity in a Workflow.
3 %
4 % WorkflowActivity represents a stage of computation in a standalone
5 % workflow model. Unlike Activity in LayeredNetwork, this class is
6 % designed for pure computational workflows without external calls.
7 %
8 % Each activity has a service time distribution that can be any
9 % phase-type compatible distribution (Exp, Erlang, APH, HyperExp, etc.).
10 %
11 % Copyright (c) 2012-2026, Imperial College London
12 % All rights reserved.
13
14 properties
15 hostDemand; % Distribution object (Exp, APH, Erlang, etc.)
16 hostDemandMean; % double - mean service time
17 hostDemandSCV; % double - squared coefficient of variation
18 workflow; % Reference to parent Workflow
19 index; % Index in the workflow's activity list
20 metadata; % Optional struct for external metadata (e.g., WfCommons)
21 end
22
23 methods
24 function obj = WorkflowActivity(workflow, name, hostDemand)
25 % WORKFLOWACTIVITY Create a workflow activity
26 %
27 % OBJ = WORKFLOWACTIVITY(WORKFLOW, NAME, HOSTDEMAND)
28 %
29 % Parameters:
30 % workflow - Parent Workflow object
31 % name - Activity name (string)
32 % hostDemand - Service time distribution or numeric mean
33 %
34 % If hostDemand is numeric, it is treated as the mean of an
35 % exponential distribution.
36
37 if nargin < 2
38 line_error(mfilename, 'Constructor requires at least workflow and name.');
39 end
40
41 obj@Element(name);
42 obj.workflow = workflow;
43
44 if nargin < 3
45 hostDemand = GlobalConstants.FineTol;
46 elseif isnumeric(hostDemand) && hostDemand == 0
47 hostDemand = GlobalConstants.FineTol;
48 end
49
50 obj.setHostDemand(hostDemand);
51 end
52
53 function obj = setHostDemand(obj, hostDemand)
54 % SETHOSTDEMAND Set the service time distribution
55 %
56 % OBJ = SETHOSTDEMAND(OBJ, HOSTDEMAND)
57 %
58 % Parameters:
59 % hostDemand - Distribution object or numeric mean
60
61 if isnumeric(hostDemand)
62 if hostDemand <= GlobalConstants.FineTol
63 obj.hostDemand = Immediate.getInstance();
64 obj.hostDemandMean = GlobalConstants.FineTol;
65 obj.hostDemandSCV = GlobalConstants.FineTol;
66 else
67 obj.hostDemand = Exp(1/hostDemand);
68 obj.hostDemandMean = hostDemand;
69 obj.hostDemandSCV = 1.0;
70 end
71 elseif isa(hostDemand, 'Distribution')
72 obj.hostDemand = hostDemand;
73 obj.hostDemandMean = hostDemand.getMean();
74 obj.hostDemandSCV = hostDemand.getSCV();
75 else
76 line_error(mfilename, 'hostDemand must be a Distribution or numeric value.');
77 end
78 end
79
80 function [alpha, T] = getPHRepresentation(obj)
81 % GETPHREPRESENTATION Get the phase-type representation
82 %
83 % [ALPHA, T] = GETPHREPRESENTATION(OBJ)
84 %
85 % Returns:
86 % alpha - Initial probability vector (1 x n)
87 % T - Subgenerator matrix (n x n)
88 %
89 % For Markovian distributions, extracts the PH representation.
90 % For other distributions, fits an APH from the first two moments.
91
92 if isa(obj.hostDemand, 'Immediate')
93 % Immediate activity: single absorbing state
94 alpha = 1;
95 T = -1e10; % Very high rate (essentially immediate)
96 return;
97 end
98
99 if isa(obj.hostDemand, 'Markovian')
100 % Extract from Markovian distribution
101 if ismethod(obj.hostDemand, 'getInitProb') && ismethod(obj.hostDemand, 'getSubgenerator')
102 alpha = obj.hostDemand.getInitProb();
103 T = obj.hostDemand.getSubgenerator();
104 else
105 % Use process representation
106 proc = obj.hostDemand.getProcess();
107 T = proc{1};
108 % Extract alpha from D1 = -T*e*alpha
109 n = size(T, 1);
110 e = ones(n, 1);
111 absRate = -T * e;
112 D1 = proc{2};
113 % D1(i,j) = absRate(i) * alpha(j), so alpha = D1(k,:) / absRate(k) for any k with absRate(k) > 0
114 idx = find(absRate > GlobalConstants.FineTol, 1);
115 if ~isempty(idx)
116 alpha = D1(idx, :) / absRate(idx);
117 else
118 alpha = zeros(1, n);
119 alpha(1) = 1;
120 end
121 end
122 else
123 % Fit APH from moments
124 mean_val = obj.hostDemandMean;
125 scv_val = obj.hostDemandSCV;
126 if scv_val < GlobalConstants.FineTol
127 scv_val = 1.0; % Default to exponential
128 end
129 aph = APH.fitMeanAndSCV(mean_val, scv_val);
130 alpha = aph.getInitProb();
131 T = aph.getSubgenerator();
132 end
133
134 % Ensure alpha is a row vector
135 alpha = reshape(alpha, 1, []);
136 end
137
138 function n = getNumberOfPhases(obj)
139 % GETNUMBEROFPHASES Get the number of phases
140 %
141 % N = GETNUMBEROFPHASES(OBJ)
142 %
143 % Returns the number of phases in the PH representation.
144
145 if isa(obj.hostDemand, 'Immediate')
146 n = 1;
147 elseif isa(obj.hostDemand, 'Markovian')
148 if isprop(obj.hostDemand, 'nPhases')
149 n = obj.hostDemand.nPhases;
150 else
151 [~, T] = obj.getPHRepresentation();
152 n = size(T, 1);
153 end
154 else
155 % Fit to get phase count
156 [~, T] = obj.getPHRepresentation();
157 n = size(T, 1);
158 end
159 end
160 end
161end