Metadata-Version: 2.4
Name: knowledgespaces
Version: 0.1.0
Summary: Knowledge Space Theory in Python
Project-URL: Homepage, https://knowledgespaces.pages.dev
Project-URL: Documentation, https://knowledgespaces.pages.dev/docs/
Project-URL: Repository, https://github.com/UBarbieri/knowledgespaces
Project-URL: Issues, https://github.com/UBarbieri/knowledgespaces/issues
Project-URL: Changelog, https://github.com/UBarbieri/knowledgespaces/blob/main/CHANGELOG.md
Author: Umberto Barbieri
License: MIT
License-File: LICENSE
Keywords: BLIM,KST,adaptive-testing,knowledge-space-theory,psychometrics
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: click>=8.0
Requires-Dist: numpy>=1.24
Requires-Dist: rich>=13.0
Requires-Dist: scipy>=1.10
Provides-Extra: docs
Requires-Dist: furo; extra == 'docs'
Requires-Dist: myst-parser>=3.0; extra == 'docs'
Requires-Dist: numpydoc>=1.7; extra == 'docs'
Requires-Dist: sphinx-copybutton; extra == 'docs'
Requires-Dist: sphinx-design; extra == 'docs'
Requires-Dist: sphinx>=7.0; extra == 'docs'
Provides-Extra: viz
Requires-Dist: matplotlib>=3.6; extra == 'viz'
Description-Content-Type: text/markdown

# knowledgespaces

**Knowledge Space Theory in Python** (Doignon & Falmagne) — from item analysis to adaptive assessment.

```python
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

```bash
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:

```python
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

```python
# 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.

```python
# 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

```python
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:

```python
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]"`.

```python
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)

```python
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)

```python
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):

```bash
# 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

```python
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](https://github.com/UBarbieri/knowledgespaces/blob/main/mcp/README.md) 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:

```python
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
