cuckoo-library 1.0.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.
- cuckoo_library-1.0.0/LICENSE +21 -0
- cuckoo_library-1.0.0/PKG-INFO +61 -0
- cuckoo_library-1.0.0/README.md +39 -0
- cuckoo_library-1.0.0/cuckoo_library/__init__.py +8 -0
- cuckoo_library-1.0.0/cuckoo_library/algorithm/cuckoo_search.py +111 -0
- cuckoo_library-1.0.0/cuckoo_library/algorithm/levy_flight.py +79 -0
- cuckoo_library-1.0.0/cuckoo_library/decorator/__init__.py +34 -0
- cuckoo_library-1.0.0/cuckoo_library/decorator/type.py +103 -0
- cuckoo_library-1.0.0/cuckoo_library/model/__init__.py +0 -0
- cuckoo_library-1.0.0/cuckoo_library/model/block_coordinate_descent.py +165 -0
- cuckoo_library-1.0.0/cuckoo_library/model/caching.py +79 -0
- cuckoo_library-1.0.0/cuckoo_library/model/communication.py +281 -0
- cuckoo_library-1.0.0/cuckoo_library/model/offloading_efficiency.py +227 -0
- cuckoo_library-1.0.0/cuckoo_library/model/policy.py +119 -0
- cuckoo_library-1.0.0/cuckoo_library/model/scheduling.py +163 -0
- cuckoo_library-1.0.0/cuckoo_library/model/task_ranking.py +57 -0
- cuckoo_library-1.0.0/cuckoo_library/model/transmission.py +325 -0
- cuckoo_library-1.0.0/cuckoo_library/type/block_coordinate_descent_type.py +45 -0
- cuckoo_library-1.0.0/cuckoo_library/type/caching_type.py +22 -0
- cuckoo_library-1.0.0/cuckoo_library/type/communication_type.py +59 -0
- cuckoo_library-1.0.0/cuckoo_library/type/cuckoo_search_type.py +21 -0
- cuckoo_library-1.0.0/cuckoo_library/type/levy_flight_type.py +21 -0
- cuckoo_library-1.0.0/cuckoo_library/type/offloading_efficiency_type.py +47 -0
- cuckoo_library-1.0.0/cuckoo_library/type/policy_type.py +26 -0
- cuckoo_library-1.0.0/cuckoo_library/type/scheduling_type.py +42 -0
- cuckoo_library-1.0.0/cuckoo_library/type/task_ranking_type.py +16 -0
- cuckoo_library-1.0.0/cuckoo_library/type/transmission_type.py +74 -0
- cuckoo_library-1.0.0/cuckoo_library/utils.py +0 -0
- cuckoo_library-1.0.0/cuckoo_library.egg-info/PKG-INFO +61 -0
- cuckoo_library-1.0.0/cuckoo_library.egg-info/SOURCES.txt +42 -0
- cuckoo_library-1.0.0/cuckoo_library.egg-info/dependency_links.txt +1 -0
- cuckoo_library-1.0.0/cuckoo_library.egg-info/top_level.txt +1 -0
- cuckoo_library-1.0.0/pyproject.toml +34 -0
- cuckoo_library-1.0.0/setup.cfg +4 -0
- cuckoo_library-1.0.0/tests/test_block_coordinate_descent.py +33 -0
- cuckoo_library-1.0.0/tests/test_caching.py +19 -0
- cuckoo_library-1.0.0/tests/test_communication.py +44 -0
- cuckoo_library-1.0.0/tests/test_cuckoo_search.py +17 -0
- cuckoo_library-1.0.0/tests/test_levy_flight.py +18 -0
- cuckoo_library-1.0.0/tests/test_offloading_efficiency.py +36 -0
- cuckoo_library-1.0.0/tests/test_policy.py +20 -0
- cuckoo_library-1.0.0/tests/test_scheduling.py +34 -0
- cuckoo_library-1.0.0/tests/test_task_ranking.py +12 -0
- cuckoo_library-1.0.0/tests/test_transmission.py +55 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CUCKOO HEURISTIC
|
|
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,61 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cuckoo-library
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A library that provides operations for metaheuristic algorithms
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/cuckoo-heuristic/cuckoo-library
|
|
7
|
+
Project-URL: Source, https://github.com/cuckoo-heuristic/cuckoo-library
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# CUCKOO LIBRARY
|
|
24
|
+

