aisp 0.3.21__py3-none-any.whl → 0.4.1__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/__init__.py +17 -4
- aisp/base/__init__.py +21 -2
- aisp/base/_classifier.py +4 -2
- aisp/base/_optimizer.py +188 -0
- aisp/base/mutation.py +85 -17
- aisp/base/populations.py +49 -0
- aisp/csa/__init__.py +12 -1
- aisp/csa/_cell.py +2 -2
- aisp/csa/_clonalg.py +369 -0
- aisp/ina/__init__.py +2 -2
- aisp/ina/_ai_network.py +5 -4
- aisp/ina/_base.py +0 -40
- aisp/nsa/__init__.py +7 -0
- aisp/utils/display.py +185 -0
- aisp/utils/sanitizers.py +53 -1
- aisp/utils/types.py +10 -2
- {aisp-0.3.21.dist-info → aisp-0.4.1.dist-info}/METADATA +2 -1
- aisp-0.4.1.dist-info/RECORD +35 -0
- aisp-0.3.21.dist-info/RECORD +0 -31
- {aisp-0.3.21.dist-info → aisp-0.4.1.dist-info}/WHEEL +0 -0
- {aisp-0.3.21.dist-info → aisp-0.4.1.dist-info}/licenses/LICENSE +0 -0
- {aisp-0.3.21.dist-info → aisp-0.4.1.dist-info}/top_level.txt +0 -0
aisp/__init__.py
CHANGED
@@ -5,9 +5,22 @@ immune system to pattern recognition and optimization tasks.
|
|
5
5
|
|
6
6
|
The package is organized into specialized modules, each dedicated to a family of Artificial
|
7
7
|
Immune Systems algorithms:
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
|
9
|
+
Modules
|
10
|
+
-------
|
11
|
+
csa : Clonal Selection Algorithms.
|
12
|
+
Inspired by the processes of antibody proliferation and mutation.
|
13
|
+
- AIRS: Artificial Immune Recognition System for classification.
|
14
|
+
- Clonalg: Clonal Selection Algorithm for optimization.
|
15
|
+
|
16
|
+
nsa : Negative Selection Algorithms
|
17
|
+
Simulates T cell maturation and is capable of detecting non-self cells.
|
18
|
+
- RNSA: Real-value Negative Selection Algorithm for classification.
|
19
|
+
- BNSA: Binary Negative Selection Algorithm for classification.
|
20
|
+
|
21
|
+
ina : Immune Network Algorithms
|
22
|
+
Based on immune network theory.
|
23
|
+
- AiNet: Artificial Immune Network for clustering.
|
11
24
|
|
12
25
|
For detailed documentation and examples, visit:
|
13
26
|
https://ais-package.github.io/docs/intro
|
@@ -18,7 +31,7 @@ from . import ina
|
|
18
31
|
from . import nsa
|
19
32
|
|
20
33
|
__author__ = "AISP Development Team"
|
21
|
-
__version__ = "0.
|
34
|
+
__version__ = "0.4.0"
|
22
35
|
__all__ = [
|
23
36
|
'csa',
|
24
37
|
'nsa',
|
aisp/base/__init__.py
CHANGED
@@ -1,7 +1,26 @@
|
|
1
|
-
"""Base
|
1
|
+
"""Base Classes and Core Utilities.
|
2
|
+
|
3
|
+
This module provides the fundamental classes and utilities that serve as the basis for all
|
4
|
+
Artificial Immune Systems algorithms implemented in the AISP package.
|
5
|
+
|
6
|
+
Classes
|
7
|
+
-------
|
8
|
+
BaseClassifier
|
9
|
+
Abstract Base Class for Classification Algorithms.
|
10
|
+
BaseClusterer
|
11
|
+
Abstract Base Class for Clustering Algorithms.
|
12
|
+
BaseOptimizer
|
13
|
+
Abstract Base Class for optimization algorithms.
|
14
|
+
|
15
|
+
Functions
|
16
|
+
---------
|
17
|
+
set_seed_numba
|
18
|
+
Set Random Seed for Numba JIT Compilation.
|
19
|
+
"""
|
2
20
|
|
3
21
|
from ._base import set_seed_numba
|
4
22
|
from ._classifier import BaseClassifier
|
5
23
|
from ._clusterer import BaseClusterer
|
24
|
+
from ._optimizer import BaseOptimizer
|
6
25
|
|
7
|
-
__all__ = ['BaseClassifier', 'BaseClusterer', 'set_seed_numba']
|
26
|
+
__all__ = ['BaseClassifier', 'BaseClusterer', 'BaseOptimizer', 'set_seed_numba']
|
aisp/base/_classifier.py
CHANGED
@@ -13,9 +13,11 @@ from ..utils.metrics import accuracy_score
|
|
13
13
|
|
14
14
|
|
15
15
|
class BaseClassifier(ABC, Base):
|
16
|
-
"""
|
16
|
+
"""Abstract base class for classification algorithms.
|
17
17
|
|
18
|
-
|
18
|
+
This class defines the core interface for classification models. It enforces the
|
19
|
+
implementation of the ``fit`` and ``predict`` methods in all derived classes,
|
20
|
+
and provides a default implementation of ``score`` and utility functions.
|
19
21
|
"""
|
20
22
|
|
21
23
|
classes: Union[npt.NDArray, list] = []
|
aisp/base/_optimizer.py
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
"""Base class for optimization algorithms."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from abc import ABC, abstractmethod
|
6
|
+
from typing import Optional, List, Any, Callable
|
7
|
+
|
8
|
+
from ..utils.display import TableFormatter
|
9
|
+
|
10
|
+
|
11
|
+
class BaseOptimizer(ABC):
|
12
|
+
"""Abstract base class for optimization algorithms.
|
13
|
+
|
14
|
+
This class defines the core interface for optimization strategies. It keeps track of cost
|
15
|
+
history, evaluated solutions, and the best solution found during the optimization process.
|
16
|
+
Subclasses must implement ``optimize`` and ``affinity_function``.
|
17
|
+
"""
|
18
|
+
|
19
|
+
def __init__(self) -> None:
|
20
|
+
self._cost_history: List[float] = []
|
21
|
+
self._solution_history: list = []
|
22
|
+
self._best_solution: Optional[Any] = None
|
23
|
+
self._best_cost: Optional[float] = None
|
24
|
+
self._protected_aliases = [
|
25
|
+
"__init__",
|
26
|
+
"optimize",
|
27
|
+
"register",
|
28
|
+
"get_report"
|
29
|
+
]
|
30
|
+
self.mode = "min"
|
31
|
+
|
32
|
+
@property
|
33
|
+
def cost_history(self) -> List[float]:
|
34
|
+
"""Return the history of costs during optimization."""
|
35
|
+
return self._cost_history
|
36
|
+
|
37
|
+
@property
|
38
|
+
def solution_history(self) -> List:
|
39
|
+
"""Returns the history of evaluated solutions."""
|
40
|
+
return self._solution_history
|
41
|
+
|
42
|
+
@property
|
43
|
+
def best_solution(self) -> Optional[Any]:
|
44
|
+
"""Return the best solution found so far, or ``None`` if unavailable."""
|
45
|
+
return self._best_solution
|
46
|
+
|
47
|
+
@property
|
48
|
+
def best_cost(self) -> Optional[float]:
|
49
|
+
"""Return the cost of the best solution found so far, or ``None`` if unavailable."""
|
50
|
+
return self._best_cost
|
51
|
+
|
52
|
+
def _record_best(self, cost: float, best_solution: Any) -> None:
|
53
|
+
"""Record a new cost value and update the best solution if improved.
|
54
|
+
|
55
|
+
Parameters
|
56
|
+
----------
|
57
|
+
cost : float
|
58
|
+
Cost value to be added to the history.
|
59
|
+
"""
|
60
|
+
self._solution_history.append(best_solution)
|
61
|
+
self._cost_history.append(cost)
|
62
|
+
is_better = (
|
63
|
+
self._best_cost is None or
|
64
|
+
(self.mode == "min" and cost < self._best_cost) or
|
65
|
+
(self.mode == "max" and cost > self._best_cost)
|
66
|
+
)
|
67
|
+
if is_better:
|
68
|
+
self._best_solution = best_solution
|
69
|
+
self._best_cost = cost
|
70
|
+
|
71
|
+
def get_report(self) -> str:
|
72
|
+
"""Generate a formatted summary report of the optimization process.
|
73
|
+
|
74
|
+
The report includes the best solution, its associated cost, and the evolution of cost
|
75
|
+
values per iteration.
|
76
|
+
|
77
|
+
Returns
|
78
|
+
-------
|
79
|
+
report : str
|
80
|
+
A formatted string containing the optimization summary.
|
81
|
+
"""
|
82
|
+
if not self._cost_history:
|
83
|
+
return "Optimization has not been run. The report is empty."
|
84
|
+
|
85
|
+
header = "\n" + "=" * 45 + "\n"
|
86
|
+
report_parts = [
|
87
|
+
header,
|
88
|
+
f"{'Optimization Summary':^45}",
|
89
|
+
header,
|
90
|
+
f"Best cost : {self.best_cost}\n",
|
91
|
+
f"Best solution : {self.best_solution}\n",
|
92
|
+
"Cost History per Iteration:\n"
|
93
|
+
]
|
94
|
+
table_formatter = TableFormatter(
|
95
|
+
{
|
96
|
+
'Iteration': 12,
|
97
|
+
'Cost': 28
|
98
|
+
}
|
99
|
+
)
|
100
|
+
|
101
|
+
report_parts.extend([table_formatter.get_header()])
|
102
|
+
|
103
|
+
for i, cost in enumerate(self._cost_history, start=1):
|
104
|
+
report_parts.append(
|
105
|
+
'\n' + table_formatter.get_row(
|
106
|
+
{
|
107
|
+
'Iteration': f"{i:>11} ",
|
108
|
+
'Cost': f"{cost:>27.6f} "
|
109
|
+
}
|
110
|
+
)
|
111
|
+
)
|
112
|
+
|
113
|
+
report_parts.append(table_formatter.get_bottom(True))
|
114
|
+
return "".join(report_parts)
|
115
|
+
|
116
|
+
@abstractmethod
|
117
|
+
def optimize(self, max_iters: int = 50, n_iter_no_change=10, verbose: bool = True) -> Any:
|
118
|
+
"""Execute the optimization process.
|
119
|
+
|
120
|
+
This abstract method must be implemented by the subclass, defining
|
121
|
+
how the optimization strategy explores the search space.
|
122
|
+
|
123
|
+
Parameters
|
124
|
+
----------
|
125
|
+
max_iters : int
|
126
|
+
Maximum number of interactions
|
127
|
+
n_iter_no_change: int, default=10
|
128
|
+
the maximum number of iterations without updating the best
|
129
|
+
verbose : bool, default=True
|
130
|
+
Flag to enable or disable detailed output during optimization.
|
131
|
+
|
132
|
+
Returns
|
133
|
+
-------
|
134
|
+
best_solution : Any
|
135
|
+
The best solution found by the optimization algorithm.
|
136
|
+
"""
|
137
|
+
|
138
|
+
@abstractmethod
|
139
|
+
def affinity_function(self, solution: Any) -> float:
|
140
|
+
"""Evaluate the affinity of a candidate solution.
|
141
|
+
|
142
|
+
This abstract method must be implemented by the subclass to define the problem-specific.
|
143
|
+
|
144
|
+
Parameters
|
145
|
+
----------
|
146
|
+
solution : Any
|
147
|
+
Candidate solution to be evaluated.
|
148
|
+
|
149
|
+
Returns
|
150
|
+
-------
|
151
|
+
cost : float
|
152
|
+
Cost value associated with the given solution.
|
153
|
+
"""
|
154
|
+
|
155
|
+
def register(self, alias: str, function: Callable[..., Any]) -> None:
|
156
|
+
"""Register a function dynamically in the optimizer instance.
|
157
|
+
|
158
|
+
Parameters
|
159
|
+
----------
|
160
|
+
alias : str
|
161
|
+
Name used to access the function as an attribute.
|
162
|
+
function : Callable[..., Any]
|
163
|
+
Callable to be registered.
|
164
|
+
|
165
|
+
Raises
|
166
|
+
------
|
167
|
+
TypeError
|
168
|
+
If `function` is not callable.
|
169
|
+
AttributeError
|
170
|
+
If `alias` is protected and cannot be modified. Or if `alias` does not exist in the
|
171
|
+
optimizer class.
|
172
|
+
"""
|
173
|
+
if not callable(function):
|
174
|
+
raise TypeError(f"Expected a function for '{alias}', got {type(function).__name__}")
|
175
|
+
if alias in self._protected_aliases or alias.startswith("_"):
|
176
|
+
raise AttributeError(f"The alias '{alias}' is protected and cannot be modified.")
|
177
|
+
if not hasattr(self, alias):
|
178
|
+
raise AttributeError(
|
179
|
+
f"Alias '{alias}' is not a valid method of {self.__class__.__name__}"
|
180
|
+
)
|
181
|
+
setattr(self, alias, function)
|
182
|
+
|
183
|
+
def reset(self):
|
184
|
+
"""Reset the object's internal state, clearing history and resetting values."""
|
185
|
+
self._cost_history: List[float] = []
|
186
|
+
self._solution_history: list = []
|
187
|
+
self._best_solution: Optional[Any] = None
|
188
|
+
self._best_cost: Optional[float] = None
|
aisp/base/mutation.py
CHANGED
@@ -10,10 +10,11 @@ import numpy.typing as npt
|
|
10
10
|
from numba import njit, types
|
11
11
|
|
12
12
|
|
13
|
-
@njit([(types.float64[:], types.int64)], cache=True)
|
13
|
+
@njit([(types.float64[:], types.int64, types.float64)], cache=True)
|
14
14
|
def clone_and_mutate_continuous(
|
15
15
|
vector: npt.NDArray[np.float64],
|
16
|
-
n: int
|
16
|
+
n: int,
|
17
|
+
mutation_rate: float
|
17
18
|
) -> npt.NDArray[np.float64]:
|
18
19
|
"""
|
19
20
|
Generate a set of mutated clones from a cell represented by a continuous vector.
|
@@ -28,6 +29,10 @@ def clone_and_mutate_continuous(
|
|
28
29
|
The original immune cell with continuous values to be cloned and mutated.
|
29
30
|
n : int
|
30
31
|
The number of mutated clones to be generated.
|
32
|
+
mutation_rate : float, default=1
|
33
|
+
If 0 <= mutation_rate < 1: probability of mutating each component.
|
34
|
+
If mutation_rate >= 1 or mutation_rate <= 0: the mutation randomizes
|
35
|
+
a number of components between 1 and len(vector).
|
31
36
|
|
32
37
|
Returns
|
33
38
|
-------
|
@@ -37,12 +42,22 @@ def clone_and_mutate_continuous(
|
|
37
42
|
n_features = vector.shape[0]
|
38
43
|
clone_set = np.empty((n, n_features), dtype=np.float64)
|
39
44
|
for i in range(n):
|
40
|
-
n_mutations = np.random.randint(1, n_features)
|
41
45
|
clone = vector.copy()
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
if 0 <= mutation_rate < 1:
|
47
|
+
any_mutation = False
|
48
|
+
for j in range(n_features):
|
49
|
+
if np.random.random() < mutation_rate:
|
50
|
+
clone[j] = np.random.random()
|
51
|
+
any_mutation = True
|
52
|
+
if not any_mutation:
|
53
|
+
idx = np.random.randint(0, n_features)
|
54
|
+
clone[idx] = np.random.random()
|
55
|
+
else:
|
56
|
+
n_mutations = np.random.randint(1, n_features)
|
57
|
+
position_mutations = np.random.permutation(n_features)[:n_mutations]
|
58
|
+
for j in range(n_mutations):
|
59
|
+
idx = position_mutations[j]
|
60
|
+
clone[idx] = np.float64(np.random.random())
|
46
61
|
clone_set[i] = clone
|
47
62
|
|
48
63
|
return clone_set
|
@@ -75,8 +90,8 @@ def clone_and_mutate_binary(
|
|
75
90
|
n_features = vector.shape[0]
|
76
91
|
clone_set = np.empty((n, n_features), dtype=np.bool_)
|
77
92
|
for i in range(n):
|
78
|
-
n_mutations = np.random.randint(1, n_features)
|
79
93
|
clone = vector.copy()
|
94
|
+
n_mutations = np.random.randint(1, n_features)
|
80
95
|
position_mutations = np.random.permutation(n_features)[:n_mutations]
|
81
96
|
for j in range(n_mutations):
|
82
97
|
idx = position_mutations[j]
|
@@ -86,11 +101,12 @@ def clone_and_mutate_binary(
|
|
86
101
|
return clone_set
|
87
102
|
|
88
103
|
|
89
|
-
@njit([(types.float64[:], types.int64, types.float64[:, :])], cache=True)
|
104
|
+
@njit([(types.float64[:], types.int64, types.float64[:, :], types.float64)], cache=True)
|
90
105
|
def clone_and_mutate_ranged(
|
91
106
|
vector: npt.NDArray[np.float64],
|
92
107
|
n: int,
|
93
|
-
bounds: npt.NDArray[np.float64]
|
108
|
+
bounds: npt.NDArray[np.float64],
|
109
|
+
mutation_rate: float
|
94
110
|
) -> npt.NDArray[np.float64]:
|
95
111
|
"""
|
96
112
|
Generate a set of mutated clones from a cell represented by custom ranges per dimension.
|
@@ -107,6 +123,10 @@ def clone_and_mutate_ranged(
|
|
107
123
|
The number of mutated clones to be generated.
|
108
124
|
bounds : np.ndarray
|
109
125
|
Array (n_features, 2) with min and max per dimension.
|
126
|
+
mutation_rate : float, default=1
|
127
|
+
If 0 <= mutation_rate < 1: probability of mutating each component.
|
128
|
+
If mutation_rate >= 1 or mutation_rate <= 0: the mutation randomizes
|
129
|
+
a number of components between 1 and len(vector).
|
110
130
|
|
111
131
|
Returns
|
112
132
|
-------
|
@@ -117,14 +137,62 @@ def clone_and_mutate_ranged(
|
|
117
137
|
clone_set = np.empty((n, n_features), dtype=np.float64)
|
118
138
|
|
119
139
|
for i in range(n):
|
120
|
-
n_mutations = np.random.randint(1, n_features)
|
121
140
|
clone = vector.copy()
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
141
|
+
if 0 <= mutation_rate < 1:
|
142
|
+
any_mutation = False
|
143
|
+
for j in range(n_features):
|
144
|
+
if np.random.random() < mutation_rate:
|
145
|
+
clone[j] = np.random.uniform(low=bounds[0][j], high=bounds[1][j])
|
146
|
+
any_mutation = True
|
147
|
+
if not any_mutation:
|
148
|
+
idx = np.random.randint(0, n_features)
|
149
|
+
clone[idx] = np.random.uniform(low=bounds[0][idx], high=bounds[1][idx])
|
150
|
+
else:
|
151
|
+
n_mutations = np.random.randint(1, n_features)
|
152
|
+
position_mutations = np.random.permutation(n_features)[:n_mutations]
|
153
|
+
for j in range(n_mutations):
|
154
|
+
idx = position_mutations[j]
|
155
|
+
min_limit = bounds[0][idx]
|
156
|
+
max_limit = bounds[1][idx]
|
157
|
+
clone[idx] = np.random.uniform(low=min_limit, high=max_limit)
|
158
|
+
clone_set[i] = clone
|
159
|
+
|
160
|
+
return clone_set
|
161
|
+
|
162
|
+
|
163
|
+
@njit([(types.int64[:], types.int64, types.float64)], cache=True)
|
164
|
+
def clone_and_mutate_permutation(
|
165
|
+
vector: npt.NDArray[np.int64],
|
166
|
+
n: int,
|
167
|
+
mutation_rate: float
|
168
|
+
) -> npt.NDArray[np.int64]:
|
169
|
+
"""Generate a set of mutated clones by random permutation.
|
170
|
+
|
171
|
+
Parameters
|
172
|
+
----------
|
173
|
+
vector : npt.NDArray[np.int64]
|
174
|
+
The original immune cell with permutation values to be cloned and mutated.
|
175
|
+
n : int
|
176
|
+
The number of mutated clones to be generated.
|
177
|
+
mutation_rate : float
|
178
|
+
Probability of mutating each component 0 <= mutation_rate < 1.
|
179
|
+
|
180
|
+
Returns
|
181
|
+
-------
|
182
|
+
clone_set : npt.NDArray
|
183
|
+
An Array(n, len(vector)) containing the `n` mutated clones of the original vector.
|
184
|
+
"""
|
185
|
+
n_features = vector.shape[0]
|
186
|
+
clone_set = np.empty((n, n_features), dtype=np.int64)
|
187
|
+
|
188
|
+
for i in range(n):
|
189
|
+
clone = vector.copy()
|
190
|
+
for j in range(n_features):
|
191
|
+
if np.random.random() < mutation_rate:
|
192
|
+
idx = np.random.randint(0, n_features)
|
193
|
+
tmp = clone[j]
|
194
|
+
clone[j] = clone[idx]
|
195
|
+
clone[idx] = tmp
|
128
196
|
clone_set[i] = clone
|
129
197
|
|
130
198
|
return clone_set
|
aisp/base/populations.py
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
"""Provide utility functions for generating antibody populations in immunological algorithms."""
|
2
|
+
|
3
|
+
from typing import Optional
|
4
|
+
|
5
|
+
import numpy as np
|
6
|
+
import numpy.typing as npt
|
7
|
+
|
8
|
+
from ..utils.types import FeatureTypeAll
|
9
|
+
|
10
|
+
|
11
|
+
def generate_random_antibodies(
|
12
|
+
n_samples: int,
|
13
|
+
n_features: int,
|
14
|
+
feature_type: FeatureTypeAll = "continuous-features",
|
15
|
+
bounds: Optional[npt.NDArray[np.float64]] = None
|
16
|
+
) -> npt.NDArray:
|
17
|
+
"""
|
18
|
+
Generate a random antibody population.
|
19
|
+
|
20
|
+
Parameters
|
21
|
+
----------
|
22
|
+
n_samples : int
|
23
|
+
Number of antibodies (samples) to generate.
|
24
|
+
n_features : int
|
25
|
+
Number of features (dimensions) for each antibody.
|
26
|
+
feature_type : FeatureType, default="continuous-features"
|
27
|
+
Specifies the type of features: "continuous-features", "binary-features",
|
28
|
+
"ranged-features", or "permutation-features".
|
29
|
+
bounds : np.ndarray
|
30
|
+
Array (n_features, 2) with min and max per dimension.
|
31
|
+
|
32
|
+
Returns
|
33
|
+
-------
|
34
|
+
npt.NDArray
|
35
|
+
Array of shape (n_samples, n_features) containing the generated antibodies.
|
36
|
+
"""
|
37
|
+
if n_features <= 0:
|
38
|
+
raise ValueError("Number of features must be greater than zero.")
|
39
|
+
|
40
|
+
if feature_type == "binary-features":
|
41
|
+
return np.random.randint(0, 2, size=(n_samples, n_features)).astype(np.bool_)
|
42
|
+
if feature_type == "ranged-features" and bounds is not None:
|
43
|
+
return np.random.uniform(low=bounds[0], high=bounds[1], size=(n_samples, n_features))
|
44
|
+
if feature_type == "permutation-features":
|
45
|
+
return np.array(
|
46
|
+
[np.random.permutation(n_features) for _ in range(n_samples)]
|
47
|
+
).astype(dtype=np.int64)
|
48
|
+
|
49
|
+
return np.random.random_sample(size=(n_samples, n_features))
|
aisp/csa/__init__.py
CHANGED
@@ -2,8 +2,19 @@
|
|
2
2
|
|
3
3
|
CSAs are inspired by the process of antibody proliferation upon detecting an antigen, during which
|
4
4
|
the generated antibodies undergo mutations in an attempt to enhance pathogen recognition.
|
5
|
+
|
6
|
+
Classes
|
7
|
+
-------
|
8
|
+
AIRS : Artificial Immune Recognition System.
|
9
|
+
A supervised learning algorithm for classification tasks based on the clonal
|
10
|
+
selection principle.
|
11
|
+
Clonalg : Clonal Selection Algorithm.
|
12
|
+
Implementation of the clonal selection algorithm for optimization, adapted
|
13
|
+
for both minimization and maximization of cost functions in binary,
|
14
|
+
continuous, and permutation problems.
|
5
15
|
"""
|
6
16
|
from ._ai_recognition_sys import AIRS
|
17
|
+
from ._clonalg import Clonalg
|
7
18
|
|
8
19
|
__author__ = 'João Paulo da Silva Barros'
|
9
|
-
__all__ = ['AIRS']
|
20
|
+
__all__ = ['AIRS', 'Clonalg']
|
aisp/csa/_cell.py
CHANGED
@@ -53,8 +53,8 @@ class Cell:
|
|
53
53
|
if feature_type == "binary-features":
|
54
54
|
return clone_and_mutate_binary(self.vector, n)
|
55
55
|
if feature_type == "ranged-features" and bounds is not None:
|
56
|
-
clone_and_mutate_ranged(self.vector, n, bounds)
|
57
|
-
return clone_and_mutate_continuous(self.vector, n)
|
56
|
+
clone_and_mutate_ranged(self.vector, n, bounds, np.float64(1.0))
|
57
|
+
return clone_and_mutate_continuous(self.vector, n, np.float64(1.0))
|
58
58
|
|
59
59
|
def __eq__(self, other):
|
60
60
|
"""Check if two cells are equal."""
|