def hopkroft(graph, structure):
    transformed_graph = {}

    supervisors = graph.getEdges()
    students = graph.getStuEdges()
    correspondence = {}
    sup_name = 0
    list_supervisors = [supervisor for supervisor in supervisors]
    list_students = [student for student in students]
    random.shuffle(list_supervisors)
    random.shuffle(list_students)
    a_to_b = {}
    for i in range(len(list_students)):
        a_to_b[list_students[i]] = 'stu' + str(i)

    for supervisor in list_supervisors:
        cardinality = structure[supervisor]
        for i in range(cardinality):
            for stu in supervisors[supervisor]:
                transformed_graph.setdefault(sup_name, set()).add(a_to_b[stu])
            correspondence[sup_name] = supervisor
            sup_name = sup_name + 1
    m = HopcroftKarp(transformed_graph).maximum_matching()

    result = BipartiteGraph()
    for student in students:
        sup_code = m[a_to_b[student]]
        result.addEdge(correspondence[sup_code], student)
    return result
Example #2
0
    def test_case3(self):
        """Testing addEdge function when adding an edge that already exists"""

        graph = BipartiteGraph()
        graph.addEdge("supervisor1", "student1")
        graph.addEdge("supervisor1", "student1")

        val1 = graph.getSupervisorDegree("supervisor1")
        val2 = graph.getStudentDegree("student1")

        self.assertEqual((val1, val2), (1, 1))
Example #3
0
    def test_case6(self):
        """Testing the removeEdge function in a graph with existing nodes and edges"""

        graph = BipartiteGraph()

        graph.addEdge("supervisor1", "student1")
        graph.removeEdge("supervisor1", "student1")

        val1 = graph.getStudentDegree("student1")
        val2 = graph.getSupervisorDegree("supervisor1")

        self.assertEqual((val1, val2), (0, 0))
    def test_case20(self):
        """Testing the isValid function - when number of students less than actual"""

        graph = BipartiteGraph()
        
        graph.addEdge("supervisor1","student1")
        graph.addEdge("supervisor3","student3")
        graph.addEdge("supervisor2","student2")

        solution = Solution(graph)

        result = solution.isValid(self.students,self.supervisors)

        self.assertFalse(result)
Example #5
0
    def test_case1(self):
        """Testing addEdge function in an empty graph"""

        graph = BipartiteGraph()

        graph.addEdge("supervisor1", "student1")

        val1 = graph.getStudents("supervisor1")
        val2 = graph.getSupervisors("student1")

        expected1 = ["student1"]
        expected2 = ["supervisor1"]

        self.assertEqual((val1, val2), (expected1, expected2))
def uniform(solution1, solution2, supervisors, students, k=None):
    """
    An implementation of uniform crossover
    """
    graph1 = solution1.getGraph()
    graph2 = solution2.getGraph()

    stuEdges1 = graph1.getStuEdges()
    stuEdges2 = graph2.getStuEdges()

    g = BipartiteGraph()
    for stu in students:
        if random.random() < 0.5:
            sup = stuEdges1[stu][0]
        else:
            sup = stuEdges2[stu][0]
        g.addEdge(sup, stu)

    fixSolution(g, supervisors, students)
    return Solution(g)
Example #7
0
    def test_case2(self):
        """Testing addEdge function in a graph with existing nodes and edges"""

        graph = BipartiteGraph()

        graph.addEdge("supervisor1", "student1")
        graph.addEdge("supervisor2", "student4")
        graph.addEdge("supervisor3", "student3")

        val1 = graph.getSupervisorDegree("supervisor1")

        graph.addEdge("supervisor1", "student2")

        curr = graph.getSupervisorDegree("supervisor1")
        val2 = graph.getSupervisors("student2")
        expected2 = ["supervisor1"]

        self.assertEqual((curr - 1, expected2), (val1, val2))
class MutationTest(unittest.TestCase):
    def setUp(self):

        #Creating a list of students and supervisors

        topicNames, topicPaths, topicIDs, levels = parseFile(
            "pystsup/test/acm.txt")

        self.supervisors = {}
        self.students = {}

        stuID = "student"
        supID = "supervisor"

        stuList1 = [
            "MapReduce-based systems", "Multidimensional range search",
            "Open source software", "Data mining", "Online shopping"
        ]
        stuList2 = [
            "Heuristic function construction", "Multi-agent systems",
            "Open source software", "Data mining", "Speech recognition"
        ]
        stuList3 = [
            "Multi-agent systems", "Speech recognition",
            "Heuristic function construction", "Data mining",
            "Object identification"
        ]
        stuList4 = [
            "Multi-agent systems", "Intelligent agents", "Speech recognition",
            "Object identification", "Heuristic function construction"
        ]

        supList1 = [
            "Multi-agent systems", "Intelligent agents",
            "MapReduce-based systems", "Object identification",
            "Heuristic function construction"
        ]
        supList2 = [
            "Open source software", "Data mining", "Speech recognition",
            "Object identification", "Heuristic function construction"
        ]
        supList3 = [
            "Multi-agent systems", "Intelligent agents", "Speech recognition",
            "Object identification", "Heuristic function construction"
        ]

        supList = [supList1, supList2, supList3]
        supQuota = [2, 2, 1]
        stuList = [stuList1, stuList2, stuList3, stuList4]

        for i in range(3):
            toAdd = []
            sup_list = {}
            rank = 0
            for kw in supList[i]:
                rank += 1
                sup_list[rank] = [
                    kw, getPath(kw, topicNames, topicPaths, topicIDs)
                ]

            sup = supID + str(i + 1)
            quota = supQuota[i]

            supervisorObject = Supervisor(sup, sup_list, quota)

            self.supervisors[sup] = supervisorObject

        for i in range(4):
            toAdd = []
            stu_list = {}
            rank = 0
            for kw in stuList[i]:
                rank += 1
                stu_list[rank] = [
                    kw, getPath(kw, topicNames, topicPaths, topicIDs)
                ]

            stu = stuID + str(i + 1)
            studentObject = Student(stu, stu_list)
            self.students[stu] = studentObject

        # Generating rank weights for c = 0.5

        self.rankWeights = Solution.calcRankWeights()

        #Creating fitness cache

        self.dummySolution = Solution()

        self.fitnessCache = {}

        for sup in self.supervisors:
            supervisorKeywords = self.supervisors[sup].getKeywords()
            for stu in self.students:
                studentKeywords = self.students[stu].getKeywords()
                f_stu, f_sup = self.dummySolution.kw_similarity(
                    studentKeywords, supervisorKeywords, self.rankWeights)
                self.fitnessCache[str((stu, sup))] = (f_stu, f_sup)

        # Creating two graphs and solutions

        self.graph1 = BipartiteGraph()
        self.graph2 = BipartiteGraph()

        self.graph1.addEdge("supervisor1", "student2")
        self.graph1.addEdge("supervisor2", "student4")
        self.graph1.addEdge("supervisor3", "student1")
        self.graph1.addEdge("supervisor1", "student3")

        self.solution1 = Solution(self.graph1)

        self.graph2.addEdge("supervisor1", "student2")
        self.graph2.addEdge("supervisor2", "student1")
        self.graph2.addEdge("supervisor3", "student4")
        self.graph2.addEdge("supervisor1", "student3")

        self.solution2 = Solution(self.graph2)

    def test_case1(self):
        """Testing mutation function for solution 1"""
        mutationProbability = 0.3
        swapProbability = 0.5
        transferProbability = 0.5
        solution3 = mutate(self.solution1, self.supervisors,
                           mutationProbability, swapProbability,
                           transferProbability)

        result = solution3.isValid(self.students, self.supervisors)

        self.assertTrue(result)

    def test_case2(self):
        """Testing mutation function for solution 1 - only swap operation"""
        mutationProbability = 0.3
        swapProbability = 0.5
        transferProbability = 0
        solution3 = mutate(self.solution1, self.supervisors,
                           mutationProbability, swapProbability,
                           transferProbability)

        result = solution3.isValid(self.students, self.supervisors)

        self.assertTrue(result)

    def test_case3(self):
        """Testing mutation function for solution 1 - only transfer operation"""
        mutationProbability = 0.3
        swapProbability = 0
        transferProbability = 0.5
        solution3 = mutate(self.solution1, self.supervisors,
                           mutationProbability, swapProbability,
                           transferProbability)

        result = solution3.isValid(self.students, self.supervisors)

        self.assertTrue(result)

    def test_case4(self):
        """Testing mutation function for solution 2"""
        mutationProbability = 0.3
        swapProbability = 0.5
        transferProbability = 0.3
        solution4 = mutate(self.solution2, self.supervisors,
                           mutationProbability, swapProbability,
                           transferProbability)

        result = solution4.isValid(self.students, self.supervisors)

        self.assertTrue(result)

    def test_case5(self):
        """Testing mutation function for a randomly created solution 1"""

        mutationProbability = 0.3
        swapProbability = 0.2
        transferProbability = 0.8

        solution1 = Solution.generateRandomSolution(self.students,
                                                    self.supervisors)

        solution2 = mutate(solution1, self.supervisors, mutationProbability,
                           swapProbability, transferProbability)

        result = solution2.isValid(self.students, self.supervisors)

        self.assertTrue(result)

    def test_case6(self):
        """Testing mutation function for a randomly created solution 2"""

        mutationProbability = 0.3
        swapProbability = 0.7
        transferProbability = 0

        solution1 = Solution.generateRandomSolution(self.students,
                                                    self.supervisors)

        solution2 = mutate(solution1, self.supervisors, mutationProbability,
                           swapProbability, transferProbability)

        result = solution2.isValid(self.students, self.supervisors)

        self.assertTrue(result)
