예제 #1
0
    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
예제 #2
0
 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)
예제 #3
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)
예제 #4
0
 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()
예제 #5
0
    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)
예제 #6
0
 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)
예제 #7
0
 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
예제 #8
0
    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)
예제 #9
0
    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)
예제 #10
0
 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))
예제 #11
0
 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])
예제 #12
0
 def get_state_tuplist(self, resource=None):
     states = self.get_state(resource)
     return tl.TupList(states.keys())
예제 #13
0
 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())
예제 #14
0
 def get_state_tasks(self):
     statesMissions = self.get_state_tuplist() + self.get_tasks(
     ).to_tuplist()
     return tl.TupList(statesMissions)