Chapter 11 – Implementing Qualitative Process Theory

How a truth-maintained rule engine becomes a physics engine that reasons about change without numbers. companion index

The big idea

Up to now the book has built general machinery: pattern rules (ch04), justification- and logic-based truth maintenance (ch06ch10). Chapter 11 cashes it in on a real application: Qualitative Process Theory (QP), Forbus’s account of how physical systems change over time when all you know is signs and orderings, not exact magnitudes. The chapter’s program, TGIZMO, is a QP engine built on top of the LTRE.

The motivating idea is that people reason about the physical world without doing arithmetic. You know that pouring water from a full glass into an empty one will raise the level in the second and lower it in the first, that the flow will slow down as the levels approach each other, and that it stops when they are equal. You did not solve a differential equation. You reasoned with three coarse values for each quantity’s rate of change – increasing, steady, decreasing – and with ordinal comparisons (this is bigger than that). QP makes that style of reasoning precise and mechanical.

The crucial move, and the reason this chapter lives in a truth-maintenance book, is that causes of change are objects you can believe or disbelieve. A process (like fluid flow or heat flow) is active only when its conditions hold. When conditions change, processes switch on and off, and the consequences must be un-derived and re-derived cleanly. That is exactly what a TMS is for. TGIZMO uses the LTRE so that “which processes are running” and “which way is each quantity moving” are beliefs with justifications, revised automatically as the situation evolves.

Scope note for this repo. TGIZMO itself is not implemented in our Python package – we ported the TMS core (chapters 6–10, 13), not the QP layer on top. So this chapter is a conceptual tour, and the exercise answers in ../exercises/ch11/ are analyses and design sketches rather than runnable code. The “Try it” section below points you at the closest machinery we do have (the LTRE), because every QP idea here is ultimately a pattern of belief and justification you can prototype with it.

Concepts, step by step

Quantities: an amount and a derivative

The atom of QP is a quantity – a property of an object that can change, like the temperature of a cup of coffee or the amount of water in a can. Each quantity carries two pieces of qualitative information:

  • its amount A – the value, known only by its ordinal relations to landmarks and other amounts (is it positive? bigger than that one? equal to zero?), never as a number;
  • its derivative D (written Ds) – the direction it is moving, one of increasing (+), steady (0), or decreasing (-).

So “the can is emptying” is Ds(amount(water-in-can)) = -. All of QP’s power comes from propagating these two coarse values through a network of relationships.

Two ways quantities affect each other

QP distinguishes two kinds of causal link, and keeping them straight is the heart of the theory:

  • Direct influence (I+, I-): a process directly adds to or subtracts from a quantity’s rate of change. Fluid flow I+s the destination’s amount and I-s the source’s amount – it literally pumps stuff from one to the other. Direct influences are the only primitive sources of change; everything else is downstream.
  • Qualitative proportionality (Qprop, Qprop-): a quantity is some unknown but monotonic function of another. Pressure is Qprop to amount (more water, more pressure), level is Qprop to amount, and so on. Qprop does not cause change by itself; it transmits change. If amount goes up and pressure is Qprop to amount, then pressure goes up too.

A useful slogan: direct influences are the engines, qualitative proportionalities are the drive shafts. The engines decide what is being pushed; the shafts carry the motion to everything geared to it.

Influence resolution: combining the pushes

A quantity can be pushed by several influences at once – two inflows and an outflow on a tank, say. Influence resolution (resolve-influences) computes the net direction of change by qualitatively adding the contributions. The arithmetic is the sign algebra: + and + give +; + and - give ? (ambiguous – you cannot tell without magnitudes); + and 0 give +. When the net is ambiguous, QP honestly reports that it cannot decide, which is often the right answer (does the tank fill or drain? it depends on which flow is bigger).

A subtle but important design point, explored in Exercise 3, is that resolution records an explicit Resolved marker rather than just checking “do we have a Ds for this quantity yet?” The two are different facts. A derivative might be known for other reasons (a boundary condition, an external stipulation), and net-derivative-equals-sign-of-the-sum is only valid once all influences are in hand. The Resolved marker is the provenance of the derived derivative: it is the justification that the LTRE can retract when the set of active processes later changes. “Ds known” is just a value with no provenance, so it cannot drive sound, retraction-aware control.

Processes and views: the causes you can believe

A process is a parameterized cause of change with four parts:

  • Individuals – the typed objects it relates (a source container, a destination, a fluid path);
  • Preconditions – non-quantity conditions that must hold (the path is aligned/open);
  • Quantity conditions – ordinal conditions on quantities (source pressure > destination pressure, source amount > 0);
  • Relations and influences – the Qprops it asserts and the I+/I-s it applies while active.