Example #9
0
class CrossoverTest(unittest.TestCase):
    def setUp(self):

        #Creating a list of students and supervisors

        topicNames, topicPaths, topicIDs, levels = parseFile(
            "pystsup/test/acm.txt")

        self.supervisors = {}
        self.students = {}

        stuID = "student"
        supID = "supervisor"

        stuList1 = [
            "MapReduce-based systems", "Multidimensional range search",
            "Open source software", "Data mining", "Online shopping"
        ]
        stuList2 = [
            "Heuristic function construction", "Multi-agent systems",
            "Open source software", "Data mining", "Speech recognition"
        ]
        stuList3 = [
            "Multi-agent systems", "Speech recognition",
            "Heuristic function construction", "Data mining",
            "Object identification"
        ]
        stuList4 = [
            "Multi-agent systems", "Intelligent agents", "Speech recognition",
            "Object identification", "Heuristic function construction"
        ]

        supList1 = [
            "Multi-agent systems", "Intelligent agents",
            "MapReduce-based systems", "Object identification",
            "Heuristic function construction"
        ]
        supList2 = [
            "Open source software", "Data mining", "Speech recognition",
            "Object identification", "Heuristic function construction"
        ]
        supList3 = [
            "Multi-agent systems", "Intelligent agents", "Speech recognition",
            "Object identification", "Heuristic function construction"
        ]

        supList = [supList1, supList2, supList3]
        supQuota = [2, 2, 1]
        stuList = [stuList1, stuList2, stuList3, stuList4]

        for i in range(3):
            toAdd = []
            sup_list = {}
            rank = 0
            for kw in supList[i]:
                rank += 1
                sup_list[rank] = [
                    kw, getPath(kw, topicNames, topicPaths, topicIDs)
                ]

            sup = supID + str(i + 1)
            quota = supQuota[i]

            supervisorObject = Supervisor(sup, sup_list, quota)

            self.supervisors[sup] = supervisorObject

        for i in range(4):
            toAdd = []
            stu_list = {}
            rank = 0
            for kw in stuList[i]:
                rank += 1
                stu_list[rank] = [
                    kw, getPath(kw, topicNames, topicPaths, topicIDs)
                ]

            stu = stuID + str(i + 1)
            studentObject = Student(stu, stu_list)
            self.students[stu] = studentObject

        # Generating rank weights for c = 0.5

        self.rankWeights = Solution.calcRankWeights()

        #Creating fitness cache

        self.dummySolution = Solution()

        self.fitnessCache = {}

        for sup in self.supervisors:
            supervisorKeywords = self.supervisors[sup].getKeywords()
            for stu in self.students:
                studentKeywords = self.students[stu].getKeywords()
                f_stu, f_sup = self.dummySolution.kw_similarity(
                    studentKeywords, supervisorKeywords, self.rankWeights)
                self.fitnessCache[str((stu, sup))] = (f_stu, f_sup)

        # Creating two graphs and solutions

        self.graph1 = BipartiteGraph()
        self.graph2 = BipartiteGraph()

        self.graph1.addEdge("supervisor1", "student2")
        self.graph1.addEdge("supervisor2", "student4")
        self.graph1.addEdge("supervisor3", "student1")
        self.graph1.addEdge("supervisor1", "student3")

        self.solution1 = Solution(self.graph1)

        self.graph2.addEdge("supervisor1", "student2")
        self.graph2.addEdge("supervisor2", "student1")
        self.graph2.addEdge("supervisor3", "student4")
        self.graph2.addEdge("supervisor1", "student3")

        self.solution2 = Solution(self.graph2)

        # Creating test for simplify function
        self.graph3 = BipartiteGraph()
        self.graph3.addEdge("s1", "st1")
        self.graph3.addEdge("s1", "st4")
        self.graph3.addEdge("s2", "st1")
        self.graph3.addEdge("s2", "st2")
        self.graph3.addEdge("s3", "st3")
        self.graph3.addEdge("s3", "st5")
        self.graph3.addEdge("s4", "st3")
        self.graph3.addEdge("s4", "st5")
        self.structure3 = {"s1": 2, "s2": 1, "s3": 1, "s4": 1}

        self.graph4 = BipartiteGraph()
        self.graph4.addEdge("s1", "st1")
        self.graph4.addEdge("s1", "st3")
        self.graph4.addEdge("s1", "st4")
        self.graph4.addEdge("s2", "st3")
        self.graph4.addEdge("s2", "st4")
        self.graph4.addEdge("s3", "st1")
        self.graph4.addEdge("s3", "st2")
        self.structure4 = {"s1": 1, "s2": 2, "s3": 1}

        #Creating 60-400 data set

        self.students2, self.supervisors2 = createRandomData(60, 400, 405)
        # m,n,quotaSum,level=3,maxQuota=10,minQuota=4,no_topics=5
        self.students3, self.supervisors3 = createRandomData(3,
                                                             5,
                                                             8,
                                                             minQuota=1,
                                                             maxQuota=3)
        self.problem_instances = [  #createRandomData(6,10,16,minQuota=1) 
            createRandomData(60, 400, 405)
        ]

        #def test_case_special_cr(self):
        #for (students,supervisors) in self.problem_instances :
        #for i in range(100):
        #   sol1 = Solution.generateRandomSolution(students,supervisors)
        #   sol2 = Solution.generateRandomSolution(students,supervisors)
        #   sp_crossover(sol1,sol2)

    def test_case_simplify1(self):
        response, already_set = simplify(self.graph3, self.structure3)
        self.assertTrue(("s1", "st1") in response)
        self.assertTrue(("s1", "st4") in response)
        self.assertTrue(("s2", "st2") in response)
        self.assertEqual(self.structure3["s1"], 0)
        self.assertEqual(self.structure3["s2"], 0)
        self.assertEqual(self.structure3["s3"], 1)
        self.assertEqual(self.structure3["s4"], 1)
        self.assertTrue(("stu", "st1") in already_set)
        self.assertTrue(("stu", "st4") in already_set)
        self.assertTrue(("stu", "st2") in already_set)
        self.assertTrue(("sup", "s1") in already_set)
        self.assertTrue(("sup", "s2") in already_set)
        self.assertEqual(len(response), 3)

    def test_case_simplify2(self):
        response, already_set = simplify(self.graph4, self.structure4)
        self.assertTrue(("s1", "st1") in response)
        self.assertTrue(("s2", "st3") in response)
        self.assertTrue(("s2", "st4") in response)
        self.assertTrue(("s3", "st2") in response)
        self.assertEqual(self.structure4["s1"], 0)
        self.assertEqual(self.structure4["s2"], 0)
        self.assertEqual(self.structure4["s3"], 0)
        self.assertTrue(("stu", "st1") in already_set)
        self.assertTrue(("stu", "st3") in already_set)
        self.assertTrue(("stu", "st4") in already_set)
        self.assertTrue(("stu", "st2") in already_set)
        self.assertTrue(("sup", "s1") in already_set)
        self.assertTrue(("sup", "s2") in already_set)
        self.assertTrue(("sup", "s3") in already_set)
        self.assertEqual(len(response), 4)

    def test_case1(self):
        """Testing the ERX Modified Crossover function - for 3sup:4stu solution"""

        solution3 = crossover(self.solution1, self.solution2, self.supervisors,
                              self.students)

        structureResult = (solution3.getGraph().getStructure()
                           == self.solution1.getGraph().getStructure()) or (
                               solution3.getGraph().getStructure()
                               == self.solution2.getGraph().getStructure())
        result = (solution3.isValid(self.students,
                                    self.supervisors)) and (structureResult)

        self.assertTrue(result)

    def test_case2(self):
        """Testing the kPoint crossover function - for 3sup:4stu solution"""

        solution3 = kPoint(self.solution1,
                           self.solution2,
                           self.supervisors,
                           self.students,
                           k=3)
        result = solution3.isValid(self.students, self.supervisors)
        self.assertTrue(result)

    def test_case3(self):
        """Testing the EDX Modified crossover function - when one valid and one dummy solution are passed"""

        self.assertRaises(
            KeyError, lambda: crossover(self.solution1, self.dummySolution,
                                        self.supervisors, self.students))

    def test_case4(self):
        """Testing the K Point Crossover function - when one valid and one dummy solution are passed"""

        self.assertRaises(
            KeyError, lambda: kPoint(self.solution2,
                                     self.dummySolution,
                                     self.supervisors,
                                     self.students,
                                     k=3))

    def test_case5(self):
        """Testing the ERX Modified Crossover function - for random 3sup:4stu solution"""

        solution1 = Solution.generateRandomSolution(self.students,
                                                    self.supervisors)
        solution2 = Solution.generateRandomSolution(self.students,
                                                    self.supervisors)

        solution3 = crossover(solution1, solution2, self.supervisors,
                              self.students)

        structureResult = (solution3.getGraph().getStructure()
                           == solution1.getGraph().getStructure()) or (
                               solution3.getGraph().getStructure()
                               == solution2.getGraph().getStructure())
        result = (solution3.isValid(self.students,
                                    self.supervisors)) and (structureResult)

        self.assertTrue(result)

    def test_case6(self):
        """Testing the K Point Crossover function - for random 3sup:4stu solution"""

        solution1 = Solution.generateRandomSolution(self.students,
                                                    self.supervisors)
        solution2 = Solution.generateRandomSolution(self.students,
                                                    self.supervisors)

        solution3 = kPoint(solution1,
                           solution2,
                           self.supervisors,
                           self.students,
                           k=3)

        result = solution3.isValid(self.students, self.supervisors)

        self.assertTrue(result)

    def test_case7(self):
        """Testing the K Point crossover function - when k=0"""

        solution3 = kPoint(self.solution1,
                           self.solution2,
                           self.supervisors,
                           self.students,
                           k=0)

        structureResult = (solution3.getGraph().getStructure()
                           == self.solution1.getGraph().getStructure()) or (
                               solution3.getGraph().getStructure()
                               == self.solution2.getGraph().getStructure())
        result = (solution3.isValid(self.students,
                                    self.supervisors)) and (structureResult)

        self.assertTrue(result)

    def test_case8(self):
        """Testing the K Point crossover function - when k=1"""

        solution3 = kPoint(self.solution1,
                           self.solution2,
                           self.supervisors,
                           self.students,
                           k=1)

        result = solution3.isValid(self.students, self.supervisors)

        self.assertTrue(result)

    def test_case9(self):
        """Testing the K Point crossover function - when k > no_students"""

        self.assertRaises(
            ValueError, lambda: kPoint(self.solution1,
                                       self.solution2,
                                       self.supervisors,
                                       self.students,
                                       k=6))

    def test_case10(self):
        """Testing the ERX Modified crossover function - for random 60sup:400stu solution"""

        solution1 = Solution.generateRandomSolution(self.students2,
                                                    self.supervisors2)
        solution2 = Solution.generateRandomSolution(self.students2,
                                                    self.supervisors2)

        solution3 = crossover(solution1, solution2, self.supervisors2,
                              self.students2)

        structureResult = (solution3.getGraph().getStructure()
                           == solution1.getGraph().getStructure()) or (
                               solution3.getGraph().getStructure()
                               == solution2.getGraph().getStructure())
        result = (solution3.isValid(self.students2,
                                    self.supervisors2)) and (structureResult)

        self.assertTrue(result)

    def test_case11(self):
        """Testing the ERX Modified crossover function - for random 60sup:400stu solution"""

        solution1 = Solution.generateRandomSolution(self.students2,
                                                    self.supervisors2)
        solution2 = Solution.generateRandomSolution(self.students2,
                                                    self.supervisors2)

        solution3 = crossover(solution1, solution2, self.supervisors,
                              self.supervisors2, self.students2)

        structureResult = (solution3.getGraph().getStructure()
                           == solution1.getGraph().getStructure()) or (
                               solution3.getGraph().getStructure()
                               == solution2.getGraph().getStructure())
        result = (solution3.isValid(self.students2,
                                    self.supervisors2)) and (structureResult)

        self.assertTrue(result)

    def test_case12(self):
        """Testing the kPoint crossover function - for random 60sup:400stu solution"""

        solution1 = Solution.generateRandomSolution(self.students2,
                                                    self.supervisors2)
        solution2 = Solution.generateRandomSolution(self.students2,
                                                    self.supervisors2)

        solution3 = kPoint(solution1,
                           solution2,
                           self.supervisors2,
                           self.students2,
                           k=15)

        result = solution3.isValid(self.students2, self.supervisors2)

        self.assertTrue(result)

    def test_case13(self):
        """Testing the kPoint crossover function - for random 60sup:400stu solution"""

        solution1 = Solution.generateRandomSolution(self.students2,
                                                    self.supervisors2)
        solution2 = Solution.generateRandomSolution(self.students2,
                                                    self.supervisors2)

        solution3 = kPoint(solution1,
                           solution2,
                           self.supervisors2,
                           self.students2,
                           k=15)

        result = solution3.isValid(self.students2, self.supervisors2)

        self.assertTrue(result)
