adaptivetesting 1.0.0__tar.gz → 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- adaptivetesting-1.0.1/.github/workflows/publish.yml +39 -0
- adaptivetesting-1.0.1/.github/workflows/python-test.yml +63 -0
- adaptivetesting-1.0.1/.gitignore +170 -0
- adaptivetesting-1.0.1/.gitlab-ci.yml +13 -0
- adaptivetesting-1.0.1/.python-version +1 -0
- adaptivetesting-1.0.1/.vscode/extensions.json +8 -0
- adaptivetesting-1.0.1/.vscode/settings.json +14 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/PKG-INFO +9 -27
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/README.md +3 -3
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/data/__sqlite_context.py +0 -3
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/implementations/__default_implementation.py +0 -1
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/implementations/__pre_test.py +5 -5
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/implementations/__semi_implementation.py +0 -1
- adaptivetesting-1.0.1/adaptivetesting/math/__gen_response_pattern.py +35 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/math/__init__.py +1 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/math/__standard_error.py +9 -8
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/math/__test_information.py +7 -13
- adaptivetesting-1.0.1/adaptivetesting/math/estimators/__bayes_modal_estimation.py +45 -0
- adaptivetesting-1.0.1/adaptivetesting/math/estimators/__functions/__bayes.py +45 -0
- adaptivetesting-1.0.1/adaptivetesting/math/estimators/__functions/__estimators.py +133 -0
- adaptivetesting-1.0.1/adaptivetesting/math/estimators/__init__.py +5 -0
- adaptivetesting-1.0.1/adaptivetesting/math/estimators/__ml_estimation.py +39 -0
- adaptivetesting-1.0.1/adaptivetesting/math/estimators/__prior.py +47 -0
- adaptivetesting-1.0.1/adaptivetesting/math/item_selection/__init__.py +1 -0
- adaptivetesting-1.0.1/adaptivetesting/math/item_selection/__urrys_rule.py +33 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__adaptive_test.py +1 -2
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__algorithm_exception.py +0 -1
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__item_pool.py +9 -10
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__item_selection_exception.py +1 -1
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__test_item.py +1 -5
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/services/__estimator_interface.py +1 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_adaptive_test.py +1 -2
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_bayes_modal.py +5 -6
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_code_examples.py +2 -2
- adaptivetesting-1.0.1/adaptivetesting/tests/test_generate_response_pattern.py +59 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_information_test.py +2 -1
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_load_test_items.py +3 -3
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_mle.py +3 -3
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_pretest.py +1 -1
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_standard_error.py +1 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_urrys_rule.py +1 -1
- adaptivetesting-1.0.1/code_examples/example_default.py +76 -0
- adaptivetesting-1.0.1/code_examples/example_psychopy.py +116 -0
- adaptivetesting-1.0.1/code_examples/example_semi.py +77 -0
- adaptivetesting-1.0.1/data/default/0.pickle +0 -0
- adaptivetesting-1.0.1/data/semi/0.pickle +0 -0
- adaptivetesting-1.0.1/docs/data.md +69 -0
- adaptivetesting-1.0.1/docs/implementations.md +117 -0
- adaptivetesting-1.0.1/docs/index.md +32 -0
- adaptivetesting-1.0.1/docs/math.md +254 -0
- adaptivetesting-1.0.1/docs/models.md +248 -0
- adaptivetesting-1.0.1/docs/services.md +42 -0
- adaptivetesting-1.0.1/docs/simulation.md +53 -0
- adaptivetesting-1.0.1/docs/tests.md +4 -0
- adaptivetesting-1.0.1/docs_generation/Makefile +20 -0
- adaptivetesting-1.0.1/docs_generation/make.bat +35 -0
- adaptivetesting-1.0.1/docs_generation/source/_static/logo.svg +67 -0
- adaptivetesting-1.0.1/docs_generation/source/_static/main.css +24 -0
- adaptivetesting-1.0.1/docs_generation/source/conf.py +46 -0
- adaptivetesting-1.0.1/docs_generation/source/data.rst +19 -0
- adaptivetesting-1.0.1/docs_generation/source/implementations.rst +31 -0
- adaptivetesting-1.0.1/docs_generation/source/index.rst +37 -0
- adaptivetesting-1.0.1/docs_generation/source/math.rst +77 -0
- adaptivetesting-1.0.1/docs_generation/source/models.rst +46 -0
- adaptivetesting-1.0.1/docs_generation/source/services.rst +18 -0
- adaptivetesting-1.0.1/docs_generation/source/simulation.rst +29 -0
- adaptivetesting-1.0.1/docs_generation/source/tests.rst +5 -0
- adaptivetesting-1.0.1/images/default.svg +208 -0
- adaptivetesting-1.0.1/images/semi-adaptive.svg +254 -0
- adaptivetesting-1.0.1/mypy.ini +8 -0
- adaptivetesting-1.0.1/pyproject.toml +36 -0
- adaptivetesting-1.0.1/requirements.txt +552 -0
- adaptivetesting-1.0.1/setup.cfg +5 -0
- adaptivetesting-1.0.1/uv.lock +1016 -0
- adaptivetesting-1.0.0/adaptivetesting.egg-info/PKG-INFO +0 -108
- adaptivetesting-1.0.0/adaptivetesting.egg-info/SOURCES.txt +0 -41
- adaptivetesting-1.0.0/adaptivetesting.egg-info/dependency_links.txt +0 -1
- adaptivetesting-1.0.0/adaptivetesting.egg-info/requires.txt +0 -4
- adaptivetesting-1.0.0/adaptivetesting.egg-info/top_level.txt +0 -1
- adaptivetesting-1.0.0/setup.cfg +0 -4
- adaptivetesting-1.0.0/setup.py +0 -36
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/LICENSE +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/__init__.py +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/data/__init__.py +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/data/__pickle_context.py +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/implementations/__init__.py +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__init__.py +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__test_result.py +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/services/__init__.py +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/services/__test_results_interface.py +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/simulation/__init__.py +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/simulation/__simulation.py +0 -0
- {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/__init__.py +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# This workflow will upload a Python Package using Twine when a release is created
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
|
|
3
|
+
|
|
4
|
+
# This workflow uses actions that are not certified by GitHub.
|
|
5
|
+
# They are provided by a third-party and are governed by
|
|
6
|
+
# separate terms of service, privacy policy, and support
|
|
7
|
+
# documentation.
|
|
8
|
+
|
|
9
|
+
name: Upload Python Package
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
release:
|
|
13
|
+
types: [published]
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
deploy:
|
|
20
|
+
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v3
|
|
27
|
+
with:
|
|
28
|
+
python-version: '3.x'
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: |
|
|
31
|
+
python -m pip install --upgrade pip
|
|
32
|
+
pip install uv
|
|
33
|
+
- name: Build package
|
|
34
|
+
run: uv build
|
|
35
|
+
- name: Publish package
|
|
36
|
+
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
|
|
37
|
+
with:
|
|
38
|
+
user: __token__
|
|
39
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
|
|
3
|
+
|
|
4
|
+
name: Package test
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [ "main", "dev"]
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [ "main" ]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v3
|
|
23
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
24
|
+
uses: actions/setup-python@v3
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
python -m pip install uv
|
|
31
|
+
uv sync
|
|
32
|
+
- name: Linting
|
|
33
|
+
run: uv run python -m flake8
|
|
34
|
+
- name: Type checking
|
|
35
|
+
run: |
|
|
36
|
+
uv run mypy
|
|
37
|
+
- name: Type checking code examples
|
|
38
|
+
run: |
|
|
39
|
+
uv run mypy code_examples
|
|
40
|
+
- name: Test with unittest
|
|
41
|
+
run: |
|
|
42
|
+
uv run python -m unittest
|
|
43
|
+
build:
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
strategy:
|
|
46
|
+
fail-fast: false
|
|
47
|
+
matrix:
|
|
48
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
49
|
+
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v3
|
|
52
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
53
|
+
uses: actions/setup-python@v3
|
|
54
|
+
with:
|
|
55
|
+
python-version: ${{ matrix.python-version }}
|
|
56
|
+
- name: Install dependencies
|
|
57
|
+
run: |
|
|
58
|
+
python -m pip install --upgrade pip
|
|
59
|
+
python -m pip install uv
|
|
60
|
+
uv sync
|
|
61
|
+
- name: Build package
|
|
62
|
+
run: |
|
|
63
|
+
uv build
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# unignore built documentation
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Distribution / packaging
|
|
13
|
+
.Python
|
|
14
|
+
build/
|
|
15
|
+
develop-eggs/
|
|
16
|
+
dist/
|
|
17
|
+
downloads/
|
|
18
|
+
eggs/
|
|
19
|
+
.eggs/
|
|
20
|
+
lib/
|
|
21
|
+
lib64/
|
|
22
|
+
parts/
|
|
23
|
+
sdist/
|
|
24
|
+
var/
|
|
25
|
+
wheels/
|
|
26
|
+
share/python-wheels/
|
|
27
|
+
*.egg-info/
|
|
28
|
+
.installed.cfg
|
|
29
|
+
*.egg
|
|
30
|
+
MANIFEST
|
|
31
|
+
|
|
32
|
+
# PyInstaller
|
|
33
|
+
# Usually these files are written by a python script from a template
|
|
34
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
35
|
+
*.manifest
|
|
36
|
+
*.spec
|
|
37
|
+
|
|
38
|
+
# Installer logs
|
|
39
|
+
pip-log.txt
|
|
40
|
+
pip-delete-this-directory.txt
|
|
41
|
+
|
|
42
|
+
# Unit test / coverage reports
|
|
43
|
+
htmlcov/
|
|
44
|
+
.tox/
|
|
45
|
+
.nox/
|
|
46
|
+
.coverage
|
|
47
|
+
.coverage.*
|
|
48
|
+
.cache
|
|
49
|
+
nosetests.xml
|
|
50
|
+
coverage.xml
|
|
51
|
+
*.cover
|
|
52
|
+
*.py,cover
|
|
53
|
+
.hypothesis/
|
|
54
|
+
.pytest_cache/
|
|
55
|
+
cover/
|
|
56
|
+
|
|
57
|
+
# Translations
|
|
58
|
+
*.mo
|
|
59
|
+
*.pot
|
|
60
|
+
|
|
61
|
+
# Django stuff:
|
|
62
|
+
*.log
|
|
63
|
+
local_settings.py
|
|
64
|
+
db.sqlite3
|
|
65
|
+
db.sqlite3-journal
|
|
66
|
+
|
|
67
|
+
# Flask stuff:
|
|
68
|
+
instance/
|
|
69
|
+
.webassets-cache
|
|
70
|
+
|
|
71
|
+
# Scrapy stuff:
|
|
72
|
+
.scrapy
|
|
73
|
+
|
|
74
|
+
# Sphinx documentation
|
|
75
|
+
!docs_generation/build/markdown/
|
|
76
|
+
!docs_generation/build/markdown/*
|
|
77
|
+
docs_generation/build/*
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# PyBuilder
|
|
81
|
+
.pybuilder/
|
|
82
|
+
target/
|
|
83
|
+
|
|
84
|
+
# Jupyter Notebook
|
|
85
|
+
.ipynb_checkpoints
|
|
86
|
+
|
|
87
|
+
# IPython
|
|
88
|
+
profile_default/
|
|
89
|
+
ipython_config.py
|
|
90
|
+
|
|
91
|
+
# pyenv
|
|
92
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
93
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
94
|
+
# .python-version
|
|
95
|
+
|
|
96
|
+
# pipenv
|
|
97
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
98
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
99
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
100
|
+
# install all needed dependencies.
|
|
101
|
+
#Pipfile.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
|
|
110
|
+
# pdm
|
|
111
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
112
|
+
#pdm.lock
|
|
113
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
114
|
+
# in version control.
|
|
115
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
116
|
+
.pdm.toml
|
|
117
|
+
|
|
118
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
119
|
+
__pypackages__/
|
|
120
|
+
|
|
121
|
+
# Celery stuff
|
|
122
|
+
celerybeat-schedule
|
|
123
|
+
celerybeat.pid
|
|
124
|
+
|
|
125
|
+
# SageMath parsed files
|
|
126
|
+
*.sage.py
|
|
127
|
+
|
|
128
|
+
# Environments
|
|
129
|
+
.env
|
|
130
|
+
.venv
|
|
131
|
+
env/
|
|
132
|
+
venv/
|
|
133
|
+
ENV/
|
|
134
|
+
env.bak/
|
|
135
|
+
venv.bak/
|
|
136
|
+
|
|
137
|
+
# Spyder project settings
|
|
138
|
+
.spyderproject
|
|
139
|
+
.spyproject
|
|
140
|
+
|
|
141
|
+
# Rope project settings
|
|
142
|
+
.ropeproject
|
|
143
|
+
|
|
144
|
+
# mkdocs documentation
|
|
145
|
+
/site
|
|
146
|
+
|
|
147
|
+
# mypy
|
|
148
|
+
.mypy_cache/
|
|
149
|
+
.dmypy.json
|
|
150
|
+
dmypy.json
|
|
151
|
+
|
|
152
|
+
# Pyre type checker
|
|
153
|
+
.pyre/
|
|
154
|
+
|
|
155
|
+
# pytype static type analyzer
|
|
156
|
+
.pytype/
|
|
157
|
+
|
|
158
|
+
# Cython debug symbols
|
|
159
|
+
cython_debug/
|
|
160
|
+
|
|
161
|
+
# PyCharm
|
|
162
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
163
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
164
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
165
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
166
|
+
#.idea/
|
|
167
|
+
|
|
168
|
+
.DS_Store
|
|
169
|
+
|
|
170
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
image: python:latest
|
|
2
|
+
|
|
3
|
+
deploy:
|
|
4
|
+
variables:
|
|
5
|
+
TWINE_USERNAME: gitlab-ci-token
|
|
6
|
+
TWINE_PASSWORD: $CI_JOB_TOKEN
|
|
7
|
+
script:
|
|
8
|
+
- pip install -r requirements.txt
|
|
9
|
+
- python -m build
|
|
10
|
+
- python -m twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*
|
|
11
|
+
only:
|
|
12
|
+
refs:
|
|
13
|
+
- tags
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"python.testing.unittestArgs": [
|
|
3
|
+
"-v",
|
|
4
|
+
"-s",
|
|
5
|
+
"./adaptivetesting/tests",
|
|
6
|
+
"-p",
|
|
7
|
+
"test*.py"
|
|
8
|
+
],
|
|
9
|
+
"python.testing.pytestEnabled": false,
|
|
10
|
+
"python.testing.unittestEnabled": true,
|
|
11
|
+
"[python]": {
|
|
12
|
+
"editor.defaultFormatter": "ms-python.autopep8"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,40 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: adaptivetesting
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: adaptivetesting is a Python package that can be used to simulate and evaluate custom CAT scenarios as well as implement them in real-world testing scenarios from a single codebase
|
|
5
|
-
|
|
6
|
-
Author: Jonas Engicht
|
|
7
|
-
Author-email: jonas.engicht@uni-jena.de
|
|
8
|
-
Maintainer: Jonas Engicht
|
|
9
|
-
Maintainer-email: jonas.engicht@uni-jena.de
|
|
10
|
-
License: Mozilla Public License Version 2.0
|
|
11
|
-
Keywords: statistics,psychology,item-response-theory,computerized-adaptive-testing
|
|
12
|
-
Requires-Python: >3.10
|
|
13
|
-
Description-Content-Type: text/markdown
|
|
5
|
+
Author-email: Jonas Engicht <dev@condecon.de>
|
|
14
6
|
License-File: LICENSE
|
|
7
|
+
Keywords: computerized-adaptive-testing,item-response-theory,psychology,statistics
|
|
8
|
+
Requires-Python: >=3.10
|
|
15
9
|
Requires-Dist: jax>=0.5.1
|
|
16
10
|
Requires-Dist: numpy>=1.20.0
|
|
17
|
-
Requires-Dist: scipy>=1.15.0
|
|
18
11
|
Requires-Dist: pandas>=2.2.0
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Dynamic: description
|
|
22
|
-
Dynamic: description-content-type
|
|
23
|
-
Dynamic: home-page
|
|
24
|
-
Dynamic: keywords
|
|
25
|
-
Dynamic: license
|
|
26
|
-
Dynamic: license-file
|
|
27
|
-
Dynamic: maintainer
|
|
28
|
-
Dynamic: maintainer-email
|
|
29
|
-
Dynamic: requires-dist
|
|
30
|
-
Dynamic: requires-python
|
|
31
|
-
Dynamic: summary
|
|
12
|
+
Requires-Dist: scipy>=1.15.0
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
32
14
|
|
|
33
15
|
# adaptivetesting
|
|
34
16
|
[](https://github.com/condecon/adaptivetesting/actions/workflows/python-test.yml)
|
|
35
17
|
[](https://github.com/condecon/adaptivetesting/actions/workflows/publish.yml)
|
|
36
18
|
|
|
37
|
-
<img src="/
|
|
19
|
+
<img src="/docs_generation/source/_static/logo.svg" style="width: 100%">
|
|
38
20
|
</img>
|
|
39
21
|
|
|
40
22
|
_adaptivetesting_ is a Python package for computerized adaptive
|
|
@@ -104,5 +86,5 @@ For more information, please consult the documentation for the ``AdaptiveTest``
|
|
|
104
86
|
| tests | Unit test for the entire package |
|
|
105
87
|
|
|
106
88
|
## Documentation
|
|
107
|
-
|
|
108
|
-
|
|
89
|
+
|
|
90
|
+
You can find extensiv documentation in the <a href="/docs/">`docs` directory</a>.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
[](https://github.com/condecon/adaptivetesting/actions/workflows/python-test.yml)
|
|
3
3
|
[](https://github.com/condecon/adaptivetesting/actions/workflows/publish.yml)
|
|
4
4
|
|
|
5
|
-
<img src="/
|
|
5
|
+
<img src="/docs_generation/source/_static/logo.svg" style="width: 100%">
|
|
6
6
|
</img>
|
|
7
7
|
|
|
8
8
|
_adaptivetesting_ is a Python package for computerized adaptive
|
|
@@ -72,5 +72,5 @@ For more information, please consult the documentation for the ``AdaptiveTest``
|
|
|
72
72
|
| tests | Unit test for the entire package |
|
|
73
73
|
|
|
74
74
|
## Documentation
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
|
|
76
|
+
You can find extensiv documentation in the <a href="/docs/">`docs` directory</a>.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from typing import List
|
|
2
|
-
from ..models.__adaptive_test import AdaptiveTest
|
|
3
2
|
from ..models.__test_result import TestResult
|
|
4
3
|
from ..services.__test_results_interface import ITestResults
|
|
5
4
|
import sqlite3
|
|
@@ -26,8 +25,6 @@ class SQLiteContext(ITestResults):
|
|
|
26
25
|
Args:
|
|
27
26
|
test_results (List[TestResult]): list of test results
|
|
28
27
|
"""
|
|
29
|
-
|
|
30
|
-
|
|
31
28
|
try:
|
|
32
29
|
con = sqlite3.connect(self.filename)
|
|
33
30
|
except sqlite3.OperationalError:
|
{adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/implementations/__pre_test.py
RENAMED
|
@@ -49,7 +49,8 @@ class PreTest:
|
|
|
49
49
|
TestItem: Selected item.
|
|
50
50
|
"""
|
|
51
51
|
# select only items with difficulty in interval
|
|
52
|
-
items_in_interval: List[TestItem] = [item for item in list(self.items)
|
|
52
|
+
items_in_interval: List[TestItem] = [item for item in list(self.items)
|
|
53
|
+
if lower < item.b <= upper]
|
|
53
54
|
# draw one item randomly
|
|
54
55
|
if self.seed is not None:
|
|
55
56
|
random.seed(self.seed)
|
|
@@ -71,11 +72,10 @@ class PreTest:
|
|
|
71
72
|
quantiles.extend(list(self.calculate_quantiles()))
|
|
72
73
|
quantiles.extend([difficulties.max()])
|
|
73
74
|
|
|
74
|
-
for i in range(len(quantiles)-1):
|
|
75
|
+
for i in range(len(quantiles) - 1):
|
|
75
76
|
selected_item = self.select_item_in_interval(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
)
|
|
77
|
+
lower=float(quantiles[i]),
|
|
78
|
+
upper=float(quantiles[i + 1]))
|
|
79
79
|
|
|
80
80
|
selected_items.append(selected_item)
|
|
81
81
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from .estimators.__functions.__estimators import probability_y1
|
|
2
|
+
from ..models.__test_item import TestItem
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def generate_response_pattern(ability: float,
|
|
7
|
+
items: list[TestItem],
|
|
8
|
+
seed: int | None = None) -> list[int]:
|
|
9
|
+
"""Generates a response pattern for a given ability level
|
|
10
|
+
and item difficulties. Also, a seed can be set.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
ability (float): participants ability
|
|
14
|
+
items (list[TestItem]): test items
|
|
15
|
+
seed (int, optional): Seed for the random process.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
list[int]: response pattern
|
|
19
|
+
"""
|
|
20
|
+
responses: list[int] = []
|
|
21
|
+
|
|
22
|
+
for item in items:
|
|
23
|
+
probability_of_success = probability_y1(mu=ability,
|
|
24
|
+
a=item.a,
|
|
25
|
+
b=item.b,
|
|
26
|
+
c=item.c,
|
|
27
|
+
d=item.d)
|
|
28
|
+
|
|
29
|
+
# simulate response based on probability of scucess
|
|
30
|
+
if seed is not None:
|
|
31
|
+
np.random.seed(seed)
|
|
32
|
+
response = np.random.binomial(n=1, p=probability_of_success)
|
|
33
|
+
responses.append(response)
|
|
34
|
+
|
|
35
|
+
return responses
|
|
@@ -28,10 +28,10 @@ def standard_error(answered_items: List[TestItem],
|
|
|
28
28
|
Returns:
|
|
29
29
|
float: Standard error
|
|
30
30
|
"""
|
|
31
|
-
a=np.array([item.a for item in answered_items])
|
|
32
|
-
b=np.array([item.b for item in answered_items])
|
|
33
|
-
c=np.array([item.c for item in answered_items])
|
|
34
|
-
d=np.array([item.d for item in answered_items])
|
|
31
|
+
a = np.array([item.a for item in answered_items])
|
|
32
|
+
b = np.array([item.b for item in answered_items])
|
|
33
|
+
c = np.array([item.c for item in answered_items])
|
|
34
|
+
d = np.array([item.d for item in answered_items])
|
|
35
35
|
|
|
36
36
|
if estimator == "ML":
|
|
37
37
|
error = 1 / math.sqrt(test_information_function(mu=np.array(estimated_ability_level),
|
|
@@ -45,10 +45,11 @@ def standard_error(answered_items: List[TestItem],
|
|
|
45
45
|
|
|
46
46
|
if estimator == "BM":
|
|
47
47
|
information = test_information_function(mu=np.array(estimated_ability_level),
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
a=a,
|
|
49
|
+
b=b,
|
|
50
|
+
c=c,
|
|
51
|
+
d=d)
|
|
52
|
+
|
|
52
53
|
if sd is None:
|
|
53
54
|
raise ValueError("sd cannot be None if BM is used as estimator.")
|
|
54
55
|
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import jax.numpy as np
|
|
2
|
-
from .estimators.__functions.__estimators import probability_y1
|
|
3
|
-
from jax import jit, grad
|
|
2
|
+
from .estimators.__functions.__estimators import probability_y1
|
|
4
3
|
from scipy.differentiate import derivative
|
|
5
4
|
|
|
6
5
|
|
|
7
|
-
|
|
8
6
|
def test_information_function(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
mu: np.ndarray,
|
|
8
|
+
a: np.ndarray,
|
|
9
|
+
b: np.ndarray,
|
|
10
|
+
c: np.ndarray,
|
|
11
|
+
d: np.ndarray,
|
|
14
12
|
) -> float:
|
|
15
13
|
"""
|
|
16
14
|
Calculates test information.
|
|
@@ -28,16 +26,12 @@ def test_information_function(
|
|
|
28
26
|
"""
|
|
29
27
|
p_y1 = probability_y1(mu, a, b, c, d)
|
|
30
28
|
|
|
31
|
-
p_y1_grad = derivative(probability_y1,
|
|
29
|
+
p_y1_grad = derivative(probability_y1,
|
|
32
30
|
mu,
|
|
33
31
|
args=(a, b, c, d))
|
|
34
|
-
|
|
35
|
-
|
|
36
32
|
|
|
37
33
|
product = (p_y1_grad.df ** 2) / (p_y1 * (1 - p_y1))
|
|
38
34
|
information_tensor = np.cumsum(product)
|
|
39
|
-
# print(f"Information tensor: {information_tensor}")
|
|
40
35
|
information = information_tensor[len(information_tensor) - 1]
|
|
41
36
|
# convert information to float and return
|
|
42
37
|
return float(information)
|
|
43
|
-
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from typing import List, Tuple
|
|
2
|
+
import jax.numpy as np
|
|
3
|
+
from ...services.__estimator_interface import IEstimator
|
|
4
|
+
from ...models.__test_item import TestItem
|
|
5
|
+
from .__functions.__bayes import maximize_posterior
|
|
6
|
+
from .__prior import Prior
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BayesModal(IEstimator):
|
|
10
|
+
def __init__(self,
|
|
11
|
+
response_pattern: List[int] | np.ndarray,
|
|
12
|
+
items: List[TestItem],
|
|
13
|
+
prior: Prior,
|
|
14
|
+
optimization_interval: Tuple[float, float] = (-10, 10)):
|
|
15
|
+
"""This class can be used to estimate the current ability level
|
|
16
|
+
of a respondent given the response pattern and the corresponding
|
|
17
|
+
item difficulties.
|
|
18
|
+
The estimation is based on maximum likelihood estimation and the
|
|
19
|
+
Rasch model.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
response_pattern (List[int]): list of response patterns (0: wrong, 1:right)
|
|
23
|
+
|
|
24
|
+
items (List[TestItem]): list of answered items
|
|
25
|
+
|
|
26
|
+
prior (Prior): prior distribution
|
|
27
|
+
"""
|
|
28
|
+
super().__init__(response_pattern, items, optimization_interval)
|
|
29
|
+
|
|
30
|
+
self.prior = prior
|
|
31
|
+
|
|
32
|
+
def get_estimation(self) -> float:
|
|
33
|
+
"""Estimate the current ability level using Bayes Modal.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
float: ability estimation
|
|
37
|
+
"""
|
|
38
|
+
return maximize_posterior(
|
|
39
|
+
self.a,
|
|
40
|
+
self.b,
|
|
41
|
+
self.c,
|
|
42
|
+
self.d,
|
|
43
|
+
self.response_pattern,
|
|
44
|
+
self.prior
|
|
45
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import jax.numpy as np
|
|
2
|
+
from scipy.optimize import minimize_scalar, OptimizeResult # type: ignore
|
|
3
|
+
from .__estimators import likelihood
|
|
4
|
+
from ..__prior import Prior
|
|
5
|
+
from ....models.__algorithm_exception import AlgorithmException
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def maximize_posterior(
|
|
9
|
+
a: np.ndarray,
|
|
10
|
+
b: np.ndarray,
|
|
11
|
+
c: np.ndarray,
|
|
12
|
+
d: np.ndarray,
|
|
13
|
+
response_pattern: np.ndarray,
|
|
14
|
+
prior: Prior
|
|
15
|
+
) -> float:
|
|
16
|
+
"""_summary_
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
a (np.ndarray): _description_
|
|
20
|
+
|
|
21
|
+
b (np.ndarray): _description_
|
|
22
|
+
|
|
23
|
+
c (np.ndarray): _description_
|
|
24
|
+
|
|
25
|
+
d (np.ndarray): _description_
|
|
26
|
+
|
|
27
|
+
response_pattern (np.ndarray): _description_
|
|
28
|
+
|
|
29
|
+
prior (Prior): _description_
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
float: Bayes Modal estimator for the given parameters
|
|
33
|
+
"""
|
|
34
|
+
def posterior(mu) -> np.ndarray:
|
|
35
|
+
return likelihood(mu, a, b, c, d, response_pattern) * prior.pdf(mu)
|
|
36
|
+
|
|
37
|
+
result: OptimizeResult = minimize_scalar(lambda mu: posterior(mu),
|
|
38
|
+
bounds=(-10, 10),
|
|
39
|
+
method="bounded") # type: ignore
|
|
40
|
+
|
|
41
|
+
if not result.success:
|
|
42
|
+
raise AlgorithmException(f"Optimization failed: {result.message}")
|
|
43
|
+
|
|
44
|
+
else:
|
|
45
|
+
return float(result.x)
|