1
+
2
+ from greyjack .persistence .CotwinBuilderBase import CotwinBuilderBase
3
+ from greyjack .variables .GJInteger import GJInteger
4
+ from examples .object_oriented .cloud_balancing .cotwin .CotScheduleCB import CotScheduleCB
5
+ from examples .object_oriented .cloud_balancing .cotwin .CotProcess import CotProcess
6
+ from examples .object_oriented .cloud_balancing .cotwin .CotComputer import CotComputer
7
+ from examples .object_oriented .cloud_balancing .score .PlainScoreCalculatorCB import PlainScoreCalculatorCB
8
+ from examples .object_oriented .cloud_balancing .score .IncrementalScoreCalculatorCB import IncrementalScoreCalculatorCB
9
+ import numpy as np
10
+ from numba import jit
11
+
12
+ class CotwinBuilder (CotwinBuilderBase ):
13
+
14
+ def __init__ (self , use_incremental_score_calculator , use_greed_init ):
15
+
16
+ self .use_incremental_score_calculator = use_incremental_score_calculator
17
+ self .use_greed_init = use_greed_init
18
+
19
+ pass
20
+
21
+ def build_cotwin (self , domain_model , is_already_initialized ):
22
+
23
+ cotwin_model = CotScheduleCB ()
24
+
25
+ cotwin_model .add_planning_entities_list (self ._build_planning_processes (domain_model ), "processes" )
26
+ cotwin_model .add_problem_facts_list (self ._build_problem_fact_computers (domain_model ), "computers" )
27
+
28
+ if self .use_incremental_score_calculator :
29
+ score_calculator = IncrementalScoreCalculatorCB ()
30
+
31
+ #to avoid joining, fast get common info only
32
+ score_calculator .utility_objects ["processes_info" ] = self ._build_processes_common_info (domain_model )
33
+ score_calculator .utility_objects ["computers_info" ] = self ._build_computers_common_info (domain_model )
34
+ score_calculator .utility_objects ["computers_costs" ] = self ._build_computers_costs (domain_model )
35
+ else :
36
+ score_calculator = PlainScoreCalculatorCB ()
37
+
38
+ cotwin_model .set_score_calculator ( score_calculator )
39
+
40
+ return cotwin_model
41
+
42
+ def _build_planning_processes (self , domain_model ):
43
+
44
+ cot_processes = []
45
+ n_computers = len (domain_model .computers )
46
+
47
+ if self .use_greed_init :
48
+ initial_computer_ids = self ._build_greed_initial_computer_ids (domain_model )
49
+ else :
50
+ initial_computer_ids = n_computers * [None ]
51
+
52
+
53
+ for i , process in enumerate (domain_model .processes ):
54
+ cot_process = CotProcess (
55
+ process .process_id ,
56
+ process .cpu_power_req ,
57
+ process .memory_size_req ,
58
+ process .network_bandwidth_req ,
59
+ GJInteger (0 , n_computers - 1 , False , initial_computer_ids [i ])
60
+ )
61
+ cot_processes .append (cot_process )
62
+
63
+ return cot_processes
64
+
65
+ def _build_greed_initial_computer_ids (self , domain_model ):
66
+
67
+ processes_info = self ._build_processes_common_info (domain_model )
68
+ computers_info = self ._build_computers_common_info (domain_model )
69
+ n_processes = len (processes_info )
70
+ m_computers = len (computers_info )
71
+
72
+ initial_computer_ids = self ._build_initial_ids (n_processes , m_computers , processes_info , computers_info )
73
+ initial_computer_ids = [int (initial_computer_ids [i ]) if initial_computer_ids [i ] >= 0 else None for i in range (len (initial_computer_ids ))]
74
+
75
+
76
+ return initial_computer_ids
77
+
78
+ @staticmethod
79
+ @jit (nopython = True , cache = True )
80
+ def _build_initial_ids (n_processes , m_computers , processes_info , computers_info ):
81
+ initial_computer_ids = np .zeros (n_processes , np .int64 ) - 1
82
+ current_consumed_resources = np .zeros (3 , np .int64 )
83
+ assigned_processes_index = [np .zeros (n_processes , np .int64 ) - 1 for i in range (m_computers )]
84
+ assigned_processes_counts = np .zeros (m_computers , np .int64 )
85
+ for process_id in range (n_processes ):
86
+
87
+ acceptable_computer_id = None
88
+ for computer_id in range (m_computers ):
89
+ current_consumed_resources = np .zeros (3 , np .int64 )
90
+ for i in range (assigned_processes_counts [computer_id ]):
91
+ current_consumed_resources += processes_info [assigned_processes_index [computer_id ][i ]]
92
+
93
+ current_consumed_resources += processes_info [process_id ]
94
+ resource_deltas = current_consumed_resources - computers_info [computer_id ]
95
+ resource_deltas = np .where (resource_deltas > 0 , resource_deltas , 0 )
96
+ resources_unacceptance = np .sum (resource_deltas )
97
+ if resources_unacceptance == 0 :
98
+ acceptable_computer_id = computer_id
99
+ assigned_processes_index [computer_id ][assigned_processes_counts [computer_id ]] = process_id
100
+ assigned_processes_counts [computer_id ] += 1
101
+ break
102
+
103
+ if acceptable_computer_id is not None :
104
+ initial_computer_ids [process_id ] = acceptable_computer_id
105
+
106
+ return initial_computer_ids
107
+
108
+
109
+ def _build_problem_fact_computers (self , domain_model ):
110
+
111
+ cot_computers = [CotComputer .build_from_domain_computer (computer ) for computer in domain_model .computers ]
112
+
113
+ return cot_computers
114
+
115
+ def _build_processes_common_info (self , domain_model ):
116
+
117
+ n_processes = len (domain_model .processes )
118
+ m_info_fields = 3
119
+ processes_common_info = np .zeros ((n_processes , m_info_fields ), dtype = np .int64 )
120
+ for i in range (n_processes ):
121
+ processes_common_info [i ][0 ] = domain_model .processes [i ].cpu_power_req
122
+ processes_common_info [i ][1 ] = domain_model .processes [i ].memory_size_req
123
+ processes_common_info [i ][2 ] = domain_model .processes [i ].network_bandwidth_req
124
+
125
+ return processes_common_info
126
+
127
+
128
+ def _build_computers_common_info (self , domain_model ):
129
+
130
+ n_computers = len (domain_model .computers )
131
+ m_info_fields = 3
132
+ computers_common_info = np .zeros ((n_computers , m_info_fields ), dtype = np .int64 )
133
+ for i in range (n_computers ):
134
+ computers_common_info [i ][0 ] = domain_model .computers [i ].cpu_power
135
+ computers_common_info [i ][1 ] = domain_model .computers [i ].memory_size
136
+ computers_common_info [i ][2 ] = domain_model .computers [i ].network_bandwidth
137
+
138
+ return computers_common_info
139
+
140
+ def _build_computers_costs (self , domain_model ):
141
+
142
+ # to avoid unnecessary slicing while constraints computation
143
+ n_computers = len (domain_model .computers )
144
+ computers_costs = np .zeros ((n_computers ), dtype = np .int64 )
145
+ for i in range (n_computers ):
146
+ computers_costs [i ] = domain_model .computers [i ].cost
147
+
148
+ return computers_costs
0 commit comments