class SolutionTest(unittest.TestCase):

    def setUp(self):

        #Creating a list of students and supervisors

        topicNames,topicPaths, topicIDs, levels = parseFile("pystsup/test/acm.txt")
        
        self.supervisors = {}
        self.students = {}

        stuID = "student"
        supID = "supervisor"

        stuList1 = ["MapReduce-based systems","Multidimensional range search","Open source software","Data mining","Online shopping"]
        stuList2 = ["Heuristic function construction","Multi-agent systems","Open source software","Data mining","Speech recognition"]
        stuList3 = ["Multi-agent systems","Speech recognition","Heuristic function construction","Data mining","Object identification"]
        stuList4 = ["Multi-agent systems","Intelligent agents","Speech recognition","Object identification","Heuristic function construction"]

        supList1 = ["Multi-agent systems","Intelligent agents","MapReduce-based systems","Object identification","Heuristic function construction"]
        supList2 = ["Open source software","Data mining","Speech recognition","Object identification","Heuristic function construction"]
        supList3 = ["Multi-agent systems","Intelligent agents","Speech recognition","Object identification","Heuristic function construction"]
        
        supList = [supList1,supList2,supList3]
        supQuota = [2,2,1]
        stuList = [stuList1,stuList2,stuList3,stuList4]

        for i in range(3):
            toAdd = []
            sup_list = {}
            rank = 0
            for kw in supList[i]:
                rank+=1
                sup_list[rank]=[kw,getPath(kw,topicNames,topicPaths, topicIDs)]

            sup = supID + str(i+1)
            quota = supQuota[i]

            supervisorObject = Supervisor(sup,sup_list,quota)

            self.supervisors[sup]=supervisorObject
            

        for i in range(4):
            toAdd = []
            stu_list = {}
            rank = 0
            for kw in stuList[i]:
                rank+=1
                stu_list[rank] = [kw,getPath(kw,topicNames,topicPaths, topicIDs)]

            stu = stuID + str(i+1)
            studentObject = Student(stu,stu_list)
            self.students[stu]=studentObject



        # Generating rank weights for c = 0.5

        self.rankWeights = Solution.calcRankWeights()

        #Creating fitness cache
        
        self.dummySolution = Solution()

        self.fitnessCache = {}

        for sup in self.supervisors:
            supervisorKeywords = self.supervisors[sup].getKeywords()
            for stu in self.students:
                studentKeywords = self.students[stu].getKeywords()
                f_stu,f_sup = self.dummySolution.kw_similarity(studentKeywords,supervisorKeywords, self.rankWeights)
                self.fitnessCache[str((stu,sup))] = (f_stu,f_sup)


        # Creating two graphs and solutions

        self.graph1 = BipartiteGraph()
        self.graph2 = BipartiteGraph()

        self.graph1.addEdge("supervisor1","student2")
        self.graph1.addEdge("supervisor2","student4")
        self.graph1.addEdge("supervisor3","student1")
        self.graph1.addEdge("supervisor1","student3")

        self.solution1 = Solution(self.graph1)

        self.graph2.addEdge("supervisor1","student2")
        self.graph2.addEdge("supervisor2","student1")
        self.graph2.addEdge("supervisor3","student4")
        self.graph2.addEdge("supervisor1","student3")

        self.solution2 = Solution(self.graph2)
    

    def test_case1(self):
        """Testing the create random solution function"""

        solution1 = Solution.generateRandomSolution(self.students,self.supervisors)
        
        result = solution1.isValid(self.students,self.supervisors)

        self.assertEqual(result,True)


    def test_case2(self):
        """Testing the calculate Rank Weights function when c = 1"""

        rankWeights = Solution.calcRankWeights(c=1)

        result = True
        
        expected = 0.2
        
        for i in rankWeights:

            if rankWeights[i] != expected:

                result = False
                break

        self.assertTrue(result)


    def test_case3(self):
        """Testing the calculate rank weights function when c = 0.3"""

        rankWeights = Solution.calcRankWeights(c=0.3)

        result = round(sum(rankWeights.values()),15)

        expected = {1: 0.701705143, 2: 0.210511543, 3: 0.063153463, 4: 0.0189460389, 5: 0.005683812}

        result2 = True

        for i in rankWeights:

            if round(rankWeights[i],8) != round(expected[i],8):
                result2 = False
                break
        

        self.assertEqual((result,result2),(1,True))


    def test_case4(self):
        """Testing the calculate rank weights function when c=0 and n=0"""

        rankWeights = Solution.calcRankWeights(c=0,n=0)
        expected = {}

        self.assertEqual(rankWeights,expected)


    def test_case5(self):
        """Testing similarity function with 2 non-similar profiles (0)"""

        dummySolution = Solution()

        supervisorKeywords = self.supervisors["supervisor3"].getKeywords()
        studentKeywords = self.students["student1"].getKeywords()
        
        f_stu,f_sup = dummySolution.kw_similarity(studentKeywords,supervisorKeywords,self.rankWeights)

        expected_fstu = 0.1217742
        expected_fsup = 0.1416129

        expected = (round(expected_fstu,6),round(expected_fsup,6))
        retrieved = (round(f_stu,6),round(f_sup,6))
        
        self.assertEqual(retrieved,expected)


    def test_case6(self):
        """Testing similarity function with 2 identical profiles (1)"""

        dummySolution = Solution()

        supervisorKeywords = self.supervisors["supervisor3"].getKeywords()
        studentKeywords = self.students["student4"].getKeywords()
        
        f_stu,f_sup = dummySolution.kw_similarity(studentKeywords,supervisorKeywords,self.rankWeights)

        self.assertEqual((f_stu,f_sup),(1,1))


    def test_case7(self):
        """Testing similarity function between 2 mostly similar profiles """
        
        dummySolution = Solution()

        supervisorKeywords = self.supervisors["supervisor3"].getKeywords()
        studentKeywords = self.students["student3"].getKeywords()

        f_stu,f_sup = dummySolution.kw_similarity(studentKeywords,supervisorKeywords,self.rankWeights)

        expected_fstu = 0.708333
        expected_fsup = 0.726882

        expected = (round(expected_fstu,6),round(expected_fsup,6))
        retrieved = (round(f_stu,6),round(f_sup,6))

        self.assertEqual(retrieved,expected)


    def test_case8(self):
        """Testing similarity function between 2 less similar profiles """
        
        dummySolution = Solution()

        supervisorKeywords = self.supervisors["supervisor3"].getKeywords()
        studentKeywords = self.students["student2"].getKeywords()

        f_stu,f_sup = dummySolution.kw_similarity(studentKeywords,supervisorKeywords,self.rankWeights)

        expected_fstu = 0.255645
        expected_fsup = 0.522043

        expected = (round(expected_fstu,6),round(expected_fsup,6))
        retrieved = (round(f_stu,6),round(f_sup,6))

        self.assertEqual(retrieved,expected)


    def test_case9(self):
        """Testing intersection function - between 2 non-intersecting lists"""

        list1 = self.supervisors["supervisor1"].getKeywords()[1][1]
        list2 = self.students["student1"].getKeywords()[1][1]

        result = self.dummySolution._intersection(list1,list2)

        self.assertEqual(result,1)


    def test_case10(self):
        """Testing intersection function - between 2 lists with 1 common element"""

        list1 = ["Document types","General and reference"]
        list2 = ["Cross-computing tools and techniques","General and reference"]


        result = self.dummySolution._intersection(list1,list2)

        self.assertEqual(result,1)


    def test_case11(self):
        """Testing intersection function - between 2 lists with 2 common element"""

        list1 = ["Reference works","Document types","General and reference"]
        list2 = ["Surveys and overviews","Document types","General and reference"]

        result = self.dummySolution._intersection(list1,list2)

        self.assertEqual(result,2)


    def test_case12(self):
        """Testing intersection function - between 2 lists with 3 common element"""

        list1 = ["Digital signal processing","Signal processing systems","Communication hardware, interfaces and storage","Hardware"]
        list2 = ["Beamforming","Signal processing systems","Communication hardware, interfaces and storage","Hardware"]

        result = self.dummySolution._intersection(list1,list2)

        self.assertEqual(result,3)


    def test_case13(self):
        """Testing intersection function - between 2 identical lists"""

        list1 = self.supervisors["supervisor1"].getKeywords()[1][1]
        list2 = self.students["student4"].getKeywords()[1][1]

        result = self.dummySolution._intersection(list1,list2)

        self.assertEqual(result,5)


    def test_case14(self):
        """Testing the calc fitness function for a bad solution"""
        
        self.solution1.calcFitness(self.students,self.supervisors,self.rankWeights,self.fitnessCache)
        F_st = self.solution1.getFst()
        F_sup = self.solution1.getFsup()

        retrieved = (round(F_sup,6),round(F_st,6))
        expected = (0.600813,1.457903)

        self.assertEqual(retrieved,expected)

    def test_case15(self):
        """Testing the calc fitness function for a fairly good solution"""
        
        self.solution2.calcFitness(self.students,self.supervisors,self.rankWeights,self.fitnessCache)
        F_st = self.solution2.getFst()
        F_sup = self.solution2.getFsup()
        
        retrieved = (round(F_sup,7),round(F_st,7))
        expected = (1.1482502,2.1678495)

        self.assertEqual(retrieved,expected)


    def test_case16(self):
        """Testing transfer function - a valid transfer"""

        self.solution1.transferStudent("student3","supervisor1","supervisor2",self.supervisors)

        solutionGraph = self.solution1.getGraph()
        val1 = solutionGraph.getStudents("supervisor1")
        val2 = solutionGraph.getStudents("supervisor2")
        val3 = solutionGraph.getSupervisors("student3")

        expected = (['student2'],['student4','student3'],['supervisor2'])

        self.assertEqual((val1,val2,val3),expected)


    def test_case17(self):
        """Testing getGraph function"""

        solutionGraph = self.solution1.getGraph()

        val1 = isinstance(solutionGraph,BipartiteGraph)
        val2 = solutionGraph.getStuEdges()

        result = (val1,val2)

        expected1 = True
        expected2 = {'student1':['supervisor3'],'student2':['supervisor1'],'student3':['supervisor1'],'student4':['supervisor2']}

        expected = (expected1,expected2)

        self.assertEqual(result,expected)


    def test_case18(self):
        """Testing the isValid function - passing a null graph"""

        graph = BipartiteGraph()
        solution = Solution(graph)
        
        result = solution.isValid(self.students,self.supervisors)

        self.assertFalse(result)


    def test_case19(self):
        """Testing the isValid function - when number of supervisors less than actual"""

        graph = BipartiteGraph()
        
        graph.addEdge("supervisor1","student1")
        graph.addEdge("supervisor2","student4")
        graph.addEdge("supervisor2","student3")
        graph.addEdge("supervisor1","student2")

        solution = Solution(graph)

        result = solution.isValid(self.students,self.supervisors)

        self.assertFalse(result)


    def test_case20(self):
        """Testing the isValid function - when number of students less than actual"""

        graph = BipartiteGraph()
        
        graph.addEdge("supervisor1","student1")
        graph.addEdge("supervisor3","student3")
        graph.addEdge("supervisor2","student2")

        solution = Solution(graph)

        result = solution.isValid(self.students,self.supervisors)

        self.assertFalse(result)
        

    def test_case21(self):
        """Testing the isValid function - when a supervisor's allocation exceeds their quota"""

        self.graph1.addEdge("supervisor3","student2")

        solution = Solution(self.graph1)

        result = solution.isValid(self.students,self.supervisors)

        self.assertFalse(result)


    def test_case22(self):
        """Testing the isValid function - when a supervisor's degree is 0"""

        self.graph1.removeEdge("supervisor3","student1")

        solution = Solution(self.graph1)

        result = solution.isValid(self.students,self.supervisors)

        self.assertFalse(result)
        


    def test_case23(self):
        """Testing the isValid function - when a student's degree is not equal to 1"""

        self.graph1.addEdge("supervisor2","student3")

        solution = Solution(self.graph1)

        result = solution.isValid(self.students,self.supervisors)

        self.assertFalse(result)


    def test_case24(self):
        """Testing is valid function - when a correct graph is passed"""

        result1 = self.solution1.isValid(self.students,self.supervisors)
        result2 = self.solution2.isValid(self.students,self.supervisors)

        self.assertEqual((result1,result2),(True,True))


    def test_case25(self):
        """Testing 'dominates' function - when both Fst and Fsup are greater in solution1 than solution2"""

        solution1 = Solution()
        solution2 = Solution()

        solution1.setFst(29.5)
        solution1.setFsup(0.4)

        solution2.setFst(27.5)
        solution2.setFsup(0.2)

        result = solution1.dominates(solution2)

        self.assertTrue(result)


    def test_case26(self):
        """Testing 'dominates' function - when only Fsup is greater in solution2 than solution1"""

        solution1 = Solution()
        solution2 = Solution()

        solution1.setFst(29.5)
        solution1.setFsup(0.4)

        solution2.setFst(27.5)
        solution2.setFsup(0.6)

        result = solution1.dominates(solution2)

        self.assertFalse(result)


    def test_case27(self):
        """Testing 'dominates' function - when Fsup is same in solution2 and solution1"""

        solution1 = Solution()
        solution2 = Solution()

        solution1.setFst(29.5)
        solution1.setFsup(0.4)

        solution2.setFst(27.5)
        solution2.setFsup(0.4)

        result = solution1.dominates(solution2)

        self.assertTrue(result)


    def test_case28(self):
        """Testing 'dominates' function - when only Fst is greater in solution2 and solution1"""

        solution1 = Solution()
        solution2 = Solution()

        solution1.setFst(26.5)
        solution1.setFsup(0.4)

        solution2.setFst(27.5)
        solution2.setFsup(0.2)

        result = solution1.dominates(solution2)

        self.assertFalse(result)
        

    def test_case29(self):
        """Testing 'dominates' function - when both Fst and Fsup are lesser in solution1 than solution2"""

        solution1 = Solution()
        solution2 = Solution()

        solution1.setFst(26.5)
        solution1.setFsup(0.2)

        solution2.setFst(27.5)
        solution2.setFsup(0.4)

        result = solution1.dominates(solution2)

        self.assertFalse(result)
        

    def test_case30(self):
        """Testing 'dominates' function - when Fst is same in solution2 and solution1"""

        solution1 = Solution()
        solution2 = Solution()

        solution1.setFst(29.5)
        solution1.setFsup(0.6)

        solution2.setFst(29.5)
        solution2.setFsup(0.4)

        result = solution1.dominates(solution2)

        self.assertTrue(result)
        

    def test_case31(self):
        """Testing 'dominates' function - when Fst is same in solution2 and solution1"""

        solution1 = Solution()
        solution2 = Solution()

        solution1.setFst(29.5)
        solution1.setFsup(0.2)

        solution2.setFst(29.5)
        solution2.setFsup(0.4)

        result = solution1.dominates(solution2)

        self.assertFalse(result)
        

    def test_case32(self):
        """Testing 'dominates' function - when Fst and Fsup are same in solution2 and solution1"""

        solution1 = Solution()
        solution2 = Solution()

        solution1.setFst(29.5)
        solution1.setFsup(0.4)

        solution2.setFst(29.5)
        solution2.setFsup(0.4)

        result = solution1.dominates(solution2)

        self.assertFalse(result)
