r-io suiter-io suitededuction docs
← All strategies
Deduction / Shared mechanism

Conditioned Implies, Supports and Needs links

A link between two functions can carry a 2L Condition Evaluation: the dependent task is only executed when the condition holds at runtime. The deduction never decides the condition, since it usually reads the output of a task that has not run yet. Instead, it copies the condition onto the process flows, adds the flows that skip the task, and plans sibling tasks according to whether their conditions are exclusive or inclusive.

implemented byFunctionLinkConditions · Scheduler · ResourceAssigner
The condition is evaluated when the process runs

In the IMT Albi Crisis use case, Confirm gas leak implies Cut off the local gas valve when @Confirmed gas leak[Confirm gas leak] == "Yes and repairable" and Cut off the school gas supply when it equals "Yes and non-repairable". The answer is only known once the firefighter has confirmed the leak, so the deduced process keeps both branches and the engine follows the right one.

00 · At a glance

What goes in, what is decided, what comes out

Inputs

From the collaborative model

  • Implies, Supports and Needs edges between functions, with their Condition Evaluation property (2L code editor, hidden on the diagram, shown as a CE badge).
  • The quick access @variable[Function name] reads an output variable of the task of that function.
Decisions

Taken at deduction

  • The guard of each task: the logical AND of the conditions of its links.
  • Whether sibling guards are exclusive (never both true) or inclusive (possibly both true).
  • The actors and the order of the sibling tasks.
Outputs

In the deduced process

  • Conditioned Sequence_Flows entering each guarded task.
  • otherwise flows to the End_Event, which release the objectives of the skipped tasks.
  • bypass flows when the planning placed a guarded task after a sibling that may be skipped.
01 · Guard of a task

Which condition guards which task

A condition always guards the dependent task, whatever the direction of the edge.

LinkGuarded taskPlanning
A Implies BBB after A
A Supports BBB in parallel with A (support task)
B Needs ABB after A

Copied onto every entering flow — the planning may insert other tasks before B, so the guard of B is copied onto every Sequence_Flow entering B. The quick access names the function explicitly, so the condition does not depend on the flow carrying it. Several conditions guarding the same task are combined with a logical AND, their local variables being renamed so that they do not collide.

One otherwise flow per source and condition — the process must not stay blocked before B when the guard is false: a flow X → End_Event named otherwise carries the negated guard (id <conditioned flow id>__otherwise). Conditioned flows leaving the same node with the same condition, written differently or not, share one otherwise flow.

Objectives released — following an otherwise flow skips B and the tasks only reachable through B. Their objectives will never be reached by a task completion, so the flow lists them in its releasesObjectives property and the engine releases their EXPECTED_FREEZE twin.

Pseudo-codecopyOnSequenceFlows
for flow X -> T in process.sequenceFlows:
  guard = AND(conditions of the links guarding T)
  if guard is empty: continue
  flow.condition = guard
  key = (X, canonical(guard))              # one otherwise per key
  otherwise[key] = X -> End_Event
      condition = NOT guard
      releasesObjectives += objectives of T
                            and of the tasks only reachable through T
02 · Exclusive or inclusive

How sibling conditions are compared

Sibling tasks depend on the same task through conditioned links (A Implies B and A Implies C, or B Needs A and C Needs A). Their guards are compared term by term, the terms being those of their logical AND.

RelationDetected when two terms areAt runtimePlanning
Exclusivethe same expression compared with == to two different literals · compared with == and != to the same literal · an expression and its negation !at most one of the tasks runsnever ordered against each other, may share actors and resources
Inclusiveany other case, same or different conditionsboth, one or none of the tasks runoptional support tasks: in parallel when possible, in sequence otherwise

The literal may be on either side of the comparison, and a condition written boolean ok = <expression>; ok; is analysed through the initial value of its local variables. A term that still depends on the statements of the condition cannot be compared and is considered compatible.

Two conditions are the same when their canonical writing is identical: the 2L code is parsed and printed again, so spaces, line breaks and a missing trailing ; do not matter.

ExamplesareExclusiveConditions
@x[F] == "a"          vs  @x[F] == "b"      # exclusive
@x[F] == "a"          vs  @x[F] != "a"      # exclusive
@ok[F]                vs  !@ok[F]           # exclusive
@x[F] == "a" && @n[F] > 3  vs  @x[F] == "b" # exclusive
@x[F] == "a"          vs  @y[F] == "b"      # inclusive
@n[F] > 3             vs  @n[F] < 2         # inclusive (not detected)
@x[F] == "a" || @y[F] vs  @x[F] == "b"      # inclusive
03 · Exclusive

