aisp 0.1.35__py3-none-any.whl → 0.1.40__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.
aisp/nsa/_ns_core.py ADDED
@@ -0,0 +1,153 @@
1
+ """ns: Negative Selection
2
+
3
+ The functions perform detector checks and utilize Numba decorators for Just-In-Time compilation
4
+ """
5
+
6
+ import numpy.typing as npt
7
+ from numba import njit, types
8
+
9
+ from ..utils.distance import compute_metric_distance, hamming
10
+
11
+
12
+ @njit(
13
+ [(
14
+ types.boolean[:, :],
15
+ types.boolean[:],
16
+ types.float64
17
+ )],
18
+ cache=True
19
+ )
20
+ def check_detector_bnsa_validity(
21
+ x_class: npt.NDArray,
22
+ vector_x: npt.NDArray,
23
+ aff_thresh: float
24
+ ) -> bool:
25
+ """
26
+ Checks the validity of a candidate detector (vector_x) against samples from a class (x_class)
27
+ using the Hamming distance. A detector is considered INVALID if its distance to any sample
28
+ in ``x_class`` is less than or equal to ``aff_thresh``.
29
+
30
+ Parameters
31
+ ----------
32
+ * x_class (``npt.NDArray``): Array containing the class samples. Expected shape:
33
+ (n_samples, n_features).
34
+ * vector_x (``npt.NDArray``): Array representing the detector. Expected shape: (n_features,).
35
+ * aff_thresh (``float``): Affinity threshold.
36
+
37
+ Returns
38
+ ----------
39
+ * True if the detector is valid, False otherwise.
40
+ """
41
+ n = x_class.shape[1]
42
+ if n != vector_x.shape[0]:
43
+ return False
44
+
45
+ for i in range(x_class.shape[0]):
46
+ # Calculate the normalized Hamming Distance
47
+ if hamming(x_class[i], vector_x) <= aff_thresh:
48
+ return False
49
+ return True
50
+
51
+
52
+ @njit(
53
+ [(
54
+ types.boolean[:],
55
+ types.boolean[:, :, :],
56
+ types.float64
57
+ )],
58
+ cache=True
59
+ )
60
+ def bnsa_class_prediction(
61
+ features: npt.NDArray,
62
+ class_detectors: npt.NDArray,
63
+ aff_thresh: float
64
+ ) -> int:
65
+ """
66
+ Defines the class of a sample from the non-self detectors.
67
+
68
+ Parameters
69
+ ----------
70
+ * features (``npt.NDArray``): binary sample to be classified (shape: [n_features]).
71
+ * class_detectors (``npt.NDArray``): Array containing the detectors of all classes
72
+ (shape: [n_classes, n_detectors, n_features]).
73
+ * aff_thresh (``float``): Affinity threshold that determines whether a detector recognizes the
74
+ sample as non-self.
75
+
76
+ Returns
77
+ ----------
78
+ * int: Index of the predicted class. Returns -1 if it is non-self for all classes.
79
+ """
80
+ n_classes, n_detectors, _ = class_detectors.shape
81
+ best_class_idx = -1
82
+ best_avg_distance = 0
83
+
84
+ for class_index in range(n_classes):
85
+ total_distance = 0.0
86
+ class_found = True
87
+
88
+ # Calculates the Hamming distance between the row and all detectors.
89
+ for detector_index in range(n_detectors):
90
+ # Calculates the normalized Hamming distance between the sample and the detector
91
+ distance = hamming(features, class_detectors[class_index][detector_index])
92
+
93
+ # If the distance is less than or equal to the threshold, the detector recognizes
94
+ # the sample as non-self.
95
+ if distance <= aff_thresh:
96
+ class_found = False
97
+ break
98
+ total_distance += distance
99
+
100
+ # if the sample is self for the class
101
+ if class_found:
102
+ avg_distance = total_distance / n_detectors
103
+ # Choose the class with the largest average distance.
104
+ if avg_distance > best_avg_distance:
105
+ best_avg_distance = avg_distance
106
+ best_class_idx = class_index
107
+
108
+ return best_class_idx
109
+
110
+
111
+ @njit(
112
+ [(
113
+ types.float64[:, :], types.float64[:],
114
+ types.float64, types.int32, types.float64
115
+ )],
116
+ cache=True
117
+ )
118
+ def check_detector_rnsa_validity(
119
+ x_class: npt.NDArray,
120
+ vector_x: npt.NDArray,
121
+ threshold: float,
122
+ metric: int,
123
+ p: float
124
+ ) -> bool:
125
+ """
126
+ Checks the validity of a candidate detector (vector_x) against samples from a class (x_class)
127
+ using the Hamming distance. A detector is considered INVALID if its distance to any sample
128
+ in ``x_class`` is less than or equal to ``aff_thresh``.
129
+
130
+ Parameters
131
+ ----------
132
+ * x_class (``npt.NDArray``): Array containing the class samples. Expected shape:
133
+ (n_samples, n_features).
134
+ * vector_x (``npt.NDArray``): Array representing the detector. Expected shape: (n_features,).
135
+ * threshold (``float``): threshold.
136
+ * metric (``int``): Distance metric to be used. Available options:
137
+ [0 (Euclidean), 1 (Manhattan), 2 (Minkowski)].
138
+ * p (``float``): Parameter for the Minkowski distance (used only if `metric`
139
+ is "minkowski").
140
+
141
+ Returns
142
+ ----------
143
+ * True if the detector is valid, False otherwise.
144
+ """
145
+ n = x_class.shape[1]
146
+ if n != vector_x.shape[0]:
147
+ return False
148
+
149
+ for i in range(x_class.shape[0]):
150
+ distance = compute_metric_distance(vector_x, x_class[i], metric, p)
151
+ if distance <= threshold:
152
+ return False
153
+ return True
aisp/utils/_multiclass.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Utility functions for handling classes with multiple categories."""
2
+
2
3
  from typing import Union
3
4
  import numpy as np
4
5
  import numpy.typing as npt
aisp/utils/distance.py ADDED
@@ -0,0 +1,215 @@
1
+ """Utility functions for normalized distance between arrays with numba decorators."""
2
+
3
+ import numpy as np
4
+ import numpy.typing as npt
5
+ from numba import njit, types
6
+
7
+ EUCLIDEAN = 0
8
+ MANHATTAN = 1
9
+ MINKOWSKI = 2
10
+ HAMMING = 3
11
+
12
+
13
+ @njit([(types.boolean[:], types.boolean[:])], cache=True)
14
+ def hamming(u: npt.NDArray[np.bool_], v: npt.NDArray[np.bool_]) -> np.float64:
15
+ """
16
+ Function to calculate the normalized Hamming distance between two points.
17
+
18
+ ((x₁ ≠ x₂) + (y₁ ≠ y₂) + ... + (yn ≠ yn)) / n
19
+
20
+ Parameters
21
+ ----------
22
+ * u (``npt.NDArray``): Coordinates of the first point.
23
+ * v (``npt.NDArray``): Coordinates of the second point.
24
+
25
+ returns
26
+ ----------
27
+ * Distance (``float``) between the two points.
28
+ """
29
+ n = len(u)
30
+ if n == 0:
31
+ return 0.0
32
+
33
+ return np.sum(u != v) / n
34
+
35
+
36
+ @njit()
37
+ def euclidean(u: npt.NDArray[np.float64], v: npt.NDArray[np.float64]) -> np.float64:
38
+ """
39
+ Function to calculate the normalized Euclidean distance between two points.
40
+
41
+ √( (x₁ – x₂)² + (y₁ – y₂)² + ... + (yn – yn)²)
42
+
43
+ Parameters
44
+ ----------
45
+ * u (``npt.NDArray``): Coordinates of the first point.
46
+ * v (``npt.NDArray``): Coordinates of the second point.
47
+
48
+ returns
49
+ ----------
50
+ * Distance (``float``) between the two points.
51
+ """
52
+ return np.linalg.norm(u - v)
53
+
54
+
55
+ @njit()
56
+ def cityblock(u: npt.NDArray[np.float64], v: npt.NDArray[np.float64]) -> np.float64:
57
+ """
58
+ Function to calculate the normalized Manhattan distance between two points.
59
+
60
+ (|x₁ – x₂| + |y₁ – y₂| + ... + |yn – yn|) / n
61
+
62
+ Parameters
63
+ ----------
64
+ * u (``npt.NDArray``): Coordinates of the first point.
65
+ * v (``npt.NDArray``): Coordinates of the second point.
66
+
67
+ returns
68
+ ----------
69
+ * Distance (``float``) between the two points.
70
+ """
71
+ n = len(u)
72
+ if n == 0:
73
+ return -1.0
74
+
75
+ return np.sum(np.abs(u - v)) / n
76
+
77
+
78
+ @njit()
79
+ def minkowski(u: npt.NDArray[np.float64], v: npt.NDArray[np.float64], p: float = 2.0):
80
+ """
81
+ Function to calculate the normalized Minkowski distance between two points.
82
+
83
+ (( |X₁ – Y₁|p + |X₂ – Y₂|p + ... + |Xn – Yn|p) ¹/ₚ.) / n
84
+
85
+ Parameters
86
+ ----------
87
+ * u (``npt.NDArray``): Coordinates of the first point.
88
+ * v (``npt.NDArray``): Coordinates of the second point.
89
+ * p float: The p parameter defines the type of distance to be calculated:
90
+ - p = 1: **Manhattan** distance — sum of absolute differences.
91
+ - p = 2: **Euclidean** distance — sum of squared differences (square root).
92
+ - p > 2: **Minkowski** distance with an increasing penalty as p increases.
93
+
94
+ returns
95
+ ----------
96
+ * Distance (``float``) between the two points.
97
+ """
98
+ n = len(u)
99
+ if n == 0:
100
+ return -1.0
101
+
102
+ return (np.sum(np.abs(u - v) ** p) ** (1 / p)) / n
103
+
104
+
105
+ @njit(
106
+ [(
107
+ types.float64[:], types.float64[:],
108
+ types.int32, types.float64
109
+ )],
110
+ cache=True
111
+ )
112
+ def compute_metric_distance(
113
+ u: npt.NDArray[np.float64],
114
+ v: npt.NDArray[np.float64],
115
+ metric: int,
116
+ p: np.float64 = 2.0
117
+ ) -> np.float64:
118
+ """
119
+ Function to calculate the distance between two points by the chosen ``metric``.
120
+
121
+ Parameters
122
+ ----------
123
+ * u (``npt.NDArray``): Coordinates of the first point.
124
+ * v (``npt.NDArray``): Coordinates of the second point.
125
+ * metric (``int``): Distance metric to be used. Available options:
126
+ [0 (Euclidean), 1 (Manhattan), 2 (Minkowski)]
127
+ * p (``float``): Parameter for the Minkowski distance (used only if `metric`
128
+ is "minkowski").
129
+
130
+ returns
131
+ ----------
132
+ * Distance (``double``) between the two points with the selected metric.
133
+ """
134
+ if metric == MANHATTAN:
135
+ return cityblock(u, v)
136
+ if metric == MINKOWSKI:
137
+ return minkowski(u, v, p)
138
+
139
+ return euclidean(u, v)
140
+
141
+
142
+ @njit(
143
+ [(
144
+ types.float64[:, :], types.float64[:],
145
+ types.int32, types.float64
146
+ )],
147
+ cache=True
148
+ )
149
+ def min_distance_to_class_vectors(
150
+ x_class: npt.NDArray[np.float64],
151
+ vector_x: npt.NDArray[np.float64],
152
+ metric: int,
153
+ p: float = 2.0
154
+ ) -> float:
155
+ """
156
+ Calculates the minimum distance between an input vector and the vectors of a class.
157
+
158
+ Parameters
159
+ ----------
160
+ * x_class (``npt.NDArray``): Array containing the class vectors to be compared
161
+ with the input vector. Expected shape: (n_samples, n_features).
162
+ * vector_x (``npt.NDArray``): Vector to be compared with the class vectors.
163
+ Expected shape: (n_features,).
164
+ * metric (``str``): Distance metric to be used. Available options:
165
+ ["hamming", "cityblock", "minkowski", "euclidean"]
166
+ * p (``float``): Parameter for the Minkowski distance (used only if `metric`
167
+ is "minkowski").
168
+
169
+ Returns
170
+ ----------
171
+ * float: The minimum distance calculated between the input vector and the class vectors.
172
+ * Returns -1.0 if the input dimensions are incompatible.
173
+ """
174
+ n = x_class.shape[1]
175
+ if n != vector_x.shape[0]:
176
+ return -1.0
177
+
178
+ min_distance = np.inf
179
+ for i in range(x_class.shape[0]):
180
+ distance = compute_metric_distance(vector_x, x_class[i], metric, p)
181
+ min_distance = min(min_distance, distance)
182
+
183
+ return min_distance
184
+
185
+
186
+ def get_metric_code(metric: str) -> int:
187
+ """
188
+ Returns the numeric code associated with a distance metric.
189
+
190
+ Parameters
191
+ ----------
192
+ * metric (str): Name of the metric. Can be "euclidean", "manhattan", "minkowski" or "hamming".
193
+
194
+ Raises
195
+ ----------
196
+ * ValueError: If the metric provided is not supported.
197
+
198
+ Returns
199
+ ----------
200
+ * int: Numeric code corresponding to the metric.
201
+ """
202
+ metric_map = {
203
+ "euclidean": EUCLIDEAN,
204
+ "manhattan": MANHATTAN,
205
+ "minkowski": MINKOWSKI,
206
+ "hamming": HAMMING
207
+ }
208
+
209
+ normalized_metric = metric.strip().lower()
210
+
211
+ if normalized_metric not in metric_map:
212
+ supported = "', '".join(metric_map.keys())
213
+ raise ValueError(f"Unknown metric: '{metric}'. Supported: {supported}")
214
+
215
+ return metric_map[normalized_metric]
aisp/utils/metrics.py CHANGED
@@ -6,8 +6,8 @@ import numpy.typing as npt
6
6
 
7
7
 
8
8
  def accuracy_score(
9
- y_true: Union[npt.NDArray, list],
10
- y_pred: Union[npt.NDArray, list]
9
+ y_true: Union[npt.NDArray, list],
10
+ y_pred: Union[npt.NDArray, list]
11
11
  ) -> float:
12
12
  """