Example #11
0
class BipartiteGraphTest(unittest.TestCase):
    def setUp(self):

        self.graph1 = BipartiteGraph()
        self.graph2 = BipartiteGraph()

        self.graph1.addEdge("supervisor1", "student1")
        self.graph1.addEdge("supervisor2", "student4")
        self.graph1.addEdge("supervisor3", "student3")
        self.graph1.addEdge("supervisor1", "student2")

        self.graph2.addEdge("supervisor1", "student4")
        self.graph2.addEdge("supervisor2", "student1")
        self.graph2.addEdge("supervisor2", "student3")
        self.graph2.addEdge("supervisor3", "student2")

        #Creating a list of students and supervisors

        topicNames, topicPaths, topicIDs, levels = parseFile(
            "pystsup/test/acm.txt")

        self.supervisors = {}
        self.students = {}

        stuID = "student"
        supID = "supervisor"

        stuList1 = [
            "MapReduce-based systems", "Multidimensional range search",
            "Open source software", "Data mining", "Online shopping"
        ]
        stuList2 = [
            "Heuristic function construction", "Multi-agent systems",
            "Open source software", "Data mining", "Speech recognition"
        ]
        stuList3 = [
            "Multi-agent systems", "Speech recognition",
            "Heuristic function construction", "Data mining",
            "Object identification"
        ]
        stuList4 = [
            "Multi-agent systems", "Intelligent agents", "Speech recognition",
            "Object identification", "Heuristic function construction"
        ]

        supList1 = [
            "Multi-agent systems", "Intelligent agents",
            "MapReduce-based systems", "Object identification",
            "Heuristic function construction"
        ]
        supList2 = [
            "Open source software", "Data mining", "Speech recognition",
            "Object identification", "Heuristic function construction"
        ]
        supList3 = [
            "Multi-agent systems", "Intelligent agents", "Speech recognition",
            "Object identification", "Heuristic function construction"
        ]

        supList = [supList1, supList2, supList3]
        supQuota = [2, 2, 1]
        stuList = [stuList1, stuList2, stuList3, stuList4]

        for i in range(3):
            toAdd = []
            sup_list = {}
            rank = 0
            for kw in supList[i]:
                rank += 1
                sup_list[kw] = [
                    rank, getPath(kw, topicNames, topicPaths, topicIDs)
                ]

            sup = supID + str(i + 1)
            quota = supQuota[i]

            supervisorObject = Supervisor(sup, sup_list, quota)

            self.supervisors[sup] = supervisorObject

        for i in range(4):
            toAdd = []
            stu_list = {}
            rank = 0
            for kw in stuList[i]:
                rank += 1
                stu_list[kw] = [
                    rank, getPath(kw, topicNames, topicPaths, topicIDs)
                ]

            stu = stuID + str(i + 1)
            studentObject = Student(stu, stu_list)
            self.students[stu] = studentObject

    def test_case1(self):
        """Testing addEdge function in an empty graph"""

        graph = BipartiteGraph()

        graph.addEdge("supervisor1", "student1")

        val1 = graph.getStudents("supervisor1")
        val2 = graph.getSupervisors("student1")

        expected1 = ["student1"]
        expected2 = ["supervisor1"]

        self.assertEqual((val1, val2), (expected1, expected2))

    def test_case2(self):
        """Testing addEdge function in a graph with existing nodes and edges"""

        graph = BipartiteGraph()

        graph.addEdge("supervisor1", "student1")
        graph.addEdge("supervisor2", "student4")
        graph.addEdge("supervisor3", "student3")

        val1 = graph.getSupervisorDegree("supervisor1")

        graph.addEdge("supervisor1", "student2")

        curr = graph.getSupervisorDegree("supervisor1")
        val2 = graph.getSupervisors("student2")
        expected2 = ["supervisor1"]

        self.assertEqual((curr - 1, expected2), (val1, val2))

    def test_case3(self):
        """Testing addEdge function when adding an edge that already exists"""

        graph = BipartiteGraph()
        graph.addEdge("supervisor1", "student1")
        graph.addEdge("supervisor1", "student1")

        val1 = graph.getSupervisorDegree("supervisor1")
        val2 = graph.getStudentDegree("student1")

        self.assertEqual((val1, val2), (1, 1))

    def test_case4(self):
        """Testing the remove edge function in an empty graph"""

        graph = BipartiteGraph()
        self.assertRaises(KeyError,
                          lambda: graph.removeEdge("supervisor1", "student1"))

    def test_case5(self):
        """Testing the removeEdge function when trying to remove an edge that doesn't exist"""

        self.assertRaises(
            ValueError,
            lambda: self.graph1.removeEdge("supervisor2", "student1"))

    def test_case6(self):
        """Testing the removeEdge function in a graph with existing nodes and edges"""

        graph = BipartiteGraph()

        graph.addEdge("supervisor1", "student1")
        graph.removeEdge("supervisor1", "student1")

        val1 = graph.getStudentDegree("student1")
        val2 = graph.getSupervisorDegree("supervisor1")

        self.assertEqual((val1, val2), (0, 0))

    def test_case7(self):
        """Testing the merge function in two graphs"""

        graph3 = self.graph1.merge(self.graph2)

        expected = {
            'supervisor1': ['student1', 'student2', 'student4'],
            'supervisor2': ['student4', 'student1', 'student3'],
            'supervisor3': ['student3', 'student2']
        }

        result = True

        for sup in expected:
            for stu in expected[sup]:
                if not graph3.isEdge(sup, stu):
                    result = False
                    break

        self.assertTrue(result)

    def test_case8(self):
        """Testing the create random graph function"""

        graph = BipartiteGraph.createRandomGraph(self.students,
                                                 self.supervisors)

        solution = Solution(graph)

        result = solution.isValid(self.students, self.supervisors)

        self.assertTrue(result)

    def test_case9(self):
        """Testing transfer function - Cannnot transfer student when a supervisor has less than 2 students"""

        self.graph1.transferStudent("student3", "supervisor3", "supervisor2",
                                    self.supervisors)
        val1 = self.graph1.getStudentDegree("student3")
        val2 = self.graph1.getSupervisors("student3")
        expected = (1, ['supervisor3'])

        self.assertEqual((val1, val2), expected)

    def test_case10(self):
        """Testing transfer function - cannot transfer student to a supervisor who reached their maximum quota"""

        self.graph1.transferStudent("student1", "supervisor1", "supervisor3",
                                    self.supervisors)

        val1 = self.graph1.getSupervisorDegree("supervisor1")
        val2 = self.graph1.getSupervisors("student1")
        val3 = self.graph1.getStudents("supervisor3")

        expected = (2, ['supervisor1'], ['student3'])

        self.assertEqual((val1, val2, val3), expected)

    def test_case11(self):
        """Testing transfer function - cannot transfer student if student doesn't exist in the graph"""

        self.graph1.transferStudent("student5", "supervisor1", "supervisor2",
                                    self.supervisors)

        val1 = self.graph1.getSupervisorDegree("supervisor1")
        val2 = self.graph1.getStudents("supervisor3")

        expected = (2, ['student3'])

        self.assertEqual((val1, val2), expected)

    def test_case12(self):
        """Testing transfer function - cannot transfer student if the edge doesn't exist in the graph"""

        self.graph1.transferStudent("student3", "supervisor1", "supervisor2",
                                    self.supervisors)

        val1 = self.graph1.getSupervisorDegree("supervisor1")
        val2 = self.graph1.getStudents("supervisor2")
        val3 = self.graph1.getStudents("supervisor1")

        expected = (2, ['student4'], ['student1', 'student2'])

        self.assertEqual((val1, val2, val3), expected)

    def test_case13(self):
        """Testing transfer function - cannot transfer student if edge already exists in the supervisor transferring to"""

        self.graph1.transferStudent("student4", "supervisor1", "supervisor2",
                                    self.supervisors)

        val1 = self.graph1.getSupervisorDegree("supervisor1")
        val2 = self.graph1.getStudents("supervisor2")
        val3 = self.graph1.getStudents("supervisor1")

        expected = (2, ['student4'], ['student1', 'student2'])

        self.assertEqual((val1, val2, val3), expected)

    def test_case14(self):
        """Testing transfer function - a valid transfer"""

        self.graph1.transferStudent("student2", "supervisor1", "supervisor2",
                                    self.supervisors)

        val1 = self.graph1.getStudents("supervisor1")
        val2 = self.graph1.getStudents("supervisor2")
        val3 = self.graph1.getSupervisors("student2")

        expected = (['student1'], ['student4', 'student2'], ['supervisor2'])

        self.assertEqual((val1, val2, val3), expected)

    def test_case15(self):
        """Testing supervisor Exists function - when a supervisor does not exist"""

        result = self.graph1.supervisorExists("supervisor4")

        self.assertFalse(result)

    def test_case16(self):
        """Testing supervisor Exists function - when a supervisor exists"""

        result = self.graph1.supervisorExists("supervisor1")

        self.assertTrue(result)

    def test_case17(self):
        """Testing student exists function - when a student does not exists"""

        result = self.graph1.studentExists("student5")

        self.assertFalse(result)

    def test_case18(self):
        """Testing student exists function - when a student exists"""

        result = self.graph1.studentExists("student1")

        self.assertTrue(result)

    def test_case19(self):
        """Testing isEdge function - when a supervisor does not exist in graph"""

        result = self.graph1.isEdge("supervisor5", "student1")
        self.assertFalse(result)

    def test_case20(self):
        """Testing isEdge function - when a student does not exist in graph"""

        result = self.graph1.isEdge("supervisor1", "student5")
        self.assertFalse(result)

    def test_case21(self):
        """Testing isEdge function - when a edge does not exist"""

        result = self.graph1.isEdge("supervisor2", "student1")

        self.assertFalse(result)

    def test_case22(self):
        """Testing isEdge function - when a edge exists"""

        result = self.graph1.isEdge("supervisor1", "student1")

        self.assertTrue(result)

    def test_case23(self):
        """Testing getStudents function"""

        result = self.graph1.getStudents("supervisor3")
        expected = ['student3']

        self.assertEqual(result, expected)

    def test_case24(self):
        """Testing getSupervisors function"""

        result = self.graph1.getSupervisors("student1")
        expected = ['supervisor1']

        self.assertEqual(result, expected)

    def test_case25(self):
        """Testing getSupervisorDegree function"""

        result = self.graph1.getSupervisorDegree("supervisor1")
        expected = 2

        self.assertEqual(result, expected)

    def test_case26(self):
        """Testing getStudentDegree function"""

        result = self.graph1.getStudentDegree("student2")
        expected = 1

        self.assertEqual(result, expected)

    def test_case27(self):
        """Testing getStructure function"""

        result = self.graph1.getStructure()
        expected = {'supervisor1': 2, 'supervisor2': 1, 'supervisor3': 1}

        self.assertEqual(result, expected)

    def test_case28(self):
        """Testing getEdges function"""

        result = self.graph1.getEdges()
        expected = {
            'supervisor1': ['student1', 'student2'],
            'supervisor2': ['student4'],
            'supervisor3': ['student3']
        }

        self.assertEqual(result, expected)

    def test_case29(self):
        """Testing getStuEdges function"""

        result = self.graph1.getStuEdges()
        expected = {
            'student1': ['supervisor1'],
            'student2': ['supervisor1'],
            'student3': ['supervisor3'],
            'student4': ['supervisor2']
        }

        self.assertEqual(result, expected)

    def test_case30(self):
        """Testing getNumberofEdges function"""

        result = self.graph1.getNumberofEdges()
        expected = 4

        self.assertEqual(result, expected)

    def test_case31(self):
        """Testing the swap function - when 2 non-existing pairs of edges are passed"""

        self.assertRaises(
            ValueError, lambda: self.graph1.swapStudents(
                "student1", "supervisor2", "student3", "supervisor1"))

    def test_case32(self):
        """Testing the swap function - when 2 non-existing students and supervisors are passed"""

        self.assertRaises(
            KeyError, lambda: self.graph1.swapStudents(
                "student5", "supervisor5", "student6", "supervisor6"))

    def test_case33(self):
        """Testing the swap function - when 2 existing edges are passed"""

        self.graph1.swapStudents("student1", "supervisor1", "student3",
                                 "supervisor3")

        result1 = self.graph1.getSupervisors("student3")
        result2 = self.graph1.getSupervisors("student1")

        expected1 = ['supervisor1']
        expected2 = ['supervisor3']

        self.assertEqual((result1, result2), (expected1, expected2))

    def test_case34(self):
        """Testing the swap function - when swaping students of same supervisor"""

        self.graph1.swapStudents("student1", "supervisor1", "student2",
                                 "supervisor1")

        result1 = self.graph1.getSupervisors("student1")
        result2 = self.graph1.getSupervisors("student2")

        expected1 = ['supervisor1']
        expected2 = ['supervisor1']

        self.assertEqual((result1, result2), (expected1, expected2))
