|
1
|
|
|
# pylint: disable=redefined-variable-type |
|
|
|
|
|
|
2
|
1 |
|
import numpy as np |
|
|
|
|
|
|
3
|
|
|
|
|
4
|
1 |
|
from grortir.main.model.core.optimization_status import OptimizationStatus |
|
5
|
1 |
|
from grortir.main.pso.group_optimization_strategy import \ |
|
6
|
|
|
GroupOptimizationStrategy |
|
7
|
|
|
|
|
8
|
|
|
|
|
9
|
1 |
|
class CreditCallsGroupOptimizationStrategy(GroupOptimizationStrategy): |
|
10
|
|
|
"""Optimization with credits. |
|
11
|
|
|
Attributes: |
|
12
|
|
|
stages_in_group (list): stages in group |
|
13
|
|
|
process (AbstractProcess): optimized process |
|
14
|
|
|
max_calls_for_group (int): max calls which can be |
|
15
|
|
|
used for this group |
|
16
|
|
|
expected_quality (float): expected quality |
|
17
|
|
|
""" |
|
18
|
|
|
|
|
19
|
1 |
|
def __init__(self, stages_in_group, process): |
|
20
|
1 |
|
self.stages_in_group = stages_in_group |
|
21
|
1 |
|
self.process = process |
|
22
|
1 |
|
self.max_calls_for_group = 0 |
|
23
|
1 |
|
self.expected_quality = np.inf |
|
24
|
|
|
|
|
25
|
1 |
|
def initialize(self): |
|
|
|
|
|
|
26
|
|
|
""" |
|
27
|
|
|
Called once and set initial value of max_calls_for_group. |
|
28
|
|
|
""" |
|
29
|
1 |
|
if self._calculate_current_cost_in_group() != 0: |
|
30
|
1 |
|
raise ValueError( |
|
31
|
|
|
"Stages in group shouldn't started with initial cost.") |
|
32
|
1 |
|
all_initial_calls = 0 |
|
33
|
1 |
|
already_used_calls = 0 |
|
34
|
1 |
|
all_stages = self.process.nodes() |
|
35
|
1 |
|
for stage in all_stages: |
|
36
|
1 |
|
all_initial_calls += stage.get_maximal_acceptable_cost() |
|
37
|
1 |
|
for stage in all_stages: |
|
38
|
1 |
|
already_used_calls += stage.get_cost() |
|
39
|
1 |
|
self.max_calls_for_group = all_initial_calls - already_used_calls |
|
40
|
|
|
|
|
41
|
1 |
|
for stage in self.stages_in_group: |
|
42
|
1 |
|
if self.expected_quality > stage.maximum_acceptable_quality: |
|
43
|
1 |
|
self.expected_quality = stage.maximum_acceptable_quality |
|
44
|
|
|
|
|
45
|
1 |
|
def should_continue(self, best_particle): |
|
|
|
|
|
|
46
|
|
|
""" |
|
47
|
|
|
Return true if optimization should be continued for Calls Process with |
|
48
|
|
|
credits. |
|
49
|
|
|
Args: |
|
50
|
|
|
best_particle Particle: best particle in swarm. |
|
51
|
|
|
|
|
52
|
|
|
Returns: |
|
53
|
|
|
bool: true if continuation is required. |
|
54
|
|
|
|
|
55
|
|
|
""" |
|
56
|
1 |
|
return self._is_safe_cost() and not self._is_enough_quality( |
|
57
|
|
|
best_particle) |
|
58
|
|
|
|
|
59
|
1 |
|
def finalize(self, best_particle): |
|
|
|
|
|
|
60
|
|
|
""" |
|
61
|
|
|
Set proper status after finished group optimization. |
|
62
|
|
|
Args: |
|
63
|
|
|
best_particle (Particle): best particle in Swarm |
|
64
|
|
|
""" |
|
65
|
1 |
|
optimizatin_status = OptimizationStatus.failed |
|
66
|
1 |
|
if self._is_safe_cost() and self._is_enough_quality( |
|
67
|
|
|
best_particle): |
|
68
|
1 |
|
optimizatin_status = OptimizationStatus.success |
|
69
|
1 |
|
for stage in self.stages_in_group: |
|
70
|
1 |
|
stage.optimization_status = optimizatin_status |
|
71
|
|
|
|
|
72
|
1 |
|
def _is_safe_cost(self): |
|
|
|
|
|
|
73
|
1 |
|
return ( |
|
74
|
|
|
self._calculate_current_cost_in_group() <= self.max_calls_for_group) |
|
75
|
|
|
|
|
76
|
1 |
|
def _is_enough_quality(self, best_particle): |
|
|
|
|
|
|
77
|
1 |
|
return best_particle.best_quality <= self.expected_quality |
|
78
|
|
|
|
|
79
|
1 |
|
def _calculate_current_cost_in_group(self): |
|
|
|
|
|
|
80
|
1 |
|
calls_used_in_group = 0 |
|
81
|
1 |
|
for stage in self.stages_in_group: |
|
82
|
1 |
|
calls_used_in_group += stage.get_cost() |
|
83
|
|
|
return calls_used_in_group |
|
84
|
|
|
|