13
13
  Function to calculate the accuracy score based on true and predicted labels.
aisp/utils/sanitizers.py CHANGED
@@ -3,6 +3,7 @@ from typing import TypeVar, Iterable, Callable, Any, Optional
3
3
 
4
4
  T = TypeVar('T')
5
5
 
6
+
6
7
  def sanitize_choice(value: T, valid_choices: Iterable[T], default: T) -> T:
7
8
  """
8
9
  Returns the value if it is present in the set of valid choices; otherwise,
@@ -10,8 +11,8 @@ def sanitize_choice(value: T, valid_choices: Iterable[T], default: T) -> T:
10
11
 
11
12
  Parameters
12
13
  ----------
13
- * value: The value to be checked.
14
- * valid_choices (iterable): A collection of valid choices.
14
+ * value (``T``): The value to be checked.
15
+ * valid_choices (``Iterable[T]``): A collection of valid choices.
15
16
  * default: The default value to be returned if 'value' is not in 'valid_choices'.
16
17
 
17
18
  Returns
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aisp
3
- Version: 0.1.35
3
+ Version: 0.1.40
4
4
  Summary: Package with techniques of artificial immune systems.
5
5
  Author-email: João Paulo da Silva Barros <jpsilvabarr@gmail.com>
6
6
  Maintainer-email: Alison Zille Lopes <alisonzille@gmail.com>
@@ -9,18 +9,21 @@ Project-URL: Homepage, https://ais-package.github.io/
9
9
  Project-URL: Documentation, https://ais-package.github.io/docs/intro
10
10
  Project-URL: Source Code, https://github.com/AIS-Package/aisp
11
11
  Project-URL: Tracker, https://github.com/AIS-Package/aisp/issues
12
- Keywords: Artificial Immune Systems,classification,Natural computing,machine learning,artificial intelligence
12
+ Keywords: Artificial Immune Systems,classification,Natural computing,machine learning,artificial intelligence,AIS
13
13
  Classifier: Operating System :: OS Independent
14
14
  Classifier: Programming Language :: Python
15
15
  Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.8
17
- Classifier: Programming Language :: Python :: 3.9
18
16
  Classifier: Programming Language :: Python :: 3.10
19
17
  Classifier: Programming Language :: Python :: 3.11
20
- Requires-Python: >=3.8.10
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.10
21
23
  Description-Content-Type: text/markdown
22
24
  License-File: LICENSE
23
25
  Requires-Dist: numpy>=1.22.4
26
+ Requires-Dist: numba>=0.59.0
24
27
  Requires-Dist: scipy>=1.8.1
25
28
  Requires-Dist: tqdm>=4.64.1
26
29
  Dynamic: license-file
@@ -86,7 +89,7 @@ Artificial Immune Systems (AIS) are inspired by the vertebrate immune system, cr
86
89
 
87
90
  #### **Installation**
88
91
 
89
- The module requires installation of [python 3.8.10](https://www.python.org/downloads/) or higher.
92
+ The module requires installation of [python 3.10](https://www.python.org/downloads/) or higher.
90
93
 
91
94
  <section id='dependencies'>
92
95
 
@@ -99,6 +102,7 @@ The module requires installation of [python 3.8.10](https://www.python.org/downl
99
102
  | numpy | ≥ 1.22.4 |
100
103
  | scipy | ≥ 1.8.1 |
101
104
  | tqdm | ≥ 4.64.1 |
105
+ | numba | ≥ 0.59.0 |
102
106
 
103
107
  </div>
104
108
 
@@ -0,0 +1,18 @@
1
+ aisp/__init__.py,sha256=pKOdkhFxWup_lhQPofFTk4rpqd0_IlYygHnkBhE2g2w,111
2
+ aisp/exceptions.py,sha256=ONiKCZrBhfUaMO1vYHnOr1_eL9PtVJ7b_HRroMbORpc,1405
3
+ aisp/base/__init__.py,sha256=rpb9ADmBtNpRAEJw61c7CsbZhHA2vGQOvjFmpk7w39c,100
4
+ aisp/base/_classifier.py,sha256=qv6TxzfnRwO7HvN7CA8PS1dueAnm-RifelRnCjrK9D0,3027
5
+ aisp/nsa/__init__.py,sha256=3-fSIJCMB_jcLGTr6DcVkloRfWyQJ8-JzD0CLhvpvgc,411
6
+ aisp/nsa/_base.py,sha256=cT404V5onduK19WW6ajxy_yUZha3Fk8KZJvJHt_UZBM,4250
7
+ aisp/nsa/_negative_selection.py,sha256=0_VI3rAeVzPcSRwjMjqCq6RT-1_a_-HCFtIIJL6jpyc,29582
8
+ aisp/nsa/_ns_core.py,sha256=VWt_L2ODXtngJ7BVmSVT7i7kK98axibOmCzbYCkjeqI,4934
9
+ aisp/utils/__init__.py,sha256=-r--qdfTq4dVJU-VoJ7dvXTNS5_I1q1aGAQ02zNBOGw,217
10
+ aisp/utils/_multiclass.py,sha256=t0RLIdUoUbvFL30a8XfO3BMXc8MimtLCHNbGCDL2BQk,1051
11
+ aisp/utils/distance.py,sha256=SZTE5KEB7QX9vKoY9GfFOfFGbswVhQM6-9baLq4ZXns,6304
12
+ aisp/utils/metrics.py,sha256=o6aD6qTLQtXhWNOMGjgweHMQ6SMQ2hh42NcSEmgY3RI,1292
13
+ aisp/utils/sanitizers.py,sha256=7wJSo5ZkRX1g16C9sEN8TWQ5l9Gzfl0-8CgLULnPNlk,1873
14
+ aisp-0.1.40.dist-info/licenses/LICENSE,sha256=fTqV5eBpeAZO0_jit8j4Ref9ikBSlHJ8xwj5TLg7gFk,7817
15
+ aisp-0.1.40.dist-info/METADATA,sha256=em8eJAx3lr87ZZ1ajsoSkIj-itauLz25E1FKcdjf1QU,4818
16
+ aisp-0.1.40.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
17
+ aisp-0.1.40.dist-info/top_level.txt,sha256=Q5aJi_rAVT5UNS1As0ZafoyS5dwNibnoyOYV7RWUB9s,5
18
+ aisp-0.1.40.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,14 +0,0 @@
1
- aisp/__init__.py,sha256=6is9Nwltdm6JZAsdLPXY56WXC7qnd0kNUEJoizOxWHg,111
2
- aisp/exceptions.py,sha256=ONiKCZrBhfUaMO1vYHnOr1_eL9PtVJ7b_HRroMbORpc,1405
3
- aisp/nsa/__init__.py,sha256=wgoFb-0WovzFovQG6UFkAb-IbZWK2wlytuJ03wmV4Q0,411
4
- aisp/nsa/_base.py,sha256=OpBC3loiWk8NEb4ulogulIOKeh6hTnxcpImF6BNy8iI,8086
5
- aisp/nsa/_negative_selection.py,sha256=iYtd39eR4O2y1bOVAAEqfMmgzIzQ_oexLCN3sRO8Mxg,32089
6
- aisp/utils/__init__.py,sha256=-r--qdfTq4dVJU-VoJ7dvXTNS5_I1q1aGAQ02zNBOGw,217
7
- aisp/utils/_multiclass.py,sha256=KJ2Le62KsSPRQB3UDMv7HT13xQLvwwZQM3QekTATDiY,1049
8
- aisp/utils/metrics.py,sha256=RmqR5FRxQUZkF9GZhAUXNplaeRldhXv592DeeYPdyV8,1300
9
- aisp/utils/sanitizers.py,sha256=QKpIu8YyNLIZT472O49QybLZB5P-NQqGaNI5xylyJ8k,1856
10
- aisp-0.1.35.dist-info/licenses/LICENSE,sha256=fTqV5eBpeAZO0_jit8j4Ref9ikBSlHJ8xwj5TLg7gFk,7817
11
- aisp-0.1.35.dist-info/METADATA,sha256=aHoORgNbmyDlN7Pd2MXCaNgGD7T30g_jtM_XIH20pZs,4603
12
- aisp-0.1.35.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
13
- aisp-0.1.35.dist-info/top_level.txt,sha256=Q5aJi_rAVT5UNS1As0ZafoyS5dwNibnoyOYV7RWUB9s,5
14
- aisp-0.1.35.dist-info/RECORD,,