1classdef WorkflowActivity < Element
2 % A computational activity in a Workflow.
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.
8 % Each activity has a service time distribution that can be any
9 % phase-type compatible distribution (Exp, Erlang, APH, HyperExp, etc.).
11 % Copyright (c) 2012-2026, Imperial College London
12 % All rights reserved.
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)
24 function obj = WorkflowActivity(workflow, name, hostDemand)
25 % WORKFLOWACTIVITY Create a workflow activity
27 % OBJ = WORKFLOWACTIVITY(WORKFLOW, NAME, HOSTDEMAND)
30 % workflow - Parent Workflow
object
31 % name - Activity name (
string)
32 % hostDemand - Service time distribution or numeric mean
34 % If hostDemand
is numeric, it
is treated as the mean of an
35 % exponential distribution.
38 line_error(mfilename, 'Constructor requires at least workflow and name.');
42 obj.workflow = workflow;
45 hostDemand = GlobalConstants.FineTol;
46 elseif isnumeric(hostDemand) && hostDemand == 0
47 hostDemand = GlobalConstants.FineTol;
50 obj.setHostDemand(hostDemand);
53 function obj = setHostDemand(obj, hostDemand)
54 % SETHOSTDEMAND Set the service time distribution
56 % OBJ = SETHOSTDEMAND(OBJ, HOSTDEMAND)
59 % hostDemand - Distribution
object or numeric mean
61 if isnumeric(hostDemand)
62 if hostDemand <= GlobalConstants.FineTol
63 obj.hostDemand = Immediate.getInstance();
64 obj.hostDemandMean = GlobalConstants.FineTol;
65 obj.hostDemandSCV = GlobalConstants.FineTol;
67 obj.hostDemand = Exp(1/hostDemand);
68 obj.hostDemandMean = hostDemand;
69 obj.hostDemandSCV = 1.0;
71 elseif isa(hostDemand, 'Distribution')
72 obj.hostDemand = hostDemand;
73 obj.hostDemandMean = hostDemand.getMean();
74 obj.hostDemandSCV = hostDemand.getSCV();
76 line_error(mfilename, 'hostDemand must be a Distribution or numeric value.');
80 function [alpha, T] = getPHRepresentation(obj)
81 % GETPHREPRESENTATION Get the phase-type representation
83 % [ALPHA, T] = GETPHREPRESENTATION(OBJ)
86 % alpha - Initial probability vector (1 x n)
87 % T - Subgenerator matrix (n x n)
89 % For Markovian distributions, extracts the PH representation.
90 % For other distributions, fits an APH from the first two moments.
92 if isa(obj.hostDemand, 'Immediate')
93 % Immediate activity: single absorbing state
95 T = -1e10; % Very high rate (essentially immediate)
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();
105 % Use process representation
106 proc = obj.hostDemand.getProcess();
108 % Extract alpha from D1 = -T*e*alpha
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);
116 alpha = D1(idx, :) / absRate(idx);
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
129 aph = APH.fitMeanAndSCV(mean_val, scv_val);
130 alpha =
aph.getInitProb();
131 T =
aph.getSubgenerator();
134 % Ensure alpha
is a row vector
135 alpha = reshape(alpha, 1, []);
138 function n = getNumberOfPhases(obj)
139 % GETNUMBEROFPHASES Get the number of phases
141 % N = GETNUMBEROFPHASES(OBJ)
143 % Returns the number of phases in the PH representation.
145 if isa(obj.hostDemand,
'Immediate')
147 elseif isa(obj.hostDemand, 'Markovian')
148 if isprop(obj.hostDemand, 'nPhases')
149 n = obj.hostDemand.nPhases;
151 [~, T] = obj.getPHRepresentation();
155 % Fit to get phase count
156 [~, T] = obj.getPHRepresentation();