Branch probabilities
How to declare them, and how they are normalised when left blank.
At each exclusive gateway, the case takes exactly one branch. The share going into each branch is what turns a static diagram into a model you can quantify.
Where you declare it
The Flows tab in the editor, the Probability % column. Or write it
into the flow label as you draw: passed 70%.
Normalisation when left blank
The tool always makes the probabilities at a gateway sum to 1, in this order of priority:
- No branch declared → split evenly. Two branches become 50/50.
- Some branches declared, the rest blank → the missing share is split evenly among the blank branches. Declare 70% on one branch and the other two get 15% each.
- All declared but the total ≠ 100% → normalised proportionally. Declaring 30/90 becomes 25%/75%.
def branch_probabilities(self, node_id):
outgoing = [e for e in self.edges if e.source == node_id]
if len(outgoing) == 1:
return {outgoing[0].target: 1.0}
declared = {e.target: e.probability for e in outgoing if e.probability is not None}
undeclared = [e.target for e in outgoing if e.target not in declared]
remaining = max(0.0, 1.0 - sum(declared.values()))
share = remaining / len(undeclared) if undeclared else 0
result = {**declared, **{t: share for t in undeclared}}
total = sum(result.values()) # luôn chuẩn hoá về 1
return {t: v / total for t, v in result.items()}
Where to get the numbers
| Source | Reliability | Note |
|---|---|---|
| System logs (ERP, ticketing, workflow) | Highest | Count the cases going down each branch over 3–6 months |
| Existing operational reports | Decent | Rejection rate and return rate are already there |
| An estimate from the people doing the work | Acceptable | Asking “out of 100 cases, how many get sent back?” is easier to answer than asking for a percentage |
Just fill in the number you trust most, then change it and see how sensitive the result is. If moving the rework rate from 20% to 30% swings total time by 15%, then measuring that particular number accurately is the thing worth doing next. That is a valuable analysis result in itself.
Complex gateways
BPMN has one more kind of gateway called complex, where the author writes their own expression to define when each branch is taken. The tool cannot guess that expression, so it provisionally computes it as an exclusive gateway and says so plainly on screen that the number is a guess. The fix: change it to an exclusive, parallel or inclusive gateway to match what you mean.
Three kinds of flow, and which of them carry a probability
The Type column on the Flows tab has three values, and they are not the same in how they are computed:
- Normal flow — the case travels along it. Declare the probability here; leave it blank and the branches of the same gateway split evenly. A loop-back flow (rework) is also a normal flow, and its probability is declared here too.
- Message — an exchange between two participants. The case does not travel along it, so it has no probability; the input field is locked. Treat it as a normal flow and the number of runs of every step behind it goes wrong.
- Exception — a branch escaping from a boundary event attached to a step. Its probability is taken out first, and only the remainder is split among the normal branches.
Event sub-processes
An event sub-process is the dotted-border block sitting on its own on the diagram, with no arrow connecting into it. It is not on the main flow: it triggers itself when something happens anywhere in the process — a customer complaint, an audit walking in, the system reporting a fault. This branch is very often forgotten because on the diagram it looks like a stray block.
You declare its probability in the very same Probability % column of the Flows table, on the row of type exception pointing at that block — exactly like every other probability. The three Source/Target/Type columns of that row are locked, because the BPMN standard does not let this block have an incoming flow. Leave the probability blank and it is computed as never happening.
The Interrupts the whole process field in the step details box decides how it is added up, and it changes the numbers quite a lot:
- No — the process keeps running and this block runs in parallel. Elapsed time takes the larger value of the two, so if the block is shorter than the rest, total time is unchanged — only effort and cost go up.
- Yes — the running process is cancelled and this block runs instead. Time is added in sequence.
For the “interrupting” kind, the tool assumes the process is cancelled at the last minute, so the number is an upper bound. Picking a lower bound would mean adding one more exception branch made the process shorter — a kind of error that is far harder to spot.
The probability of a scenario
The probability that one specific path happens is the product of the probabilities of the branches it passes through. The scenario list displays this number, and their total tells you what percentage of the possibilities you have covered — under 100% means there are still scenarios cut off by a loop.
(here ∏ is a product — the tool multiplies together the probabilities of each choice along the path)