Fuzzy Jev Explore

what Jev judges
TOML, optional
⌘ ↵ to run · the diagram redraws as you type

Rules diagram

–
No diagram yetWrite rules on the left, or load an example, and they're drawn here as you type.

Writing rules

a rules file is TOML: a policy written over Jev's answers

How it fits together

state→Jev→answersprobabilities→[terms]degrees 0–1→[[rule]] ifrule scores→thenitems · outputs
  1. Jev reads the state and answers the questions with probabilities.
  2. [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.
  3. Each [[rule]] combines degrees in its if with AND, OR, NOT and hedges into a rule score: how strongly the policy supports its then.
  4. 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

TableNeededKeysDefault
[logic]noand = "min", "product" or "lukasiewicz"; or = "max", "probsum" or "bounded"min, max
[decide]nothreshold: 0 to 10.5
[terms]yesname = "target", one per answer the rules read
[output.NAME]norange = [low, high], then a set per key: [a, b, c] or [a, b, c, d]
[[rule]]at least oneif, 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 typeTargetThe term’s degreeExample
yes/no (Noul)idthe probability of yesraining = "raining"
Scoreid.Levelthat level’s probabilityhot = "temp.Hot"
Choiceid.optionthat option’s probabilitybilling = "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

OperatorMeansDegreea = 0.8, b = 0.6
a AND bboththe file’s and function (default min(a, b))0.6
a OR beitherthe file’s or function (default max(a, b))0.8
NOT anot1 − a0.2
( … )groupingthe inside’s degree

Precedence, tightest first

  1. Hedges and NOT apply to the next term or group: NOT VERY hot is NOT (VERY hot).
  2. AND
  3. 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.

HedgeDegreea = 0.7a = 0.3Passes 0.5 when
VERY aa²0.490.09a ≥ 0.71
EXTREMELY aa³0.340.03a ≥ 0.79
SOMEWHAT a√a0.840.55a ≥ 0.25
INDEED a2a² when a ≤ 0.5, else 1 − 2(1 − a)²0.820.18a ≥ 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"
andFormula0.8 AND 0.6What it does
min (default)min(a, b)0.60The weakest condition decides.
producta × b0.48Every weak condition lowers the result.
lukasiewiczmax(0, a + b − 1)0.40Strict: high only when both are.
orFormula0.8 OR 0.6What it does
max (default)max(a, b)0.80The strongest reason decides; a second one adds nothing.
probsuma + b − ab0.92Reasons reinforce each other; a reason written twice counts twice.
boundedmin(1, a + b)1.00Reasons 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"
WrittenShapeBelongs fully
[a, peak, c]triangleat peak
[a, b, c, d]trapezoidfrom b to c
[a, a, c, d] / [a, b, d, d]left / right shoulderfrom the start / to the end
[p, p, p]a single pointonly at p

How the value is worked out

  1. Score each set: the OR of the scores of the rules that conclude it.
  2. Clip each set flat at its score.
  3. Merge the clipped shapes with the file’s OR, point by point.
  4. 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

MistakeWhat 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–1the 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.