Exemplo n.º 1
0
 def __init__(self):
     self.Q = EventQueue()
     self.T = StatusStructure()   
     self.T1 = StatusStructure()  
     self.T2 = StatusStructure()  
     self.intersections = []
     self.vertices = []
     self.halfedges = []
     self.faces = []
     self.face1 = []
     self.face2 = []
     self.cycles = [CycleNode(cycle=None, inf_outer=True)]
Exemplo n.º 2
0
class FindIntersections():
    def __init__(self):
        self.Q = EventQueue()
        self.T = StatusStructure()
        self.intersections = []

    def find_intersections(self, lines):
        for line in lines:
            self.Q.insert_line(line)
        while not self.Q.is_empty():
            next_event = self.Q.pop_next_event()
            self.handle_event_point(next_event)

    def handle_event_point(self, p):
        U_p = p.lines
        L_p, C_p, L_C = self.T.find_segments_contain(p.point)
        U_C = U_p + C_p
        L_U_C = L_C + U_p
        if len(L_U_C) > 1:
            self.intersections.append(p.point)
        for line in L_C:
            self.T.delete(p.point, line)
        self.T.insert(p.point, U_C)
        self.T._print_name()
        if len(U_C) == 0:
            s_l = self.T.find_left_neighbor(p.point)
            s_r = self.T.find_right_neighbor(p.point)
            self.find_new_event(s_l, s_r, p.point)
        else:
            s_lm = self.T.find_leftmost(p.point)
            s_l = self.T.find_left_neighbor(p.point)
            self.find_new_event(s_lm, s_l, p.point)
            s_rm = self.T.find_rightmost(p.point)
            s_r = self.T.find_right_neighbor(p.point)
            self.find_new_event(s_rm, s_r, p.point)

    def find_new_event(self, s_l, s_r, p):
        if s_l is None or s_r is None:
            return
        i = s_l.intersect(s_r)
        if i is None:
            return
        x_i, y_i = i
        x_p, y_p = p
        if y_i < y_p or (y_i == y_p and x_i > x_p):
            self.Q.insert(i)
