Exemplo n.º 1
0
def addExtras(quintuplets: list, leftoverStudents: list, matchBefore: dict):
    for student in leftoverStudents:
        index = -1      #The index of the group the student will add onto
        maxScore = -20000 #The max score group that the student would like

        for i in range(len(quintuplets)):
            if len(quintuplets[i]) != 5:
                #Skip this index because its not a valid group of five
                continue
            
            #Test whether the group has matched before
            tempList = [student]
            tempList.extend(quintuplets[i])
            if isValidGroup(matchBefore, tempList) == 0:
                #The group is valid so you may commence
                tempScore = scoreGroupByOne(student, quintuplets[i], matchBefore)
                if tempScore > maxScore:
                    index = i
                    maxScore = tempScore
        
        if index == -1:
            print("Error: literally could not find student a group to match to, so I stuck the student in the first group")
            index = 0
        
        quintuplets[index].append(student)
    
    return quintuplets
Exemplo n.º 2
0
def makeQuads(students: dict, matchDict: dict, pairs: list):
    #Make a copy that won't change the orignal students
    extraStudents = []

    for pair in pairs:
        extraStudents.append(pair)
        
    quads = []

    #Control mechanisms for the loop: check if all the pairs been put into quads
    finished = False
    if len(extraStudents) == 0:
        finished = True
    i = 0
    
    #You don't want to loop too many times, but run five times at most to find good matches that have not matched before
    while(not finished and i < 10):
        preferenceList = preferenceSymmetricalSort(extraStudents, "TwoByTwo", matchDict)
        game = StableRoommates.create_from_dictionary(preferenceList)
        ans = game.solve()

        
        #remove the students who did not find matches out, delete them from the ans dict
        extraStudents = removeImpossibleTwo(ans, matchDict, students, pairs, extraStudents)
        
        #Take the remaining, succesful students, and place them into pairs
        moveStudentsTwo(ans, quads, students, pairs)

        #Update your controls
        if len(extraStudents) == 0:
            finished = True
        i = i + 1
    
    for index in range(5):
        listUsedIndexes = list()
        pairsToMake = list()
        for index1 in range(len(extraStudents)):
            for index2 in range(len(extraStudents)):
                if index1 != index2 and (index1 not in listUsedIndexes) and (index2 not in listUsedIndexes):
                    if isValidGroup(matchDict, [extraStudents[index1][0], extraStudents[index1][1], extraStudents[index2][0], extraStudents[index2][1]]) == 0:
                        listUsedIndexes.append(index1)
                        listUsedIndexes.append(index2)
                        pairsToMake.append([index1, index2])

        usedStudents = list()
        for pairToMake in pairsToMake:
            quads.append([extraStudents[pairToMake[0]][0], extraStudents[pairToMake[0]][1], extraStudents[pairToMake[1]][0], extraStudents[pairToMake[1]][1]])
            usedStudents.extend([extraStudents[pairToMake[0]], extraStudents[pairToMake[1]]])
        

        for student in usedStudents:
            extraStudents.remove(student)

    #Now do random
    for index in range(0, len(extraStudents), 2):
        quads.append([extraStudents[index][0], extraStudents[index][1], extraStudents[index+1][0], extraStudents[index+1][1]])
    extraStudents.clear()

    return quads
Exemplo n.º 3
0
def removeImpossibleTwo(game: dict, matchDict: dict, students: dict, pairs: list, studentSupposedToBeMatched: list):
    #create an empty list to store all the removed students
    extraStudents = []

    #I can't change the dict size while its going, so I need to record all the keys to take out in the iteration
    keysToTakeOut = []

    #The game ignores people it did not match, so if someone is supposed to matched and isn't, move them back into extra students
    for pair in studentSupposedToBeMatched:
        flag = False
        for key in game:
            if students[int(str(key))] in pair:
                flag = True
                break
        if not flag:
            extraStudents.append(pair)

    for key in game:
        if key != None and game[key]!= None:
            #only want to make a list of both students if they exist
            tempList = [0] * 4
            student1 = students[int(str(key))]
            student2 = students[int(str(game[key]))]

            for pair in pairs:
                flag1 = False
                flag2 = False
                if student1 in pair:
                    flag1 = True
                    tempList[0] = pair[0]
                    tempList[1] = pair[1]
                if student2 in pair:
                    flag2 = True
                    tempList[2] = pair[0]
                    tempList[3] = pair[1]
                if flag1 and flag2:
                    break
            
            #If the two people cannot be in the group, then we are going to remove the first person
            if isValidGroup(matchDict, tempList) != 0:
                #Delete both people from the list and move them into extraStudents
                keysToTakeOut.append(key)
            

    for key in keysToTakeOut:
        #Need to add back both students in the pair
        for pair in pairs:
            #Find the pair that corresponds to this key
            #Should probably make pair into a dictionary later
            if students[int(str(key))] in pair:
                extraStudents.append(pair)
                break
        game.pop(key)

    return extraStudents
Exemplo n.º 4
0
def scoreOneByOne(student1: Student, student2: Student, matchDict: dict):

    #Assign weights to the priorty list
    scoreWeights = [50, 30, 15, 5, 0]
    score = 0

    if matchPartner(student1, student2) > 0 and matchPartner(
            student2, student1) > 0:
        score += 40000

    for i in range(4):
        #IF the priority list hits default, score no further
        if student1.priorityList[i] == "default":
            break
        #If the student priority is matched, add its weight to the score
        elif student1.priorityList[i] == "International":
            if matchInternational(student1, student2):
                score = score + scoreWeights[i]
        elif student1.priorityList[i] == "Language":
            if matchLanguage(student1, student2):
                score = score + scoreWeights[i]
        elif student1.priorityList[i] == "Matching Time to Meet":
            if matchTime(student1, student2):
                score = score + scoreWeights[i]
        elif student1.priorityList[i] == "What They Want to Do":
            if matchActivity(student1, student2):
                score = score + scoreWeights[i]
        elif student1.priorityList[i] == "Gender":
            if matchGender(student1, student2):
                score = score + scoreWeights[i]
        else:
            print(
                "Error, this index of the priority list does not meet any acceptable criteria",
                student1.name, i)

    #If the two students have matched before, punish it harshly in score
    #The punishment needs to be high enough to make groups with only one match still poor
    tempList = [student1, student2]
    score = score - 2000 * isValidGroup(matchDict, tempList)

    return score
Exemplo n.º 5
0
def removeImpossibleOne(game: dict, matchDict: dict, students: dict,
                        studentsSupposedToBeMatched: list):
    #create an empty list to store all the removed students
    extraStudents = []

    #I can't change the dict size while its going, so I need to record all the keys to take out in the iteration
    keysToTakeOut = []

    #The game ignores people it did not match, so if someone is supposed to matched and isn't, move them back into extra students
    for student in studentsSupposedToBeMatched:
        flag = False
        for key in game:
            if students[int(str(key))] == student:
                flag = True
                break
        if not flag:
            extraStudents.append(student)

    for key in game:
        if game[key] == "":
            keysToTakeOut.append(key)
            continue

        #only want to make a list of both students if they exist
        if key != None and game[key] != None:
            listStudents = [
                students[int(str(key))], students[int(str(game[key]))]
            ]

            #If the two people cannot be in the group, then we are going to remove the first person
            if isValidGroup(matchDict, listStudents) != 0:
                #Delete both people from the list and move them into extraStudents
                keysToTakeOut.append(key)
                continue

    #For each key to take out, add that student to extraStudents
    for key in keysToTakeOut:
        extraStudents.append(students[int(str(key))])
        game.pop(key)

    return extraStudents