Both branches follow their common task

The scheduler used to place a task after its sibling as soon as they shared an actor or a resource. With exclusive guards this made the second branch unreachable: to reach it, the process had to go through the first one, whose condition is its opposite.

Scheduler — each scheduled task knows the ids of the tasks exclusive with it (ScheduleTask.exclusiveTaskIds). The time slots they reserved never make it unavailable, so every exclusive branch starts right after the common task, each with its own condition.

Actors of support tasks — support tasks of the same task normally need distinct actors. Exclusive support tasks never run together, so they may share one (ResourceTask.exclusiveFunctionIds).

IMT Albi Crisisdeduced process
Start -> Confirm gas leak
Confirm gas leak -> Cut off the local gas valve
    [@Confirmed gas leak[Confirm gas leak] == "Yes and repairable"]
Confirm gas leak -> Cut off the school gas supply
    [@Confirmed gas leak[Confirm gas leak] == "Yes and non-repairable"]
Confirm gas leak -> End   # otherwise, one per branch
04 · Inclusive

Optional support tasks and bypass flows

With two inclusive conditions C1 (task B) and C2 (task C), four outcomes must stay possible: C1 and C2, C1 only, C2 only, none.

Optional support tasks — inclusive siblings prefer different actors: the actors already assigned to a sibling are offered last (ResourceAssigner.prioritizeActorsFreeOfInclusiveTasks). When another actor is available the tasks run in parallel. Otherwise the same actor is kept and the scheduler places them in sequence; the solution is not lost.

Bypass flows — when the planning placed C after B, although B is not a prerequisite of C, and B may be skipped while C is not (a condition of B does not guard C), C would become unreachable when B is skipped. For each flow P → B, a flow P → C named bypass (id <P id>__bypass__<C id>) carries guard(C) AND NOT guard(B). Its own otherwise flow (id ending with __skipped__otherwise) carries NOT guard(B) AND NOT guard(C) and releases the objectives of C. Longer chains are bypassed recursively. No bypass is added when the two guards are the same: C then runs exactly when B runs.

OutcomeFollowed flows
C1 and C2A → B, then B → C
C1 onlyA → B, then B → End (otherwise of C, releases C)
C2 onlyA → End (otherwise of B, releases B) and A → C (bypass)
noneA → End (otherwise of B) and A → End (skipped otherwise, releases C)
A B C End C1 C2 bypass: C2 and not C1 otherwise: not C1 · skipped: not C1 and not C2 otherwise: not C2
C was placed after B because they share an actor; the bypass keeps C reachable when B is skipped.
05 · Runtime

What the workflow engine does

LEAVEEvaluate the conditioned flowsinclusiveWhen a task ends, every outgoing flow whose condition is true is followed, together with the unconditioned ones (PRIOTransitionController, SequenceFlowConditionEvaluator). A condition that fails to evaluate counts as false.
PAIROtherwise = negationby idAn otherwise flow is not evaluated on its own: its result is the negation of its conditioned flow, found by removing the __otherwise suffix, so exactly one of both is followed. A skipped otherwise has no conditioned flow of that id and is evaluated on its own condition.
RELEASESkipped objectivesasyncFollowing an otherwise flow unpublishes the EXPECTED_FREEZE twins listed in releasesObjectives (OtherwiseFlowObjectiveRelease).
JOINDead paths are not awaitedreverse pathA task with several entering flows does not wait for a flow whose upstream path is dead: C starts once, from B or from the bypass. The End_Event waits for every live path.
06 · Watch points

What to keep in mind

Detection on the writing only

Exclusivity is detected on the syntax of the conditions: @n[F] > 3 and @n[F] < 2 are exclusive but treated as inclusive. The result stays correct, since bypass flows keep every outcome reachable, but the plan may be longer than necessary. A real expression solver is planned.

Quote the text values

@x[F] == Yes and non-repairable is a syntax error: the condition cannot be evaluated, the flow is never followed and its otherwise flow always is. Write "Yes and non-repairable", exactly as the value of the output variable.

Extra flows in the process

The otherwise, bypass and skipped otherwise flows are plain model edges added when the process model is built. Their ids are deterministic: the same process always gives the same flows.

