Qualitative reasoning about dynamical systems: QSIM and friends, with tensorized/GPU execution in PyTorch.
Project description
qualitative-qsim
A Python/PyTorch library for qualitative reasoning (QR) about dynamical systems: simulating and analyzing the behavior of continuous systems when the governing equations are only partially known — described by monotonic relationships, signs, orderings, and landmark values rather than exact functions and parameters.
The initial centerpiece is an implementation of QSIM (Kuipers-style qualitative simulation), with the architecture deliberately laid out so other QR formalisms (envisionment, process-based modeling, semi-quantitative refinement) and tensorized/GPU-accelerated execution can slot in alongside it.
Status: functional alpha. The practical QSIM path, core model representation, behavior graphs, serialization, and numeric coverage bridge are the supported alpha core. The broader research surface is deliberately exposed at lower maturity levels rather than implied to have uniform validation. The project is available under the MIT License; APIs are pre-1.0 and may change.
| Maturity | Surface | What the label means |
|---|---|---|
| Core alpha | Model/QSIM practical profile, behavior graphs, schemas, trajectory abstraction and coverage | Supported alpha path; golden, adversarial, integration, and concrete-trajectory soundness checks |
| Experimental | Classic landmark discovery, chatter controls, energy/Lyapunov and phase filters, Q2 refinement, tensor execution and differentiable losses | Semantics and limitations are tested, but configuration and performance contracts may change |
| Research preview | Diagnosis, decomposition, induction, envisionment/guidance, process/device front ends, monotonicity and comparative/causal analysis | Usable and evidence-backed, but narrower scenario coverage; independently audit before consequential use |
The maturity and qualification record lists the evidence and known limits behind each label. The roadmap records implementation scope, not a claim that every module has equal validation depth.
Why qualitative reasoning?
A numeric simulator answers "what does this system with these parameters do from this initial condition?" A qualitative simulator answers a complementary question: "what are all the behaviors any system consistent with this qualitative description can exhibit?"
That makes QR useful for:
- Incomplete models — reasoning when you know
flow increases with levelbut not the pipe's discharge coefficient. - Behavior enumeration — producing the complete branching tree of qualitatively distinct outcomes (overflows / reaches equilibrium / oscillates), with guarantees that no real behavior is missed.
- Abstraction of numeric systems — compressing families of numeric trajectories into a small graph of qualitative states, giving a discrete, symbolic summary of a continuous system's phase portrait.
- Verification and explanation — checking that a fitted or learned numeric model only does things the qualitative physics allows, and explaining behaviors in human terms ("the level rises, decelerating, toward equilibrium").
Shape of the library
Model description Reasoning engines Analysis / bridge
───────────────── ───────────────── ──────────────────
QuantitySpace QSIM simulation Behavior graphs + queries
Variables (mag, dir) Attainable envisionment Trajectory abstraction
Constraints (M+, ADD, Batched/tensorized Coverage oracle
DERIV, MULT, ...) filtering (torch) Sign-structure intake
Corresponding values Semi-quantitative (Q2) Explanation + viz
Operating regions Landmark discovery Landmark harvest/proposal
docs/— design notes: vision, the hands-on tutorial, QR landscape survey, research references and implementation lineage, architecture, QSIM deep-dive, compact constraint syntax, signed-graph consistency, tensorization & GPU strategy, production-shaped scale profiles, numeric bridge, host integration, piecewise-affine analysis, literature survey, roadmap, and open questions.src/qrlib/— the library: core representations, the reference and tensorized engines, the numeric bridge, semi-quantitative refinement, analysis, and visualization (the architecture guide maps the layout).tests/— golden models, equivalence properties, and the soundness harness (concrete ODE instances integrated, abstracted, and verified against predicted behavior graphs).benchmarks/— measured reference-vs-tensor comparisons.
Installation
The supported install includes PyTorch:
pip install qualitative-qsim
PyTorch is imported lazily: ordinary model construction, reference
simulation, analysis, and the pure-Python bridge do not import it, while
SimConfig(backend="auto") uses tensor filtering only when the measured
workload shape benefits; explicit "reference" / "tensor" modes and
qrlib.tensor use the installed dependency directly.
Quick taste
import qrlib as qr
from qrlib import Qdir
from qrlib.analysis import explain
m = qr.Model("bathtub")
m.variable("amount", landmarks=("0", "FULL"))
m.variable("level", landmarks=("0", "TOP"))
m.variable("outflow", landmarks=("0", "OMAX"))
m.variable("inflow", landmarks=("0", "IF*"))
m.variable("netflow", landmarks=("0",), unbounded=True)
m.constrain(qr.MPlus("amount", "level", cvals=(("0", "0"), ("FULL", "TOP"))))
m.constrain(qr.MPlus("level", "outflow", cvals=(("0", "0"), ("TOP", "OMAX"))))
m.constrain(qr.Add("netflow", "outflow", "inflow")) # netflow + outflow = inflow
m.constrain(qr.Deriv("amount", "netflow")) # d(amount)/dt = netflow
m.constrain(qr.Constant("inflow"))
initial = m.state(
amount=("0", Qdir.INC), level=("0", Qdir.INC), outflow=("0", Qdir.INC),
inflow=("IF*", Qdir.STD), netflow=(("0", "+inf"), Qdir.DEC),
)
result = qr.qsim(m, initial)
for b in result.behaviors():
print(explain.narrate(result.graph, b))
yields exactly the three textbook outcomes — equilibrium below FULL, equilibrium exactly at FULL, and overflow. The practical default keeps an intermediate equilibrium unnamed:
Behavior of 'bathtub': 3 states, ending in quiescent.
0. Initially, amount at 0, rising, level at 0, rising, ...
1. Then, over an interval, amount rises into (0, FULL); ...
2. At the next instant, amount levels off in (0, FULL); ...
— the system is in equilibrium ...
SimConfig() is the sound, bounded practical profile: landmark discovery is
off and structurally unobservable direction chatter is merged automatically.
Use SimConfig.classic() when named intermediate extrema and full textbook
QSIM discovery are required; classic runs may not terminate and report
actionable diagnostics when a resource limit is reached.
Constraints may equivalently use the optional compact authoring syntax, for
example m.constrain("Deriv(amount, netflow)"); models still store and
serialize ordinary constraint objects.
From here: qrlib.bridge.coverage checks numeric trajectories against the
graph (witness paths / localized refutations), qrlib.semiquant turns
landmark bounds and monotone-function envelopes into guaranteed value and
transition-time bounds (and prunes numerically impossible behaviors), and
qrlib.viz renders timelines and behavior trees as plain data or SVG.
Additional modules provide total envisionment, temporal-logic guidance,
model induction and diagnosis, comparative/causal analysis, decomposition,
differentiable constraint losses, and process/device modeling front ends.
qrlib.analysis.monotonicity.check_signed_graph additionally certifies
whether all declared M+/M-/Minus relationships admit one consistent
orthant ordering, returning a contradictory signed cycle when they do not.
Design commitments (early)
- Model description is decoupled from every engine. A
Modelis pure data; QSIM, envisioners, tensor engines, and abstraction tools all consume the same description. - PyTorch-native state encoding. Qualitative states have a canonical integer-tensor encoding so that large frontiers, ensembles of models, and batches of numeric trajectories can be processed with batched tensor ops (GPU when it helps; the semantics never require it).
- Numeric systems are first-class neighbors. Interfaces are shaped so a numeric dynamical system (a vector field / trajectory source) can be abstracted into, or checked against, a qualitative model — see the numeric bridge.
- Embeddable by design. Larger dynamical-systems toolkits should be able to build thin adapter modules on top of qrlib — names as canonical identity, no CAS/graph-library dependencies in core, tensors as the only numeric interchange, serializable witness-carrying results — see host integration.
- Soundness is sacred, spuriousness is managed. Like QSIM itself: never drop a real behavior; add filters to prune impossible ones.
Research lineage and citation
The core semantics follow Kuipers1986 and the authoritative Kuipers1994 presentation. Process-centered authoring draws from Forbus1984, device composition and envisionment from deKleerBrown1984, and semi-quantitative refinement from KuipersBerleant1988.
The
canonical annotated bibliography
maps every research-derived feature to its source. Machine-readable records
are in
paper.bib,
software citation metadata is in
CITATION.cff,
and the draft JOSS article is
paper.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qualitative_qsim-0.1.0.tar.gz.
File metadata
- Download URL: qualitative_qsim-0.1.0.tar.gz
- Upload date:
- Size: 310.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5c56c63f906e0600d89e5f104e3ff5fd93606f92ff0da021b01090373ce059c
|
|
| MD5 |
dfc5ef456bbcfecd1736d14ba8923c84
|
|
| BLAKE2b-256 |
a9a13165759276f517d351314cd8c2ae481ed9cd3fefc2b2ea814443c2f75e96
|
Provenance
The following attestation bundles were made for qualitative_qsim-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on alanoursland/qualitative-qsim
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qualitative_qsim-0.1.0.tar.gz -
Subject digest:
c5c56c63f906e0600d89e5f104e3ff5fd93606f92ff0da021b01090373ce059c - Sigstore transparency entry: 2255346001
- Sigstore integration time:
-
Permalink:
alanoursland/qualitative-qsim@cd2bf39d0f4d22c88a398db960db70b5e59838f4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/alanoursland
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@cd2bf39d0f4d22c88a398db960db70b5e59838f4 -
Trigger Event:
release
-
Statement type:
File details
Details for the file qualitative_qsim-0.1.0-py3-none-any.whl.
File metadata
- Download URL: qualitative_qsim-0.1.0-py3-none-any.whl
- Upload date:
- Size: 152.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78cfd66a188973150ae442ff35952e1b099d57158da49a3e7f128ee42eda2dd4
|
|
| MD5 |
226219e5f3c9ce2470fadce9682efc0e
|
|
| BLAKE2b-256 |
17c81e7dcbc72b52dafef096112990b07b4c2fc593b6a5a98485c66653ffffca
|
Provenance
The following attestation bundles were made for qualitative_qsim-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on alanoursland/qualitative-qsim
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qualitative_qsim-0.1.0-py3-none-any.whl -
Subject digest:
78cfd66a188973150ae442ff35952e1b099d57158da49a3e7f128ee42eda2dd4 - Sigstore transparency entry: 2255346006
- Sigstore integration time:
-
Permalink:
alanoursland/qualitative-qsim@cd2bf39d0f4d22c88a398db960db70b5e59838f4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/alanoursland
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@cd2bf39d0f4d22c88a398db960db70b5e59838f4 -
Trigger Event:
release
-
Statement type: