def mutate(schedl, randGen): newSched = copy.deepcopy(schedl) searchingForTwoEntries = 1 mutationCount = randGen.randint(1, MAX_MUTATIONS_PER_SCHEDULE) index1 = 0 index2 = 0 tempEntry = {} #start = time.time() for x in list(range(mutationCount)): searchingForTwoEntries = 1 while searchingForTwoEntries: index1 = randGen.randint(0, len(newSched['lst']) - 1) index2 = randGen.randint(0, len(newSched['lst']) - 1) #TODO add swapping when one of the random slots doesnt have an entry yet if index1 != index2 and \ 'entry' in newSched['lst'][index1] and \ 'entry' in newSched['lst'][index2] and \ newSched['lst'][index1]['catShort'] == newSched['lst'][index2]['catShort']: searchingForTwoEntries = 0 #end loop tempEntry = newSched['lst'][index1]['entry'] newSched['lst'][index1]['entry'] = newSched['lst'][index2]['entry'] newSched['lst'][index2]['entry'] = tempEntry #end loop schedFitness.fitnessTest(newSched, False) #entryCount = 0 #for sched in newSched: # if 'entry' in sched: # entryCount += 1 #if entryCount != len(entriesList): # sys.exit('Entry count fail after 3mut') #end = time.time() #print ('Mut %d %f' % (mutationCount,(end - start))) #if checkSchedForDupes(newSched): # schedIO.printSched(newSched, 'newSched.txt') # sys.exit('Got mutated dupes printed newSched') return newSched
def mutate (schedl, randGen): newSched = copy.deepcopy(schedl) searchingForTwoEntries = 1 mutationCount = randGen.randint(1,MAX_MUTATIONS_PER_SCHEDULE) index1 = 0 index2 = 0 tempEntry = {} #start = time.time() for x in list(range(mutationCount)): searchingForTwoEntries = 1 while searchingForTwoEntries: index1 = randGen.randint(0, len(newSched['lst'])-1) index2 = randGen.randint(0, len(newSched['lst'])-1) #TODO add swapping when one of the random slots doesnt have an entry yet if index1 != index2 and \ 'entry' in newSched['lst'][index1] and \ 'entry' in newSched['lst'][index2] and \ newSched['lst'][index1]['catShort'] == newSched['lst'][index2]['catShort']: searchingForTwoEntries = 0 #end loop tempEntry = newSched['lst'][index1]['entry'] newSched['lst'][index1]['entry'] = newSched['lst'][index2]['entry'] newSched['lst'][index2]['entry'] = tempEntry #end loop schedFitness.fitnessTest(newSched, False) #entryCount = 0 #for sched in newSched: # if 'entry' in sched: # entryCount += 1 #if entryCount != len(entriesList): # sys.exit('Entry count fail after 3mut') #end = time.time() #print ('Mut %d %f' % (mutationCount,(end - start))) #if checkSchedForDupes(newSched): # schedIO.printSched(newSched, 'newSched.txt') # sys.exit('Got mutated dupes printed newSched') return newSched
def scheduleSex(baseParent, donorParent, randGen): #A new child schedule is created by first cloning the baseParent. The child #is then modified via accepting a few "traits" of the donorParent. newSched = copy.deepcopy(baseParent) searchingForEntry = 1 swapsCount = randGen.randint(1, MAX_SWAPS_PER_RHOMP) index1 = 0 index2 = -1 tempEntry = {} #start = time.time() for x in list(range(swapsCount)): searchingForEntry = 1 while searchingForEntry: index1 = randGen.randint(0, (len(newSched['lst'])) - 1) if 'entry' in newSched['lst'][index1]: searchingForEntry = 0 #end loop #print('Searching %s %s' % (newSched['lst'][index1]['entry']['school'], newSched['lst'][index1]['entry']['entryTitle'])) if 'entry' in donorParent['lst'][index1]: tempEntry = donorParent['lst'][index1]['entry'] #Now find where the entry from parent 2 is located in parent 1 for y in list(range(len(newSched['lst']))): if 'entry' in newSched['lst'][y] and \ newSched['lst'][y]['entry']['index'] == tempEntry['index']: index2 = y break else: print('newSched[\'lst\'][index1] :') print(newSched['lst'][index1]) schedIO.printSched(newSched, 'newSched.txt') #WILL FAIL schedIO.printSched(donorParent, 'donorParent.txt') checkSchedForDupes(donorParent) sys.exit("No match in donorParent") else: #donorParent has an unfilled session in that spot. Find a corresponding one in newSched newSchedIndexList = list(range(len(newSched['lst']))) randGen.shuffle(newSchedIndexList) #Randomize the list for z in newSchedIndexList: if 'entry' not in newSched['lst'][z] and \ newSched['lst'][z]['isBreak'] == False and \ newSched['lst'][z]['catShort'] == newSched['lst'][index1]['catShort']: index2 = z break #end if if index1 == index2: #The random entry to swap is already in the same place #in both parents, no need to do anything #This is possibly not needed since the swap algorithm won't #harm anything. continue if newSched['lst'][index1]['catShort'] != newSched['lst'][index2][ 'catShort']: #This algorithm assumes that for any index (q) in baseParent array, #the catagory of baseParent(q) is equal to the catagory of donorParent(q) sys.exit("Woa nelly sumthins mixed up") #Its possible that index2 doesn't have an entry. if 'entry' in newSched['lst'][index2]: tempEntry = newSched['lst'][index1]['entry'] newSched['lst'][index1]['entry'] = newSched['lst'][index2]['entry'] newSched['lst'][index2]['entry'] = tempEntry else: newSched['lst'][index2]['entry'] = newSched['lst'][index1]['entry'] del (newSched['lst'][index1]['entry']) #if checkSchedForDupes(newSched): # schedIO.printSched(newSched, 'newSched.txt') # sys.exit('Got dupes printed newSched') #entryCount = 0 #for sched in newSched: # if 'entry' in sched: # entryCount += 1 #if entryCount != len(entriesList): # sys.exit('Entry count fail after 2') #end loop schedFitness.fitnessTest(newSched, False) #end = time.time() #print ('Sex %d %f' % (swapsCount,(end - start))) return newSched
choice2ListIdx = x #print ('\nSwap entry index %d %d' % (userChoice1Idx, userChoice2Idx)) #print ('Swap array Index %d %d' % (choice1ListIdx, choice2ListIdx)) print ('Old Score %d' % schedule['score']) if swapSchool2 == 'E': schedule['lst'][choice2ListIdx]['entry'] = schedule['lst'][choice1ListIdx]['entry'] del schedule['lst'][choice1ListIdx]['entry'] else: temp1Copy = schedule['lst'][choice1ListIdx]['entry'] schedule['lst'][choice1ListIdx]['entry'] = schedule['lst'][choice2ListIdx]['entry'] schedule['lst'][choice2ListIdx]['entry'] = temp1Copy schedFitness.fitnessTest (schedl = schedule, \ saveReport = False) newSchedFolder = os.path.join(schedDir, 'edits', str(int(schedule['score']))) tempDir = newSchedFolder while os.path.isdir(tempDir): tempDir = newSchedFolder + folderChar folderChar = chr(ord(folderChar) + 1) newSchedFolder = tempDir schedIO.printSched (schedule = schedule, \ schoolInf = schoolInfo, \ entriesLst = entryList, \ outFolder = newSchedFolder) schedFitness.fitnessTest (schedl = schedule, \ saveReport = True, \
def createRandomSchedules(scheduleList, sessions, entries, randGen, maxCount=None): #Schedule looks like this: #{'score' : 25402, # 'lst' : # {'category' : 'Group Mime', # 'catShort' : 'GM', # 'start' : 800, # 'end' : 805, # 'room' : '132', # 'duration' : 10, # 'entry' : # {'school' : 'Kim Jong Il The Reformer North High', # 'code' : 'X4', # 'driveTime' : 50, # 'deps' : 'cy', # 'catShort' : 'GM'}, # 'isBreak' : False} randFailCount = 0 generatedSchedCount = 0 sessionsOk = 1 for x in range(len(scheduleList)): if maxCount != None and generatedSchedCount == maxCount: break if scheduleList[x]['lst'] != None: #Only fill in the blank array slots continue # with new random schedules randSched = copy.deepcopy(sessions) #Keep a seperate array whose elements are indexes into the sessions array. As #sessions are filled, remove that session from the list. This way the random #generator doesn't pick more and more already-filled sessions as the list of #available slots gets smaller. scratchList = list(range(len(sessions))) #Looks like [0,1,2,3,4, ... ] for item in entries: failedTrys = 0 placedItem = 0 #Find the starting and ending session index for this entry's catagory. This #way the random picker can select from a limited set instead of the whole #schedule. Can't just use the categoryIndexes dict because we are working #from the scratchlist here. foundStart = 0 startIdx = 0 endIdx = len(scratchList)-1 for scratchIdx in range(len(scratchList)): if not foundStart and randSched[scratchList[scratchIdx]]['catShort'] == item['catShort']: startIdx = scratchIdx foundStart = True elif foundStart and randSched[scratchList[scratchIdx]]['catShort'] != item['catShort']: endIdx = scratchIdx-1 break #print ('%s Start %d End %d' % (item['catShort'], startIdx, endIdx)) #end loop while 1: #Pick a random spot in the scratchlist randomIdx = randGen.randint(startIdx, endIdx) randomSessionIdx = scratchList[randomIdx] #print('Length %d Rand %d Cat %s' % (len(scratchList), scratchList[randomIdx], randSched[randomSessionIdx]['catShort'])) #See if that session is eligable for this entry. if randSched[randomSessionIdx]['catShort'] == item['catShort'] and \ randSched[randomSessionIdx]['isBreak'] == False: randSched[randomSessionIdx]['entry'] = item #Found a good match. Schedule it. del scratchList[randomIdx] #Remove this session from the available list placedItem = 1 break else: failedTrys += 1 #end if if failedTrys >= MAX_FAILED_TRYS_COUNT: randFailCount += 1 break #end loop if not placedItem: #Iterate thru all the list at this point to ensure the #random picker didn't miss 1 available slot. for y, idx in enumerate(scratchList): if randSched[idx]['catShort'] == item['catShort'] and \ randSched[idx]['isBreak'] == False: randSched[idx]['entry'] = item #Found a good match. Schedule it. del scratchList[y] #Remove this session from the available list placedItem = 1 break #end if #end loop #end if if not placedItem: print (item) print ('Not enough sessions for cateagory %s\n' % item['catShort']) sessionsOk = 0 #end entry loop #entryCount = 0 #for sched in randSched: # if 'entry' in sched: # entryCount += 1 #if entryCount != len(entriesList): # sys.exit('Entry count fail after 5rdm') #end entry loop scheduleList[x]['lst'] = randSched schedFitness.fitnessTest(scheduleList[x], False) generatedSchedCount += 1 #end schedule loop if sessionsOk != 1: sys.exit('Sessions file needs work. Exiting.') return randFailCount
def scheduleSex(baseParent, donorParent, randGen): #A new child schedule is created by first cloning the baseParent. The child #is then modified via accepting a few "traits" of the donorParent. newSched = copy.deepcopy(baseParent) searchingForEntry = 1 swapsCount = randGen.randint(1,MAX_SWAPS_PER_RHOMP) index1 = 0 index2 = -1 tempEntry = {} #start = time.time() for x in list(range(swapsCount)): searchingForEntry = 1 while searchingForEntry: index1 = randGen.randint(0, (len(newSched['lst']))-1) if 'entry' in newSched['lst'][index1]: searchingForEntry = 0 #end loop #print('Searching %s %s' % (newSched['lst'][index1]['entry']['school'], newSched['lst'][index1]['entry']['entryTitle'])) if 'entry' in donorParent['lst'][index1]: tempEntry = donorParent['lst'][index1]['entry'] #Now find where the entry from parent 2 is located in parent 1 for y in list(range(len(newSched['lst']))): if 'entry' in newSched['lst'][y] and \ newSched['lst'][y]['entry']['index'] == tempEntry['index']: index2 = y break else: print ('newSched[\'lst\'][index1] :') print (newSched['lst'][index1]) schedIO.printSched(newSched, 'newSched.txt') #WILL FAIL schedIO.printSched(donorParent, 'donorParent.txt') checkSchedForDupes(donorParent) sys.exit ("No match in donorParent") else: #donorParent has an unfilled session in that spot. Find a corresponding one in newSched newSchedIndexList = list(range(len(newSched['lst']))) randGen.shuffle (newSchedIndexList) #Randomize the list for z in newSchedIndexList: if 'entry' not in newSched['lst'][z] and \ newSched['lst'][z]['isBreak'] == False and \ newSched['lst'][z]['catShort'] == newSched['lst'][index1]['catShort']: index2 = z break #end if if index1 == index2: #The random entry to swap is already in the same place #in both parents, no need to do anything #This is possibly not needed since the swap algorithm won't #harm anything. continue if newSched['lst'][index1]['catShort'] != newSched['lst'][index2]['catShort']: #This algorithm assumes that for any index (q) in baseParent array, #the catagory of baseParent(q) is equal to the catagory of donorParent(q) sys.exit ("Woa nelly sumthins mixed up") #Its possible that index2 doesn't have an entry. if 'entry' in newSched['lst'][index2]: tempEntry = newSched['lst'][index1]['entry'] newSched['lst'][index1]['entry'] = newSched['lst'][index2]['entry'] newSched['lst'][index2]['entry'] = tempEntry else: newSched['lst'][index2]['entry'] = newSched['lst'][index1]['entry'] del(newSched['lst'][index1]['entry']) #if checkSchedForDupes(newSched): # schedIO.printSched(newSched, 'newSched.txt') # sys.exit('Got dupes printed newSched') #entryCount = 0 #for sched in newSched: # if 'entry' in sched: # entryCount += 1 #if entryCount != len(entriesList): # sys.exit('Entry count fail after 2') #end loop schedFitness.fitnessTest(newSched, False) #end = time.time() #print ('Sex %d %f' % (swapsCount,(end - start))) return newSched
if jobCurrentSize == jobMaxSize - 10: logger.msg('*') #This is a good time to do work while waiting for the child procs to finish #Print out the best score every so often if time.time() - lastScorePrintTime > config['BEST_SCORE_PRINT_MINS'] * 60: if stageNum == 1 and len(topScores) > 0: (lowestScore, lowestScoreIdx) = computeTopScore (topScores) scorePrintFolder = os.path.join(outFolder, str(math.floor(lowestScore))) if not os.path.exists(scorePrintFolder): schedIO.printSched (schedule = topScores[lowestScoreIdx], \ schoolInf = schoolInfo, \ outFolder = scorePrintFolder) schedFitness.fitnessTest (schedl = topScores[lowestScoreIdx], \ saveReport = True, \ fileName = os.path.join(scorePrintFolder, 'FitnessReport.txt')) validateSched(topScores[lowestScoreIdx], sessionList, entriesList, logger) elif stageNum == 2 and len(rdm) > 0: (lowestScore, lowestScoreIdx) = computeTopScore (rdm) scorePrintFolder = os.path.join(outFolder, str(math.floor(lowestScore))) if not os.path.exists(scorePrintFolder): schedIO.printSched (schedule = rdm[lowestScoreIdx], \ schoolInf = schoolInfo, \ outFolder = scorePrintFolder) schedFitness.fitnessTest (schedl = rdm[lowestScoreIdx], \ saveReport = True, \ fileName = os.path.join(scorePrintFolder, 'FitnessReport.txt')) validateSched(rdm[lowestScoreIdx], sessionList, entriesList, logger) lastScorePrintTime = time.time()
def createRandomSchedules(scheduleList, sessions, entries, randGen, maxCount=None): #Schedule looks like this: #{'score' : 25402, # 'lst' : # {'category' : 'Group Mime', # 'catShort' : 'GM', # 'start' : 800, # 'end' : 805, # 'room' : '132', # 'duration' : 10, # 'entry' : # {'school' : 'Kim Jong Il The Reformer North High', # 'code' : 'X4', # 'driveTime' : 50, # 'deps' : 'cy', # 'catShort' : 'GM'}, # 'isBreak' : False} randFailCount = 0 generatedSchedCount = 0 sessionsOk = 1 for x in range(len(scheduleList)): if maxCount != None and generatedSchedCount == maxCount: break if scheduleList[x]['lst'] != None: #Only fill in the blank array slots continue # with new random schedules randSched = copy.deepcopy(sessions) #Keep a seperate array whose elements are indexes into the sessions array. As #sessions are filled, remove that session from the list. This way the random #generator doesn't pick more and more already-filled sessions as the list of #available slots gets smaller. scratchList = list(range(len(sessions))) #Looks like [0,1,2,3,4, ... ] for item in entries: failedTrys = 0 placedItem = 0 #Find the starting and ending session index for this entry's catagory. This #way the random picker can select from a limited set instead of the whole #schedule. Can't just use the categoryIndexes dict because we are working #from the scratchlist here. foundStart = 0 startIdx = 0 endIdx = len(scratchList) - 1 for scratchIdx in range(len(scratchList)): if not foundStart and randSched[scratchList[scratchIdx]][ 'catShort'] == item['catShort']: startIdx = scratchIdx foundStart = True elif foundStart and randSched[scratchList[scratchIdx]][ 'catShort'] != item['catShort']: endIdx = scratchIdx - 1 break #print ('%s Start %d End %d' % (item['catShort'], startIdx, endIdx)) #end loop while 1: #Pick a random spot in the scratchlist randomIdx = randGen.randint(startIdx, endIdx) randomSessionIdx = scratchList[randomIdx] #print('Length %d Rand %d Cat %s' % (len(scratchList), scratchList[randomIdx], randSched[randomSessionIdx]['catShort'])) #See if that session is eligable for this entry. if randSched[randomSessionIdx]['catShort'] == item['catShort'] and \ randSched[randomSessionIdx]['isBreak'] == False: randSched[randomSessionIdx][ 'entry'] = item #Found a good match. Schedule it. del scratchList[ randomIdx] #Remove this session from the available list placedItem = 1 break else: failedTrys += 1 #end if if failedTrys >= MAX_FAILED_TRYS_COUNT: randFailCount += 1 break #end loop if not placedItem: #Iterate thru all the list at this point to ensure the #random picker didn't miss 1 available slot. for y, idx in enumerate(scratchList): if randSched[idx]['catShort'] == item['catShort'] and \ randSched[idx]['isBreak'] == False: randSched[idx][ 'entry'] = item #Found a good match. Schedule it. del scratchList[ y] #Remove this session from the available list placedItem = 1 break #end if #end loop #end if if not placedItem: print(item) print('Not enough sessions for cateagory %s\n' % item['catShort']) sessionsOk = 0 #end entry loop #entryCount = 0 #for sched in randSched: # if 'entry' in sched: # entryCount += 1 #if entryCount != len(entriesList): # sys.exit('Entry count fail after 5rdm') #end entry loop scheduleList[x]['lst'] = randSched schedFitness.fitnessTest(scheduleList[x], False) generatedSchedCount += 1 #end schedule loop if sessionsOk != 1: sys.exit('Sessions file needs work. Exiting.') return randFailCount
jobMinSize = 10 jobSizeIncr = 10 lastScorePrintTime = time.time() logger.msg('Start Main Loop') jobCurrentSize = jobMinSize #DEBUG for getting a quick printout schedIO.printSched (schedule = rdm[2], \ schoolInf = schoolInfo, \ entriesLst = entriesList, \ outFolder = outFolder + '/xx') schedFitness.fitnessTest (schedl = rdm[2], \ saveReport = True, \ fileName = os.path.join(outFolder + '/xx', 'FitnessReport.txt')) if dryRunMode: logger.msg('Finished dry run') exit() while True: parentsList = findParentSchedules(rdm, jobCurrentSize, randGenMain) for x in parentsList: taskQueue.put({ 'cmd': 'XOver', 'idx': x[0], 'sch1': rdm[x[0]], 'sch2': rdm[x[1]] })