sigmaepsilon.math 2.2.2__tar.gz → 2.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/PKG-INFO +1 -1
  2. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/pyproject.toml +1 -1
  3. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/__init__.py +2 -0
  4. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/approx/__init__.py +2 -0
  5. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/approx/functions.py +25 -15
  6. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/approx/lagrange.py +6 -4
  7. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/approx/ls.py +8 -5
  8. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/approx/ls_approx.py +2 -0
  9. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/approx/ls_poly.py +2 -0
  10. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/approx/ls_preproc.py +2 -0
  11. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/approx/mls.py +13 -15
  12. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/arraysetops.py +2 -0
  13. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/decorate.py +5 -2
  14. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/downloads.py +3 -2
  15. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/function/__init__.py +1 -0
  16. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/function/function.py +17 -21
  17. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/function/functions.py +7 -10
  18. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/function/metafunction.py +15 -9
  19. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/function/relation.py +18 -22
  20. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/function/symutils.py +8 -8
  21. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/function/testfunction.py +14 -2
  22. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/function/utils.py +4 -5
  23. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/graph/__init__.py +2 -0
  24. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/graph/graph.py +7 -10
  25. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/graph/utils.py +4 -5
  26. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/hist.py +2 -0
  27. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/knn.py +7 -5
  28. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/__init__.py +2 -0
  29. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/abstract.py +19 -4
  30. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/exceptions.py +6 -4
  31. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/frame.py +93 -99
  32. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/imap.py +2 -0
  33. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/logical.py +20 -28
  34. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/meta.py +73 -76
  35. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/solve.py +5 -0
  36. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/sparse/__init__.py +1 -0
  37. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/sparse/csr.py +12 -15
  38. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/sparse/jaggedarray.py +32 -43
  39. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/sparse/utils.py +6 -0
  40. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/tensor.py +42 -43
  41. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/testing.py +7 -0
  42. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/tr.py +2 -0
  43. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/utils.py +87 -53
  44. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/linalg/vector.py +22 -28
  45. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/logical.py +22 -32
  46. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/mathtypes.py +2 -0
  47. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/metautils.py +3 -3
  48. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/numint.py +8 -3
  49. sigmaepsilon_math-2.4.0/src/sigmaepsilon/math/optimize/__init__.py +25 -0
  50. sigmaepsilon_math-2.4.0/src/sigmaepsilon/math/optimize/bga.py +93 -0
  51. sigmaepsilon_math-2.4.0/src/sigmaepsilon/math/optimize/bitchromosome.py +123 -0
  52. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/optimize/ga.py +214 -97
  53. sigmaepsilon_math-2.4.0/src/sigmaepsilon/math/optimize/iga.py +111 -0
  54. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/optimize/lp.py +79 -21
  55. sigmaepsilon_math-2.4.0/src/sigmaepsilon/math/optimize/rga.py +149 -0
  56. sigmaepsilon_math-2.4.0/src/sigmaepsilon/math/optimize/selection.py +126 -0
  57. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/optimize/state.py +12 -3
  58. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/src/sigmaepsilon/math/utils.py +34 -34
  59. sigmaepsilon_math-2.2.2/src/sigmaepsilon/math/optimize/__init__.py +0 -10
  60. sigmaepsilon_math-2.2.2/src/sigmaepsilon/math/optimize/bga.py +0 -192
  61. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/LICENSE +0 -0
  62. {sigmaepsilon_math-2.2.2 → sigmaepsilon_math-2.4.0}/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sigmaepsilon.math
3
- Version: 2.2.2
3
+ Version: 2.4.0
4
4
  Summary: A Python Library for Applied Mathematics in Physical Sciences.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "sigmaepsilon.math"
7
- version = "2.2.2"
7
+ version = "2.4.0"
8
8
  description = "A Python Library for Applied Mathematics in Physical Sciences."
