def calculate_free_blocks(self) -> List[IntInterval]: free_blocks: List[IntInterval] = [] lower: int = 0 for block in self.allocation_blocks_m: if block.interval.lower != 0 and lower < block.interval.lower: free_blocks.append( IntInterval.closed(lower, block.interval.lower - 1)) lower = block.interval.upper + 1 if lower < self.time_slot_num: free_blocks.append( IntInterval.closed(lower, self.time_slot_num - 1)) return free_blocks
def compareAirTemp(airTemp, plantModel): """ 比较空气温度 :param airTemp: 实时数据 :param plantModel: 标准生长模型 :return: SensorResult """ if not plantModel.airTemprature_low or not plantModel.airTemprature_high: return SensorResult(True, airTemp, standardData='0-0', advice='标准生长模型为空') ret = airTemp in IntInterval.closed(plantModel.airTemprature_low, plantModel.airTemprature_high) if ret: return SensorResult( True, airTemp, str(plantModel.airTemprature_low) + '-' + str(plantModel.airTemprature_high)) else: # todo 给出指导意见 if airTemp - plantModel.airTemprature_low < 0: advice = "当前温度为{},标准温度为{},建议至少{}温度{}".format( airTemp, plantModel.airTemprature_low, '上调', plantModel.airTemprature_low - airTemp) else: advice = "当前温度为{},标准温度为{},建议至少{}温度{}".format( airTemp, plantModel.airTemprature_high, '下调', airTemp - plantModel.airTemprature_high) return SensorResult(False, airTemp, str(plantModel.airTemprature_low) + '-' + str(plantModel.airTemprature_high), advice=advice)
def reset(self): self.flow_times_mapper = { } # clear flow-time-slots mapper when hyper period changes self.allocation_blocks = [] # clear time slot allocation self.allocation_blocks_m = [] # clear merged time slot allocation self.allocation_blocks_c = [] self.allocation_blocks_m_c = [] self.load = 0 self.load_c = 0 self.time_slot_used = 0 self.time_slot_used_c = 0 self.flow_num = 0 self.flow_num_c = 0 self.flow_segment_num = 0 if self.bandwidth != 0 and self.min_flow_size != 0 and self.__hyper_period: self.time_slot_len = ceil(self.min_flow_size / self.bandwidth) # self.time_slot_num = floor(self.__hyper_period / self.time_slot_len) self.time_slot_len = ceil( self.min_flow_size / config.GRAPH_CONFIG['max-bandwidth']) # TODO fix bug here self.time_slot_num = floor(self.__hyper_period / self.time_slot_len) self.free_intervals = [ IntInterval.closed(0, self.time_slot_num - 1) ] else: self.time_slot_len = 0 self.time_slot_num = 0 self.free_intervals = [] self.to_string()
def compareAirHum(airHum, plantModel): if not plantModel.airHumidity_low or not plantModel.airHumidity_high: return SensorResult(True, airHum, '0', '0', '标准生长模型为空') ret = airHum in IntInterval.closed(plantModel.airHumidity_low, plantModel.airHumidity_high) if ret: return SensorResult( True, airHum, str(plantModel.airHumidity_low) + '-' + str(plantModel.airHumidity_high)) else: # todo 给出指导意见 if airHum - plantModel.airHumidity_low < 0: advice = "当前光照强度为{},标准光照强度为{},建议至少{}光照强度{}".format( airHum, plantModel.airHumidity_low, '上调', plantModel.airHumidity_low - airHum) else: advice = "当前光照强度为{},标准光照强度为{},建议至少{}光照强度{}".format( airHum, plantModel.airHumidity_high, '下调', airHum - plantModel.airHumidity_high) return SensorResult(False, airHum, str(plantModel.airHumidity_low) + '-' + str(plantModel.airHumidity_high), advice=advice)
def compareLight(light, plantModel): if not plantModel.lightIntensity_low or not plantModel.lightIntensity_high: return SensorResult(True, light, '0', '0', '标准生长模型为空') ret = light in IntInterval.closed(plantModel.lightIntensity_low, plantModel.lightIntensity_high) if ret: return SensorResult( True, light, str(plantModel.lightIntensity_low) + '-' + str(plantModel.lightIntensity_high)) else: # todo 给出指导意见 if light - plantModel.lightIntensity_low < 0: advice = "当前光照强度为{},标准光照强度为{},建议至少{}光照强度{}".format( light, plantModel.lightIntensity_low, '上调', plantModel.lightIntensity_low - light) else: advice = "当前光照强度为{},标准光照强度为{},建议至少{}光照强度{}".format( light, plantModel.lightIntensity_high, '下调', light - plantModel.lightIntensity_high) return SensorResult(False, light, str(plantModel.lightIntensity_low) + '-' + str(plantModel.lightIntensity_high), advice=advice)
def compareSoilHum(soilHum, plantModel): if not plantModel.soilHumidity_low or not plantModel.soilHumidity_high: return SensorResult(True, soilHum, '0', '0', '标准生长模型为空') ret = soilHum in IntInterval.closed(plantModel.soilHumidity_low, plantModel.soilHumidity_high) if ret: return SensorResult( True, soilHum, str(plantModel.soilHumidity_low) + '-' + str(plantModel.soilHumidity_high)) else: # todo 给出指导意见 if soilHum - plantModel.soilHumidity_low < 0: advice = "当前土壤湿度为{},标准土壤湿度为{},建议至少{}土壤湿度{}".format( soilHum, plantModel.soilHumidity_low, '上调', plantModel.soilHumidity_low - soilHum) else: advice = "当前土壤湿度为{},标准土壤湿度为{},建议至少{}土壤湿度{}".format( soilHum, plantModel.soilHumidity_high, '下调', soilHum - plantModel.soilHumidity_high) return SensorResult(False, soilHum, str(plantModel.soilHumidity_low) + '-' + str(plantModel.soilHumidity_high), advice=advice)
def try_allocate(self, time_offset: int, flow_id: int, allocation_num: int, phase_num: int, bp: int, overlaped=False) -> bool: ''' brute force method to check whether flow can be allocated or not :param time_offset: :param flow_id: :param allocation_num: :param phase_num: :param bp: :return: ''' if self.time_slot_num == 0: logger.error('time slots on edge [' + str(self.edge_id) + '] does not initialize') return False if bp < allocation_num: logger.error('required time slots exceed base period') return False for phase in range(phase_num): # _lower: int = floor(time_offset % self.hyper_period / self.time_slot_len) _lower: int = floor(time_offset % (self.time_slot_num * self.time_slot_len) / self.time_slot_len) _upper: int = _lower + allocation_num - 1 _intervals: List[IntInterval] = [] if _lower < self.time_slot_num: if _upper < self.time_slot_num: _interval: IntInterval = IntInterval.closed(_lower, _upper) _intervals: List[IntInterval] = [_interval] else: _lower_0 = _lower _upper_0 = self.time_slot_num - 1 _interval_0 = IntInterval.closed(_lower_0, _upper_0) _lower_1 = 0 _upper_1 = _upper % self.time_slot_num _intervals = [] _interval_1 = IntInterval.closed(_lower_1, _upper_1) _intervals = [_interval_0, _interval_1] else: logger.error('lower bound exceed number of time slots') return False if overlaped is True: for __interval in _intervals: for block in self.allocation_blocks: fid = block.flow_id if __interval.lower in block.interval and __interval.upper in block.interval: if not self._is_same_flow( fid, flow_id, time_offset, block.send_time_offset, allocation_num): return False elif __interval.lower in block.interval and __interval.upper > block.interval.upper: if not self._is_same_flow( fid, flow_id, time_offset, block.send_time_offset, allocation_num): return False elif __interval.upper in block.interval and __interval.lower < block.interval.lower: if not self._is_same_flow( fid, flow_id, time_offset, block.send_time_offset, allocation_num): return False elif block.interval.lower in __interval and block.interval.upper in __interval: if not self._is_same_flow( fid, flow_id, time_offset, block.send_time_offset, allocation_num): return False else: for __interval in _intervals: for block in self.allocation_blocks: if __interval.lower in block.interval and __interval.upper in block.interval: return False elif __interval.lower in block.interval and __interval.upper > block.interval.upper: return False elif __interval.upper in block.interval and __interval.lower < block.interval.lower: return False elif block.interval.lower in __interval and block.interval.upper in __interval: return False time_offset += bp return True
def allocate(self, flow: Flow, arrival_time_offset, send_time_offset: int, phase_num: int, allocation_num: int): for _phase in range(phase_num): _block_num: int = len(self.allocation_blocks) _block_m_num: int = len(self.allocation_blocks_m) _lower: int = floor(send_time_offset % self.hyper_period / self.time_slot_len) # _lower: int = floor(send_time_offset % (self.time_slot_num * self.time_slot_len) / self.time_slot_len) _upper: int = _lower + allocation_num - 1 _blocks: List[AllocationBlock] = [] # create time slots allocation blocks if _lower < self.time_slot_num: if _upper < self.time_slot_num: _interval: IntInterval = IntInterval.closed(_lower, _upper) _block = AllocationBlock(flow.flow_id, _interval, at_offset=arrival_time_offset, st_offset=send_time_offset, phase=_phase) _blocks = [_block] else: _lower_0 = _lower _upper_0 = self.time_slot_num - 1 _interval_0 = IntInterval.closed(_lower_0, _upper_0) _block_0 = AllocationBlock(flow.flow_id, _interval_0, at_offset=arrival_time_offset, st_offset=send_time_offset, phase=_phase) _lower_1 = 0 _upper_1 = _upper % self.time_slot_num _interval_1 = IntInterval.closed(_lower_1, _upper_1) _block_1 = AllocationBlock(flow.flow_id, _interval_1, at_offset=arrival_time_offset, st_offset=send_time_offset, phase=_phase) _blocks = [_block_0, _block_1] else: logger.error('f**k damn!') # insert directly without merge operation for __block in _blocks: if len(self.allocation_blocks) == 0: self.allocation_blocks.append(__block) else: for _i, block in enumerate(self.allocation_blocks): if __block.interval.lower <= block.interval.lower: self.allocation_blocks.insert(_i, __block) break else: if _i >= _block_num - 1: # append to last self.allocation_blocks.insert(_i + 1, __block) break if _phase == 0: _next_arrival_time_offset = \ send_time_offset + flow.period + self.propagation_delay + self.process_delay # add blocks to flow-time-slots mapper if flow.flow_id in self.flow_times_mapper: for __block in _blocks: self.flow_times_mapper[flow.flow_id].append(__block) else: __blocks: List[AllocationBlock] = _blocks.copy() self.flow_times_mapper[flow.flow_id] = __blocks # # insert with merging operation # for __block in _blocks: # if len(self.allocation_blocks_m) == 0: # self.allocation_blocks_m.append(__block) # else: # for _i, block_m in enumerate(self.allocation_blocks_m): # if __block.interval.lower <= block_m.interval.lower: # self.allocation_blocks_m.insert(_i, __block) # if __block.interval.upper in block_m.interval and __block.flow_id == block_m.flow_id: # __block.interval.upper = block_m.interval.upper # del self.allocation_blocks_m[_i + 1] # if _i != 0: # _pre_block_m: AllocationBlock = self.allocation_blocks_m[_i - 1] # if __block.interval.lower in _pre_block_m.interval and __block.flow_id == block_m.flow_id: # __block.interval.lower = _pre_block_m.interval.lower # del self.allocation_blocks_m[_i - 1] # break # else: # if _i >= _block_m_num - 1: # self.allocation_blocks_m.insert(_i + 1, __block) # _pre_block_m: AllocationBlock = self.allocation_blocks_m[_i] # if __block.interval.lower in _pre_block_m.interval and __block.flow_id == block_m.flow_id: # __block.interval.lower = _pre_block_m.interval.lower # del self.allocation_blocks_m[_i] # break # if flow not exit, then the number of flow add 1 if flow.flow_id not in self.flow_times_mapper: self.flow_num += 1 # add to next phase send_time_offset += flow.period # calculate merged allocation blocks self.allocation_blocks_m = self.merge_allocation_blocks() # calculate free allocation blocks self.free_intervals = self.calculate_free_blocks() # calculate time slot used _sum: int = 0 for _block_m in self.allocation_blocks_m: _sum += _block_m.interval.upper - _block_m.interval.lower + 1 self.time_slot_used = _sum # add guard band total_guard_band: int = 0 block_num = len(self.allocation_blocks_m) for i in range(block_num): if i + 1 < block_num and self.allocation_blocks_m[i].interval.upper + 1 != \ self.allocation_blocks_m[i + 1].interval.lower: total_guard_band += 1 self.time_slot_used += total_guard_band # calculate payload self.load = self.time_slot_used / self.time_slot_num
def test_closed(self): interval = IntInterval.closed(10, 11, step=2) assert interval.lower == 10 assert interval.upper == 12 assert interval.is_closed assert interval.step == 2
from intervals import IntInterval BLOCK_RANGE_TABLE_NAME = { IntInterval.closed(1, 5): 'talbe1', IntInterval.closed(5, 10): 'table2' } BLOCK_RANGES = BLOCK_RANGE_TABLE_NAME.keys() for interval in BLOCK_RANGES: if 2 in interval: print(interval) print(interval.lower, interval.upper) print(BLOCK_RANGE_TABLE_NAME[interval])