RePA Tool — Language Reference

The ReLang Handbook

Everything you need to model, simulate, verify and train Reconfigurable Probabilistic Automata. From your first state to advanced PDL formulae.

Section 01

What is ReLang?

ReLang is the modelling language of the RePA Tool. It lets you describe a probabilistic system as a set of states connected by transitions, each carrying a probability weight. On top of that you can add hyper-edges (rules) that dynamically change those weights at runtime — making the system reconfigurable.

🎲

Probabilistic

Every outgoing transition from a state carries a weight. Together they sum to 1.

Reconfigurable

Hyper-edges allow transitions to activate, deactivate, or modify each other's weights live.

🔒

Guarded

Any edge can carry an if (condition) guard evaluated at runtime.

📐

Verifiable

Full PDL and probabilistic PCTL verification built in, with animation playback.

Section 02

File Structure

A .Re / .rta file is plain text. The order of declarations is flexible — but the recommended layout is shown below.

my-model.Re
// 1. Optional model name (stripped by the engine)
name MyModel

// 2. Global settings
paradigm    probabilistic
calibration normalize
training    laplace

// 3. Variable declarations
int   counter = 0
float rate    = 0.5
bool  flag    = false

// 4. Initial state
init start

// 5. Transitions
start ---> end : doIt (1.0)

// 6. Hyper-edges (rules)
doIt ->> doIt : selfBuff (0.8)
Section 03

Global Settings

paradigm

Controls how weights are interpreted.

ValueDescription
probabilisticWeights are probabilities; outgoing edges from a state must sum to 1 (default).
fuzzyWeights are membership degrees [0,1]; no normalisation enforced. Rule effects use min/max logic.

calibration

How remaining probability is redistributed when a rule changes a weight.

ValueBehaviour
normalizeAll other active edges are scaled proportionally so the total remains 1 (default).
proportionalThe remainder is shared in proportion to the unmodified edges' original weights.
equalThe remainder is shared equally across unmodified edges.
revise_equalThe remainder/excess is shared equally across all active edges, including the modified one.

training

Activates statistical learning from event sequences.

training                         // Laplace smoothing (default)
training laplace                 // Explicit Laplace
training aggregation arith (0.9) // Aggregation with lambda

Section 04

Transitions & Edges

A transition moves the system from one state to another when fired. The canonical syntax is:

SOURCE ---> TARGET : label (weight) [aggregation] [disabled] [if (condition)] [then { updates }]

Arrow styles

ArrowMeaning
--->Standard transition (shorthand, auto-ID = label)
-transId->Transition with an explicit transId distinct from the label
-transId->Same as above with named identifier for referencing
transId vs label When you write s0 -step-> s1 : myLabel, the edge has transId = step and label = myLabel. Using ---> makes both equal. The label is what rules target; the transId is used for Cytoscape IDs.

Basic examples

// Minimal: no weight → defaults to 1.0, then normalised
s0 ---> s1 : go

// Explicit weight
s0 ---> s1 : go   (0.7)
s0 ---> s2 : stay (0.3)

// With named transId
s0 -t1-> s1 : myAction (0.5)

// Starts disabled (inactive until a rule enables it)
s0 ---> s1 : secret (0.5) disabled

// Self-loop
s0 ---> s0 : idle (1.0)

Weights

Weights are floating-point values in [0.0, 1.0]. The engine automatically normalises outgoing active edges from a state at load time so they sum to 1. If you provide unnormalised values (e.g. all edges with weight 1.0), the engine will divide them evenly.

Tip — ratios You can write weights as ratios and let the engine normalise. Three edges with (1.0, 1.0, 2.0) will become (0.25, 0.25, 0.50).

Aggregation types

Used when a hyper-edge modifies a weight. The aggregation determines how the new weight is computed from the trigger weight wS, the rule weight wR, and the target's current weight wT.

KeywordFormulaEffect
arith(wS + wR + wT) / 3Average — gentle (default)
prodwS × wR × wTProduct — strong suppression
maxmax(wS, wR, wT)Takes the maximum — buff-dominant
minmin(wS, wR, wT)Takes the minimum — debuff-dominant
geom(wS × wR × wT)^(1/3)Geometric mean — balanced
// Edge declared with aggregation keyword
s0 ---> s1 : boost (0.8) max

// Rule also carries its own aggregation
boost ->> otherAction : buffRule (0.9) prod
Section 05

Hyper-Edges (Rules)

Rules are edges between labels, not states. When the source label fires, the rule's effect is applied to the target label.