Exemplo n.º 3
0
class MapOverlay:
    def __init__(self):
        self.Q = EventQueue()
        self.T = StatusStructure()   
        self.T1 = StatusStructure()  
        self.T2 = StatusStructure()  
        self.intersections = []
        self.vertices = []
        self.halfedges = []
        self.faces = []
        self.face1 = []
        self.face2 = []
        self.cycles = [CycleNode(cycle=None, inf_outer=True)]
        
    def find_intersections(self, halfedges):
        for he in halfedges:
            self.Q.insert_he(he)
        while not self.Q.is_empty():
            next_event = self.Q.pop_next_event()
            self.handle_event_point(next_event)
            
    def handle_event_point(self, p):
        def assign_pointer(hedges):
            root = hedges[0]
            sorted_hedges = []
            dcel1_hedges = [hedge for hedge in hedges if hedge.belong_to == root.belong_to]
            dcel2_hedges = [hedge for hedge in hedges if hedge.belong_to != root.belong_to]
            i1 = i2 = 0
            i = 1
            while i < len(dcel2_hedges):
                if root.clockwise_angle(dcel2_hedges[i]) < root.clockwise_angle(dcel2_hedges[i-1]):
                    break
                i += 1
            dcel2_hedges = dcel2_hedges[i:] + dcel2_hedges[:i]
            while (i1 + i2) < len(hedges):
                if i1 == len(dcel1_hedges):
                    sorted_hedges.extend(dcel2_hedges[i2:])
                    break
                elif i2 == len(dcel2_hedges):
                    sorted_hedges.extend(dcel1_hedges[i1:])
                    break
                if root.clockwise_angle(dcel1_hedges[i1]) < root.clockwise_angle(dcel2_hedges[i2]):
                    sorted_hedges.append(dcel1_hedges[i1])
                    i1 += 1
                else:
                    sorted_hedges.append(dcel2_hedges[i2])
                    i2 += 1            
            for i in range(0, len(sorted_hedges)-1):
                c_he = sorted_hedges[i]
                n_he = sorted_hedges[i+1]
                c_he.twin.set_next(n_he)
            c_he = sorted_hedges[-1]
            n_he = sorted_hedges[0]
            c_he.twin.set_next(n_he)

        U_p = p.segments_u
        L_p, C_p, L_C = self.T.find_segments_contain(p.point)
        U_C = U_p + C_p
        L_U_C = L_C + U_p
        if len(L_U_C) > 1:
            self.intersections.append(p.point)
        for segment in L_C:
            self.T.delete(p.point, segment)
            if segment.belong_to == 'dcel1' and p.point.belong_to == 'dcel1':
                self.T1.delete(p.point, segment)
            if segment.belong_to == 'dcel2' and p.point.belong_to == 'dcel2':
                self.T2.delete(p.point, segment)
        self.T.insert(p.point, U_C)
        if p.point.belong_to == 'dcel1':
            self.T1.insert(p.point, [s for s in U_C if s.belong_to == 'dcel1'])
        if p.point.belong_to == 'dcel2':
            self.T2.insert(p.point, [s for s in U_C if s.belong_to == 'dcel2'])
        if not p.point.involves_both:
            if p.point.belong_to == 'dcel1':
                d2_left_he = self.T2.find_left_neighbor(p.point)
                if d2_left_he is None:
                    p.point.face_contain = None
                else:
                    p.point.face_contain = d2_left_he.halfedge.incident_face
            else:
                d1_left_he = self.T1.find_left_neighbor(p.point)
                if d1_left_he is None:
                    p.point.face_contain = None
                else:
                    p.point.face_contain = d1_left_he.halfedge.incident_face

        if len(U_C) == 0:
            s_l = self.T.find_left_neighbor(p.point)
            s_r = self.T.find_right_neighbor(p.point)
            self.find_new_event(s_l, s_r, p.point)
        else:
            s_lm = self.T.find_leftmost(p.point)
            s_l = self.T.find_left_neighbor(p.point)
            self.find_new_event(s_lm, s_l, p.point)
            s_rm = self.T.find_rightmost(p.point)
            s_r = self.T.find_right_neighbor(p.point)
            self.find_new_event(s_rm, s_r, p.point)

        if p.point.involves_both:
            assign_pointer(p.halfedges)
            p.point.incident_edge = p.halfedges[0]
        self.vertices.append(p.point)  
        p.point.left_hedge = s_l.halfedge if s_l is not None else None    
            
    def find_new_event(self, s_l, s_r, p):
        def add_new_he(new_l, s_l, i):
            h_newl = HalfEdge(origin=i)
            h_sl = HalfEdge(origin=i)
            h_newl.belong_to = new_l.belong_to
            h_sl.belong_to = s_l.belong_to
            h_newl.copy_next(s_l.halfedge)
            h_sl.copy_next(s_l.halfedge.twin)
            h_newl.set_twin(s_l.halfedge.twin)
            h_sl.set_twin(s_l.halfedge)
            new_l.set_halfedge(h_newl)
            return h_sl, h_newl
        
        if s_l is None or s_r is None:
            return
        i = s_l.intersect(s_r)
        if i is None:
            return
        x_i, y_i = i.coordinates
        x_p, y_p = p.coordinates
        if y_i < y_p or (y_i == y_p and x_i > x_p):
            segments=[]
            he_w_origin_i = []
            if s_l.lower_endpoint != i and s_l.upper_endpoint != i:
                new_l = Segment(s_l.lower_endpoint, i)
                new_l.belong_to = s_l.belong_to
                s_l.lower_endpoint = i
                segments.append(new_l)
                h1, h2 = add_new_he(new_l, s_l, i)
                he_w_origin_i.extend([h1, h2])
                self.halfedges.extend([h1, h2])
            if s_r.lower_endpoint != i and s_r.upper_endpoint != i:
                new_r = Segment(s_r.lower_endpoint, i)
                new_r.belong_to = s_r.belong_to
                s_r.lower_endpoint = i
                segments.append(new_r)
                h1, h2 = add_new_he(new_r, s_r, i)
                he_w_origin_i.extend([h1, h2])
                self.halfedges.extend([h1, h2])
            self.Q.insert(i, segments=segments, hedges=he_w_origin_i)

    def plot(self, halfedges):
        for he in halfedges:
            x = he.origin
            y = he.next.origin
            if he.belong_to == he[0].belong_to:
                plt.plot((x.coordinates[0], y.coordinates[0]), (x.coordinates[1], y.coordinates[1]), 'ro-')
            else:
                plt.plot((x.coordinates[0], y.coordinates[0]), (x.coordinates[1], y.coordinates[1]), 'bo-')
        for point in self.intersections:
            plt.plot(point.coordinates[0], point.coordinates[1], marker='x', markersize=10, color="blue")
        plt.show()

    def detect_cycle(self):
        he_set = set(self.halfedges)
        while len(he_set) != 0:
            first_he = he_set.pop()
            current_cycle = [first_he]
            current_he = first_he
            while current_he.next != first_he:
                current_he = current_he.next
                he_set.remove(current_he)
                current_cycle.append(current_he)
            self.cycles.append(CycleNode(current_cycle))
        for cycle in self.cycles:
            if cycle.is_inner_boundary:
                left_hedge = cycle.find_leftmost_he().next.origin.left_hedge
                outer_cycle = left_hedge.cycle if left_hedge is not None else self.cycles[0]
                outer_cycle.links.append(cycle)
                

    def compute_faces(self):
        outer_cycles = [cycle for cycle in self.cycles if not cycle.is_inner_boundary]
        for outer_cycle in outer_cycles:
            face = Face()
            face.outer_component = outer_cycle.cycle[0] if len(outer_cycle.cycle) != 0 else None
            for inner_cycle in outer_cycle.links:
                face.inner_components.append(inner_cycle.cycle[0])
            face.cycle = outer_cycle
            self.faces.append(face)

            he_list = outer_cycle.cycle if len(outer_cycle.cycle) != 0 else outer_cycle.links[0].cycle
            he_list.append(he_list[0])
            for i in range(len(he_list) - 1):
                prev_hedge = he_list[i]
                current_hedge = he_list[i+1]
                if current_hedge.origin.involves_both and prev_hedge.incident_face.belong_to != current_hedge.incident_face.belong_to:
                    f1 = prev_hedge.incident_face.name
                    f2 = current_hedge.incident_face.name
                    face.name = str(f1) + '.' + str(f2)
                    break
            if face.name is None:
                he = face.outer_component if face.outer_component is not None else face.inner_components[0]
                v = he.origin
                f1 = he.incident_face.name
                if v.face_contain is None:
                    if v.belong_to == 'dcel1':
                        f2 = [f for f in self.face2 if f.outer_component is None][0].name
                    else:
                        f2 = [f for f in self.face1 if f.outer_component is None][0].name
                else:
                    f2 = v.face_contain.name
                face.name = str(f1) + '.' + str(f2)
            
            outer_cycle = face.cycle
            for hedge in outer_cycle.cycle:
                hedge.incident_face = face
            for inner_cycle in outer_cycle.links:
                for hedge in inner_cycle.cycle:
                    hedge.incident_face = face
        
    def get_dcel(self):
        return DCEL(self.vertices, self.halfedges, self.faces)
    
    def calculate(self, dcel1, dcel2, plot = False):
        dcel1.set_name('dcel1')
        dcel2.set_name('dcel2')
        h = dcel1.halfedges + dcel2.halfedges
        self.face1 = dcel1.faces
        if self.face1[0].name is None:
            for index, f in enumerate(self.face1):
                f.name = 'f_'+str(index)
        self.face2 = dcel2.faces
        if self.face2[0].name is None:
            for index, f in enumerate(self.face2):
                f.name = 'g_'+str(index)
        if plot:
            _, ax = plt.subplots(nrows=1, ncols=3)
            dcel1.plot_dcel(ax[0])
            dcel2.plot_dcel(ax[1])
        start_time = time.time()
        self.halfedges = h
        self.find_intersections(h)
        print('Find intersection: ', time.time() - start_time)
        self.detect_cycle()
        print('Detect cycle: ', time.time() - start_time)
        self.compute_faces()
        print('Compute faces:', time.time() - start_time)
        dcel = self.get_dcel()
        total_time = time.time() - start_time
        print('Finish:', total_time)
        if plot:
            dcel.plot_dcel(ax[2])
            plt.show()
        return dcel, total_time
Exemplo n.º 4
0
 def __init__(self):
     self.pool = SampleTree()
     self.eventQueue = EventQueue()
     self.__resetCounts()
Exemplo n.º 5
0
class Model(object):
    def __init__(self):
        self.pool = SampleTree()
        self.eventQueue = EventQueue()
        self.__resetCounts()

    ##################################################################
    # there are five kinds of rates:
    # N: (fixed) number of bases in the model
    # rll: rate for dcj on the bases in the contig pool
    # rld: rate for dcj where one break is in the pool
    #      and the other rate is in the garbage
    # rdd: both in garbage
    # fl: telomere loss modifier
    # fg: telomere gain modifier
    # pgain: dead gain probability
    ##################################################################
    def setParameters(self, N, rll, rld = 0, rdd = 0, fl = 0, fg = 0,
                      pgain = 0):        
        self.eventQueue.reset()
        self.N = N
        self.fl = fl
        self.fg = fg
        self.pgain = pgain

        if rll > 0:
            self.eventQueue.addEventType(N * rll, self.__llEvent)
        if rld > 0:
            self.eventQueue.addEventType(N * rld, self.__ldEvent)
        if rdd > 0:
            self.eventQueue.addEventType(N * rdd, self.__ddEvent)
            
    ##################################################################
    # intitialize the starting state
    # the the contigs will all have the same sizes (modulo rounding)
    # in order to satisfy the input parameters exactly
    ##################################################################
    def setStartingState(self, garbageSize, numLinear, numCircular):
        assert self.N > garbageSize + numLinear + numCircular
        self.pool = SampleTree()

        numGarbage = 0
        if garbageSize > 0:
            garbage = CircularContig(garbageSize)
            garbage.setDead()
            self.pool.insert(garbage, garbage.numBases())
            numGarbage = 1
        
        lrat = float(numLinear) / (numLinear + numCircular)
        crat = float(numCircular) / (numLinear + numCircular)
        linearBases = math.floor((self.N - garbageSize) * lrat)
        circularBases = math.ceil((self.N - garbageSize) * crat)
        assert linearBases + circularBases + garbageSize == self.N

        if numLinear > 0:
            linSize = math.floor(linearBases / numLinear)
            extra = linearBases % numLinear
            added = 0
            for i in range(numLinear):
                size = linSize
                if i < extra:
                    size += 1
                # plus 1 since number of adjacencies is 1 + number of bases
                contig = LinearContig(size + 1)
                self.pool.insert(contig, contig.numBases())
                added += contig.size
            assert added == linearBases + numLinear
            assert self.pool.size() == numLinear + numGarbage
            assert self.pool.weight() == linearBases + garbageSize

        if numCircular > 0:
            circSize = math.floor(circularBases / numCircular)
            extra = circularBases % numCircular
            added = 0
            for i in range(numCircular):
                size = circSize
                if i < extra:
                    size += 1
                contig = CircularContig(size)
                self.pool.insert(contig, contig.numBases())
                added += contig.size
            assert added == circularBases
            assert self.pool.size() == numLinear + numCircular + numGarbage
            assert self.pool.weight() == circularBases + linearBases + \
            garbageSize

    ##################################################################
    # run the simulation for the specified time
    ##################################################################
    def simulate(self, time):
        self.eventQueue.begin()
        self.__resetCounts()
        while True:
            nextEvent = self.eventQueue.next(time)
            if nextEvent is not None:
                nextEvent()
            else:
                break

    ##################################################################
    # draw (and remove) two random adajcenies and their
    # contigs from the pool (only if they are not dead)
    ##################################################################
    def __drawSamples(self):
        sampleNode1, offset1 = self.pool.uniformSample()
        sampleNode2, offset2 = self.pool.uniformSample()

        # the offset is weighted based on the number of bases
        # we want to translate this into number of edges (splitting)
        # the probability between linear and telomere edges.
        # so for linear contigs with zero offset, we flip a coin to
        # move it to the other side. 
        if sampleNode1.data.isLinear() and offset1 == 0:
            if random.random() < 0.5:
                offset1 = sampleNode1.data.numBases()
        if sampleNode2 is not sampleNode1 and sampleNode2.data.isLinear() and\
           offset2 == 0:
            if random.random() < 0.5:
                offset2 = sampleNode2.data.numBases()

        assert offset1 < sampleNode1.data.size
        assert offset2 < sampleNode2.data.size
        
        return (sampleNode1, offset1, sampleNode2, offset2)

    
    ##################################################################
    #LIVE-LIVE event.  Is normal DCJ operation between two live contigs
    #unless the two breakpoints are identical or on telomeres, in which
    #case fl and fg parameters are used to use fission operations to
    #modifiy the number of telomeres
    ##################################################################
    def __llEvent(self):
        if self.pool.size() == 0 or self.pool.weight() == 1:
            return
        
        # draw (and remove) two random adajcenies and their
        #contigs from the pool (only if they are not dead)
        sampleNode1, offset1, sampleNode2, offset2 = self.__drawSamples()
        c1 = sampleNode1.data
        c2 = sampleNode2.data

        # don't deal with dead contigs in this event
        if c1.isDead() == True or c2.isDead() == True:
            return

        self.pool.remove(sampleNode1)
        if c1 is not c2:
            self.pool.remove(sampleNode2)

        # case 1) gain of telomere
        if sampleNode1 is sampleNode2 and offset1 == offset2:
            return self.__llGain(c1, c2, offset1, offset2)
            
          
        # case 2) loss of telomere
        elif c1.isLinear() and c2.isLinear() and \
                 (offset1 == 0 or offset1 == c1.size - 1) and \
                 (offset2 == 0 or offset2 == c2.size - 1):
            return self.__llLoss(c1, c2, offset1, offset2)

        # case 3) no gain or loss
        self.llCount += 1
        forward = random.randint(0, 1) == 1

        # do the dcj
        dcjResult = dcj(c1, offset1, c2, offset2, forward)
            
        # add the resulting contigs back to the pool
        for res in dcjResult:
            self.pool.insert(res, res.numBases())
            
    ##################################################################
    # Do the fission telomere gain operation (if fg check passes)
    ##################################################################
    def __llGain(self, c1, c2, offset1, offset2):
        # correct "not composite check below"
        if c1.isCircular() or (offset1 != 0 and offset1 != c1.size - 1):
            forward = self.fg > random.random()
            if forward:
                self.fgCount += 1
                dcjResult = dcj(c1, offset1, c2, offset2, forward)
                if c1.isCircular():
                    assert len(dcjResult) == 1 and dcjResult[0].isLinear()
                else:
                    assert len(dcjResult) == 2 and dcjResult[0].isLinear() \
                           and dcjResult[1].isLinear()
                # add the resulting contigs back to the pool
                for res in dcjResult:
                    self.pool.insert(res, res.numBases())
                return

        self.pool.insert(c1, c1.numBases())
        if c2 is not c1:
            self.pool.insert(c2, c2.numBases())
                     
    ##################################################################
    # Do the fission telomer loss operation (if fl check passes)
    ##################################################################
    def __llLoss(self, c1, c2, offset1, offset2):
        if c1 is c2:
            forward = self.fl / 4.0 > random.random()
        else:
            forward = self.fl / 2.0 > random.random()
        if forward:
            c1 = c1.circularize()
            if c1 is not c2:
                c2 = c2.circularize()
            dcjResult = dcj(c1, offset1, c2, offset2, forward)
            self.flCount += 1
            assert len(dcjResult) == 1
            if c1 is not c2:
                assert dcjResult[0].isLinear()
            else:
                assert dcjResult[0].isCircular()
            # add the resulting contigs back to the pool
            for res in dcjResult:
                self.pool.insert(res, res.numBases())
        else:
            self.pool.insert(c1, c1.numBases())
            if c2 is not c1:
                self.pool.insert(c2, c2.numBases())


    ##################################################################
    #LIVE-DEAD (or DEAD-LIVE) event.  One contig is alive and the
    #other is the unique dead contig.  This can result in a loss of
    #live contigs and/or change in number of live bases
    ##################################################################
    def __ldEvent(self):
        if self.pool.size() == 0 or self.pool.weight() == 1:
            return
        
        # draw (and remove) two random adajcenies and their
        #contigs from the pool (only if they are not dead)
        sampleNode1, offset1, sampleNode2, offset2 = self.__drawSamples()
        c1 = sampleNode1.data
        c2 = sampleNode2.data

        # only deal with live / dead contigs in this event
        if (c1.isDead() == c2.isDead()):
            return

        self.pool.remove(sampleNode1)
        if c1 is not c2:
            self.pool.remove(sampleNode2)

        # make sure c1 is alive and c2 is dead
        if c1.isDead():
            c1, c2 = c2, c1
            offset1, offset2 = offset2, offset1

        # do the dcj
        dcjResult = dcj(c1, offset1, c2, offset2, random.randint(0, 1) == 1)

        deadIdx = 0;
        if len(dcjResult) == 2 and \
               random.randint(0, dcjResult[0].size + dcjResult[1].size) >= \
               dcjResult[0].size:
            deadIdx = 1
        dcjResult[deadIdx].setDead(True)

        if len(dcjResult) == 1:
            self.ldLossCount += 1
        else:
            self.ldSwapCount += 1
            
        # add the resulting contigs back to the pool
        deadCount = 0
        for res in dcjResult:
            if res.isDead():
                deadCount += 1
            self.pool.insert(res, res.numBases())
        assert deadCount == 1
            
    ##################################################################
    #DEAD-DEAD event.  The dead contig rearranges with itself.  pgain
    #is used to decide how oftern this oepration breaks off a new circular
    #live chormosome
    ##################################################################
    def __ddEvent(self):
        if self.pool.size() == 0 or self.pool.weight() == 1:
            return
        
        sampleNode1, offset1, sampleNode2, offset2 = self.__drawSamples()
        c1 = sampleNode1.data
        c2 = sampleNode2.data

        # only deal with dead / dead contigs in this event
        if (c1.isDead() == False or c2.isDead() == False):
            return

        # only support single dead contig
        assert c1 is c2

        # don't know what to do here
        if (offset1 == offset2):
            return        

        self.pool.remove(sampleNode1)
        if c1 is not c2:
            self.pool.remove(sampleNode2)

        #forward means do not cut
        forward = random.random() > self.pgain

        # do the dcj
        dcjResult = dcj(c1, offset1, c2, offset2, forward)

        deadIdx = 0;
        if len(dcjResult) == 2 and \
               random.randint(0, dcjResult[0].size + dcjResult[1].size) \
                            >= dcjResult[0].size:
                    deadIdx = 1
        dcjResult[deadIdx].setDead(True)

        if forward:
            self.ddSwapCount += 1
            assert len(dcjResult) == 1
        else:
            self.ddGainCount += 1
            assert len(dcjResult) == 2
            assert not dcjResult[0].isDead() or not dcjResult[1].isDead()
        
         # add the resulting contigs back to the pool
        for res in dcjResult:
            self.pool.insert(res, res.numBases())

          
    ##################################################################
    # all counters set to zero.  
    ##################################################################
    def __resetCounts(self):
        self.llCount = 0
        self.fgCount = 0
        self.flCount = 0
        self.ldLossCount = 0
        self.ldSwapCount = 0
        self.ddGainCount = 0
        self.ddSwapCount = 0
