Blame view

src/scheduler/simulator.py 5.09 KB
715fabb7   haribo   #3430 (100%)
1
2
3
4
5
6
7
8
9
10
11
from scheduler.models import Scheduler
from pyrosapp.models import *
from django.contrib.auth.models import User
import urllib.request as urllib2
from html.parser import HTMLParser
import math
import operator
from decimal import Decimal
import time
from operator import attrgetter

94336356   haribo   Added starting fi...
12

715fabb7   haribo   #3430 (100%)
13
14
15
16
17
18
19
20
21
22
23
class MyHTMLParser(HTMLParser):
    '''
        Subclassing HTMLParser to access the data properly
    '''

    def __init__(self):
        HTMLParser.__init__(self)
        self.data = []

    def handle_data(self, data):
        self.data.append(data)
94336356   haribo   Added starting fi...
24

715fabb7   haribo   #3430 (100%)
25
26
27
    def handle_comment(self, data):
        pass

94336356   haribo   Added starting fi...
28

715fabb7   haribo   #3430 (100%)
29
30
31
32
class Simulator():
    '''
        Simulates the creation of a planning thanks to an HTML file
    '''
94336356   haribo   Added starting fi...
33

715fabb7   haribo   #3430 (100%)
34
35
    def __init__(self):
        pass
94336356   haribo   Added starting fi...
36

715fabb7   haribo   #3430 (100%)
37
38
39
    def simulate(self, sequences_file):
        '''
           ENTRY POINT
94336356   haribo   Added starting fi...
40

715fabb7   haribo   #3430 (100%)
41
           Parse the file with sequences, then call the Scheduler simulation function and give the result to the view
94336356   haribo   Added starting fi...
42

715fabb7   haribo   #3430 (100%)
43
44
45
           :param sequences_file : HTML file containing sequences description 
           :returns : a tuple (Schedule, list of sequences) after the scheduling process
        '''
94336356   haribo   Added starting fi...
46

715fabb7   haribo   #3430 (100%)
47
48
        file = urllib2.urlopen(sequences_file)
        data = str(file.read())
94336356   haribo   Added starting fi...
49

715fabb7   haribo   #3430 (100%)
50
51
52
53
        parser = MyHTMLParser()
        parser.feed(data)

        """filter unwanted \n and other data"""
77816f10   haribo   Workflow implemen...
54
55
        filtered_list = list(map(lambda s: s.strip(), parser.data))
        page_text = "".join(filtered_list[11:])
715fabb7   haribo   #3430 (100%)
56

77816f10   haribo   Workflow implemen...
57
58
        raw_sequences = page_text.split("\\n")
        del raw_sequences[0]
94336356   haribo   Added starting fi...
59
60
61
        del raw_sequences[len(raw_sequences) - 1]
        raw_sequences = [
            sequence for sequence in raw_sequences if len(sequence) > 0]
715fabb7   haribo   #3430 (100%)
62
63
64
65
66
67

        """Create the default models linked to the sequences"""
        sp = ScientificProgram()
        country = Country()
        usr_lvl = UserLevel()
        usr = User(username="toto")
94336356   haribo   Added starting fi...
68
        py_usr = PyrosUser(
94082e77   haribo   Date: 03/06/2016
69
            user=usr, country=country, user_level=usr_lvl, quota=1000)
94336356   haribo   Added starting fi...
70
        req = Request(scientific_program=sp, pyros_user=py_usr)
715fabb7   haribo   #3430 (100%)
71
72
73
74
75

        scheduler = Scheduler()

        """Create the sequences"""
        sequences = []
77816f10   haribo   Workflow implemen...
76
77
78
79
        for raw_sequence in raw_sequences:
            sequence_array = raw_sequence.split(" ")
            id_seq = sequence_array[0]
            priority = int(sequence_array[2])
715fabb7   haribo   #3430 (100%)
80
            ''' transforms the duration (seconds) in days (86,400s in a day)'''
77816f10   haribo   Workflow implemen...
81
82
83
            duration = Decimal(float(sequence_array[4]) / 86400.0)
            jd1 = Decimal("%.8f" % float(sequence_array[5]))
            jd2 = Decimal("%.8f" % float(sequence_array[6]))
94336356   haribo   Added starting fi...
84

