def free_slots(self, begin_time=0, end_time=None): ''' :returns: a DataFrame (compatible with a JobSet) that contains all the not overlapping square free slots of this JobSet maximzing the time. It can be transform to a JobSet to be plot as gantt chart. ''' # slots_time contains tuple of # (slot_begin_time,free_resources_intervals) free_interval_serie = self.free_intervals(begin_time, end_time) slots_time = [(free_interval_serie.time[0], [self.res_bounds])] new_slots_time = slots_time columns = ['jobID', 'allocated_processors', 'starting_time', 'finish_time', 'execution_time', 'submission_time'] free_slots_df = pd.DataFrame(columns=columns) prev_free_itvs = [self.res_bounds] slots = 0 for i, curr_row in free_interval_serie.iterrows(): if i == 0: continue new_slots_time = [] curr_time = curr_row.time taken_resources = difference(prev_free_itvs, curr_row.free_itvs) freed_resources = difference(curr_row.free_itvs, prev_free_itvs) if i == len(free_interval_serie) - 1: taken_resources = [self.res_bounds] if taken_resources: # slot ends: store it and update free slot for begin_time, itvs in slots_time: to_update = intersection(itvs, taken_resources) if to_update != []: # store new slots slots = slots + 1 new_slot = [str(slots), to_update, begin_time, curr_time, curr_time - begin_time, begin_time] free_slots_df.loc[slots] = new_slot # remove free slots free_res = difference(itvs, to_update) if free_res != []: new_slots_time.append((begin_time, free_res)) else: new_slots_time.append((begin_time, itvs)) if freed_resources: # slots begin: udpate free slot if not new_slots_time: new_slots_time = slots_time new_slots_time.append((curr_time, freed_resources)) # update previous prev_free_itvs = curr_row.free_itvs # clean slots_free slots_time = new_slots_time return free_slots_df
def free_intervals(self, begin_time=0, end_time=None): ''' :returns: a dataframe with the free resources over time. Each line corespounding to an event in the jobset. ''' df = self.df # Create a list of start and stop event associated to the proc # allocation: # Free -> Used : grab = 1 # Used -> Free : grab = 0 event_columns = ['time', 'free_itvs', 'grab'] start_event_df = pd.concat([df['starting_time'], df['allocated_processors'], pd.Series(np.ones(len(df), dtype=bool))], axis=1) start_event_df.columns = event_columns # Stop event have zero in grab stop_event_df = pd.concat([df['finish_time'], df['allocated_processors'], pd.Series(np.zeros(len(df), dtype=bool))], axis=1) stop_event_df.columns = event_columns # merge events and sort them event_df = start_event_df.append( stop_event_df, ignore_index=True).sort_values( by=['time', 'grab']).reset_index(drop=True) # cut events if necessary # reindex event_df event_df = event_df.sort_values(by='time').set_index(['time'], drop=False) # find closest index begin = event_df.index.searchsorted(begin_time) if end_time is not None: end = event_df.index.searchsorted(end_time) else: end = len(event_df.index) - 1 event_df = event_df.iloc[begin:end].reset_index(drop=True) # All resources are free at the beginning event_columns = ['time', 'free_itvs'] first_row = [begin_time, [self.res_bounds]] free_interval_serie = pd.DataFrame(columns=event_columns) free_interval_serie.loc[0] = first_row for index, row in event_df.iterrows(): current_itv = free_interval_serie.ix[index]['free_itvs'] if row.grab: new_itv = difference(current_itv, row.free_itvs) else: new_itv = union(current_itv, row.free_itvs) new_row = [row.time, new_itv] free_interval_serie.loc[index + 1] = new_row if end_time is not None: last_row = [end_time, []] free_interval_serie.loc[len(free_interval_serie)] = last_row return free_interval_serie