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())
715fabb7   haribo   #3430 (100%)
49
50
51
52
        parser = MyHTMLParser()
        parser.feed(data)

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

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

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

        scheduler = Scheduler()

        """Create the sequences"""
        sequences = []
77816f10   haribo   Workflow implemen...
75
76
77
78
        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%)
79
            ''' transforms the duration (seconds) in days (86,400s in a day)'''
77816f10   haribo   Workflow implemen...
80
81
82
            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...
83

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

94336356   haribo   Added starting fi...
88
89
        # 1) trouver le nombre qu'on retrouve le plus souvent en troncature de
        # jd1 (faire un dico)
715fabb7   haribo   #3430 (100%)
90
91
92
93
94
95
96
97
        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...
98

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

94336356   haribo   Added starting fi...
103
104
        # 3) set le plan_start et le plan_end en fonction du plus petit jd1 et
        # du plus grand jd2
715fabb7   haribo   #3430 (100%)
105
106
107
108
109
110
111
112
113
        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...
114

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

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

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

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

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

715fabb7   haribo   #3430 (100%)
125
126
127
128
129
130
131
132
    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
133
        sequences.sort(key=lambda x: x[1].tsp)
94336356   haribo   Added starting fi...
134

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