Inclusive tasks and actors

A different actor is only preferred, never required: with a single actor of the role, inclusive tasks are planned in sequence with bypass flows.

07 · Sources

Where to read further

gind-governance-workflow-deduction-strategy-abstract/…/process/edges/FunctionLinkConditions.javaGuards, combination and negation, exclusive and inclusive functions, otherwise and bypass flows.
gind-governance-workflow-planner-default/…/scheduler/Scheduler.java · ScheduleProcess.javaExclusive tasks never block each other.
gind-governance-workflow-planner-default/…/resources/ResourceTaskGraph.java · ResourceAssigner.javaExclusive and inclusive functions of the task graph, actor preference of inclusive tasks.
gind-workflow-engine-prio/…/boundary/SequenceFlowConditionEvaluator.java · OtherwiseFlowObjectiveRelease.javaRuntime evaluation and release of the skipped objectives.
gind-models-collaborative-model/…/Collaborative_MetaModel.xmlCondition Evaluation of Implies, Supports, Needs and Sequence_Flow.
Déduction / Mécanisme commun

Liens Implies, Supports et Needs conditionnés

Un lien entre deux fonctions peut porter une Condition Evaluation 2L : la tâche dépendante ne s’exécute que si la condition est vraie à l’exécution. La déduction ne tranche jamais la condition, qui lit en général la sortie d’une tâche pas encore exécutée. Elle recopie la condition sur les flux du processus, ajoute les flux qui sautent la tâche et planifie les tâches sœurs selon que leurs conditions sont exclusives ou inclusives.

implémenté parFunctionLinkConditions · Scheduler · ResourceAssigner
La condition est évaluée à l’exécution du processus

Dans le cas d’usage IMT Albi Crisis, Confirm gas leak implique Cut off the local gas valve quand @Confirmed gas leak[Confirm gas leak] == "Yes and repairable" et Cut off the school gas supply quand la valeur vaut "Yes and non-repairable". La réponse n’est connue qu’une fois la fuite confirmée par le pompier : le processus déduit garde les deux branches et le moteur suit la bonne.

00 · En bref

Ce qui entre, ce qui est décidé, ce qui sort

Entrées

Depuis le modèle collaboratif

  • Les arêtes Implies, Supports et Needs entre fonctions, avec leur propriété Condition Evaluation (éditeur de code 2L, masquée sur le diagramme, signalée par un badge CE).
  • L’accès rapide @variable[Nom de la fonction] lit une variable de sortie de la tâche de cette fonction.
Décisions

Prises à la déduction

  • La garde de chaque tâche : le ET logique des conditions de ses liens.
  • Si les gardes de tâches sœurs sont exclusives (jamais vraies ensemble) ou inclusives (possiblement vraies ensemble).
  • Les acteurs et l’ordre des tâches sœurs.
Sorties

Dans le processus déduit

  • Des Sequence_Flow conditionnés entrant dans chaque tâche gardée.
  • Des flux otherwise vers l’End_Event, qui libèrent les objectifs des tâches sautées.
  • Des flux bypass quand la planification a placé une tâche gardée après une tâche sœur qui peut être sautée.
01 · Garde d’une tâche

Quelle condition garde quelle tâche

Une condition garde toujours la tâche dépendante, quel que soit le sens de l’arête.

LienTâche gardéePlanification
A Implies BBB après A
A Supports BBB en parallèle de A (tâche support)
B Needs ABB après A

Recopiée sur chaque flux entrant — la planification peut insérer d’autres tâches avant B : la garde de B est donc recopiée sur chaque Sequence_Flow entrant dans B. L’accès rapide nomme explicitement la fonction, la condition ne dépend donc pas du flux qui la porte. Plusieurs conditions gardant la même tâche sont combinées par un ET logique, leurs variables locales étant renommées pour ne pas entrer en collision.

Un flux otherwise par source et par condition — le processus ne doit pas rester bloqué avant B quand la garde est fausse : un flux X → End_Event nommé otherwise porte la garde niée (id <id du flux conditionné>__otherwise). Les flux conditionnés qui quittent le même nœud avec la même condition, écrite de la même façon ou non, partagent un seul flux otherwise.

Objectifs libérés — suivre un flux otherwise saute B et les tâches atteignables seulement par B. Leurs objectifs ne seront jamais atteints par la fin d’une tâche : le flux les liste dans sa propriété releasesObjectives et le moteur libère leur jumeau EXPECTED_FREEZE.

