tfidf-stability 0.2.0__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.
- tfidf_stability-0.2.0/.clang-format +38 -0
- tfidf_stability-0.2.0/.editorconfig +26 -0
- tfidf_stability-0.2.0/.gitattributes +22 -0
- tfidf_stability-0.2.0/.gitignore +107 -0
- tfidf_stability-0.2.0/.pre-commit-config.yaml +89 -0
- tfidf_stability-0.2.0/.zenodo.json +29 -0
- tfidf_stability-0.2.0/CHANGELOG.md +81 -0
- tfidf_stability-0.2.0/CITATION.cff +47 -0
- tfidf_stability-0.2.0/CMakeLists.txt +72 -0
- tfidf_stability-0.2.0/CMakePresets.json +136 -0
- tfidf_stability-0.2.0/CONTRIBUTING.md +58 -0
- tfidf_stability-0.2.0/LICENSE.md +63 -0
- tfidf_stability-0.2.0/LICENSES/Apache-2.0.txt +73 -0
- tfidf_stability-0.2.0/LICENSES/BSD-3-Clause.txt +11 -0
- tfidf_stability-0.2.0/LICENSES/CC-BY-4.0.txt +156 -0
- tfidf_stability-0.2.0/LICENSES/MIT.txt +18 -0
- tfidf_stability-0.2.0/PKG-INFO +903 -0
- tfidf_stability-0.2.0/README.md +853 -0
- tfidf_stability-0.2.0/REUSE.toml +129 -0
- tfidf_stability-0.2.0/SECURITY.md +71 -0
- tfidf_stability-0.2.0/THIRD_PARTY_NOTICES.md +106 -0
- tfidf_stability-0.2.0/configs/ablations.yaml +48 -0
- tfidf_stability-0.2.0/configs/datasets.yaml +79 -0
- tfidf_stability-0.2.0/configs/default.yaml +65 -0
- tfidf_stability-0.2.0/configs/equivalent_mutants.txt +217 -0
- tfidf_stability-0.2.0/configs/equivalent_mutants_cpp.txt +98 -0
- tfidf_stability-0.2.0/configs/pipeline_digest.txt +32 -0
- tfidf_stability-0.2.0/cpp/CMakeLists.txt +132 -0
- tfidf_stability-0.2.0/cpp/bench/CMakeLists.txt +18 -0
- tfidf_stability-0.2.0/cpp/bench/bench_main.cpp +206 -0
- tfidf_stability-0.2.0/cpp/bindings/module.cpp +650 -0
- tfidf_stability-0.2.0/cpp/cmake/NumericsFlags.cmake +118 -0
- tfidf_stability-0.2.0/cpp/cmake/Sanitizers.cmake +32 -0
- tfidf_stability-0.2.0/cpp/cmake/Warnings.cmake +48 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/core/build_config.hpp.in +26 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/core/fp_guard.hpp +220 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/core/reduction.hpp +276 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/core/types.hpp +62 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/ranking/attributes.hpp +92 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/ranking/distances.hpp +391 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/ranking/margins.hpp +104 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/ranking/ranker.hpp +159 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/ranking/sort_keys.hpp +122 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/ranking/tie_groups.hpp +182 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/similarity/scoring.hpp +208 -0
- tfidf_stability-0.2.0/cpp/include/tfidf/vectorisation/sparse.hpp +270 -0
- tfidf_stability-0.2.0/cpp/tests/CMakeLists.txt +34 -0
- tfidf_stability-0.2.0/cpp/tests/main.cpp +2 -0
- tfidf_stability-0.2.0/cpp/tests/test_distances.cpp +514 -0
- tfidf_stability-0.2.0/cpp/tests/test_fp_guard.cpp +242 -0
- tfidf_stability-0.2.0/cpp/tests/test_ranking.cpp +748 -0
- tfidf_stability-0.2.0/cpp/tests/test_reduction.cpp +424 -0
- tfidf_stability-0.2.0/cpp/tests/test_scoring.cpp +669 -0
- tfidf_stability-0.2.0/cpp/third_party/MANIFEST.sha256 +2 -0
- tfidf_stability-0.2.0/cpp/third_party/doctest/doctest.h +7106 -0
- tfidf_stability-0.2.0/cpp/third_party/nanobench/nanobench.h +3484 -0
- tfidf_stability-0.2.0/data/README.md +95 -0
- tfidf_stability-0.2.0/data/assets/MANIFEST.sha256 +12 -0
- tfidf_stability-0.2.0/data/assets/stopwords_en_v1.txt +160 -0
- tfidf_stability-0.2.0/docs/experiments.md +132 -0
- tfidf_stability-0.2.0/docs/index.md +140 -0
- tfidf_stability-0.2.0/docs/main.pdf +0 -0
- tfidf_stability-0.2.0/docs/mathematical_formulation.md +143 -0
- tfidf_stability-0.2.0/docs/perturbation_notes.md +100 -0
- tfidf_stability-0.2.0/docs/ranking_stability.md +108 -0
- tfidf_stability-0.2.0/docs/spec_addenda.md +1427 -0
- tfidf_stability-0.2.0/docs/tie_breaking_discontinuities.md +152 -0
- tfidf_stability-0.2.0/examples/inspect_intermediates.py +440 -0
- tfidf_stability-0.2.0/examples/minimal_corpus_demo.py +382 -0
- tfidf_stability-0.2.0/examples/stability_certificate_demo.py +336 -0
- tfidf_stability-0.2.0/examples/tie_break_discontinuity_demo.py +319 -0
- tfidf_stability-0.2.0/notebooks/cosine_stability.ipynb +123 -0
- tfidf_stability-0.2.0/notebooks/idf_sensitivity.ipynb +121 -0
- tfidf_stability-0.2.0/notebooks/margin_distributions.ipynb +137 -0
- tfidf_stability-0.2.0/notebooks/pipeline_walkthrough.ipynb +155 -0
- tfidf_stability-0.2.0/notebooks/sanity_check.ipynb +203 -0
- tfidf_stability-0.2.0/notebooks/tie_break_ablation.ipynb +139 -0
- tfidf_stability-0.2.0/notebooks/tie_group_case_study.ipynb +163 -0
- tfidf_stability-0.2.0/pyproject.toml +252 -0
- tfidf_stability-0.2.0/reports/intermediates_d000000.json +180 -0
- tfidf_stability-0.2.0/reports/similarity.json +1037 -0
- tfidf_stability-0.2.0/reports/stability_profile.json +1664 -0
- tfidf_stability-0.2.0/reports/summary.md +190 -0
- tfidf_stability-0.2.0/reports/text/bibliography.bib +256 -0
- tfidf_stability-0.2.0/reports/text/main.tex +459 -0
- tfidf_stability-0.2.0/reports/tie_break_ablations.json +2371 -0
- tfidf_stability-0.2.0/requirements-dev.txt +53 -0
- tfidf_stability-0.2.0/requirements.txt +15 -0
- tfidf_stability-0.2.0/scripts/benchmark.py +92 -0
- tfidf_stability-0.2.0/scripts/build_corpus.py +85 -0
- tfidf_stability-0.2.0/scripts/check_cpp_format.py +99 -0
- tfidf_stability-0.2.0/scripts/check_dependencies.py +158 -0
- tfidf_stability-0.2.0/scripts/check_docs.py +390 -0
- tfidf_stability-0.2.0/scripts/check_layout.py +56 -0
- tfidf_stability-0.2.0/scripts/check_python_floor.py +109 -0
- tfidf_stability-0.2.0/scripts/check_test_vacuity.py +345 -0
- tfidf_stability-0.2.0/scripts/check_vendored.py +110 -0
- tfidf_stability-0.2.0/scripts/check_versions.py +168 -0
- tfidf_stability-0.2.0/scripts/export_intermediates.py +140 -0
- tfidf_stability-0.2.0/scripts/fetch_data.py +180 -0
- tfidf_stability-0.2.0/scripts/make_figures.py +1086 -0
- tfidf_stability-0.2.0/scripts/render_summary.py +503 -0
- tfidf_stability-0.2.0/scripts/run_similarity.py +134 -0
- tfidf_stability-0.2.0/scripts/run_stability_profile.py +408 -0
- tfidf_stability-0.2.0/scripts/run_tie_break_ablations.py +521 -0
- tfidf_stability-0.2.0/scripts/snapshot.py +227 -0
- tfidf_stability-0.2.0/src/tfidf_stability/__init__.py +18 -0
- tfidf_stability-0.2.0/src/tfidf_stability/_native/__init__.py +166 -0
- tfidf_stability-0.2.0/src/tfidf_stability/analysis/__init__.py +29 -0
- tfidf_stability-0.2.0/src/tfidf_stability/analysis/noise_floor.py +374 -0
- tfidf_stability-0.2.0/src/tfidf_stability/analysis/query_grid.py +262 -0
- tfidf_stability-0.2.0/src/tfidf_stability/analysis/stability_profile.py +306 -0
- tfidf_stability-0.2.0/src/tfidf_stability/analysis/stratify.py +192 -0
- tfidf_stability-0.2.0/src/tfidf_stability/analysis/summarise.py +222 -0
- tfidf_stability-0.2.0/src/tfidf_stability/analysis/tie_break_ablations.py +201 -0
- tfidf_stability-0.2.0/src/tfidf_stability/benchmarks/__init__.py +1 -0
- tfidf_stability-0.2.0/src/tfidf_stability/benchmarks/tfidf_perf.py +838 -0
- tfidf_stability-0.2.0/src/tfidf_stability/cli/__init__.py +1 -0
- tfidf_stability-0.2.0/src/tfidf_stability/cli/commands.py +541 -0
- tfidf_stability-0.2.0/src/tfidf_stability/cli/main.py +144 -0
- tfidf_stability-0.2.0/src/tfidf_stability/datasets/__init__.py +1 -0
- tfidf_stability-0.2.0/src/tfidf_stability/datasets/loaders.py +193 -0
- tfidf_stability-0.2.0/src/tfidf_stability/datasets/movielens.py +313 -0
- tfidf_stability-0.2.0/src/tfidf_stability/datasets/synthetic.py +446 -0
- tfidf_stability-0.2.0/src/tfidf_stability/persistence/__init__.py +36 -0
- tfidf_stability-0.2.0/src/tfidf_stability/persistence/manifest.py +195 -0
- tfidf_stability-0.2.0/src/tfidf_stability/persistence/model.py +99 -0
- tfidf_stability-0.2.0/src/tfidf_stability/persistence/save_load.py +552 -0
- tfidf_stability-0.2.0/src/tfidf_stability/perturbation/__init__.py +54 -0
- tfidf_stability-0.2.0/src/tfidf_stability/perturbation/corpus_edits.py +166 -0
- tfidf_stability-0.2.0/src/tfidf_stability/perturbation/experiments.py +165 -0
- tfidf_stability-0.2.0/src/tfidf_stability/perturbation/idf_perturb.py +181 -0
- tfidf_stability-0.2.0/src/tfidf_stability/perturbation/score_bounds.py +203 -0
- tfidf_stability-0.2.0/src/tfidf_stability/perturbation/vector_perturb.py +216 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/__init__.py +1 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/_snowball/MANIFEST.sha256 +6 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/_snowball/__init__.py +33 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/_snowball/among.py +12 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/_snowball/basestemmer.py +280 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/_snowball/english_stemmer.py +676 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/lemmatise.py +210 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/ngrams.py +118 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/normalise.py +108 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/pipeline.py +352 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/stopwords.py +211 -0
- tfidf_stability-0.2.0/src/tfidf_stability/preprocessing/tokenise.py +108 -0
- tfidf_stability-0.2.0/src/tfidf_stability/profiles/__init__.py +37 -0
- tfidf_stability-0.2.0/src/tfidf_stability/profiles/query_modes.py +339 -0
- tfidf_stability-0.2.0/src/tfidf_stability/profiles/user_profile.py +302 -0
- tfidf_stability-0.2.0/src/tfidf_stability/ranking/__init__.py +95 -0
- tfidf_stability-0.2.0/src/tfidf_stability/ranking/attributes.py +479 -0
- tfidf_stability-0.2.0/src/tfidf_stability/ranking/distances.py +355 -0
- tfidf_stability-0.2.0/src/tfidf_stability/ranking/margins.py +215 -0
- tfidf_stability-0.2.0/src/tfidf_stability/ranking/ranker.py +321 -0
- tfidf_stability-0.2.0/src/tfidf_stability/ranking/sort_keys.py +160 -0
- tfidf_stability-0.2.0/src/tfidf_stability/ranking/tie_groups.py +364 -0
- tfidf_stability-0.2.0/src/tfidf_stability/similarity/__init__.py +1 -0
- tfidf_stability-0.2.0/src/tfidf_stability/similarity/cosine.py +107 -0
- tfidf_stability-0.2.0/src/tfidf_stability/similarity/geometry.py +208 -0
- tfidf_stability-0.2.0/src/tfidf_stability/similarity/scoring.py +379 -0
- tfidf_stability-0.2.0/src/tfidf_stability/types.py +69 -0
- tfidf_stability-0.2.0/src/tfidf_stability/utils/__init__.py +1 -0
- tfidf_stability-0.2.0/src/tfidf_stability/utils/hashing.py +125 -0
- tfidf_stability-0.2.0/src/tfidf_stability/utils/io.py +182 -0
- tfidf_stability-0.2.0/src/tfidf_stability/utils/logging.py +306 -0
- tfidf_stability-0.2.0/src/tfidf_stability/utils/numerics.py +377 -0
- tfidf_stability-0.2.0/src/tfidf_stability/utils/validation.py +245 -0
- tfidf_stability-0.2.0/src/tfidf_stability/vectorisation/__init__.py +1 -0
- tfidf_stability-0.2.0/src/tfidf_stability/vectorisation/df_counts.py +80 -0
- tfidf_stability-0.2.0/src/tfidf_stability/vectorisation/idf.py +168 -0
- tfidf_stability-0.2.0/src/tfidf_stability/vectorisation/sparse.py +237 -0
- tfidf_stability-0.2.0/src/tfidf_stability/vectorisation/tf.py +80 -0
- tfidf_stability-0.2.0/src/tfidf_stability/vectorisation/tfidf.py +250 -0
- tfidf_stability-0.2.0/src/tfidf_stability/vectorisation/vocabulary.py +299 -0
- tfidf_stability-0.2.0/tests/conftest.py +136 -0
- tfidf_stability-0.2.0/tests/fixtures/mini_corpus.jsonl +6 -0
- tfidf_stability-0.2.0/tests/fixtures/snowball/MANIFEST.sha256 +2 -0
- tfidf_stability-0.2.0/tests/fixtures/snowball/output.txt +42649 -0
- tfidf_stability-0.2.0/tests/fixtures/snowball/voc.txt +42649 -0
- tfidf_stability-0.2.0/tests/test_analysis_harness.py +1581 -0
- tfidf_stability-0.2.0/tests/test_benchmark_smoke.py +706 -0
- tfidf_stability-0.2.0/tests/test_canonical_bytes.py +927 -0
- tfidf_stability-0.2.0/tests/test_cli.py +1465 -0
- tfidf_stability-0.2.0/tests/test_cosine_edge_cases.py +700 -0
- tfidf_stability-0.2.0/tests/test_cpp_mutation_gate.py +431 -0
- tfidf_stability-0.2.0/tests/test_datasets.py +1569 -0
- tfidf_stability-0.2.0/tests/test_df_counts_oracle.py +193 -0
- tfidf_stability-0.2.0/tests/test_df_idf_correctness.py +865 -0
- tfidf_stability-0.2.0/tests/test_doc_references.py +253 -0
- tfidf_stability-0.2.0/tests/test_fuzz_parsers.py +335 -0
- tfidf_stability-0.2.0/tests/test_lemmatiser_backends.py +376 -0
- tfidf_stability-0.2.0/tests/test_logging.py +449 -0
- tfidf_stability-0.2.0/tests/test_margins_and_flip_radii.py +1132 -0
- tfidf_stability-0.2.0/tests/test_mutation_gate.py +876 -0
- tfidf_stability-0.2.0/tests/test_native_differential.py +463 -0
- tfidf_stability-0.2.0/tests/test_native_distances_differential.py +261 -0
- tfidf_stability-0.2.0/tests/test_native_ranking_differential.py +499 -0
- tfidf_stability-0.2.0/tests/test_native_selection.py +380 -0
- tfidf_stability-0.2.0/tests/test_ordering_distances.py +617 -0
- tfidf_stability-0.2.0/tests/test_packaged_assets.py +168 -0
- tfidf_stability-0.2.0/tests/test_persistence_roundtrip.py +976 -0
- tfidf_stability-0.2.0/tests/test_perturbation_bounds.py +1048 -0
- tfidf_stability-0.2.0/tests/test_perturbation_experiments.py +409 -0
- tfidf_stability-0.2.0/tests/test_preprocessing_determinism.py +1204 -0
- tfidf_stability-0.2.0/tests/test_profiles_and_loo.py +689 -0
- tfidf_stability-0.2.0/tests/test_public_api_surface.py +495 -0
- tfidf_stability-0.2.0/tests/test_query_grid_protocol.py +459 -0
- tfidf_stability-0.2.0/tests/test_ranking_tie_breaks.py +1698 -0
- tfidf_stability-0.2.0/tests/test_reduction_policies.py +905 -0
- tfidf_stability-0.2.0/tests/test_render_summary.py +180 -0
- tfidf_stability-0.2.0/tests/test_repository_gates.py +834 -0
- tfidf_stability-0.2.0/tests/test_reproducibility_snapshot.py +456 -0
- tfidf_stability-0.2.0/tests/test_scoring_kernels.py +603 -0
- tfidf_stability-0.2.0/tests/test_tfidf_sparse_ops.py +1040 -0
- tfidf_stability-0.2.0/tests/test_tie_break_ablations.py +587 -0
- tfidf_stability-0.2.0/tests/test_tie_groups_tau.py +883 -0
- tfidf_stability-0.2.0/tests/test_validation_contracts.py +450 -0
- tfidf_stability-0.2.0/tooling/__init__.py +11 -0
- tfidf_stability-0.2.0/tooling/allowlist.py +177 -0
- tfidf_stability-0.2.0/tooling/gate.py +32 -0
- tfidf_stability-0.2.0/tooling/mutation_cpp.py +472 -0
- tfidf_stability-0.2.0/tooling/mutation_python.py +512 -0
- tfidf_stability-0.2.0/tooling/renumber_allowlists.py +175 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
Language: Cpp
|
|
3
|
+
BasedOnStyle: LLVM
|
|
4
|
+
Standard: c++20
|
|
5
|
+
|
|
6
|
+
ColumnLimit: 100
|
|
7
|
+
IndentWidth: 4
|
|
8
|
+
TabWidth: 4
|
|
9
|
+
UseTab: Never
|
|
10
|
+
|
|
11
|
+
AccessModifierOffset: -4
|
|
12
|
+
AlignAfterOpenBracket: Align
|
|
13
|
+
AllowShortFunctionsOnASingleLine: Inline
|
|
14
|
+
AllowShortIfStatementsOnASingleLine: WithoutElse
|
|
15
|
+
AlwaysBreakTemplateDeclarations: Yes
|
|
16
|
+
BinPackArguments: false
|
|
17
|
+
BinPackParameters: false
|
|
18
|
+
BreakBeforeBraces: Attach
|
|
19
|
+
IndentPPDirectives: AfterHash
|
|
20
|
+
NamespaceIndentation: None
|
|
21
|
+
PointerAlignment: Left
|
|
22
|
+
SeparateDefinitionBlocks: Always
|
|
23
|
+
SpaceAfterTemplateKeyword: false
|
|
24
|
+
|
|
25
|
+
# Keep the public headers first, then the rest -- makes include cycles obvious.
|
|
26
|
+
SortIncludes: CaseSensitive
|
|
27
|
+
IncludeBlocks: Regroup
|
|
28
|
+
IncludeCategories:
|
|
29
|
+
- Regex: '^<tfidf/'
|
|
30
|
+
Priority: 1
|
|
31
|
+
- Regex: '^<nanobind/'
|
|
32
|
+
Priority: 2
|
|
33
|
+
- Regex: '^<doctest'
|
|
34
|
+
Priority: 3
|
|
35
|
+
- Regex: '^<'
|
|
36
|
+
Priority: 4
|
|
37
|
+
- Regex: '.*'
|
|
38
|
+
Priority: 5
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
charset = utf-8
|
|
5
|
+
end_of_line = lf
|
|
6
|
+
insert_final_newline = true
|
|
7
|
+
trim_trailing_whitespace = true
|
|
8
|
+
indent_style = space
|
|
9
|
+
|
|
10
|
+
[*.{py,pyi}]
|
|
11
|
+
indent_size = 4
|
|
12
|
+
max_line_length = 100
|
|
13
|
+
|
|
14
|
+
[*.{cpp,hpp,c,h,cc,cxx}]
|
|
15
|
+
indent_size = 4
|
|
16
|
+
max_line_length = 100
|
|
17
|
+
|
|
18
|
+
[*.{yaml,yml,json,toml}]
|
|
19
|
+
indent_size = 2
|
|
20
|
+
|
|
21
|
+
[*.{md,tex,bib}]
|
|
22
|
+
indent_size = 2
|
|
23
|
+
trim_trailing_whitespace = false
|
|
24
|
+
|
|
25
|
+
[Makefile]
|
|
26
|
+
indent_style = tab
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Normalise line endings so file hashes are platform-independent. This repository
|
|
2
|
+
# asserts byte-identical reproducibility across Linux, macOS and Windows, and CRLF
|
|
3
|
+
# drift would break every content hash in the manifests.
|
|
4
|
+
* text=auto eol=lf
|
|
5
|
+
|
|
6
|
+
# Binary artefacts must never be line-ending translated.
|
|
7
|
+
*.pdf binary
|
|
8
|
+
*.png binary
|
|
9
|
+
*.jpg binary
|
|
10
|
+
*.zip binary
|
|
11
|
+
*.pyd binary
|
|
12
|
+
*.so binary
|
|
13
|
+
*.dylib binary
|
|
14
|
+
|
|
15
|
+
# Fixtures and golden values are hashed byte-for-byte; pin them explicitly.
|
|
16
|
+
tests/fixtures/*.jsonl text eol=lf
|
|
17
|
+
tests/golden/*.json text eol=lf
|
|
18
|
+
data/assets/* text eol=lf
|
|
19
|
+
data/lexicon/* text eol=lf
|
|
20
|
+
|
|
21
|
+
# Notebooks diff poorly; mark them so GitHub collapses them in reviews.
|
|
22
|
+
*.ipynb linguist-documentation
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# --- Python -----------------------------------------------------------------
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
.installed.cfg
|
|
7
|
+
dist/
|
|
8
|
+
sdist/
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
env/
|
|
12
|
+
.python-version
|
|
13
|
+
|
|
14
|
+
# --- Test / type / lint caches ----------------------------------------------
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.hypothesis/
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
.ruff_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
.coverage.*
|
|
21
|
+
coverage.xml
|
|
22
|
+
htmlcov/
|
|
23
|
+
*.gcda
|
|
24
|
+
*.gcno
|
|
25
|
+
*.gcov
|
|
26
|
+
|
|
27
|
+
# --- CMake / native build ----------------------------------------------------
|
|
28
|
+
build/
|
|
29
|
+
# Every workflow builds into its own directory beside build/: build-tests,
|
|
30
|
+
# build-assert, build-bench, build-fastmath, build-asan, build-tsan. Only
|
|
31
|
+
# `build/` was ignored, so running any command from ci.yml or sanitizers.yml
|
|
32
|
+
# as documented left an untracked tree in `git status`.
|
|
33
|
+
build-*/
|
|
34
|
+
_skbuild/
|
|
35
|
+
CMakeUserPresets.json
|
|
36
|
+
compile_commands.json
|
|
37
|
+
*.o
|
|
38
|
+
*.obj
|
|
39
|
+
*.a
|
|
40
|
+
*.lib
|
|
41
|
+
*.exp
|
|
42
|
+
*.ilk
|
|
43
|
+
*.pdb
|
|
44
|
+
|
|
45
|
+
# Built extension modules land in the package tree; never commit them.
|
|
46
|
+
src/tfidf_stability/_native/*.pyd
|
|
47
|
+
src/tfidf_stability/_native/*.so
|
|
48
|
+
src/tfidf_stability/_native/*.dylib
|
|
49
|
+
|
|
50
|
+
# --- Data --------------------------------------------------------------------
|
|
51
|
+
# MovieLens may NOT be redistributed (see data/README.md). Fetched, never committed.
|
|
52
|
+
data/raw/
|
|
53
|
+
data/interim/
|
|
54
|
+
data/processed/
|
|
55
|
+
data/external/
|
|
56
|
+
!data/README.md
|
|
57
|
+
!data/assets/
|
|
58
|
+
!data/lexicon/
|
|
59
|
+
|
|
60
|
+
# Figures ARE committed. They are renderings, and matplotlib stamps its version
|
|
61
|
+
# into every PNG, so the bytes depend on the plotting library rather than on the
|
|
62
|
+
# result: two people regenerating from identical JSON get different files. That
|
|
63
|
+
# argued for keeping them out, and for a while they were.
|
|
64
|
+
#
|
|
65
|
+
# It was the wrong trade. reports/text/main.tex embeds seven of them, so a fresh
|
|
66
|
+
# clone built the report with seven "figure not generated" boxes, and the results
|
|
67
|
+
# were invisible to anyone reading the repository rather than running it. A
|
|
68
|
+
# figure nobody can see is worth less than a figure whose bytes are not
|
|
69
|
+
# reproducible. The JSON beside them is the reproducible artefact and the digest
|
|
70
|
+
# in each caption ties the image back to it, so the provenance claim survives.
|
|
71
|
+
#
|
|
72
|
+
# Consequence to know about: a regenerated PNG shows as modified whenever
|
|
73
|
+
# matplotlib changes, even with the underlying result identical. Check the digest
|
|
74
|
+
# in the caption, not the bytes.
|
|
75
|
+
|
|
76
|
+
reports/*.csv
|
|
77
|
+
!reports/text/
|
|
78
|
+
|
|
79
|
+
# The experiment JSON *is* committed, deliberately. A figure or a quoted number
|
|
80
|
+
# whose underlying data is absent from the tree is an assertion nobody can check,
|
|
81
|
+
# which is the one thing this repository is built not to be. Each file carries
|
|
82
|
+
# its own result digest and the provenance of the run that produced it, so a
|
|
83
|
+
# reader can regenerate it and compare rather than take it on trust.
|
|
84
|
+
|
|
85
|
+
# --- LaTeX -------------------------------------------------------------------
|
|
86
|
+
*.aux
|
|
87
|
+
*.bbl
|
|
88
|
+
*.blg
|
|
89
|
+
*.fdb_latexmk
|
|
90
|
+
*.fls
|
|
91
|
+
*.lof
|
|
92
|
+
*.log
|
|
93
|
+
*.lot
|
|
94
|
+
*.out
|
|
95
|
+
*.synctex.gz
|
|
96
|
+
*.toc
|
|
97
|
+
reports/text/*.pdf
|
|
98
|
+
|
|
99
|
+
# --- Notebooks ---------------------------------------------------------------
|
|
100
|
+
.ipynb_checkpoints/
|
|
101
|
+
|
|
102
|
+
# --- Editors / OS ------------------------------------------------------------
|
|
103
|
+
.vscode/
|
|
104
|
+
.idea/
|
|
105
|
+
*.swp
|
|
106
|
+
.DS_Store
|
|
107
|
+
Thumbs.db
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Local checks, mirroring the cheap half of ci.yml.
|
|
2
|
+
#
|
|
3
|
+
# Only the fast ones. A pre-commit hook that takes a minute gets
|
|
4
|
+
# bypassed with --no-verify, and a bypassed hook is worse than no hook: it
|
|
5
|
+
# trains the habit of skipping checks.
|
|
6
|
+
|
|
7
|
+
# The three rewriting hooks share one exclusion, defined on the first of them
|
|
8
|
+
# and referenced by the other two. Those files' bytes are the point:
|
|
9
|
+
# `scripts/check_vendored.py` verifies each against a recorded SHA-256, so a
|
|
10
|
+
# hook that rewrites one breaks the check that proves it is upstream code.
|
|
11
|
+
|
|
12
|
+
repos:
|
|
13
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
14
|
+
rev: v5.0.0
|
|
15
|
+
hooks:
|
|
16
|
+
- id: trailing-whitespace
|
|
17
|
+
# Two trailing spaces are a hard line break in Markdown. Stripping them
|
|
18
|
+
# reflows every paragraph that used one, which in README.md alone would
|
|
19
|
+
# silently rewrite 136 lines of rendered output.
|
|
20
|
+
args: [--markdown-linebreak-ext=md]
|
|
21
|
+
exclude: &verified_bytes >-
|
|
22
|
+
^(cpp/third_party/|src/tfidf_stability/preprocessing/_snowball/|data/assets/|tests/fixtures/snowball/)
|
|
23
|
+
- id: end-of-file-fixer
|
|
24
|
+
exclude: *verified_bytes
|
|
25
|
+
- id: check-yaml
|
|
26
|
+
- id: check-toml
|
|
27
|
+
- id: check-added-large-files
|
|
28
|
+
args: [--maxkb=512]
|
|
29
|
+
- id: mixed-line-ending
|
|
30
|
+
args: [--fix=lf] # digests are taken over LF-normalised bytes
|
|
31
|
+
exclude: *verified_bytes
|
|
32
|
+
|
|
33
|
+
# ruff runs from the environment, not from a mirror pinned here.
|
|
34
|
+
#
|
|
35
|
+
# This used `astral-sh/ruff-pre-commit` at rev v0.7.4 while requirements-dev.txt
|
|
36
|
+
# pins ruff==0.16.2, so a contributor's hook and CI enforced two different
|
|
37
|
+
# linters nine minor versions apart -- and the newer one is strictly stricter.
|
|
38
|
+
# That is precisely the drift the exact pin exists to prevent: ruff 0.16
|
|
39
|
+
# stabilised PLR0917, which the tree had never been checked against, and the
|
|
40
|
+
# lint job failed on a commit that changed no Python at all. A local hook makes
|
|
41
|
+
# requirements-dev.txt the single place the version is stated.
|
|
42
|
+
#
|
|
43
|
+
# The cost is that `pre-commit` no longer installs ruff itself, so the hook
|
|
44
|
+
# needs the dev requirements present. That is already true of every other
|
|
45
|
+
# local hook here.
|
|
46
|
+
- repo: local
|
|
47
|
+
hooks:
|
|
48
|
+
- id: ruff
|
|
49
|
+
name: ruff (from requirements-dev.txt)
|
|
50
|
+
# `--force-exclude` is required, not optional. pre-commit passes explicit
|
|
51
|
+
# filenames, and ruff applies `extend-exclude` from pyproject.toml only
|
|
52
|
+
# to files it discovers itself -- so without this the hook lints and
|
|
53
|
+
# rewrites the vendored Snowball stemmer, breaking the SHA-256 that
|
|
54
|
+
# `scripts/check_vendored.py` verifies.
|
|
55
|
+
entry: python -m ruff check --force-exclude --fix
|
|
56
|
+
language: system
|
|
57
|
+
types_or: [python, pyi]
|
|
58
|
+
- id: ruff-format
|
|
59
|
+
name: ruff-format (from requirements-dev.txt)
|
|
60
|
+
# `--check`, not a rewrite. `ci.yml` gates on `ruff format --check`,
|
|
61
|
+
# so reporting here names the file before it reaches CI without mixing
|
|
62
|
+
# formatting churn into the diff being committed.
|
|
63
|
+
entry: python -m ruff format --force-exclude --check
|
|
64
|
+
language: system
|
|
65
|
+
types_or: [python, pyi]
|
|
66
|
+
|
|
67
|
+
- repo: local
|
|
68
|
+
hooks:
|
|
69
|
+
- id: vendored-digests
|
|
70
|
+
name: vendored assets match their manifests
|
|
71
|
+
# The provenance claims in THIRD_PARTY_NOTICES.md depend on this, and it
|
|
72
|
+
# is the one check that silently decays if left to CI alone.
|
|
73
|
+
entry: python scripts/check_vendored.py
|
|
74
|
+
language: system
|
|
75
|
+
pass_filenames: false
|
|
76
|
+
# Every directory holding a MANIFEST.sha256, which is what
|
|
77
|
+
# `check_vendored.py` discovers. `verified_bytes` above lists the same
|
|
78
|
+
# four, from the other side: these bytes are checked, so no hook may
|
|
79
|
+
# rewrite them.
|
|
80
|
+
files: ^(cpp/third_party/|src/tfidf_stability/preprocessing/_snowball/|data/assets/|tests/fixtures/snowball/)
|
|
81
|
+
|
|
82
|
+
- id: test-vacuity
|
|
83
|
+
name: no test passes without asserting anything
|
|
84
|
+
# Pure AST work over tests/, so it costs milliseconds and catches the
|
|
85
|
+
# guard-forgotten-on-a-new-test case at the moment it is written.
|
|
86
|
+
entry: python scripts/check_test_vacuity.py
|
|
87
|
+
language: system
|
|
88
|
+
pass_filenames: false
|
|
89
|
+
files: ^tests/.*\.py$
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Numerical Stability and Perturbation Behaviour in TF-IDF-Based Similarity Systems",
|
|
3
|
+
"upload_type": "software",
|
|
4
|
+
"description": "<p>A self-contained implementation and analysis of a TF-IDF-based document similarity and ranking system, written to make the algebraic structure and perturbation behaviour of the pipeline explicit. The work treats ranking stability as a first-class object, characterising it through score-separation margin distributions, and isolates decision-level discontinuities introduced by deterministic tie-breaking rules.</p><p>It comprises a normative pure-Python reference implementation and a bit-identical optimised C++20 evaluator, whose equivalence is enforced by the test suite. Every published number is reproducible from a recorded pipeline digest.</p><p>The <code>license</code> field records the licence of the software. The prose, figures and generated reports are CC-BY-4.0; LICENSE.md sets out the split and REUSE.toml states it per file.</p>",
|
|
5
|
+
"creators": [
|
|
6
|
+
{
|
|
7
|
+
"name": "Miezaniec, Matthew Maksymilian",
|
|
8
|
+
"affiliation": "King's College London"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"keywords": [
|
|
12
|
+
"TF-IDF",
|
|
13
|
+
"information retrieval",
|
|
14
|
+
"cosine similarity",
|
|
15
|
+
"numerical stability",
|
|
16
|
+
"perturbation analysis",
|
|
17
|
+
"ranking stability",
|
|
18
|
+
"reproducibility"
|
|
19
|
+
],
|
|
20
|
+
"license": "Apache-2.0",
|
|
21
|
+
"access_right": "open",
|
|
22
|
+
"related_identifiers": [
|
|
23
|
+
{
|
|
24
|
+
"identifier": "https://github.com/Canon-Regularis/tfidf-stability-and-sensitivity",
|
|
25
|
+
"relation": "isSupplementTo",
|
|
26
|
+
"scheme": "url"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to this project, in [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
4
|
+
form. Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
|
+
|
|
6
|
+
Written by hand rather than generated. `release.yml` sets
|
|
7
|
+
`generate_release_notes: true`, which lists merged pull-request titles; this
|
|
8
|
+
repository's history is direct commits, so that list is close to empty and says
|
|
9
|
+
nothing about what moved. A published number changing is the thing a reader of
|
|
10
|
+
this project needs told, and no commit log states it.
|
|
11
|
+
|
|
12
|
+
**Every entry that moves a published number names the digest it moved to.** The
|
|
13
|
+
recorded values live in `configs/pipeline_digest.txt` and in each
|
|
14
|
+
`reports/*.json`, and `scripts/snapshot.py --check` is what compares them.
|
|
15
|
+
|
|
16
|
+
## [Unreleased]
|
|
17
|
+
|
|
18
|
+
No tag has been cut yet, so everything below is the content of the first
|
|
19
|
+
release. The declared version is 0.2.0, and `scripts/check_versions.py --tag
|
|
20
|
+
v0.2.0` is what holds the tag and the four files that state it together.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- `wheels.yml` and the reusable `build-wheels.yml`: the wheel build now runs
|
|
25
|
+
nightly, and on any push or pull request touching `cpp/**`, `CMakeLists.txt`,
|
|
26
|
+
`CMakePresets.json` or the build workflows, rather than only on a release
|
|
27
|
+
tag. The push trigger matters because this repository's history is direct
|
|
28
|
+
commits. The nightly run also builds cp314, which no release ships until a
|
|
29
|
+
nightly has produced it.
|
|
30
|
+
- `codeql.yml`: static analysis for `python` and `c-cpp`, the latter built
|
|
31
|
+
through the `ci` preset so the flags analysed are the flags shipped.
|
|
32
|
+
- `SECURITY.md`, and `REUSE.toml` giving the Apache-2.0 / CC-BY-4.0 split a
|
|
33
|
+
machine-readable form. `reuse lint` runs as the ninth repository gate.
|
|
34
|
+
- `reports/summary.md`, generated from the committed reports by
|
|
35
|
+
`scripts/render_summary.py`, with a `--check` mode that fails when the two
|
|
36
|
+
disagree.
|
|
37
|
+
- A TestPyPI rehearsal that blocks `publish`, build-provenance attestations over
|
|
38
|
+
the release assets, a CycloneDX SBOM generated from a clean runtime
|
|
39
|
+
environment, and recorded SHA-256 digests for everything published.
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
- `release.yml`: the `wheels` matrix now `needs: [sdist]`, so the tag-versus-
|
|
44
|
+
declared-version check stops the build before three platforms run rather than
|
|
45
|
+
only blocking publication.
|
|
46
|
+
- The wheel now carries `LICENSES/BSD-3-Clause.txt` and
|
|
47
|
+
`THIRD_PARTY_NOTICES.md`. The vendored Snowball stemmer is BSD-3-Clause and
|
|
48
|
+
nanobind is statically linked into the extension, so both the licence text
|
|
49
|
+
and the copyright notices it requires go out with the package.
|
|
50
|
+
- `THIRD_PARTY_NOTICES.md` records nanobind as linked into the distributed
|
|
51
|
+
package rather than as a build-time dependency, which is what
|
|
52
|
+
`nanobind_add_module(... NB_STATIC ...)` makes it.
|
|
53
|
+
- `REUSE.toml` names the vendored files individually. The three generated
|
|
54
|
+
Snowball modules and the two test vectors are BSD-3-Clause; the `__init__.py`
|
|
55
|
+
and the `MANIFEST.sha256` beside them are first-party and stay Apache-2.0.
|
|
56
|
+
Each upstream holder is recorded as a separate copyright statement, so the
|
|
57
|
+
generated SPDX document attributes the years correctly.
|
|
58
|
+
- Report payloads use one key per concept: `is_exact_tie` everywhere,
|
|
59
|
+
`E1_excluded_undefined` for what it counts, `trajectory_seed` distinct from
|
|
60
|
+
the run seed, and document ids rather than candidate indices.
|
|
61
|
+
`intermediates_*.json` gained the envelope its siblings carry, so it can be
|
|
62
|
+
identity-checked for the first time.
|
|
63
|
+
- The seven figures are one visual system: a shared style, a palette in which a
|
|
64
|
+
colour means one thing throughout, and a stamp grammar that is the same on
|
|
65
|
+
each. A measured zero is now drawn as a zero rather than as an absent bar.
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
|
|
69
|
+
- `ruff check --fix` was rewriting the vendored Snowball stemmer through
|
|
70
|
+
pre-commit and breaking the SHA-256 that `scripts/check_vendored.py` verifies.
|
|
71
|
+
`extend-exclude` does not apply to filenames passed explicitly, which is what
|
|
72
|
+
pre-commit does; both ruff hooks now pass `--force-exclude`.
|
|
73
|
+
- The `vendored-digests` hook did not select `data/assets/`, so a change to a
|
|
74
|
+
hashed asset did not run the check that verifies it.
|
|
75
|
+
- The figures carried provenance stamps naming result digests that no longer
|
|
76
|
+
existed, because `reports/*.json` was regenerated without re-rendering them.
|
|
77
|
+
- The mutation sandbox did not copy `CMakePresets.json`, `.github`,
|
|
78
|
+
`requirements-dev.txt` or `reports/`, so a suite that reads any of them failed
|
|
79
|
+
the campaign baseline before a mutant was applied.
|
|
80
|
+
|
|
81
|
+
[Unreleased]: https://github.com/Canon-Regularis/tfidf-stability-and-sensitivity/commits/main
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
title: >-
|
|
3
|
+
Numerical Stability and Perturbation Behaviour in TF-IDF-Based
|
|
4
|
+
Similarity Systems
|
|
5
|
+
message: If you use this software or its results, please cite it.
|
|
6
|
+
type: software
|
|
7
|
+
authors:
|
|
8
|
+
- given-names: Matthew Maksymilian
|
|
9
|
+
family-names: Miezaniec
|
|
10
|
+
email: matthewmiezaniec1@gmail.com
|
|
11
|
+
affiliation: King's College London
|
|
12
|
+
repository-code: >-
|
|
13
|
+
https://github.com/Canon-Regularis/tfidf-stability-and-sensitivity
|
|
14
|
+
abstract: >-
|
|
15
|
+
A self-contained implementation and analysis of a TF-IDF-based document
|
|
16
|
+
similarity and ranking system, written to make the algebraic structure and
|
|
17
|
+
perturbation behaviour of the pipeline explicit. The work treats ranking
|
|
18
|
+
stability as a first-class object, characterising it through score-separation
|
|
19
|
+
margin distributions, and isolates decision-level discontinuities introduced
|
|
20
|
+
by deterministic tie-breaking rules. It comprises a normative pure-Python
|
|
21
|
+
reference implementation and a bit-identical optimised C++20 evaluator, whose
|
|
22
|
+
equivalence is enforced by the test suite.
|
|
23
|
+
keywords:
|
|
24
|
+
- TF-IDF
|
|
25
|
+
- information retrieval
|
|
26
|
+
- cosine similarity
|
|
27
|
+
- numerical stability
|
|
28
|
+
- perturbation analysis
|
|
29
|
+
- ranking stability
|
|
30
|
+
- reproducibility
|
|
31
|
+
license:
|
|
32
|
+
- Apache-2.0
|
|
33
|
+
- CC-BY-4.0
|
|
34
|
+
version: 0.2.0
|
|
35
|
+
# The date this version was released, not the date work began. It is checked
|
|
36
|
+
# against nothing, so it is the one field here that can drift silently; the git
|
|
37
|
+
# tag is the authority.
|
|
38
|
+
date-released: '2026-09-29'
|
|
39
|
+
# Filled in once Zenodo has minted one. Two DOIs exist: the concept DOI, which
|
|
40
|
+
# always resolves to the newest version, and a version DOI per release. The
|
|
41
|
+
# concept DOI belongs here, because a reader citing "this software" means the
|
|
42
|
+
# work rather than one snapshot of it.
|
|
43
|
+
#
|
|
44
|
+
# identifiers:
|
|
45
|
+
# - type: doi
|
|
46
|
+
# value: 10.5281/zenodo.XXXXXXX
|
|
47
|
+
# description: The concept DOI, resolving to the latest version.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# tfidf-stability, top-level build.
|
|
3
|
+
#
|
|
4
|
+
# The native backend is an OPTIONAL accelerator. The normative implementation is
|
|
5
|
+
# the pure-Python `reference` backend, which needs no compiler. Configure with
|
|
6
|
+
# -DTFIDF_BUILD_NATIVE=OFF for a fully functional reference-only install on a
|
|
7
|
+
# machine with no C++ toolchain.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
cmake_minimum_required(VERSION 3.20)
|
|
10
|
+
|
|
11
|
+
project(tfidf_stability
|
|
12
|
+
VERSION 0.2.0
|
|
13
|
+
DESCRIPTION "Numerical stability and perturbation behaviour in TF-IDF similarity systems"
|
|
14
|
+
LANGUAGES CXX)
|
|
15
|
+
|
|
16
|
+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cpp/cmake")
|
|
17
|
+
|
|
18
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
19
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
20
|
+
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
21
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
22
|
+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
23
|
+
|
|
24
|
+
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
25
|
+
set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
|
|
26
|
+
endif()
|
|
27
|
+
|
|
28
|
+
# -----------------------------------------------------------------------------
|
|
29
|
+
# Options
|
|
30
|
+
# -----------------------------------------------------------------------------
|
|
31
|
+
option(TFIDF_BUILD_NATIVE "Build the native (C++/nanobind) backend" ON)
|
|
32
|
+
option(TFIDF_BUILD_TESTS "Build the C++ unit-test binary" OFF)
|
|
33
|
+
option(TFIDF_BUILD_BENCH "Build the C++ microbenchmark binary" OFF)
|
|
34
|
+
option(TFIDF_WERROR "Treat compiler warnings as errors" OFF)
|
|
35
|
+
|
|
36
|
+
# NON-REPRODUCIBLE knobs. Both OFF for every published result. The manifest
|
|
37
|
+
# records their state and refuses to label a run reproducible when either is on.
|
|
38
|
+
option(TFIDF_ARCH_TUNE "Enable -march=native (NON-REPRODUCIBLE)" OFF)
|
|
39
|
+
option(TFIDF_FAST_MATH "Enable fast-math on purpose, to prove the numeric \
|
|
40
|
+
guard rails actually fire. Never use for results." OFF)
|
|
41
|
+
|
|
42
|
+
set(TFIDF_SANITIZERS "" CACHE STRING
|
|
43
|
+
"Semicolon/comma list of sanitizers, e.g. 'address;undefined' or 'thread'")
|
|
44
|
+
|
|
45
|
+
# enable_testing() has to be called from the TOP-LEVEL list file. Called deeper,
|
|
46
|
+
# CTest writes no root CTestTestfile.cmake and `ctest` reports "No tests were
|
|
47
|
+
# found" while still exiting 0.
|
|
48
|
+
if(TFIDF_BUILD_TESTS)
|
|
49
|
+
enable_testing()
|
|
50
|
+
endif()
|
|
51
|
+
|
|
52
|
+
add_subdirectory(cpp)
|
|
53
|
+
|
|
54
|
+
# -----------------------------------------------------------------------------
|
|
55
|
+
# Configuration summary. Printed so a build's numeric policy is never implicit.
|
|
56
|
+
# -----------------------------------------------------------------------------
|
|
57
|
+
message(STATUS "")
|
|
58
|
+
message(STATUS "=== tfidf-stability ${PROJECT_VERSION} =====================================")
|
|
59
|
+
message(STATUS " compiler : ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
|
|
60
|
+
message(STATUS " build type : ${CMAKE_BUILD_TYPE}")
|
|
61
|
+
message(STATUS " native backend : ${TFIDF_BUILD_NATIVE}")
|
|
62
|
+
message(STATUS " C++ tests : ${TFIDF_BUILD_TESTS}")
|
|
63
|
+
message(STATUS " benchmarks : ${TFIDF_BUILD_BENCH}")
|
|
64
|
+
message(STATUS " sanitizers : '${TFIDF_SANITIZERS}'")
|
|
65
|
+
if(TFIDF_ARCH_TUNE OR TFIDF_FAST_MATH)
|
|
66
|
+
message(STATUS " reproducible : *** NO *** (arch-tune=${TFIDF_ARCH_TUNE} \
|
|
67
|
+
fast-math=${TFIDF_FAST_MATH})")
|
|
68
|
+
else()
|
|
69
|
+
message(STATUS " reproducible : yes (strict IEEE-754, no FMA contraction)")
|
|
70
|
+
endif()
|
|
71
|
+
message(STATUS "==============================================================")
|
|
72
|
+
message(STATUS "")
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 6,
|
|
3
|
+
"cmakeMinimumRequired": { "major": 3, "minor": 25, "patch": 0 },
|
|
4
|
+
"configurePresets": [
|
|
5
|
+
{
|
|
6
|
+
"name": "base",
|
|
7
|
+
"hidden": true,
|
|
8
|
+
"generator": "Ninja",
|
|
9
|
+
"binaryDir": "${sourceDir}/build/${presetName}",
|
|
10
|
+
"cacheVariables": {
|
|
11
|
+
"CMAKE_BUILD_TYPE": "Release",
|
|
12
|
+
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
|
|
13
|
+
"TFIDF_BUILD_NATIVE": "ON",
|
|
14
|
+
"TFIDF_BUILD_TESTS": "ON",
|
|
15
|
+
"TFIDF_WERROR": "ON"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "ci",
|
|
20
|
+
"inherits": "base",
|
|
21
|
+
"displayName": "The default build, with whatever compiler the runner provides"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "mingw",
|
|
25
|
+
"inherits": "base",
|
|
26
|
+
"displayName": "MinGW-w64 UCRT (this project's reference Windows toolchain)",
|
|
27
|
+
"cacheVariables": { "CMAKE_CXX_COMPILER": "g++" },
|
|
28
|
+
"condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" }
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "msvc",
|
|
32
|
+
"inherits": "base",
|
|
33
|
+
"displayName": "MSVC (requires the Visual Studio C++ workload)",
|
|
34
|
+
"cacheVariables": { "CMAKE_CXX_COMPILER": "cl" },
|
|
35
|
+
"condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" }
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "gcc",
|
|
39
|
+
"inherits": "base",
|
|
40
|
+
"displayName": "GCC (Linux)",
|
|
41
|
+
"cacheVariables": { "CMAKE_CXX_COMPILER": "g++" }
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "clang",
|
|
45
|
+
"inherits": "base",
|
|
46
|
+
"displayName": "Clang",
|
|
47
|
+
"cacheVariables": { "CMAKE_CXX_COMPILER": "clang++" }
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
{
|
|
51
|
+
"name": "debug",
|
|
52
|
+
"inherits": "base",
|
|
53
|
+
"displayName": "Unoptimised -- must produce byte-identical results to release",
|
|
54
|
+
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "mutation",
|
|
58
|
+
"inherits": "base",
|
|
59
|
+
"displayName": "The baseline the nightly mutation campaign scores against",
|
|
60
|
+
"description": "Warnings are not errors here. A mutation deliberately writes code that trips one -- `< -> <=` makes a comparison always true, `+ -> -` converts a sign -- so under -Werror those mutants fail to compile and score `stillborn` instead of being scored against the tests. The C++ extension is off because the campaign's verdict is ctest alone.",
|
|
61
|
+
"cacheVariables": { "TFIDF_BUILD_NATIVE": "OFF", "TFIDF_WERROR": "OFF" }
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "glibcxx-assertions",
|
|
65
|
+
"inherits": "base",
|
|
66
|
+
"displayName": "Debug with libstdc++ bounds assertions armed",
|
|
67
|
+
"cacheVariables": {
|
|
68
|
+
"CMAKE_BUILD_TYPE": "Debug",
|
|
69
|
+
"CMAKE_CXX_FLAGS": "-D_GLIBCXX_ASSERTIONS"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "asan",
|
|
74
|
+
"inherits": "base",
|
|
75
|
+
"displayName": "AddressSanitizer + UndefinedBehaviorSanitizer",
|
|
76
|
+
"cacheVariables": {
|
|
77
|
+
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
|
78
|
+
"TFIDF_SANITIZERS": "address;undefined"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"name": "tsan",
|
|
83
|
+
"inherits": "base",
|
|
84
|
+
"displayName": "ThreadSanitizer (exercises the query-parallel path)",
|
|
85
|
+
"cacheVariables": { "CMAKE_BUILD_TYPE": "RelWithDebInfo", "TFIDF_SANITIZERS": "thread" }
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"name": "fastmath-guard-check",
|
|
89
|
+
"inherits": "base",
|
|
90
|
+
"displayName": "Deliberately unsound build -- CI asserts the guards REJECT it",
|
|
91
|
+
"cacheVariables": { "TFIDF_FAST_MATH": "ON" }
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "bench",
|
|
95
|
+
"inherits": "base",
|
|
96
|
+
"displayName": "Benchmarks (arch-tuned; NOT reproducible)",
|
|
97
|
+
"cacheVariables": {
|
|
98
|
+
"TFIDF_BUILD_BENCH": "ON",
|
|
99
|
+
"TFIDF_ARCH_TUNE": "ON",
|
|
100
|
+
"TFIDF_BUILD_TESTS": "OFF"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"buildPresets": [
|
|
105
|
+
{ "name": "ci", "configurePreset": "ci" },
|
|
106
|
+
{ "name": "mingw", "configurePreset": "mingw" },
|
|
107
|
+
{ "name": "msvc", "configurePreset": "msvc" },
|
|
108
|
+
{ "name": "gcc", "configurePreset": "gcc" },
|
|
109
|
+
{ "name": "clang", "configurePreset": "clang" },
|
|
110
|
+
{ "name": "debug", "configurePreset": "debug" },
|
|
111
|
+
{ "name": "mutation", "configurePreset": "mutation" },
|
|
112
|
+
{ "name": "glibcxx-assertions", "configurePreset": "glibcxx-assertions" },
|
|
113
|
+
{ "name": "asan", "configurePreset": "asan" },
|
|
114
|
+
{ "name": "tsan", "configurePreset": "tsan" },
|
|
115
|
+
{ "name": "bench", "configurePreset": "bench" },
|
|
116
|
+
{ "name": "fastmath-guard-check", "configurePreset": "fastmath-guard-check" }
|
|
117
|
+
],
|
|
118
|
+
"testPresets": [
|
|
119
|
+
{
|
|
120
|
+
"name": "base",
|
|
121
|
+
"hidden": true,
|
|
122
|
+
"output": { "outputOnFailure": true },
|
|
123
|
+
"execution": { "noTestsAction": "error", "stopOnFailure": false }
|
|
124
|
+
},
|
|
125
|
+
{ "name": "ci", "inherits": "base", "configurePreset": "ci" },
|
|
126
|
+
{ "name": "mingw", "inherits": "base", "configurePreset": "mingw" },
|
|
127
|
+
{ "name": "msvc", "inherits": "base", "configurePreset": "msvc" },
|
|
128
|
+
{ "name": "gcc", "inherits": "base", "configurePreset": "gcc" },
|
|
129
|
+
{ "name": "clang", "inherits": "base", "configurePreset": "clang" },
|
|
130
|
+
{ "name": "debug", "inherits": "base", "configurePreset": "debug" },
|
|
131
|
+
{ "name": "mutation", "inherits": "base", "configurePreset": "mutation" },
|
|
132
|
+
{ "name": "glibcxx-assertions", "inherits": "base", "configurePreset": "glibcxx-assertions" },
|
|
133
|
+
{ "name": "asan", "inherits": "base", "configurePreset": "asan" },
|
|
134
|
+
{ "name": "tsan", "inherits": "base", "configurePreset": "tsan" }
|
|
135
|
+
]
|
|
136
|
+
}
|