列表类扩展,以便每个实例都是新的

时间:2015-08-16 17:20:51

标签: python-3.x

我创建了类EventList作为python中本机list类的扩展。我遇到的问题是,当我创建类的实例时,这些实例不会创建新对象。

如果您运行下面的代码(已完成),您将发现类实例elm1的内容被elm2覆盖,并被elm3覆盖。 (见代码底部)

我需要在课程EventList中更改哪些内容才能正确扩展课程list,以便EventList的每个实例都是新的且独立的?

from numpy.random import exponential, normal
from enum import Enum
from matplotlib import pyplot as plt


class States(int):
    Failed = 0
    Working = 1
    Maintenance = 2


class ElementTypes(Enum):
    Generic = 100
    Bus = 0
    Gen = 1
    Branch = 2
    Switch = 3
    Load = 4
    Grid = 5


class EventList(list):

    def add(self, event):
        self.append(event)

    def size(self):
        return len(self)

    def remove_redundant(self):
        # Remove the redundant events
        n = self.size()
        i = n-2
        while i > 0:
            if self[i][1] == self[i-1][1]:
                del self[i]
            i -= 1

    def merge_events(self, event_list, remove_redundant=True):
        """
        Add another list of events to this list.
        It can also remove the redundant events
        """
        self += event_list
        # print(self)
        self.sort()
        # print(self)
        # set the final event state as the previous event state
        n = self.size()
        self[n-1] = (self[n-1][0], self[n-2][1])
        # print(self)
        # remove redundant events
        if remove_redundant:
            self.remove_redundant()

    def merge_series_component_events(self, events_list):
        """
        Composes the series events list of a number of components

        Args:
            events_list: list of EventList objects corresponding to a number of components in series
        """
        c_num = len(events_list)  # number of components

        for k in range(c_num):
            for evt in events_list[k]:
                if evt[1] == States.Failed:
                    self.add(evt)  # a down-event is always added
                else:
                    all_working = True
                    i = 0
                    while i < c_num and all_working:
                        t = evt[0]
                        if not events_list[i].state_at(t + 1e-6):
                            all_working = False
                        i += 1

                    # up-events are added only if all the components are up for the examined up-event time
                    if all_working:
                        self.add(evt)

        self.sort()
        self.remove_redundant()

    def state_at(self, t):
        """
        Returns the state at any given time
        """
        n = self.size()
        s0 = self[0]
        sn = self[n-1]

        if t <= s0[0]:
            return s0[1]

        elif t >= sn[0]:
            return sn[1]

        else:  # look for it
            for i in range(1, n):
                if t >= self[i-1][0] and t <= self[i][0]:
                    # t is found
                    return self[i-1][1]

    def plot(self, ylab=''):
        n = len(self)
        for i in range(n-1):
            #print(str(self[i][0]) + ", " + str(self[i+1][0]) + '->' + str(str(self[i][1])))
            plt.plot((self[i][0], self[i+1][0]), (self[i][1], self[i][1]), 'k-')
            plt.plot((self[i][0], self[i][0]), (0, 1), 'k-')
            plt.plot((self[i+1][0], self[i+1][0]), (0, 1), 'k-')
            if self[i][1] == States.Failed:
                color = 'r'
            else:
                color = 'g'
            plt.axvspan(ymin=0, ymax=1, xmin=self[i][0], xmax=self[i+1][0], facecolor=color, alpha=0.5)
        plt.ylabel(ylab)
        plt.xlim((0, self[n-1][0]+10))

class Element(object):
    """
    This class represents the system element.
    In a graph it is given by a node element, regardless of the element's nature
    """

    # element name
    name = ''

    type = None

    # flag denoting if the element is active or not. If not active it counts as if it was failed
    is_on_line = True

    # Current state of the element given by the possible states enumerated by the class States
    current_state = States.Working

    # Weight of the element, in an electrical grid, this value can be the element impedance
    weight = 0

    # mean time to failure
    MTTF = 0

    # mean time to repair
    MTTR = 0

    # deviation from time to repair, relevant when using normal laws for the repair time
    DEVTR = 1

    use_normal_recovery_law = False

    # list of tuples representing an event
    # each tuple if of the form: (time, state)
    events = EventList()

    # Time based maintenance event list
    time_based_maintenance_events = EventList()

    def __init__(self, name, element_type, MTTF, MTTR, DEVTR=None, state=States.Working, weight=0, online=True):
        """
        Class constructor

        Args:
            name = name of the element

            element_type = type of element given by the class ElementTypes

            MTTF = mean time to failure

            MTTR = mean time to repair

            DEVTR = deviation from time to repair

            state = initial state of the element, given by the possible states enumerated by the class States

            weight = possible weight of the element

            online = flag denoting if the element is active or not.
        """

        self.name = name
        self.type = element_type
        self.MTTF = MTTF
        self.MTTR = MTTR
        self.DEVTR = DEVTR
        self.current_state = state
        self.weight = weight
        self.is_on_line = online

        if DEVTR is not None:
            self.use_normal_recovery_law = True

    def generate_states(self, simulation_time):
        """
        Generate the system events randomly.

        Once failed, a component is accounted to be replaced (as good as new)

        Args:

            simulation_time: simulation time limit (typically the expected life of the system)
        """
        events = EventList()

        self.events.clear()
        # append the initial state event
        self.events.append((0, self.current_state * self.is_on_line))
        # append the last state event
        self.events.append((simulation_time, -1 * self.is_on_line))

        mttf = self.MTTF
        mttr = self.MTTR

        # generate failure-repair events
        t = 0
        last_state = self.current_state
        while t < simulation_time:  # simulate failures and recoveries until the time is reached
            if (not last_state) == States.Failed:  # if the state to set is failed, get the time of the failure
                t_evt = t + exponential(mttf)
                last_state = States.Failed
            else:  # the element is failed, calculate its recovery time
                if self.use_normal_recovery_law:
                    t_evt = t + normal(mttr, self.DEVTR)
                else:
                    t_evt = t + exponential(mttr)
                last_state = States.Working

            if t_evt <= simulation_time:
                events.append((t_evt, last_state * self.is_on_line))
            t = t_evt


        self.events.merge_events(events + self.time_based_maintenance_events)


if __name__ == '__main__':
    simulation_time = 172000
    name = 'element'
    type = ElementTypes.Generic
    MTTF = 36402.64
    MTTR = 6500.30

    plt.subplot(4, 1, 1)
    elm1 = Element(name, type, MTTF, MTTR)
    elm1.generate_states(simulation_time)
    print(elm1.events)
    elm1.events.plot()

    plt.subplot(4, 1, 2)
    elm2 = Element(name, type, MTTF, MTTR)
    elm2.generate_states(simulation_time)
    print(elm2.events)
    elm2.events.plot()

    plt.subplot(4, 1, 3)
    elm3 = Element(name, type, MTTF, MTTR)
    elm3.generate_states(simulation_time)
    print(elm3.events)
    elm3.events.plot()

    print('after')
    print(elm1.events)
    print(elm2.events)
    print(elm3.events)

    plt._show()
    input()

0 个答案:

没有答案