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