7a79e25b   haribo   Date: 19/05/2016
85
            sequence = Sequence(request=req, status=Sequence.OBSERVABLE,
715fabb7   haribo   #3430 (100%)
86
87
88
                                name="sequence", id=id_seq, priority=priority, duration=duration, jd1=jd1, jd2=jd2, t_prefered=-1)
            sequences.append(sequence)

94336356   haribo   Added starting fi...
89
90
        # 1) trouver le nombre qu'on retrouve le plus souvent en troncature de
        # jd1 (faire un dico)
715fabb7   haribo   #3430 (100%)
91
92
93
94
95
96
97
98
        days = {}
        for sequence in sequences:
            truncated = math.floor(float(sequence.jd1))
            if truncated in days.keys():
                days[truncated] += 1
            else:
                days[truncated] = 1
        maximum_truncated = max(days.keys(), key=(lambda key: days[key]))
94336356   haribo   Added starting fi...
99

715fabb7   haribo   #3430 (100%)
100
        # 2) virer toutes les séquences qui n'ont pas ce jd1 en troncature
94336356   haribo   Added starting fi...
101
102
        sequences = [sequence for sequence in sequences if math.floor(
            float(sequence.jd1)) == maximum_truncated]
715fabb7   haribo   #3430 (100%)
103

94336356   haribo   Added starting fi...
104
105
        # 3) set le plan_start et le plan_end en fonction du plus petit jd1 et
        # du plus grand jd2
715fabb7   haribo   #3430 (100%)
106
107
108
109
110
111
112
113
114
        scheduler.schedule.plan_start = -1
        scheduler.schedule.plan_end = -1
        for sequence in sequences:
            if scheduler.schedule.plan_start == -1 or sequence.jd1 < scheduler.schedule.plan_start:
                scheduler.schedule.plan_start = sequence.jd1
            if scheduler.schedule.plan_end == -1 or sequence.jd2 > scheduler.schedule.plan_end:
                scheduler.schedule.plan_end = sequence.jd2

        start = time.time()
94336356   haribo   Added starting fi...
115

715fabb7   haribo   #3430 (100%)
116
117
118
        schedule, sequences = scheduler.simulate_schedule(sequences)

        end = time.time()
94336356   haribo   Added starting fi...
119

715fabb7   haribo   #3430 (100%)
120
        print("Duration : ", end - start)
94336356   haribo   Added starting fi...
121

715fabb7   haribo   #3430 (100%)
122
        self.test_sequences_validity(schedule, sequences)
94336356   haribo   Added starting fi...
123

715fabb7   haribo   #3430 (100%)
124
        return (schedule, sequences)
94336356   haribo   Added starting fi...
125

715fabb7   haribo   #3430 (100%)
126
127
128
129
130
131
132
133
    def test_sequences_validity(self, schedule, sequences):
        '''
            For PLANNED sequences, tests if :
                - all the sequences are in the schedule
                - there is no overlap between sequences
                - [tsp - tep] is in [jd1 - jd2]
                - tep < tsp
        '''
7a79e25b   haribo   Date: 19/05/2016
134
        sequences.sort(key=lambda x: x[1].tsp)
94336356   haribo   Added starting fi...
135

7a79e25b   haribo   Date: 19/05/2016
136
        for index, (sequence, shs) in enumerate(sequences):
eecfb779   haribo   Date: 26/05/2016
137
            if shs.status == Sequence.PENDING:
7a79e25b   haribo   Date: 19/05/2016
138
                if shs.tsp > shs.tep:
715fabb7   haribo   #3430 (100%)
139
                    raise ValueError("tep < tsp ...")
7a79e25b   haribo   Date: 19/05/2016
140
                if shs.tsp < schedule.plan_start or schedule.plan_end < shs.tep:
715fabb7   haribo   #3430 (100%)
141
                    raise ValueError("[tsp;tep] not in [plan_start;plan_end]")
7a79e25b   haribo   Date: 19/05/2016
142
                if shs.tsp < sequence.jd1 or sequence.jd2 < shs.tep:
715fabb7   haribo   #3430 (100%)
143
                    raise ValueError("[tsp;tep] not in [jd1;jd2]")
7a79e25b   haribo   Date: 19/05/2016
144
                if index > 0 and shs.tsp < sequences[index - 1][1].tep:
715fabb7   haribo   #3430 (100%)
145
                    raise ValueError("There is a sequence overlap")