Skip to content
Extraits de code Groupes Projets
tp_lphys1201.py 4,89 ko
Newer Older
  • Learn to ignore specific revisions
  • import random, sys
    
    
    class student:
        uniqueId = 0
    
        def __init__(self, average_question_time):
            self.id = student.uniqueId
            self.n_answered = 0
            student.uniqueId += 1
    
            self.next_question_time = -1
            self.waiting_time = 0
            self.prob_question = 1/average_question_time
            self.get_next_question(0)
    
        def get_next_question(self, time):
            self.next_question_time = time + random.expovariate(self.prob_question)
    
        def __repr__(self):
            return("Next question at : {}".format(self.next_question_time))
    
        def __gt__(self,other):
            return self.next_question_time > other.next_question_time
        def __ge__(self,other):
            return self.next_question_time >= other.next_question_time
        def __lt__(self,other):
            return self.next_question_time < other.next_question_time
        def __le__(self,other):
            return self.next_question_time <= other.next_question_time
    
    class teacher:
        uniqueId = 0
        def __init__(self, alpha, beta):
            self.n_answered = 0
            self.id = teacher.uniqueId
            teacher.uniqueId += 1
            self.alpha     = alpha
            self.beta      = beta
            self.time_busy = 0
            self.total_working_time = 0
    
    
        def get_answer_time(self, time):
            solve_time = time + random.weibullvariate(self.alpha,self.beta)
            self.time_busy = solve_time
            self.total_working_time += solve_time - time
            return solve_time
    
        def is_busy(self,time):
            return time < self.time_busy
    
        def __repr__(self):
            return("Will be busy until {}".format(self.time_busy))
    
        def __gt__(self,other):
            return self.time_busy > other.time_busy
        def __ge__(self,other):
            return self.time_busy >= other.time_busy
        def __lt__(self,other):
            return self.time_busy < other.time_busy
        def __le__(self,other):
            return self.time_busy <= other.time_busy
    
    
    def simulate(n_students, n_teachers, av_student = 45, alpha = 3, beta = 1.6):
        teachers = [ teacher(alpha,beta) for i in range(n_teachers) ]
        students = [ student(av_student) for i in range(n_students) ]
    
        time = 0
        while time < 120:
            students.sort()
            teachers.sort()
    
            for t in teachers:
                if not t.is_busy(time):
                    s = students[0]
                    start_help = max(time,s.next_question_time)
                    s.waiting_time += start_help - s.next_question_time
    
                    solve_time = t.get_answer_time(start_help)
                    s.get_next_question(solve_time)
    
                    t.n_answered += 1
                    s.n_answered +=1
    
                    break
    
    
            teachers.sort()
            time = teachers[0].time_busy
    
        average_waiting_time       = 0
        average_questions_answered = 0
        for s in students:
            average_waiting_time        += s.waiting_time
            average_questions_answered  += s.n_answered
    
        average_time_worked = 0
        for t in teachers:
            average_time_worked += t.total_working_time
    
        return (average_waiting_time/n_students, average_questions_answered/n_students, average_time_worked/n_teachers,time)
    
    
    def simulate_many(n_simul,n_students, n_teachers, av_student = 45, alpha = 6, beta = 1.6, silent = False):
        if not silent:
            print(20*"*")
            print(20*"*")
            print("Simulating classroom with :")
            print("{} students with a question every {} min on average".format(n_students,av_student))
            print("{} teachers answering question with alpha = {} and beta = {}".format(n_teachers,alpha,beta))
            print("These parameters result in a mode of {:0.2f}m per question".format(alpha*(1-1/beta)**(1/beta)))
        data = [0,0,0,0]
        for i in range(n_simul):
            simul_results = simulate(n_students, n_teachers, av_student, alpha, beta)
            data[0] += simul_results[0]
            data[1] += simul_results[1]
            data[2] += simul_results[2]
            data[3] += simul_results[3]
    
        data = [x/n_simul for x in data]
        if not silent:
            print("After {} simulations, the following results were found:".format(n_simul))
            print("An average of {:0.2f} questions were answered after waiting {:0.2f} minutes.".format(data[1],data[0]))
            print("The teachers were busy {:0.2f}% of the time".format(100*data[2]/data[3]))
            print("A total of {:0.2f} questions were answered".format(data[1]*n_students))
        return data[0]
    
    
    def sweep_alpha(n_students, wait_thresh, n_simul = 1000, n_teachers = 2, av_student = 45, beta = 1.6):
        alpha_max = 16
        alpha     = 0
        for i in range(10):
            alpha_step = alpha_max/(1<<i)
            alpha += alpha_step
    
            if simulate_many(n_simul, n_students, n_teachers, av_student, alpha, beta, silent = True) > wait_thresh:
                alpha -= alpha_step
    
        print("alpha = {}".format(alpha))
        simulate_many(n_simul, n_students, n_teachers, av_student, alpha, beta)
    
    
    simulate_many(10000 , 13 , 2 , 40 )
    
    simulate_many(10000 , 26 , 2 , 40 )
    
    sweep_alpha(26,2)
    
    sweep_alpha(26,1)