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.
Files changed (93) hide show
  1. adaptivetesting-1.0.1/.github/workflows/publish.yml +39 -0
  2. adaptivetesting-1.0.1/.github/workflows/python-test.yml +63 -0
  3. adaptivetesting-1.0.1/.gitignore +170 -0
  4. adaptivetesting-1.0.1/.gitlab-ci.yml +13 -0
  5. adaptivetesting-1.0.1/.python-version +1 -0
  6. adaptivetesting-1.0.1/.vscode/extensions.json +8 -0
  7. adaptivetesting-1.0.1/.vscode/settings.json +14 -0
  8. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/PKG-INFO +9 -27
  9. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/README.md +3 -3
  10. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/data/__sqlite_context.py +0 -3
  11. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/implementations/__default_implementation.py +0 -1
  12. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/implementations/__pre_test.py +5 -5
  13. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/implementations/__semi_implementation.py +0 -1
  14. adaptivetesting-1.0.1/adaptivetesting/math/__gen_response_pattern.py +35 -0
  15. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/math/__init__.py +1 -0
  16. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/math/__standard_error.py +9 -8
  17. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/math/__test_information.py +7 -13
  18. adaptivetesting-1.0.1/adaptivetesting/math/estimators/__bayes_modal_estimation.py +45 -0
  19. adaptivetesting-1.0.1/adaptivetesting/math/estimators/__functions/__bayes.py +45 -0
  20. adaptivetesting-1.0.1/adaptivetesting/math/estimators/__functions/__estimators.py +133 -0
  21. adaptivetesting-1.0.1/adaptivetesting/math/estimators/__init__.py +5 -0
  22. adaptivetesting-1.0.1/adaptivetesting/math/estimators/__ml_estimation.py +39 -0
  23. adaptivetesting-1.0.1/adaptivetesting/math/estimators/__prior.py +47 -0
  24. adaptivetesting-1.0.1/adaptivetesting/math/item_selection/__init__.py +1 -0
  25. adaptivetesting-1.0.1/adaptivetesting/math/item_selection/__urrys_rule.py +33 -0
  26. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__adaptive_test.py +1 -2
  27. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__algorithm_exception.py +0 -1
  28. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__item_pool.py +9 -10
  29. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__item_selection_exception.py +1 -1
  30. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__test_item.py +1 -5
  31. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/services/__estimator_interface.py +1 -0
  32. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_adaptive_test.py +1 -2
  33. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_bayes_modal.py +5 -6
  34. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_code_examples.py +2 -2
  35. adaptivetesting-1.0.1/adaptivetesting/tests/test_generate_response_pattern.py +59 -0
  36. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_information_test.py +2 -1
  37. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_load_test_items.py +3 -3
  38. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_mle.py +3 -3
  39. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_pretest.py +1 -1
  40. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_standard_error.py +1 -0
  41. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/tests/test_urrys_rule.py +1 -1
  42. adaptivetesting-1.0.1/code_examples/example_default.py +76 -0
  43. adaptivetesting-1.0.1/code_examples/example_psychopy.py +116 -0
  44. adaptivetesting-1.0.1/code_examples/example_semi.py +77 -0
  45. adaptivetesting-1.0.1/data/default/0.pickle +0 -0
  46. adaptivetesting-1.0.1/data/semi/0.pickle +0 -0
  47. adaptivetesting-1.0.1/docs/data.md +69 -0
  48. adaptivetesting-1.0.1/docs/implementations.md +117 -0
  49. adaptivetesting-1.0.1/docs/index.md +32 -0
  50. adaptivetesting-1.0.1/docs/math.md +254 -0
  51. adaptivetesting-1.0.1/docs/models.md +248 -0
  52. adaptivetesting-1.0.1/docs/services.md +42 -0
  53. adaptivetesting-1.0.1/docs/simulation.md +53 -0
  54. adaptivetesting-1.0.1/docs/tests.md +4 -0
  55. adaptivetesting-1.0.1/docs_generation/Makefile +20 -0
  56. adaptivetesting-1.0.1/docs_generation/make.bat +35 -0
  57. adaptivetesting-1.0.1/docs_generation/source/_static/logo.svg +67 -0
  58. adaptivetesting-1.0.1/docs_generation/source/_static/main.css +24 -0
  59. adaptivetesting-1.0.1/docs_generation/source/conf.py +46 -0
  60. adaptivetesting-1.0.1/docs_generation/source/data.rst +19 -0
  61. adaptivetesting-1.0.1/docs_generation/source/implementations.rst +31 -0
  62. adaptivetesting-1.0.1/docs_generation/source/index.rst +37 -0
  63. adaptivetesting-1.0.1/docs_generation/source/math.rst +77 -0
  64. adaptivetesting-1.0.1/docs_generation/source/models.rst +46 -0
  65. adaptivetesting-1.0.1/docs_generation/source/services.rst +18 -0
  66. adaptivetesting-1.0.1/docs_generation/source/simulation.rst +29 -0
  67. adaptivetesting-1.0.1/docs_generation/source/tests.rst +5 -0
  68. adaptivetesting-1.0.1/images/default.svg +208 -0
  69. adaptivetesting-1.0.1/images/semi-adaptive.svg +254 -0
  70. adaptivetesting-1.0.1/mypy.ini +8 -0
  71. adaptivetesting-1.0.1/pyproject.toml +36 -0
  72. adaptivetesting-1.0.1/requirements.txt +552 -0
  73. adaptivetesting-1.0.1/setup.cfg +5 -0
  74. adaptivetesting-1.0.1/uv.lock +1016 -0
  75. adaptivetesting-1.0.0/adaptivetesting.egg-info/PKG-INFO +0 -108
  76. adaptivetesting-1.0.0/adaptivetesting.egg-info/SOURCES.txt +0 -41
  77. adaptivetesting-1.0.0/adaptivetesting.egg-info/dependency_links.txt +0 -1
  78. adaptivetesting-1.0.0/adaptivetesting.egg-info/requires.txt +0 -4
  79. adaptivetesting-1.0.0/adaptivetesting.egg-info/top_level.txt +0 -1
  80. adaptivetesting-1.0.0/setup.cfg +0 -4
  81. adaptivetesting-1.0.0/setup.py +0 -36
  82. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/LICENSE +0 -0
  83. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/__init__.py +0 -0
  84. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/data/__init__.py +0 -0
  85. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/data/__pickle_context.py +0 -0
  86. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/implementations/__init__.py +0 -0
  87. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__init__.py +0 -0
  88. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/models/__test_result.py +0 -0
  89. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/services/__init__.py +0 -0
  90. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/services/__test_results_interface.py +0 -0
  91. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/simulation/__init__.py +0 -0
  92. {adaptivetesting-1.0.0 → adaptivetesting-1.0.1}/adaptivetesting/simulation/__simulation.py +0 -0
  93. {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,8 @@
1
+ {
2
+ "recommendations": [
3
+ "ms-python.autopep8",
4
+ "njpwerner.autodocstring",
5
+ "ms-python.python",
6
+ "ms-python.flake8"
7
+ ]
8
+ }
@@ -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.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
- Home-page: https://github.com/condecon/adaptivetesting
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
- Dynamic: author
20
- Dynamic: author-email
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
  [![Unittests](https://github.com/condecon/adaptivetesting/actions/workflows/python-test.yml/badge.svg)](https://github.com/condecon/adaptivetesting/actions/workflows/python-test.yml)
35
17
  [![Deploy to PyPi](https://github.com/condecon/adaptivetesting/actions/workflows/publish.yml/badge.svg)](https://github.com/condecon/adaptivetesting/actions/workflows/publish.yml)
36
18
 
37
- <img src="/docs/source/_static/logo.svg" style="width: 100%">
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
- Extensive documentation is available in the source code,
108
- but it can also be compiled to a webpage using sphinx.
89
+
90
+ You can find extensiv documentation in the <a href="/docs/">`docs` directory</a>.
@@ -2,7 +2,7 @@
2
2
  [![Unittests](https://github.com/condecon/adaptivetesting/actions/workflows/python-test.yml/badge.svg)](https://github.com/condecon/adaptivetesting/actions/workflows/python-test.yml)
3
3
  [![Deploy to PyPi](https://github.com/condecon/adaptivetesting/actions/workflows/publish.yml/badge.svg)](https://github.com/condecon/adaptivetesting/actions/workflows/publish.yml)
4
4
 
5
- <img src="/docs/source/_static/logo.svg" style="width: 100%">
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
- Extensive documentation is available in the source code,
76
- but it can also be compiled to a webpage using sphinx.
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:
@@ -1,4 +1,3 @@
1
- from typing import List
2
1
  from ..models.__adaptive_test import AdaptiveTest
3
2
  from ..models.__item_pool import ItemPool
4
3
  from ..models.__algorithm_exception import AlgorithmException
@@ -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) if lower < item.b <= upper]
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
- lower=float(quantiles[i]),
77
- upper=float(quantiles[i+1])
78
- )
77
+ lower=float(quantiles[i]),
78
+ upper=float(quantiles[i + 1]))
79
79
 
80
80
  selected_items.append(selected_item)
81
81
 
@@ -1,4 +1,3 @@
1
- from typing import List
2
1
  from ..models.__adaptive_test import AdaptiveTest
3
2
  from ..models.__item_pool import ItemPool
4
3
  from ..models.__algorithm_exception import AlgorithmException
@@ -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
@@ -1,2 +1,3 @@
1
1
  from .__standard_error import standard_error
2
2
  from .__test_information import test_information_function
3
+ from .__gen_response_pattern import generate_response_pattern
@@ -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
- a=a,
49
- b=b,
50
- c=c,
51
- d=d)
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, probability_y0
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
- mu: np.ndarray,
10
- a: np.ndarray,
11
- b: np.ndarray,
12
- c: np.ndarray,
13
- d: np.ndarray,
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)