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
|
|
|
|