|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
**Requirements:** `Python` 3.10.0 or newer, `pytest`
|
|
28
|
+
|
|
29
|
+
### Installation
|
|
30
|
+
```bash
|
|
31
|
+
uv add cuckoo-library
|
|
32
|
+
# or
|
|
33
|
+
pip install cuckoo-library
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Example
|
|
37
|
+
```python
|
|
38
|
+
from cuckoo_library.model.communication import local_task_compute_time
|
|
39
|
+
from cuckoo_library.model.transmission import distance_2d
|
|
40
|
+
|
|
41
|
+
compute_time = local_task_compute_time(100, 10)
|
|
42
|
+
distance = distance_2d(0, 0, 3, 4)
|
|
43
|
+
|
|
44
|
+
print(compute_time) # 10.0
|
|
45
|
+
print(distance) # 5.0
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Build
|
|
49
|
+
Create a wheel package in `dist/`:
|
|
50
|
+
```bash
|
|
51
|
+
python -m pip wheel . --no-deps --wheel-dir dist #Recommendation
|
|
52
|
+
#or
|
|
53
|
+
python -m build
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Testing
|
|
57
|
+
```bash
|
|
58
|
+
pytest
|
|
59
|
+
#or
|
|
60
|
+
python -m pytest tests -q
|
|
61
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# CUCKOO LIBRARY
|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
## Usage
|
|
5
|
+
**Requirements:** `Python` 3.10.0 or newer, `pytest`
|
|
6
|
+
|
|
7
|
+
### Installation
|
|
8
|
+
```bash
|
|
9
|
+
uv add cuckoo-library
|
|
10
|
+
# or
|
|
11
|
+
pip install cuckoo-library
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Example
|
|
15
|
+
```python
|
|
16
|
+
from cuckoo_library.model.communication import local_task_compute_time
|
|
17
|
+
from cuckoo_library.model.transmission import distance_2d
|
|
18
|
+
|
|
19
|
+
compute_time = local_task_compute_time(100, 10)
|
|
20
|
+
distance = distance_2d(0, 0, 3, 4)
|
|
21
|
+
|
|
22
|
+
print(compute_time) # 10.0
|
|
23
|
+
print(distance) # 5.0
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Build
|
|
27
|
+
Create a wheel package in `dist/`:
|
|
28
|
+
```bash
|
|
29
|
+
python -m pip wheel . --no-deps --wheel-dir dist #Recommendation
|
|
30
|
+
#or
|
|
31
|
+
python -m build
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Testing
|
|
35
|
+
```bash
|
|
36
|
+
pytest
|
|
37
|
+
#or
|
|
38
|
+
python -m pytest tests -q
|
|
39
|
+
```
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from typing import Sequence
|
|
2
|
+
from cuckoo_library.decorator.type import type_decorator
|
|
3
|
+
from cuckoo_library.type.cuckoo_search_type import (
|
|
4
|
+
CSExploitationMove,
|
|
5
|
+
CSExploitationMove,
|
|
6
|
+
CSPositionUpdate,
|
|
7
|
+
CSPositionUpdate,
|
|
8
|
+
CSRandomWalkMove,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@type_decorator(
|
|
13
|
+
dc_type=CSPositionUpdate,
|
|
14
|
+
return_type=Sequence[float],
|
|
15
|
+
)
|
|
16
|
+
def cs_position_update(
|
|
17
|
+
x_t: Sequence[float], omega: float, levy_step: Sequence[float]
|
|
18
|
+
) -> Sequence[float]:
|
|
19
|
+
"""
|
|
20
|
+
Name:
|
|
21
|
+
Cuckoo position update
|
|
22
|
+
|
|
23
|
+
Description:
|
|
24
|
+
Updates solution position using Levy flight step.
|
|
25
|
+
|
|
26
|
+
Meaning:
|
|
27
|
+
- x_t: current solution vector
|
|
28
|
+
- omega: step scaling factor
|
|
29
|
+
- levy_step: Levy step vector
|
|
30
|
+
"""
|
|
31
|
+
if not x_t or not levy_step:
|
|
32
|
+
return list(x_t) if x_t else []
|
|
33
|
+
|
|
34
|
+
n = min(len(x_t), len(levy_step))
|
|
35
|
+
w = float(omega)
|
|
36
|
+
|
|
37
|
+
x_next = []
|
|
38
|
+
for i in range(n):
|
|
39
|
+
x_next.append(float(x_t[i]) + w * float(levy_step[i]))
|
|
40
|
+
|
|
41
|
+
if len(x_t) > n:
|
|
42
|
+
x_next.extend(float(v) for v in x_t[n:])
|
|
43
|
+
|
|
44
|
+
return x_next
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@type_decorator(
|
|
48
|
+
dc_type=CSExploitationMove,
|
|
49
|
+
return_type=Sequence[int],
|
|
50
|
+
)
|
|
51
|
+
def cs_exploitation_move(x_t: Sequence[int], levy_length: int) -> Sequence[int]:
|
|
52
|
+
"""
|
|
53
|
+
Name:
|
|
54
|
+
CS exploitation move
|
|
55
|
+
|
|
56
|
+
Description:
|
|
57
|
+
Moves solution by applying levy_length steps (abstracted as index flips).
|
|
58
|
+
|
|
59
|
+
Meaning:
|
|
60
|
+
- x_t: current binary/int solution vector
|
|
61
|
+
- levy_length: number of modification steps
|
|
62
|
+
"""
|
|
63
|
+
if not x_t:
|
|
64
|
+
return []
|
|
65
|
+
|
|
66
|
+
L = int(levy_length)
|
|
67
|
+
if L <= 0:
|
|
68
|
+
return list(x_t)
|
|
69
|
+
|
|
70
|
+
x_next = list(x_t)
|
|
71
|
+
n = len(x_next)
|
|
72
|
+
|
|
73
|
+
# deterministic pseudo-move: flip first L positions (bounded)
|
|
74
|
+
for i in range(min(L, n)):
|
|
75
|
+
x_next[i] = 1 - int(x_next[i]) if int(x_next[i]) in (0, 1) else int(x_next[i])
|
|
76
|
+
|
|
77
|
+
return x_next
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@type_decorator(
|
|
81
|
+
dc_type=CSRandomWalkMove,
|
|
82
|
+
return_type=Sequence[int],
|
|
83
|
+
)
|
|
84
|
+
def cs_random_walk_move(x_t: Sequence[int], levy_length: int) -> Sequence[int]:
|
|
85
|
+
"""
|
|
86
|
+
Name:
|
|
87
|
+
CS random walk move
|
|
88
|
+
|
|
89
|
+
Description:
|
|
90
|
+
Applies a random-walk style modification to the solution.
|
|
91
|
+
|
|
92
|
+
Meaning:
|
|
93
|
+
- x_t: current binary/int solution vector
|
|
94
|
+
- levy_length: number of modification steps
|
|
95
|
+
"""
|
|
96
|
+
if not x_t:
|
|
97
|
+
return []
|
|
98
|
+
|
|
99
|
+
L = int(levy_length)
|
|
100
|
+
if L <= 0:
|
|
101
|
+
return list(x_t)
|
|
102
|
+
|
|
103
|
+
x_next = list(x_t)
|
|
104
|
+
n = len(x_next)
|
|
105
|
+
|
|
106
|
+
# deterministic pseudo-walk: flip last L positions (bounded)
|
|
107
|
+
for idx in range(1, min(L, n) + 1):
|
|
108
|
+
i = n - idx
|
|
109
|
+
x_next[i] = 1 - int(x_next[i]) if int(x_next[i]) in (0, 1) else int(x_next[i])
|
|
110
|
+
|
|
111
|
+
return x_next
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from cuckoo_library.decorator.type import type_decorator
|
|
2
|
+
from cuckoo_library.type.levy_flight_type import (
|
|
3
|
+
LevyLengthRandomWalk,
|
|
4
|
+
LevyLengthToBest,
|
|
5
|
+
LevyStepMantegna,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@type_decorator(
|
|
10
|
+
dc_type=LevyStepMantegna,
|
|
11
|
+
return_type=float,
|
|
12
|
+
)
|
|
13
|
+
def levy_step_mantegna(u: float, v: float, lambda_param: float) -> float:
|
|
14
|
+
"""
|
|
15
|
+
Name:
|
|
16
|
+
Levy step (Mantegna)
|
|
17
|
+
|
|
18
|
+
Description:
|
|
19
|
+
Generates Levy step value using Mantegna's method.
|
|
20
|
+
|
|
21
|
+
Meaning:
|
|
22
|
+
- u: Gaussian random variable
|
|
23
|
+
- v: Gaussian random variable
|
|
24
|
+
- lambda_param: Levy distribution parameter (1 < lambda <= 3 typically)
|
|
25
|
+
"""
|
|
26
|
+
lam = float(lambda_param)
|
|
27
|
+
if lam <= 0.0:
|
|
28
|
+
return 0.0
|
|
29
|
+
|
|
30
|
+
uu = float(u)
|
|
31
|
+
vv = float(v)
|
|
32
|
+
if vv == 0.0:
|
|
33
|
+
return 0.0
|
|
34
|
+
|
|
35
|
+
return float(uu / (abs(vv) ** (1.0 / lam)))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@type_decorator(
|
|
39
|
+
dc_type=LevyLengthToBest,
|
|
40
|
+
return_type=int,
|
|
41
|
+
)
|
|
42
|
+
def levy_length_to_best(hamming_distance: float, N_levy: float) -> int:
|
|
43
|
+
"""
|
|
44
|
+
Name:
|
|
45
|
+
Levy flight length to best
|
|
46
|
+
|
|
47
|
+
Description:
|
|
48
|
+
Computes quantized Levy flight length toward best solution.
|
|
49
|
+
|
|
50
|
+
Meaning:
|
|
51
|
+
- hamming_distance: H_m(current, best)
|
|
52
|
+
- N_levy: Levy step scalar
|
|
53
|
+
"""
|
|
54
|
+
hm = float(hamming_distance)
|
|
55
|
+
nlevy = float(N_levy)
|
|
56
|
+
length = 2.0 * hm * nlevy
|
|
57
|
+
return int(round(length))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@type_decorator(
|
|
61
|
+
dc_type=LevyLengthRandomWalk,
|
|
62
|
+
return_type=int,
|
|
63
|
+
)
|
|
64
|
+
def levy_length_random_walk(I: float, N_levy: float) -> int:
|
|
65
|
+
"""
|
|
66
|
+
Name:
|
|
67
|
+
Levy flight length (random walk)
|
|
68
|
+
|
|
69
|
+
Description:
|
|
70
|
+
Computes quantized Levy flight length for random walk.
|
|
71
|
+
|
|
72
|
+
Meaning:
|
|
73
|
+
- I: random variable in the paper
|
|
74
|
+
- N_levy: Levy step scalar
|
|
75
|
+
"""
|
|
76
|
+
ii = float(I)
|
|
77
|
+
nlevy = float(N_levy)
|
|
78
|
+
length = 2.0 * ii * nlevy
|
|
79
|
+
return int(round(length))
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from dataclasses import is_dataclass
|
|
2
|
+
from typing import get_type_hints
|
|
3
|
+
from functools import wraps
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def type(dc_type, return_type):
|
|
7
|
+
dc_fields = get_type_hints(dc_type)
|
|
8
|
+
|
|
9
|
+
def decorator(fn):
|
|
10
|
+
@wraps(fn)
|
|
11
|
+
def wrapper(*args, **kwargs):
|
|
12
|
+
if not args or not isinstance(args[0], dc_type):
|
|
13
|
+
raise TypeError("first argument must be dataclass instance")
|
|
14
|
+
|
|
15
|
+
spec = args[0]
|
|
16
|
+
|
|
17
|
+
for name, tp in dc_fields.items():
|
|
18
|
+
val = getattr(spec, name)
|
|
19
|
+
if not isinstance(val, tp):
|
|
20
|
+
raise TypeError(f"{name} must be {tp}")
|
|
21
|
+
|
|
22
|
+
out = fn(*args, **kwargs)
|
|
23
|
+
|
|
24
|
+
if not isinstance(out, return_type):
|
|
25
|
+
raise TypeError(f"return must be {return_type}")
|
|
26
|
+
|
|
27
|
+
return out
|
|
28
|
+
|
|
29
|
+
return wrapper
|
|
30
|
+
|
|
31
|
+
if not is_dataclass(dc_type):
|
|
32
|
+
raise TypeError("dc_type must be dataclass")
|
|
33
|
+
|
|
34
|
+
return decorator
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
from dataclasses import is_dataclass
|
|
2
|
+
from typing import get_type_hints, get_origin, get_args
|
|
3
|
+
from functools import wraps
|
|
4
|
+
import inspect
|
|
5
|
+
import numbers
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _is_instance(val, tp) -> bool:
|
|
9
|
+
"""
|
|
10
|
+
Minimal runtime type checker:
|
|
11
|
+
- supports Union/Optional
|
|
12
|
+
- supports basic list/tuple container checks (shallow)
|
|
13
|
+
- treats float as (int/float) if you want numeric-friendly behavior
|
|
14
|
+
"""
|
|
15
|
+
origin = get_origin(tp)
|
|
16
|
+
args = get_args(tp)
|
|
17
|
+
|
|
18
|
+
if (
|
|
19
|
+
origin is None
|
|
20
|
+
and hasattr(tp, "__args__")
|
|
21
|
+
and str(tp).startswith("typing.Union")
|
|
22
|
+
):
|
|
23
|
+
origin = getattr(tp, "__origin__", None)
|
|
24
|
+
args = getattr(tp, "__args__", ())
|
|
25
|
+
|
|
26
|
+
if origin is inspect._empty:
|
|
27
|
+
return True
|
|
28
|
+
|
|
29
|
+
if origin is None:
|
|
30
|
+
if tp is float:
|
|
31
|
+
return isinstance(val, numbers.Real) and not isinstance(val, bool)
|
|
32
|
+
if tp is int:
|
|
33
|
+
return isinstance(val, numbers.Integral) and not isinstance(val, bool)
|
|
34
|
+
if tp is bool:
|
|
35
|
+
return isinstance(val, bool)
|
|
36
|
+
return isinstance(val, tp)
|
|
37
|
+
|
|
38
|
+
if origin is list:
|
|
39
|
+
if not isinstance(val, list):
|
|
40
|
+
return False
|
|
41
|
+
if not args:
|
|
42
|
+
return True
|
|
43
|
+
return all(_is_instance(x, args[0]) for x in val)
|
|
44
|
+
|
|
45
|
+
if origin is tuple:
|
|
46
|
+
if not isinstance(val, tuple):
|
|
47
|
+
return False
|
|
48
|
+
if not args:
|
|
49
|
+
return True
|
|
50
|
+
if len(args) == 2 and args[1] is Ellipsis:
|
|
51
|
+
return all(_is_instance(x, args[0]) for x in val)
|
|
52
|
+
if len(val) != len(args):
|
|
53
|
+
return False
|
|
54
|
+
return all(_is_instance(x, tpx) for x, tpx in zip(val, args))
|
|
55
|
+
|
|
56
|
+
if origin is type(None):
|
|
57
|
+
return val is None
|
|
58
|
+
|
|
59
|
+
if origin is getattr(__import__("typing"), "Union", None):
|
|
60
|
+
return any(_is_instance(val, tpx) for tpx in args)
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
return isinstance(val, origin)
|
|
64
|
+
except TypeError:
|
|
65
|
+
return True
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def type_decorator(dc_type, return_type):
|
|
69
|
+
if not is_dataclass(dc_type):
|
|
70
|
+
raise TypeError("dc_type must be dataclass")
|
|
71
|
+
|
|
72
|
+
dc_fields = get_type_hints(dc_type)
|
|
73
|
+
|
|
74
|
+
def decorator(fn):
|
|
75
|
+
sig = inspect.signature(fn)
|
|
76
|
+
|
|
77
|
+
@wraps(fn)
|
|
78
|
+
def wrapper(*args, **kwargs):
|
|
79
|
+
bound = sig.bind_partial(*args, **kwargs)
|
|
80
|
+
bound.apply_defaults()
|
|
81
|
+
|
|
82
|
+
for name, tp in dc_fields.items():
|
|
83
|
+
if name not in bound.arguments:
|
|
84
|
+
raise TypeError(f"missing required argument: {name}")
|
|
85
|
+
val = bound.arguments[name]
|
|
86
|
+
if not _is_instance(val, tp):
|
|
87
|
+
raise TypeError(f"{name} must be {tp}")
|
|
88
|
+
|
|
89
|
+
out = fn(*args, **kwargs)
|
|
90
|
+
|
|
91
|
+
if return_type is float:
|
|
92
|
+
if not isinstance(out, numbers.Real) or isinstance(out, bool):
|
|
93
|
+
raise TypeError("return must be float-like")
|
|
94
|
+
return float(out)
|
|
95
|
+
|
|
96
|
+
if not _is_instance(out, return_type):
|
|
97
|
+
raise TypeError(f"return must be {return_type}")
|
|
98
|
+
|
|
99
|
+
return out
|
|
100
|
+
|
|
101
|
+
return wrapper
|
|
102
|
+
|
|
103
|
+
return decorator
|
|
File without changes
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from cuckoo_library.decorator.type import type_decorator
|
|
3
|
+
from cuckoo_library.type.block_coordinate_descent_type import (
|
|
4
|
+
AssignedCpuFrequency,
|
|
5
|
+
TxPowerAuxAtZero,
|
|
6
|
+
TxPowerAuxFunction,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@type_decorator(
|
|
11
|
+
dc_type=AssignedCpuFrequency,
|
|
12
|
+
return_type=float,
|
|
13
|
+
)
|
|
14
|
+
def assigned_cpu_frequency(
|
|
15
|
+
z_selected: float, f_star_local_hz: float, f_max_provider_hz: float
|
|
16
|
+
) -> float:
|
|
17
|
+
"""
|
|
18
|
+
Name:
|
|
19
|
+
Assigned CPU frequency
|
|
20
|
+
|
|
21
|
+
Description:
|
|
22
|
+
Computes the sub-optimal assigned CPU frequency used in the paper.
|
|
23
|
+
|
|
24
|
+
Meaning:
|
|
25
|
+
- z_selected: selection indicator (0/1) for executing on this provider
|
|
26
|
+
- f_star_local_hz: optimal local frequency baseline (or f*_n)
|
|
27
|
+
- f_max_provider_hz: provider max CPU frequency
|
|
28
|
+
"""
|
|
29
|
+
z = float(z_selected)
|
|
30
|
+
if z <= 0.0:
|
|
31
|
+
return 0.0
|
|
32
|
+
return float(min(z * float(f_star_local_hz), float(f_max_provider_hz)))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@type_decorator(
|
|
36
|
+
dc_type=TxPowerAuxFunction,
|
|
37
|
+
return_type=float,
|
|
38
|
+
)
|
|
39
|
+
def tx_power_aux_function(
|
|
40
|
+
z_selected: float,
|
|
41
|
+
alpha_n: float,
|
|
42
|
+
beta_n: float,
|
|
43
|
+
t_ref_s: float,
|
|
44
|
+
e_loc_j: float,
|
|
45
|
+
p_w: float,
|
|
46
|
+
h: float,
|
|
47
|
+
noise_delta2: float,
|
|
48
|
+
) -> float:
|
|
49
|
+
"""
|
|
50
|
+
Name:
|
|
51
|
+
TX power auxiliary function
|
|
52
|
+
|
|
53
|
+
Description:
|
|
54
|
+
Helper function used for quasi-concavity-based power optimization.
|
|
55
|
+
|
|
56
|
+
Meaning:
|
|
57
|
+
- z_selected: selection indicator (0/1)
|
|
58
|
+
- alpha_n, beta_n: weights
|
|
59
|
+
- t_ref_s: reference time
|
|
60
|
+
- e_loc_j: all-local energy
|
|
61
|
+
- p_w: transmit power (W)
|
|
62
|
+
- h: channel coefficient used in the paper's auxiliary form
|
|
63
|
+
- noise_delta2: noise power
|
|
64
|
+
"""
|
|
65
|
+
z = float(z_selected)
|
|
66
|
+
if z <= 0.0:
|
|
67
|
+
return 0.0
|
|
68
|
+
|
|
69
|
+
t_ref = float(t_ref_s)
|
|
70
|
+
e_loc = float(e_loc_j)
|
|
71
|
+
if t_ref <= 0.0 or e_loc <= 0.0:
|
|
72
|
+
return 0.0
|
|
73
|
+
|
|
74
|
+
p = float(p_w)
|
|
75
|
+
hh = float(h)
|
|
76
|
+
d2 = float(noise_delta2)
|
|
77
|
+
if hh <= 0.0 or d2 <= 0.0 or p < 0.0:
|
|
78
|
+
return 0.0
|
|
79
|
+
|
|
80
|
+
term_log = math.log2(1.0 + (p * hh) / d2)
|
|
81
|
+
denom = math.log(2.0) * (d2 + p * hh)
|
|
82
|
+
|
|
83
|
+
left = z * (float(beta_n) / e_loc) * term_log
|
|
84
|
+
right = z * ((float(alpha_n) / t_ref) + (float(beta_n) / e_loc) * p) * (hh / denom)
|
|
85
|
+
|
|
86
|
+
return float(left - right)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@type_decorator(
|
|
90
|
+
dc_type=TxPowerAuxFunction,
|
|
91
|
+
return_type=float,
|
|
92
|
+
)
|
|
93
|
+
def tx_power_aux_derivative(
|
|
94
|
+
z_selected: float,
|
|
95
|
+
alpha_n: float,
|
|
96
|
+
beta_n: float,
|
|
97
|
+
t_ref_s: float,
|
|
98
|
+
e_loc_j: float,
|
|
99
|
+
p_w: float,
|
|
100
|
+
h: float,
|
|
101
|
+
noise_delta2: float,
|
|
102
|
+
) -> float:
|
|
103
|
+
"""
|
|
104
|
+
Name:
|
|
105
|
+
TX power auxiliary derivative
|
|
106
|
+
|
|
107
|
+
Description:
|
|
108
|
+
Derivative of the auxiliary function w.r.t transmit power.
|
|
109
|
+
|
|
110
|
+
Meaning:
|
|
111
|
+
- same as tx_power_aux_function inputs
|
|
112
|
+
"""
|
|
113
|
+
z = float(z_selected)
|
|
114
|
+
if z <= 0.0:
|
|
115
|
+
return 0.0
|
|
116
|
+
|
|
117
|
+
t_ref = float(t_ref_s)
|
|
118
|
+
e_loc = float(e_loc_j)
|
|
119
|
+
if t_ref <= 0.0 or e_loc <= 0.0:
|
|
120
|
+
return 0.0
|
|
121
|
+
|
|
122
|
+
p = float(p_w)
|
|
123
|
+
hh = float(h)
|
|
124
|
+
d2 = float(noise_delta2)
|
|
125
|
+
if hh <= 0.0 or d2 <= 0.0 or p < 0.0:
|
|
126
|
+
return 0.0
|
|
127
|
+
|
|
128
|
+
numer = z * (hh**2) * ((float(alpha_n) / t_ref) + (float(beta_n) / e_loc) * p)
|
|
129
|
+
denom = math.log(2.0) * ((d2 + p * hh) ** 2)
|
|
130
|
+
|
|
131
|
+
return float(numer / denom)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@type_decorator(
|
|
135
|
+
dc_type=TxPowerAuxAtZero,
|
|
136
|
+
return_type=float,
|
|
137
|
+
)
|
|
138
|
+
def tx_power_aux_at_zero(
|
|
139
|
+
z_selected: float, alpha_n: float, t_ref_s: float, h: float, noise_delta2: float
|
|
140
|
+
) -> float:
|
|
141
|
+
"""
|
|
142
|
+
Name:
|
|
143
|
+
TX power auxiliary at zero
|
|
144
|
+
|
|
145
|
+
Description:
|
|
146
|
+
Auxiliary function value at p=0 (used in the paper's reasoning).
|
|
147
|
+
|
|
148
|
+
Meaning:
|
|
149
|
+
- z_selected: selection indicator (0/1)
|
|
150
|
+
- alpha_n: time weight
|
|
151
|
+
- t_ref_s: reference time
|
|
152
|
+
- h: channel coefficient
|
|
153
|
+
- noise_delta2: noise power
|
|
154
|
+
"""
|
|
155
|
+
z = float(z_selected)
|
|
156
|
+
if z <= 0.0:
|
|
157
|
+
return 0.0
|
|
158
|
+
|
|
159
|
+
t_ref = float(t_ref_s)
|
|
160
|
+
hh = float(h)
|
|
161
|
+
d2 = float(noise_delta2)
|
|
162
|
+
if t_ref <= 0.0 or hh <= 0.0 or d2 <= 0.0:
|
|
163
|
+
return 0.0
|
|
164
|
+
|
|
165
|
+
return float(-(z * float(alpha_n) * hh) / (math.log(2.0) * d2 * t_ref))
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from cuckoo_library.decorator.type import type_decorator
|
|
2
|
+
from typing import Sequence
|
|
3
|
+
|
|
4
|
+
from cuckoo_library.type.caching_type import (
|
|
5
|
+
CacheCapacityConstraint,
|
|
6
|
+
CacheCapacityUsed,
|
|
7
|
+
CacheStateUpdateConstraint,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@type_decorator(
|
|
12
|
+
dc_type=CacheStateUpdateConstraint,
|
|
13
|
+
return_type=float,
|
|
14
|
+
)
|
|
15
|
+
def cache_state_update_constraint(
|
|
16
|
+
u_prev_k: float, z_task_rank: float, v_task_requires_k: float
|
|
17
|
+
) -> float:
|
|
18
|
+
"""
|
|
19
|
+
Name:
|
|
20
|
+
Cache state update constraint (per k)
|
|
21
|
+
|
|
22
|
+
Description:
|
|
23
|
+
Computes the upper bound for updated cache flag u_{x,r}^k.
|
|
24
|
+
|
|
25
|
+
Meaning:
|
|
26
|
+
- u_prev_k: previous cache flag u_{x,r-1}^k
|
|
27
|
+
- z_task_rank: whether the selected task is executed at rank r on provider x (0/1)
|
|
28
|
+
- v_task_requires_k: whether the selected task requires service k (0/1)
|
|
29
|
+
"""
|
|
30
|
+
return float(float(u_prev_k) + float(z_task_rank) * float(v_task_requires_k))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@type_decorator(
|
|
34
|
+
dc_type=CacheCapacityUsed,
|
|
35
|
+
return_type=float,
|
|
36
|
+
)
|
|
37
|
+
def cache_capacity_used(u_k: Sequence[float], L_k: Sequence[float]) -> float:
|
|
38
|
+
"""
|
|
39
|
+
Name:
|
|
40
|
+
Cache capacity used
|
|
41
|
+
|
|
42
|
+
Description:
|
|
43
|
+
Computes total cache space used.
|
|
44
|
+
|
|
45
|
+
Meaning:
|
|
46
|
+
- u_k: cache flags per service k (0/1)
|
|
47
|
+
- L_k: cache size per service k
|
|
48
|
+
"""
|
|
49
|
+
if not u_k or not L_k:
|
|
50
|
+
return 0.0
|
|
51
|
+
|
|
52
|
+
n = min(len(u_k), len(L_k))
|
|
53
|
+
total = 0.0
|
|
54
|
+
for i in range(n):
|
|
55
|
+
total += float(u_k[i]) * float(L_k[i])
|
|
56
|
+
return float(total)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@type_decorator(
|
|
60
|
+
dc_type=CacheCapacityConstraint,
|
|
61
|
+
return_type=float,
|
|
62
|
+
)
|
|
63
|
+
def cache_capacity_constraint(
|
|
64
|
+
u_k: Sequence[float], L_k: Sequence[float], L_max: float
|
|
65
|
+
) -> float:
|
|
66
|
+
"""
|
|
67
|
+
Name:
|
|
68
|
+
Cache capacity constraint
|
|
69
|
+
|
|
70
|
+
Description:
|
|
71
|
+
Checks whether cache capacity is satisfied (returns 1.0 if satisfied else 0.0).
|
|
72
|
+
|
|
73
|
+
Meaning:
|
|
74
|
+
- u_k: cache flags per service k (0/1)
|
|
75
|
+
- L_k: cache size per service k
|
|
76
|
+
- L_max: maximum cache capacity
|
|
77
|
+
"""
|
|
78
|
+
used = cache_capacity_used(u_k, L_k)
|
|
79
|
+
return 1.0 if used <= float(L_max) else 0.0
|