9
9
  classifiers=[ # https://pypi.org/classifiers/
10
10
  "Development Status :: 5 - Production/Stable",
@@ -1,3 +1,5 @@
1
+ """General-purpose applied-math tools for the SigmaEpsilon ecosystem."""
2
+
1
3
  from os.path import dirname, abspath
2
4
  from importlib.metadata import metadata
3
5
 
@@ -1,3 +1,5 @@
1
+ """Least-squares style approximation tools (moving least squares, weight functions, Lagrange interpolation)."""
2
+
1
3
  from .ls import moving_least_squares, least_squares, weighted_least_squares
2
4
  from .functions import (
3
5
  CubicWeightFunction,
@@ -1,3 +1,5 @@
1
+ """Weight functions used by the moving least squares approximator."""
2
+
1
3
  from typing import Tuple, Any, Iterable
2
4
  from numbers import Number
3
5
 
@@ -9,9 +11,7 @@ from ..function import Function
9
11
 
10
12
 
11
13
  class MLSWeightFunction(Function):
12
- """
13
- Base class for weight functions for the moving least squares method.
14
- """
14
+ """Base class for weight functions for the moving least squares method."""
15
15
 
16
16
  def __init__(
17
17
  self,
@@ -48,6 +48,7 @@ class MLSWeightFunction(Function):
48
48
 
49
49
  @property
50
50
  def core(self) -> ndarray | Iterable[Number] | None:
51
+ """Return the core (center) of the weight function."""
51
52
  return self._core
52
53
 
53
54
  @core.setter
@@ -66,6 +67,7 @@ class MLSWeightFunction(Function):
66
67
 
67
68
  @property
68
69
  def supportdomain(self) -> ndarray | Iterable[Number] | None:
70
+ """Return the support domain of the weight function."""
69
71
  return self._supportdomain
70
72
 
71
73
  @supportdomain.setter
@@ -81,6 +83,7 @@ class MLSWeightFunction(Function):
81
83
  return
82
84
 
83
85
  def preproc_evaluation(self, x: Iterable[Number]):
86
+ """Validate and coerce the evaluation point `x` into a NumPy array."""
84
87
  if not isinstance(x, (ndarray, float)):
85
88
  if isinstance(x, Iterable):
86
89
  x = np.array(x)
@@ -90,16 +93,17 @@ class MLSWeightFunction(Function):
90
93
  )
91
94
 
92
95
  def value(self, x: Iterable[Number]) -> float:
93
- """
94
- Evaluates the function.
95
- """
96
+ """Evaluate the function."""
96
97
  raise NotImplementedError
97
98
 
98
99
 
99
100
  def isMLSWeightFunction(f: Any) -> bool:
100
- """
101
- Returns `True` if the argument is a valid weight function for the
102
- moving least squares method.
101
+ """Return `True` if the argument is a valid weight function for the moving least squares method.
102
+
103
+ Parameters
104
+ ----------
105
+ f : Any
106
+ The object to check.
103
107
  """
104
108
  c1 = isinstance(f, MLSWeightFunction)
105
109
  c2 = MLSWeightFunction in list(type(f).__bases__)
@@ -107,9 +111,7 @@ def isMLSWeightFunction(f: Any) -> bool:
107
111
 
108
112
 
109
113
  class ConstantWeightFunction(MLSWeightFunction):
110
- """
111
- A constant weight function for the moving least squares method.
112
- """
114
+ """A constant weight function for the moving least squares method."""
113
115
 
114
116
  def __init__(self, *, value: Number = 1.0, **kwargs):
115
117
  super().__init__(**kwargs)
@@ -117,6 +119,7 @@ class ConstantWeightFunction(MLSWeightFunction):
117
119
  return
118
120
 
119
121
  def value(self, x: Iterable[Number]) -> float:
122
+ """Return the value of the weight function at `x`."""
120
123
  if self.supportdomain is None:
121
124
  return self._value
122
125
 
@@ -129,16 +132,16 @@ class ConstantWeightFunction(MLSWeightFunction):
129
132
  return self._value
130
133
 
131
134
  def gradient(self, x: Iterable[Number]) -> ndarray:
135
+ """Return the gradient of the weight function at `x`."""
132
136
  return np.zeros(self.dimension, dtype=float)
133
137
 
134
138
  def Hessian(self, x: Iterable[Number]) -> ndarray:
139
+ """Return the Hessian of the weight function at `x`."""
135
140
  return np.zeros((self.dimension, self.dimension), dtype=float)
136
141
 
137
142
 
138
143
  class SingularWeightFunction(MLSWeightFunction):
139
- """
140
- A singular weight function for the moving least squares method.
141
- """
144
+ """A singular weight function for the moving least squares method."""
142
145
 
143
146
  def __init__(self, *, eps: Number = 1e-5, **kwargs):
144
147
  super().__init__(**kwargs)
@@ -146,13 +149,16 @@ class SingularWeightFunction(MLSWeightFunction):
146
149
  return
147
150
 
148
151
  def value(self, x: Iterable[Number]):
152
+ """Return the value of the weight function at `x`."""
149
153
  self.preproc_evaluation(x)
150
154
  return 1 / (norm(np.subtract(self.core, x)) ** 2 + self.eps**2)
151
155
 
152
156
  def gradient(self, x: Iterable[Number]) -> ndarray:
157
+ """Return the gradient of the weight function at `x`."""
153
158
  return np.zeros(self.dimension, dtype=float)
154
159
 
155
160
  def Hessian(self, x: Iterable[Number]) -> ndarray:
161
+ """Return the Hessian of the weight function at `x`."""
156
162
  return np.zeros((self.dimension, self.dimension), dtype=float)
157
163
 
158
164
 
@@ -170,6 +176,7 @@ class CubicWeightFunction(MLSWeightFunction):
170
176
  """
171
177
 
172
178
  def evaluate(self, x: Iterable[Number]) -> Tuple[float, ndarray, ndarray]:
179
+ """Return the value, gradient and Hessian of the weight function at `x`."""
173
180
  if self.dimension == 1:
174
181
  return self._evaluate_1d(x)
175
182
  elif self.dimension == 2:
@@ -259,16 +266,19 @@ class CubicWeightFunction(MLSWeightFunction):
259
266
  return val, grad, Hessian
260
267
 
261
268
  def value(self, x: Iterable[Number]) -> float:
269
+ """Return the value of the weight function at `x`."""
262
270
  self.preproc_evaluation(x)
263
271
  res, _, _ = self.evaluate(x)
264
272
  return res
265
273
 
266
274
  def gradient(self, x: Iterable[Number]) -> ndarray:
275
+ """Return the gradient of the weight function at `x`."""
267
276
  self.preproc_evaluation(x)
268
277
  _, res, _ = self.evaluate(x)
269
278
  return res
270
279
 
271
280
  def Hessian(self, x: Iterable[Number]) -> ndarray:
281
+ """Return the Hessian of the weight function at `x`."""
272
282
  self.preproc_evaluation(x)
273
283
  _, _, res = self.evaluate(x)
274
284
  return res
@@ -1,3 +1,5 @@
1
+ """Lagrange polynomial generation and 1d approximation utilities."""
2
+
1
3
  from typing import Iterable, Callable
2
4
 
3
5
  import sympy as sy
@@ -33,8 +35,9 @@ def gen_Lagrange_1d(
33
35
  lambdify: bool = False,
34
36
  out: dict | None = None
35
37
  ) -> dict:
36
- """
37
- Generates Lagrange polynomials and their derivatives up to 3rd, for approximation
38
+ """Generate Lagrange polynomials and their derivatives.
39
+
40
+ Generates polynomials and their derivatives up to 3rd order, for approximation
38
41
  in 1d space, based on N input pairs of position and value. Geometrical parameters
39
42
  can be numeric or symbolic.
40
43
 
@@ -165,8 +168,7 @@ def gen_Lagrange_1d(
165
168
  def approx_Lagrange_1d(
166
169
  points: Iterable, values: Iterable, lambdify: bool = False
167
170
  ) -> Callable:
168
- """
169
- Returns a callable that maps from 'source' to 'target' in 1d.
171
+ """Return a callable that maps from 'source' to 'target' in 1d.
170
172
 
171
173
  Parameters
172
174
  ----------
@@ -1,3 +1,5 @@
1
+ """Least squares and moving least squares approximation."""
2
+
1
3
  from typing import Callable, Iterable
2
4
 
3
5
  import numpy as np
@@ -18,8 +20,9 @@ def moving_least_squares(
18
20
  w: Callable | None = None,
19
21
  **kwargs,
20
22
  ) -> Callable:
21
- """
22
- Moving least squares approximation. The usage is the same as for the
23
+ """Perform moving least squares approximation.
24
+
25
+ The usage is the same as for the
23
26
  :func:`~sigmaepsilon.math.approx.ls.weighted_least_squares` function.
24
27
  """
25
28
  dim = 1 if len(points.shape) == 1 else points.shape[1]
@@ -50,7 +53,8 @@ def least_squares(
50
53
  deg: int = 1,
51
54
  order: int = 2,
52
55
  ) -> Callable:
53
- """
56
+ r"""Fit a polynomial to the given points and values in the least-squares sense.
57
+
54
58
  Given :math:`N` points located at :math:`\mathbf{x}_i` in :math:`\mathbb{R}^d`
55
59
  where :math:`i \in [1 \dots N]`. The returned fit function approximates the given
56
60
  values :math:`f_i` at :math:`\mathbf{x}_i` in the least-squares sence with the
@@ -95,8 +99,7 @@ def weighted_least_squares(
95
99
  order: int = 2,
96
100
  w: Callable | None = None,
97
101
  ) -> Callable:
98
- """
99
- Returns a Callable that can be used to approximate over datasets.
102
+ """Return a Callable that can be used to approximate over datasets.
100
103
 
101
104
  Parameters
102
105
  ----------
@@ -1,3 +1,5 @@
1
+ """Numba-jitted kernels for moving least squares approximation and its derivatives."""
2
+
1
3
  from typing import Tuple
2
4
 
3
5
  from numpy import ndarray
@@ -1,3 +1,5 @@
1
+ """Polynomial basis functions and their derivatives for least squares approximation."""
2
+
1
3
  import numpy as np
2
4
 
3
5
 
@@ -1,3 +1,5 @@
1
+ """Assembly of the moment matrices used by moving least squares approximation."""
2
+
1
3
  from typing import Callable, Tuple
2
4
 
3
5
  import numpy as np
@@ -1,3 +1,5 @@
1
+ """High performance, object oriented moving least squares approximation."""
2
+
1
3
  from numbers import Number
2
4
 
3
5
  from numpy import ndarray
@@ -33,9 +35,9 @@ def _approximate_nd(
33
35
 
34
36
 
35
37
  class MLSApproximator:
36
- """
37
- Object oriented, high performance implementation of a specific version of the
38
- moving least squares method. This implementation is less flexible than the others,
38
+ """Object oriented, high performance implementation of moving least squares.
39
+
40
+ This implementation is less flexible than the others,
39
41
  but performes well for extremely large datasets too. If you want to experiment
40
42
  with the hyperparameters of the MLS as a method, it is suggested to use the other
41
43
  solutions offered by the library.
@@ -130,32 +132,28 @@ class MLSApproximator:
130
132
 
131
133
  @property
132
134
  def neighbours(self) -> ndarray | None:
133
- """
134
- Returns the neighbours of the target points. If the neighbours are not
135
- calculated yet, it returns None.
135
+ """Return the neighbours of the target points.
136
+
137
+ If the neighbours are not calculated yet, it returns None.
136
138
  """
137
139
  return self._neighbours
138
140
 
139
141
  @neighbours.setter
140
142
  def neighbours(self, val: ndarray) -> None:
141
- """
142
- Sets the neighbours of the target points.
143
- """
143
+ """Set the neighbours of the target points."""
144
144
  self._neighbours = val
145
145
 
146
146
  @property
147
147
  def factors(self) -> ndarray | None:
148
- """
149
- Returns the factors of the target points. If the factors are not
150
- calculated yet, it returns None.
148
+ """Return the factors of the target points.
149
+
150
+ If the factors are not calculated yet, it returns None.
151
151
  """
152
152
  return self._factors
153
153
 
154
154
  @factors.setter
155
155
  def factors(self, val: ndarray) -> None:
156
- """
157
- Sets the factors of the target points.
158
- """
156
+ """Set the factors of the target points."""
159
157
  self._factors = val
160
158
 
161
159
  def _calc_factors_and_neighbours(self, X_S: ndarray, X_T: ndarray) -> None:
@@ -1,3 +1,5 @@
1
+ """Set operations on arrays, including unique-element finding for 2d arrays."""
2
+
1
3
  import numpy as np
2
4
  from numpy import ndarray
3
5
  from awkward import Array as akarray
@@ -1,3 +1,5 @@
1
+ """Decorators shared across the package."""
2
+
1
3
  from typing import Callable, Any
2
4
  import numpy as np
3
5
 
@@ -10,8 +12,9 @@ def _squeeze_if_array(arr: Any) -> Any:
10
12
 
11
13
 
12
14
  def squeeze(default: bool = True) -> Callable:
13
- """
14
- A decorator that squeezes outputs of a function if
15
+ """Return a decorator that squeezes outputs of a function.
16
+
17
+ Applies when
15
18
  * the result is a NumPy array
16
19
  * the result is a tuple of NumPy arrays
17
20
  * the result is a dictionary of NumPy arrays as values
@@ -1,3 +1,5 @@
1
+ """Utilities for downloading test data used by the library."""
2
+
1
3
  import numpy as np
2
4
 
3
5
  from sigmaepsilon.core.downloads import download_file, delete_downloads
@@ -10,8 +12,7 @@ __all__ = [
10
12
 
11
13
 
12
14
  def download_mls_testdata() -> np.ndarray:
13
- """
14
- Downloads the data of a cloud of points.
15
+ """Download the data of a cloud of points.
15
16
 
16
17
  Returns
17
18
  -------
@@ -1,4 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
+ """Function and relation objects used to model optimization problems."""
2
3
  from .function import Function, FunctionLike
3
4
  from .relation import Equality, InEquality, Relation
4
5
 
@@ -1,3 +1,5 @@
1
+ """Base class for symbolic and numerical functions."""
2
+
1
3
  from typing import TypeVar, Callable, Iterable
2
4
  from collections import OrderedDict
3
5
  import warnings
@@ -19,8 +21,9 @@ FunctionLike = TypeVar("FunctionLike", str, Callable, Expr)
19
21
 
20
22
 
21
23
  class Function(MetaFunction):
22
- """
23
- Base class for all kinds of functions. It can be used to represent
24
+ """Base class for all kinds of functions.
25
+
26
+ It can be used to represent
24
27
  symbolic and numerical functions. The class is designed to be as
25
28
  flexible as possible, so it can be used in a wide range of applications.
26
29
 
@@ -182,6 +185,7 @@ class Function(MetaFunction):
182
185
  variables: Iterable | None = None,
183
186
  **kwargs
184
187
  ):
188
+ """Update the instance in place with new function definitions."""
185
189
  self.from_str = None
186
190
 
187
191
  if f0 is not None:
@@ -202,8 +206,8 @@ class Function(MetaFunction):
202
206
 
203
207
  @property
204
208
  def symbolic(self) -> bool:
205
- """
206
- Returns `True` if the function is a fit subject of symbolic manipulation.
209
+ """Return `True` if the function is a fit subject of symbolic manipulation.
210
+
207
211
  This is probably only true if the object was created from a string or
208
212
  `sympy` expression.
209
213
  """
@@ -217,9 +221,7 @@ class Function(MetaFunction):
217
221
 
218
222
  @property
219
223
  def linear(self) -> bool:
220
- """
221
- Returns True if the function is at most linear in all of its variables.
222
- """
224
+ """Return True if the function is at most linear in all of its variables."""
223
225
  warnings.warn(
224
226
  "The property `linear` is deprecated and will be removed in a future version. "
225
227
  "Use `is_linear` instead.",
@@ -230,9 +232,7 @@ class Function(MetaFunction):
230
232
 
231
233
  @property
232
234
  def is_linear(self) -> bool:
233
- """
234
- Returns `True` if the function is at most linear in all of its variables.
235
- """
235
+ """Return `True` if the function is at most linear in all of its variables."""
236
236
  if self.is_symbolic:
237
237
  return all(
238
238
  np.array([degree(self.expr, v) for v in self.variables], dtype=int) <= 1
@@ -242,25 +242,22 @@ class Function(MetaFunction):
242
242
 
243
243
  @property
244
244
  def is_symbolic(self) -> bool:
245
- """
246
- Returns `True` if the function is a fit subject of symbolic manipulation.
245
+ """Return `True` if the function is a fit subject of symbolic manipulation.
246
+
247
247
  This is probably only true if the object was created from a string or
248
248
  `SymPy` expression.
249
249
  """
250
250
  return self.expr is not None
251
251
 
252
252
  def simplify(self) -> None:
253
- """
254
- Simplifies the symbolic expression of the instance.
255
- """
253
+ """Simplify the symbolic expression of the instance."""
256
254
  if self.is_symbolic:
257
255
  self.expr = self.expr.simplify()
258
256
  else:
259
257
  raise TypeError("This is exclusive to symbolic functions.")
260
258
 
261
259
  def linear_coefficients(self, normalize: bool = False) -> dict | None:
262
- """
263
- Returns the linear coeffiecients, if the function is symbolic and linear.
260
+ """Return the linear coeffiecients, if the function is symbolic and linear.
264
261
 
265
262
  Parameters
266
263
  ----------
@@ -284,8 +281,7 @@ class Function(MetaFunction):
284
281
  return None
285
282
 
286
283
  def coefficients(self, normalize: bool = False) -> dict | None:
287
- """
288
- Returns the coefficients if the function is symbolic.
284
+ """Return the coefficients if the function is symbolic.
289
285
 
290
286
  Parameters
291
287
  ----------
@@ -322,8 +318,8 @@ class Function(MetaFunction):
322
318
  return None
323
319
 
324
320
  def to_latex(self) -> str:
325
- """
326
- Returns the LaTeX code of the symbolic expression of the instance.
321
+ """Return the LaTeX code of the symbolic expression of the instance.
322
+
327
323
  Only for symbolic functions.
328
324
 
329
325
  Examples
@@ -1,3 +1,5 @@
1
+ """Standard benchmark test functions for optimizers."""
2
+
1
3
  import sympy as sy
2
4
 
3
5
  from .testfunction import TestMinFunction2D
@@ -14,8 +16,7 @@ __all__ = [
14
16
 
15
17
 
16
18
  def Rosenbrock(a: float = 1, b: float = 100) -> TestMinFunction2D:
17
- """
18
- Implements the Rosenbrock function, aka. Banana function.
19
+ """Implement the Rosenbrock function, aka. Banana function.
19
20
 
20
21
  :math:`f(x, y) = (a - x)^2 + b (y - x^2)^2`
21
22
 
@@ -29,8 +30,7 @@ def Rosenbrock(a: float = 1, b: float = 100) -> TestMinFunction2D:
29
30
 
30
31
 
31
32
  def Himmelblau() -> TestMinFunction2D:
32
- """
33
- Creates the Himmelblau's function object.
33
+ """Create the Himmelblau's function object.
34
34
 
35
35
  :math:`f(x,y) = (x^2 + y - 11)^2 + (x + y^2 - 7)^2`
36
36
 
@@ -50,8 +50,7 @@ def Himmelblau() -> TestMinFunction2D:
50
50
 
51
51
 
52
52
  def GoldsteinPrice() -> TestMinFunction2D:
53
- """
54
- Creates the Goldstein-Price function object.
53
+ r"""Create the Goldstein-Price function object.
55
54
 
56
55
  .. math::
57
56
  :nowrap:
@@ -72,8 +71,7 @@ def GoldsteinPrice() -> TestMinFunction2D:
72
71
 
73
72
 
74
73
  def Beale() -> TestMinFunction2D:
75
- """
76
- Creates the Beale function object.
74
+ r"""Create the Beale function object.
77
75
 
78
76
  .. math::
79
77
  :nowrap:
@@ -93,8 +91,7 @@ def Beale() -> TestMinFunction2D:
93
91
 
94
92
 
95
93
  def Matyas() -> TestMinFunction2D:
96
- """
97
- Creates the Matyas function object.
94
+ """Create the Matyas function object.
98
95
 
99
96
  :math:`f(x, y) = 0.26 (x^2 + y^2) - 0.48 x y`
100
97
 
@@ -1,3 +1,5 @@
1
+ """Metaclass and base class shared by symbolic and numerical functions."""
2
+
1
3
  from sympy import Expr
2
4
 
3
5
  from sigmaepsilon.core.abstract import ABCMeta_Weak
@@ -5,11 +7,10 @@ from .symutils import symbolize
5
7
 
6
8
 
7
9
  class ABCMeta_MetaFunction(ABCMeta_Weak):
8
- """
9
- Metaclass for defining ABCs for algebraic structures.
10
- """
10
+ """Metaclass for defining ABCs for algebraic structures."""
11
11
 
12
12
  def __new__(metaclass, name, bases, namespace, /, **kwargs):
13
+ """Create a new class, promoting `value`/`gradient`/`Hessian` to `f`/`g`/`G`."""
13
14
  cls = super().__new__(metaclass, name, bases, namespace, **kwargs)
14
15
  if "value" in namespace:
15
16
  cls.f = namespace["value"]
@@ -24,14 +25,21 @@ class ABCMeta_MetaFunction(ABCMeta_Weak):
24
25
 
25
26
 
26
27
  class MetaFunction(metaclass=ABCMeta_MetaFunction):
28
+ """Base class providing the `f`/`g`/`G` interface for functions.
29
+
30
+ Subclasses that define `value`, `gradient` and/or `Hessian` methods
31
+ automatically get those promoted to `f`, `g` and `G` respectively, via
32
+ :class:`ABCMeta_MetaFunction`.
33
+ """
34
+
27
35
  __slots__ = ("f0", "f1", "f2", "dimension", "domain", "expr", "variables", "vmap")
28
36
 
29
37
  def __call__(self, *args, **kwargs):
38
+ """Return the function value, equivalent to calling :meth:`f`."""
30
39
  return self.f(*args, **kwargs)
31
40
 
32
41
  def f(self, *args, **kwargs):
33
- """
34
- Returns the function value.
42
+ """Return the function value.
35
43
 
36
44
  For this operation the object must have an implementation of
37
45
 
@@ -42,8 +50,7 @@ class MetaFunction(metaclass=ABCMeta_MetaFunction):
42
50
  return self.f0(*args, **kwargs)
43
51
 
44
52
  def g(self, *args, **kwargs):
45
- """
46
- Returns the gradient vector if available.
53
+ """Return the gradient vector if available.
47
54
 
48
55
  For this operation the object must have an implementation of
49
56
 
@@ -54,8 +61,7 @@ class MetaFunction(metaclass=ABCMeta_MetaFunction):
54
61
  return self.f1(*args, **kwargs)
55
62
 
56
63
  def G(self, *args, **kwargs):
57
- """
58
- Returns the Hessian matrix if available.
64
+ """Return the Hessian matrix if available.
59
65
 
60
66
  For this operation the object must have an implementation of
61
67