A view is the same idea for being-a-something rather than doing-something (a quantity of stuff is a liquid while its temperature is in a certain range). Both are instantiated by matching their individuals against the object pool, then made active exactly when their preconditions and quantity conditions are believed. The set of currently active processes and views is the process structure, and it is the single most important abstraction in the chapter: it is what QP states are individuated by.

This matching is plain pattern-directed instantiation – the same job the TRE and LTRE do. Exercise 2 drives the point home with a deliberately broken process whose influences mention variables (?bar, ?self) never bound in its individuals field: instantiation either produces nothing or produces ill-formed instances over unground terms. The lesson is a familiar one for rule systems – every variable used in a body must be bound by the head – and it motivates the friendlier individuals syntax of Exercise 17.

Ordinal reasoning and consistency

Underneath everything sits an inequality/equality network over amounts and landmarks. QP needs to know, for instance, that if pressure(src) > pressure(dst) and both are Qprop to their amounts, then the flow’s quantity condition holds. Maintaining this soundly means transitive closure of <, =, > and detecting contradictions, the job of check-comp-cycle.

Exercise 4 asks why that checker does not explicitly handle the “the owning object does not exist, so its number relates to nothing” case. The elegant answer is that the invariant is enforced structurally: the assertions that put a number into ordinal relations are themselves justified by the existence of the object. When the object is gone, those justifications go out, the LTMS retracts the relations, and the checker simply never sees them. This is the chapter’s recurring design philosophy in miniature: push invariants into the justification structure so downstream algorithms can assume them, rather than re-checking them everywhere.

States and the measurement-interpretation algorithm

A state (snapshot) records a complete qualitative situation: which processes are active, the ordinal relations, and every quantity’s Ds. The chapter’s flagship reasoning task is measurement interpretation (MI): given some observed values or derivatives, find all process structures that could explain them. MI is a search – it assumes a candidate set of active/inactive processes, runs influence resolution, and uses the LTMS to detect when the candidate contradicts the data, pruning with nogoods exactly as dependency-directed search does.

Exercise 5 is the clearest window into why states are defined the way they are. “No flow” can happen for two reasons – equal pressures, or a blocked path – yet QP shows a single no-flow state. Why? Because a state is individuated by which processes are active, not by why the inactive ones are inactive. The flow process is off in both cases, the process structure is identical, and the current behavior is the same. The two reasons differ only in finer-grained truth values that matter for transitions (a small nudge restarts flow from equal pressures, but not from a blocked path) – and that finer abstraction is exactly the more expensive alternative weighed in Exercise 15a.

The modeling language and how it compiles

Models are written in a small modeling language (mlang) whose :RELATIONS, :INFLUENCES, and condition fields are turned into LTRE clauses by translate-relations at definition time. A recurring theme of the exercises is that the qualitative math – correspondences, shared-function declarations, arithmetic in equations – can be implemented either as run-time LTRE rules or expanded at compile time, and the trade-off mirrors RETE-style network compilation: more compiled output, but fewer, flatter, faster run-time rules.

The examples, explained

The chapter’s worked examples are all variations on fluid and heat flow, and each one isolates one mechanism:

  • Fluid flow between two containers. The canonical example. The flow process has individuals (source, destination, path), a precondition (the path is aligned), and quantity conditions (source has positive amount, source pressure exceeds destination pressure). While active it I-s the source amount and I+s the destination amount; pressures follow via Qprop. Watching it run shows the whole QP loop: a quantity condition makes the process active, the influences set derivatives, resolution combines them, the amounts and pressures move, and eventually a quantity condition fails and the process shuts off. This is the example behind Exercise 1 (is the “amount > 0” condition redundant given the pressure condition? – no, because pressure is only Qprop to amount, not equal to it, so the engine cannot infer a positive amount from a pressure inequality unless you add a correspondence and a shared-function fact) and Exercise 5 (the single no-flow state).

  • Heat flow driven by a temperature difference. Structurally identical to fluid flow but with temperatures and heat. It motivates two threads: the magnitude function m (Exercise 6), because the rate depends on the size of the temperature gap regardless of which side is hotter; and the arithmetic-in-equations machinery (Exercise 16c/16d), because flow-rate = temp(src) - temp(dst) must compile into Qprop+ on the source temperature, Qprop- on the destination temperature, and a correspondence saying the rate is zero when the temperatures are equal.

  • A water can / boiling scenario. The vehicle for the interpretation depends on the theory lesson (Exercise 13). If you tell MI the water level is dropping but the theory has no evaporation process, MI can only explain the drop with whatever removal process it does have (an outflow), or it returns no interpretation at all. Adding evaporation and condensation gives MI a legitimate new explanation – and more interpretations for the same data, illustrating the price of expressiveness. The fix-the-gap exercise (13b) and the prune-the-ambiguity exercises (8, 14) are two sides of the same coin: richer theories explain more but discriminate less, so you buy back precision with extra measurements, temporal continuity, or commonsense constraints.

Across all of them, the thing to watch is the interaction between the TMS and the physics: process activation is belief, influence resolution is derivation, and any change to the situation ripples through justifications automatically. That is why QP belongs on top of a truth-maintenance engine and not on top of an ordinary database.

Exercises walk-through

The full set with detailed analyses is in ../exercises/ch11/README.md. Because TGIZMO is out of scope for our port, these are conceptual answers – algorithm sketches, derivations, and design discussions, with no code run. The notable ones:

  • Ex 1 – is the “amount > 0” flow condition redundant? No, in general. Pressure is only qualitatively proportional to amount, so a pressure inequality does not by itself establish a positive amount. It becomes redundant only if you add a zero-correspondence and a shared-function declaration making two containers’ pressure functions identical (Ex 16a/16b).

  • Ex 2 – the malformed Zorch-it process. A worked diagnosis of free variables in a process body: instantiation produces nothing or produces degenerate instances over unground terms. A robust mlang should signal the error at compile time – motivation for the typed individuals syntax of Ex 17.

  • Ex 3 – why resolution uses a Resolved marker. Because the marker is the provenance of the net derivative, so the LTRE can retract resolution when the influence set changes; “Ds known” is a value without provenance and cannot drive sound, retraction-aware control. (See “Influence resolution” above.)

  • Ex 4 – the missing non-relation check in check-comp-cycle. Not needed, because object existence justifies the ordinal relations; when the object is gone the TMS retracts them and the checker never sees them. A clean example of pushing an invariant into the justification structure.

  • Ex 5 – one no-flow state for two causes. States are individuated by the active-process set, not by why inactive processes are off; equal-pressure and blocked-path are the same state but differ for transitions. (See “States and MI” above.)

  • Ex 6 – the magnitude function m. When it earns its keep (comparing opposing rates, symmetric driving terms, equilibrium reasoning), what must change to support it (the parser, the ordinal reasoner’s defining axioms, sign arithmetic, Qprop propagation, snapshots), and the algebra itself. The hard rule is the qualitative chain rule for the derivative: Ds(m(q)) = sign(q) * Ds(q) for q != 0, with a non-smooth bounce at zero that limit analysis should flag.

  • Ex 7 – profiling and three speedups. For an LTRE-based QP engine the matcher/instantiator usually dominates; the recommended fixes are type/argument indexing (a discrimination net), incremental re-instantiation of deltas only, and compile-time expansion of the math primitives (Ex 16e). The same trio recurs whenever you scale a pattern-directed system.

  • Ex 8 – discriminating measurements. A myopic information-gain probe selector (8a) that ranks unmeasured parameters by how well their predicted Ds values split the surviving interpretations – the same one-step-lookahead criterion used in GDE/Sherlock diagnosis – and an offline discrimination tree (8b) that compiles MI’s answers into a decision tree so run-time interpretation is just a tree walk, no TMS at all.

  • Ex 9 – reconstructing the database from a state. A snapshot of believed facts is not by itself enough to rebuild LTMS labels; you also need the defining assumptions (the precondition/quantity-condition truth assignment), the domain theory and scenario, and any external boundary values. Given those, reconsider (9b) rebuilds the state by re-deriving (reset, re-assert assumptions, run to fixpoint) rather than writing labels back – which is what lets the stored state stay compact.

  • Ex 10–12 – limit analysis, the envisioner, the history generator. The three-step ascent of qualitative simulation. Limit analysis (10) computes a state’s possible successors by finding which ordinal relations are closing toward equality and which quantity conditions are about to flip, filtered for rate consistency. The envisioner (11) is a fixed-point graph search that applies limit analysis until no new states appear, yielding the full envisionment (sinks are equilibria, cycles are oscillations). The history generator (12) instead unrolls a single time-ordered path, distinguishing intervals (episodes) from instants (transitions) and branching on genuine qualitative ambiguity.

  • Ex 13 – interpretation depends on theory and scenario. Without evaporation, MI cannot explain a falling water level the intuitive way; adding evaporation and condensation gives it a legitimate explanation and more interpretations. The headline lesson: interpretation is only as good as the domain theory.

  • Ex 14 – pruning interpretations. Three knowledge sources – extra measurements, temporal/history continuity (the current state must be a legal successor of the known previous one), and structural/commonsense constraints – with a sketch of wiring temporal continuity into the MI driver via a legal-successors constraint.

  • Ex 15 – MI search organization. Branching on individual precondition/quantity-condition truth values instead of active-process sets gives more, finer interpretations (up to 2^(#conditions)), more detail per interpretation, and worse efficiency (15a). If you only want the process structure, a leaner MI enumerates structures directly and checks feasibility lazily (15b); for very large problems, a backward-chaining MI instantiates only the sub-theory relevant to the measured quantities (15c) – goal-directed instantiation, the only way to scale to plant-sized models.

  • Ex 16 – extending the qualitative math. The workhorse Correspondence rule (16a) carries ordinal info across a Qprop from a known value point; Function-Spec (16b) shares one monotonic function across objects so ordinal facts propagate between individuals (equal glasses, more water, higher level); and equations with +, -, *, / compile into Qprop/Qprop- facts plus zero-correspondences (16c/16d), optionally expanded at compile time in translate-relations (16e).

  • Ex 17 – friendlier :INDIVIDUALS syntax. Add :TYPE, :CONDITIONS, :TEST, and :BIND as macro sugar lowering to the plain typed-pattern form (17a); weigh an optional :ASSUMPTIONS keyword (17b, recommendation: include it but default-derive assumption status from clause type); and move to an order-aware binding environment so the new keywords compose safely (17c, whose prompt is truncated in the source we worked from – the answer reconstructs the likely intent and flags the gap honestly).

Try it in this repo

There is no QP engine in this package, so there is nothing here that runs TGIZMO, MI, or limit analysis. The honest answer is that chapter 11 is conceptual in this repo, and the worked analysis lives in ../exercises/ch11/README.md.

What you can do is play with the LTRE that TGIZMO would have been built on, to get a feel for the belief-and-justification mechanics that make process activation and influence resolution work. The QP pattern – “a cause is active only while its conditions hold, and its consequences retract automatically when they stop” – is just a TMS-backed rule, and you can write that in the LTRE today:

. .venv/bin/activate

# A rule whose conclusion is retracted when its premise stops being believed --
# the same belief-revision behaviour QP relies on for process activation:
python examples/run_kb.py examples/kb/belief_revision.kb

# Dependency-directed search with nogood learning -- the engine under MI's
# "assume a process structure, prune on contradiction" loop:
python examples/coloring_dds.py

A tiny LTRE session that mimics the shape of a process turning a derivative on and off (a “flow active” condition driving an “amount increasing” conclusion):

from ltms.ltre import LTRE
e = LTRE()
# "while the flow process is active, the destination amount is increasing"
e.assert_(("implies", ("flow-active",), ("ds-increasing", "dest-amount")))
e.assume(("flow-active",), "scenario")
assert e.is_true(("ds-increasing", "dest-amount"))   # process is running
e.retract(("flow-active",), "scenario")
assert e.is_unknown(("ds-increasing", "dest-amount"))  # condition failed -> retracted

That retraction-on-condition-change is the core service QP needs from a TMS. The real engine adds the qualitative algebra (signs, ordinals, influence resolution) and the state-space search (MI, limit analysis) on top – the parts this repo leaves at the analysis level in ../exercises/ch11/. For the closest implemented relatives of QP’s search-with-learning loop, see the chapter 10 facilities – indirect proof, closed-world assumptions, and dependency-directed search – in ../src/ltms/indirect.py, ../src/ltms/cwa.py, and ../src/ltms/dds.py.

Takeaways

  • QP reasons about change with signs and orderings, not numbers: every quantity has an amount (known ordinally) and a derivative (+/0/-).
  • Direct influences (I+/I-) are the engines; qualitative proportionalities (Qprop) are the drive shafts. Only influences originate change; Qprop transmits it. Influence resolution qualitatively sums the engines, honestly reporting “ambiguous” when signs conflict.
  • A process/view is a cause you can believe, active only while its preconditions and quantity conditions hold. The set of active ones is the process structure, and states are individuated by it – which is why two reasons for “no flow” collapse into one state.
  • QP belongs on a TMS because situations change: activations and derivatives are beliefs with justifications, retracted and re-derived automatically. The Resolved marker (Ex 3) and the existence-justified ordinal relations (Ex 4) show the design ethos – push invariants into the justification structure.
  • Measurement interpretation is an assume-and-prune search (like dependency-directed search); limit analysis computes successor states, and stacking it gives the envisioner and history generator.
  • Interpretation is only as good as the domain theory: richer theories explain more but discriminate less, so you buy back precision with measurements, temporal continuity, and commonsense constraints.
  • In this repo chapter 11 is conceptual; the closest runnable machinery is the LTRE, and the full exercise analysis is in ../exercises/ch11/.

Back to the companion index · previous: Chapter 10 – LTRE · next: Chapter 12 – ATMS.


This site uses Just the Docs, a documentation theme for Jekyll.