API Reference¶
Complete reference generated from source code docstrings.
High-level API¶
High-level convenience API for common KST operations.
Designed for users who want simple function calls without needing to construct intermediate objects. Accepts plain Python types (lists, dicts, tuples) instead of library-specific classes.
This module re-exports its functions at the package level, so you can write:
import knowledgespaces
structure = ks.space_from_prerequisites(...)
instead of dealing with SurmiseRelation, KnowledgeStructure, etc.
- knowledgespaces.api.space_from_prerequisites(items, prerequisites)[source]¶
Build a knowledge structure from prerequisite pairs.
- Parameters:
- itemslist[str]
All item names.
- prerequisiteslist[tuple[str, str]]
Pairs (a, b) meaning ‘a is a prerequisite of b’.
- Returns:
- KnowledgeStructure
The ordinal knowledge structure (closed under union and intersection).
- Parameters:
- Return type:
Examples
>>> ks = space_from_prerequisites( ... ["add", "sub", "mul"], ... [("add", "sub"), ("sub", "mul")], ... ) >>> ks.n_states 4
- knowledgespaces.api.structure_from_skill_map(skill_map, skill_prerequisites=None)[source]¶
Derive a knowledge structure from a skill map (CB-KST).
Note: with conjunctive skill maps (items requiring multiple skills) the result is not necessarily union-closed and therefore may not be a knowledge space. Use
is_knowledge_spaceto check.- Parameters:
- skill_mapdict[str, list[str]]
For each item, the list of skills it requires. Example: {“q1”: [“s_add”], “q2”: [“s_add”, “s_carry”]}
- skill_prerequisiteslist[tuple[str, str]] or None
Pairs (a, b) meaning ‘skill a is a prerequisite of skill b’. If None, skills are treated as independent.
- Returns:
- KnowledgeStructure
The derived knowledge structure (may or may not be a space).
- Parameters:
- Return type:
Examples
>>> ks = structure_from_skill_map( ... {"q1": ["s1"], "q2": ["s1", "s2"]}, ... [("s1", "s2")], ... )
- knowledgespaces.api.space_from_skill_map(skill_map, skill_prerequisites=None)[source]¶
Deprecated: use
structure_from_skill_map()instead.This function was renamed because with conjunctive skill maps the result is not necessarily a knowledge space.
- knowledgespaces.api.assess(structure, responses, beta=0.1, eta=0.2, prior=None)[source]¶
Assess a student’s knowledge state from their responses.
- Parameters:
- structureKnowledgeStructure
The knowledge structure.
- responsesdict[str, bool] or list[tuple[str, bool]]
Observed responses. Two formats accepted:
dict: one observation per item, e.g.{"add": True, "sub": False}list of tuples: multiple observations allowed per item (from different instances), e.g.[("add", True), ("add", True), ("sub", False)]
In the list format, the same item can appear multiple times. Each observation updates the posterior independently (local independence assumption).
- betafloat or dict[str, float]
Slip parameter (scalar or per-item).
- etafloat or dict[str, float]
Guess parameter (scalar or per-item).
- priordict[frozenset[str], float] or None
Optional prior over states (e.g. from a previous EM fit). If None, a uniform prior is used.
- Returns:
- dict
Keys: ‘state’ (most likely state as a set), ‘probability’, ‘mastery’ (per-item mastery probabilities), ‘inner_fringe’, ‘outer_fringe’.
- Parameters:
- Return type:
Examples
One observation per item:
result = assess(structure, {"add": True, "sub": True, "mul": False})
Multiple instances of the same item:
result = assess(structure, [("add", True), ("add", True), ("sub", False)])
- knowledgespaces.api.assess_from_fit(structure, fit, responses)[source]¶
Assess using estimated parameters from
fit_blim().Equivalent to
assess(structure, responses, beta=..., eta=..., prior=...)with values taken from the fit result.- Parameters:
- structureKnowledgeStructure
The knowledge structure (same used for fitting).
- fitdict
Output of
fit_blim().- responsesdict or list
Observed responses (same format as
assess()).
- Parameters:
- Return type:
- knowledgespaces.api.adaptive_assess(structure, ask_fn, *, instances=None, beta=0.1, eta=0.2, prior=None, threshold=0.85, max_questions=25)[source]¶
Run a complete adaptive assessment.
- Parameters:
- structureKnowledgeStructure
The knowledge structure.
- ask_fncallable
If instances is None: takes an item name (str) and returns bool. If instances is provided: takes an instance ID (str) and returns bool.
- instancesdict[str, list[str]] or None
Optional mapping {item: [instance_id, …]} for multi-instance assessment. When provided, the engine selects the best un-asked instance (not item) and passes its ID to ask_fn. Different instances of the same item are treated as equivalent by the BLIM.
- beta, etafloat or dict[str, float]
BLIM parameters (scalar or per-item).
- priordict[frozenset[str], float] or None
Optional prior over states. If None, uniform.
- thresholdfloat
Stop when most likely state reaches this probability.
- max_questionsint
Maximum number of questions to ask.
- Returns:
- dict
Keys: ‘state’, ‘probability’, ‘mastery’, ‘inner_fringe’, ‘outer_fringe’, ‘questions_asked’ (int), ‘history’ (list of (instance_or_item, item, response) tuples).
- Parameters:
- Return type:
Examples
Simple (one instance per item):
result = adaptive_assess(structure, lambda item: item in {"add", "sub"})
With multiple instances:
result = adaptive_assess( structure, lambda inst_id: ask_student(inst_id), instances={ "addition": ["3+2", "7+5", "12+9"], "subtraction": ["8-3", "15-7"], }, )
- knowledgespaces.api.adaptive_assess_from_fit(structure, fit, ask_fn, *, instances=None, threshold=0.85, max_questions=25)[source]¶
Run adaptive assessment using parameters from
fit_blim().Equivalent to
adaptive_assess(structure, ask_fn, beta=..., eta=..., prior=...)with values taken from the fit result.- Parameters:
- structureKnowledgeStructure
The knowledge structure (same used for fitting).
- fitdict
Output of
fit_blim().- ask_fncallable
Question function (same as
adaptive_assess()).- instances, threshold, max_questions
Passed through to
adaptive_assess().
- Parameters:
- Return type:
- knowledgespaces.api.fit_blim(structure, items, responses, counts=None)[source]¶
Estimate BLIM parameters from response data via EM.
- Parameters:
- structureKnowledgeStructure
The knowledge structure.
- itemslist[str]
Item names (column labels for the response matrix).
- responsesarray-like
Binary response matrix, shape (n_patterns, n_items).
- countsarray-like or None
Optional frequency of each pattern.
- Returns:
- dict
Keys: ‘beta’ (dict item→float), ‘eta’ (dict item→float), ‘pi’ (dict frozenset→float, state prior probabilities), ‘states’ (list of frozensets, ordered as in pi), ‘log_likelihood’ (float), ‘converged’ (bool), ‘n_iterations’ (int), ‘gof’ (dict with G2, df, p_value, npar, AIC, BIC).
- Parameters:
- Return type:
Examples
>>> result = fit_blim(structure, ["a","b","c"], [[1,1,1],[1,1,0],[1,0,0],[0,0,0]]) >>> result["converged"] True
knowledgespaces.structures¶
Surmise relations (partial orders) on item domains.
A surmise relation is a partial order (reflexive, antisymmetric, transitive) on a set of items that encodes prerequisite dependencies. If (a, b) is in the relation, then mastering item a is a prerequisite for mastering item b.
Note: the class stores only strict pairs (a != b) and treats reflexivity as implicit. The QUERY algorithm (Block 1) assumes antisymmetry during pruning, consistent with the standard KST formulation where the surmise relation is a partial order (Learning Spaces, Falmagne & Doignon, 2011).
- References:
Falmagne, J.-C., & Doignon, J.-P. (2011). Learning Spaces. Springer-Verlag.
- class knowledgespaces.structures.relations.SurmiseRelation(items, relations)[source]¶
A partial order on items representing prerequisite dependencies.
The relation is stored as a set of directed pairs (a, b) meaning ‘a is a prerequisite of b’. Self-loops are excluded from storage (reflexivity is implicit). Antisymmetry is assumed by the QUERY algorithm but not enforced at construction time; use
is_antisymmetric()to verify.- Parameters:
- itemsCollection[str]
The domain of items.
- relationsCollection[tuple[str, str]]
Pairs (a, b) where a is a prerequisite of b. Self-loops (a, a) are silently ignored.
- Parameters:
- transitive_closure()[source]¶
Compute the transitive closure (Floyd-Warshall).
Returns a new SurmiseRelation containing all transitively implied pairs. If (a, b) and (b, c) are in the relation, (a, c) is added.
- Return type:
- transitive_reduction()[source]¶
Compute the transitive reduction (Hasse diagram).
Returns a new SurmiseRelation containing only the direct prerequisite edges — removes any edge (a, c) when there exists an intermediate item b such that (a, b) and (b, c) are both in the transitive closure.
- Return type:
- prerequisites_of(item)[source]¶
Return the prerequisites of an item in the stored relation.
Returns only items directly related in this instance’s edges. To get all transitive prerequisites, call
transitive_closure()first, then query the result.
- successors_of(item)[source]¶
Return the successors of an item in the stored relation.
Returns only items directly related in this instance’s edges. To get all transitive successors, call
transitive_closure()first, then query the result.
- levels()[source]¶
Compute topological levels.
Level 0 items have no prerequisites. Level n items have max predecessor level n-1.
- to_matrix()[source]¶
Return (sorted items, adjacency matrix).
matrix[i][j] = 1 iff items[i] is a prerequisite of items[j].
- classmethod from_adjacency_matrix(items, matrix)[source]¶
Create from an adjacency matrix.
matrix[i][j] = 1 means items[i] is a prerequisite of items[j].
Knowledge structures, spaces, and learning spaces.
A knowledge structure on a domain Q is a family K of subsets of Q (called knowledge states) that contains at least the empty set and Q itself.
Special cases: - Knowledge space: closed under set union. - Closure space: closed under set intersection. - Learning space: a well-graded knowledge space (equivalently, an antimatroid).
- References:
Doignon, J.-P., & Falmagne, J.-C. (1999). Knowledge Spaces. Springer-Verlag.
Falmagne, J.-C., & Doignon, J.-P. (2011). Learning Spaces. Springer-Verlag.
- class knowledgespaces.structures.knowledge_structure.KnowledgeStructure(domain, states)[source]¶
A family of knowledge states over a domain of items.
- Parameters:
- domainCollection[str]
The set of all items.
- statesCollection[Collection[str]]
The knowledge states (subsets of domain). The empty set and the full domain are added automatically if missing.
- Parameters:
- property is_well_graded: bool¶
True if every non-empty state has an immediate predecessor.
A state K has an immediate predecessor if there exists q in K such that K {q} is also a state.
Note
This checks a local condition (every state has at least one single-item predecessor), not the full well-gradedness definition which requires a tight path between every pair of comparable states (Falmagne & Doignon, 2011, Def. 1.44). For knowledge spaces (union-closed families) the two conditions are equivalent (Theorem 1.49, ibid.), so
is_learning_space(which combinesis_knowledge_space and is_well_graded) is correct. On a bareKnowledgeStructurethat is not union-closed, this property may returnTrueeven when full well-gradedness does not hold.
- property is_accessible: bool¶
True if every state is reachable from the empty set.
Reachability means there exists a chain from ∅ to the state where each step adds exactly one item.
- property is_learning_space: bool¶
True if this is a well-graded knowledge space.
Equivalent to: knowledge space + well-graded. Equivalent to: no hanging states + ∅ and Q present.
- inner_fringe(state)[source]¶
Items whose removal yields another valid state.
These represent the ‘most recently consolidated’ items in the state.
- outer_fringe(state)[source]¶
Items whose addition yields another valid state.
These represent the ‘next learnable’ items from this state.
- hanging_states()[source]¶
Non-empty states with empty inner fringe.
A hanging state cannot be reached incrementally — it indicates a structural problem in the learning space.
- atoms()[source]¶
Atoms of the knowledge structure.
An atom at item q is a minimal state containing q — i.e. a state K such that q ∈ K and no proper subset of K that is also a state contains q. An item can have more than one atom.
In a closure space (closed under intersection) each item has exactly one atom (the intersection of all states containing it). In a knowledge space (closed under union) the collection of all atoms equals the base.
- Returns:
- dict[str, list[frozenset[str]]]
Mapping from each item to the list of its atoms (minimal states containing that item), sorted by size then content.
- Return type:
References
Doignon & Falmagne (1999), Knowledge Spaces, Def. 1.23. Falmagne & Doignon (2011), Learning Spaces, Chapter 1.
- base()[source]¶
Minimal generating family under union.
The base B of a knowledge space K is the smallest family such that K equals the closure of B under union (plus ∅). A state K is in the base iff it cannot be expressed as the union of states in K that are strictly contained in K.
Only meaningful for knowledge spaces (closed under union).
- learning_paths(target=None, max_paths=100)[source]¶
Find learning paths from ∅ to target.
A learning path is a maximal chain where each step adds one item.
- classmethod from_surmise_relation(relation)[source]¶
Build the ordinal knowledge structure from a surmise relation.
A state is valid iff for every item in the state, all its prerequisites are also in the state (downward closure).
The resulting structure is always closed under both union and intersection (it is a distributive lattice).
- Parameters:
relation (SurmiseRelation)
- Return type:
- classmethod from_states(states)[source]¶
Build from an explicit collection of states.
The domain is inferred as the union of all states.
- Parameters:
states (Collection[Collection[str]])
- Return type:
- intersection_with(other)[source]¶
Intersection of two structures: states present in both.
- Parameters:
other (KnowledgeStructure)
- Return type:
- projection(sub_domain)[source]¶
Project (restrict) the structure to a subset of items.
For each state K, the projected state is K ∩ sub_domain. Only items present in the original domain are retained.
- Raises:
- ValueError
If sub_domain contains items not in the original domain.
- Parameters:
sub_domain (Collection[str])
- Return type:
knowledgespaces.query¶
Core types for the QUERY algorithm.
Defines the Query object and the result containers used across all blocks of the algorithm.
- class knowledgespaces.query.types.InferenceSource(*values)[source]¶
How a query answer was determined.
- class knowledgespaces.query.types.Query(antecedent, consequent)[source]¶
A single query: ‘Does failing all items in A imply failing q?’
For pair queries (Block 1): antecedent has 1 item. For group queries (Block 2+): antecedent has 2+ items. For Qmax minimality test: antecedent = Q without {q}.
- Parameters:
- antecedentfrozenset[str]
The set A of items.
- consequentstr
The target item q.
- Parameters:
- class knowledgespaces.query.types.QueryAnswer(query, answer, source)[source]¶
A resolved query with its answer and source.
- Parameters:
query (Query)
answer (bool)
source (InferenceSource)
Expert protocols for the QUERY algorithm.
An expert is any callable that answers prerequisite queries. This module defines the protocol and provides built-in implementations for testing and interactive use.
- References:
Koppen, M., & Doignon, J.-P. (1990). How to build a knowledge space by querying an expert. Journal of Mathematical Psychology, 34, 311-331.
- class knowledgespaces.query.expert.Expert(*args, **kwargs)[source]¶
Protocol for expert query functions.
An expert receives a Query and returns True (positive) or False (negative).
The semantic of a positive answer to Query(A, q) is: ‘If a student fails all items in A, they will also fail q.’ Equivalently: mastering q requires mastering at least one item in A.
- class knowledgespaces.query.expert.PresetExpert(answers=None, default=False)[source]¶
Expert with predetermined answers, for testing and replay.
- Parameters:
- answersdict[tuple[frozenset[str], str], bool]
Mapping from (antecedent, consequent) to answer.
- defaultbool
Answer for queries not in the mapping.
- Parameters:
- classmethod from_relation(relations)[source]¶
Create an expert that answers based on a known surmise relation.
A pair query (a -> q) is positive iff (a, q) is in the relation. A group query (A -> q) is positive iff some a in A has (a, q).
This simulates an expert who knows the true prerequisite structure. Suitable for testing the query algorithm against a known ground truth.
- Parameters:
relations (Collection[tuple[str, str]])
- Return type:
- class knowledgespaces.query.expert.CallbackExpert(fn)[source]¶
Expert that delegates to a user-supplied function.
Block 1 of the QUERY algorithm: surmise relation discovery.
Extracts prerequisite relations between items by querying an expert with pair queries (a -> q) and optional Qmax minimality tests.
Implementation note — multi-phase optimization.
The standard QUERY Block 1 (Koppen & Doignon, 1990; Learning Spaces, Falmagne & Doignon, 2011, Ch. 4) iterates over all item pairs and uses transitivity + antisymmetry to prune redundant queries.
This implementation splits Block 1 into four phases as an optimization that maximises early inference opportunities:
Phase 0 (optional): Qmax test — group query Q{q} → q for each item, identifies globally minimal items that need no pair queries.
Phase 1: Forward pass — pair queries with transitivity/antisymmetry pruning, processing items in input order.
Phase 2: Bottom-up pass — re-explores from minimal items outward, exploiting newly discovered transitivity.
Phase 3: Final verification sweep — covers any pair not yet resolved by Phases 1–2, guaranteeing completeness.
The result is identical to the standard single-pass algorithm: the same surmise relation is discovered, but typically with fewer expert queries thanks to the ordering strategy. Completeness is guaranteed by Phase 3.
- References:
Koppen, M., & Doignon, J.-P. (1990). How to build a knowledge space by querying an expert. Journal of Mathematical Psychology, 34, 311-331.
Falmagne, J.-C., & Doignon, J.-P. (2011). Learning Spaces, Chapter 4. Springer-Verlag.
- class knowledgespaces.query.block1.Block1Stats(pair_queries=0, group_queries=0, deduced_by_transitivity=0, skipped_by_antisymmetry=0)[source]¶
Statistics from Block 1 execution.
- class knowledgespaces.query.block1.Block1Result(relation, closure, minimal_global, minimal_local, stats, log=<factory>)[source]¶
Result of Block 1 query phase.
- Parameters:
relation (SurmiseRelation)
closure (SurmiseRelation)
stats (Block1Stats)
log (list[QueryAnswer])
- knowledgespaces.query.block1.run_block1(items, expert, *, use_qmax=True)[source]¶
Execute Block 1 of the QUERY algorithm.
- Parameters:
- itemslist[str]
The domain of items.
- expertExpert
The expert to query.
- use_qmaxbool
If True, run Phase 0 (Qmax minimality test). Default True.
- Returns:
- Block1Result
Discovered surmise relation, closure, minimal items, and stats.
- Parameters:
- Return type:
Block 2+ of the QUERY algorithm: learning space refinement.
Refines an ordinal space (from Block 1) into a learning space by querying group prerequisites. Block N tests antecedent sets of size N.
Block 2 handles antecedent size 2, Block 3 size 3, etc. The algorithm is identical at every level — only the antecedent cardinality changes.
Three inference mechanisms reduce expert queries:
Negative monotonicity: if q is globally minimal (Qmax), then (A,q)=NO.
Positive monotonicity: if any subset of A already implies q, then (A,q)=YES.
Structural test (Theorem 43): if answering YES would create hanging states, then the answer must be NO.
- References:
Doignon, J.-P., & Falmagne, J.-C. (1999). Knowledge Spaces, Chapter 4. Springer-Verlag.
- class knowledgespaces.query.block2.BlockNStats(expert_queries=0, inferred_negative_monotonicity=0, inferred_positive_monotonicity=0, inferred_structural=0)[source]¶
Statistics from a Block N execution.
- class knowledgespaces.query.block2.BlockNResult(structure, positive, negative, stats, log=<factory>)[source]¶
Result of a Block N query phase.
- Parameters:
structure (KnowledgeStructure)
stats (BlockNStats)
log (list[QueryAnswer])
- knowledgespaces.query.block2.run_block_n(items, structure, prior_positive, expert, *, antecedent_size=2, minimal_global=frozenset({}))[source]¶
Execute Block N of the QUERY algorithm.
- Parameters:
- itemslist[str]
The domain of items.
- structureKnowledgeStructure
The current knowledge structure to refine.
- prior_positiveset[tuple[frozenset[str], str]]
Positive relations from all previous blocks. Each entry is (antecedent_set, consequent). Single-item antecedents come from Block 1’s closure: {(frozenset({a}), b) for (a,b) in closure}.
- expertExpert
The expert to query.
- antecedent_sizeint
Size of antecedent sets to test. Default 2 (standard Block 2).
- minimal_globalfrozenset[str]
Items certified globally minimal by Qmax in Block 1.
- Returns:
- BlockNResult
Refined structure, discovered relations, and stats.
- Parameters:
- Return type:
Full QUERY pipeline: Block 1 → L1 → Block 2 → … → Block N.
Orchestrates the complete derivation of a learning space from expert queries.
- class knowledgespaces.query.pipeline.QueryPipelineResult(structure, block1, block_n_results=<factory>)[source]¶
Result of the full QUERY pipeline.
- Parameters:
structure (KnowledgeStructure)
block1 (Block1Result)
block_n_results (list[BlockNResult])
- knowledgespaces.query.pipeline.run_query(items, expert, *, use_qmax=True, max_antecedent_size=2)[source]¶
Run the full QUERY algorithm.
- Parameters:
- itemslist[str]
The domain of items.
- expertExpert
The expert to query.
- use_qmaxbool
If True, use Qmax minimality test in Block 1.
- max_antecedent_sizeint
Maximum antecedent size for group queries. Default 2 (Block 2 only). Set to 3 for Block 3, etc.
- Returns:
- QueryPipelineResult
The derived learning space with full traceability.
- Parameters:
- Return type:
knowledgespaces.derivation¶
Skill maps: the mapping from items to required skills.
A skill map μ assigns to each item q the set of skills μ(q) needed to solve it. The problem function p(C) = {q ∈ Q | μ(q) ⊆ C} maps a competence state to the set of solvable items.
- References:
Doignon, J.-P., & Falmagne, J.-C. (1999). Knowledge Spaces, Chapter 7. Springer-Verlag.
- class knowledgespaces.derivation.skill_map.SkillMap(items, skills, mapping)[source]¶
Mapping from items to the skills required to solve them.
- Parameters:
- itemsCollection[str]
The domain of items.
- skillsCollection[str]
The set of all skills.
- mappingMapping[str, Collection[str]]
For each item, the skills required to solve it: μ(q).
- Raises:
- ValueError
If an item references a skill not in the skills set, or if mapping keys don’t match items.
- Parameters:
- problem_function(competence)[source]¶
Compute p(C) = {q ∈ Q | μ(q) ⊆ C}.
An item is solvable iff ALL its required skills are present in the competence state.
- to_matrix()[source]¶
Return (items, skills, binary matrix).
matrix[i][j] = 1 iff skill skills[j] is required by items[i].
Competence-Based Knowledge Space Theory (CB-KST) derivation.
Given a skill map μ (items → skills) and a surmise relation on skills, derives the knowledge structure on items through the problem function.
The pipeline: 1. Build competence structure C from skill prerequisites. 2. Apply problem function p(C) to each competence state. 3. Collect unique knowledge states → knowledge structure K.
Additionally provides conversion from skill prerequisites to item prerequisites (surmise relation on items).
- References:
Doignon, J.-P., & Falmagne, J.-C. (1999). Knowledge Spaces, Chapter 7. Springer-Verlag.
- class knowledgespaces.derivation.cbkst.CBKSTResult(competence_structure, knowledge_structure, mapping, skill_map, skill_relation)[source]¶
Result of a CB-KST derivation.
- Parameters:
competence_structure (KnowledgeStructure)
knowledge_structure (KnowledgeStructure)
skill_map (SkillMap)
skill_relation (SurmiseRelation)
- knowledgespaces.derivation.cbkst.derive_knowledge_structure(skill_map, skill_relation)[source]¶
Derive a knowledge structure from a competence model.
- Parameters:
- skill_mapSkillMap
The mapping μ: items → required skills.
- skill_relationSurmiseRelation
Prerequisite relation on skills (will be transitively closed). Must cover all skills referenced by the skill map.
- Returns:
- CBKSTResult
Contains the competence structure C, knowledge structure K, and the mapping from competence states to knowledge states.
- Raises:
- ValueError
If skill_map references skills not in skill_relation’s domain.
- Parameters:
skill_map (SkillMap)
skill_relation (SurmiseRelation)
- Return type:
- knowledgespaces.derivation.cbkst.skill_to_item_relation(skill_map, skill_relation)[source]¶
Derive an item surmise relation from skills.
Item p is a prerequisite of item q iff every skill required by p is “covered” by q — meaning the skill is either directly required by q or is a prerequisite of a skill required by q.
- Formally:
covers(q) = μ(q) ∪ {s : ∃t ∈ μ(q), (s,t) ∈ closure} p ≺ q iff μ(p) ⊆ covers(q)
Note: the result is already transitively closed.
- Parameters:
- skill_mapSkillMap
The mapping μ: items → required skills.
- skill_relationSurmiseRelation
Prerequisite relation on skills.
- Returns:
- SurmiseRelation
Surmise relation on items.
- Raises:
- ValueError
If skill_map references skills not in skill_relation’s domain.
- Parameters:
skill_map (SkillMap)
skill_relation (SurmiseRelation)
- Return type:
knowledgespaces.assessment¶
Basic Local Independence Model (BLIM) and Bayesian state inference.
The BLIM defines the probability of a response pattern given a knowledge state, using two parameters: - beta (slip): P(incorrect | item mastered) - eta (guess): P(correct | item not mastered)
The model assumes local independence: responses to different items are conditionally independent given the knowledge state.
StatePosterior maintains the Bayesian probability distribution over knowledge states and supports sequential updating.
- References:
Doignon, J.-P., & Falmagne, J.-C. (1999). Knowledge Spaces, Chapter 12. Springer-Verlag.
Falmagne, J.-C., & Doignon, J.-P. (2011). Learning Spaces, Chapter 12. Springer-Verlag.
- class knowledgespaces.assessment.blim.BLIMParams(beta, eta)[source]¶
Parameters for the Basic Local Independence Model.
- Parameters:
- betafloat or dict[str, float]
Slip probability: P(incorrect response | item mastered). A scalar applies the same value to every item; a dict maps each item to its own slip probability. Values must be in [0, 1).
- etafloat or dict[str, float]
Guess probability: P(correct response | item not mastered). A scalar applies the same value to every item; a dict maps each item to its own guess probability. Values must be in [0, 1).
- The constraint beta + eta < 1 (per item, when dicts are used)
- ensures model identifiability: a mastered item must be more likely
- to get a correct response than an unmastered one.
- Parameters:
- class knowledgespaces.assessment.blim.BLIM(structure, params)[source]¶
Basic Local Independence Model on a knowledge structure.
- Parameters:
- structureKnowledgeStructure
The knowledge structure defining valid states.
- paramsBLIMParams
Slip and guess parameters (scalar or per-item dict).
- Parameters:
structure (KnowledgeStructure)
params (BLIMParams)
- likelihood(item, response, state)[source]¶
Compute P(response | state) for a single item and state.
- Parameters:
- itemstr
The item being assessed.
- responsebool
True for correct, False for incorrect.
- statefrozenset[str]
The knowledge state. Must be a state in the structure.
- Raises:
- ValueError
If item is not in the domain or state is not in the structure.
- Parameters:
- Return type:
- class knowledgespaces.assessment.blim.StatePosterior(blim, probabilities)[source]¶
Bayesian probability distribution over knowledge states.
Immutable: update() returns a new StatePosterior.
- Parameters:
- blimBLIM
The BLIM model defining states and likelihoods.
- probabilitiesnp.ndarray
Probability for each state. Must sum to 1.
- Parameters:
blim (BLIM)
probabilities (np.ndarray)
- classmethod uniform(blim)[source]¶
Create a uniform prior (maximum uncertainty).
- Parameters:
blim (BLIM)
- Return type:
- classmethod from_prior(blim, prior)[source]¶
Create from an explicit prior mapping states to probabilities.
- update(item, response)[source]¶
Return a new posterior after observing a response.
- Applies Bayes’ theorem:
P(state | response) ∝ P(response | state) × P(state)
- Parameters:
- itemstr
The item that was assessed. Must be in the structure’s domain.
- responsebool
True for correct, False for incorrect.
- Raises:
- ValueError
If item is not in the domain, or if the observation has zero probability under all states with nonzero prior (impossible evidence).
- Parameters:
- Return type:
- knowledgespaces.assessment.blim.shannon_entropy(probs)[source]¶
Shannon entropy in bits, handling zero probabilities.
Adaptive assessment: item selection policies and termination criteria.
Provides the Expected Information Gain (EIG) policy for selecting the most informative item at each step of an adaptive assessment.
- References:
Cover, T. M., & Thomas, J. A. (2006). Elements of Information Theory, 2nd ed. Wiley.
- class knowledgespaces.assessment.adaptive.ItemScore(item, score)[source]¶
Score of an item under a selection policy.
- knowledgespaces.assessment.adaptive.select_item_eig(posterior, candidates=None, exclude=None)[source]¶
Select the item maximizing Expected Information Gain.
EIG(q) = H(current) - E[H(posterior after observing q)]
where the expectation is over both possible responses (correct/incorrect), weighted by their marginal probability.
- Parameters:
- posteriorStatePosterior
Current state distribution.
- candidateslist[str] or None
Items to consider. If None, uses all items in the domain.
- excludeset[str] or None
Items to exclude (e.g. already asked). Applied after candidates.
- Returns:
- ItemScore
The best item and its EIG score.
- Raises:
- ValueError
If no candidates are available, or if candidates contains items not in the domain.
- Parameters:
posterior (StatePosterior)
- Return type:
- knowledgespaces.assessment.adaptive.is_converged(posterior, threshold=0.85)[source]¶
Check if the assessment has converged.
Convergence occurs when the most likely state has probability above the threshold.
- Parameters:
- posteriorStatePosterior
Current state distribution.
- thresholdfloat
Probability threshold for convergence. Must be in (0, 1]. Default 0.85.
- Raises:
- ValueError
If threshold is not in (0, 1].
- Parameters:
posterior (StatePosterior)
threshold (float)
- Return type:
Instance pool: multiple questions per item.
In KST assessment, each item (competency) can be tested through multiple instances (concrete questions). The adaptive engine selects the best instance, maps it to its parent item for the BLIM update, and excludes only that specific instance from future selection.
This module provides the InstancePool data structure and an instance-aware version of select_item_eig.
- class knowledgespaces.assessment.instances.Instance(id, item)[source]¶
A concrete question that tests a specific item.
- class knowledgespaces.assessment.instances.InstancePool(instances)[source]¶
A collection of instances mapped to items.
- Parameters:
- instanceslist[Instance]
All available instances.
- Raises:
- ValueError
If instance IDs are not unique, or if an instance references an item not in the provided domain.
- Parameters:
- class knowledgespaces.assessment.instances.InstanceScore(instance_id, item, score)[source]¶
Score of an instance under the EIG policy.
- knowledgespaces.assessment.instances.select_instance_eig(posterior, pool, asked=None)[source]¶
Select the instance maximizing Expected Information Gain.
This is the instance-aware version of select_item_eig. It computes EIG per item, picks the item with highest EIG, then selects a random un-asked instance of that item (since instances of the same item are equivalent from the BLIM perspective).
- Parameters:
- posteriorStatePosterior
Current state distribution.
- poolInstancePool
Available instances.
- askedset[str] or None
Instance IDs already asked (excluded from selection).
- Returns:
- InstanceScore
The best instance, its parent item, and EIG score.
- Raises:
- ValueError
If no un-asked instances remain, or if pool items don’t match the structure’s domain.
- Parameters:
posterior (StatePosterior)
pool (InstancePool)
- Return type:
knowledgespaces.estimation¶
EM algorithm for BLIM parameter estimation.
Estimates slip (β) and guess (η) parameters from observed response patterns using Expectation-Maximization. Supports both global (homogeneous) and per-item (heterogeneous) parameterization.
The algorithm iterates between: - E-step: compute posterior P(state | response pattern) for each pattern. - M-step: re-estimate β, η, and state prior π from sufficient statistics.
- References:
Doignon, J.-P., & Falmagne, J.-C. (1999). Knowledge Spaces, Chapter 12. Springer-Verlag.
Heller, J., & Wickelmaier, F. (2013). Minimum discrepancy estimation in probabilistic knowledge structures. Electronic Notes in Discrete Mathematics, 42, 49-56.
- class knowledgespaces.estimation.blim_em.ResponseMatrix(items, patterns, counts=None)[source]¶
Observed response patterns from a group of respondents.
- Parameters:
- itemslist[str]
Item labels (columns), must match the structure’s domain.
- patternsnp.ndarray
Binary matrix of shape (n_respondents, n_items). patterns[r, q] = 1 if respondent r answered item q correctly.
- countsnp.ndarray or None
Optional frequency for each unique pattern. If None, each row in patterns is one respondent (count=1 each).
- Parameters:
- class knowledgespaces.estimation.blim_em.GoodnessOfFit(G2, df, p_value, npar, AIC, BIC, BIC_N)[source]¶
Goodness-of-fit statistics for a BLIM estimate.
Follows the approach of Heller & Wickelmaier (2013) and the R
pkspackage (Heller & Wickelmaier, 2013, J. Stat. Softw.). The primary statistic is the likelihood ratio G2 (deviance), tested against a chi-squared distribution.- Attributes:
- G2float
Likelihood ratio statistic: 2 * sum_r N_r ln(N_r / E_r).
- dfint
Degrees of freedom:
max(min(2^Q - 1, N) - npar, 0). Themin(2^Q - 1, N)cap follows thepksconvention: when the total sample size N is smaller than the number of possible response patterns (2^Q), the saturated model cannot be fully identified, so N replaces 2^Q - 1.- p_valuefloat
P-value from chi-squared test on G2.
- nparint
Number of free parameters:
|K| - 1 + 2 * Q.- AICfloat
Akaike Information Criterion:
-2*LL + 2*npar.- BICfloat
Bayesian Information Criterion using the number of unique response patterns:
-2*LL + ln(n_patterns)*npar. This follows thepksconvention (Heller & Wickelmaier, 2013). SeeBIC_Nfor the standard textbook variant.- BIC_Nfloat
Bayesian Information Criterion using the total sample size:
-2*LL + ln(N)*npar. This is the standard BIC definition (Schwarz, 1978).
- Parameters:
- class knowledgespaces.estimation.blim_em.BLIMEstimate(beta, eta, pi, log_likelihood, n_iterations, converged, items, states, gof)[source]¶
Result of BLIM parameter estimation via EM.
- Attributes:
- betanp.ndarray
Slip parameters, shape (n_items,). beta[q] = P(incorrect | q mastered).
- etanp.ndarray
Guess parameters, shape (n_items,). eta[q] = P(correct | q not mastered).
- pinp.ndarray
State prior probabilities, shape (n_states,).
- log_likelihoodfloat
Final log-likelihood of the data.
- n_iterationsint
Number of EM iterations until convergence.
- convergedbool
True if converged within max_iter.
- itemslist[str]
Item labels corresponding to beta/eta indices.
- stateslist[frozenset[str]]
Knowledge states corresponding to pi indices (same order).
- gofGoodnessOfFit
Goodness-of-fit statistics (G2, df, p-value, AIC, BIC).
- Parameters:
- knowledgespaces.estimation.blim_em.estimate_blim(structure, data, *, max_iter=500, tol=1e-06, beta_init=0.1, eta_init=0.1)[source]¶
Estimate BLIM parameters via Expectation-Maximization.
- Parameters:
- structureKnowledgeStructure
The knowledge structure defining valid states.
- dataResponseMatrix
Observed response patterns.
- max_iterint
Maximum number of EM iterations. Default 500.
- tolfloat
Convergence tolerance on log-likelihood change. Default 1e-6.
- beta_initfloat or np.ndarray
Initial slip values. Scalar for homogeneous, array for per-item.
- eta_initfloat or np.ndarray
Initial guess values. Scalar for homogeneous, array for per-item.
- Returns:
- BLIMEstimate
Estimated parameters, log-likelihood, and convergence info.
- Raises:
- ValueError
If data items don’t match structure domain, or if init parameters are out of range.
- Parameters:
structure (KnowledgeStructure)
data (ResponseMatrix)
max_iter (int)
tol (float)
- Return type:
- knowledgespaces.estimation.blim_em.estimate_blim_restarts(structure, data, *, n_restarts=10, max_iter=500, tol=1e-06, seed=None)[source]¶
Estimate BLIM parameters with multiple random restarts.
Runs
estimate_blim()n_restartstimes with random initial values for beta, eta, and selects the result with the highest log-likelihood. This helps avoid local optima.The R
pkspackage does not provide this natively — users must loop manually withrandinit=TRUE.- Parameters:
- structureKnowledgeStructure
The knowledge structure defining valid states.
- dataResponseMatrix
Observed response patterns.
- n_restartsint
Number of random restarts. Default 10.
- max_iterint
Maximum EM iterations per restart.
- tolfloat
Convergence tolerance per restart.
- seedint or None
Random seed for reproducibility.
- Returns:
- BLIMEstimate
The best result (highest log-likelihood) across all restarts.
- Parameters:
structure (KnowledgeStructure)
data (ResponseMatrix)
n_restarts (int)
max_iter (int)
tol (float)
seed (int | None)
- Return type:
knowledgespaces.io¶
CSV import/export for KST objects.
Supports three standard CSV formats: - Skill map matrix: rows=items, cols=skills, binary (μ: items→skills). - Prerequisite matrix: rows=labels, cols=labels, binary (surmise relation). - Knowledge structure: state_size, state_id, then binary columns per item.
All CSV files use the first column as row index and the first row as header.
- knowledgespaces.io.csv.read_skill_map(path)[source]¶
Read a skill map from CSV.
Expected format:
,skill1,skill2,... item1,0,1,... item2,1,0,...
- knowledgespaces.io.csv.read_relation(path)[source]¶
Read a surmise relation from a CSV prerequisite matrix.
Expected format:
,label1,label2,... label1,0,1,... label2,0,0,...
Row labels must match column labels exactly.
- Raises:
- ValueError
If rows have wrong column count, non-binary values, or row labels don’t match header labels.
- Parameters:
- Return type:
- knowledgespaces.io.csv.write_relation(relation, path)[source]¶
Write a surmise relation to a CSV prerequisite matrix.
- Parameters:
relation (SurmiseRelation)
- Return type:
None
- knowledgespaces.io.csv.read_structure(path)[source]¶
Read a knowledge structure from CSV.
Expected format:
state_size,state_id,item1,item2,... 0,0,0,0,... 1,1,1,0,...
- Raises:
- ValueError
If rows have wrong column count or non-binary item values.
- Parameters:
- Return type:
- knowledgespaces.io.csv.write_structure(structure, path)[source]¶
Write a knowledge structure to CSV.
- Parameters:
structure (KnowledgeStructure)
- Return type:
None
JSON serialization for KST objects.
Provides roundtrip-safe serialization for the core KST types: KnowledgeStructure, SurmiseRelation, and SkillMap.
- knowledgespaces.io.json.structure_to_dict(structure)[source]¶
Serialize a KnowledgeStructure to a JSON-compatible dict.
- Parameters:
structure (KnowledgeStructure)
- Return type:
- knowledgespaces.io.json.dict_to_structure(data)[source]¶
Deserialize a KnowledgeStructure from a dict.
- Raises:
- ValueError
If required keys are missing or have wrong types.
- Parameters:
- Return type:
- knowledgespaces.io.json.write_structure_json(structure, path)[source]¶
Write a KnowledgeStructure to a JSON file.
- Parameters:
structure (KnowledgeStructure)
- Return type:
None
- knowledgespaces.io.json.read_structure_json(path)[source]¶
Read a KnowledgeStructure from a JSON file.
- Parameters:
- Return type:
- knowledgespaces.io.json.relation_to_dict(relation)[source]¶
Serialize a SurmiseRelation to a JSON-compatible dict.
- Parameters:
relation (SurmiseRelation)
- Return type:
- knowledgespaces.io.json.dict_to_relation(data)[source]¶
Deserialize a SurmiseRelation from a dict.
- Raises:
- ValueError
If required keys are missing or have wrong types.
- Parameters:
- Return type:
- knowledgespaces.io.json.write_relation_json(relation, path)[source]¶
Write a SurmiseRelation to a JSON file.
- Parameters:
relation (SurmiseRelation)
- Return type:
None
- knowledgespaces.io.json.read_relation_json(path)[source]¶
Read a SurmiseRelation from a JSON file.
- Parameters:
- Return type:
- knowledgespaces.io.json.skill_map_to_dict(skill_map)[source]¶
Serialize a SkillMap to a JSON-compatible dict.
knowledgespaces.metrics¶
Distance measures between knowledge structures.
Provides formal metrics for comparing two knowledge structures: - Symmetric difference distance - Hausdorff distance (on states) - Directional Hamming distances (H→A and A→H) - Graph Edit Distance on prerequisite relations
All functions require matching domains.
- knowledgespaces.metrics.distances.symmetric_difference(ks1, ks2)[source]¶
Number of states in exactly one of the two structures.
Card(K1 △ K2) = Card(K1 K2) + Card(K2 K1)
- Raises:
- ValueError
If structures have different domains.
- Parameters:
ks1 (KnowledgeStructure)
ks2 (KnowledgeStructure)
- Return type:
- knowledgespaces.metrics.distances.hausdorff(ks1, ks2)[source]¶
Hausdorff distance between two structures.
- max(max over K in K1 of min over L in K2 of d(K,L),
max over L in K2 of min over K in K1 of d(K,L))
where d is the Hamming distance between states. Returns 0 if the structures are identical.
- Raises:
- ValueError
If structures have different domains.
- Parameters:
ks1 (KnowledgeStructure)
ks2 (KnowledgeStructure)
- Return type:
- class knowledgespaces.metrics.distances.DirectionalDistances(forward_mean, backward_mean, forward_max, backward_max)[source]¶
Directional Hamming distances between two structures.
- Attributes:
- forward_meanfloat
Mean min-distance from ks1 states to nearest ks2 state.
- backward_meanfloat
Mean min-distance from ks2 states to nearest ks1 state.
- forward_maxint
Max min-distance from ks1 to ks2.
- backward_maxint
Max min-distance from ks2 to ks1.
- Parameters:
- knowledgespaces.metrics.distances.directional_distances(ks1, ks2)[source]¶
Compute directional Hamming distances.
- Raises:
- ValueError
If structures have different domains.
- Parameters:
ks1 (KnowledgeStructure)
ks2 (KnowledgeStructure)
- Return type:
- knowledgespaces.metrics.distances.graph_edit_distance(rel1, rel2)[source]¶
Edge differences between two surmise relation graphs.
- Returns:
- addedint
Edges in rel2 but not in rel1.
- removedint
Edges in rel1 but not in rel2.
- totalint
added + removed.
- Raises:
- ValueError
If relations have different domains.
- Parameters:
rel1 (SurmiseRelation)
rel2 (SurmiseRelation)
- Return type:
Agreement measures between knowledge structures or relations.
Provides Cohen’s kappa and related indices for comparing prerequisite matrices or state memberships.
- knowledgespaces.metrics.agreement.cohens_kappa(rel1, rel2)[source]¶
Cohen’s kappa for agreement on prerequisite relations.
Compares two surmise relations on the same domain. For every ordered pair (a, b) with a ≠ b, counts agreement/disagreement on whether (a, b) is a prerequisite.
- Parameters:
- rel1, rel2SurmiseRelation
Must have the same item domain.
- Returns:
- float
Cohen’s kappa in [-1, 1]. 1 = perfect agreement, 0 = chance agreement, <0 = worse than chance.
- Raises:
- ValueError
If the relations have different domains.
- Parameters:
rel1 (SurmiseRelation)
rel2 (SurmiseRelation)
- Return type: