def evaluateNewIndividualFormat(individual): ''' Fitness function that evaluates and each individual in the population and assigns a fitness value to it which is the average waiting time for the individual (i.e a timetable) @param: individual - encoded individual which represents an timetable for mulitple lines. ''' individual = sorted(individual, key=itemgetter(3)) individual = sorted(individual, key=itemgetter(0)) # Second, we loop trough the number of genes in order to retrieve the # number of requests for that particular trip # For the 1st trip, the starting time has to be selected request = [] totalWaitingMinutes = [] cnt = [] db = DB() # ---------------------------------------------------- # Evaluate average time based on requests (& capacity) # ---------------------------------------------------- leftOver = [] l = len(db.timeSliceArray) - 1 startT = datetime.datetime.combine(Fitness.yesterday, datetime.time(db.timeSliceArray[l][0], 0, 0)) endT = datetime.datetime.combine(Fitness.yesterday, datetime.time(db.timeSliceArray[l][1], 59, 59)) firstSliceHr = datetime.datetime.combine(Fitness.yesterday, datetime.time(db.timeSliceArray[0][0], 0, 0)) for i in range(len(individual)): phenotype = db.generatePhenotype(individual[i][0], individual[i][3]) initialCrew = 0 leftOvers = 0 leftOversWaitTime = 0 firstHrOfTimeSlice, LastHrOfTimeSlice = fitnessClass.getTimeSlice(individual[i][3]) diffToFirstHrSlice = individual[i][3] - firstHrOfTimeSlice diffToFirstHrSlice = diffToFirstHrSlice.days * databaseClass.minutesDay + diffToFirstHrSlice.seconds / databaseClass.minutesHour diffToLastHrSlice = LastHrOfTimeSlice - individual[i][3] diffToLastHrSlice = diffToLastHrSlice.days * databaseClass.minutesDay + diffToLastHrSlice.seconds / databaseClass.minutesHour backTrips = round(float(diffToFirstHrSlice)/float(individual[i][2])) forwardTrips = round(float(diffToLastHrSlice)/float(individual[i][2])) noOfTrips = backTrips + forwardTrips + 1 for key in fitnessClass.totalRequestsBusline: if individual[i][0] == key[0] and (key[1] <= individual[i][3] <= key[2]): totalCapacityInSlice = noOfTrips * individual[i][1] initialCrew = fitnessClass.totalRequestsBusline[key] try: if (initialCrew >totalCapacityInSlice ): leftOvers = initialCrew - totalCapacityInSlice if (individual[i][3] + timedelta(minutes=individual[i][2]) > endT): timed = (endT - individual[i][3]) + timedelta(hours=db.timeSliceArray[0][0]) timed = (timed.days * databaseClass.minutesDay) + (timed.seconds / databaseClass.minutesHour) timed = timed * leftOvers leftOver.append([timed, leftOvers]) else: timed = (individual[i][2]) * leftOvers leftOver.append([timed, leftOvers]) except IndexError: print("Error") for j in range(len(phenotype)): # TODO: Fix trips that finish at the next day deprtTimeBusStop = phenotype[j][1] # Search on Fitness.request array for the all request made in a slice for a particular busStop and Line request = fitnessClass.searchRequest(firstHrOfTimeSlice, LastHrOfTimeSlice, phenotype[j][0], individual[i][0]) if len(request) > 0: waitingMinutes = 0 count = 0 for k in range(len(request)): requestTime = request[k]["_id"]["RequestTime"] # Senario 1 - When the request time made is after the starting time provided in the GENE # i.e people who can NOT make it. if requestTime > deprtTimeBusStop: difference = requestTime-deprtTimeBusStop difference = difference.days * databaseClass.minutesDay + difference.seconds / databaseClass.minutesHour noOfTimesToGoForwardOnClock = math.ceil(float(difference)/float(individual[i][2])) if noOfTimesToGoForwardOnClock == 1: newTripToTake = deprtTimeBusStop + timedelta(minutes=individual[i][2]) waitingTime = (newTripToTake - requestTime) waitingMinutes = waitingTime.days * databaseClass.minutesDay + waitingTime.seconds / databaseClass.minutesHour else: totalMinToGoForwardOnClock = noOfTimesToGoForwardOnClock * individual[i][2] newTripToTake = deprtTimeBusStop + timedelta(minutes=totalMinToGoForwardOnClock) waitingTime = (newTripToTake - requestTime) waitingMinutes = waitingTime.days * databaseClass.minutesDay + waitingTime.seconds / databaseClass.minutesHour # Senario 2 - When the request time made is before the starting time provided in the GENE # i.e people who can make it. else: difference = deprtTimeBusStop-requestTime difference = difference.days * databaseClass.minutesDay + difference.seconds / databaseClass.minutesHour noOfTimesToGoBackOnClock = math.floor(float(difference)/float(individual[i][2])) if noOfTimesToGoBackOnClock == 0: waitingTime = (deprtTimeBusStop - requestTime) waitingMinutes = waitingTime.days * databaseClass.minutesDay + waitingTime.seconds / databaseClass.minutesHour else: totalMinToGoBackOnClock = noOfTimesToGoBackOnClock * individual[i][2] newTripToTake = deprtTimeBusStop - timedelta(minutes=totalMinToGoBackOnClock) waitingTime = (newTripToTake - requestTime) waitingMinutes = waitingTime.days * databaseClass.minutesDay + waitingTime.seconds / databaseClass.minutesHour count = count + int(request[k]["total"]) waitingMinutes = waitingMinutes * request[k]["total"] totalWaitingMinutes.append(waitingMinutes) # The cnt array consists of the number of requests made for a particular request time # eg. 3 people made a request to leave at 4:30 cnt.append(count) totalLeftOverTime = 0 noOfLeftOvers = 0 for k in range(len(leftOver)): totalLeftOverTime += leftOver[k][0] noOfLeftOvers += leftOver[k][1] totalWaitingTime = sum(totalWaitingMinutes) + totalLeftOverTime averageWaitingTime = totalWaitingTime / (sum(cnt) + noOfLeftOvers) return averageWaitingTime,