Pseudo-codecopyOnSequenceFlows
pour chaque flux X -> T du processus :
  garde = ET(conditions des liens gardant T)
  si garde vide : continuer
  flux.condition = garde
  cle = (X, canonique(garde))             # un otherwise par clé
  otherwise[cle] = X -> End_Event
      condition = NON garde
      releasesObjectives += objectifs de T
                            et des tâches atteignables seulement par T
02 · Exclusif ou inclusif

Comment les conditions sœurs sont comparées

Des tâches sœurs dépendent de la même tâche par des liens conditionnés (A Implies B et A Implies C, ou B Needs A et C Needs A). Leurs gardes sont comparées terme à terme, les termes étant ceux de leur ET logique.

RelationDétectée quand deux termes sontÀ l’exécutionPlanification
Exclusivela même expression comparée par == à deux littéraux différents · comparée par == et != au même littéral · une expression et sa négation !au plus une des tâches s’exécutejamais ordonnées l’une par rapport à l’autre, peuvent partager acteurs et ressources
Inclusivetous les autres cas, conditions identiques ou différentesles deux, une seule ou aucune des tâches s’exécutenttâches supports optionnelles : en parallèle si possible, sinon en séquence

Le littéral peut être de part ou d’autre de la comparaison, et une condition écrite boolean ok = <expression>; ok; est analysée à travers la valeur initiale de ses variables locales. Un terme qui dépend encore des instructions de la condition ne peut pas être comparé : il est considéré comme compatible.

Deux conditions sont identiques quand leur écriture canonique est la même : le code 2L est analysé puis réimprimé, les espaces, retours à la ligne et un ; final manquant ne comptent donc pas.

ExemplesareExclusiveConditions
@x[F] == "a"          vs  @x[F] == "b"      # exclusives
@x[F] == "a"          vs  @x[F] != "a"      # exclusives
@ok[F]                vs  !@ok[F]           # exclusives
@x[F] == "a" && @n[F] > 3  vs  @x[F] == "b" # exclusives
@x[F] == "a"          vs  @y[F] == "b"      # inclusives
@n[F] > 3             vs  @n[F] < 2         # inclusives (non détecté)
@x[F] == "a" || @y[F] vs  @x[F] == "b"      # inclusives
03 · Exclusif

Les deux branches suivent leur tâche commune

Le planificateur plaçait une tâche après sa sœur dès qu’elles partageaient un acteur ou une ressource. Avec des gardes exclusives, la seconde branche devenait inatteignable : pour l’atteindre, il fallait passer par la première, dont la condition est son contraire.

Ordonnanceur — chaque tâche ordonnancée connaît les ids des tâches exclusives avec elle (ScheduleTask.exclusiveTaskIds). Les créneaux qu’elles ont réservés ne la rendent jamais indisponible : chaque branche exclusive démarre juste après la tâche commune, avec sa propre condition.

Acteurs des tâches supports — les tâches supports d’une même tâche exigent normalement des acteurs distincts. Des tâches supports exclusives ne s’exécutent jamais ensemble et peuvent donc en partager un (ResourceTask.exclusiveFunctionIds).

IMT Albi Crisisprocessus déduit
Start -> Confirm gas leak
Confirm gas leak -> Cut off the local gas valve
    [@Confirmed gas leak[Confirm gas leak] == "Yes and repairable"]
Confirm gas leak -> Cut off the school gas supply
    [@Confirmed gas leak[Confirm gas leak] == "Yes and non-repairable"]
Confirm gas leak -> End   # otherwise, un par branche
04 · Inclusif

Tâches supports optionnelles et flux bypass

Avec deux conditions inclusives C1 (tâche B) et C2 (tâche C), quatre sorties doivent rester possibles : C1 et C2, C1 seule, C2 seule, aucune.

Tâches supports optionnelles — les tâches sœurs inclusives préfèrent des acteurs différents : les acteurs déjà affectés à une sœur sont proposés en dernier (ResourceAssigner.prioritizeActorsFreeOfInclusiveTasks). Si un autre acteur est disponible, les tâches s’exécutent en parallèle. Sinon le même acteur est gardé et l’ordonnanceur les place en séquence : la solution n’est pas perdue.

