From da8e56c3bf7a639736fb800c93dd9d4781c41608 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Thu, 30 Jan 2025 21:07:49 +0200 Subject: [PATCH 1/9] Add ruff configuration --- .editorconfig | 1 + pyproject.toml | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/.editorconfig b/.editorconfig index 8d3905d..e269037 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,7 @@ root = true [*] end_of_line = lf insert_final_newline = true +trim_trailing_whitespace = false # Matches multiple files with brace expansion notation # Set default charset diff --git a/pyproject.toml b/pyproject.toml index 375a28e..5e8f313 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,3 +57,46 @@ jitcsde = [ write_to = "jitcsde/version.py" local_scheme = "no-local-version" +[tool.ruff] +target-version = "py37" +line-length = 320 + +[tool.ruff.lint] +select = [ + "A", # flake8-builtins + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "E", # flake8 + "F", # flake8 + "I", # flake8-isort + "NPY", # numpy + "Q", # flake8-quotes + "RUF", # ruff + "UP", # pyupgrade + "W", # flake8 +] +ignore = [ + "A001", # shadowing-builtin-variable + "A005", # shadowing-builtin-module + "C409", # incorrectly-parenthesized-tuple-in-subscript + "E203", # whitespace-before-punctuation + "E402", # module-import-not-at-top-of-file + "E501", # line-too-long + "E731", # assign-to-lambda + "RUF001", # ambiguous-unicode-character-string + "RUF002", # ambiguous-unicode-character-docstring + "RUF003", # ambiguous-unicode-character-comment + "W191", # indentation-contains-tabs + "W293", # blank-line-with-whitespace +] + +[tool.ruff.lint.flake8-quotes] +docstring-quotes = "double" +inline-quotes = "double" +multiline-quotes = "double" + +[tool.ruff.lint.isort] +combine-as-imports = true +known-local-folder = [ "jitcsde" ] +known-first-party = [ "jitcxde_common" ] +lines-after-imports = 2 From 0b44b53494d7c2bbfc21d7aab71a24e29597092c Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Thu, 30 Jan 2025 21:08:52 +0200 Subject: [PATCH 2/9] Add ruff CI job --- .github/workflows/ci.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 24b728d..e768a00 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,20 @@ concurrency: cancel-in-progress: true jobs: + typos: + name: Spelling (typos) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: crate-ci/typos@master + + ruff: + name: Linting (ruff) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 + test: name: Unittest (${{ matrix.os }}-${{ matrix.compiler }}-py${{ matrix.python-version }}) runs-on: ${{ matrix.os }} From 8a6a5a14f7367afcbe5965348a861e94fb752a70 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Thu, 30 Jan 2025 21:09:35 +0200 Subject: [PATCH 3/9] Fix ruff I (isort) errors --- docs/conf.py | 4 +++- examples/noisy_and_jumpy_lorenz.py | 3 ++- examples/noisy_lorenz.py | 3 ++- jitcsde/__init__.py | 8 ++------ jitcsde/_jitcsde.py | 17 ++++++++++------- jitcsde/_python_core.py | 4 +++- jitcsde/sympy_symbols.py | 1 + tests/Butcher.py | 3 ++- tests/Butcher_SRA.py | 1 + tests/compare_C_and_Python_core.py | 6 +++--- tests/kmc.py | 4 +++- tests/test_integration_speed.py | 6 ++++-- tests/test_jitcsde.py | 11 +++++++---- tests/test_jumps.py | 11 +++++++---- tests/test_python_core.py | 7 +++++-- tests/test_step_functions.py | 12 +++++++----- tests/test_sympy_input.py | 9 ++++++--- tests/validation.py | 6 ++++-- 18 files changed, 72 insertions(+), 44 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index b226c7d..c458187 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,8 +1,10 @@ -import sys import os +import sys from unittest.mock import MagicMock as Mock + from setuptools_scm import get_version + MOCK_MODULES = [ 'numpy', 'numpy.testing', 'numpy.random', 'symengine', 'symengine.printing', 'symengine.lib.symengine_wrapper', diff --git a/examples/noisy_and_jumpy_lorenz.py b/examples/noisy_and_jumpy_lorenz.py index b7e04d8..0c9e962 100644 --- a/examples/noisy_and_jumpy_lorenz.py +++ b/examples/noisy_and_jumpy_lorenz.py @@ -29,9 +29,10 @@ """ if __name__ == "__main__": - from jitcsde import y, jitcsde_jump import numpy import symengine + + from jitcsde import jitcsde_jump, y ρ = 28 σ = 10 diff --git a/examples/noisy_lorenz.py b/examples/noisy_lorenz.py index b14f3e2..adba3fa 100644 --- a/examples/noisy_lorenz.py +++ b/examples/noisy_lorenz.py @@ -72,9 +72,10 @@ """ if __name__ == "__main__": - from jitcsde import y, jitcsde import numpy import symengine + + from jitcsde import jitcsde, y ρ = 28 σ = 10 diff --git a/jitcsde/__init__.py b/jitcsde/__init__.py index e74166e..dee6933 100644 --- a/jitcsde/__init__.py +++ b/jitcsde/__init__.py @@ -1,9 +1,5 @@ -from ._jitcsde import ( - jitcsde, jitcsde_jump, - t, y, - UnsuccessfulIntegration, - test - ) +from ._jitcsde import UnsuccessfulIntegration, jitcsde, jitcsde_jump, t, test, y + try: from .version import version as __version__ diff --git a/jitcsde/_jitcsde.py b/jitcsde/_jitcsde.py index 9346160..987c4ca 100644 --- a/jitcsde/_jitcsde.py +++ b/jitcsde/_jitcsde.py @@ -1,17 +1,20 @@ #!/usr/bin/python3 # -*- coding: utf-8 -*- -from warnings import warn -from itertools import count, chain -from os import path as path -import shutil import random -import symengine +import shutil +from itertools import chain, count +from os import path as path +from warnings import warn + import numpy as np -from jitcxde_common import jitcxde, checker -from jitcxde_common.helpers import sort_helpers, sympify_helpers, copy_helpers, filter_helpers, find_dependent_helpers +import symengine + +from jitcxde_common import checker, jitcxde +from jitcxde_common.helpers import copy_helpers, filter_helpers, find_dependent_helpers, sort_helpers, sympify_helpers from jitcxde_common.symbolic import collect_arguments, has_function + #: the symbol for the state that must be used to define the differential equation. It is a function and the integer argument denotes the component. You may just as well define an analogous function directly with SymEngine or SymPy, but using this function is the best way to get the most of future versions of JiTCSDE, in particular avoiding incompatibilities. You can import a SymPy variant from the submodule `sympy_symbols` instead (see `SymPy vs. SymEngine`_ for details). y = symengine.Function("y") diff --git a/jitcsde/_python_core.py b/jitcsde/_python_core.py index 51344ff..9f5db86 100644 --- a/jitcsde/_python_core.py +++ b/jitcsde/_python_core.py @@ -1,11 +1,13 @@ #!/usr/bin/python3 # -*- coding: utf-8 -*- -import symengine import numpy as np +import symengine from numpy import sqrt + from jitcxde_common.symbolic import ordered_subs + def perform_step(t,h,f,g,y,I_1,I_11,I_111,I_10): """ Optimised step evaluation. Tested against a human-readable version in test_step_functions.py. diff --git a/jitcsde/sympy_symbols.py b/jitcsde/sympy_symbols.py index 5acc0e5..659a85b 100644 --- a/jitcsde/sympy_symbols.py +++ b/jitcsde/sympy_symbols.py @@ -1,5 +1,6 @@ import sympy + #: the symbol for the state that must be used to define the differential equation. It is a function and the integer argument denotes the component. This one is different from the one you can import from jitcsde directly by being defined via SymPy and thus being better suited for some symbolic processing techniques that are not available in SymEngine yet. y = sympy.Function("y",real=True) diff --git a/tests/Butcher.py b/tests/Butcher.py index 955d709..4029d76 100644 --- a/tests/Butcher.py +++ b/tests/Butcher.py @@ -1,4 +1,5 @@ -from numpy import sqrt, array +from numpy import array, sqrt + A0 = array([ [ 0 , 0, 0, 0], diff --git a/tests/Butcher_SRA.py b/tests/Butcher_SRA.py index d899ed0..11305e1 100644 --- a/tests/Butcher_SRA.py +++ b/tests/Butcher_SRA.py @@ -1,5 +1,6 @@ from numpy import array + A0 = array([ [ 0 , 0], [3/4, 0], diff --git a/tests/compare_C_and_Python_core.py b/tests/compare_C_and_Python_core.py index fee4644..b7f2542 100644 --- a/tests/compare_C_and_Python_core.py +++ b/tests/compare_C_and_Python_core.py @@ -8,15 +8,15 @@ """ import platform -from sys import argv from random import Random +from sys import argv -import symengine import numpy as np +import symengine from numpy.testing import assert_allclose +from jitcsde import jitcsde, y from jitcsde._python_core import sde_integrator as py_sde_integrator -from jitcsde import y, jitcsde if platform.system() == "Windows": diff --git a/tests/kmc.py b/tests/kmc.py index cbd8148..a1801f1 100755 --- a/tests/kmc.py +++ b/tests/kmc.py @@ -1,9 +1,11 @@ #!/usr/bin/python3 # -*- coding: utf-8 -*- +import warnings + import numpy as np from scipy.stats import sem -import warnings + def KMC(Xs, h, kmax=4, nbins=100): """ diff --git a/tests/test_integration_speed.py b/tests/test_integration_speed.py index d2b50c9..3eb9ae9 100644 --- a/tests/test_integration_speed.py +++ b/tests/test_integration_speed.py @@ -1,6 +1,8 @@ -from jitcsde import jitcsde, y -from jitcode import jitcode import numpy as np +from jitcode import jitcode + +from jitcsde import jitcsde, y + """ Tests the SDE integrator by comparing the trajectories of: diff --git a/tests/test_jitcsde.py b/tests/test_jitcsde.py index 84a04b4..395569f 100644 --- a/tests/test_jitcsde.py +++ b/tests/test_jitcsde.py @@ -1,10 +1,13 @@ -import numpy as np -from numpy.testing import assert_allclose -from jitcsde import jitcsde, y, UnsuccessfulIntegration, test import platform -from symengine import symbols, exp, Rational, Function import unittest +import numpy as np +from numpy.testing import assert_allclose +from symengine import Function, Rational, exp, symbols + +from jitcsde import UnsuccessfulIntegration, jitcsde, test, y + + if platform.system() == "Windows": compile_args = None else: diff --git a/tests/test_jumps.py b/tests/test_jumps.py index 41f059f..ca7ee05 100644 --- a/tests/test_jumps.py +++ b/tests/test_jumps.py @@ -1,10 +1,13 @@ -import numpy as np -from numpy.testing import assert_allclose -from jitcsde import jitcsde_jump, y, UnsuccessfulIntegration import platform -from symengine import symbols, exp, Rational import unittest +import numpy as np +from numpy.testing import assert_allclose +from symengine import Rational, exp, symbols + +from jitcsde import UnsuccessfulIntegration, jitcsde_jump, y + + if platform.system() == "Windows": compile_args = None else: diff --git a/tests/test_python_core.py b/tests/test_python_core.py index bb86ec7..ee67074 100644 --- a/tests/test_python_core.py +++ b/tests/test_python_core.py @@ -1,8 +1,11 @@ +import unittest + import numpy as np -from jitcsde._python_core import sde_integrator from numpy.testing import assert_allclose, assert_array_equal from symengine import Integer -import unittest + +from jitcsde._python_core import sde_integrator + test_noise = [] for _ in range(10): diff --git a/tests/test_step_functions.py b/tests/test_step_functions.py index 7725468..73cb42b 100644 --- a/tests/test_step_functions.py +++ b/tests/test_step_functions.py @@ -2,13 +2,15 @@ Compares results of the step function from the Python core with the one derived from the Butcher tableaus. """ -import numpy as np -from jitcsde._python_core import perform_step as step_1 -from Butcher import perform_step as step_2 -from jitcsde._python_core import perform_SRA_step as SRA_step_1 -from Butcher_SRA import perform_step as SRA_step_2 import unittest +import numpy as np +from Butcher import perform_step as step_2 +from Butcher_SRA import perform_step as SRA_step_2 + +from jitcsde._python_core import perform_SRA_step as SRA_step_1, perform_step as step_1 + + n = 100 class TestStepFunctions(unittest.TestCase): diff --git a/tests/test_sympy_input.py b/tests/test_sympy_input.py index 784578c..5b86ca3 100644 --- a/tests/test_sympy_input.py +++ b/tests/test_sympy_input.py @@ -2,11 +2,14 @@ Tests whether things works independent of where symbols are imported from. """ +import random + +import symengine +import sympy + import jitcsde import jitcsde.sympy_symbols -import sympy -import symengine -import random + symengine_manually = [ symengine.Symbol("t",real=True), diff --git a/tests/validation.py b/tests/validation.py index 95dafa8..76e360f 100644 --- a/tests/validation.py +++ b/tests/validation.py @@ -6,11 +6,13 @@ """ import numpy as np -from jitcsde._python_core import sde_integrator -from jitcsde import jitcsde, y import symengine from kmc import KMC +from jitcsde import jitcsde, y +from jitcsde._python_core import sde_integrator + + kmax = 6 thresholds = [0.6,0.6,0.6,0.5,0.5,0.4] nbins = 100 From e7ef553fb2a93af13eaf46be2b78b7d0d3b87eb6 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Thu, 30 Jan 2025 21:18:41 +0200 Subject: [PATCH 4/9] Fix ruff UP (pyupgrade) errors --- docs/conf.py | 8 +++--- examples/noisy_and_jumpy_lorenz.py | 3 --- examples/noisy_lorenz.py | 5 +--- jitcsde/_jitcsde.py | 39 ++++++++++++++---------------- jitcsde/_python_core.py | 15 +++++------- tests/compare_C_and_Python_core.py | 10 +++----- tests/kmc.py | 1 - tests/validation.py | 11 +++------ 8 files changed, 37 insertions(+), 55 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index c458187..207b138 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,7 +12,9 @@ ] sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES) -class GroupHandler_mock(object): pass +class GroupHandler_mock: + pass + sys.modules['jitcxde_common.transversal'] = Mock(GroupHandler=GroupHandler_mock) sys.path.insert(0,os.path.abspath("../examples")) @@ -31,8 +33,8 @@ class GroupHandler_mock(object): pass master_doc = 'index' -project = u'JiTCSDE' -copyright = u'2017, Gerrit Ansmann' +project = 'JiTCSDE' +copyright = '2017, Gerrit Ansmann' release = version = get_version(root='..', relative_to=__file__) diff --git a/examples/noisy_and_jumpy_lorenz.py b/examples/noisy_and_jumpy_lorenz.py index 0c9e962..a387d0c 100644 --- a/examples/noisy_and_jumpy_lorenz.py +++ b/examples/noisy_and_jumpy_lorenz.py @@ -1,6 +1,3 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- - """ As an example, suppose that we want to add jumps to the noisy Lorenz oscillator from `example`. These shall have exponentially distributed waiting times (i.e. they are a Poisson process) with a scale parameter :math:`β=1.0`. diff --git a/examples/noisy_lorenz.py b/examples/noisy_lorenz.py index adba3fa..5b99f47 100644 --- a/examples/noisy_lorenz.py +++ b/examples/noisy_lorenz.py @@ -1,7 +1,4 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- - -""" +r""" Suppose we want to integrate Lorenz oscillator each of whose components is subject to a diffusion that amounts to :math:`p` of the respective component, i.e.: .. math:: diff --git a/jitcsde/_jitcsde.py b/jitcsde/_jitcsde.py index 987c4ca..4b39b96 100644 --- a/jitcsde/_jitcsde.py +++ b/jitcsde/_jitcsde.py @@ -1,6 +1,3 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- - import random import shutil from itertools import chain, count @@ -89,7 +86,7 @@ def __init__( self, module_location = None ): - super(jitcsde,self).__init__(n,verbose,module_location) + super().__init__(n,verbose,module_location) if f_sym and not g_sym and not module_location: raise ValueError("You gave f_sym as an argument but neither g_sym nor module_location. JiTCSDE cannot properly work with this.") @@ -120,7 +117,7 @@ def __init__( self, def _determine_additivity(self,additive): if additive is None: self.additive = ( - all( not has_function(entry ,y) for entry in self.g_sym() ) + all( not has_function(entry ,y) for entry in self.g_sym() ) and all( not has_function(helper[1],y) for helper in self._g_helpers ) ) else: @@ -214,7 +211,7 @@ def t(self, value): @checker def _check_non_empty(self): for function,name in [(self.f_sym, "f_sym"), (self.g_sym, "g_sym")]: - self._check_assert( function(), "%s is empty."%name ) + self._check_assert( function(), f"{name} is empty." ) @checker def _check_valid_arguments(self): @@ -223,11 +220,11 @@ def _check_valid_arguments(self): for argument in collect_arguments(entry,y): self._check_assert( argument[0] >= 0, - "y is called with a negative argument (%i) in component %i of %s." % (argument[0],i,name) + f"y is called with a negative argument ({argument[0]}) in component {i} of {name}." ) self._check_assert( argument[0] < self.n, - "y is called with an argument (%i) higher than the system’s dimension (%i) in component %i of %s." % (argument[0], self.n,i,name) + f"y is called with an argument ({argument[i]}) higher than the system’s dimension ({self.n}) in component {i} of {name}." ) @checker @@ -239,7 +236,7 @@ def _check_valid_symbols(self): for symbol in entry.atoms(symengine.Symbol): self._check_assert( symbol in valid_symbols, - "Invalid symbol (%s) in component %i of %s." % (symbol.name,i,name) + f"Invalid symbol ({symbol.name}) in component {i} of {name}." ) def reset_integrator(self): @@ -353,7 +350,7 @@ def compile_C( if simplify is None: simplify = self.n<=10 - helper_lengths = dict() + helper_lengths = {} for sym,helpers,name,long_name in [ ( self.f_sym, self._f_helpers, "f", "drift" ), @@ -571,15 +568,15 @@ def set_integration_parameters(self, def _control_for_min_step(self): if self.dt < self.min_step: - raise UnsuccessfulIntegration("\n" + raise UnsuccessfulIntegration( + "\n" "Could not integrate with the given tolerance parameters:\n\n" - "atol: %e\n" - "rtol: %e\n" - "min_step: %e\n\n" + f"atol: {self.atol:e}\n" + f"rtol: {self.rtol:e}\n" + f"min_step: {self.min_step:e}\n\n" "The most likely reasons for this are:\n" "• The SDE is ill-posed or stiff.\n" - "• You did not allow for an absolute error tolerance (atol) though your SDE calls for it. Even a very small absolute tolerance (1e-16) may sometimes help." - % (self.atol, self.rtol, self.min_step)) + "• You did not allow for an absolute error tolerance (atol) though your SDE calls for it. Even a very small absolute tolerance (1e-16) may sometimes help.") def _adjust_step_size(self, actual_dt): """ @@ -674,7 +671,7 @@ class jitcsde_jump(jitcsde): def __init__( self, IJI, amp, *args, **kwargs ): if not kwargs.pop("ito",True): raise NotImplementedError("I don’t know how to convert jumpy Stratonovich SDEs to Itō SDEs – nobody does.") - super(jitcsde_jump,self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.IJI = IJI self.amp = amp self._next_jump = None @@ -687,23 +684,23 @@ def next_jump(self): return self._next_jump def reset_integrator(self): - super(jitcsde_jump,self).reset_integrator() + super().reset_integrator() self._next_jump = None def integrate(self, target_time): while self.next_jump Date: Thu, 30 Jan 2025 21:20:18 +0200 Subject: [PATCH 5/9] Fix ruff Q (quotes) errors --- docs/conf.py | 40 ++++++++++++++++++++-------------------- jitcsde/__init__.py | 2 +- jitcsde/_python_core.py | 2 +- tests/kmc.py | 2 +- tests/validation.py | 2 +- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 207b138..306d707 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,37 +6,37 @@ MOCK_MODULES = [ - 'numpy', 'numpy.testing', 'numpy.random', - 'symengine', 'symengine.printing', 'symengine.lib.symengine_wrapper', - 'jitcxde_common.helpers','jitcxde_common.numerical','jitcxde_common.symbolic' + "numpy", "numpy.testing", "numpy.random", + "symengine", "symengine.printing", "symengine.lib.symengine_wrapper", + "jitcxde_common.helpers","jitcxde_common.numerical","jitcxde_common.symbolic" ] sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES) class GroupHandler_mock: pass -sys.modules['jitcxde_common.transversal'] = Mock(GroupHandler=GroupHandler_mock) +sys.modules["jitcxde_common.transversal"] = Mock(GroupHandler=GroupHandler_mock) sys.path.insert(0,os.path.abspath("../examples")) sys.path.insert(0,os.path.abspath("../jitcsde")) -needs_sphinx = '1.3' +needs_sphinx = "1.3" extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.mathjax', - 'numpydoc', + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.mathjax", + "numpydoc", ] -source_suffix = '.rst' +source_suffix = ".rst" -master_doc = 'index' +master_doc = "index" -project = 'JiTCSDE' -copyright = '2017, Gerrit Ansmann' +project = "JiTCSDE" +copyright = "2017, Gerrit Ansmann" -release = version = get_version(root='..', relative_to=__file__) +release = version = get_version(root="..", relative_to=__file__) default_role = "any" @@ -44,18 +44,18 @@ class GroupHandler_mock: add_module_names = False -html_theme = 'nature' -pygments_style = 'colorful' -htmlhelp_basename = 'JiTCSDEdoc' +html_theme = "nature" +pygments_style = "colorful" +htmlhelp_basename = "JiTCSDEdoc" numpydoc_show_class_members = False -autodoc_member_order = 'bysource' +autodoc_member_order = "bysource" def on_missing_reference(app, env, node, contnode): - if node['reftype'] == 'any': + if node["reftype"] == "any": return contnode else: return None def setup(app): - app.connect('missing-reference', on_missing_reference) + app.connect("missing-reference", on_missing_reference) diff --git a/jitcsde/__init__.py b/jitcsde/__init__.py index dee6933..568e672 100644 --- a/jitcsde/__init__.py +++ b/jitcsde/__init__.py @@ -5,4 +5,4 @@ from .version import version as __version__ except ImportError: from warnings import warn - warn('Failed to find (autogenerated) version.py. Do not worry about this unless you really need to know the version.') + warn("Failed to find (autogenerated) version.py. Do not worry about this unless you really need to know the version.") diff --git a/jitcsde/_python_core.py b/jitcsde/_python_core.py index fe42be3..7cec333 100644 --- a/jitcsde/_python_core.py +++ b/jitcsde/_python_core.py @@ -170,7 +170,7 @@ def get_state(self): return self.state def get_p(self, atol, rtol): - with np.errstate(divide='ignore',invalid='ignore'): + with np.errstate(divide="ignore",invalid="ignore"): return np.nanmax(self.error/(atol + rtol*np.abs(self.new_y))) def print_noises(self): diff --git a/tests/kmc.py b/tests/kmc.py index bc47a67..04ccce2 100755 --- a/tests/kmc.py +++ b/tests/kmc.py @@ -69,7 +69,7 @@ def Bin(value): # add KMCs and their standard errors to results: for k in range(1,kmax+1): - with np.errstate(divide='ignore',invalid='ignore'): + with np.errstate(divide="ignore",invalid="ignore"): with warnings.catch_warnings(): for message in [ "Mean of empty slice.", diff --git a/tests/validation.py b/tests/validation.py index 13d5170..fa3f1ca 100644 --- a/tests/validation.py +++ b/tests/validation.py @@ -127,7 +127,7 @@ def kmc_test(dt,runner,ks): for dt, runner, name in cases(scenario): ks = list(range(kmax)) for _ in range(5): - with np.errstate(invalid='ignore'): + with np.errstate(invalid="ignore"): ks = kmc_test(dt,runner,ks) if ks: retries += 1 From da8f46935199a6c964e82dfc79721f05b0d19060 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Thu, 30 Jan 2025 21:28:22 +0200 Subject: [PATCH 6/9] Fix ruff F+E (flake8) errors --- jitcsde/__init__.py | 4 ++-- jitcsde/_python_core.py | 8 ++++---- tests/Butcher.py | 2 +- tests/Butcher_SRA.py | 2 +- tests/test_jitcsde.py | 6 +++--- tests/test_jumps.py | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/jitcsde/__init__.py b/jitcsde/__init__.py index 568e672..14079bf 100644 --- a/jitcsde/__init__.py +++ b/jitcsde/__init__.py @@ -1,8 +1,8 @@ -from ._jitcsde import UnsuccessfulIntegration, jitcsde, jitcsde_jump, t, test, y +from ._jitcsde import UnsuccessfulIntegration, jitcsde, jitcsde_jump, t, test, y # noqa: F401 try: - from .version import version as __version__ + from .version import version as __version__ # noqa: F401 except ImportError: from warnings import warn warn("Failed to find (autogenerated) version.py. Do not worry about this unless you really need to know the version.") diff --git a/jitcsde/_python_core.py b/jitcsde/_python_core.py index 7cec333..f52c732 100644 --- a/jitcsde/_python_core.py +++ b/jitcsde/_python_core.py @@ -158,11 +158,11 @@ def get_I_SRA(self, h): def get_next_step(self, h): if self.additive: - I = self.get_I_SRA(h) - self.new_y, E_D, E_N = perform_SRA_step(self.t,h,self.f,self.g,self.state,*I) + args = self.get_I_SRA(h) + self.new_y, E_D, E_N = perform_SRA_step(self.t,h,self.f,self.g,self.state,*args) else: - I = self.get_I(h) - self.new_y, E_D, E_N = perform_step(self.t,h,self.f,self.g,self.state,*I) + args = self.get_I(h) + self.new_y, E_D, E_N = perform_step(self.t,h,self.f,self.g,self.state,*args) self.error = abs(E_D) + abs(E_N) self.new_t = self.t+h diff --git a/tests/Butcher.py b/tests/Butcher.py index 4029d76..fc0fa1b 100644 --- a/tests/Butcher.py +++ b/tests/Butcher.py @@ -58,7 +58,7 @@ def solution(α,β1,β2,β3,β4): X_bar = y + sum( α[i] * f(t+c0[i]*h,H0[i]) * h for i in range(4) ) for i in range(4): X_bar += g( t+c1[i]*h, H1[i] ) * ( - β1[i] * I_1 + β1[i] * I_1 + β2[i] * I_11 / sqrt(h) + β3[i] * I_10 / h + β4[i] * I_111 / h diff --git a/tests/Butcher_SRA.py b/tests/Butcher_SRA.py index 11305e1..e2af76c 100644 --- a/tests/Butcher_SRA.py +++ b/tests/Butcher_SRA.py @@ -32,7 +32,7 @@ def solution(α,β1,β2): X_bar = y + sum( α[i] * f(t+c0[i]*h,H0[i]) * h for i in range(2) ) for i in range(2): X_bar += g( t+c1[i]*h ) * ( - β1[i] * I_1 + β1[i] * I_1 + β2[i] * I_10 / h ) return X_bar diff --git a/tests/test_jitcsde.py b/tests/test_jitcsde.py index 395569f..626c205 100644 --- a/tests/test_jitcsde.py +++ b/tests/test_jitcsde.py @@ -12,7 +12,7 @@ compile_args = None else: from jitcxde_common import DEFAULT_COMPILE_ARGS - compile_args = DEFAULT_COMPILE_ARGS+["-g","-UNDEBUG"] + compile_args = [*DEFAULT_COMPILE_ARGS,"-g","-UNDEBUG"] # Ensures that all kinds of formatting the input actually work and produce the same result. The correctness of this result itself is checked in validation_test.py. @@ -111,7 +111,7 @@ def f_generator(): def g_generator(): yield from g -class TestStrat(CompareResults): +class TestStratWithGenerator(CompareResults): def setUp(self): self.SDE = jitcsde(f_generator,g_generator) @@ -119,7 +119,7 @@ def setUp(self): f_dict = { y(i):entry for i,entry in enumerate(f) } g_dict = { y(i):entry for i,entry in enumerate(g) } -class TestStrat(CompareResults): +class TestStratWithDict(CompareResults): def setUp(self): self.SDE = jitcsde(f_dict,g_dict) diff --git a/tests/test_jumps.py b/tests/test_jumps.py index ca7ee05..98a4a50 100644 --- a/tests/test_jumps.py +++ b/tests/test_jumps.py @@ -5,14 +5,14 @@ from numpy.testing import assert_allclose from symengine import Rational, exp, symbols -from jitcsde import UnsuccessfulIntegration, jitcsde_jump, y +from jitcsde import jitcsde_jump, y if platform.system() == "Windows": compile_args = None else: from jitcxde_common import DEFAULT_COMPILE_ARGS - compile_args = DEFAULT_COMPILE_ARGS+["-g","-UNDEBUG"] + compile_args = [*DEFAULT_COMPILE_ARGS,"-g","-UNDEBUG"] f = [-y(0)**3 + 4*y(0) + y(0)**2] g = [5*exp(-y(0)**2+y(0)-Rational(3,2)) + 3] @@ -64,7 +64,7 @@ def tearDown(self): class TestStrat(unittest.TestCase): def testError(self): with self.assertRaises(NotImplementedError): - SDE = jitcsde_jump( IJI, amp, f, g, ito=False ) + _SDE = jitcsde_jump( IJI, amp, f, g, ito=False ) class TestCheck(unittest.TestCase): def test_check_index_negative(self): From 823e2c6ad79d147c711cfab44655a62d8749b2c3 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Thu, 30 Jan 2025 21:35:49 +0200 Subject: [PATCH 7/9] Fix ruff NPY (numpy) errors --- examples/noisy_and_jumpy_lorenz.py | 15 ++++++++------- examples/noisy_lorenz.py | 9 +++++---- jitcsde/_jitcsde.py | 9 ++++++--- tests/test_integration_speed.py | 4 +++- tests/test_python_core.py | 12 +++++++----- tests/test_step_functions.py | 24 ++++++++++++++---------- tests/validation.py | 6 ++++-- 7 files changed, 47 insertions(+), 32 deletions(-) diff --git a/examples/noisy_and_jumpy_lorenz.py b/examples/noisy_and_jumpy_lorenz.py index a387d0c..ead7be8 100644 --- a/examples/noisy_and_jumpy_lorenz.py +++ b/examples/noisy_and_jumpy_lorenz.py @@ -26,11 +26,12 @@ """ if __name__ == "__main__": - import numpy + import numpy as np import symengine from jitcsde import jitcsde_jump, y + rng = np.random.default_rng(seed=42) ρ = 28 σ = 10 β = symengine.Rational(8,3) @@ -45,22 +46,22 @@ g = [ p*y(i) for i in range(3) ] def IJI(time,state): - return numpy.random.exponential(1.0) + return rng.exponential(1.0) def jump(time,state): - return numpy.array([ + return np.array([ 0.0, 0.0, - numpy.random.normal(0.0,abs(state[2])) + rng.normal(0.0,abs(state[2])) ]) SDE = jitcsde_jump(IJI,jump,f,g) - initial_state = numpy.random.random(3) + initial_state = rng.random(3) SDE.set_initial_value(initial_state,0.0) data = [] - for time in numpy.arange(0.0, 100.0, 0.01): + for time in np.arange(0.0, 100.0, 0.01): data.append( SDE.integrate(time) ) - numpy.savetxt("timeseries.dat", data) + np.savetxt("timeseries.dat", data) diff --git a/examples/noisy_lorenz.py b/examples/noisy_lorenz.py index 5b99f47..0df53ad 100644 --- a/examples/noisy_lorenz.py +++ b/examples/noisy_lorenz.py @@ -69,11 +69,12 @@ """ if __name__ == "__main__": - import numpy + import numpy as np import symengine from jitcsde import jitcsde, y + rng = np.random.default_rng(seed=42) ρ = 28 σ = 10 β = symengine.Rational(8,3) @@ -89,11 +90,11 @@ SDE = jitcsde(f,g) - initial_state = numpy.random.random(3) + initial_state = rng.random(3) SDE.set_initial_value(initial_state,0.0) data = [] - for time in numpy.arange(0.0, 100.0, 0.01): + for time in np.arange(0.0, 100.0, 0.01): data.append( SDE.integrate(time) ) - numpy.savetxt("timeseries.dat", data) + np.savetxt("timeseries.dat", data) diff --git a/jitcsde/_jitcsde.py b/jitcsde/_jitcsde.py index 4b39b96..d7329ee 100644 --- a/jitcsde/_jitcsde.py +++ b/jitcsde/_jitcsde.py @@ -668,13 +668,16 @@ class jitcsde_jump(jitcsde): This must be a NumPy array, even if your system is one-dimensional. """ - def __init__( self, IJI, amp, *args, **kwargs ): - if not kwargs.pop("ito",True): + def __init__( self, IJI, amp, *args, rng=None, ito=True, **kwargs ): + if not ito: raise NotImplementedError("I don’t know how to convert jumpy Stratonovich SDEs to Itō SDEs – nobody does.") + if rng is None: + rng = np.random.default_rng() super().__init__(*args, **kwargs) self.IJI = IJI self.amp = amp self._next_jump = None + self.rng = rng @property def next_jump(self): @@ -706,7 +709,7 @@ def check(self, fail_fast=True): def check_amp_function(self): output = self.amp( self.t or 0.0, - self.y or np.random.random(self.n) + self.y or self.rng.random(self.n) ) self._check_assert( diff --git a/tests/test_integration_speed.py b/tests/test_integration_speed.py index 3eb9ae9..1ffc8e2 100644 --- a/tests/test_integration_speed.py +++ b/tests/test_integration_speed.py @@ -14,6 +14,8 @@ https://math.stackexchange.com/q/2712378 """ +rng = np.random.default_rng(seed=42) + # The dynamics used for testing # ----------------------------- @@ -27,7 +29,7 @@ d*(b*y(0) - c/d*y(1)), ] -initial_state = np.random.random(2) +initial_state = rng.random(2) # Integrating the ODE #-------------------- diff --git a/tests/test_python_core.py b/tests/test_python_core.py index ee67074..4566e85 100644 --- a/tests/test_python_core.py +++ b/tests/test_python_core.py @@ -7,11 +7,13 @@ from jitcsde._python_core import sde_integrator +rng = np.random.default_rng(seed=42) + test_noise = [] for _ in range(10): test_noise.append([ - np.random.exponential(), - np.random.normal(2.0), + rng.exponential(), + rng.normal(2.0), ]) max_h = sum(x[0] for x in test_noise) @@ -38,21 +40,21 @@ def test_unchanged(self): assert_allclose(actual_DW, control_DW) def test_insertion(self): - intermediate_h = np.random.uniform(0,max_h) + intermediate_h = rng.uniform(0,max_h) first = self.SDE.get_noise(intermediate_h) second = self.SDE.get_noise(intermediate_h) assert_array_equal(first,second) self.test_unchanged() def test_extension(self): - external_h = np.random.uniform(max_h,2*max_h) + external_h = rng.uniform(max_h,2*max_h) first = self.SDE.get_noise(external_h) second = self.SDE.get_noise(external_h) assert_array_equal(first,second) self.test_unchanged() def test_size_of_noise_memory(self): - control_h = np.random.uniform(0,max_h) + control_h = rng.uniform(0,max_h) self.SDE.get_noise(control_h) self.SDE.accept_step() current_h = sum(x[0] for x in self.SDE.noises) diff --git a/tests/test_step_functions.py b/tests/test_step_functions.py index 73cb42b..09019c7 100644 --- a/tests/test_step_functions.py +++ b/tests/test_step_functions.py @@ -15,36 +15,40 @@ class TestStepFunctions(unittest.TestCase): def test_step_function(self): + rng = np.random.default_rng(seed=42) + # some random coefficients: - R = np.random.uniform( 0.5, 2, (4,n) ) - P = np.random.randint( -2, 3, (8,n) ) + R = rng.uniform( 0.5, 2, (4,n) ) + P = rng.integers( -2, 3, (8,n) ) # random functions def f(t,y): return R[0]*y**P[0]*t**P[1] + R[1]*y**P[2]*t**P[3] def g(t,y): return R[2]*y**P[4]*t**P[5] + R[3]*y**P[6]*t**P[7] - t = np.random.uniform( 0.5, 2 ) - h = np.random.uniform( 0.1, 2 ) - args = np.random.uniform( 0.5, 2, (5,n) ) + t = rng.uniform( 0.5, 2 ) + h = rng.uniform( 0.1, 2 ) + args = rng.uniform( 0.5, 2, (5,n) ) result_1 = step_1(t,h,f,g,*args) result_2 = step_2(t,h,f,g,*args) np.testing.assert_allclose(result_1,result_2,rtol=1e-5,atol=1e-10) def test_SRA_step_function(self): + rng = np.random.default_rng(seed=42) + # some random coefficients: - R = np.random.uniform( 0.5, 2, (4,n) ) - P = np.random.randint( -2, 3, (6,n) ) + R = rng.uniform( 0.5, 2, (4,n) ) + P = rng.integers( -2, 3, (6,n) ) # random functions def f(t,y): return R[0]*y**P[0]*t**P[1] + R[1]*y**P[2]*t**P[3] def g(t): return R[2]*t**P[4] + R[3]**t**P[5] - t = np.random.uniform( 0.5, 2 ) - h = np.random.uniform( 0.1, 2 ) - args = np.random.uniform( 0.5, 2, (3,n) ) + t = rng.uniform( 0.5, 2 ) + h = rng.uniform( 0.1, 2 ) + args = rng.uniform( 0.5, 2, (3,n) ) result_1 = SRA_step_1(t,h,f,g,*args) result_2 = SRA_step_2(t,h,f,g,*args) diff --git a/tests/validation.py b/tests/validation.py index fa3f1ca..2e22f29 100644 --- a/tests/validation.py +++ b/tests/validation.py @@ -10,6 +10,8 @@ from jitcsde._python_core import sde_integrator +rng = np.random.default_rng(seed=42) + kmax = 6 thresholds = [0.6,0.6,0.6,0.5,0.5,0.4] nbins = 100 @@ -56,7 +58,7 @@ def test_integrator( SDE.set_initial_value( np.array([0.0]) ) if pin: - size = np.random.exponential(dt) + size = rng.exponential(dt) number = int(times(dt,N)[-1]/size) SDE.pin_noise(number,size) @@ -70,7 +72,7 @@ def cases(scenario): yield dt, lambda: test_python_core(scenario,dt=dt), "Python core" # Tests the noise memory by making random request in-between the steps. - each_step = lambda SDE: SDE.get_noise(np.random.exponential(dt)) + each_step = lambda SDE: SDE.get_noise(rng.exponential(dt)) yield ( dt, lambda: test_python_core(scenario,dt=dt,each_step=each_step), From ecc14767b80d395e9c30390bfdabe97da32a2b9d Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Thu, 30 Jan 2025 21:39:03 +0200 Subject: [PATCH 8/9] Fix ruff B (bugbear) errors --- jitcsde/__init__.py | 2 +- jitcsde/_jitcsde.py | 10 ++++----- tests/compare_C_and_Python_core.py | 35 +++++++++++++++--------------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/jitcsde/__init__.py b/jitcsde/__init__.py index 14079bf..713e6f9 100644 --- a/jitcsde/__init__.py +++ b/jitcsde/__init__.py @@ -5,4 +5,4 @@ from .version import version as __version__ # noqa: F401 except ImportError: from warnings import warn - warn("Failed to find (autogenerated) version.py. Do not worry about this unless you really need to know the version.") + warn("Failed to find (autogenerated) version.py. Do not worry about this unless you really need to know the version.", stacklevel=2) diff --git a/jitcsde/_jitcsde.py b/jitcsde/_jitcsde.py index d7329ee..60b0c08 100644 --- a/jitcsde/_jitcsde.py +++ b/jitcsde/_jitcsde.py @@ -102,7 +102,7 @@ def __init__( self, self._determine_additivity(additive) if not ito: if self.additive: - warn("No need for conversion from Stratonovich to Itō for additive SDE.") + warn("No need for conversion from Stratonovich to Itō for additive SDE.", stacklevel=2) else: self._stratonovich_to_ito() @@ -535,10 +535,10 @@ def set_integration_parameters(self, if first_step > max_step: first_step = max_step - warn("Decreasing first_step to match max_step") + warn("Decreasing first_step to match max_step", stacklevel=2) if min_step > first_step: min_step = first_step - warn("Decreasing min_step to match first_step") + warn("Decreasing min_step to match first_step", stacklevel=2) assert decrease_threshold>=1.0, "decrease_threshold smaller than 1" assert increase_threshold<=1.0, "increase_threshold larger than 1" @@ -548,7 +548,7 @@ def set_integration_parameters(self, assert atol>=0.0, "negative atol" assert rtol>=0.0, "negative rtol" if atol==0 and rtol==0: - warn("atol and rtol are both 0. You probably do not want this.") + warn("atol and rtol are both 0. You probably do not want this.", stacklevel=2) self.atol = atol self.rtol = rtol @@ -650,7 +650,7 @@ def pin_noise(self, number, step_size): assert number>=0, "Number must be non-negative" assert step_size>0, "Step size must be positive" if not isinstance(number,int): - warn("`number` does not appear to be a integer. This is very likely cause an error immediately.") + warn("`number` does not appear to be a integer. This is very likely cause an error immediately.", stacklevel=2) self.SDE.pin_noise(number,step_size) class jitcsde_jump(jitcsde): diff --git a/tests/compare_C_and_Python_core.py b/tests/compare_C_and_Python_core.py index 108c44e..833ba7f 100644 --- a/tests/compare_C_and_Python_core.py +++ b/tests/compare_C_and_Python_core.py @@ -20,7 +20,7 @@ compile_args = None else: from jitcxde_common import DEFAULT_COMPILE_ARGS - compile_args = DEFAULT_COMPILE_ARGS+["-g","-UNDEBUG","-O1"] + compile_args = [*DEFAULT_COMPILE_ARGS,"-g","-UNDEBUG","-O1"] def compare(x,y,rtol=1e-4,atol=1e-4): try: @@ -37,6 +37,7 @@ def compare(x,y,rtol=1e-4,atol=1e-4): y(0)*(28-y(2))-y(1), y(0)*y(1)-8/3.*y(2) ] +rng = Random() for additive in [False,True]: if additive: @@ -44,19 +45,17 @@ def compare(x,y,rtol=1e-4,atol=1e-4): else: G = [ 0.1*y(i) for i in range(len(F)) ] - RNG = Random() - errors = 0 for realisation in range(number_of_runs): print( ".", end="", flush=True ) - seed = RNG.randint(0,1000000) + seed = rng.randint(0,1000000) - initial_state = np.array([RNG.random() for _ in range(len(F))]) + initial_state = np.array([rng.random() for _ in range(len(F))]) P = py_sde_integrator( - lambda:F, lambda:G, + lambda: F, lambda G=G: G, initial_state, 0.0, seed=seed, additive=additive ) @@ -65,29 +64,29 @@ def compare(x,y,rtol=1e-4,atol=1e-4): SDE.compile_C(extra_compile_args=compile_args,chunk_size=1) C = SDE.jitced.sde_integrator(0.0,initial_state,seed) - def get_next_step(): - r = RNG.uniform(1e-7,1e-3) + def get_next_step(P=P, C=C): + r = rng.uniform(1e-7,1e-3) P.get_next_step(r) C.get_next_step(r) - def time(): + def time(P=P, C=C): compare(P.t, C.t) - def get_state(): + def get_state(P=P, C=C): compare(P.get_state(), C.get_state()) - def get_p(): - r = 10**RNG.uniform(-10,-5) - q = 10**RNG.uniform(-10,-5) + def get_p(P=P, C=C): + r = 10**rng.uniform(-10,-5) + q = 10**rng.uniform(-10,-5) compare( np.log(P.get_p(r,q)), np.log(C.get_p(r,q)), rtol=1e-2, atol=1e-2 ) - def accept_step(): + def accept_step(P=P, C=C): P.accept_step() C.accept_step() - def pin_noise(): - step = RNG.uniform(1e-8,1.0) - number = RNG.randint(0,5) + def pin_noise(P=P, C=C): + step = rng.uniform(1e-8,1.0) + number = rng.randint(0,5) P.pin_noise(number,step) C.pin_noise(number,step) @@ -104,7 +103,7 @@ def pin_noise(): ] for i in range(10): - action = RNG.sample(actions,1)[0] + action = rng.sample(actions,1)[0] try: action() except AssertionError: From 8e41b55429c6aeac60d275e93093c6560719e774 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Thu, 30 Jan 2025 21:41:23 +0200 Subject: [PATCH 9/9] Fix some typos --- docs/index.rst | 2 +- jitcsde/_jitcsde.py | 2 +- pyproject.toml | 4 ++++ tests/kmc.py | 2 +- tests/test_jitcsde.py | 2 +- tests/test_jumps.py | 2 +- 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 746fa97..773e471 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -104,7 +104,7 @@ References .. [RN17] C. Rackauckas, Q. Nie: Adaptive methods for stochastic differential equations via natural embeddings and rejection sampling with memory, Discrete Cont. Dyn.-B 22, pp. 2731–2761 (2017), `10.3934/dcdsb.2017133 `_. -.. [R10] A. Rößler, Runge–Kutta methods for the strong approximation of solutions of stochastic differential equations, SIAM J. Numer. Anal. 48, pp. 922–952 (2010) `10.1137/09076636X `_. +.. [R10] A. Rößler, Runge–Kutta methods for the strong approximation of solutions of stochastic differential equations, SIAM J. Numerical Anal. 48, pp. 922–952 (2010) `10.1137/09076636X `_. .. _JiTCODE: http://github.com/neurophysik/jitcode diff --git a/jitcsde/_jitcsde.py b/jitcsde/_jitcsde.py index 60b0c08..4fb9cf1 100644 --- a/jitcsde/_jitcsde.py +++ b/jitcsde/_jitcsde.py @@ -62,7 +62,7 @@ class jitcsde(jitcxde): * A SymEngine function object used in `f_sym` to represent the function call. If you want to use any JiTCSDE features that need the derivative, this must have a properly defined `f_diff` method with the derivative being another callback function (or constant). * The Python function to be called. This function will receive the state array (`y`) as the first argument. All further arguments are whatever you use as arguments of the SymEngine function in `f_sym`. These can be any expression that you might use in the definition of the derivative and contain, e.g., dynamical variables, time, control parameters, and helpers. The only restriction is that the arguments are floats (and not vectors or similar). The return value must also be a float (or something castable to float). It is your responsibility to ensure that this function adheres to these criteria, is deterministic and sufficiently smooth with respect its arguments; expect nasty errors otherwise. - * The number of arguments, **excluding** the state array as mandatory first argument. This means if you have a variadic Python function, you cannot just call it with different numbers of arguments in `f_sym`, but you have to define separate callbacks for each of numer of arguments. + * The number of arguments, **excluding** the state array as mandatory first argument. This means if you have a variadic Python function, you cannot just call it with different numbers of arguments in `f_sym`, but you have to define separate callbacks for each of number of arguments. See `this example `_ (for JiTCDDE) for how to use this. diff --git a/pyproject.toml b/pyproject.toml index 5e8f313..bd81472 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -100,3 +100,7 @@ combine-as-imports = true known-local-folder = [ "jitcsde" ] known-first-party = [ "jitcxde_common" ] lines-after-imports = 2 + +[tool.typos.default.extend-words] +# short for Stratonovich used in various names +strat = "strat" diff --git a/tests/kmc.py b/tests/kmc.py index 04ccce2..dae8637 100755 --- a/tests/kmc.py +++ b/tests/kmc.py @@ -48,7 +48,7 @@ def KMC(Xs, h, kmax=4, nbins=100): Max = max(Xs) + (max(Xs)-min(Xs))/nbins*0.5 # bin borders X_bins = np.linspace(Min,Max,nbins+1) - # intialise results with middles of bins: + # initialise results with middles of bins: results = [(X_bins[1:]+X_bins[:-1])/2] def Bin(value): diff --git a/tests/test_jitcsde.py b/tests/test_jitcsde.py index 626c205..5b25860 100644 --- a/tests/test_jitcsde.py +++ b/tests/test_jitcsde.py @@ -47,7 +47,7 @@ def test_numpy_rng(self): self.SDE.compile_C(numpy_rng=True,extra_compile_args=compile_args) self.test_default() - def test_reproducability(self): + def test_reproducibility(self): self.test_default() def test_Python_core(self): diff --git a/tests/test_jumps.py b/tests/test_jumps.py index 98a4a50..a29cad2 100644 --- a/tests/test_jumps.py +++ b/tests/test_jumps.py @@ -46,7 +46,7 @@ def test_default(self): self.SDE.set_seed(42) self.SDE.set_initial_value(initial_value,0.0) - def test_reproducability(self): + def test_reproducibility(self): self.test_default() def test_Python_core(self):