diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 0ad25ff..52d1fa6 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -32,7 +32,7 @@ ] include: - environment-file: ci/py312-latest.yaml - os: macos-latest + os: macos-13 # Intel - environment-file: ci/py312-latest.yaml os: macos-14 # Apple Silicon - environment-file: ci/py312-latest.yaml @@ -60,7 +60,7 @@ - name: environment info run: "micromamba info && micromamba list" - + - name: run tests run: | pytest \ @@ -71,8 +71,18 @@ --cov fastpair \ --cov-append \ --cov-report term-missing \ - --cov-report xml . - + --cov-report xml . \ + + - name: run doctests (dev only) + if: contains(matrix.environment-file, 'dev') + run: | + pytest \ + fastpair/ \ + --verbose \ + -r a \ + --color yes \ + --doctest-only + - name: codecov uses: codecov/codecov-action@v4 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index df0f70d..d6ad7ce 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,3 +5,11 @@ repos: hooks: - id: ruff - id: ruff-format + - repo: https://github.com/pre-commit/mirrors-mypy + rev: "v1.10.1" + hooks: + - id: mypy + +ci: + autofix_prs: false + autoupdate_schedule: quarterly diff --git a/ci/py310-oldest.yaml b/ci/py310-oldest.yaml index 3f799f6..e6caa59 100644 --- a/ci/py310-oldest.yaml +++ b/ci/py310-oldest.yaml @@ -5,6 +5,7 @@ dependencies: - python=3.10 - numpy=1.24 - scipy=1.10 + - typing_extensions # testing - pytest - pytest-cov diff --git a/ci/py311-latest.yaml b/ci/py311-latest.yaml index d92f8db..4b99501 100644 --- a/ci/py311-latest.yaml +++ b/ci/py311-latest.yaml @@ -4,6 +4,7 @@ channels: dependencies: - python=3.11 - scipy + - typing_extensions # testing - pytest - pytest-cov diff --git a/ci/py312-dev.yaml b/ci/py312-dev.yaml index 1664a5e..8e2221d 100644 --- a/ci/py312-dev.yaml +++ b/ci/py312-dev.yaml @@ -4,9 +4,11 @@ channels: dependencies: - python=3.12 - pip + - typing_extensions # testing - pytest - pytest-cov + - pytest-doctestplus - pip: # nightly builds - --pre \ diff --git a/ci/py312-latest.yaml b/ci/py312-latest.yaml index d5c5642..3ea1f5a 100644 --- a/ci/py312-latest.yaml +++ b/ci/py312-latest.yaml @@ -4,6 +4,7 @@ channels: dependencies: - python=3.12 - scipy + - typing_extensions # testing - pytest - pytest-cov diff --git a/fastpair/base.py b/fastpair/base.py index 7b5226f..3576c39 100644 --- a/fastpair/base.py +++ b/fastpair/base.py @@ -2,16 +2,30 @@ # Copyright (c) 2002-2015, David Eppstein # Licensed under the MIT Licence (http://opensource.org/licenses/MIT). + from collections import defaultdict from itertools import combinations, cycle import scipy.spatial.distance as dist +from .types import ( + AllNeighs, + Callable, + ClosestPair, + Dist, + DistNeighDict, # noqa: F401 + DistNeighTuple, + Iterable, + PointCoords, + PointsInput, + Self, +) + __all__ = ["FastPair", "dist"] class AttrDict(dict): - """Simple dict with support for accessing elements as attributes.""" + """Simple ``dict`` with support for accessing elements as attributes.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -21,7 +35,7 @@ def __init__(self, *args, **kwargs): class FastPair: """FastPair: Data-structure for the dynamic closest-pair problem. - This data-structure is based on the observation that the conga line data + This data structure is based on the observation that the conga line data structure, in practice, does better the more subsets you give to it: even though the worst case time for :math:`k` subsets is :math:`O(nk log (n/k))`, that worst case seems much harder to reach than the nearest neighbor algorithm. @@ -50,35 +64,125 @@ class FastPair: https://doi.org/10.1145/351827.351829 """ - def __init__(self, min_points=10, dist=dist.euclidean): - """Initialize an empty FastPair data-structure. + def __init__(self, min_points: int = 10, dist: Callable = dist.euclidean) -> None: + """Initialize an empty ``FastPair`` data-structure. Parameters ---------- min_points : int, default=10 The minimum number of points to add before initializing the - data-structure. Queries _before_ `min_points` have been added to - the data-structure will be brute-force. - dist : function, default=scipy.spatial.distance.euclidean + data structure. Queries *before* ``min_points`` have been added to + the data structure will be brute-force. + dist : Callable, default=scipy.spatial.distance.euclidean Can be any Python function that returns a distance (float) between - between two vectors (tuples) `u` and `v`. Any distance function - from `scipy.spatial.distance` will do the trick. By default, the + between two vectors (tuples) ``u`` and ``v``. Any distance function + from ``scipy.spatial.distance`` will do the trick. By default, the Euclidean distance function is used. This function should play - nicely with the `merge` function. + nicely with the ``merge`` function. + + Attributes + ---------- + initialized : bool + ``True`` after the ``build()`` method is called. + neighbors : defaultdict[AttrDict] + Internally defined ``dict`` with support for accessing + elements as attributes where keys are ``PointCoords`` + and values are ``DistNeighDict``. + points : None | PointsInput + An list of 2D (two-dimensional) point tuples in the point set. + All objects in ``points`` **must** have equivalent dimensions. + + Examples + -------- + Create empty data structure with default values. + + >>> import fastpair + >>> fp = fastpair.FastPair() + >>> fp + + + Add points and build conga line. + + >>> points_2d = ((1, 1), (2, 2), (4, 4)) + >>> fp.build(points_2d) + + + Query closest pair. + + >>> fp.closest_pair() + (np.float64(1.4142135623730951), ((1, 1), (2, 2))) + + Add a point to the data structure. + + >>> fp += (1, 0) + >>> fp + + + Query again for closest pair. + + >>> fp.closest_pair() + (np.float64(1.0), ((1, 0), (1, 1))) + + Remove a point from the data structure. + + >>> fp -= (1, 1) + >>> fp + + + Query again for closest pair. + + >>> fp.closest_pair() + (np.float64(2.23606797749979), ((1, 0), (2, 2))) + + The default distance metric is ``scipy.spatial.distance.euclidean``. + Let's rebuild the ``FastPair`` with another metric. Many of the + distance functions available via ``scipy.spatial.distance`` can used. + Here we'll try ``cityblock``, which Manhattan distance. + + >>> from scipy.spatial import distance + >>> fp = fastpair.FastPair(min_points=3, dist=distance.cityblock) + >>> fp.build(points_2d) + + + While the closet pair remains the same, the distance between the + pair has increased with the new distance function. + + >>> fp.closest_pair() + (np.int64(2), ((1, 1), (2, 2))) """ + self.min_points = min_points self.dist = dist - self.initialized = False # Has the data-structure been initialized? - self.neighbors = defaultdict(AttrDict) # Dict of neighbor points and dists - self.points = [] # Internal point set; entries may be non-unique - - def __add__(self, p): + # Has the data-structure been initialized? + self.initialized = False + # Dict of neighbor points and dists + self.neighbors: defaultdict = defaultdict(AttrDict) + # Internal point set; entries may be non-unique + self.points: list = [] + + def __repr__(self) -> str: + mp = self.min_points + d = self.dist.__name__ + init = "" if self.initialized else "not " + curr_pnts = len(self) + dim = 0 if not self.points else len(self.points[0]) + return ( + f"" + ) + + def __add__(self, p: PointCoords) -> Self: """Add a point and find its nearest neighbor. There is some extra logic here to allow us to gradually build up the - FastPair data-structure until we reach `min_points`. Once `min_points` - has been reached, we initialize the data-structure and start to take - advantage of the FastPair efficiencies. + ``FastPair`` data structure until we reach ``min_points``. Once ``min_points`` + has been reached, we initialize the data structure and start to take + advantage of the ``FastPair`` efficiencies. """ self.points.append(p) if self.initialized: @@ -87,7 +191,7 @@ def __add__(self, p): self.build() return self - def __sub__(self, p): + def __sub__(self, p: PointCoords) -> Self: """Remove a point and update neighbors.""" self.points.remove(p) if self.initialized: @@ -97,51 +201,75 @@ def __sub__(self, p): self._find_neighbor(q) return self - def __len__(self): + def __len__(self) -> int: """Number of points in data structure.""" return len(self.points) - def __call__(self): + def __call__(self) -> ClosestPair: """Find closest pair by scanning list of nearest neighbors.""" return self.closest_pair() - def __contains__(self, p): + def __contains__(self, p: PointCoords) -> bool: return p in self.points - def __iter__(self): + def __iter__(self) -> Iterable: return iter(self.points) - def __getitem__(self, item): + def __getitem__(self, item: PointCoords) -> DistNeighTuple: if item not in self: raise KeyError(f"{item} not found") return self.neighbors[item] - def __setitem__(self, item, value): + def __setitem__(self, item: PointCoords, value: Dist | PointCoords): if item not in self: raise KeyError(f"{item} not found") self._update_point(item, value) - def build(self, points=None): - """Build a FastPairs data-structure from a set of (new) points. + def build(self, points: None | PointsInput = None) -> Self: + """Build a ``FastPair`` data-structure from a set of (new) points. Here we use a conga line rather than calling explicitly (re)building the neighbors map multiple times as it is more efficient. This method - needs to be called _before_ querying the data-structure or adding/ + needs to be called *before* querying the data structure or adding/ removing any new points. Once it has been called, the internal - `initialized` flag will be set to True. Otherwise, simple brute-force - versions of queries and calculations will be used. + ``initialized`` flag will be set to ``True``. Otherwise, simple + brute-force versions of queries and calculations will be used. Parameters ---------- - points : list of tuples/vectors, default=None - An optional list of point tuples to be added to the point set, - prior to computing the conga line and main FastPair data structure. + points : None | PointsInput, default=None + An optional list of 2D+ (two-dimensional or greater) point tuples + to be added to the point set, prior to computing the conga line + and main ``FastPair`` data structure. All objects in ``points`` + **must** have equivalent dimensions. + + Examples + -------- + + Initialize and build the data structure 300 equally-spaced 2D points. + + >>> import fastpair + >>> fp = fastpair.FastPair().build([(i, 1) for i in range(300)]) + >>> fp + + + Ensure all neighbor distances are exactly 1.0 (except the last point + which has no conga-style neighbor). + + >>> all([fp.neighbors[i]["dist"] == 1.0 for i in fp.points[:-1]]) + True + + Since the last point has no neighbors, its distance is assigned as ``inf``. + + >>> fp.neighbors[fp.points[-1]]["dist"] + inf """ if points is not None: self.points += list(points) np = len(self) - # Go through and find all neighbors, placing then in a conga line + # Go through and find all neighbors, placing them in a conga line for i in range(np - 1): # Find neighbor to p[0] to start nbr = i + 1 @@ -163,13 +291,29 @@ def build(self, points=None): self.initialized = True return self - def closest_pair(self): + def closest_pair(self) -> ClosestPair: """Find closest pair by scanning list of nearest neighbors. - If `npoints` is less than `min_points`, a brute-force version - of the closest pair algrithm is used. + If ``npoints`` is less than ``min_points``, a brute-force version + of the closest pair algorithm is used. + + Examples + -------- + Create and build the data structure with default values. + + >>> import fastpair + >>> fp = fastpair.FastPair(min_points=3).build(((1, 1), (2, 2), (4, 4))) + >>> fp + + + Query closest pair. + + >>> fp.closest_pair() + (np.float64(1.4142135623730951), ((1, 1), (2, 2))) """ - if len(self) < 2: + npoints = len(self) + if npoints < 2: raise ValueError("Must have `npoints >= 2` to form a pair.") elif not self.initialized: return self.closest_pair_brute_force() @@ -182,28 +326,39 @@ def closest_pair(self): b = self.neighbors[a].neigh return d, (a, b) - def closest_pair_brute_force(self): + def closest_pair_brute_force(self) -> ClosestPair: """Find closest pair using brute-force algorithm.""" return _closest_pair_brute_force(self.points, self.dist) - def sdist(self, p): - """Compute distances from input to all other points in data-structure. + def sdist(self, p: PointCoords) -> AllNeighs: + """Compute distances from input to all other points in data structure. This returns an iterator over all other points and their distance - from the input point `p`. The resulting iterator returns tuples with + from the input point ``p``. The resulting iterator returns tuples with the first item giving the distance, and the second item giving in - neighbor point. The `min` of this iterator is essentially a brute- - force 'nearest-neighbor' calculation. To do this, supply `itemgetter` - (or a lambda version) as the `key` argument to `min`. + neighbor point. The ``min`` of this iterator is essentially a brute- + force 'nearest-neighbor' calculation. To do this, supply ``operator.itemgetter`` + (or a ``lambda`` function) as the ``key`` argument to ``min``. Examples -------- - >>> fp = FastPair().build(points) - >>> min(fp.sdist(point), key=itemgetter(0)) + Initialize and build the data structure. + + >>> import fastpair, operator + >>> points = ((1, 1), (2, 2), (4, 4)) + >>> fp = fastpair.FastPair().build(points) + + Query the data structure using the ``.sdist()`` method for the closest + single point to ``(1, 1)``. + + >>> focal_point = (1, 1) + >>> min(fp.sdist(focal_point), key=operator.itemgetter(0)) + (np.float64(1.4142135623730951), (2, 2)) """ + return ((self.dist(a, b), b) for a, b in zip(cycle([p]), self.points) if b != a) - def _find_neighbor(self, p): + def _find_neighbor(self, p: PointCoords): """Find and update nearest neighbor of a given point.""" # If no neighbors available, set flag for `_update_point` to find if len(self) < 2: @@ -225,16 +380,15 @@ def _find_neighbor(self, p): self.neighbors[p].neigh = q return dict(self.neighbors[p]) # Return plain ol' dict - def _update_point(self, old, new): + def _update_point(self, old: PointCoords, new: PointCoords): """Update point location, neighbors, and distances. All distances to point have changed, we need to recompute all aspects of the data structure that may be affected. Note that although we - completely recompute the neighbors of the original point (`old`), we + completely recompute the neighbors of the original point (``old``), we don't explicitly rebuild the neighbors map, since that would double the number of distance computations made by this routine. Also, like - deletion, we don't change any _other_ point's neighbor to the updated - point. + deletion, we don't change any *other* point's neighbor to the updated point. """ # Out with the old, in with the new... self.points.remove(old) @@ -265,13 +419,15 @@ def _update_point(self, old, new): # return self._update_point(a, c) -def _closest_pair_brute_force(pts, dst=dist.euclidean): +def _closest_pair_brute_force( + pts: PointsInput, dst: Callable = dist.euclidean +) -> ClosestPair: """Compute closest pair of points using brute-force algorithm. Notes ----- Computes all possible combinations of points and compares their distances. - This is _not_ efficient, nor scalable, but it provides a useful reference + This is *not* efficient, nor scalable, but it provides a useful reference for more efficient algorithms. This version is actually pretty fast due to its use of fast Python builtins. """ diff --git a/fastpair/tests/conftest.py b/fastpair/tests/conftest.py index 36b8bc4..0119bd8 100644 --- a/fastpair/tests/conftest.py +++ b/fastpair/tests/conftest.py @@ -2,12 +2,12 @@ import pytest -def rand_tuple(dim: int = 2, seed: None | int = None) -> tuple[float]: +def rand_tuple(dim: int = 2, seed: None | int = None) -> tuple[float, ...]: rng = numpy.random.default_rng(seed) return tuple([round(rng.uniform(), 4) for j in range(dim)]) -def point_set(n: int = 50, d: int = 10, seed: int = 0) -> list[tuple[float, float]]: +def point_set(n: int = 50, d: int = 10, seed: int = 0) -> list[tuple[float, ...]]: """Return ``numpy.array`` of shape ``(n, d)``.""" return [rand_tuple(dim=d, seed=seed + i) for i in range(n)] diff --git a/fastpair/tests/test_fastpair.py b/fastpair/tests/test_fastpair.py index 3f762ff..634dc97 100644 --- a/fastpair/tests/test_fastpair.py +++ b/fastpair/tests/test_fastpair.py @@ -11,6 +11,7 @@ from itertools import combinations, cycle from operator import itemgetter from types import FunctionType +from typing import Any import numpy import pytest @@ -18,7 +19,7 @@ from fastpair import FastPair -def normalized_distance(_a: numpy.array, _b: numpy.array) -> float: +def normalized_distance(_a: numpy.ndarray, _b: numpy.ndarray) -> numpy.floating[Any]: """Compute the normalized distance between 2 arrays.""" b = _b.astype(int) a = _a.astype(int) @@ -28,7 +29,7 @@ def normalized_distance(_a: numpy.array, _b: numpy.array) -> float: return norm_diff / (norm1 + norm2) -def image_distance(image1: tuple, image2: tuple) -> float: +def image_distance(image1: tuple, image2: tuple) -> numpy.floating[Any]: """Custom distance metric.""" (sig1, _) = image1 (sig2, _) = image2 @@ -37,9 +38,8 @@ def image_distance(image1: tuple, image2: tuple) -> float: return normalized_distance(sig1, sig2) -def contains_same(s: list, t: list) -> bool: - """Determine if 2 lists contain the same (set-theoretic) elements.""" - s, t = set(s), set(t) +def contains_same(s: set, t: set) -> bool: + """Determine if 2 set[list] objects contain the same (set-theoretic) elements.""" return s >= t and s <= t @@ -386,7 +386,7 @@ def test_basic(self): ps.remove(e) ps.remove(f) ps.append(g) - assert contains_same(fp.points, ps) + assert contains_same(set(fp.points), set(ps)) assert len(fp.points) == len(ps) == 1 @@ -414,7 +414,7 @@ def test_complex(self): ps.remove(e) ps.remove(f) ps.append(g) - assert contains_same(fp.points, ps) + assert contains_same(set(fp.points), set(ps)) assert len(fp.points) == len(ps) == 1 diff --git a/fastpair/types.py b/fastpair/types.py new file mode 100644 index 0000000..db9d3bb --- /dev/null +++ b/fastpair/types.py @@ -0,0 +1,71 @@ +# Copyright (c) 2016, Carson J. Q. Farmer +# Copyright (c) 2002-2015, David Eppstein +# Licensed under the MIT Licence (http://opensource.org/licenses/MIT). + +import sys +from collections.abc import Callable, Generator, Iterable +from typing import Annotated, TypeAlias, TypedDict, TypeVar + +################################################################ +# See GH#73 -- remove once Python 3.11 is minimum +if sys.version_info.minor < 11: + from typing_extensions import Self +else: + from typing import Self +################################################################ + +import numpy + +__all__ = [ + "Callable", + "Iterable", + "Self", + "NumericCoord", + "PointCoords", + "PointsInput", + "Dist", + "DistNeighTuple", + "AllNeighs", + "DistNeighDict", + "NeighCoords", + "ClosestPair", +] + + +# point typing --------------------------------------------------------------------- +_Numeric = TypeVar("_Numeric", float, int, complex, numpy.number) +_NumericAnnotation = Annotated[_Numeric, "Any numeric value."] +NumericCoord: TypeAlias = _NumericAnnotation + +_PointCoords = TypeVar("_PointCoords", bound=tuple[NumericCoord]) +PointCoords = Annotated[_PointCoords, "A tuple of at least 2 numeric elements."] + +_PointsInput = TypeVar("_PointsInput", bound=Iterable[PointCoords]) +PointsInput = Annotated[_PointsInput, "Input for ``.build()``."] + + +# distance typing ------------------------------------------------------------------ +Dist: TypeAlias = _NumericAnnotation + +_DistNeighTuple = TypeVar("_DistNeighTuple", bound=tuple[Dist, PointCoords]) +DistNeighTuple = Annotated[_DistNeighTuple, "Returned from ``.__getitem__()``."] + +_AllNeighs = Generator[DistNeighTuple, None, None] +AllNeighs = Annotated[_AllNeighs, "Returned from ``.sdist()``."] + + +# pair typing ---------------------------------------------------------------------- +class DistNeighDict(TypedDict): + """The values of the ``FastPair.neighbors`` dictionary. Also potentially + returned from ``._update_point()``. See GH#69. + """ + + dist: Dist + neigh: PointCoords + + +_NeighCoords = tuple[PointCoords, PointCoords] +NeighCoords = Annotated[_NeighCoords, "2 instances of ``PointCoords``."] + +_ClosestPair = TypeVar("_ClosestPair", bound=tuple[Dist, NeighCoords]) +ClosestPair = Annotated[_ClosestPair, "Returned from ``.closest_pair()``."] diff --git a/notebooks/basic_usage.ipynb b/notebooks/basic_usage.ipynb index 5ae2c52..738399b 100644 --- a/notebooks/basic_usage.ipynb +++ b/notebooks/basic_usage.ipynb @@ -18,11 +18,11 @@ "id": "2da42c3d-a668-456c-9d05-5b826d2ca963", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.402265Z", - "iopub.status.busy": "2024-06-15T18:59:33.401881Z", - "iopub.status.idle": "2024-06-15T18:59:33.431762Z", - "shell.execute_reply": "2024-06-15T18:59:33.430862Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.402240Z" + "iopub.execute_input": "2024-07-10T21:57:06.485142Z", + "iopub.status.busy": "2024-07-10T21:57:06.484639Z", + "iopub.status.idle": "2024-07-10T21:57:06.517136Z", + "shell.execute_reply": "2024-07-10T21:57:06.516878Z", + "shell.execute_reply.started": "2024-07-10T21:57:06.485114Z" } }, "outputs": [ @@ -30,11 +30,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "Last updated: 2024-06-15T14:59:33.420817-04:00\n", + "Last updated: 2024-07-10T17:57:06.508030-04:00\n", "\n", "Python implementation: CPython\n", - "Python version : 3.12.3\n", - "IPython version : 8.25.0\n", + "Python version : 3.12.4\n", + "IPython version : 8.26.0\n", "\n", "Compiler : Clang 16.0.6 \n", "OS : Darwin\n", @@ -59,11 +59,11 @@ "id": "5f2c2691-2f11-4649-aafd-eaf734d5c368", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.432574Z", - "iopub.status.busy": "2024-06-15T18:59:33.432449Z", - "iopub.status.idle": "2024-06-15T18:59:33.660652Z", - "shell.execute_reply": "2024-06-15T18:59:33.660447Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.432556Z" + "iopub.execute_input": "2024-07-10T21:57:06.517885Z", + "iopub.status.busy": "2024-07-10T21:57:06.517779Z", + "iopub.status.idle": "2024-07-10T21:57:07.053924Z", + "shell.execute_reply": "2024-07-10T21:57:07.053552Z", + "shell.execute_reply.started": "2024-07-10T21:57:06.517867Z" } }, "outputs": [ @@ -73,8 +73,8 @@ "text": [ "Watermark: 2.4.3\n", "\n", + "fastpair : 0.1.1.dev12+gb5fa448.d20240622\n", "matplotlib: 3.9.0\n", - "fastpair : 0.1.1.dev8+g5f8e7a5.d20240611\n", "\n" ] } @@ -106,11 +106,11 @@ "id": "c4845e9d-f5d5-4f92-94f8-72f809f0fac9", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.661746Z", - "iopub.status.busy": "2024-06-15T18:59:33.661641Z", - "iopub.status.idle": "2024-06-15T18:59:33.664384Z", - "shell.execute_reply": "2024-06-15T18:59:33.664183Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.661739Z" + "iopub.execute_input": "2024-07-10T21:57:07.055454Z", + "iopub.status.busy": "2024-07-10T21:57:07.055178Z", + "iopub.status.idle": "2024-07-10T21:57:07.058404Z", + "shell.execute_reply": "2024-07-10T21:57:07.058190Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.055443Z" } }, "outputs": [ @@ -147,18 +147,19 @@ "id": "7e37b5d2-e626-486d-a02f-c982eea73907", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.664794Z", - "iopub.status.busy": "2024-06-15T18:59:33.664731Z", - "iopub.status.idle": "2024-06-15T18:59:33.666585Z", - "shell.execute_reply": "2024-06-15T18:59:33.666413Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.664787Z" + "iopub.execute_input": "2024-07-10T21:57:07.058848Z", + "iopub.status.busy": "2024-07-10T21:57:07.058776Z", + "iopub.status.idle": "2024-07-10T21:57:07.060804Z", + "shell.execute_reply": "2024-07-10T21:57:07.060608Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.058841Z" } }, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 4, @@ -185,18 +186,19 @@ "id": "895e21eb-9449-4aa5-999b-5ac13f9e4219", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.666934Z", - "iopub.status.busy": "2024-06-15T18:59:33.666875Z", - "iopub.status.idle": "2024-06-15T18:59:33.668678Z", - "shell.execute_reply": "2024-06-15T18:59:33.668503Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.666927Z" + "iopub.execute_input": "2024-07-10T21:57:07.061227Z", + "iopub.status.busy": "2024-07-10T21:57:07.061159Z", + "iopub.status.idle": "2024-07-10T21:57:07.063703Z", + "shell.execute_reply": "2024-07-10T21:57:07.063503Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.061219Z" } }, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 5, @@ -237,11 +239,11 @@ "id": "01160597-4c0f-4cd1-9cd4-b7dc8bce6b2a", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.669075Z", - "iopub.status.busy": "2024-06-15T18:59:33.668999Z", - "iopub.status.idle": "2024-06-15T18:59:33.670639Z", - "shell.execute_reply": "2024-06-15T18:59:33.670479Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.669069Z" + "iopub.execute_input": "2024-07-10T21:57:07.064497Z", + "iopub.status.busy": "2024-07-10T21:57:07.064278Z", + "iopub.status.idle": "2024-07-10T21:57:07.067597Z", + "shell.execute_reply": "2024-07-10T21:57:07.067095Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.064467Z" } }, "outputs": [ @@ -276,11 +278,11 @@ "id": "9d7adeb7-36a4-41e7-93e9-9a1fee6edbed", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.671017Z", - "iopub.status.busy": "2024-06-15T18:59:33.670952Z", - "iopub.status.idle": "2024-06-15T18:59:33.672651Z", - "shell.execute_reply": "2024-06-15T18:59:33.672478Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.671011Z" + "iopub.execute_input": "2024-07-10T21:57:07.068239Z", + "iopub.status.busy": "2024-07-10T21:57:07.068145Z", + "iopub.status.idle": "2024-07-10T21:57:07.070957Z", + "shell.execute_reply": "2024-07-10T21:57:07.070608Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.068231Z" } }, "outputs": [ @@ -313,11 +315,11 @@ "id": "30355b1a-3757-43c0-ab95-0733f4f50e81", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.672954Z", - "iopub.status.busy": "2024-06-15T18:59:33.672898Z", - "iopub.status.idle": "2024-06-15T18:59:33.674490Z", - "shell.execute_reply": "2024-06-15T18:59:33.674320Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.672948Z" + "iopub.execute_input": "2024-07-10T21:57:07.071672Z", + "iopub.status.busy": "2024-07-10T21:57:07.071569Z", + "iopub.status.idle": "2024-07-10T21:57:07.074085Z", + "shell.execute_reply": "2024-07-10T21:57:07.073893Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.071651Z" } }, "outputs": [ @@ -352,18 +354,18 @@ "id": "78034246-f548-4a1c-9872-ea071462c058", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.674824Z", - "iopub.status.busy": "2024-06-15T18:59:33.674719Z", - "iopub.status.idle": "2024-06-15T18:59:33.676467Z", - "shell.execute_reply": "2024-06-15T18:59:33.676278Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.674818Z" + "iopub.execute_input": "2024-07-10T21:57:07.074626Z", + "iopub.status.busy": "2024-07-10T21:57:07.074543Z", + "iopub.status.idle": "2024-07-10T21:57:07.076670Z", + "shell.execute_reply": "2024-07-10T21:57:07.076477Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.074618Z" } }, "outputs": [ { "data": { "text/plain": [ - "(1.4142135623730951, ((1, 1), (2, 2)))" + "(np.float64(1.4142135623730951), ((1, 1), (2, 2)))" ] }, "execution_count": 9, @@ -389,18 +391,18 @@ "id": "9f7315f7-72d0-4693-9808-d1e325f93c8d", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.676827Z", - "iopub.status.busy": "2024-06-15T18:59:33.676771Z", - "iopub.status.idle": "2024-06-15T18:59:33.678580Z", - "shell.execute_reply": "2024-06-15T18:59:33.678391Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.676821Z" + "iopub.execute_input": "2024-07-10T21:57:07.077363Z", + "iopub.status.busy": "2024-07-10T21:57:07.077295Z", + "iopub.status.idle": "2024-07-10T21:57:07.079470Z", + "shell.execute_reply": "2024-07-10T21:57:07.079253Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.077356Z" } }, "outputs": [ { "data": { "text/plain": [ - "(1.4142135623730951, ((1, 1), (2, 2)))" + "(np.float64(1.4142135623730951), ((1, 1), (2, 2)))" ] }, "execution_count": 10, @@ -426,18 +428,18 @@ "id": "37366768-415c-42ab-9c18-110750160483", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.678945Z", - "iopub.status.busy": "2024-06-15T18:59:33.678887Z", - "iopub.status.idle": "2024-06-15T18:59:33.681266Z", - "shell.execute_reply": "2024-06-15T18:59:33.681076Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.678939Z" + "iopub.execute_input": "2024-07-10T21:57:07.080075Z", + "iopub.status.busy": "2024-07-10T21:57:07.080011Z", + "iopub.status.idle": "2024-07-10T21:57:07.082084Z", + "shell.execute_reply": "2024-07-10T21:57:07.081898Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.080068Z" } }, "outputs": [ { "data": { "text/plain": [ - "(1.4142135623730951, ((1, 1), (2, 2)))" + "(np.float64(1.4142135623730951), ((1, 1), (2, 2)))" ] }, "execution_count": 11, @@ -465,11 +467,11 @@ "id": "65890425-a4c6-45f2-8c57-90c7afd9a204", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.683179Z", - "iopub.status.busy": "2024-06-15T18:59:33.683091Z", - "iopub.status.idle": "2024-06-15T18:59:33.684782Z", - "shell.execute_reply": "2024-06-15T18:59:33.684599Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.683171Z" + "iopub.execute_input": "2024-07-10T21:57:07.084025Z", + "iopub.status.busy": "2024-07-10T21:57:07.083910Z", + "iopub.status.idle": "2024-07-10T21:57:07.086158Z", + "shell.execute_reply": "2024-07-10T21:57:07.085795Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.084008Z" } }, "outputs": [ @@ -492,11 +494,11 @@ "id": "ac10107e-1f1b-437c-a0c5-0323460a9bff", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.685173Z", - "iopub.status.busy": "2024-06-15T18:59:33.685115Z", - "iopub.status.idle": "2024-06-15T18:59:33.687289Z", - "shell.execute_reply": "2024-06-15T18:59:33.687107Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.685167Z" + "iopub.execute_input": "2024-07-10T21:57:07.087276Z", + "iopub.status.busy": "2024-07-10T21:57:07.086911Z", + "iopub.status.idle": "2024-07-10T21:57:07.089871Z", + "shell.execute_reply": "2024-07-10T21:57:07.089651Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.087267Z" } }, "outputs": [ @@ -530,18 +532,18 @@ "id": "9284e7a7-0765-4d9e-9f51-0c64217fe778", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.687723Z", - "iopub.status.busy": "2024-06-15T18:59:33.687661Z", - "iopub.status.idle": "2024-06-15T18:59:33.689574Z", - "shell.execute_reply": "2024-06-15T18:59:33.689367Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.687716Z" + "iopub.execute_input": "2024-07-10T21:57:07.090462Z", + "iopub.status.busy": "2024-07-10T21:57:07.090344Z", + "iopub.status.idle": "2024-07-10T21:57:07.092428Z", + "shell.execute_reply": "2024-07-10T21:57:07.092229Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.090454Z" } }, "outputs": [ { "data": { "text/plain": [ - "1.4142135623730951" + "np.float64(1.4142135623730951)" ] }, "execution_count": 14, @@ -567,11 +569,11 @@ "id": "2e255c57-90c4-4596-8f31-9f352cc89357", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.690071Z", - "iopub.status.busy": "2024-06-15T18:59:33.689975Z", - "iopub.status.idle": "2024-06-15T18:59:33.691883Z", - "shell.execute_reply": "2024-06-15T18:59:33.691718Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.690064Z" + "iopub.execute_input": "2024-07-10T21:57:07.092773Z", + "iopub.status.busy": "2024-07-10T21:57:07.092711Z", + "iopub.status.idle": "2024-07-10T21:57:07.095051Z", + "shell.execute_reply": "2024-07-10T21:57:07.094662Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.092766Z" } }, "outputs": [ @@ -597,18 +599,18 @@ "id": "dcc5c91e-1ab4-4ee9-acad-a9a349de8793", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.692191Z", - "iopub.status.busy": "2024-06-15T18:59:33.692136Z", - "iopub.status.idle": "2024-06-15T18:59:33.694180Z", - "shell.execute_reply": "2024-06-15T18:59:33.693986Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.692185Z" + "iopub.execute_input": "2024-07-10T21:57:07.095713Z", + "iopub.status.busy": "2024-07-10T21:57:07.095629Z", + "iopub.status.idle": "2024-07-10T21:57:07.097711Z", + "shell.execute_reply": "2024-07-10T21:57:07.097487Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.095706Z" } }, "outputs": [ { "data": { "text/plain": [ - "29.698484809834994" + "np.float64(29.698484809834994)" ] }, "execution_count": 16, @@ -636,20 +638,20 @@ "id": "05d78d6f-1f73-4718-b070-cc81e27154ec", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.694597Z", - "iopub.status.busy": "2024-06-15T18:59:33.694529Z", - "iopub.status.idle": "2024-06-15T18:59:33.696568Z", - "shell.execute_reply": "2024-06-15T18:59:33.696373Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.694591Z" + "iopub.execute_input": "2024-07-10T21:57:07.098137Z", + "iopub.status.busy": "2024-07-10T21:57:07.098074Z", + "iopub.status.idle": "2024-07-10T21:57:07.100071Z", + "shell.execute_reply": "2024-07-10T21:57:07.099866Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.098129Z" } }, "outputs": [ { "data": { "text/plain": [ - "((2.8284271247461903, (1, 1)),\n", - " (4.242640687119285, (2, 2)),\n", - " (7.0710678118654755, (4, 4)))" + "((np.float64(2.8284271247461903), (1, 1)),\n", + " (np.float64(4.242640687119285), (2, 2)),\n", + " (np.float64(7.0710678118654755), (4, 4)))" ] }, "execution_count": 17, @@ -685,18 +687,18 @@ "id": "aa6bab3b-18d0-489e-9d56-2b1e215b8f36", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.696931Z", - "iopub.status.busy": "2024-06-15T18:59:33.696865Z", - "iopub.status.idle": "2024-06-15T18:59:33.699292Z", - "shell.execute_reply": "2024-06-15T18:59:33.699068Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.696924Z" + "iopub.execute_input": "2024-07-10T21:57:07.100591Z", + "iopub.status.busy": "2024-07-10T21:57:07.100362Z", + "iopub.status.idle": "2024-07-10T21:57:07.102711Z", + "shell.execute_reply": "2024-07-10T21:57:07.102402Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.100584Z" } }, "outputs": [ { "data": { "text/plain": [ - "(1.4142135623730951, ((1, 1), (2, 2)))" + "(np.float64(1.4142135623730951), ((1, 1), (2, 2)))" ] }, "execution_count": 18, @@ -727,11 +729,11 @@ "id": "62b69b65-7070-4667-a447-cc8f7b2a6396", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.699861Z", - "iopub.status.busy": "2024-06-15T18:59:33.699640Z", - "iopub.status.idle": "2024-06-15T18:59:33.786552Z", - "shell.execute_reply": "2024-06-15T18:59:33.786306Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.699853Z" + "iopub.execute_input": "2024-07-10T21:57:07.103301Z", + "iopub.status.busy": "2024-07-10T21:57:07.103033Z", + "iopub.status.idle": "2024-07-10T21:57:07.232355Z", + "shell.execute_reply": "2024-07-10T21:57:07.232095Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.103270Z" } }, "outputs": [ @@ -775,11 +777,11 @@ "id": "55c1f26a-62e1-4c9b-a407-23f476967f65", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.787074Z", - "iopub.status.busy": "2024-06-15T18:59:33.786995Z", - "iopub.status.idle": "2024-06-15T18:59:33.789125Z", - "shell.execute_reply": "2024-06-15T18:59:33.788914Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.787066Z" + "iopub.execute_input": "2024-07-10T21:57:07.232900Z", + "iopub.status.busy": "2024-07-10T21:57:07.232828Z", + "iopub.status.idle": "2024-07-10T21:57:07.235550Z", + "shell.execute_reply": "2024-07-10T21:57:07.235289Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.232893Z" } }, "outputs": [], @@ -803,18 +805,18 @@ "id": "58e711ce-4774-4e26-958e-13dabb91c7f2", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.789448Z", - "iopub.status.busy": "2024-06-15T18:59:33.789378Z", - "iopub.status.idle": "2024-06-15T18:59:33.791875Z", - "shell.execute_reply": "2024-06-15T18:59:33.791673Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.789440Z" + "iopub.execute_input": "2024-07-10T21:57:07.236088Z", + "iopub.status.busy": "2024-07-10T21:57:07.236016Z", + "iopub.status.idle": "2024-07-10T21:57:07.238308Z", + "shell.execute_reply": "2024-07-10T21:57:07.238128Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.236080Z" } }, "outputs": [ { "data": { "text/plain": [ - "(1.0, ((1, 2), (1, 1)))" + "(np.float64(1.0), ((1, 2), (1, 1)))" ] }, "execution_count": 21, @@ -847,11 +849,11 @@ "id": "f44c118b-cca2-4c40-b0a1-f66436f0ab22", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.792296Z", - "iopub.status.busy": "2024-06-15T18:59:33.792234Z", - "iopub.status.idle": "2024-06-15T18:59:33.873693Z", - "shell.execute_reply": "2024-06-15T18:59:33.873470Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.792289Z" + "iopub.execute_input": "2024-07-10T21:57:07.238663Z", + "iopub.status.busy": "2024-07-10T21:57:07.238590Z", + "iopub.status.idle": "2024-07-10T21:57:07.321617Z", + "shell.execute_reply": "2024-07-10T21:57:07.321356Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.238656Z" } }, "outputs": [ @@ -896,11 +898,11 @@ "id": "100f2b17-9c34-4d43-9e21-f293744fcb68", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.874275Z", - "iopub.status.busy": "2024-06-15T18:59:33.874202Z", - "iopub.status.idle": "2024-06-15T18:59:33.876386Z", - "shell.execute_reply": "2024-06-15T18:59:33.876170Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.874268Z" + "iopub.execute_input": "2024-07-10T21:57:07.322224Z", + "iopub.status.busy": "2024-07-10T21:57:07.322154Z", + "iopub.status.idle": "2024-07-10T21:57:07.324133Z", + "shell.execute_reply": "2024-07-10T21:57:07.323882Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.322217Z" } }, "outputs": [], @@ -924,18 +926,18 @@ "id": "3c729bbd-6e6d-4e1d-bc04-e8bbdb81c9a7", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.876768Z", - "iopub.status.busy": "2024-06-15T18:59:33.876686Z", - "iopub.status.idle": "2024-06-15T18:59:33.878895Z", - "shell.execute_reply": "2024-06-15T18:59:33.878683Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.876760Z" + "iopub.execute_input": "2024-07-10T21:57:07.324707Z", + "iopub.status.busy": "2024-07-10T21:57:07.324636Z", + "iopub.status.idle": "2024-07-10T21:57:07.327169Z", + "shell.execute_reply": "2024-07-10T21:57:07.326972Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.324699Z" } }, "outputs": [ { "data": { "text/plain": [ - "(1.0, ((1, 2), (1, 1)))" + "(np.float64(1.0), ((1, 2), (1, 1)))" ] }, "execution_count": 24, @@ -969,11 +971,11 @@ "id": "1a071985-2d07-4473-a5a4-5c2ab151139d", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:33.879285Z", - "iopub.status.busy": "2024-06-15T18:59:33.879227Z", - "iopub.status.idle": "2024-06-15T18:59:33.963223Z", - "shell.execute_reply": "2024-06-15T18:59:33.962995Z", - "shell.execute_reply.started": "2024-06-15T18:59:33.879279Z" + "iopub.execute_input": "2024-07-10T21:57:07.327711Z", + "iopub.status.busy": "2024-07-10T21:57:07.327600Z", + "iopub.status.idle": "2024-07-10T21:57:07.410781Z", + "shell.execute_reply": "2024-07-10T21:57:07.410256Z", + "shell.execute_reply.started": "2024-07-10T21:57:07.327703Z" } }, "outputs": [ @@ -1028,7 +1030,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/notebooks/n-dimensional_pointsets.ipynb b/notebooks/n-dimensional_pointsets.ipynb index cb470f5..44978f7 100644 --- a/notebooks/n-dimensional_pointsets.ipynb +++ b/notebooks/n-dimensional_pointsets.ipynb @@ -18,11 +18,11 @@ "id": "2da42c3d-a668-456c-9d05-5b826d2ca963", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:19.800738Z", - "iopub.status.busy": "2024-06-15T18:59:19.800507Z", - "iopub.status.idle": "2024-06-15T18:59:19.832881Z", - "shell.execute_reply": "2024-06-15T18:59:19.832503Z", - "shell.execute_reply.started": "2024-06-15T18:59:19.800703Z" + "iopub.execute_input": "2024-07-10T21:57:28.422228Z", + "iopub.status.busy": "2024-07-10T21:57:28.422038Z", + "iopub.status.idle": "2024-07-10T21:57:28.450826Z", + "shell.execute_reply": "2024-07-10T21:57:28.450544Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.422207Z" } }, "outputs": [ @@ -30,11 +30,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "Last updated: 2024-06-15T14:59:19.824932-04:00\n", + "Last updated: 2024-07-10T17:57:28.442134-04:00\n", "\n", "Python implementation: CPython\n", - "Python version : 3.12.3\n", - "IPython version : 8.25.0\n", + "Python version : 3.12.4\n", + "IPython version : 8.26.0\n", "\n", "Compiler : Clang 16.0.6 \n", "OS : Darwin\n", @@ -59,11 +59,11 @@ "id": "5f2c2691-2f11-4649-aafd-eaf734d5c368", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:19.833802Z", - "iopub.status.busy": "2024-06-15T18:59:19.833671Z", - "iopub.status.idle": "2024-06-15T18:59:20.062575Z", - "shell.execute_reply": "2024-06-15T18:59:20.062380Z", - "shell.execute_reply.started": "2024-06-15T18:59:19.833784Z" + "iopub.execute_input": "2024-07-10T21:57:28.451498Z", + "iopub.status.busy": "2024-07-10T21:57:28.451397Z", + "iopub.status.idle": "2024-07-10T21:57:28.708230Z", + "shell.execute_reply": "2024-07-10T21:57:28.707977Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.451475Z" } }, "outputs": [ @@ -73,9 +73,9 @@ "text": [ "Watermark: 2.4.3\n", "\n", - "fastpair : 0.1.1.dev8+g5f8e7a5.d20240611\n", + "numpy : 2.0.0\n", + "fastpair : 0.1.1.dev12+gb5fa448.d20240622\n", "matplotlib: 3.9.0\n", - "numpy : 1.26.4\n", "\n" ] } @@ -114,11 +114,11 @@ "id": "26917e2e-d996-469e-9028-3edd638ffe10", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.063748Z", - "iopub.status.busy": "2024-06-15T18:59:20.063563Z", - "iopub.status.idle": "2024-06-15T18:59:20.065445Z", - "shell.execute_reply": "2024-06-15T18:59:20.065238Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.063740Z" + "iopub.execute_input": "2024-07-10T21:57:28.709409Z", + "iopub.status.busy": "2024-07-10T21:57:28.709287Z", + "iopub.status.idle": "2024-07-10T21:57:28.711253Z", + "shell.execute_reply": "2024-07-10T21:57:28.711056Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.709401Z" } }, "outputs": [], @@ -151,18 +151,18 @@ "id": "e7078d76-f6db-43c9-aff8-8c541ea385f9", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.065764Z", - "iopub.status.busy": "2024-06-15T18:59:20.065702Z", - "iopub.status.idle": "2024-06-15T18:59:20.068272Z", - "shell.execute_reply": "2024-06-15T18:59:20.068088Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.065758Z" + "iopub.execute_input": "2024-07-10T21:57:28.711632Z", + "iopub.status.busy": "2024-07-10T21:57:28.711561Z", + "iopub.status.idle": "2024-07-10T21:57:28.714223Z", + "shell.execute_reply": "2024-07-10T21:57:28.713985Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.711624Z" } }, "outputs": [ { "data": { "text/plain": [ - "[(10.236432494005134,)]" + "[(np.float64(10.236432494005134),)]" ] }, "execution_count": 4, @@ -188,20 +188,20 @@ "id": "c9a81f46-a864-4d96-a9a3-9e801a8a6e42", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.068756Z", - "iopub.status.busy": "2024-06-15T18:59:20.068653Z", - "iopub.status.idle": "2024-06-15T18:59:20.070411Z", - "shell.execute_reply": "2024-06-15T18:59:20.070230Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.068750Z" + "iopub.execute_input": "2024-07-10T21:57:28.714664Z", + "iopub.status.busy": "2024-07-10T21:57:28.714573Z", + "iopub.status.idle": "2024-07-10T21:57:28.716675Z", + "shell.execute_reply": "2024-07-10T21:57:28.716445Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.714657Z" } }, "outputs": [ { "data": { "text/plain": [ - "[(10.236432494005134, 19.009273926518706),\n", - " (2.8831922543926747, 18.972988942744877),\n", - " (6.236629040209709, 8.466528979451514)]" + "[(np.float64(10.236432494005134), np.float64(19.009273926518706)),\n", + " (np.float64(2.8831922543926747), np.float64(18.972988942744877)),\n", + " (np.float64(6.236629040209709), np.float64(8.466528979451514))]" ] }, "execution_count": 5, @@ -231,18 +231,19 @@ "id": "8a43ef42-621d-42b1-9ca6-cc1e5ec1d0b1", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.070857Z", - "iopub.status.busy": "2024-06-15T18:59:20.070765Z", - "iopub.status.idle": "2024-06-15T18:59:20.072578Z", - "shell.execute_reply": "2024-06-15T18:59:20.072408Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.070851Z" + "iopub.execute_input": "2024-07-10T21:57:28.717099Z", + "iopub.status.busy": "2024-07-10T21:57:28.717038Z", + "iopub.status.idle": "2024-07-10T21:57:28.719730Z", + "shell.execute_reply": "2024-07-10T21:57:28.719515Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.717092Z" } }, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 6, @@ -272,11 +273,11 @@ "id": "cccf5da4-94ad-46d6-89a6-17a1444ca15a", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.072982Z", - "iopub.status.busy": "2024-06-15T18:59:20.072923Z", - "iopub.status.idle": "2024-06-15T18:59:20.074833Z", - "shell.execute_reply": "2024-06-15T18:59:20.074665Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.072976Z" + "iopub.execute_input": "2024-07-10T21:57:28.720286Z", + "iopub.status.busy": "2024-07-10T21:57:28.720211Z", + "iopub.status.idle": "2024-07-10T21:57:28.723221Z", + "shell.execute_reply": "2024-07-10T21:57:28.722929Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.720279Z" } }, "outputs": [ @@ -284,8 +285,12 @@ "data": { "text/plain": [ "(4.0502751383410684,\n", - " ((18.870650112211077, 7.188420666831464, 15.696108239399543),\n", - " (17.38663089357139, 7.282768525810457, 19.463536292657878)))" + " ((np.float64(18.870650112211077),\n", + " np.float64(7.188420666831464),\n", + " np.float64(15.696108239399543)),\n", + " (np.float64(17.38663089357139),\n", + " np.float64(7.282768525810457),\n", + " np.float64(19.463536292657878))))" ] }, "execution_count": 7, @@ -316,11 +321,11 @@ "id": "c8c7dd0d-20ca-43cd-b22a-c0308f203497", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.075343Z", - "iopub.status.busy": "2024-06-15T18:59:20.075222Z", - "iopub.status.idle": "2024-06-15T18:59:20.167579Z", - "shell.execute_reply": "2024-06-15T18:59:20.167365Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.075337Z" + "iopub.execute_input": "2024-07-10T21:57:28.723751Z", + "iopub.status.busy": "2024-07-10T21:57:28.723664Z", + "iopub.status.idle": "2024-07-10T21:57:28.818350Z", + "shell.execute_reply": "2024-07-10T21:57:28.818114Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.723743Z" } }, "outputs": [ @@ -367,11 +372,11 @@ "id": "626ff3e1-727a-49ab-ad1b-91fd4eae5541", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.168108Z", - "iopub.status.busy": "2024-06-15T18:59:20.168036Z", - "iopub.status.idle": "2024-06-15T18:59:20.169974Z", - "shell.execute_reply": "2024-06-15T18:59:20.169784Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.168100Z" + "iopub.execute_input": "2024-07-10T21:57:28.818858Z", + "iopub.status.busy": "2024-07-10T21:57:28.818778Z", + "iopub.status.idle": "2024-07-10T21:57:28.820742Z", + "shell.execute_reply": "2024-07-10T21:57:28.820511Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.818850Z" } }, "outputs": [], @@ -402,11 +407,11 @@ "id": "144bebae-d91b-432a-b048-6b4f6d7e68d5", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.170357Z", - "iopub.status.busy": "2024-06-15T18:59:20.170288Z", - "iopub.status.idle": "2024-06-15T18:59:20.172189Z", - "shell.execute_reply": "2024-06-15T18:59:20.171978Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.170350Z" + "iopub.execute_input": "2024-07-10T21:57:28.821165Z", + "iopub.status.busy": "2024-07-10T21:57:28.821097Z", + "iopub.status.idle": "2024-07-10T21:57:28.823480Z", + "shell.execute_reply": "2024-07-10T21:57:28.823249Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.821157Z" } }, "outputs": [ @@ -414,8 +419,12 @@ "data": { "text/plain": [ "(3.738192198648357,\n", - " ((1.7129833428724872, 4.736210131921994, 16.025489304127937),\n", - " (5.232242684986328, 5.969822868282466, 16.284514811885607)))" + " ((np.float64(1.7129833428724872),\n", + " np.float64(4.736210131921994),\n", + " np.float64(16.025489304127937)),\n", + " (np.float64(5.232242684986328),\n", + " np.float64(5.969822868282466),\n", + " np.float64(16.284514811885607))))" ] }, "execution_count": 10, @@ -448,11 +457,11 @@ "id": "d26a20cc-5710-43d4-911f-733f85b5d882", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.172555Z", - "iopub.status.busy": "2024-06-15T18:59:20.172491Z", - "iopub.status.idle": "2024-06-15T18:59:20.265862Z", - "shell.execute_reply": "2024-06-15T18:59:20.265608Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.172549Z" + "iopub.execute_input": "2024-07-10T21:57:28.823968Z", + "iopub.status.busy": "2024-07-10T21:57:28.823886Z", + "iopub.status.idle": "2024-07-10T21:57:28.915380Z", + "shell.execute_reply": "2024-07-10T21:57:28.915121Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.823959Z" } }, "outputs": [ @@ -507,11 +516,11 @@ "id": "5c7921d4-9fd5-4fa0-9d9e-e39a4b12e2b4", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.267699Z", - "iopub.status.busy": "2024-06-15T18:59:20.267595Z", - "iopub.status.idle": "2024-06-15T18:59:20.395680Z", - "shell.execute_reply": "2024-06-15T18:59:20.395397Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.267689Z" + "iopub.execute_input": "2024-07-10T21:57:28.917381Z", + "iopub.status.busy": "2024-07-10T21:57:28.917271Z", + "iopub.status.idle": "2024-07-10T21:57:29.045927Z", + "shell.execute_reply": "2024-07-10T21:57:29.045598Z", + "shell.execute_reply.started": "2024-07-10T21:57:28.917372Z" } }, "outputs": [ @@ -573,18 +582,19 @@ "id": "a25c1e2b-7b5e-4cf4-ab8a-e267dca0b502", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.396449Z", - "iopub.status.busy": "2024-06-15T18:59:20.396296Z", - "iopub.status.idle": "2024-06-15T18:59:20.411426Z", - "shell.execute_reply": "2024-06-15T18:59:20.411189Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.396438Z" + "iopub.execute_input": "2024-07-10T21:57:29.046477Z", + "iopub.status.busy": "2024-07-10T21:57:29.046386Z", + "iopub.status.idle": "2024-07-10T21:57:29.060710Z", + "shell.execute_reply": "2024-07-10T21:57:29.060485Z", + "shell.execute_reply.started": "2024-07-10T21:57:29.046468Z" } }, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 13, @@ -612,11 +622,11 @@ "id": "e56fcf7d-739d-4e44-967e-b157fdc408b5", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.411981Z", - "iopub.status.busy": "2024-06-15T18:59:20.411911Z", - "iopub.status.idle": "2024-06-15T18:59:20.414050Z", - "shell.execute_reply": "2024-06-15T18:59:20.413832Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.411974Z" + "iopub.execute_input": "2024-07-10T21:57:29.061295Z", + "iopub.status.busy": "2024-07-10T21:57:29.061169Z", + "iopub.status.idle": "2024-07-10T21:57:29.063850Z", + "shell.execute_reply": "2024-07-10T21:57:29.063617Z", + "shell.execute_reply.started": "2024-07-10T21:57:29.061287Z" } }, "outputs": [ @@ -649,33 +659,33 @@ "id": "3a2dda4b-e65a-44c9-881b-1267bffe0425", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.414516Z", - "iopub.status.busy": "2024-06-15T18:59:20.414451Z", - "iopub.status.idle": "2024-06-15T18:59:20.416562Z", - "shell.execute_reply": "2024-06-15T18:59:20.416371Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.414509Z" + "iopub.execute_input": "2024-07-10T21:57:29.064633Z", + "iopub.status.busy": "2024-07-10T21:57:29.064540Z", + "iopub.status.idle": "2024-07-10T21:57:29.067659Z", + "shell.execute_reply": "2024-07-10T21:57:29.067431Z", + "shell.execute_reply.started": "2024-07-10T21:57:29.064625Z" } }, "outputs": [ { "data": { "text/plain": [ - "([(18.870650112211077,\n", - " 7.188420666831464,\n", - " 15.696108239399543,\n", - " 11.825563704588236),\n", - " (19.463536292657878,\n", - " 4.490486614702625,\n", - " 16.10991735856244,\n", - " 13.617924625616881)],\n", - " [(6.281485191595186,\n", - " 15.617152919852579,\n", - " 18.501034362350563,\n", - " 0.8032379106434839),\n", - " (19.60606658563202,\n", - " 0.9476558986387795,\n", - " 18.152996427027382,\n", - " 3.1155672960451475)])" + "([(np.float64(18.870650112211077),\n", + " np.float64(7.188420666831464),\n", + " np.float64(15.696108239399543),\n", + " np.float64(11.825563704588236)),\n", + " (np.float64(19.463536292657878),\n", + " np.float64(4.490486614702625),\n", + " np.float64(16.10991735856244),\n", + " np.float64(13.617924625616881))],\n", + " [(np.float64(6.281485191595186),\n", + " np.float64(15.617152919852579),\n", + " np.float64(18.501034362350563),\n", + " np.float64(0.8032379106434839)),\n", + " (np.float64(19.60606658563202),\n", + " np.float64(0.9476558986387795),\n", + " np.float64(18.152996427027382),\n", + " np.float64(3.1155672960451475))])" ] }, "execution_count": 15, @@ -701,11 +711,11 @@ "id": "cfedf7c1-83f2-4c4e-a83c-4741a681ba3d", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.416957Z", - "iopub.status.busy": "2024-06-15T18:59:20.416891Z", - "iopub.status.idle": "2024-06-15T18:59:20.419429Z", - "shell.execute_reply": "2024-06-15T18:59:20.419202Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.416950Z" + "iopub.execute_input": "2024-07-10T21:57:29.068203Z", + "iopub.status.busy": "2024-07-10T21:57:29.068117Z", + "iopub.status.idle": "2024-07-10T21:57:29.070228Z", + "shell.execute_reply": "2024-07-10T21:57:29.070032Z", + "shell.execute_reply.started": "2024-07-10T21:57:29.068195Z" } }, "outputs": [ @@ -713,14 +723,14 @@ "data": { "text/plain": [ "(1.471913992306667,\n", - " ((12.143319051427731,\n", - " 8.096696612806012,\n", - " 8.069117114956994,\n", - " 1.7566196855998584),\n", - " (12.855616484647092,\n", - " 8.883192737858987,\n", - " 7.978835783535024,\n", - " 0.7405309621851197)))" + " ((np.float64(12.143319051427731),\n", + " np.float64(8.096696612806012),\n", + " np.float64(8.069117114956994),\n", + " np.float64(1.7566196855998584)),\n", + " (np.float64(12.855616484647092),\n", + " np.float64(8.883192737858987),\n", + " np.float64(7.978835783535024),\n", + " np.float64(0.7405309621851197))))" ] }, "execution_count": 16, @@ -753,11 +763,11 @@ "id": "38fb8d6c-7a2b-48b3-b473-c2793451880c", "metadata": { "execution": { - "iopub.execute_input": "2024-06-15T18:59:20.419997Z", - "iopub.status.busy": "2024-06-15T18:59:20.419923Z", - "iopub.status.idle": "2024-06-15T18:59:20.796052Z", - "shell.execute_reply": "2024-06-15T18:59:20.795820Z", - "shell.execute_reply.started": "2024-06-15T18:59:20.419990Z" + "iopub.execute_input": "2024-07-10T21:57:29.070730Z", + "iopub.status.busy": "2024-07-10T21:57:29.070629Z", + "iopub.status.idle": "2024-07-10T21:57:29.511556Z", + "shell.execute_reply": "2024-07-10T21:57:29.511305Z", + "shell.execute_reply.started": "2024-07-10T21:57:29.070723Z" } }, "outputs": [ @@ -766,36 +776,36 @@ "output_type": "stream", "text": [ "points=100, dimensions=7\n", - " fp.closest_pair()=(22.22611077089287, ((75, 82, 62, 53, 97, 30, 37), (77, 89, 72, 61, 97, 44, 46)))\n", + " fp.closest_pair()=(np.float64(22.22611077089287), ((np.int64(75), np.int64(82), np.int64(62), np.int64(53), np.int64(97), np.int64(30), np.int64(37)), (np.int64(77), np.int64(89), np.int64(72), np.int64(61), np.int64(97), np.int64(44), np.int64(46))))\n", "points=200, dimensions=7\n", - " fp.closest_pair()=(15.491933384829668, ((62, 28, 18, 58, 90, 59, 24), (60, 33, 17, 52, 92, 58, 37)))\n", + " fp.closest_pair()=(np.float64(15.491933384829668), ((np.int64(62), np.int64(28), np.int64(18), np.int64(58), np.int64(90), np.int64(59), np.int64(24)), (np.int64(60), np.int64(33), np.int64(17), np.int64(52), np.int64(92), np.int64(58), np.int64(37))))\n", "\n", "points=100, dimensions=7\n", - " fp.closest_pair()=(22.22611077089287, ((75, 82, 62, 53, 97, 30, 37), (77, 89, 72, 61, 97, 44, 46)))\n", + " fp.closest_pair()=(np.float64(22.22611077089287), ((np.int64(75), np.int64(82), np.int64(62), np.int64(53), np.int64(97), np.int64(30), np.int64(37)), (np.int64(77), np.int64(89), np.int64(72), np.int64(61), np.int64(97), np.int64(44), np.int64(46))))\n", "points=200, dimensions=7\n", - " fp.closest_pair()=(15.491933384829668, ((62, 28, 18, 58, 90, 59, 24), (60, 33, 17, 52, 92, 58, 37)))\n", + " fp.closest_pair()=(np.float64(15.491933384829668), ((np.int64(62), np.int64(28), np.int64(18), np.int64(58), np.int64(90), np.int64(59), np.int64(24)), (np.int64(60), np.int64(33), np.int64(17), np.int64(52), np.int64(92), np.int64(58), np.int64(37))))\n", "\n", "points=100, dimensions=7\n", - " fp.closest_pair()=(22.22611077089287, ((75, 82, 62, 53, 97, 30, 37), (77, 89, 72, 61, 97, 44, 46)))\n", + " fp.closest_pair()=(np.float64(22.22611077089287), ((np.int64(75), np.int64(82), np.int64(62), np.int64(53), np.int64(97), np.int64(30), np.int64(37)), (np.int64(77), np.int64(89), np.int64(72), np.int64(61), np.int64(97), np.int64(44), np.int64(46))))\n", "points=200, dimensions=7\n", - " fp.closest_pair()=(15.491933384829668, ((62, 28, 18, 58, 90, 59, 24), (60, 33, 17, 52, 92, 58, 37)))\n", + " fp.closest_pair()=(np.float64(15.491933384829668), ((np.int64(62), np.int64(28), np.int64(18), np.int64(58), np.int64(90), np.int64(59), np.int64(24)), (np.int64(60), np.int64(33), np.int64(17), np.int64(52), np.int64(92), np.int64(58), np.int64(37))))\n", "\n", "points=100, dimensions=7\n", - " fp.closest_pair()=(22.22611077089287, ((75, 82, 62, 53, 97, 30, 37), (77, 89, 72, 61, 97, 44, 46)))\n", + " fp.closest_pair()=(np.float64(22.22611077089287), ((np.int64(75), np.int64(82), np.int64(62), np.int64(53), np.int64(97), np.int64(30), np.int64(37)), (np.int64(77), np.int64(89), np.int64(72), np.int64(61), np.int64(97), np.int64(44), np.int64(46))))\n", "points=200, dimensions=7\n", - " fp.closest_pair()=(15.491933384829668, ((62, 28, 18, 58, 90, 59, 24), (60, 33, 17, 52, 92, 58, 37)))\n", + " fp.closest_pair()=(np.float64(15.491933384829668), ((np.int64(62), np.int64(28), np.int64(18), np.int64(58), np.int64(90), np.int64(59), np.int64(24)), (np.int64(60), np.int64(33), np.int64(17), np.int64(52), np.int64(92), np.int64(58), np.int64(37))))\n", "\n", "points=100, dimensions=7\n", - " fp.closest_pair()=(22.22611077089287, ((75, 82, 62, 53, 97, 30, 37), (77, 89, 72, 61, 97, 44, 46)))\n", + " fp.closest_pair()=(np.float64(22.22611077089287), ((np.int64(75), np.int64(82), np.int64(62), np.int64(53), np.int64(97), np.int64(30), np.int64(37)), (np.int64(77), np.int64(89), np.int64(72), np.int64(61), np.int64(97), np.int64(44), np.int64(46))))\n", "points=200, dimensions=7\n", - " fp.closest_pair()=(15.491933384829668, ((62, 28, 18, 58, 90, 59, 24), (60, 33, 17, 52, 92, 58, 37)))\n", + " fp.closest_pair()=(np.float64(15.491933384829668), ((np.int64(62), np.int64(28), np.int64(18), np.int64(58), np.int64(90), np.int64(59), np.int64(24)), (np.int64(60), np.int64(33), np.int64(17), np.int64(52), np.int64(92), np.int64(58), np.int64(37))))\n", "\n", "points=100, dimensions=7\n", - " fp.closest_pair()=(22.22611077089287, ((75, 82, 62, 53, 97, 30, 37), (77, 89, 72, 61, 97, 44, 46)))\n", + " fp.closest_pair()=(np.float64(22.22611077089287), ((np.int64(75), np.int64(82), np.int64(62), np.int64(53), np.int64(97), np.int64(30), np.int64(37)), (np.int64(77), np.int64(89), np.int64(72), np.int64(61), np.int64(97), np.int64(44), np.int64(46))))\n", "points=200, dimensions=7\n", - " fp.closest_pair()=(15.491933384829668, ((62, 28, 18, 58, 90, 59, 24), (60, 33, 17, 52, 92, 58, 37)))\n", + " fp.closest_pair()=(np.float64(15.491933384829668), ((np.int64(62), np.int64(28), np.int64(18), np.int64(58), np.int64(90), np.int64(59), np.int64(24)), (np.int64(60), np.int64(33), np.int64(17), np.int64(52), np.int64(92), np.int64(58), np.int64(37))))\n", "\n", - "62.2 ms ± 5.66 ms per loop (mean ± std. dev. of 3 runs, 2 loops each)\n" + "73 ms ± 4.84 ms per loop (mean ± std. dev. of 3 runs, 2 loops each)\n" ] } ], @@ -845,7 +855,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/pyproject.toml b/pyproject.toml index ba8b498..0ac6a18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,7 @@ requires-python = ">=3.10" dependencies = [ "numpy>=1.24", "scipy>=1.10", + "typing_extensions", # only for 3.10 -- remove when 3.11+ ] [project.urls] @@ -48,6 +49,7 @@ tests = [ "pre-commit", "pytest", "pytest-cov", + "pytest-doctestplus", "ruff", "setuptools_scm", ] @@ -93,3 +95,8 @@ include = [ "*__init__.py" = [ "F401", # imported but unused ] + +[tool.mypy] +non_interactive = true +install_types = true +ignore_missing_imports = true