def get_fixed_states(self, resource=None, filter_horizon=False): """ This function returns the fixed states in the beginning of the planning period They can be maintenances or mission assignments They include previous states too :param resource: if given filters only for that resource :return: """ previous_states = self.get_prev_states(resource) first_period = self.get_param('start') period_0 = self.get_prev_period(first_period) min_assign = self.get_min_assign() # we get the states into a tuple list, # we turn them into a start-finish tuple # we filter it so we only take the start-finish periods that end before the horizon assignments = \ previous_states.to_start_finish(self.compare_tups).\ vfilter(lambda x: x[3] == period_0) fixed_assignments_q = \ [(a[0], a[2], min_assign.get(a[2], 0) - len(self.get_periods_range(a[1], a[3]))) for a in assignments if len(self.get_periods_range(a[1], a[3])) < min_assign.get(a[2], 0)] fixed_future = tl.TupList([(f_assign[0], f_assign[1], self.shift_period(first_period, t)) for f_assign in fixed_assignments_q for t in range(f_assign[2])]) previous_n = tl.TupList((r, s, t) for r, t, s in previous_states) if not filter_horizon: fixed_future.extend(previous_n) return fixed_future
def get_fixed_maintenances(self, dict_key=None, *args, **kwargs): fixed_states = self.get_fixed_states(*args, **kwargs) fixed_maints = tl.TupList([(a, t) for (a, s, t) in fixed_states if s == 'M']) if dict_key is None: return fixed_maints if dict_key == 'resource': return fixed_maints.to_dict(result_col=1) if dict_key == 'period': return fixed_maints.to_dict(result_col=0)
def get_maintenance_periods(self, resource=None, state_list=None): """ :param str resource: optional resource to filter :param set state_list: maintenances to filter :return: (resource, maint_start, maint_stop) :rtype: tl.TupList """ if state_list is None: state_list = set('M') all_states = self.get_states(resource) maintenances = tl.TupList([(k[0], k[1]) for k in all_states if k[2] in state_list]) ct = self.instance.compare_tups return maintenances.to_start_finish(ct)
def get_states(self, resource=None): """ :param str resource: optional filter :return: (resource, period, state) list :rtype: tl.TupList """ # in the input examples of the instance # (although for now this is the case) maints_codes = self.instance.get_maintenances() previous_states = self.instance.get_prev_states(resource).\ vfilter(lambda x: x[2] in maints_codes) states = self.solution.get_state_tuplist(resource) previous_states.extend(states) return tl.TupList(previous_states).unique2()
def get_non_maintenance_periods(self, resource=None, state_list=None): """ :return: a tuplist with the following structure: resource: [(resource, start_period1, end_period1), (resource, start_period2, end_period2), ..., (resource, start_periodN, end_periodN)] two consecutive periods being separated by a maintenance operation. It's built using the information of the maintenance operations. :param resource: if not None, we filter to only provide this resource's info :return: a tuplist with the following structure: resource: [(resource, start_period1, end_period1), (resource, start_period2, end_period2), ..., (resource, start_periodN, end_periodN)] two consecutive periods being separated by a maintenance operation. It's built using the information of the maintenance operations. """ # TODO: change to: # cycles_dict = self.get_all_maintenance_cycles(resource) # return cycles_dict.to_tuplist() first, last = self.instance.get_param( 'start'), self.instance.get_param('end') maintenances = \ self.get_maintenance_periods(resource, state_list=state_list).\ to_dict(result_col=[1, 2]) if resource is None: resources = self.instance.get_resources() else: resources = [resource] # we initialize nomaint periods for resources that do not have a single maintenance: nonmaintenances = [(r, first, last) for r in resources if r not in maintenances] # now, we iterate over all maintenances to add the before and the after for res in maintenances: maints = sorted(maintenances[res], key=lambda x: x[0]) first_maint_start = maints[0][0] last_maint_end = maints[-1][1] if first_maint_start > first: first_maint_start_prev = self.instance.get_prev_period( first_maint_start) nonmaintenances.append((res, first, first_maint_start_prev)) for maint1, maint2 in zip(maints, maints[1:]): start = self.instance.get_next_period(maint1[1]) end = self.instance.get_prev_period(maint2[0]) nonmaintenances.append((res, start, end)) if last_maint_end != last: start = self.instance.get_next_period(last_maint_end) nonmaintenances.append((res, start, last)) return tl.TupList(nonmaintenances)
def get_all_maintenance_cycles(self, resource=None): """ gets all periods in between maintenances for all resources :return: dictionary indexed by resource of a list of tuples. {resource: [(start1, stop1), (start2, stop2)]} :rtype: :py:class:`pytups.SuperDict` """ starts_stops = self.get_maintenance_periods(resource=resource) if resource is None: resources = self.instance.get_resources() else: resources = [resource] return \ tl.TupList(starts_stops).\ to_dict(result_col=[1, 2]).\ vapply(sorted). \ fill_with_default(keys=resources, default=[]). \ vapply(self.get_maintenance_cycles)
def get_instances_paths(self): num_slashes = 2 keys_positions = [1, 2] if self.no_scenario: num_slashes = 1 keys_positions = 1 zipobj = zipfile.ZipFile(self.path) all_files = tl.TupList(di.dirs_in_zip(zipobj)) scenario_instances = all_files.vfilter( lambda f: f.count("/") == num_slashes) keys = (scenario_instances.vapply( str.split, "/").vapply(tuple).take(keys_positions)) result_dict = sd.SuperDict(zip(keys, scenario_instances)) if self.scenarios: scenarios = set(self.scenarios) return result_dict.kfilter(lambda k: k[0] in scenarios) else: return result_dict
def check_min_max_assignment(self, **params): """ :return: periods were the min assignment (including maintenance) in format: (resource, start, end): error. if error negative: bigger than max. Otherwise: less than min is not respected """ # TODO: do it with self.solution.get_schedule() tasks = self.solution.get_tasks().to_tuplist() maints = self.solution.get_state_tuplist() previous = sd.SuperDict.from_dict(self.instance.get_resources("states")).\ to_dictup().to_tuplist() min_assign = self.instance.get_min_assign() max_assign = self.instance.get_max_assign() num_periods = self.instance.get_param('num_period') ct = self.instance.compare_tups all_states = maints + tasks + previous all_states_periods = \ tl.TupList(all_states).\ sorted(key=lambda v: (v[0], v[2], v[1])).\ to_start_finish(ct, sort=False) first_period = self.instance.get_param('start') last_period = self.instance.get_param('end') incorrect = {} for (resource, start, state, finish) in all_states_periods: # periods that finish before the horizon # or at the end are not checked if finish < first_period or finish == last_period: continue size_period = len(self.instance.get_periods_range(start, finish)) if size_period < min_assign.get(state, 1): incorrect[resource, start, finish, state] = min_assign[state] - size_period elif size_period > max_assign.get(state, num_periods): incorrect[resource, start, finish, state] = max_assign[state] - size_period return sd.SuperDict(incorrect)
def check_maints_size(self, **params): maints = self.instance.get_maintenances() duration = maints.get_property('duration_periods') inst = self.instance start, end = inst.get_param('start'), inst.get_param('end') m_s_tab_r = pd.DataFrame.from_records( self.get_state_periods().to_list(), columns=['resource', 'start', 'maint', 'end']) def dist_periods(series, series2): return pd.Series( self.instance.get_dist_periods(p, p2) for p, p2 in zip(series, series2)) # TODO: this check was too strict but the model complied with it, apparently... inside = (m_s_tab_r.start > start) & (m_s_tab_r.end < end) m_s_tab = m_s_tab_r[inside].reset_index() m_s_tab['dist'] = dist_periods(m_s_tab.start, m_s_tab.end) + 1 m_s_tab['duration'] = m_s_tab.maint.map(duration) m_s_tab['value'] = m_s_tab.dist - m_s_tab.duration error = m_s_tab[m_s_tab.value != 0] result = error[['resource', 'start', 'value']].to_records(index=False) return tl.TupList(result).to_dict(result_col=2, is_list=False)
def get_periods_range(self, start, end): pos_period = self.get_period_positions() period_pos = self.get_periods_by_position() return tl.TupList(period_pos[t] for t in range(pos_period[start], pos_period[end] + 1))
def get_fixed_tasks(self, *args, **kwargs): tasks = self.get_tasks() states = self.get_fixed_states(*args, **kwargs) return tl.TupList([(a, s, t) for (a, s, t) in states if s in tasks])
def get_state_tuplist(self, resource=None): states = self.get_state(resource) return tl.TupList(states.keys())
def get_in_task(self): tasks = [(t, r) for (r, t) in self.get_tasks()] return tl.TupList(tasks).\ to_dict(1, is_list=True).\ to_lendict().\ fill_with_default(self.get_periods())
def get_state_tasks(self): statesMissions = self.get_state_tuplist() + self.get_tasks( ).to_tuplist() return tl.TupList(statesMissions)