CbKST—Functions for Competence-Based Knowledge Space Theory

Cord Hockemeyer

June 24, 2026

Table of contents

Introduction

Knowledge space theory (KST) was founded by Doignon and Falmagne (1985, 1999; see also Falmagne et al., 2013; Heller & Stefanutti, 2024a) as a means for efficient adaptive assessment of knowledge. Efficiency here means that the number of items tested should be relatively small. KST models prerequisite relationships between test items and infers from previous answers to the mastery of other items based on these prerquisites. However, it is a behavioral model, i.e. it does not look into the skills and competencies underlying the response behaviour.

Competence-based Knowledge Space Theory (CbKST; see, e.g., Doignon, 1994; Düntsch & Gediga, 1995; Korossy, 1997; Albert & Lukas, 1999; Heller et al., 2006, Heller et al., 2013, Heller & Stefanutti, 2024b) aims at mending this. Its core element are skill maps or skill multimaps assigning to each test items the skills and competencies required for solving it.

General remarks

Some general remarks on the competence extension to KST

In the context of knowledge space theory, the terms skill and competence are often used synonymously. When skill multimaps are used, however, there is a clear distinction: competences are the subsets of skills assigned to an item through the skill multimap. The competences are interpreted as alternative sets of prerequisites for solving the item, especially for different possible solujtion paths.

