sphere-n 0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sphere_n/__init__.py ADDED
@@ -0,0 +1,16 @@
1
+ import sys
2
+
3
+ if sys.version_info[:2] >= (3, 8):
4
+ # TODO: Import directly (no need for conditional) when `python_requires = >= 3.9`
5
+ from importlib.metadata import PackageNotFoundError, version # pragma: no cover
6
+ else:
7
+ from importlib_metadata import PackageNotFoundError, version # pragma: no cover
8
+
9
+ try:
10
+ # Change here if project is renamed and does not equal the package name
11
+ dist_name = "sphere-n"
12
+ __version__ = version(dist_name)
13
+ except PackageNotFoundError: # pragma: no cover
14
+ __version__ = "unknown"
15
+ finally:
16
+ del version, PackageNotFoundError
sphere_n/cylind_n.py ADDED
@@ -0,0 +1,88 @@
1
+ """
2
+ This code defines a system for generating points on an n-dimensional sphere using a technique called cylindrical mapping. The main purpose is for the sake of comparison with the sphere_n.py code.
3
+
4
+ The code takes a list of integers as input, which are used as bases for the low-discrepancy sequence generators. These generators help create a more uniform distribution of points compared to random sampling.
5
+
6
+ The output of this code is a list of floating-point numbers representing coordinates on the n-dimensional sphere. Each time you call the pop() method of a CylindN object, it produces a new set of coordinates.
7
+
8
+ The code achieves its purpose through a recursive algorithm. It uses two main components: a van der Corput sequence generator (VdCorput) for one dimension, and either a Circle generator or another CylindN generator for the remaining dimensions. This recursive structure allows it to handle spheres of any dimension.
9
+
10
+ The main logic flow happens in the pop() method. It first generates a cosine value (cosphi) using the van der Corput sequence, mapping it to the range [-1, 1]. Then it calculates the sine value (sinphi) using the Pythagorean identity. The method then recursively generates coordinates for lower dimensions and scales them by sinphi, finally adding cosphi as the last coordinate.
11
+
12
+ An important data transformation occurs in the pop() method, where the uniform distribution from the van der Corput sequence is transformed into a cosine distribution, which is necessary for proper spherical mapping.
13
+
14
+ The code also includes a reseed() method, which allows you to reset the internal state of the generators. This is useful for reproducibility in scientific simulations or when you need to generate the same sequence of points multiple times.
15
+ """
16
+
17
+ from abc import abstractmethod, ABC
18
+ from typing import List
19
+
20
+ # import numexpr as ne
21
+ from lds_gen.lds import Circle, VdCorput # low-discrepancy sequence generators
22
+ import numpy as np
23
+ import math
24
+
25
+ PI: float = np.pi
26
+
27
+
28
+ class CylindGen(ABC):
29
+ """Base interface for n-sphere generators using cylindrical mapping."""
30
+
31
+ @abstractmethod
32
+ def pop(self) -> List[float]:
33
+ """Generates and returns a vector of values."""
34
+ raise NotImplementedError
35
+
36
+ @abstractmethod
37
+ def reseed(self, seed: int) -> None:
38
+ """Reseeds the generator with a new seed."""
39
+ raise NotImplementedError
40
+
41
+
42
+ class CylindN(CylindGen):
43
+ """Low-discrepency sequence generator using cylindrical mapping.
44
+
45
+ Examples:
46
+ >>> cgen = CylindN([2, 3, 5, 7])
47
+ >>> cgen.reseed(0)
48
+ >>> for _ in range(1):
49
+ ... print(cgen.pop())
50
+ ...
51
+ [0.4702654580212986, 0.5896942325314937, -0.565685424949238, -0.33333333333333337, 0.0]
52
+ """
53
+
54
+ def __init__(self, base: List[int]) -> None:
55
+ """_summary_
56
+
57
+ Args:
58
+ base (List[int]): _description_
59
+ """
60
+ n = len(base) - 1
61
+ assert n >= 1
62
+ self.vdc = VdCorput(base[0])
63
+ self.c_gen = Circle(base[1]) if n == 1 else CylindN(base[1:])
64
+
65
+ def pop(self) -> List[float]:
66
+ """_summary_
67
+
68
+ Returns:
69
+ List[float]: _description_
70
+ """
71
+ cosphi = 2.0 * self.vdc.pop() - 1.0 # map to [-1, 1]
72
+ sinphi = math.sqrt(1.0 - cosphi * cosphi)
73
+ return [xi * sinphi for xi in self.c_gen.pop()] + [cosphi]
74
+
75
+ def reseed(self, seed: int) -> None:
76
+ """_summary_
77
+
78
+ Args:
79
+ seed (int): _description_
80
+ """
81
+ self.vdc.reseed(seed)
82
+ self.c_gen.reseed(seed)
83
+
84
+
85
+ if __name__ == "__main__":
86
+ import doctest
87
+
88
+ doctest.testmod()
sphere_n/discrep_2.py ADDED
@@ -0,0 +1,26 @@
1
+ import numpy as np
2
+
3
+
4
+ def discrep_2(K, X):
5
+ """dispersion measure
6
+
7
+ Arguments:
8
+ K ([type]): [description]
9
+ X ([type]): [description]
10
+
11
+ Returns:
12
+ float: dispersion
13
+ """
14
+ nsimplex, n = K.shape
15
+ maxq = 0
16
+ minq = 1000
17
+ for k in range(nsimplex):
18
+ p = X[K[k, :], :]
19
+ for i in range(n - 1):
20
+ for j in range(i + 1, n):
21
+ dot = np.dot(p[i, :], p[j, :])
22
+ q = 1.0 - dot * dot
23
+ maxq = max(maxq, q)
24
+ minq = min(minq, q)
25
+ dis = np.arcsin(np.sqrt(maxq)) - np.arcsin(np.sqrt(minq))
26
+ return dis
sphere_n/sphere_n.py ADDED
@@ -0,0 +1,195 @@
1
+ """
2
+ Sphere N Generator
3
+
4
+ This code is a Sphere N Generator, which is designed to create points on the surface of spheres in different dimensions. It's a tool that mathematicians, scientists, or computer graphics programmers might use when they need to work with spherical shapes in multiple dimensions.
5
+
6
+ The main input for this code is a list of integers, which are used as bases for generating sequences of numbers. These bases are used to initialize different types of generators that create points on spheres.
7
+
8
+ The output of this code is a series of lists containing floating-point numbers. Each list represents a point on the surface of a sphere, with the number of elements in the list corresponding to the dimension of the sphere.
9
+
10
+ To achieve its purpose, the code uses several mathematical concepts and algorithms. It starts by defining some constants and helper functions that are used in the calculations. These functions (get_tp_odd, get_tp_even, and get_tp) create lookup tables for mapping values in different dimensions.
11
+
12
+ The code then defines several classes that generate points on spheres:
13
+
14
+ 1. SphereGen: This is an abstract base class that defines the common interface for all sphere generators.
15
+
16
+ 2. Sphere3: This class generates points on a 3-dimensional sphere. It uses a combination of van der Corput sequences and 2-dimensional sphere points to create 3D points.
17
+
18
+ 3. SphereN: This class can generate points on spheres of any dimension (3 or higher). It uses a recursive approach, building higher-dimensional spheres from lower-dimensional ones.
19
+
20
+ Each of these classes has methods to generate new points (pop) and to reset the generator with a new starting point (reseed).
21
+
22
+ The code achieves its purpose through a combination of mathematical transformations and recursive algorithms. It uses trigonometric functions (sine, cosine) and interpolation to map values from one range to another. The core idea is to generate sequences of numbers that, when interpreted as coordinates, create an even distribution across the surface of a sphere.
23
+
24
+ An important aspect of the code is its use of caching (@cache decorator) for some functions. This improves performance by storing the results of expensive calculations so they don't need to be repeated.
25
+
26
+ Overall, this code provides a flexible way to generate evenly distributed points on spheres of various dimensions, which can be useful in many scientific and graphical applications.
27
+ """
28
+
29
+ from abc import abstractmethod, ABC
30
+ from typing import List
31
+
32
+ # import numexpr as ne
33
+ from lds_gen.lds import Sphere, VdCorput # low-discrepancy sequence generators
34
+ from functools import cache
35
+ import numpy as np
36
+ import math
37
+
38
+ PI: float = np.pi
39
+ X: np.ndarray = np.linspace(0.0, PI, 300)
40
+ NEG_COSINE: np.ndarray = -np.cos(X)
41
+ SINE: np.ndarray = np.sin(X)
42
+ F2: np.ndarray = (X + NEG_COSINE * SINE) / 2.0
43
+ HALF_PI = PI / 2.0
44
+
45
+
46
+ @cache
47
+ def get_tp_odd(n: int) -> np.ndarray:
48
+ """table-lookup of mapping function for odd n
49
+
50
+ Returns:
51
+ np.ndarray: _description_
52
+ """
53
+ if n == 1:
54
+ return NEG_COSINE
55
+ tp_minus2 = get_tp_odd(n - 2) # NOQA
56
+ # return ne.evaluate("((n - 1) * tp_minus2 + NEG_COSINE * SINE**(n - 1)) / n")
57
+ return ((n - 1) * tp_minus2 + NEG_COSINE * SINE ** (n - 1)) / n
58
+
59
+
60
+ @cache
61
+ def get_tp_even(n: int) -> np.ndarray:
62
+ """table-lookup of mapping function for even n
63
+
64
+ Returns:
65
+ np.ndarray: _description_
66
+ """
67
+ if n == 0:
68
+ return X
69
+ tp_minus2 = get_tp_even(n - 2) # NOQA
70
+ # return ne.evaluate("((n - 1) * tp_minus2 + NEG_COSINE * SINE**(n - 1)) / n")
71
+ return ((n - 1) * tp_minus2 + NEG_COSINE * SINE ** (n - 1)) / n
72
+
73
+
74
+ def get_tp(n: int) -> np.ndarray:
75
+ """table-lookup of mapping function for n
76
+
77
+ Returns:
78
+ np.ndarray: _description_
79
+ """
80
+ return get_tp_even(n) if n % 2 == 0 else get_tp_odd(n)
81
+
82
+
83
+ class SphereGen(ABC):
84
+ """Base class for sphere generators."""
85
+
86
+ @abstractmethod
87
+ def pop(self) -> List[float]:
88
+ """Generates and returns a vector of values."""
89
+ raise NotImplementedError
90
+
91
+ @abstractmethod
92
+ def reseed(self, seed: int) -> None:
93
+ """Reseeds the generator with a new seed."""
94
+ raise NotImplementedError
95
+
96
+
97
+ class Sphere3(SphereGen):
98
+ """3-Sphere sequence generator
99
+
100
+ Examples:
101
+ >>> sgen = Sphere3([2, 3, 5])
102
+ >>> sgen.reseed(0)
103
+ >>> for _ in range(1):
104
+ ... print(sgen.pop())
105
+ ...
106
+ [0.2913440162992141, 0.8966646826186098, -0.33333333333333337, 6.123233995736766e-17]
107
+ """
108
+
109
+ vdc: VdCorput # van der Corput sequence generator
110
+ sphere2: Sphere # 2-Sphere generator
111
+
112
+ def __init__(self, base: List[int]) -> None:
113
+ """_summary_
114
+
115
+ Args:
116
+ base (List[int]): _description_
117
+ """
118
+ self.vdc = VdCorput(base[0])
119
+ self.sphere2 = Sphere(base[1:3])
120
+
121
+ def reseed(self, seed: int) -> None:
122
+ """_summary_
123
+
124
+ Args:
125
+ seed (int): _description_
126
+ """
127
+ self.vdc.reseed(seed)
128
+ self.sphere2.reseed(seed)
129
+
130
+ def pop(self) -> List[float]:
131
+ """_summary_
132
+
133
+ Returns:
134
+ List[float]: _description_
135
+ """
136
+ ti = HALF_PI * self.vdc.pop() # map to [t0, tm-1]
137
+ xi = np.interp(ti, F2, X)
138
+ cosxi = math.cos(xi)
139
+ sinxi = math.sin(xi)
140
+ return [sinxi * s for s in self.sphere2.pop()] + [cosxi]
141
+
142
+
143
+ class SphereN(SphereGen):
144
+ """Sphere-N sequence generator
145
+
146
+ Examples:
147
+ >>> sgen = SphereN([2, 3, 5, 7])
148
+ >>> sgen.reseed(0)
149
+ >>> for _ in range(1):
150
+ ... print(sgen.pop())
151
+ ...
152
+ [0.4809684718990214, 0.6031153874276115, -0.5785601510223212, 0.2649326520763179, 6.123233995736766e-17]
153
+ """
154
+
155
+ def __init__(self, base: List[int]) -> None:
156
+ """_summary_
157
+
158
+ Args:
159
+ base (List[int]): _description_
160
+ """
161
+ n = len(base) - 1
162
+ assert n >= 2
163
+ self.vdc = VdCorput(base[0])
164
+ self.s_gen = Sphere(base[1:3]) if n == 2 else SphereN(base[1:])
165
+ self.n = n
166
+ tp = get_tp(n)
167
+ self.range = tp[-1] - tp[0]
168
+
169
+ def pop(self) -> List[float]:
170
+ """_summary_
171
+
172
+ Returns:
173
+ List[float]: _description_
174
+ """
175
+ vd = self.vdc.pop()
176
+ tp = get_tp(self.n)
177
+ ti = tp[0] + self.range * vd # map to [t0, tm-1]
178
+ xi = np.interp(ti, tp, X)
179
+ sinphi = math.sin(xi)
180
+ return [xi * sinphi for xi in self.s_gen.pop()] + [math.cos(xi)]
181
+
182
+ def reseed(self, seed: int) -> None:
183
+ """_summary_
184
+
185
+ Args:
186
+ seed (int): _description_
187
+ """
188
+ self.vdc.reseed(seed)
189
+ self.s_gen.reseed(seed)
190
+
191
+
192
+ if __name__ == "__main__":
193
+ import doctest
194
+
195
+ doctest.testmod()
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: sphere-n
3
+ Version: 0.2
4
+ Summary: A library for low-discrepancy sequences
5
+ Home-page: https://github.com/pyscaffold/pyscaffold/
6
+ Author: Wai-Shing Luk
7
+ Author-email: luk036@gmail.com
8
+ License: MIT
9
+ Project-URL: Documentation, https://pyscaffold.org/
10
+ Platform: any
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Programming Language :: Python
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/x-rst; charset=UTF-8
15
+ License-File: LICENSE.txt
16
+ Requires-Dist: importlib-metadata
17
+ Requires-Dist: numpy
18
+ Provides-Extra: testing
19
+ Requires-Dist: setuptools; extra == "testing"
20
+ Requires-Dist: pytest; extra == "testing"
21
+ Requires-Dist: pytest-cov; extra == "testing"
22
+ Requires-Dist: numpy; extra == "testing"
23
+ Requires-Dist: scipy; extra == "testing"
24
+ Dynamic: license-file
25
+
26
+ [![codecov](https://codecov.io/gh/luk036/sphere-n/branch/main/graph/badge.svg?token=EIv4D8NlYj)](https://codecov.io/gh/luk036/sphere-n)
27
+ [![Documentation Status](https://readthedocs.org/projects/sphere-n/badge/?version=latest)](https://sphere-n.readthedocs.io/en/latest/?badge=latest)
28
+
29
+ # ⚽ sphere-n
30
+
31
+ > Generator of Low discrepancy Sequence on S_n
32
+
33
+ This library implements a generator for the generation of low-discrepancy sequences on n-dimensional spheres. Low-discrepancy sequences are utilized for the generation of points that are distributed uniformly across a given space. This technique is of significant value in a number of fields, including computer graphics, numerical integration, and Monte Carlo simulations.
34
+
35
+ The principal objective of this library is to facilitate the generation of points on the surface of spheres of varying dimensions, including three-dimensional and higher-dimensional spheres. The input required is the dimension of the sphere (n) and a set of base numbers to be used for the underlying sequence generation. The output is a series of vectors, with each vector representing a point on the surface of the n-dimensional sphere.
36
+
37
+ The library achieves this through a combination of mathematical calculations and recursive structures. The library utilizes a number of fundamental components, including:
38
+
39
+ 1. The VdCorput sequence generator produces a sequence of numbers that are evenly distributed between 0 and 1.
40
+ 2. Subsequently, the aforementioned numerical data is mapped onto the surface of a sphere through the use of interpolation functions.
41
+ 3. The SphereGen module represents an abstract base class that defines the common interface for all sphere generators.
42
+ 4. The recursive structures, namely Sphere3 and NSphere, facilitate the construction of higher-dimensional spheres from their lower-dimensional counterparts.
43
+
44
+ The primary logic flow begins with the construction of a SphereN object, which utilizes either a Sphere3 (for 3D) or a recursive process to generate lower-dimensional spheres for higher dimensions. In the generation of points, the VdCorput sequence is employed to obtain a base number, which is then subjected to a series of transformations involving sine, cosine, and interpolation in order to map it onto the surface of the sphere.
45
+
46
+ A noteworthy aspect of the library is its incorporation of caching (through the @cache decorator) to optimize performance by storing and reusing calculated values. Moreover, the library provides traits and structures that facilitate the adaptable deployment of the sphere generators. The SphereGen abstract base class serves to define a common interface for a variety of sphere generators, whereas the NSphere and SphereN structures are responsible for implementing the actual generation logic.
47
+
48
+ In conclusion, this library provides a sophisticated yet flexible method for generating evenly distributed points on high-dimensional spheres, which can be advantageous in numerous scientific and computational applications.
49
+
50
+ ## Dependencies
51
+
52
+ - [luk036/lds-gen](https://github.com/luk036/lds-gen)
53
+ - numpy
54
+ - scipy (for testing only)
55
+
56
+ ## 👀 See also
57
+
58
+ - [sphere-n-cpp](https://github.com/luk036/sphere-n-cpp)
59
+ - [sphere-n-rs](https://github.com/luk036/sphere-n-rs)
60
+ - [slides](https://luk036.github.io/n_sphere/slides.html)
61
+
62
+ ## 👉 Note
63
+
64
+ This project has been set up using PyScaffold 3.2.1. For details and usage
65
+ information on PyScaffold see <https://pyscaffold.org/>.
@@ -0,0 +1,9 @@
1
+ sphere_n/__init__.py,sha256=maG-vIFXReSK10FS8_urv6C-TfJrlIYSGKw9p9h3hmY,579
2
+ sphere_n/cylind_n.py,sha256=5zRpnSGPdzhM9SSsQBGF7Cr6_HSUWtzrubIL9537p1E,3612
3
+ sphere_n/discrep_2.py,sha256=Ts-D8Rov95aOc0etDc0mE_L7_dDqkamyC-Sm3B4vnCA,612
4
+ sphere_n/sphere_n.py,sha256=ouO9I1MpIDAEhA3S7KEVY9HRG0vEnXqNOA0gj_fmWqE,6723
5
+ sphere_n-0.2.dist-info/licenses/LICENSE.txt,sha256=MyvlyWiWdJ3ZpAOA4wziXlNa9Hbx8XnEL1Aztt9F7W8,1080
6
+ sphere_n-0.2.dist-info/METADATA,sha256=cCpMVrh1qR5T_s2M8oowSzrVghJVW4dZHauBV4N9g6g,4248
7
+ sphere_n-0.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
8
+ sphere_n-0.2.dist-info/top_level.txt,sha256=iHzEhUMhA0LQaS3boyXp_F3-Nz1VBrfWAufktLNGrdo,9
9
+ sphere_n-0.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (78.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Wai-Shing Luk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ sphere_n