Exemplo n.º 6
0
def removeImpossibleQuin(ans: dict, matchDict: dict, students: dict, aloneStudents:dict, aloneSupposedToBeMatched:list, quadSupposedToBeMatched: list):
    remainingAlone = []
    remainingQuads = []

    #If the remaing along and quads from supposed to be matching do not show up in the ans, place them back to be matched
    for student in aloneSupposedToBeMatched:
        for key in ans:
            flag = False
            if aloneStudents[int(str(key))] == student:
                flag = True
                break
        if not flag:
            remainingAlone.append(student)

    for quad in quadSupposedToBeMatched:
        for key in ans:
            flag = False
            if students[int(str(ans[key]))] in quad:
                flag = True
                break
        if not flag:
            remainingQuads.append(quad)

    keysToTakeOut = []

    #For the rest, check to make sure the pairing is valid
    for key in ans:
        if key != None and ans[key] != None:
            tempList = [aloneStudents[int(str(key))]]
            quadStudent = students[int(str(ans[key]))]

            flagQuad = False
            for quad in quadSupposedToBeMatched:
                if quadStudent in quad:
                    tempList.extend(quad)
                    flagQuad = True
                    break

            if flagQuad == False:
                print("Could not find quad in removeimpossible")

            if isValidGroup(matchDict, tempList) != 0:
                keysToTakeOut.append(key)
            
    for key in keysToTakeOut:
        #Find the students that correspond to these keys
        remainingAlone.append(aloneStudents[int(str(key))])

        quadStudent = students[int(str(ans[key]))]
        for quad in quadSupposedToBeMatched:
            if quadStudent in quad:
                remainingQuads.append(quad)
                break
        ans.pop(key)
    
    aloneSupposedToBeMatched.clear()
    quadSupposedToBeMatched.clear()

    aloneSupposedToBeMatched.extend(remainingAlone)
    quadSupposedToBeMatched.extend(remainingQuads)

    return 
Exemplo n.º 7
0
def makePairs(students: dict, matchDict: dict):
    #Make a copy that won't change the orignal students
    extraStudents = []

    for student in students:
        extraStudents.append((students[student]))
        
    pairs = []

    #Control mechanisms for the loop: check if all the students have been paired, and that the list has not been 
    finished = False
    if len(extraStudents) == 0:
        finished = True
    
    i = 0
    #You don't want to loop too many times, but run five times at most to find good matches that have not matched before
    while(not finished and i < 10):
        preferenceList = preferenceSymmetricalSort(extraStudents, "OneByOne", matchDict)
        game = StableRoommates.create_from_dictionary(preferenceList)
        ans = game.solve()
        
        #remove the students who did not find matches out, delete them from the ans dict
        extraStudents = removeImpossibleOne(ans, matchDict, students, extraStudents)

        #Take the remaining, succesful students, and place them into pairs
        moveStudentsOne(ans, pairs, students)

        #Update your controls
        if len(extraStudents) == 0:
            finished = True
            break

        i = i + 1
    
    for index in range(5):
        listUsedIndexes = list()
        pairsToMake = list()
        for index1 in range(len(extraStudents)):
            for index2 in range(len(extraStudents)):
                if index1 != index2 and (index1 not in listUsedIndexes) and (index2 not in listUsedIndexes):
                    if isValidGroup(matchDict, [extraStudents[index1], extraStudents[index2]]) == 0:
                        listUsedIndexes.append(index1)
                        listUsedIndexes.append(index2)
                        pairsToMake.append([index1, index2])

        usedStudents = list()
        for pairToMake in pairsToMake:
            pairs.append([extraStudents[pairToMake[0]], extraStudents[pairToMake[1]]])
            usedStudents.extend([extraStudents[pairToMake[0]], extraStudents[pairToMake[1]]])
        

        for student in usedStudents:
            extraStudents.remove(student)


    if len(extraStudents)%2 == 1:
        print("Problem: odd number of students in extraStudents")

    #Match the rest of the students randomly and print that the matching sucked
    for index in range(0, len(extraStudents), 2):
        if (index+1) < len(extraStudents):
            pairs.append([extraStudents[index], extraStudents[index+1]])
    extraStudents.clear()

    
    #Return the pairs list (list[Student, Student])
    return pairs