Exemplo n.º 6
0
    def simulate(self):
        t = 0
        simulationTime = 10000
        simulationLimit = 10000
        arrivalDataRate = self.utilization / 0.00302  # = (6040 bits / 2e+6 bits/s) s   |
        lastDataPackageTime = 0

        maxEventListSize = 1000

        roundSize = 2000  # packages processed
        transientPhaseSize = 2500  #packages processed
        numberOfRounds = 10
        totalSimulationsPackages = (numberOfRounds *
                                    roundSize) + transientPhaseSize

        consumedEvents = []
        eventQueue = EventQueue()
        voiceChannels = []
        voiceQueue = []
        dataQueue = []
        servedPackages = 0

        totalDataWaitingTimePerRound = [0] * numberOfRounds
        WaitingTimeSamplePerRound = []
        for i in range(numberOfRounds):
            WaitingTimeSamplePerRound.append([])

        totalDataProcessingTimePerRound = [0] * numberOfRounds
        ProcessingTimeSamplePerRound = []
        for i in range(numberOfRounds):
            ProcessingTimeSamplePerRound.append([])

        totalVoiceWaitingTimePerRound = [0] * numberOfRounds
        VoiceWaitingTimeSamplePerRound = []
        for i in range(numberOfRounds):
            VoiceWaitingTimeSamplePerRound.append([])

        X2PerRound = [
            0.000256
        ] * numberOfRounds  # voice package processing time is fixed due to voice package size being fixed
        # T1 = W1 + X1 | T2 = W2 + X2
        Nq1PerRound = [0] * numberOfRounds
        Nq2PerRound = [0] * numberOfRounds

        voicePackagesProcessedPerRound = [0] * numberOfRounds

        dataPackagesProcessedPerRound = [0] * numberOfRounds

        averageVoiceWaitingPerRound = []
        averageDataWaitingPerRound = []
        averageDataServingTimePerRound = []

        transmissions = [{}] * (constants.VOICE_CHANNELS * numberOfRounds)

        in_service_package = None

        # Generating voice channels
        for i in range(constants.VOICE_CHANNELS):
            voiceChannels.append(VoiceChannel(i))

        currentEvent = None
        currentRound = -1

        servedDataPackages = 0

        while servedDataPackages < totalSimulationsPackages:  #t < simulationTime and len(consumedEvents) < simulationLimit:

            # print('Served packages: ' + str(servedPackages))

            if servedDataPackages > transientPhaseSize:
                # We're passed transient phase
                if currentRound != (
                    (servedDataPackages - transientPhaseSize) // roundSize):
                    currentRound = (servedDataPackages -
                                    transientPhaseSize) // roundSize
                    #print(currentRound)
                    #print(servedPackages)
                    #print(roundSize)
                    self.log(str(currentRound))

            if currentRound >= 0 and ((
                (servedDataPackages + 1) - transientPhaseSize) //
                                      roundSize) > currentRound:
                Nq1PerRound[currentRound] = len(dataQueue)
                Nq2PerRound[currentRound] = len(voiceQueue)

            self.log('Simulation time\t' + str(t) + 's\nEvent Queue Size:\t' +
                     str(eventQueue.length()))

            if currentEvent is not None:
                consumedEvents.append(currentEvent)
                self.log('Event consumed\t' + str(currentEvent.type))

                # treat evt
                # if the event is a voice package arrival, the package is created and put in the
                # voice package queue
                if currentEvent.type == EventType.CREATE_VOICE_PACKAGE:
                    voiceQueue.append(
                        Package(PackageType.VOICE_PACKAGE, currentEvent.source,
                                t, currentEvent.transmission))
                    self.log('Voice Package from ' +
                             constants.PACKAGE_SOURCE[currentEvent.source] +
                             ' queued')
                # if the event type means a voice package should be moved from queue to processing
                # the first package in the queue is removed and we create an event to finish serving it
                elif currentEvent.type == EventType.VOICE_PACKAGE_PROCESSING:
                    in_service_package = voiceQueue.pop(0)
                    in_service_package.startServingTime = t
                    if currentRound >= 0:
                        totalVoiceWaitingTimePerRound[currentRound] += (
                            in_service_package.startServingTime -
                            in_service_package.arrivalTime)
                        VoiceWaitingTimeSamplePerRound[currentRound].append(
                            in_service_package.startServingTime -
                            in_service_package.arrivalTime)
                        # only for plot purpose
                        averageDataServingTimePerRound.append(
                            sum(totalDataProcessingTimePerRound) /
                            (sum(dataPackagesProcessedPerRound) + 1))
                        averageVoiceWaitingPerRound.append(
                            sum(totalVoiceWaitingTimePerRound) /
                            (sum(voicePackagesProcessedPerRound) + 1))
                        averageDataWaitingPerRound.append(
                            sum(totalDataWaitingTimePerRound) /
                            (sum(dataPackagesProcessedPerRound) + 1))

                    eventQueue.add(
                        Event(
                            t + (in_service_package.size /
                                 float(constants.CHANNEL_SIZE)),
                            EventType.VOICE_PACKAGE_SERVED,
                            in_service_package.source,
                            in_service_package.transmission))
                    self.log(
                        'Voice Package from ' +
                        constants.PACKAGE_SOURCE[in_service_package.source] +
                        'is in the router')
                # if the event is a voice package finishing being served we clear the router/server
                elif currentEvent.type == EventType.VOICE_PACKAGE_SERVED:
                    self.log(
                        'Voice Package from ' +
                        constants.PACKAGE_SOURCE[in_service_package.source] +
                        ' has finished serving')
                    if currentRound >= 0:
                        voicePackagesProcessedPerRound[currentRound] += 1
                    servedPackages += 1

                    if currentRound >= 0 and in_service_package.transmission in transmissions[
                        (in_service_package.source - 1) +
                        (currentRound * constants.VOICE_CHANNELS)].keys():
                        transmission = transmissions[
                            (in_service_package.source - 1) +
                            (currentRound * constants.VOICE_CHANNELS)][
                                in_service_package.transmission]
                        transmission.processedPackages += 1

                        if transmission.size < transmission.processedPackages:
                            transmission.endTime = t

                    in_service_package = None
                # if the event is a data package arrival, the package is created and put in the
                # data package queue
                elif currentEvent.type == EventType.CREATE_DATA_PACKAGE:
                    dataQueue.append(
                        Package(PackageType.DATA_PACKAGE, currentEvent.source,
                                t, currentEvent.transmission))
                    self.log('Data Package from ' +
                             constants.PACKAGE_SOURCE[currentEvent.source] +
                             ' with size ' +
                             str(dataQueue[len(dataQueue) - 1].size) +
                             ' queued')
                    # here we also create the next data package

                # if the event type means a data package should be moved from queue to processing
                # the first package in the queue is removed and we create an event to finish serving it
                elif currentEvent.type == EventType.DATA_PACKAGE_PROCESSING:
                    in_service_package = dataQueue.pop(0)
                    in_service_package.startServingTime = t
                    if currentRound >= 0:
                        totalDataWaitingTimePerRound[currentRound] += (
                            in_service_package.startServingTime -
                            in_service_package.arrivalTime)
                        WaitingTimeSamplePerRound[currentRound].append(
                            in_service_package.startServingTime -
                            in_service_package.arrivalTime)
                        # only for plot purpose
                        averageDataServingTimePerRound.append(
                            sum(totalDataProcessingTimePerRound) /
                            (sum(dataPackagesProcessedPerRound) + 1))
                        averageVoiceWaitingPerRound.append(
                            sum(totalVoiceWaitingTimePerRound) /
                            (sum(voicePackagesProcessedPerRound) + 1))
                        averageDataWaitingPerRound.append(
                            sum(totalDataWaitingTimePerRound) /
                            (sum(dataPackagesProcessedPerRound) + 1))

                    evt = Event(
                        t + (in_service_package.size /
                             float(constants.CHANNEL_SIZE)),
                        EventType.DATA_PACKAGE_SERVED,
                        in_service_package.source,
                        in_service_package.transmission)
                    if self.preemptive:
                        evt.package_reference = in_service_package
                    eventQueue.add(evt)
                    self.log(
                        'Data Package from ' +
                        constants.PACKAGE_SOURCE[in_service_package.source] +
                        ' with size ' + str(in_service_package.size) +
                        ' is in the router')
                # if the event is a data package finishing being served we clear the router/server
                elif currentEvent.type == EventType.DATA_PACKAGE_SERVED:
                    self.log(
                        'Data Package from ' +
                        constants.PACKAGE_SOURCE[in_service_package.source] +
                        ' with size ' + str(in_service_package.size) +
                        ' has finished serving')
                    in_service_package.endServingTime = t
                    if currentRound >= 0:
                        totalDataProcessingTimePerRound[currentRound] += (
                            in_service_package.endServingTime -
                            in_service_package.startServingTime)
                        dataPackagesProcessedPerRound[currentRound] += 1
                        ProcessingTimeSamplePerRound[currentRound].append(
                            in_service_package.endServingTime -
                            in_service_package.startServingTime)
                        # only for plot purpose
                        averageDataServingTimePerRound.append(
                            sum(totalDataProcessingTimePerRound) /
                            (sum(dataPackagesProcessedPerRound) + 1))
                        averageVoiceWaitingPerRound.append(
                            sum(totalVoiceWaitingTimePerRound) /
                            (sum(voicePackagesProcessedPerRound) + 1))
                        averageDataWaitingPerRound.append(
                            sum(totalDataWaitingTimePerRound) /
                            (sum(dataPackagesProcessedPerRound) + 1))

                    servedPackages += 1
                    servedDataPackages += 1

                    in_service_package = None

                # Note: altough voice and data events could be treated together, the separation will make
                # things easier to track and change for the preemptive scenario

            if self.preemptive:
                if len(
                        voiceQueue
                ) > 0 and in_service_package is not None and in_service_package.type == PackageType.DATA_PACKAGE:
                    totalDataProcessingTimePerRound[currentRound] += (
                        t - in_service_package.startServingTime)
                    ProcessingTimeSamplePerRound[currentRound].append(
                        t - in_service_package.startServingTime)
                    pkg = Package(PackageType.DATA_PACKAGE, 0, t + 0.000256, 0)
                    pkg.size = in_service_package.size  # - (( t - in_service_package.startServingTime ) * constants.CHANNEL_SIZE)
                    dataQueue.insert(0, pkg)
                    eventQueue.remove_with_package(in_service_package)
                    in_service_package = None
                    if pkg.size < 0:
                        print("ERROR SIZE")

            # if there's no package being processed
            if in_service_package is None:
                # we check if there's any voice packages waiting to be processed
                if len(voiceQueue) > 0:
                    eventQueue.add(
                        Event(t, EventType.VOICE_PACKAGE_PROCESSING,
                              voiceQueue[0].source,
                              voiceQueue[0].transmission))
                # in case there's no voice package to be processed we check if there's any data package
                # to process
                # Note: this is due to the fact voice packages have the priority
                elif len(dataQueue) > 0:
                    eventQueue.add(
                        Event(t, EventType.DATA_PACKAGE_PROCESSING, 0, 0))

            # Generate voice arrivals
            self.log('==================================')
            for i in range(len(voiceChannels)):
                if t >= voiceChannels[
                        i].nextTransmission:  # and eventQueue.length() < maxEventListSize:
                    evtTimes = voiceChannels[i].getEventTimes(t)[1:]
                    transmissionId = 0
                    if currentRound >= 0 and len(evtTimes) > 0:
                        transmission = Transmission(evtTimes[0], 0,
                                                    (len(evtTimes) - 1), 0)
                        transmissionId = len(
                            transmissions[i +
                                          (currentRound *
                                           constants.VOICE_CHANNELS)].keys())
                        transmissions[i +
                                      (currentRound * constants.VOICE_CHANNELS
                                       )][transmissionId] = transmission
                    for evtTime in evtTimes:
                        evt = Event(evtTime + t,
                                    EventType.CREATE_VOICE_PACKAGE, i + 1,
                                    transmissionId)
                        # self.log('Voice evt added in ' + str(evt.eventTime) + 's', 0.005)
                        eventQueue.add(evt)
            self.log('==================================')

            # Generate data arrivals
            if t >= lastDataPackageTime:
                evtTime = lastDataPackageTime + np.random.exponential(
                    1 / arrivalDataRate)
                eventQueue.add(
                    Event(evtTime, EventType.CREATE_DATA_PACKAGE, 0, 0))
                lastDataPackageTime = evtTime
                self.log('Data evt added in ' + str(evtTime) + 's')
                #print('Data evt added in ' + str(evtTime) + 's')

            # self.log('---------')
            # for i in range(eventQueue.length()):
            #     self.log(str(eventQueue.get(i).type) + ' ' + str(eventQueue.get(i).eventTime))
            # self.log('---------')

            # getting next event in simulation time and setting simulation time to event's time
            currentEvent = eventQueue.pop()
            # self.log('--------- next event ---------')
            # self.log(str(currentEvent.type) + ' ' + str(currentEvent.eventTime))
            # self.log('---------')
            t = currentEvent.eventTime

        # GENERATE STATISTICS

        finalW1 = 0
        finalStdW1 = 0
        finalW2 = 0
        finalStdW2 = 0
        finalX1 = 0
        finalStdX1 = 0
        finalX2 = 0
        finalStdX2 = 0
        finalT1 = 0
        finalStdT1 = 0
        finalT2 = 0
        finalStdT2 = 0
        finalNq1 = 0
        finalStdNq1 = 0
        finalNq2 = 0
        finalStdNq2 = 0

        delta = 0

        if (self.PLOT):
            if (not (os.path.exists("images"))):
                os.mkdir("images")

            plt.plot(averageDataWaitingPerRound)
            plt.ylabel('E[W1]')
            plt.ylabel('Pacotes servidos')
            plt.title("V.A. W1 com valor rho1 = " + str(self.utilization))
            plt.xlim(xmax=servedPackages)
            plt.savefig('images/W1-' + str(self.utilization) + '.png')
            plt.clf()

            plt.plot(averageDataServingTimePerRound)
            plt.ylabel('E[X1]')
            plt.ylabel('Pacotes servidos')
            plt.title("V.A. X1 com valor rho1 = " + str(self.utilization))
            plt.xlim(xmax=servedPackages)
            plt.savefig('images/X1-' + str(self.utilization) + '.png')
            plt.clf()

            plt.plot(averageVoiceWaitingPerRound)
            plt.ylabel('E[W2]')
            plt.ylabel('Pacotes servidos')
            plt.title("V.A. W2 com valor rho1 = " + str(self.utilization))
            plt.xlim(xmax=servedPackages)
            plt.savefig('images/W2-' + str(self.utilization) + '.png')
            plt.clf()

        stdW1perRound = []
        stdW2perRound = []
        stdX1perRound = []
        stdX2perRound = []
        stdT1perRound = []
        stdT2perRound = []
        stdNq1perRound = []
        stdNq2perRound = []

        for i in range(numberOfRounds):
            W1 = totalDataWaitingTimePerRound[
                i] / dataPackagesProcessedPerRound[i]
            X1 = totalDataProcessingTimePerRound[
                i] / dataPackagesProcessedPerRound[i]
            T1 = X1 + W1
            stdT1perRound.append(T1)
            W2 = totalVoiceWaitingTimePerRound[
                i] / voicePackagesProcessedPerRound[i]
            X2 = X2PerRound[i]
            T2 = X2 + W2
            stdT2perRound.append(T2)
            #print('Round ' + str(i) + ':\nW1: ' + str(W1) + '\tX1: ' + str(X1) + '\tT1: ' + str(T1))
            #print('W2: ' + str(W2) + '\tX2: ' + str(X2) + '\tT2: ' + str(T2) + '\n')

            dt = 0
            dt2 = 0
            dts = [0] * constants.VOICE_CHANNELS
            for j in range(len(transmissions) // constants.VOICE_CHANNELS):
                for k in transmissions[j +
                                       (i * constants.VOICE_CHANNELS)].keys():
                    transmission = transmissions[
                        j + (i * constants.VOICE_CHANNELS)].get(k)
                    if transmission.endTime > 0:
                        dt += (
                            (transmission.endTime - transmission.startTime) /
                            (len(transmissions[j +
                                               (i * constants.VOICE_CHANNELS)])
                             - 1))
                dts[j] = dt

            for j in range(len(transmissions) // constants.VOICE_CHANNELS):
                for k in transmissions[j +
                                       (i * constants.VOICE_CHANNELS)].keys():
                    transmission = transmissions[
                        j + (i * constants.VOICE_CHANNELS)].get(k)
                    if transmission.endTime > 0:
                        dt2 += (
                            ((transmission.endTime - transmission.startTime) -
                             dts[j])**2) / (len(transmissions[
                                 j + (i * constants.VOICE_CHANNELS)]) - 1)

            finalW1 += W1 / numberOfRounds
            stdW1perRound.append(std(WaitingTimeSamplePerRound[i]))

            finalW2 += W2 / numberOfRounds
            stdW2perRound.append(std(VoiceWaitingTimeSamplePerRound[i]))

            finalX1 += X1 / numberOfRounds
            stdX1perRound.append(std(ProcessingTimeSamplePerRound[i]))

            finalX2 += X2 / numberOfRounds

            finalT1 += T1 / numberOfRounds

            finalT2 += T2 / numberOfRounds
            finalNq1 += dataPackagesProcessedPerRound[i] / numberOfRounds
            finalNq2 += voicePackagesProcessedPerRound[i] / numberOfRounds
            dt /= (constants.M1 * numberOfRounds)
            dt2 /= (constants.M2 / (constants.M3 * self.utilization) *
                    numberOfRounds)

        finalNq1 = arrivalDataRate * finalW1
        finalNq2 = constants.VOICE_PACKAGE_ARRIVAL_RATE * finalW2

        finalStdW1 = std(stdW1perRound)
        finalStdW2 = std(stdW2perRound)
        finalStdX1 = std(stdX1perRound)
        finalStdX2 = std(X2PerRound)

        finalStdNq1 = std(dataPackagesProcessedPerRound)
        finalStdNq2 = std(voicePackagesProcessedPerRound)

        finalStdT1 = std(stdT1perRound)

        finalStdT2 = std(stdT2perRound)

        print('E[W1]: ' + str(finalW1))
        print('Std[W1]: ' + str(finalStdW1))
        print('IC para W1: ' +
              str(stats.norm.interval(0.9, loc=finalW1, scale=finalStdW1)))
        print('E[W2]: ' + str(finalW2))
        print('Std[W2]: ' + str(finalStdW2))
        print('IC para W2: ' +
              str(stats.norm.interval(0.9, loc=finalW2, scale=finalStdW2)))
        print('E[X1]: ' + str(finalX1))
        print('Std[X1]: ' + str(finalStdX1))
        print('IC para X1: ' +
              str(stats.norm.interval(0.9, loc=finalX1, scale=finalStdX1)))
        print('E[X2]: ' + str(finalX2))
        print('Std[X2]: ' + str(finalStdX2))
        print('IC para X2: ' +
              str(stats.norm.interval(0.9, loc=finalX2, scale=finalStdX2)))
        print('E[T1]: ' + str(finalT1))
        print('Std[T1]: ' + str(finalStdT1))
        print('IC para T1: ' +
              str(stats.norm.interval(0.9, loc=finalT1, scale=finalStdT1)))
        print('E[T2]: ' + str(finalT2))
        print('Std[T2]: ' + str(finalStdT2))
        print('IC para T2: ' +
              str(stats.norm.interval(0.9, loc=finalT2, scale=finalStdT2)))
        print('E[Nq1]: ' + str(finalNq1))
        print('Std[Nq1]: ' + str(finalStdNq1))
        print('IC para Nq1: ' +
              str(stats.norm.interval(0.9, loc=finalNq1, scale=finalStdNq1)))
        print('E[Nq2]: ' + str(finalNq2))
        print('Std[Nq2]: ' + str(finalStdNq2))
        print('IC para Nq2: ' +
              str(stats.norm.interval(0.9, loc=finalNq2, scale=finalStdNq2)))
        print('E[Delta]: ' + str(dt))
        print('V[Delta]: ' + str(dt2))
Exemplo n.º 7
0
 def __init__(self):
     self.Q = EventQueue()
     self.T = StatusStructure()
     self.intersections = []