Flux bypass — quand la planification a placé C après B alors que B n’est pas un prérequis de C, et que B peut être sautée sans que C le soit (une condition de B ne garde pas C), C deviendrait inatteignable quand B est sautée. Pour chaque flux P → B, un flux P → C nommé bypass (id <id de P>__bypass__<id de C>) porte garde(C) ET NON garde(B). Son propre flux otherwise (id terminé par __skipped__otherwise) porte NON garde(B) ET NON garde(C) et libère les objectifs de C. Les chaînes plus longues sont contournées récursivement. Aucun bypass n’est ajouté quand les deux gardes sont identiques : C s’exécute alors exactement quand B s’exécute.

SortieFlux suivis
C1 et C2A → B, puis B → C
C1 seuleA → B, puis B → End (otherwise de C, libère C)
C2 seuleA → End (otherwise de B, libère B) et A → C (bypass)
aucuneA → End (otherwise de B) et A → End (otherwise « skipped », libère C)
A B C End C1 C2 bypass : C2 et non C1 otherwise : non C1 · skipped : non C1 et non C2 otherwise : non C2
C a été placée après B parce qu’elles partagent un acteur ; le bypass garde C atteignable quand B est sautée.
05 · Exécution

Ce que fait le moteur de workflow

SORTIEÉvaluer les flux conditionnésinclusifÀ la fin d’une tâche, chaque flux sortant dont la condition est vraie est suivi, avec les flux non conditionnés (PRIOTransitionController, SequenceFlowConditionEvaluator). Une condition dont l’évaluation échoue compte comme fausse.
PAIREOtherwise = négationpar idUn flux otherwise n’est pas évalué seul : son résultat est la négation de son flux conditionné, retrouvé en retirant le suffixe __otherwise, donc exactement un des deux est suivi. Un otherwise « skipped » n’a pas de flux conditionné de cet id et est évalué sur sa propre condition.
LIBÉRERObjectifs sautésasyncSuivre un flux otherwise dépublie les jumeaux EXPECTED_FREEZE listés dans releasesObjectives (OtherwiseFlowObjectiveRelease).
JOINTURELes chemins morts ne sont pas attenduschemin inverseUne tâche à plusieurs flux entrants n’attend pas un flux dont le chemin amont est mort : C démarre une seule fois, depuis B ou depuis le bypass. L’End_Event attend tous les chemins vivants.
06 · Points de vigilance

À garder en tête

Détection sur l’écriture seulement

L’exclusivité est détectée sur la syntaxe des conditions : @n[F] > 3 et @n[F] < 2 sont exclusives mais traitées comme inclusives. Le résultat reste correct, puisque les flux bypass gardent toutes les sorties atteignables, mais le plan peut être plus long que nécessaire. Un vrai solveur d’expressions est prévu.

Mettre les valeurs texte entre guillemets

@x[F] == Yes and non-repairable est une erreur de syntaxe : la condition ne peut pas être évaluée, le flux n’est jamais suivi et son flux otherwise l’est toujours. Écrire "Yes and non-repairable", exactement comme la valeur de la variable de sortie.

Flux supplémentaires dans le processus

Les flux otherwise, bypass et otherwise « skipped » sont de simples arêtes ajoutées à la construction du modèle de processus. Leurs ids sont déterministes : le même processus donne toujours les mêmes flux.

Tâches inclusives et acteurs

Un acteur différent est seulement préféré, jamais exigé : avec un seul acteur du rôle, les tâches inclusives sont planifiées en séquence avec des flux bypass.

07 · Sources

Où poursuivre la lecture

gind-governance-workflow-deduction-strategy-abstract/…/process/edges/FunctionLinkConditions.javaGardes, combinaison et négation, fonctions exclusives et inclusives, flux otherwise et bypass.
gind-governance-workflow-planner-default/…/scheduler/Scheduler.java · ScheduleProcess.javaLes tâches exclusives ne se bloquent jamais.
gind-governance-workflow-planner-default/…/resources/ResourceTaskGraph.java · ResourceAssigner.javaFonctions exclusives et inclusives du graphe de tâches, préférence d’acteurs des tâches inclusives.
gind-workflow-engine-prio/…/boundary/SequenceFlowConditionEvaluator.java · OtherwiseFlowObjectiveRelease.javaÉvaluation à l’exécution et libération des objectifs sautés.
gind-models-collaborative-model/…/Collaborative_MetaModel.xmlCondition Evaluation d’Implies, Supports, Needs et Sequence_Flow.