Exemplo n.º 8
0
def makeQuintuplets(quads: list, aloneStudents: dict, singles: dict, matchBefore: dict):
    #Each quad needs to match with one alone Student
    #make an empty list to avoid changing quads and aloneStudents
    extraStudentsQuads = []
    extraStudentsAlone = []
    for quad in quads:
        extraStudentsQuads.append(quad)
    for key in aloneStudents:
        extraStudentsAlone.append(aloneStudents[key])

    quintuplets = []

    finished = False
    if len(extraStudentsAlone) != len(extraStudentsQuads):
        print("Error: size mismatch in makeQuintuplets")
    if len(extraStudentsAlone) == 0:
        finished = True
    i = 0

    while (not finished) and i < 5:
        preferenceListOnes = preferenceAsymmetricalSort(extraStudentsAlone, extraStudentsQuads, "GroupByOne", matchBefore)
        preferenceListQuads = preferenceAsymmetricalSort(extraStudentsQuads, extraStudentsAlone, "OneByGroup", matchBefore)
        
        game = StableMarriage.create_from_dictionaries(preferenceListOnes, preferenceListQuads)
        ans = game.solve()

        
        removeImpossibleQuin(ans, matchBefore, singles, aloneStudents, extraStudentsAlone, extraStudentsQuads)
        
        moveStudentsGroups(quintuplets, ans, singles, aloneStudents, quads)
        
        if len(extraStudentsAlone) == 0:
            finished = True
        i = i+ 1

        if len(extraStudentsAlone) != len(extraStudentsQuads):
            print("Errror: size mismatch in makeQuintuplets")

    
    listUsedIndexesAlone = list()
    listUsedIndexesQuads = list()
    groupsToMake = list()
    for index1 in range(len(extraStudentsAlone)):
        for index2 in range(len(extraStudentsQuads)):
            if index1 not in listUsedIndexesAlone and index2 not in listUsedIndexesQuads:
                tempList = [(extraStudentsAlone[index1])]
                tempList.extend(extraStudentsQuads[index2])
                if isValidGroup(matchBefore, tempList) == 0:
                    listUsedIndexesAlone.append(index1)
                    listUsedIndexesQuads.append(index2)
                    groupsToMake.append([index1, index2])
    
    usedAlone = list()
    usedQuads = list()
    for groupToMake in groupsToMake:
        tempList = [extraStudentsAlone[groupToMake[0]]]
        tempList.extend(extraStudentsQuads[groupToMake[1]])
        quintuplets.append(tempList)
        usedAlone.append(extraStudentsAlone[groupToMake[0]])
        usedQuads.append(extraStudentsQuads[groupToMake[1]])

    for student in usedAlone:
        extraStudentsAlone.remove(student)
    
    for student in usedQuads:
        extraStudentsQuads.remove(student)

    for index in range(0, len(extraStudentsAlone)):
        tempList = extraStudentsQuads[index]
        tempList.append(extraStudentsAlone[index])
        quintuplets.append(tempList)
    
    extraStudentsAlone.clear()
    extraStudentsQuads.clear()
    
    return quintuplets
