Knowledge Space Theory in Python
Project description
knowledgespaces
Knowledge Space Theory in Python (Doignon & Falmagne) — from item analysis to adaptive assessment.
import knowledgespaces as ks
# Build a knowledge structure from prerequisites
structure = ks.space_from_prerequisites(
["add", "sub", "mul"],
[("add", "sub"), ("sub", "mul")],
)
print(structure.n_states) # 4 (out of 8 possible)
print(structure.is_learning_space) # True
# Assess a student
result = ks.assess(structure, {"add": True, "sub": True, "mul": False})
print(result["state"]) # {'add', 'sub'}
print(result["outer_fringe"]) # {'mul'} — what to learn next
Install
uv add knowledgespaces
# or
pip install knowledgespaces
Requires Python 3.10+. Dependencies: numpy, scipy, click, rich.
Quickstart
All examples below use the same domain — basic arithmetic:
import knowledgespaces as ks
# add → sub → mul (linear prerequisite chain)
structure = ks.space_from_prerequisites(
items=["add", "sub", "mul"],
prerequisites=[("add", "sub"), ("sub", "mul")],
)
print(f"{structure.n_states} valid states out of {2**structure.n_items} possible")
# 4 valid states out of 8 possible
1. Assess a student
# One observation per item
result = ks.assess(structure, {"add": True, "sub": True, "mul": False})
print(result["state"]) # {'add', 'sub'}
print(result["probability"]) # confidence
print(result["outer_fringe"]) # {'mul'} — what to learn next
# Multiple observations per item (from different instances)
result = ks.assess(structure, [("add", True), ("add", True), ("sub", True), ("mul", False)])
2. Adaptive assessment
In KST, each item (competency) can be tested through multiple instances (concrete questions). The engine selects the most informative instance, maps it to its parent item for the BLIM update, and never repeats the same question.
# Recommended: provide multiple instances per item
result = ks.adaptive_assess(
structure,
ask_fn=lambda instance_id: ask_student(instance_id), # your UI/API
instances={
"add": ["3+2", "7+5", "12+9"],
"sub": ["8-3", "15-7", "20-6"],
"mul": ["4*3", "6*7", "9*8"],
},
max_questions=10,
)
print(result["state"])
print(f"Converged in {result['questions_asked']} questions")
# Quick testing without instances (one question per item)
result = ks.adaptive_assess(structure, lambda item: item in {"add", "sub"})
3. Estimate BLIM parameters from data
result = ks.fit_blim(
structure,
items=["add", "sub", "mul"],
responses=[[1, 1, 1], [1, 1, 0], [1, 0, 0], [0, 0, 0]],
counts=[45, 30, 20, 5],
)
print(result["converged"]) # True
print(result["beta"]) # {'add': 0.04, 'sub': 0.08, 'mul': 0.12}
print(result["eta"]) # {'add': 0.11, 'sub': 0.09, 'mul': 0.06}
# Goodness-of-fit statistics
print(result["gof"]["G2"]) # likelihood ratio statistic
print(result["gof"]["p_value"]) # chi-squared p-value
print(result["gof"]["AIC"]) # Akaike Information Criterion
print(result["gof"]["BIC"]) # Bayesian Information Criterion
# Use estimated parameters to assess a new student
assessment = ks.assess_from_fit(structure, result, {"add": True, "sub": True, "mul": False})
print(assessment["state"]) # {'add', 'sub'}
# Or run adaptive assessment with estimated parameters
assessment = ks.adaptive_assess_from_fit(structure, result, ask_fn=my_question_function)
For better parameter estimates, use multi-restart EM to avoid local optima:
from knowledgespaces.estimation import estimate_blim_restarts, ResponseMatrix
data = ResponseMatrix(items=["add", "sub", "mul"], patterns=responses, counts=counts)
best = estimate_blim_restarts(structure, data, n_restarts=10, seed=42)
print(best.log_likelihood) # best LL across 10 random initializations
4. Visualize structures
Plotting requires the optional viz extra:
pip install "knowledgespaces[viz]".
from knowledgespaces.viz import plot_hasse, plot_relation
# Hasse diagram of knowledge states
fig = plot_hasse(structure, title="Arithmetic Knowledge Space")
fig.savefig("hasse.png")
# Prerequisite relation diagram
rel = structure.surmise_relation()
fig = plot_relation(rel, title="Prerequisites")
5. Build from skill maps (CB-KST)
structure = ks.structure_from_skill_map(
skill_map={"q1": ["s_add"], "q2": ["s_add", "s_carry"], "q3": ["s_mul"]},
skill_prerequisites=[("s_add", "s_carry")],
)
6. Import/export CSV (compatible with R)
from knowledgespaces.io import read_skill_map, read_relation, read_structure, write_structure
structure = read_structure("learning_space.csv")
write_structure(structure, "output.csv")
7. Command-line interface
The knowledgespaces CLI provides interactive tools for non-programmers (e.g. teachers, domain experts):
# Inspect a structure file
ks inspect structure.json
ks inspect data.csv --kind structure --states --paths
# Derive a structure by querying an expert interactively
ks query add sub mul div -o structure.json
# Run an adaptive assessment
ks assess structure.json
ks assess structure.json --instances pool.json --threshold 0.9
All commands support --json for machine-readable output and --no-color for non-interactive environments.
8. Compare structures
from knowledgespaces.metrics import symmetric_difference, hausdorff, cohens_kappa
print(symmetric_difference(ks_human, ks_ai)) # states in one but not other
print(hausdorff(ks_human, ks_ai)) # max min-distance
print(cohens_kappa(rel_human, rel_ai)) # agreement on prerequisites
9. Use via LLM (MCP server)
The project provides an MCP server that lets you use KST directly from Claude, ChatGPT, or any MCP-compatible AI assistant — no Python code needed. It lives in the project's GitHub repository and is not bundled in the pip install knowledgespaces package.
You: "Build a knowledge structure for arithmetic with items add, sub, mul
where add is prerequisite for sub, and sub for mul."
Claude: [calls build_structure tool] → returns structure with 4 states, learning space ✓
You: "Assess a student who got add and sub correct but mul wrong."
Claude: [calls assess_student tool] → state {add, sub}, outer fringe {mul}
You: "Show me the Hasse diagram."
Claude: [calls plot_hasse tool] → displays diagram with student state highlighted
The server exposes tools, the full library documentation as MCP resources, and prompt templates for guided workflows. See the MCP server README for setup instructions.
Advanced usage
The high-level API (space_from_prerequisites, assess, etc.) covers most use cases. For full control, use the building blocks directly:
from knowledgespaces import KnowledgeStructure, SurmiseRelation, BLIM, BLIMParams, StatePosterior
# Build objects manually
rel = SurmiseRelation(["a", "b", "c"], [("a", "b"), ("b", "c")])
closure = rel.transitive_closure()
hasse = closure.transitive_reduction()
ks = KnowledgeStructure.from_surmise_relation(closure)
# Inspect structural properties
print(ks.is_knowledge_space) # True
print(ks.is_closure_space) # True
print(ks.base()) # minimal generating family
print(ks.learning_paths()) # all paths from ∅ to full domain
print(ks.atoms()) # {item: [minimal states containing item]}
# Query experts
from knowledgespaces import run_query
from knowledgespaces.query import CallbackExpert
result = run_query(["a", "b", "c"], CallbackExpert(my_expert_fn))
# Full BLIM control
blim = BLIM(structure, BLIMParams(beta=0.1, eta=0.2))
posterior = StatePosterior.uniform(blim)
posterior = posterior.update("a", True)
Modules
| Module | What it does |
|---|---|
knowledgespaces |
High-level API: space_from_prerequisites, assess, fit_blim, ... |
knowledgespaces.structures |
SurmiseRelation, KnowledgeStructure — core algebraic objects |
knowledgespaces.query |
QUERY algorithm (Block 1 + Block N) — derive structures from expert queries |
knowledgespaces.derivation |
CB-KST — derive structures from skill maps |
knowledgespaces.assessment |
BLIM + Bayesian adaptive assessment with EIG item selection |
knowledgespaces.estimation |
EM algorithm for BLIM parameter estimation |
knowledgespaces.io |
CSV and JSON import/export |
knowledgespaces.metrics |
Hausdorff, symmetric difference, Cohen's kappa, directional distances |
knowledgespaces.cli |
CLI: ks inspect, ks query, ks assess |
mcp/ |
MCP server (in the GitHub repo, not the PyPI package): use KST via LLM |
Scalability note
This library uses exact enumeration of knowledge states. It works well for domains up to ~20 items. For larger domains, consider approximate or incremental methods (not yet implemented).
References
- Doignon, J.-P., & Falmagne, J.-C. (1999). Knowledge Spaces. Springer-Verlag.
- Falmagne, J.-C., & Doignon, J.-P. (2011). Learning Spaces. Springer-Verlag.
- Koppen, M., & Doignon, J.-P. (1990). How to build a knowledge space by querying an expert. Journal of Mathematical Psychology, 34(3), 311–331.
- Heller, J., & Wickelmaier, F. (2013). Minimum discrepancy estimation in probabilistic knowledge structures. Electronic Notes in Discrete Mathematics, 42, 49–56.
License
MIT
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 knowledgespaces-0.1.0.tar.gz.
File metadata
- Download URL: knowledgespaces-0.1.0.tar.gz
- Upload date:
- Size: 249.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f6cfa1d85193486c3893c83936b01bdfe3e59431cdfde5448f98ea9c094baea8
|
|
| MD5 |
b8aa19d0eb315bfbb7c54b2608205495
|
|
| BLAKE2b-256 |
fbc3c399cf41f10a6d5f085ecc2d11b0e463231efd7d120f04cd94e942e62641
|
Provenance
The following attestation bundles were made for knowledgespaces-0.1.0.tar.gz:
Publisher:
release.yml on UBarbieri/knowledgespaces
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
knowledgespaces-0.1.0.tar.gz -
Subject digest:
f6cfa1d85193486c3893c83936b01bdfe3e59431cdfde5448f98ea9c094baea8 - Sigstore transparency entry: 1756292317
- Sigstore integration time:
-
Permalink:
UBarbieri/knowledgespaces@acf611e601bcece2cf0f4377ffed71ce6eff049c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/UBarbieri
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@acf611e601bcece2cf0f4377ffed71ce6eff049c -
Trigger Event:
push
-
Statement type:
File details
Details for the file knowledgespaces-0.1.0-py3-none-any.whl.
File metadata
- Download URL: knowledgespaces-0.1.0-py3-none-any.whl
- Upload date:
- Size: 85.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f489fcf0c9f9b95605933c324fb02f5ec0a6904ed349c2f0ac121705e8783ca9
|
|
| MD5 |
41651bc9caaf6670c52df8875ca28b37
|
|
| BLAKE2b-256 |
c4d97e2e964970165a266e824afb9f0f7b7dc589c3a06a6ec078cf44a135ff99
|
Provenance
The following attestation bundles were made for knowledgespaces-0.1.0-py3-none-any.whl:
Publisher:
release.yml on UBarbieri/knowledgespaces
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
knowledgespaces-0.1.0-py3-none-any.whl -
Subject digest:
f489fcf0c9f9b95605933c324fb02f5ec0a6904ed349c2f0ac121705e8783ca9 - Sigstore transparency entry: 1756292324
- Sigstore integration time:
-
Permalink:
UBarbieri/knowledgespaces@acf611e601bcece2cf0f4377ffed71ce6eff049c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/UBarbieri
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@acf611e601bcece2cf0f4377ffed71ce6eff049c -
Trigger Event:
push
-
Statement type: