Querying Experts¶
The QUERY algorithm (Koppen & Doignon, 1990) derives a knowledge structure by asking an expert prerequisite questions.
How it works¶
The algorithm asks questions of the form:
If a student fails all items in set \(A\), will they also fail item \(q\)?
It proceeds in phases:
Block 1: Pair queries (\(|A| = 1\)) to discover the surmise relation.
Block 2+: Group queries (\(|A| \geq 2\)) to refine the structure into a learning space.
Three inference mechanisms reduce the number of questions:
Negative monotonicity: If \(q\) is minimal, no set implies \(q\).
Positive monotonicity: If a subset of \(A\) already implies \(q\), so does \(A\).
Structural test (Theorem 43): If answering YES would create a hanging state, the answer must be NO.
Basic usage¶
from knowledgespaces import run_query
from knowledgespaces.query import CallbackExpert
def my_expert(antecedent, consequent):
# Your logic: human input, LLM call, database lookup, etc.
known = {("add", "sub"), ("sub", "mul"), ("mul", "div")}
return any((a, consequent) in known for a in antecedent)
expert = CallbackExpert(my_expert)
result = run_query(["add", "sub", "mul", "div"], expert)
print(result.is_learning_space)
print(result.total_expert_queries)
Controlling the algorithm¶
# Without Qmax minimality test (fewer group queries, more pair queries)
result = run_query(items, expert, use_qmax=False)
# With Block 3 (group queries of size 3)
result = run_query(items, expert, max_antecedent_size=3)
Inspecting results¶
# The derived structure
for state in result.structure:
print(set(state))
# Block 1 details
print(result.block1.relation) # direct prerequisites found
print(result.block1.minimal_global) # items certified minimal by Qmax
print(result.block1.stats) # query counts
# Full query log
for entry in result.block1.log:
print(f"{entry.query} → {entry.answer} ({entry.source.name})")