How it fits together
state→Jev→answersprobabilities→[terms]degrees 0–1→[[rule]] ifrule scores→thenitems · outputs
- Jev reads the state and answers the questions with probabilities.
[terms] gives a short name to each answer the rules need. A term reads one probability and uses it as a degree from 0 to 1.
- Each
[[rule]] combines degrees in its if with AND, OR, NOT and hedges into a rule score: how strongly the policy supports its then.
- Each
then is an item, a yes when its score reaches the threshold, or a set of an output, which becomes a crisp number such as “2.17 hours”.
The file is checked against the questions before Jev is called, and the diagram redraws as you type, so a mistake costs nothing. A score is support, not a probability: don’t pass it on as “80% likely”.
The file at a glance
| Table | Needed | Keys | Default |
[logic] | no | and = "min", "product" or "lukasiewicz"; or = "max", "probsum" or "bounded" | min, max |
[decide] | no | threshold: 0 to 1 | 0.5 |
[terms] | yes | name = "target", one per answer the rules read | |
[output.NAME] | no | range = [low, high], then a set per key: [a, b, c] or [a, b, c, d] | |
[[rule]] | at least one | if, then, weight (0 to 1) | weight = 1.0 |
Any other key is an error, so a typo such as treshold is caught rather than ignored.
[terms]: naming the answers
A term is a lowercase name (a–z, 0–9, _) that points at one answer. Terms are lowercase and operators uppercase, so one can’t be taken for the other.
| Question type | Target | The term’s degree | Example |
| yes/no (Noul) | id | the probability of yes | raining = "raining" |
| Score | id.Level | that level’s probability | hot = "temp.Hot" |
| Choice | id.option | that option’s probability | billing = "team.billing" |
[terms]
cold = "temp.Cold" # a Score's level, written exactly as in the questions
this_week = "urgency.This week" # spaces and case must match
raining = "raining" # a yes/no question: its id alone
billing = "team.billing" # a Choice's option
- Exact text:
temp.hot doesn’t match the level Hot; the error lists the ones that exist.
- A Score or Choice needs a level or option (
temp alone is an error); a yes/no question takes none (raining.yes is an error).
- Unused terms are allowed while you edit, but they are still checked.
[[rule]]: if, then, weight
Each [[rule]] is one piece of know-how. Its if is a condition over terms, its then what it supports.
[[rule]]
if = "raining AND NOT hot" # a condition over the terms
then = "raincoat" # an item …
[[rule]]
if = "cold OR (raining AND humid)"
then = "warm layers"
weight = 0.8 # trusted a little less: its score is the if × 0.8
[[rule]]
if = "today OR blocked"
then = "reply_within IS soon" # … or OUTPUT IS SET, a set of an [output]
- A rule’s score is what its
if comes to, times its weight (default 1).
- Several rules with the same
then are joined by the file’s OR: with max, the strongest one decides.
- A
then of three words with IS in the middle is always an output (OUTPUT IS SET); any other text is an item.
Worked through: Jev gives raining 0.98 and hot 0.00, so raining AND NOT hot = min(0.98, 1 − 0.00) = 0.98, at or over the threshold of 0.5: a raincoat is a yes.
AND, OR, NOT
| Operator | Means | Degree | a = 0.8, b = 0.6 |
a AND b | both | the file’s and function (default min(a, b)) | 0.6 |
a OR b | either | the file’s or function (default max(a, b)) | 0.8 |
NOT a | not | 1 − a | 0.2 |
( … ) | grouping | the inside’s degree | |
Precedence, tightest first
- Hedges and
NOT apply to the next term or group: NOT VERY hot is NOT (VERY hot).
AND
OR: cold OR raining AND humid is cold OR (raining AND humid).
Use parentheses whenever you mean something else: (cold OR raining) AND humid.
- Operators are uppercase only: a lowercase
and is an error that points you to AND.
- An
if may be up to 256 words and brackets; beyond that, split it into rules with the same then.
Hedges
A hedge reshapes a term’s degree, or a group’s in parentheses. It moves where the threshold falls, and that is all it does.
| Hedge | Degree | a = 0.7 | a = 0.3 | Passes 0.5 when |
VERY a | a² | 0.49 | 0.09 | a ≥ 0.71 |
EXTREMELY a | a³ | 0.34 | 0.03 | a ≥ 0.79 |
SOMEWHAT a | √a | 0.84 | 0.55 | a ≥ 0.25 |
INDEED a | 2a² when a ≤ 0.5, else 1 − 2(1 − a)² | 0.82 | 0.18 | a ≥ 0.5 (pushes away from 0.5, and leaves 0.5 where it is) |
VERY angry asks for more certainty that the level is Angry; it can’t tell angry from furious. If intensity matters, give the question a level for it.
[logic]: the AND and OR functions
One AND and one OR for the whole file. The same OR joins conditions inside a rule, joins rules with the same then, and merges an output’s sets.
[logic]
and = "min" # or "product", "lukasiewicz"
or = "max" # or "probsum", "bounded"
and | Formula | 0.8 AND 0.6 | What it does |
min (default) | min(a, b) | 0.60 | The weakest condition decides. |
product | a × b | 0.48 | Every weak condition lowers the result. |
lukasiewicz | max(0, a + b − 1) | 0.40 | Strict: high only when both are. |
or | Formula | 0.8 OR 0.6 | What it does |
max (default) | max(a, b) | 0.80 | The strongest reason decides; a second one adds nothing. |
probsum | a + b − ab | 0.92 | Reasons reinforce each other; a reason written twice counts twice. |
bounded | min(1, a + b) | 1.00 | Reasons add up, capped at 1: for levels of one question, their probabilities’ sum. |
The usual pairs are min + max, product + probsum, and lukasiewicz + bounded. Leave it at min and max unless you want reasons to add up.
Items and the threshold
A then that isn’t OUTPUT IS SET names an item, any text: raincoat, page on-call. An item is a yes when its score is at or over the threshold.
[decide]
threshold = 0.6 # an item is a yes at or over this; default 0.5
- Nothing is exclusive unless a rule makes it so: with
raining at 0.5, both raining and NOT raining score 0.5 and both are a yes at 0.5.
- One threshold serves every item. For a costly action, use a weight or a separate rules file.
Outputs: a crisp amount
When the answer is an amount (“how many hours until we reply?”), conclude in an output. Each set is a shape on the output’s axis; rules conclude OUTPUT IS SET.
[output.reply_within] # the name: lowercase. The unit (hours) goes in a comment.
range = [0, 72] # the axis: low, high
soon = [0, 0, 2, 6] # a trapezoid a, b, c, d (here a left shoulder)
same_day = [4, 12, 24] # a triangle: a, peak, c
later = [20, 48, 72, 72] # a right shoulder, holding to the end
[[rule]]
if = "today OR blocked"
then = "reply_within IS soon"
| Written | Shape | Belongs fully |
[a, peak, c] | triangle | at peak |
[a, b, c, d] | trapezoid | from b to c |
[a, a, c, d] / [a, b, d, d] | left / right shoulder | from the start / to the end |
[p, p, p] | a single point | only at p |
How the value is worked out
- Score each set: the OR of the scores of the rules that conclude it.
- Clip each set flat at its score.
- Merge the clipped shapes with the file’s OR, point by point.
- Take the centroid, the balance point of the merged shape: that is the value. With no set above 0 there is no value (
-).
Points must be in order and inside range; overlap neighbouring sets so an answer between two levels lands between them. Read the value with its sets’ scores: it says where the support lies, not how much.
A complete example
For questions temp (Score: Cold, Mild, Hot), humidity (Score: Dry, Normal, Humid) and raining (yes/no):
[logic]
and = "min"
or = "max"
[decide]
threshold = 0.5
[terms]
cold = "temp.Cold"
mild = "temp.Mild"
hot = "temp.Hot"
humid = "humidity.Humid"
raining = "raining"
[[rule]]
if = "cold"
then = "coat"
[[rule]]
if = "mild AND NOT raining"
then = "light jacket"
[[rule]]
if = "raining AND NOT hot"
then = "raincoat"
[[rule]]
if = "VERY hot AND humid"
then = "t-shirt"
[[rule]]
if = "humid OR hot"
then = "breathable fabric"
weight = 0.9
Load the wear, irrigation or triage example from the header to see more, including an output and a Choice.
Mistakes and tips
| Mistake | What you’ll see |
| a level that doesn’t exist | [terms] hot: `temp` has no level `hot`; its levels are … |
a term not in [terms] | rule 1 (`wet`): `wet` isn't in [terms], which names … |
| a lowercase operator | `and` isn't in [terms]; the operator is written AND |
| a missing operator | `hot` where AND or OR should be |
| an unknown output | … there is no [output.wter]; did you mean `water IS some`? |
| a weight or threshold outside 0–1 | the weight is 2; it goes from 0 to 1 |
Designing rules
- Ask graded things as Scores with 3–5 named levels; keep yes/no for things that are simply true or false.
- One rule per piece of know-how, in the owner’s words: “a raincoat when it rains, unless it’s hot” is
raining AND NOT hot.
- Check coverage: walk the combinations (cold / mild / hot × raining or not) and make sure some rule speaks for each.
- Look for conflicts between rules that say opposite things about one situation, and decide which wins.
- Tune on real states: fix a rule, a weight or the threshold, never the answers; then check on cases you didn’t tune on.