Exemplo n.º 9
0
def gradeGroups(groups: list, matchBefore: dict):

    #Count the number of students who did or did not take the survey
    defaultStudents = 0
    studentsTakeSurvey = 0

    #Count the number of students who succesfully got a gender match out of the ones who wanted it
    studentsGenderMatch = 0
    studentsWantGenderMatch = 0

    #Count the number of students who wanted asynch/synch and got a match in their group
    studentsWantTime = 0
    studentsGotTime = 0

    #Count the number of groups and the valid groups
    numGroups = 0
    numValidGroups = 0

    #Count the number of groups with a leader personality
    groupsGotLeader = 0

    #Count the number of students who wanted another international student and got it
    studentsWantInternational = 0
    studentsGotInternational = 0

    #Count all the students who got their preferred language
    studentsGotLanguage = 0

    #Count all the students who got their preferred activity
    studentsGotOption = 0

    #Count which priority the students got first
    #If both second choice and first are met on one student, only firstChoice increases
    studentGotChoice = [0, 0, 0, 0, 0, 0]

    #Count the number of groups where there are people of multiple confidence levels
    numGroupsMixConfidence = 0

    #Iterate through each group
    for group in groups:
        #Increment the number of overall Groups
        numGroups = numGroups + 1

        #increment valid group if the groups are valid
        if isValidGroup(matchBefore, group) == 0:
            numValidGroups = numValidGroups + 1

        #increment confidenceLevels if group has a mixture of high to low confidence
        if scoreAtLeastOneConfidenceLevel(group) > 0:
            numGroupsMixConfidence = numGroupsMixConfidence + 1

        #a flag that becomes true if anyone in the group is a leader
        flagLeader = False

        #The others are by person
        for person in group:
            #Flags to control what the person does and does not get
            flagGender = False
            flagTime = False
            flagInternational = False
            flagLanguage = False
            flagOption = False

            #Default students should not affect stats
            if person.pronouns == "default/defaults":
                defaultStudents = defaultStudents + 1
                continue
            else:
                studentsTakeSurvey = studentsTakeSurvey + 1

            #if anyone in the group is a leader, the whole group gets a leader
            if person.preferLeader == True:
                flagLeader = True

            #check this person based on the rest of the group
            for person2 in group:
                #Don't check a person against themself
                if person != person2:

                    #Gender
                    if matchGender(person, person2):
                        flagGender = True

                    #Time
                    if matchTime(person, person2):
                        flagTime = True

                    #International
                    if matchInternational(person, person2):
                        flagInternational = True

                    #Language
                    if person.language == person2.language:
                        flagLanguage = True

                    #Option
                    if person.option1 == person2.option1:
                        flagOption = True

            #Only count the person if the person wanted to match on gender
            if person.preferSame != 1:
                studentsWantGenderMatch = studentsWantGenderMatch + 1
                if flagGender:
                    studentsGenderMatch = studentsGenderMatch + 1

            #Only count the person if the person wanted to match on time
            if person.preferAsy != 1:
                studentsWantTime = studentsWantTime + 1
                if flagTime:
                    studentsGotTime = studentsGotTime + 1

            #Only count the person if the person wanted to match on international
            if person.international == 2:
                studentsWantInternational = studentsWantInternational + 1
                if flagInternational:
                    studentsGotInternational = studentsGotInternational + 1

            #The student matched at least one other person on language
            if flagLanguage:
                studentsGotLanguage = studentsGotLanguage + 1

            #The student matched at least one other person on activity
            if flagOption:
                studentsGotOption = studentsGotOption + 1

            #Find the highest priority that the student managed to get
            for i in range(5):
                #If at any point, they default, ignore the rest of their opinions
                if person.priorityList[i] == "default":
                    break
                elif person.priorityList[i] == "Gender":
                    if flagGender:
                        studentGotChoice[i] = studentGotChoice[i] + 1
                        break
                elif person.priorityList[i] == "International":
                    if flagInternational:
                        studentGotChoice[i] = studentGotChoice[i] + 1
                        break
                elif person.priorityList[i] == "Language":
                    if flagLanguage:
                        studentGotChoice[i] = studentGotChoice[i] + 1
                        break
                elif person.priorityList[i] == "What They Want to Do":
                    if flagOption:
                        studentGotChoice[i] = studentGotChoice[i] + 1
                        break
                elif person.priorityList[i] == "Matching Time to Meet":
                    if flagTime:
                        studentGotChoice[i] = studentGotChoice[i] + 1
                        break

        #If any student flagged as a leader, the group has a leader
        if flagLeader:
            groupsGotLeader = groupsGotLeader + 1

    print(studentsTakeSurvey, " of students took the survey while ",
          defaultStudents, " did not take it.")
    print("Group who got leader: " +
          str((100 * (groupsGotLeader / numGroups))) + "%")
    print("Group who got confidence: " +
          str((100 * (numGroupsMixConfidence / numGroups))) + "%")
    print("Students who got gender match: " +
          str((100 * (studentsGenderMatch / studentsWantGenderMatch))) + "%")
    print("Students who got time: " +
          str((100 * (studentsGotTime / studentsWantTime))) + "%")
    print("Students who got international: " +
          str((100 *
               (studentsGotInternational / studentsWantInternational))) + "%")
    print("Students who got language: " +
          str((100 * (studentsGotLanguage / studentsTakeSurvey))) + "%")
    print("Students who got activity: " +
          str((100 * (studentsGotOption / studentsTakeSurvey))) + "%")
    print()
    print("First choice: ", studentGotChoice[0])
    print("Second choice: ", studentGotChoice[1])
    print("Third choice: ", studentGotChoice[2])
    print("Fourth choice: ", studentGotChoice[3])
    print("Fifth choice: ", studentGotChoice[4])

    studentGotNoChoice = studentsTakeSurvey - sum(studentGotChoice)

    print("\nGroups that are valid: " + str(numValidGroups / numGroups * 100) +
          "%")
    print()