cmenpy 2026a0__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.
- cmenpy/__init__.py +29 -0
- cmenpy/bounds/__init__.py +40 -0
- cmenpy/context/__init__.py +96 -0
- cmenpy/epoch/__init__.py +60 -0
- cmenpy/functools/__init__.py +44 -0
- cmenpy/functools/utils.py +0 -0
- cmenpy/generator/__init__.py +17 -0
- cmenpy/hints/__init__.py +4 -0
- cmenpy/hints/array.py +8 -0
- cmenpy/hints/dynamic.py +8 -0
- cmenpy/hints/option.py +3 -0
- cmenpy/hints/primitives.py +5 -0
- cmenpy/kernel/__init__.py +5 -0
- cmenpy/kernel/buffer.py +86 -0
- cmenpy/kernel/index.py +43 -0
- cmenpy/kernel/low/__init__.py +17 -0
- cmenpy/kernel/mask.py +42 -0
- cmenpy/kernel/size.py +34 -0
- cmenpy/model/__init__.py +167 -0
- cmenpy/model/optimizer/__init__.py +5 -0
- cmenpy/model/optimizer/base.py +36 -0
- cmenpy/model/optimizer/functions/__init__.py +144 -0
- cmenpy/model/optimizer/functions/params.py +90 -0
- cmenpy/model/optimizer/functions/protocols.py +31 -0
- cmenpy/model/optimizer/template/__init__.py +110 -0
- cmenpy/model/optimizer/template/protocols.py +11 -0
- cmenpy/model/optimizer/variables/__init__.py +39 -0
- cmenpy/population/__init__.py +3 -0
- cmenpy/population/agent/__init__.py +12 -0
- cmenpy/population/agent/base/__init__.py +53 -0
- cmenpy/population/agent/base/attributes.py +25 -0
- cmenpy/population/agent/base/template.py +9 -0
- cmenpy/population/agent/generator.py +15 -0
- cmenpy/population/agent/inmutable.py +34 -0
- cmenpy/population/agent/mutable.py +38 -0
- cmenpy/population/attributes/__init__.py +8 -0
- cmenpy/population/attributes/base.py +81 -0
- cmenpy/population/attributes/matrix/__init__.py +21 -0
- cmenpy/population/attributes/matrix/mixin.py +14 -0
- cmenpy/population/dynamic/__init__.py +0 -0
- cmenpy/population/dynamic/base.py +30 -0
- cmenpy/population/iterator/__init__.py +0 -0
- cmenpy/population/iterator/base.py +28 -0
- cmenpy/population/operations/__init__.py +36 -0
- cmenpy/population/operations/access.py +24 -0
- cmenpy/population/operations/assign.py +40 -0
- cmenpy/population/operations/compute.py +30 -0
- cmenpy/population/operations/extract.py +21 -0
- cmenpy/population/operations/stream/__init__.py +6 -0
- cmenpy/population/operations/stream/base.py +21 -0
- cmenpy/population/operations/stream/everybody.py +12 -0
- cmenpy/population/operations/stream/reader.py +15 -0
- cmenpy/population/operations/stream/vectorizable.py +17 -0
- cmenpy/population/operations/stream/writer.py +9 -0
- cmenpy/population/operations/swap.py +17 -0
- cmenpy/population/swarm.py +19 -0
- cmenpy/space/__init__.py +0 -0
- cmenpy/target/__init__.py +56 -0
- cmenpy/tracker/__init__.py +26 -0
- cmenpy/tracker/epoch.py +19 -0
- cmenpy-2026a0.dist-info/METADATA +84 -0
- cmenpy-2026a0.dist-info/RECORD +70 -0
- cmenpy-2026a0.dist-info/WHEEL +5 -0
- cmenpy-2026a0.dist-info/licenses/LICENSE.md +674 -0
- cmenpy-2026a0.dist-info/top_level.txt +3 -0
- example/__init__.py +0 -0
- example/gwo_algorithm_matrix.py +45 -0
- example/hello_world_v1.py +58 -0
- example/hello_world_v2.py +70 -0
- test/__init__.py +0 -0
cmenpy/__init__.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
__version__ = "2026a0"
|
|
2
|
+
|
|
3
|
+
from cmenpy.bounds import Bounds
|
|
4
|
+
from cmenpy.epoch import EpochIteration, Epoch
|
|
5
|
+
from cmenpy.functools import is_best, is_worst, best_of, worst_of
|
|
6
|
+
from cmenpy.kernel import KernelSize, KernelBuffer
|
|
7
|
+
from cmenpy.model import declare, template, template_check
|
|
8
|
+
from cmenpy.model.optimizer import FunctionOptimizerModel, TemplateOptimizerModel
|
|
9
|
+
from cmenpy.model.optimizer.variables import Argument, Variable
|
|
10
|
+
from cmenpy.population.swarm import PopulationSwarm
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"declare",
|
|
14
|
+
"template",
|
|
15
|
+
"template_check",
|
|
16
|
+
"is_best",
|
|
17
|
+
"is_worst",
|
|
18
|
+
"best_of",
|
|
19
|
+
"worst_of",
|
|
20
|
+
"Argument",
|
|
21
|
+
"Variable",
|
|
22
|
+
"EpochIteration",
|
|
23
|
+
"Epoch",
|
|
24
|
+
"KernelBuffer",
|
|
25
|
+
"KernelSize",
|
|
26
|
+
"PopulationSwarm",
|
|
27
|
+
"FunctionOptimizerModel",
|
|
28
|
+
"TemplateOptimizerModel",
|
|
29
|
+
]
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from cmenpy.hints import ScalarType
|
|
5
|
+
|
|
6
|
+
InnerSequence = typing.Union[typing.Tuple[ScalarType, ...], typing.List[ScalarType]]
|
|
7
|
+
SequenceStructure = typing.List[InnerSequence[ScalarType]]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Bounds:
|
|
11
|
+
def __init__(self, bounds: SequenceStructure[ScalarType]):
|
|
12
|
+
self.__bounds = bounds
|
|
13
|
+
|
|
14
|
+
@functools.cached_property
|
|
15
|
+
def ndim(self):
|
|
16
|
+
return len(self.__bounds)
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def low(self):
|
|
20
|
+
return self.__bounds[0][0]
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def up(self):
|
|
24
|
+
return self.__bounds[0][1]
|
|
25
|
+
|
|
26
|
+
def __iter__(self):
|
|
27
|
+
return (b for b in self.__bounds)
|
|
28
|
+
|
|
29
|
+
def __len__(self):
|
|
30
|
+
return len(self.__bounds)
|
|
31
|
+
|
|
32
|
+
def __class_getitem__(cls, params):
|
|
33
|
+
return create_bounds(params)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def create_bounds(bounds: SequenceStructure[ScalarType] | Bounds) -> Bounds:
|
|
37
|
+
if isinstance(bounds, Bounds):
|
|
38
|
+
return bounds
|
|
39
|
+
|
|
40
|
+
return Bounds(bounds)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from cmenpy.bounds import Bounds
|
|
6
|
+
from cmenpy.epoch import EpochIteration
|
|
7
|
+
from cmenpy.generator import DefaultGenerator
|
|
8
|
+
from cmenpy.kernel import KernelBuffer, KernelSize
|
|
9
|
+
from cmenpy.target import Target, TargetFunction
|
|
10
|
+
from cmenpy.tracker import Tracker
|
|
11
|
+
from cmenpy.hints.option import SenseType
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Context:
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
f: Target,
|
|
18
|
+
bounds: Bounds,
|
|
19
|
+
buffer: KernelBuffer,
|
|
20
|
+
generator: DefaultGenerator,
|
|
21
|
+
sense: SenseType,
|
|
22
|
+
):
|
|
23
|
+
self.__target = TargetFunction(f, bounds)
|
|
24
|
+
self.__bounds = bounds
|
|
25
|
+
self.__buff = buffer
|
|
26
|
+
self.__generator = generator
|
|
27
|
+
self.__sense = sense
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def target(self) -> TargetFunction:
|
|
31
|
+
return self.__target
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def bounds(self) -> Bounds:
|
|
35
|
+
return self.__bounds
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def buff(self) -> KernelBuffer:
|
|
39
|
+
return self.__buff
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def rng(self) -> np.random.Generator:
|
|
43
|
+
return self.__generator.rng
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def sense(self) -> SenseType:
|
|
47
|
+
return self.__sense
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class MainContextManager:
|
|
51
|
+
def __init__(
|
|
52
|
+
self,
|
|
53
|
+
f: Target,
|
|
54
|
+
bounds: Bounds,
|
|
55
|
+
epochs: int,
|
|
56
|
+
size: KernelSize,
|
|
57
|
+
seed: typing.Optional[int] = None,
|
|
58
|
+
debug: bool = False,
|
|
59
|
+
sense: SenseType = "min",
|
|
60
|
+
):
|
|
61
|
+
self.__size = size
|
|
62
|
+
self.__target = TargetFunction(f, bounds)
|
|
63
|
+
self.__bounds = bounds
|
|
64
|
+
self.__sense = sense
|
|
65
|
+
self.__k_buff = KernelBuffer(size, self.__bounds, self.__target, self.__sense)
|
|
66
|
+
self.__generator = DefaultGenerator(seed=seed)
|
|
67
|
+
self.__tracker = Tracker(self.__k_buff)
|
|
68
|
+
self.__epoch_it = EpochIteration(epochs, self.__tracker, self.__target, debug)
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def sense(self):
|
|
72
|
+
return self.__sense
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def epoch_it(self) -> EpochIteration:
|
|
76
|
+
return self.__epoch_it
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def buffer(self) -> KernelBuffer:
|
|
80
|
+
return self.__k_buff
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def target(self) -> TargetFunction:
|
|
84
|
+
return self.__target
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def bounds(self) -> Bounds:
|
|
88
|
+
return self.__bounds
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def default_generator(self) -> DefaultGenerator:
|
|
92
|
+
return self.__generator
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def tracker(self) -> Tracker:
|
|
96
|
+
return self.__tracker
|
cmenpy/epoch/__init__.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
from cmenpy.target import Target, TargetFunction
|
|
4
|
+
from cmenpy.tracker import Tracker
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Epoch:
|
|
8
|
+
def __init__(self, e: int):
|
|
9
|
+
self.__e: int = e
|
|
10
|
+
|
|
11
|
+
def __int__(self):
|
|
12
|
+
return self.__e
|
|
13
|
+
|
|
14
|
+
def __float__(self):
|
|
15
|
+
return float(self.__e)
|
|
16
|
+
|
|
17
|
+
def __repr__(self):
|
|
18
|
+
return f"Epoch({self.__e})"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class EpochIteration:
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
epochs: int,
|
|
25
|
+
tracker: Tracker,
|
|
26
|
+
target: TargetFunction,
|
|
27
|
+
debug: bool = False,
|
|
28
|
+
):
|
|
29
|
+
if epochs <= 0:
|
|
30
|
+
raise ValueError("Epochs must be a positive integer.")
|
|
31
|
+
|
|
32
|
+
self.__epochs: int = epochs
|
|
33
|
+
self.__current_epoch: int = 0
|
|
34
|
+
self.__cpu_time: float = 0
|
|
35
|
+
self.__tracker: Tracker = tracker
|
|
36
|
+
self.__target: TargetFunction = target
|
|
37
|
+
self.__debug: bool = debug
|
|
38
|
+
|
|
39
|
+
def __iter__(self):
|
|
40
|
+
for e in range(0, self.__epochs):
|
|
41
|
+
self.__current_epoch = e
|
|
42
|
+
|
|
43
|
+
start = time.process_time()
|
|
44
|
+
yield e
|
|
45
|
+
self.__cpu_time = time.process_time() - start
|
|
46
|
+
|
|
47
|
+
if self.__debug:
|
|
48
|
+
self.__tracker.track(e, self.cpu_time, self.__target.nfe)
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def current(self):
|
|
52
|
+
return self.__current_epoch
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def max(self) -> int:
|
|
56
|
+
return self.__epochs
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def cpu_time(self):
|
|
60
|
+
return self.__cpu_time
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from cmenpy.hints.option import SenseType
|
|
6
|
+
|
|
7
|
+
A = typing.TypeVar("A")
|
|
8
|
+
B = typing.TypeVar("B")
|
|
9
|
+
AB = tuple[A, B]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def is_best(ab: AB, sense: SenseType = "min"):
|
|
13
|
+
a, b = ab
|
|
14
|
+
|
|
15
|
+
if sense == "min":
|
|
16
|
+
mask = np.array(a) < np.array(b)
|
|
17
|
+
else:
|
|
18
|
+
mask = np.array(a) > np.array(b)
|
|
19
|
+
|
|
20
|
+
return np.flatnonzero(mask)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def is_worst(ab: AB, sense: SenseType = "min"):
|
|
24
|
+
a, b = ab
|
|
25
|
+
|
|
26
|
+
if sense == "min":
|
|
27
|
+
mask = np.array(a) > np.array(b)
|
|
28
|
+
else:
|
|
29
|
+
mask = np.array(a) < np.array(b)
|
|
30
|
+
|
|
31
|
+
return np.flatnonzero(mask)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def best_of(a: A) -> int:
|
|
36
|
+
return a.best
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def worst_of(a: A) -> int:
|
|
41
|
+
return a.worst
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
__all__ = ["is_best", "is_worst", "best_of", "worst_of"]
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DefaultGenerator:
|
|
7
|
+
def __init__(self, seed: typing.Optional[int] = None) -> None:
|
|
8
|
+
self.__seed = seed
|
|
9
|
+
self.__rng = np.random.default_rng(self.__seed)
|
|
10
|
+
|
|
11
|
+
@property
|
|
12
|
+
def seed(self) -> typing.Optional[int]:
|
|
13
|
+
return self.__seed
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def rng(self) -> np.random.Generator:
|
|
17
|
+
return self.__rng
|
cmenpy/hints/__init__.py
ADDED
cmenpy/hints/array.py
ADDED
cmenpy/hints/dynamic.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
|
|
3
|
+
from cmenpy.population.agent.base import BaseAgent
|
|
4
|
+
from cmenpy.hints import NDArrayType
|
|
5
|
+
|
|
6
|
+
Source = NDArrayType | Iterable[float | int]
|
|
7
|
+
SourceIterable = BaseAgent | NDArrayType
|
|
8
|
+
DualSource = tuple[SourceIterable, SourceIterable]
|
cmenpy/hints/option.py
ADDED
cmenpy/kernel/buffer.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from cmenpy.bounds import Bounds
|
|
6
|
+
from cmenpy.kernel.index import BufferIndex
|
|
7
|
+
from cmenpy.kernel.low import init_buffer
|
|
8
|
+
from cmenpy.kernel.mask import KernelMask
|
|
9
|
+
from cmenpy.kernel.size import KernelSize
|
|
10
|
+
from cmenpy.target import TargetFunction
|
|
11
|
+
from cmenpy.hints import NDArrayType
|
|
12
|
+
from cmenpy.hints.option import SenseType
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class KernelBuffer:
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
size: KernelSize,
|
|
19
|
+
bounds: Bounds,
|
|
20
|
+
target: TargetFunction,
|
|
21
|
+
sense: SenseType,
|
|
22
|
+
):
|
|
23
|
+
self.__size = size
|
|
24
|
+
self.__bounds = bounds
|
|
25
|
+
self.__target = target
|
|
26
|
+
self.__sense = sense
|
|
27
|
+
|
|
28
|
+
self.__buffer: NDArrayType = init_buffer(self.__size.max, bounds.ndim)
|
|
29
|
+
self.__mask = KernelMask(self.__size)
|
|
30
|
+
|
|
31
|
+
def apply(
|
|
32
|
+
self,
|
|
33
|
+
x: NDArrayType,
|
|
34
|
+
idx: typing.Union[int, slice, typing.List[int], None] = None,
|
|
35
|
+
) -> None:
|
|
36
|
+
"""Vectorizes the target function to evaluate and update the solutions matrix.
|
|
37
|
+
|
|
38
|
+
The internal buffer stores "fitness" in column 0 and "solutions" or "x"
|
|
39
|
+
from column 1 onwards. Supports updating a single row, a slice, a list/array
|
|
40
|
+
of indices, or the entire active matrix if `idx` is None.
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
x : NDArrayType
|
|
45
|
+
An array containing the new solution data to be inserted into the buffer.
|
|
46
|
+
idx : int, slice, NDArrayType, list, optional
|
|
47
|
+
The row index, slice, or index mask to update. If None, defaults to
|
|
48
|
+
the internal mask.
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
None
|
|
53
|
+
"""
|
|
54
|
+
rows = self.__mask.founds if idx is None else idx
|
|
55
|
+
self.__buffer[rows, 1:] = x
|
|
56
|
+
|
|
57
|
+
if isinstance(idx, int):
|
|
58
|
+
self.__buffer[rows, 0] = self.__target.evaluate(x)
|
|
59
|
+
else:
|
|
60
|
+
self.__buffer[rows, 0] = np.apply_along_axis(
|
|
61
|
+
self.__target, 1, self.__buffer[rows, 1:]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def shape(self):
|
|
66
|
+
return self.__buffer.shape
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def mask(self) -> KernelMask:
|
|
70
|
+
return self.__mask
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def raw(self) -> NDArrayType:
|
|
74
|
+
return self.__buffer
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def idx(self) -> BufferIndex:
|
|
78
|
+
return BufferIndex(self.__buffer, self.__mask, self.__sense)
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def size(self) -> KernelSize:
|
|
82
|
+
return self.__size
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def snapshot(self) -> "KernelBuffer":
|
|
86
|
+
return KernelBuffer(self.__size, self.__bounds, self.__target, self.__sense)
|
cmenpy/kernel/index.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from cmenpy.kernel.mask import KernelMask
|
|
4
|
+
from cmenpy.hints import NDArrayType
|
|
5
|
+
from cmenpy.hints.option import SenseType
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BufferIndex:
|
|
9
|
+
def __init__(self, buffer: NDArrayType, mask: KernelMask, sense: SenseType):
|
|
10
|
+
self.__buffer = buffer
|
|
11
|
+
self.__sense = sense
|
|
12
|
+
self.__mask = mask
|
|
13
|
+
|
|
14
|
+
def __iter__(self):
|
|
15
|
+
pop_size, _ = self.__buffer.shape
|
|
16
|
+
|
|
17
|
+
return iter(range(0, pop_size))
|
|
18
|
+
|
|
19
|
+
def __invert__(self):
|
|
20
|
+
return np.where(~np.isnan(self.__buffer[:, 0]))[0].astype(int)
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def sort(self):
|
|
24
|
+
_idx = np.argsort(self.__buffer[:, 0])
|
|
25
|
+
|
|
26
|
+
if self.__sense == "max":
|
|
27
|
+
return _idx[::-1]
|
|
28
|
+
|
|
29
|
+
return _idx
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def best(self):
|
|
33
|
+
if self.__sense == "max":
|
|
34
|
+
return self.sort[-1]
|
|
35
|
+
|
|
36
|
+
return self.sort[0]
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def worst(self):
|
|
40
|
+
if self.__sense == "max":
|
|
41
|
+
return self.sort[0]
|
|
42
|
+
|
|
43
|
+
return self.sort[-1]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from cmenpy.hints import NDArrayType
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def expand_buffer(
|
|
7
|
+
n: int,
|
|
8
|
+
ndim: int,
|
|
9
|
+
) -> NDArrayType:
|
|
10
|
+
return np.hstack(([n], np.full((ndim + 1), np.nan)))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def init_buffer(
|
|
14
|
+
n_pop: int,
|
|
15
|
+
ndim: int,
|
|
16
|
+
) -> NDArrayType:
|
|
17
|
+
return np.full((n_pop, ndim + 1), np.nan)
|
cmenpy/kernel/mask.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from cmenpy.kernel.size import KernelSize
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class KernelMask:
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
size: KernelSize,
|
|
12
|
+
):
|
|
13
|
+
self.__size: KernelSize = size
|
|
14
|
+
self.__mask = np.fromiter((False for _ in range(0, size.max)), dtype=bool)
|
|
15
|
+
self.__mask[0 : self.__size.size] = True
|
|
16
|
+
|
|
17
|
+
def __iter__(self):
|
|
18
|
+
return iter(map(bool, self.__mask))
|
|
19
|
+
|
|
20
|
+
def __setitem__(
|
|
21
|
+
self,
|
|
22
|
+
key: typing.Union[int, slice, typing.List[int], None],
|
|
23
|
+
value: bool,
|
|
24
|
+
):
|
|
25
|
+
self.__mask[key] = value
|
|
26
|
+
|
|
27
|
+
def __getitem__(
|
|
28
|
+
self, key: typing.Union[int, slice, typing.List[int], None]
|
|
29
|
+
) -> typing.Any:
|
|
30
|
+
return self.__mask[key]
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def active(self):
|
|
34
|
+
return sum(self.__mask)
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def passive(self):
|
|
38
|
+
return len(self.__mask) - sum(self.__mask)
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def founds(self) -> list[bool]:
|
|
42
|
+
return [*map(bool, self.__mask)]
|
cmenpy/kernel/size.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class KernelSize:
|
|
5
|
+
def __init__(
|
|
6
|
+
self,
|
|
7
|
+
size: int,
|
|
8
|
+
min_size: typing.Optional[int] = None,
|
|
9
|
+
max_size: typing.Optional[int] = None,
|
|
10
|
+
):
|
|
11
|
+
if min_size is None:
|
|
12
|
+
min_size = size
|
|
13
|
+
|
|
14
|
+
if max_size is None:
|
|
15
|
+
max_size = size
|
|
16
|
+
|
|
17
|
+
if size < min_size or size > max_size:
|
|
18
|
+
raise ValueError("Size must be between 'min_size' and 'max_size'.")
|
|
19
|
+
|
|
20
|
+
self.__size = size
|
|
21
|
+
self.__min = min_size
|
|
22
|
+
self.__max = max_size
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def max(self) -> int:
|
|
26
|
+
return self.__max
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def min(self) -> int:
|
|
30
|
+
return self.__min
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def size(self) -> int:
|
|
34
|
+
return self.__size
|