intensify 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.
- intensify-0.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +62 -0
- intensify-0.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +22 -0
- intensify-0.2.0/.github/PULL_REQUEST_TEMPLATE.md +19 -0
- intensify-0.2.0/.github/workflows/ci.yml +129 -0
- intensify-0.2.0/.github/workflows/publish.yml +37 -0
- intensify-0.2.0/.gitignore +47 -0
- intensify-0.2.0/.pre-commit-config.yaml +24 -0
- intensify-0.2.0/CHANGELOG.md +177 -0
- intensify-0.2.0/CITATION.cff +38 -0
- intensify-0.2.0/CODE_OF_CONDUCT.md +43 -0
- intensify-0.2.0/CONTRIBUTING.md +68 -0
- intensify-0.2.0/ISSUES.md +465 -0
- intensify-0.2.0/LICENSE +21 -0
- intensify-0.2.0/PKG-INFO +170 -0
- intensify-0.2.0/README.md +123 -0
- intensify-0.2.0/SECURITY.md +27 -0
- intensify-0.2.0/benchmarks/README.md +48 -0
- intensify-0.2.0/benchmarks/reference_dataset.py +147 -0
- intensify-0.2.0/benchmarks/run_intensify.py +186 -0
- intensify-0.2.0/benchmarks/run_scaling.py +143 -0
- intensify-0.2.0/benchmarks/run_tick.py +128 -0
- intensify-0.2.0/devdoc.md +995 -0
- intensify-0.2.0/docs/_static/.gitkeep +1 -0
- intensify-0.2.0/docs/api_reference.rst +50 -0
- intensify-0.2.0/docs/benchmarks.md +168 -0
- intensify-0.2.0/docs/conf.py +28 -0
- intensify-0.2.0/docs/getting_started.md +157 -0
- intensify-0.2.0/docs/index.rst +14 -0
- intensify-0.2.0/docs/scaling.md +68 -0
- intensify-0.2.0/docs/user_guide/diagnostics.md +80 -0
- intensify-0.2.0/docs/user_guide/index.rst +10 -0
- intensify-0.2.0/docs/user_guide/inference.md +149 -0
- intensify-0.2.0/docs/user_guide/kernels.md +110 -0
- intensify-0.2.0/docs/user_guide/simulation.md +63 -0
- intensify-0.2.0/examples/biology_epidemiology_ecology.ipynb +1219 -0
- intensify-0.2.0/examples/neuroscience_spike_analysis.ipynb +1052 -0
- intensify-0.2.0/examples/seismology_aftershocks.ipynb +1018 -0
- intensify-0.2.0/intensify/__init__.py +96 -0
- intensify-0.2.0/intensify/_config.py +41 -0
- intensify-0.2.0/intensify/backends/__init__.py +10 -0
- intensify-0.2.0/intensify/backends/_backend.py +90 -0
- intensify-0.2.0/intensify/backends/jax_backend.py +132 -0
- intensify-0.2.0/intensify/backends/numpy_backend.py +144 -0
- intensify-0.2.0/intensify/core/__init__.py +57 -0
- intensify-0.2.0/intensify/core/base.py +122 -0
- intensify-0.2.0/intensify/core/diagnostics/__init__.py +34 -0
- intensify-0.2.0/intensify/core/diagnostics/goodness_of_fit.py +197 -0
- intensify-0.2.0/intensify/core/diagnostics/metrics.py +39 -0
- intensify-0.2.0/intensify/core/diagnostics/residuals.py +79 -0
- intensify-0.2.0/intensify/core/inference/__init__.py +317 -0
- intensify-0.2.0/intensify/core/inference/bayesian.py +162 -0
- intensify-0.2.0/intensify/core/inference/em.py +176 -0
- intensify-0.2.0/intensify/core/inference/mle.py +1300 -0
- intensify-0.2.0/intensify/core/inference/multivariate_hawkes_mle_params.py +76 -0
- intensify-0.2.0/intensify/core/inference/online.py +131 -0
- intensify-0.2.0/intensify/core/inference/univariate_hawkes_mle_params.py +154 -0
- intensify-0.2.0/intensify/core/kernels/__init__.py +34 -0
- intensify-0.2.0/intensify/core/kernels/approx_power_law.py +135 -0
- intensify-0.2.0/intensify/core/kernels/base.py +197 -0
- intensify-0.2.0/intensify/core/kernels/exponential.py +100 -0
- intensify-0.2.0/intensify/core/kernels/nonparametric.py +191 -0
- intensify-0.2.0/intensify/core/kernels/power_law.py +79 -0
- intensify-0.2.0/intensify/core/kernels/sum_exponential.py +122 -0
- intensify-0.2.0/intensify/core/processes/__init__.py +31 -0
- intensify-0.2.0/intensify/core/processes/cox.py +304 -0
- intensify-0.2.0/intensify/core/processes/hawkes.py +372 -0
- intensify-0.2.0/intensify/core/processes/marked_hawkes.py +233 -0
- intensify-0.2.0/intensify/core/processes/nonlinear_hawkes.py +279 -0
- intensify-0.2.0/intensify/core/processes/poisson.py +373 -0
- intensify-0.2.0/intensify/core/regularizers.py +55 -0
- intensify-0.2.0/intensify/core/simulation/__init__.py +17 -0
- intensify-0.2.0/intensify/core/simulation/cluster.py +142 -0
- intensify-0.2.0/intensify/core/simulation/thinning.py +249 -0
- intensify-0.2.0/intensify/py.typed +0 -0
- intensify-0.2.0/intensify/visualization/__init__.py +14 -0
- intensify-0.2.0/intensify/visualization/connectivity.py +84 -0
- intensify-0.2.0/intensify/visualization/event_histograms.py +106 -0
- intensify-0.2.0/intensify/visualization/intensity.py +102 -0
- intensify-0.2.0/intensify/visualization/kernels.py +70 -0
- intensify-0.2.0/pyproject.toml +114 -0
- intensify-0.2.0/tests/__init__.py +1 -0
- intensify-0.2.0/tests/conftest.py +28 -0
- intensify-0.2.0/tests/test_backends.py +35 -0
- intensify-0.2.0/tests/test_cluster.py +28 -0
- intensify-0.2.0/tests/test_cox.py +57 -0
- intensify-0.2.0/tests/test_diagnostics.py +76 -0
- intensify-0.2.0/tests/test_edge_cases.py +111 -0
- intensify-0.2.0/tests/test_em.py +31 -0
- intensify-0.2.0/tests/test_hawkes.py +95 -0
- intensify-0.2.0/tests/test_inhomogeneous_poisson.py +37 -0
- intensify-0.2.0/tests/test_jit.py +430 -0
- intensify-0.2.0/tests/test_jit_integration.py +637 -0
- intensify-0.2.0/tests/test_kernels.py +71 -0
- intensify-0.2.0/tests/test_mle_kernel_expansion.py +106 -0
- intensify-0.2.0/tests/test_multivariate_hawkes.py +93 -0
- intensify-0.2.0/tests/test_plan_phases.py +346 -0
- intensify-0.2.0/tests/test_poisson.py +57 -0
- intensify-0.2.0/tests/test_real_data_stress.py +1052 -0
- intensify-0.2.0/tests/test_remaining_kernels.py +139 -0
- intensify-0.2.0/tests/test_simulation.py +33 -0
- intensify-0.2.0/tests/test_textbook_cases.py +112 -0
- intensify-0.2.0/tests/test_visualization.py +51 -0
- intensify-0.2.0/tutorials/01_basic_hawkes.ipynb +32 -0
- intensify-0.2.0/tutorials/02_multivariate.ipynb +44 -0
- intensify-0.2.0/tutorials/03_marked_and_online.ipynb +38 -0
- intensify-0.2.0/tutorials/04_connectivity_and_nonlinear.ipynb +36 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something doesn't work as documented.
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for taking the time to file a bug report. A minimal,
|
|
9
|
+
reproducible example is the fastest path to a fix.
|
|
10
|
+
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: reproducer
|
|
13
|
+
attributes:
|
|
14
|
+
label: Minimal reproducer
|
|
15
|
+
description: Self-contained Python snippet that demonstrates the bug.
|
|
16
|
+
render: python
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: expected
|
|
22
|
+
attributes:
|
|
23
|
+
label: Expected vs observed
|
|
24
|
+
description: What you expected to happen, and what actually happened.
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
|
|
28
|
+
- type: textarea
|
|
29
|
+
id: traceback
|
|
30
|
+
attributes:
|
|
31
|
+
label: Full traceback (if any)
|
|
32
|
+
render: text
|
|
33
|
+
|
|
34
|
+
- type: input
|
|
35
|
+
id: version
|
|
36
|
+
attributes:
|
|
37
|
+
label: intensify version
|
|
38
|
+
placeholder: "`python -c 'import intensify; print(intensify.__version__)'`"
|
|
39
|
+
validations:
|
|
40
|
+
required: true
|
|
41
|
+
|
|
42
|
+
- type: input
|
|
43
|
+
id: python
|
|
44
|
+
attributes:
|
|
45
|
+
label: Python version
|
|
46
|
+
placeholder: "3.12.2"
|
|
47
|
+
validations:
|
|
48
|
+
required: true
|
|
49
|
+
|
|
50
|
+
- type: dropdown
|
|
51
|
+
id: backend
|
|
52
|
+
attributes:
|
|
53
|
+
label: Active backend
|
|
54
|
+
options: [jax, numpy]
|
|
55
|
+
validations:
|
|
56
|
+
required: true
|
|
57
|
+
|
|
58
|
+
- type: input
|
|
59
|
+
id: os
|
|
60
|
+
attributes:
|
|
61
|
+
label: OS
|
|
62
|
+
placeholder: "Ubuntu 22.04 / macOS 14 / Windows 11"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest a new feature or capability.
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: What problem does this solve?
|
|
9
|
+
description: Describe the use case, not just the desired API.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: proposal
|
|
15
|
+
attributes:
|
|
16
|
+
label: Proposed solution
|
|
17
|
+
description: A sketch of the API or implementation.
|
|
18
|
+
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: alternatives
|
|
21
|
+
attributes:
|
|
22
|
+
label: Alternatives considered
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR do and why? 1-3 sentences. -->
|
|
4
|
+
|
|
5
|
+
## Changes
|
|
6
|
+
|
|
7
|
+
<!-- Bulleted list of the concrete changes. -->
|
|
8
|
+
|
|
9
|
+
## Checklist
|
|
10
|
+
|
|
11
|
+
- [ ] Tests added or updated (and pass locally)
|
|
12
|
+
- [ ] `ruff check intensify tests` clean
|
|
13
|
+
- [ ] Public API changes documented in `CHANGELOG.md` under `## [Unreleased]`
|
|
14
|
+
- [ ] Math changes cite a paper or textbook in docstrings / comments
|
|
15
|
+
- [ ] Breaking change? Call it out clearly above
|
|
16
|
+
|
|
17
|
+
## Related issues
|
|
18
|
+
|
|
19
|
+
Closes #
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
16
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
cache: 'pip'
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
pip install hatch
|
|
31
|
+
hatch env create
|
|
32
|
+
|
|
33
|
+
- name: Lint with ruff
|
|
34
|
+
run: hatch run lint:check
|
|
35
|
+
|
|
36
|
+
- name: Test with pytest
|
|
37
|
+
run: hatch run pytest:test
|
|
38
|
+
|
|
39
|
+
typecheck:
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
|
|
44
|
+
- name: Set up Python
|
|
45
|
+
uses: actions/setup-python@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.12"
|
|
48
|
+
|
|
49
|
+
- name: Install dependencies
|
|
50
|
+
run: |
|
|
51
|
+
python -m pip install --upgrade pip
|
|
52
|
+
pip install -e ".[dev]" mypy
|
|
53
|
+
|
|
54
|
+
- name: mypy
|
|
55
|
+
run: mypy intensify --ignore-missing-imports --no-strict-optional || true
|
|
56
|
+
|
|
57
|
+
docs:
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v4
|
|
61
|
+
|
|
62
|
+
- name: Set up Python
|
|
63
|
+
uses: actions/setup-python@v5
|
|
64
|
+
with:
|
|
65
|
+
python-version: "3.12"
|
|
66
|
+
|
|
67
|
+
- name: Install dependencies
|
|
68
|
+
run: |
|
|
69
|
+
python -m pip install --upgrade pip
|
|
70
|
+
pip install hatch
|
|
71
|
+
pip install -e ".[docs]"
|
|
72
|
+
|
|
73
|
+
- name: Build docs
|
|
74
|
+
run: sphinx-build -W -b html docs docs/_build/html
|
|
75
|
+
|
|
76
|
+
- uses: actions/upload-artifact@v4
|
|
77
|
+
with:
|
|
78
|
+
name: docs-html
|
|
79
|
+
path: docs/_build/html
|
|
80
|
+
|
|
81
|
+
readme-doctest:
|
|
82
|
+
runs-on: ubuntu-latest
|
|
83
|
+
steps:
|
|
84
|
+
- uses: actions/checkout@v4
|
|
85
|
+
- uses: actions/setup-python@v5
|
|
86
|
+
with:
|
|
87
|
+
python-version: "3.12"
|
|
88
|
+
- name: Install
|
|
89
|
+
run: |
|
|
90
|
+
python -m pip install --upgrade pip
|
|
91
|
+
pip install -e ".[dev]"
|
|
92
|
+
- name: Doctest README
|
|
93
|
+
env:
|
|
94
|
+
MPLBACKEND: Agg
|
|
95
|
+
run: |
|
|
96
|
+
python -c "
|
|
97
|
+
import os, re, sys, subprocess
|
|
98
|
+
src = open('README.md').read()
|
|
99
|
+
blocks = re.findall(r'\`\`\`python\n(.*?)\n\`\`\`', src, flags=re.S)
|
|
100
|
+
if not blocks:
|
|
101
|
+
print('No python blocks found in README'); sys.exit(0)
|
|
102
|
+
code = blocks[0]
|
|
103
|
+
print('Running README quickstart block...')
|
|
104
|
+
env = dict(os.environ, MPLBACKEND='Agg')
|
|
105
|
+
subprocess.check_call([sys.executable, '-c', code], env=env)
|
|
106
|
+
"
|
|
107
|
+
|
|
108
|
+
build:
|
|
109
|
+
runs-on: ubuntu-latest
|
|
110
|
+
needs: [test, typecheck, docs]
|
|
111
|
+
if: github.ref == 'refs/heads/main'
|
|
112
|
+
|
|
113
|
+
steps:
|
|
114
|
+
- uses: actions/checkout@v4
|
|
115
|
+
|
|
116
|
+
- name: Set up Python
|
|
117
|
+
uses: actions/setup-python@v5
|
|
118
|
+
with:
|
|
119
|
+
python-version: "3.12"
|
|
120
|
+
|
|
121
|
+
- name: Build distribution
|
|
122
|
+
run: |
|
|
123
|
+
pip install hatch
|
|
124
|
+
hatch build
|
|
125
|
+
|
|
126
|
+
- uses: actions/upload-artifact@v4
|
|
127
|
+
with:
|
|
128
|
+
name: dist
|
|
129
|
+
path: dist/*
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*.*.*"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build-and-publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
environment:
|
|
11
|
+
name: pypi
|
|
12
|
+
url: https://pypi.org/project/intensify/
|
|
13
|
+
permissions:
|
|
14
|
+
id-token: write # OIDC trusted publishing
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
|
|
23
|
+
- name: Build sdist + wheel
|
|
24
|
+
run: |
|
|
25
|
+
python -m pip install --upgrade pip hatch
|
|
26
|
+
hatch build
|
|
27
|
+
|
|
28
|
+
- name: Sanity-check artifacts
|
|
29
|
+
run: |
|
|
30
|
+
ls -la dist/
|
|
31
|
+
python -m pip install twine
|
|
32
|
+
python -m twine check dist/*
|
|
33
|
+
|
|
34
|
+
- name: Publish to PyPI
|
|
35
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
36
|
+
with:
|
|
37
|
+
packages-dir: dist/
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
env/
|
|
8
|
+
venv/
|
|
9
|
+
.venv/
|
|
10
|
+
env.bak/
|
|
11
|
+
venv.bak/
|
|
12
|
+
|
|
13
|
+
# IDEs
|
|
14
|
+
.vscode/
|
|
15
|
+
.idea/
|
|
16
|
+
*.swp
|
|
17
|
+
*.swo
|
|
18
|
+
*~
|
|
19
|
+
|
|
20
|
+
# Distribution / packaging
|
|
21
|
+
dist/
|
|
22
|
+
build/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
*.egg
|
|
25
|
+
manifest.in
|
|
26
|
+
wheels/
|
|
27
|
+
|
|
28
|
+
# Testing
|
|
29
|
+
.pytest_cache/
|
|
30
|
+
.coverage
|
|
31
|
+
htmlcov/
|
|
32
|
+
nosetests.xml
|
|
33
|
+
coverage.xml
|
|
34
|
+
*.cover
|
|
35
|
+
|
|
36
|
+
# Project-specific
|
|
37
|
+
*.db
|
|
38
|
+
*.sqlite
|
|
39
|
+
data/
|
|
40
|
+
results/
|
|
41
|
+
.DS_Store
|
|
42
|
+
|
|
43
|
+
# JAX
|
|
44
|
+
.jax/
|
|
45
|
+
|
|
46
|
+
# Sphinx build output
|
|
47
|
+
docs/_build/
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.11.2
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
|
|
9
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
10
|
+
rev: v4.6.0
|
|
11
|
+
hooks:
|
|
12
|
+
- id: check-yaml
|
|
13
|
+
- id: check-toml
|
|
14
|
+
- id: check-added-large-files
|
|
15
|
+
args: ["--maxkb=1000"]
|
|
16
|
+
- id: end-of-file-fixer
|
|
17
|
+
- id: trailing-whitespace
|
|
18
|
+
- id: mixed-line-ending
|
|
19
|
+
|
|
20
|
+
- repo: https://github.com/codespell-project/codespell
|
|
21
|
+
rev: v2.3.0
|
|
22
|
+
hooks:
|
|
23
|
+
- id: codespell
|
|
24
|
+
args: ["--skip=*.ipynb,coverage.xml,.venv,docs/_build"]
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `intensify` are documented here.
|
|
4
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
|
|
5
|
+
this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- `MLEInference.fit(..., fit_decay=False)` — locks every β slot in the
|
|
11
|
+
flat parameter vector to its initial value via a zero-width L-BFGS-B
|
|
12
|
+
bound. Reduces the active parameter count, speeds up the fit, and
|
|
13
|
+
matches the problem `tick.HawkesExpKern` solves (β supplied as
|
|
14
|
+
input). Supported for `ExponentialKernel` and `SumExponentialKernel`
|
|
15
|
+
in univariate, marked, nonlinear, and multivariate paths. Raises
|
|
16
|
+
`TypeError` for kernels without an identifiable decay-rate axis
|
|
17
|
+
(`PowerLawKernel.beta` is a tail exponent, not a decay rate).
|
|
18
|
+
- **Scaling-study benchmarks** in `docs/scaling.md` showing
|
|
19
|
+
`mv_exp_5d` fit time vs N from 501 to 91,249 total events. Both
|
|
20
|
+
intensify and tick scale linearly; the ~10× wall-clock ratio is
|
|
21
|
+
stable across the whole range (it does not grow at scale);
|
|
22
|
+
parameter-recovery RMSE is statistically indistinguishable by
|
|
23
|
+
N≈10k. Reproducible via `benchmarks/run_scaling.py`.
|
|
24
|
+
- **O(N·M) recursive multivariate neg-log-likelihood** for the
|
|
25
|
+
shared-β exp-Hawkes case (every β_{m,k} the same scalar), cached
|
|
26
|
+
per `M`. Auto-selected by `_fit_multivariate_numpy` when
|
|
27
|
+
`fit_decay=False` and the kernel matrix has a shared β. Replaces the
|
|
28
|
+
dense O(N²) lag matrix with a `jax.lax.scan` carrying an M-vector
|
|
29
|
+
state per source dim. For `mv_exp_5d` (N=1099, M=5): ~220× fewer
|
|
30
|
+
compute steps, **17 ms fits vs 200 ms** on the same problem.
|
|
31
|
+
Per-cell β still falls back to the dense path.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
- **Correctness (critical, multivariate Hawkes likelihood)**:
|
|
35
|
+
`MultivariateHawkes._log_likelihood_dim` summed `log λ_m(t)` over
|
|
36
|
+
every event in the system, then summed across `m` — an `M`-fold
|
|
37
|
+
overcounting of the log-intensity term. The textbook likelihood is
|
|
38
|
+
`Σ_n log λ_{k_n}(t_n) − Σ_m Λ_m(T)`, i.e. each event contributes
|
|
39
|
+
`log` of its own *source* dim's intensity exactly once. Verified
|
|
40
|
+
against a hand-computed reference on a 2-d sim (current −63.0 vs
|
|
41
|
+
correct −44.4 on an identical data set). Fix causes multivariate MLE
|
|
42
|
+
parameter RMSE on the `mv_exp_5d` benchmark to drop from 0.167 → ~0.1,
|
|
43
|
+
now within 2× of tick on the same data. This bug was silently
|
|
44
|
+
affecting every multivariate Hawkes fit since the library's
|
|
45
|
+
inception.
|
|
46
|
+
- **Performance (univariate JAX MLE)**: each fit was paying ~370 ms on
|
|
47
|
+
fresh JIT compilation because `_make_jit_neg_loglik_*` returned a new
|
|
48
|
+
`@jax.jit`-decorated closure per call (closing over `events_jax` /
|
|
49
|
+
`T_jax`). JAX caches by function identity, so the trace was
|
|
50
|
+
recompiled every fit. The neg-log-likelihood functions are now lifted
|
|
51
|
+
to module scope and the `value+grad` / Hessian closures are cached by
|
|
52
|
+
`(kernel kind, n_components, r)`. Result: `uni_exp_small` fit dropped
|
|
53
|
+
from **376 ms → 5 ms** steady-state (~75× faster), bringing univariate
|
|
54
|
+
intensify within ~5× of `tick.HawkesExpKern` on the same data while
|
|
55
|
+
still fitting the decay rate jointly.
|
|
56
|
+
- **Performance (multivariate JAX MLE)**: `_fit_multivariate_numpy` now
|
|
57
|
+
has a JAX-JIT fast path for the all-`ExponentialKernel` case
|
|
58
|
+
(indirectly required by the flat-vector parameter layout already).
|
|
59
|
+
Uses a dense N×N causal lag matrix with gathered per-pair
|
|
60
|
+
`(α_mk, β_mk)` from `(source_i, source_j)` indexing, and caches the
|
|
61
|
+
compiled `value+grad` per `M`. Multivariate `mv_exp_5d` fit dropped
|
|
62
|
+
**77 s → 1.1 s** (~70× faster). Mixed-kernel multivariate matrices
|
|
63
|
+
still take the numpy fallback path (unchanged).
|
|
64
|
+
- Pre-0.2.0 callers of `_make_jit_neg_loglik_exp` /
|
|
65
|
+
`_make_jit_neg_loglik_sum_exp` / `_make_jit_neg_loglik_power_law` /
|
|
66
|
+
`_make_jit_neg_loglik_approx_pl` and the old
|
|
67
|
+
`_jax_hessian_std_errors(neg_ll_fn, x_opt, names)` signature still
|
|
68
|
+
work — they're shimmed to the cached implementation.
|
|
69
|
+
|
|
70
|
+
## [0.2.0] - 2026-04-20
|
|
71
|
+
|
|
72
|
+
Public launch release. Consolidates correctness, API polish, and the
|
|
73
|
+
full documentation, CI, and scientific-credibility scaffolding needed
|
|
74
|
+
for lab adoption. Includes verified head-to-head benchmarks vs
|
|
75
|
+
[tick](https://github.com/X-DataInitiative/tick).
|
|
76
|
+
|
|
77
|
+
### Fixed
|
|
78
|
+
- **Correctness (critical)**: `_recursive_compensators` in the time-rescaling
|
|
79
|
+
diagnostic had incorrect math for `ExponentialKernel` /
|
|
80
|
+
`SumExponentialKernel` — the computed cumulative intensities were off by a
|
|
81
|
+
factor of β, causing KS p-values to be catastrophically small under
|
|
82
|
+
well-specified models. Replaced with the correct recursion (equivalent
|
|
83
|
+
to the verified general pairwise-integral path, but O(N) instead of
|
|
84
|
+
O(N²)). Unknown recursive kernels now fall back to the general path
|
|
85
|
+
rather than applying the buggy formula. Before this fix the fast path of
|
|
86
|
+
`time_rescaling_test` and `qq_plot` produced wrong p-values for every
|
|
87
|
+
exponential-family Hawkes fit.
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
- `benchmarks/` with README, `reference_dataset.py`, `run_intensify.py`,
|
|
91
|
+
`run_tick.py`, and verified head-to-head results in
|
|
92
|
+
`docs/benchmarks.md`. Datasets use portable `.npy`+`.json` pairs so the
|
|
93
|
+
same files work across NumPy 1.x and 2.x environments. pyhawkes was
|
|
94
|
+
evaluated and dropped (transitive deps reference
|
|
95
|
+
`scipy.misc.logsumexp`, removed in SciPy 1.0).
|
|
96
|
+
- `tests/test_textbook_cases.py`: parameter-recovery on seeded simulations,
|
|
97
|
+
log-likelihood scaling, well-specified-vs-misspecified KS sanity check.
|
|
98
|
+
- Community infrastructure: `CITATION.cff`, `CONTRIBUTING.md`,
|
|
99
|
+
`CODE_OF_CONDUCT.md`, `SECURITY.md`, GitHub issue + PR templates.
|
|
100
|
+
- Documentation: expanded `docs/getting_started.md` with regularization
|
|
101
|
+
shorthand, backend-switching, and input-validation notes; new
|
|
102
|
+
`docs/user_guide/diagnostics.md` covering the (corrected) time-rescaling
|
|
103
|
+
theorem; new `docs/user_guide/simulation.md`; kernel-coverage table in
|
|
104
|
+
`docs/user_guide/inference.md`.
|
|
105
|
+
- README rewrite: PyPI / Python / license / CI badges, "Why intensify?"
|
|
106
|
+
comparison vs `tick` and `pyhawkes`, citation block, doc links.
|
|
107
|
+
- CI: multi-OS matrix (ubuntu / macOS / windows), mypy job, Sphinx
|
|
108
|
+
docs-build job with `-W` treat-warnings-as-errors, README-quickstart
|
|
109
|
+
doctest job (`MPLBACKEND=Agg`), PyPI publish workflow on tags using
|
|
110
|
+
OIDC trusted publishing.
|
|
111
|
+
- Pre-commit: `codespell`, `check-yaml`, `check-toml`,
|
|
112
|
+
`check-added-large-files`, `end-of-file-fixer`, `trailing-whitespace`,
|
|
113
|
+
`mixed-line-ending`.
|
|
114
|
+
|
|
115
|
+
## [0.1.1] - 2026-04-19
|
|
116
|
+
|
|
117
|
+
API-consistency release. No correctness changes; surface-area polish.
|
|
118
|
+
|
|
119
|
+
### Added
|
|
120
|
+
- `MarkedHawkes` and `NonlinearHawkes` MLE now support every kernel type
|
|
121
|
+
the univariate helpers understand: `ExponentialKernel` (signed and
|
|
122
|
+
unsigned), `SumExponentialKernel`, `PowerLawKernel`, `ApproxPowerLawKernel`,
|
|
123
|
+
`NonparametricKernel`. Previously both processes raised
|
|
124
|
+
`NotImplementedError` for anything other than unsigned `ExponentialKernel`.
|
|
125
|
+
- `regularization="l1"` / `"elasticnet"` string shorthand accepted by
|
|
126
|
+
`MLEInference.fit`, resolving to default `L1()` / `ElasticNet()`.
|
|
127
|
+
Instances still pass through unchanged.
|
|
128
|
+
- Backend proxy: `get_backend()` returns a lazy proxy that delegates every
|
|
129
|
+
attribute to the currently active backend. Module-level
|
|
130
|
+
`bt = get_backend()` captures now pick up runtime `set_backend()` switches.
|
|
131
|
+
- `tests/test_mle_kernel_expansion.py`: parametric regression suite for the
|
|
132
|
+
expanded MLE kernel surface + regularization shorthand + backend proxy.
|
|
133
|
+
|
|
134
|
+
### Changed
|
|
135
|
+
- `hawkes_mle_bounds` and `hawkes_mle_apply_vector` now preserve
|
|
136
|
+
`ExponentialKernel.allow_signed` so signed kernels round-trip through MLE
|
|
137
|
+
correctly when reused by `NonlinearHawkes`.
|
|
138
|
+
|
|
139
|
+
### Fixed
|
|
140
|
+
- Pre-existing test/spec mismatches aligned with documented behavior:
|
|
141
|
+
`endogeneity_index` saturates at 1.0 at critical branching (per docstring);
|
|
142
|
+
`FitResult.connectivity_matrix()` raises `TypeError` (not `ValueError`)
|
|
143
|
+
when called on a non-multivariate process — test expectations updated.
|
|
144
|
+
|
|
145
|
+
## [0.1.0] - 2026-04-19
|
|
146
|
+
|
|
147
|
+
First versioned release. Focus: correctness on real data, stable packaging.
|
|
148
|
+
|
|
149
|
+
### Added
|
|
150
|
+
- `__version__` attribute on the top-level package.
|
|
151
|
+
- `py.typed` marker for PEP 561 type-checker support.
|
|
152
|
+
- `Kernel.scale(factor)` method on all built-in kernels so
|
|
153
|
+
`project_params` can enforce stationarity uniformly across kernel types
|
|
154
|
+
(`ExponentialKernel`, `SumExponentialKernel`, `PowerLawKernel`,
|
|
155
|
+
`ApproxPowerLawKernel`, `NonparametricKernel`).
|
|
156
|
+
- `RuntimeWarning` emitted from every MLE fit path when the SciPy optimizer
|
|
157
|
+
does not converge — previously only the multivariate path warned.
|
|
158
|
+
- `RuntimeWarning` when the fitted multivariate Hawkes spectral radius
|
|
159
|
+
remains ≥ 1 after projection (non-stationary fit).
|
|
160
|
+
- Minimum-version pins on all runtime dependencies (`numpy>=1.24`,
|
|
161
|
+
`jax>=0.4.20`, `scipy>=1.11`, `optax>=0.1.7`, `matplotlib>=3.7`).
|
|
162
|
+
- Project URLs: Documentation, Issues, Changelog.
|
|
163
|
+
- Classifiers: `Operating System :: OS Independent`,
|
|
164
|
+
`Topic :: Scientific/Engineering :: Mathematics`, `Typing :: Typed`.
|
|
165
|
+
|
|
166
|
+
### Changed
|
|
167
|
+
- `UnivariateHawkes.project_params` and `MultivariateHawkes.project_params`
|
|
168
|
+
now use `Kernel.scale()`, so non-`alpha` kernels (e.g. `SumExponentialKernel`,
|
|
169
|
+
`NonparametricKernel`) are actually projected instead of silently skipped.
|
|
170
|
+
- Version bumped from `0.1.0-alpha` to `0.1.0`.
|
|
171
|
+
|
|
172
|
+
### Fixed
|
|
173
|
+
- Replaced runtime-validation `assert` statements in
|
|
174
|
+
`intensify/core/kernels/nonparametric.py` and
|
|
175
|
+
`intensify/core/processes/marked_hawkes.py` with explicit `ValueError` /
|
|
176
|
+
`RuntimeError` raises. Asserts are stripped under `python -O` and previously
|
|
177
|
+
hid real errors.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use intensify in your research, please cite it as below."
|
|
3
|
+
title: "intensify: A modern Python point process library with deep Hawkes specialization"
|
|
4
|
+
abstract: >-
|
|
5
|
+
intensify is an open-source Python library for simulating, fitting, and
|
|
6
|
+
diagnosing point process models — with emphasis on Hawkes processes for
|
|
7
|
+
quantitative finance and computational neuroscience. It provides
|
|
8
|
+
univariate, multivariate, marked, and nonlinear Hawkes variants; a
|
|
9
|
+
pluggable kernel family (exponential, sum-of-exponentials, power-law,
|
|
10
|
+
approximate power-law, nonparametric); MLE inference with JAX autodiff
|
|
11
|
+
and a NumPy fallback; and goodness-of-fit tooling based on the
|
|
12
|
+
time-rescaling theorem.
|
|
13
|
+
type: software
|
|
14
|
+
authors:
|
|
15
|
+
- family-names: Hill
|
|
16
|
+
given-names: Matthew
|
|
17
|
+
license: MIT
|
|
18
|
+
repository-code: "https://github.com/hillmatt7/intensify"
|
|
19
|
+
url: "https://hillmatt7.github.io/intensify"
|
|
20
|
+
version: 0.2.0
|
|
21
|
+
date-released: "2026-04-19"
|
|
22
|
+
keywords:
|
|
23
|
+
- point-process
|
|
24
|
+
- hawkes-process
|
|
25
|
+
- self-exciting
|
|
26
|
+
- maximum-likelihood
|
|
27
|
+
- jax
|
|
28
|
+
- quantitative-finance
|
|
29
|
+
- computational-neuroscience
|
|
30
|
+
- time-rescaling
|
|
31
|
+
preferred-citation:
|
|
32
|
+
type: software
|
|
33
|
+
authors:
|
|
34
|
+
- family-names: Hill
|
|
35
|
+
given-names: Matthew
|
|
36
|
+
title: "intensify: A modern Python point process library with deep Hawkes specialization"
|
|
37
|
+
year: 2026
|
|
38
|
+
url: "https://github.com/hillmatt7/intensify"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in
|
|
6
|
+
the `intensify` community a harassment-free experience for everyone,
|
|
7
|
+
regardless of age, body size, visible or invisible disability, ethnicity,
|
|
8
|
+
sex characteristics, gender identity and expression, level of experience,
|
|
9
|
+
education, socio-economic status, nationality, personal appearance, race,
|
|
10
|
+
caste, color, religion, or sexual identity and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment:
|
|
18
|
+
|
|
19
|
+
- Demonstrating empathy and kindness toward other people.
|
|
20
|
+
- Being respectful of differing opinions, viewpoints, and experiences.
|
|
21
|
+
- Giving and gracefully accepting constructive feedback.
|
|
22
|
+
- Taking responsibility and apologizing to those affected by our mistakes.
|
|
23
|
+
- Focusing on what is best not just for us as individuals but for the
|
|
24
|
+
overall community.
|
|
25
|
+
|
|
26
|
+
Examples of unacceptable behavior:
|
|
27
|
+
|
|
28
|
+
- Sexualized language or imagery; sexual attention or advances of any kind.
|
|
29
|
+
- Trolling, insulting or derogatory comments, personal or political attacks.
|
|
30
|
+
- Public or private harassment.
|
|
31
|
+
- Publishing others' private information without explicit permission.
|
|
32
|
+
- Other conduct that could reasonably be considered inappropriate in a
|
|
33
|
+
professional setting.
|
|
34
|
+
|
|
35
|
+
## Enforcement
|
|
36
|
+
|
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
38
|
+
reported to the maintainers via GitHub's private security advisory channel
|
|
39
|
+
or by email. All complaints will be reviewed and investigated promptly and
|
|
40
|
+
fairly.
|
|
41
|
+
|
|
42
|
+
This Code of Conduct is adapted from the
|
|
43
|
+
[Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Contributing to intensify
|
|
2
|
+
|
|
3
|
+
Thank you for considering a contribution. This project aims to be a reliable,
|
|
4
|
+
well-tested building block for point-process research in labs and industry.
|
|
5
|
+
|
|
6
|
+
## Ground rules
|
|
7
|
+
|
|
8
|
+
- **Correctness first.** Every numerical change should ship with a test that
|
|
9
|
+
asserts the quantity it affects, not just that the code runs.
|
|
10
|
+
- **No silent fallbacks.** If a code path can produce a wrong answer under
|
|
11
|
+
certain conditions (non-stationary fit, degenerate data, optimizer stall),
|
|
12
|
+
surface it as a `warning` or `raise`, never as a silent sentinel.
|
|
13
|
+
- **Backend-agnostic.** Anything under `intensify/core/` must work with
|
|
14
|
+
both the JAX and NumPy backends. Use `from ...backends import get_backend`
|
|
15
|
+
and call backend methods through the returned proxy.
|
|
16
|
+
|
|
17
|
+
## Development setup
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/hillmatt7/intensify
|
|
21
|
+
cd intensify
|
|
22
|
+
|
|
23
|
+
# Create a virtualenv and install with dev extras
|
|
24
|
+
python -m venv .venv
|
|
25
|
+
source .venv/bin/activate
|
|
26
|
+
pip install -e ".[dev,docs]"
|
|
27
|
+
|
|
28
|
+
pre-commit install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Running checks
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Lint + format
|
|
35
|
+
hatch run lint:check
|
|
36
|
+
|
|
37
|
+
# Tests (with coverage)
|
|
38
|
+
pytest tests/
|
|
39
|
+
|
|
40
|
+
# Docs
|
|
41
|
+
hatch run docs:build
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Pull request checklist
|
|
45
|
+
|
|
46
|
+
- [ ] Tests cover the new or changed behavior.
|
|
47
|
+
- [ ] `pytest tests/` passes locally (no new warnings unless intentional).
|
|
48
|
+
- [ ] `ruff check intensify tests` is clean.
|
|
49
|
+
- [ ] Public API changes are documented in `CHANGELOG.md` under `## [Unreleased]`.
|
|
50
|
+
- [ ] If you changed math, a citation (paper or textbook chapter) appears in
|
|
51
|
+
the docstring or in-line comment.
|
|
52
|
+
|
|
53
|
+
## Reporting bugs
|
|
54
|
+
|
|
55
|
+
Open an issue at
|
|
56
|
+
<https://github.com/hillmatt7/intensify/issues/new/choose>.
|
|
57
|
+
Please include a minimal reproducer, the observed vs expected behavior,
|
|
58
|
+
your Python version, `intensify.__version__`, and the active backend
|
|
59
|
+
(`intensify.get_backend_name()`).
|
|
60
|
+
|
|
61
|
+
## Security
|
|
62
|
+
|
|
63
|
+
See [`SECURITY.md`](SECURITY.md) for reporting security issues privately.
|
|
64
|
+
|
|
65
|
+
## Community
|
|
66
|
+
|
|
67
|
+
This project follows the [Contributor Covenant](CODE_OF_CONDUCT.md). By
|
|
68
|
+
participating you agree to uphold it.
|