def kPoint(solution1, solution2, supervisors, students, k=5):
    """
    An Implementation of K-Point crossover for this problem.
    """
    graph1 = solution1.getGraph()
    graph2 = solution2.getGraph()

    stuEdges1 = graph1.getStuEdges()
    stuEdges2 = graph2.getStuEdges()
    supEdges1 = graph1.getEdges()

    #Randomly getting the structure from the two graphs

    num = random.randint(1, 2)
    if num == 1:
        structure = graph1.getStructure()
    else:
        structure = graph2.getStructure()

    #Setting up the vectors

    students = list(stuEdges1.keys())
    sol1 = []
    sol2 = []
    for i in range(len(students)):
        sol1.append(stuEdges1[students[i]][0])
        sol2.append(stuEdges2[students[i]][0])

    #Dividing the both solutions into k-points

    sol1Points = []
    sol2Points = []

    points = sorted(random.sample(range(1, len(students)), k))
    curr = 0

    for i in range(k - 1):
        sol1Points.append(sol1[curr:points[i]])
        sol2Points.append(sol2[curr:points[i]])
        curr = points[i]

    sol1Points.append(sol1[curr:])
    sol2Points.append(sol2[curr:])

    #Perform the crossover

    result = []

    if k == 0:
        n = random.randint(1, 2)
        if n == 1:
            result = sol1
        else:
            result = sol2

    else:

        for point in range(k):
            n = random.randint(1, 2)
            if n == 1:
                result.extend(sol1Points[point])
            else:
                result.extend(sol2Points[point])

    graph = BipartiteGraph()
    for i in range(len(students)):
        graph.addEdge(result[i], students[i])

    fixSolution(graph, supervisors, students)
    #supEdges = graph.getEdges()
    #availableStudents = set()
    #reqSup = set(list(supEdges1.keys())).difference(set(list(supEdges.keys())))

    #sol3 = Solution(graph)
    #canTransferFrom,canTransferTo = sol3.getTransferable(supervisors)

    #for sup in supEdges:
    #    supDegree = len(supEdges[sup])
    #    supQuota = supervisors[sup].getQuota()
    #    if supDegree > supQuota:
    #        excess = supDegree - supQuota
    #        for i in random.sample(supEdges[sup],excess):
    #            availableStudents.add(i)
    #    elif supDegree == 0:
    #        reqSup.add(sup)

    #for sup in reqSup:

    #    if len(availableStudents)==0:
    #        fromSup = random.choice(list(canTransferFrom))
    #        stu = random.choice(graph.getStudents(fromSup))
    #        availableStudents.add(stu)

    #    x = random.choice(list(availableStudents))
    #    availableStudents.remove(x)
    #    oldSup = graph.getSupervisors(x)[0]
    #    graph.transferStudent1(x,oldSup,sup,supervisors)

    #sol3 = Solution(graph)
    #canTransferFrom,canTransferTo = sol3.getTransferable(supervisors)

    #for stu in availableStudents:
    #    con = False
    #    oldSup = graph.getSupervisors(stu)[0]

    #    if oldSup in canTransferTo:
    #        canTransferTo.remove(oldSup)
    #        con=True

    #    toSup = random.choice(list(canTransferTo))

    #    graph.transferStudent1(stu,oldSup,toSup,supervisors)

    #    if con:
    #        canTransferTo.add(oldSup)

    #    if not(graph.getSupervisorDegree(toSup) < supervisors[toSup].getQuota()):
    #        canTransferTo.remove(toSup)

    return Solution(graph)
def crossover(solution1, solution2, supervisors=None, students=None, k=None):
    """
    Function to perfrom crossover on two solutions.

    Parameters:
    
        solution1 (Solution) - parent solution 1
        solution2 (Solution) - parent solution 2

    Returns:

        A New Solution Object - an offspring solution from both the parent solutions.
    """

    #Merging the two Graphs

    graph1 = solution1.getGraph()
    graph2 = solution2.getGraph()

    mergedGraph = graph1.merge(graph2)

    stuEdges = mergedGraph.getStuEdges()
    supEdges = mergedGraph.getEdges()

    #Randomly getting the structure from the two graphs
    stf1 = solution1.getStructuralFitness(supervisors)
    stf2 = solution2.getStructuralFitness(supervisors)

    if random.random() <= (stf1) / (stf1 + stf2):
        structure = graph1.getStructure()
    else:
        structure = graph2.getStructure()

    lockedEdges = set()
    lockedVertices = set()

    allStudents = set(list(stuEdges.keys()))

    result = BipartiteGraph()

    counts = {
    }  #stores the degree of the supervisors in the new offspring graph

    for sup in supEdges:
        counts[sup] = 0

    #Simplify first time here
    simplified = True
    prev_count = {}
    while prev_count != counts:
        prev_count = dict(counts)
        for sup in supEdges:
            supDegree = len(supEdges[sup])
            reqDegree = structure[sup]
            for stu in supEdges[sup]:

                if len(stuEdges[stu]) == 1 and not stu in lockedVertices:
                    mergedGraph.removeExcept(sup, stu)
                    result.addEdge(sup, stu)
                    lockedVertices.add(stu)
                    counts[sup] += 1

                    if counts[sup] == reqDegree:
                        toKeep = result.getStudents(sup)
                        toRemove = mergedGraph.getRemainingStu(sup, toKeep)

                        for i in toRemove:
                            mergedGraph.removeEdge(sup, i)

    prev = set()
    toContinue = False

    while len(lockedVertices) != len(stuEdges):

        for sup in supEdges:

            #If the supervisor degree is not equal to degree we want
            if counts[sup] != structure[sup]:

                supDegree = mergedGraph.getSupervisorDegree(sup)
                reqSupDegree = structure[sup]
                students = mergedGraph.getStudents(sup)

                #Pick a random student that is not locked from the supervior's list of students
                curr = random.choice(students)
                if (curr not in lockedVertices):

                    #If that edge can be locked, then lock it.
                    if mergedGraph.canLock(sup, curr, structure, counts,
                                           lockedVertices):

                        #Remove other supervisors in student's list of supervisors

                        mergedGraph.removeExcept(sup, curr)

                        #Add it to the new graph and also locked vertices
                        result.addEdge(sup, curr)
                        lockedVertices.add(curr)

                        #Increment the degree of the supervisor
                        counts[sup] += 1

                        #If the degee is the degree we want
                        if counts[sup] == reqSupDegree:

                            toKeep = result.getStudents(
                                sup)  #Get the students we want to keep
                            toRemove = mergedGraph.getRemainingStu(
                                sup,
                                toKeep)  #Get students we dont want to keep

                            #Remove those students (edges)

                            for stu in toRemove:
                                mergedGraph.removeEdge(sup, stu)

        #If we can lock any further, then we break the loop
        if len(prev) != len(lockedVertices):
            prev = set(list(lockedVertices))
        else:
            toContinue = True
            break

    #Allocate remaining students to supervisors that don't meet the required degree
    if toContinue:
        availableStudents = allStudents.difference(lockedVertices)
        for sup in supEdges:
            reqDegree = structure[sup]
            supDegree = counts[sup]
            supNeeds = reqDegree - supDegree
            if supDegree != reqDegree:
                toAdd = random.sample(availableStudents, supNeeds)
                for stu in toAdd:
                    result.addEdge(sup, stu)
                    lockedVertices.add(stu)
                    counts[sup] += supNeeds
                    availableStudents.remove(stu)

    return Solution(result)