ArrowNameEffect
->>Activation / BuffApplies aggregation to increase the target edge's weight, or activates a disabled edge.
--!Negation / DebuffApplies aggregation to decrease the target edge's weight, or deactivates an active edge.
--xNegation (alias)Same as --!

Syntax

triggerLabel ->> targetLabel [: ruleLabel] (ruleWeight) [aggregation] [if (condition)] [then { updates }]
rules.Re
// Every time 'like' fires, it increases 'watchAgain' weight
like      ->>  watchAgain : like_boost  (0.9) max

// Every time 'skip' fires, it suppresses 'watchAgain'
skip      --!  watchAgain : skip_debuff (0.1) prod

// Rule only fires if a variable condition is met
login     ->>  premiumOffer : showOffer   (0.8) if (userTier >= 2)

// Rule that also updates a variable
purchase  ->>  upsell       : upsellRule  (0.7) if (cart > 0) then {
    revenue' := revenue + 1
}

// Short form — no explicit rule label (auto-generated)
eventA    --!  eventA       (0.05)
Cascade propagation Rules can target other rule labels, creating chains. If a ->> b and b ->> c, firing a will cascade through b and reach c. The engine detects cycles and stops.
Section 06

Variables & Types

Scalar types

int   count    = 0           // integer, default 0
int   level[0..10]    = 1   // bounded integer [min..max]
float ratio    = 0.5
float prob[0.0..1.0]     = 1.0 
bool  isActive = false

Arrays

// Static array
int[] scores = [10, 20, 30]

// Dynamic array (grows when you assign to index == length)
dyn int[] log = []

// Dynamic with max size
dyn int[] recent [max=5] = []   // keeps only last 5 items

// Access in an expression
x' := scores[1]          // x = 20

// Write with ArrayAssign
scores[0]' := 99         // scores becomes [99, 20, 30]
Section 07

Conditions (Guards)

A guard is an if (...) clause attached to any edge or rule. The transition only fires if the condition is true in the current state.

Comparison operators

OperatorMeaning
==Equal (also accepted as =)
!=Not equal
<Less than
<=Less than or equal
>Greater than
>=Greater than or equal

Logical connectives

KeywordSymbolMeaning
AND&&Both conditions must hold
OR||At least one must hold

Weight check

You can guard on the current probability of an edge using P(label) or F(label):

// Fire only if 'attack' has probability >= 0.6
idle ---> alert : warn if (P(attack) >= 0.6)

// Fire only if the failure probability F(action) is low
idle ---> safe  : proceed if (F(fail) < 0.1)

Examples

// Simple guard
s0 ---> s1 : step if (counter < 5)

// Compound guard
s0 ---> s2 : jump  if (flag == true AND score >= 10)

// Guard with then-block
s0 ---> s1 : advance if (n < 3) then {
    n' := n + 1
}
Section 08

Updates (Side Effects)

When a transition fires, it can update variables. Updates appear in a then { ... } block, or inline for a single assignment.

Assignment

// Inline (no then-block needed for a single statement)
s0 ---> s1 : pay  total' := total + 10

// then-block for multiple statements
s0 ---> s1 : buy  then {
    balance' := balance - 5
    items'   := items   + 1
}

// Nested if inside then
s0 ---> s1 : check then {
    if (score > 50) then {
        grade' := 1
    }
}

Math expressions

OperatorMeaning
+Addition
-Subtraction
*Multiplication
/Integer or float division

Print statement

print(counter)        // prints value to browser console
print(score * 2)      // expression is evaluated first
Section 09

Functions

You can define reusable functions and call them inside expressions or updates.

// Define a function
def clamp(x, lo, hi) {
    if (x < lo) then { return lo }
    if (x > hi) then { return hi }
    return x
}

// Use in an update
s0 ---> s1 : adjust then {
    volume' := clamp(volume + 10, 0, 100)
}

// foreach loop (works on arrays)
def sumArr(arr) {
    total' := 0
    foreach (item in arr) {
        total' := total + item
    }
    return total
}
Section 10

Modules — aut

The aut keyword creates a named sub-automaton. State and label names inside are automatically prefixed, so there are no name collisions between modules.

aut RobotA {
    init idle
    idle    ---> working : start (1.0)
    working ---> idle    : stop  (1.0)
}

aut RobotB {
    init idle
    idle    ---> busy    : start (1.0)
    busy    ---> idle    : done  (1.0)
}

// Cross-module rule: RobotA's 'start' enables RobotB's 'start'
RobotA.start ->> RobotB.start : sync (0.8)

Section 11

PDL Verification

The PDL (Probabilistic Dynamic Logic) verifier checks logical properties of your model starting from any state. Results include a boolean verdict or a quantitative probability.

Propositional connectives

true  |  false  |  ¬φ  |  φ ∧ ψ  |  φ ∨ ψ  |  φ → ψ  |  φ ↔ ψ

State & condition propositions

s0 // true if current state = s0
counter == 3 // variable condition
flag == true

Modal operators

FormulaMeaning
<> φDiamond: some next state satisfies φ
[] φBox: all next states satisfy φ
<α> φAfter program α there exists a state satisfying φ
[α] φAfter program α all reachable states satisfy φ

PDL programs (α)

SyntaxMeaning
actionNameFire this action once
a ; bSequence: fire a then b
a + bChoice: fire a or b
a*Kleene star: repeat a zero or more times

Probabilistic path operators

FormulaMeaning
{ P>=0.9 [ F φ ] }Probability of eventually reaching φ is ≥ 0.9
{ P=? [ F φ ] }What is the exact probability of eventually reaching φ?
{ P=? [ G φ ] }What is the probability of φ holding globally?
{ P=? [ X φ ] }Probability of φ at the next step
{ P=? [ X X φ ] }Probability of φ after exactly 2 steps
{ P=? [ φ U ψ ] }Probability that φ holds until ψ is reached
{ P=? <α> φ }Probability of reaching φ after program α
Where to type PDL Use the PDL tab in the right panel. Select a starting state, then type your formula. Click the coloured buttons to insert state names, actions, and operators automatically.

PDL examples

// Can we reach state 'win'?
<> win

// Is it true that every next step goes to 'safe'?
[] safe

// After firing 'attack', can we reach 'dead'?
<attack> dead

// No matter how we fire 'move', we stay in 'valid'?
[move*] valid
// What is the probability of eventually reaching 'goal'?
P=? [ F goal ]

// Is the probability of failing globally below 5%?
P<0.05 [ G !fail ]

// Probability of reaching 'win' within exactly 3 steps
P=? [ X X X win ]

// Probability that 'idle' holds until 'working' is reached
P=? [ idle U working ]
// After firing 'a' then 'b', is 'target' reachable?
<a ; b> target

// After choosing between 'left' or 'right', reach 'exit'
<left + right> exit

// After any number of 'loop' firings, is 'done' reachable?
<loop*> done

// Probability of reaching 'end' via the sequence
P=? <step ; step ; step> end
// Is the variable counter == 5 eventually reachable?
P=? [ F counter == 5 ]

// Does every reachable state keep score >= 0?
[] score >= 0

// Combination: in state 'end' with total > 100
end && total > 100

// Is there a path where flag becomes true?
P=? [ F flag == true ]
Section 12

PCTL / PRISM Export Advanced

RePA can export your model to PRISM-compatible DTMC format and evaluate PCTL properties directly from the PCTL tab. The PRISM property language is a superset of what you type in the PDL panel.

PCTL syntax reference

SyntaxMeaning
P=? [ F s=3 ]Probability of reaching state ID 3
P>=0.9 [ F goal ]Is probability of reaching goal ≥ 0.9?
P=? [ G safe ]Probability of always being in safe
P=? [ X s=2 ]Probability of next state being 2
P=? [ a U b ]Probability of a holding until b
action_act=1Tests if action is currently enabled (in PRISM export)
action_act=0Tests if action is currently disabled

PCTL property file example

properties.pctl
// What is the probability of eventually reaching 'Delivered'?
P=? [ F Delivered ]

// Is it almost certain we avoid 'Crashed'?
P>=0.99 [ G !Crashed ]

// Is it always the case that 'go_work' can be activated?
P=? [ F go_work_act=1 ]

// Probability of reaching success in exactly 2 steps
P=? [ X X success ]
Workflow Use File → Export PRISM to download the .pm model, then paste your .pctl properties into PRISM for full model checking. Alternatively, the built-in PCTL tab runs properties directly without leaving the browser.
Section 13

Path Optimizer

The Path tab in the bottom panel uses a best-first search to find either the most probable or least probable path to a target.

OptionValues
Search TypeReach State — pick a destination state. Variable Value — find when a variable equals a given integer.
CriterionMax Probability (most likely path) or Min Probability (rarest path).

Results show the sequence of labels fired and the cumulative probability of that path.


Section 14

Statistical Training

Feed event-log data to the model and its weights will be updated automatically using empirical frequency or aggregation rules.

Input format

Each line is one session. Events within a session are comma-separated label names.

// File: sessions.txt
buy, checkout, pay
browse, buy, browse, exit
login, buy, pay

Training modes