It should be noticed that, for two competence states \(C\) and \(C'\) and the corresponding performance states \(P\) and \(P'\), the performance state corresponding to \(C\cup C'\) is not necessarily \(P\cup P'\) but may be a (strict) superset of it. As a consequence, the performance structure corresponding to a competence space (cbkst_performancestructure(multimap, comp)) is not necessarily a performance space, i.e. closed under union. Also, if we map an arbitrary subset \(P\) of test items with cbkst_perf2comp() to the minimal competence states and map them back to the performance level with cbkst_comp2perf(), we may obtain a larger subset \(P'\supset P\); more concretely, we would obtain one or more performance states, actually the minimal ones containing \(P\).

Core data structure

While generally, CbKST focuses on skill maps with skill multimaps as an extension allowing for different solution paths for the test items, within the implementation of the CbKST package, the skill multimaps are the core element and basic object class. Skill maps are a mere special case (and thus a sub class) of skill multimaps. Practically, both classes are identical, i.e. data frames. These data frames contain item IDs in the first columns and a binary matrix in subsequent columns (one per skill) where a ‘1’ denotes the case that a skill is a prerequisite for the mastery of the respective test item (and ‘0’ otherwise). If a skill multimap data frame has exactly one row per test item, it describes a skill map.

File format

Skill (multi-) map files can be in ODS or XLSX spreadsheet format. Their table layout is basically the same as the data frame structure. A preceding header row contains the skill IDs in the columns 2 to \(n\). The first entry in the header row is not used by the functions in CbKST.

exampledata$mu
Item.ID a b c d
z 1 0 0 0
y 0 1 0 0
x 1 1 0 0
w 1 1 1 0
v 1 1 0 1

Functions in CbKST

Input/Output

We start CbKST activities with reading a skill (multi) map from file. This is done through read_skillmultimap(). For practical reasons, only spreadsheet format files are allowed, currently concretely ODS (Libreoffice/Openoffice) and XLSX (Microsoft Excel) format. CSV files (comma separated values) may follow at a later time.

The read_skillmultimap() function is deliberately kept simple, it takes a filename as only parameter. This includes certain assumptions, e.g. the existence of a header row in the file containing the skill names (see next section).

Example

fpath <- system.file("extdata", "skillmap.ods", package="CbKST")
sm <- read_skillmultimap(fpath)
sm
Item.ID a b c d
z 1 0 0 0
y 0 1 0 0
x 1 1 0 0
w 1 1 1 0
v 1 1 0 1
class(sm)
#> [1] "cbkst_skillmap"      "cbkst_skillmultimap" "data.frame"         
fpath <- system.file("extdata", "multimap.ods", package="CbKST")
mm <- read_skillmultimap(fpath)
mm
Item.ID a b c d
z 1 0 0 0
y 0 1 0 0
x 1 1 0 0
w 1 1 1 0
w 1 1 0 1
v 1 1 1 1
class(mm)
#> [1] "cbkst_skillmultimap" "data.frame"         

As can be seen in the code and results above, the result of read_skillmultimap() is of class cbkst_skillmultimap. If, however, we have the special case of a skill map, i.e. every item is assigned exactly one competence, the result belongs additionally also to class cbkst_skillmap.

Mapping states between skills and performances

There are three functions mapping states between skill/competence and performance level. cbkst_comp2per() determines the subset of items (performance state) solvable by a person in a given skill state. In the counter direction, cbkst_perf2comp() determines the minimal skill states (as binary matrix of class kmfamset) allowing for a specified performance state. This function can also regard an additionally specified skill structure further constraining the result. A simplified variant is cbkst_simple_perf2comp() which required a skill map (instead of a more general skill multimap) as parameter and does not allow for further constraints through a competence structure. Here, the result is again (like in cbkst_comp2perf()) a single state (as a vector).

Please note that for cbkst_perf2comp() and cbkst_simple_perf2comp(), the performance state must be specified as a named vector. The item IDs of the performance state must fit to the item IDs used in the skill (multi) map.

Example

cbkst_comp2perf(c(1,1,0,0), exampledata$mu)
#> z y x w v 
#> 1 1 1 0 0 
perf <- c(1,1,1,0,0)
names(perf) <- c("z", "y", "x", "w", "v")
cbkst_perf2comp(perf, exampledata$multi, exampledata$cspace)
1 1 0 0
cbkst_simple_perf2comp(perf, exampledata$mu)
#> [1] 1 1 0 0

Mapping structures between skills and performances

The functions cbkst_performaancestructure() and cbkst_competencestructure() map whole structures. cbkst_performancestructure() determines the family of all subset of test items which are a performance state for some competence state. cbkst_competencestructure() on the other hand provides all minimal competence states behind some performance state.

Example

cbkst_performancestructure(exampledata$mu)
z y x w v
0 0 0 0 0
1 0 0 0 0
0 1 0 0 0
1 1 1 0 0
1 1 1 1 0
1 1 1 0 1
1 1 1 1 1
cbkst_performancestructure(exampledata$mu, comp=exampledata$cspace)
z y x w v
0 0 0 0 0
1 0 0 0 0
1 1 1 0 0
1 1 1 1 0
1 1 1 1 1
cbkst_competencestructure(exampledata$multi)
a b c d
0 0 0 0
1 1 1 1
1 1 1 0
1 1 0 1
1 1 0 0
0 1 0 0
1 0 0 0
cbkst_competencestructure(exampledata$multi, perf=exampledata$pspace)
a b c d
0 0 0 0
1 0 0 0
1 1 0 0
1 1 1 0
1 1 0 1
1 1 1 1

Example data

The CbKST package provides some example data — mainly for testing and illustration. They can be accessed as elements of the list exampledata.

exampledata
#> $mu
#>   Item.ID a b c d
#> 1       z 1 0 0 0
#> 2       y 0 1 0 0
#> 3       x 1 1 0 0
#> 4       w 1 1 1 0
#> 5       v 1 1 0 1
#> 
#> $multi
#>   Item.ID a b c d
#> 1       z 1 0 0 0
#> 2       y 0 1 0 0
#> 3       x 1 1 0 0
#> 4       w 1 1 1 0
#> 5       w 1 1 0 1
#> 6       v 1 1 1 1
#> 
#> $cspace
#>      a b c d
#> [1,] 0 0 0 0
#> [2,] 1 0 0 0
#> [3,] 1 1 0 0
#> [4,] 1 1 1 0
#> [5,] 1 1 1 1
#> attr(,"class")
#> [1] "kmspace"     "kmstructure" "kmfamset"    "matrix"      "array"      
#> 
#> $pspace
#>      z y x w v
#> [1,] 0 0 0 0 0
#> [2,] 1 0 0 0 0
#> [3,] 1 1 0 0 0
#> [4,] 1 1 1 0 0
#> [5,] 1 1 1 1 0
#> [6,] 1 1 1 1 1
#> attr(,"class")
#> [1] "kmspace"     "kmstructure" "kmfamset"    "matrix"      "array"      
#> 

These data are in parallel also given as files in the package’s extdata directory. The file path can be built as shown below.

fpath <- system.file("extdata", "skillmap.ods", package="CbKST")

The following four files are provided:

References