ModeBehaviour
laplaceBayesian frequency estimation. Each firing of an edge increments a counter; weight = hits / total, with a Laplace prior of 50 virtual samples to avoid cold-start extremes.
aggregation arith (λ)Each firing applies the aggregation formula to update the weight. λ controls the learning rate.

Persistent vs reset mode

By default each session in the file is replayed from the initial state (reset). If your model uses persistent mode, the state carries over between sessions.

Sync weights to editor

After training, click Sync Weights → Editor to write the learned weights back into your source code. You can then save and re-use the calibrated model.


Section 15

Complete Model Examples

1. Simple two-state loop

A minimal model: one initial state, one transition out and one back, with a self-activating rule.

simple.Re
init s0

s0 ---> s1 : a
s1 ---> s0 : b

// Every time 'a' fires it deactivates itself
a  --!  a : offA

2. Vending machine with dynamic stock

vending.Re
int stock = 3
init Idle

Idle       ---> Selecting : insertCoin
Selecting  ---> Idle      : buyItem   (0.7) if (stock > 0) then {
    stock' := stock - 1
}
Selecting  ---> Idle      : cancel    (0.3)

// When stock reaches 0, buyItem disables itself
buyItem --! buyItem : outOfStock (0.1) if (stock == 0)

3. Recommendation algorithm

recommender.Re
calibration proportional
init Feed

Feed    ---> Watch  : watch
Watch   ---> Watch  : like
Watch   ---> Feed   : dontLike
Watch   ---> Feed   : refresh   disabled
Feed    ---> List   : watchLike disabled
List    ---> Watch  : watch2

// Rules
watch     ->>  dontLike  : wd
like      --!  dontLike  : ld
like      ->>  refresh   : lr
like      ->>  watchLike : lw
dontLike  --!  watchLike : dw

4. Biased coin over time

coin.Re
calibration proportional
int  flips = 0
int  side  = 0
init toss

toss ---> toss : heads (0.5) if (flips < 10) then {
    flips' := flips + 1
    side'  := 0
}
toss ---> toss : tails (0.5) if (flips < 10) then {
    flips' := flips + 1
    side'  := 1
}

// Bias: each heads makes the next heads more likely
heads ->> heads : bias (0.9) max

5. Drone delivery with failure recovery

drone.Re
init Home

Home       ---> Flying    : launch   (1.0)
Flying     ---> Delivered : success  (0.8)
Flying     ---> Crashed   : fail     (0.2)
Delivered  ---> Home      : return   (1.0)

// On failure, recovery re-enables the return path
fail ->> return (1.0)

// Useful PDL queries for this model:
// What is the probability of eventual delivery?
{ P=? [ F Delivered ] }
// Can we always recover from a crash?
[] !Crashed || <> Home

6. Multi-module robotic system

robots.Re
aut ArmA {
    init rest
    rest   ---> grip  : pickup (0.9)
    grip   ---> rest  : drop   (1.0)
}

aut ArmB {
    init rest
    rest   ---> place : insert  (1.0) disabled
    place  ---> rest  : release (1.0)
}

// ArmA's drop enables ArmB's insert
ArmA.drop ->> ArmB.insert : handoff (1.0)
// ArmB's release disables insert again
ArmB.release --! ArmB.insert : reset (1.0)
Appendix

Quick Reference Card

Declaration keywords

KeywordExampleMeaning
namename MyModelModel identifier (optional)
paradigmparadigm fuzzyprobabilistic or fuzzy
calibrationcalibration equalnormalize / equal / proportional
trainingtraining laplaceEnable statistical learning
initinit s0Set initial state
intint x = 0Integer variable
floatfloat r = 0.5Float variable
boolbool ok = trueBoolean variable
dyn int[]dyn int[] q = []Dynamic array
defdef f(x) { ... }Function definition
autaut Worker { ... }Module / sub-automaton

Edge arrows

ArrowTypeUsage
--->StandardSimple transition
-id->NamedTransition with explicit transId
->>Rule ONHyper-edge: activate / buff target
--!Rule OFFHyper-edge: deactivate / debuff target
--xRule OFFAlias for --!

PDL formula cheatsheet

FormulaReads as
<> φSome next state satisfies φ
[] φAll next states satisfy φ
<a> φFire a, then some state satisfies φ
[a] φFire a, then all states satisfy φ
<a*> φFire a zero or more times to reach φ
{ P=? [ F φ ] }Probability of eventually reaching φ
{ P=? [ G φ ] }Probability of φ holding always
{ P=? [ X φ ] }Probability of φ at next step
{ P=? [ φ U ψ ] }Probability of φ until ψ
{ P>=0.9 [ F φ ] }Is prob of reaching φ at least 90%?