コード例 #1
0
ファイル: benchmark.py プロジェクト: afrancis13/MAS-Solver
    def test_benchmark_dag(self):
        """
        Tests that random graph generators are working properly, and generates the
        benchmark data that is saved to `benchmark.txt` in the root directory for
        this project.
        """
        # |V| = 4
        pre_time_dag_one = time.time()
        output_dag_one = DAGSolver(self.matrix_input_dag_one).topological_sort()
        post_time_dag_one = time.time()
        solving_time_dag_one = post_time_dag_one - pre_time_dag_one
        self.assertIsNotNone(output_dag_one)
        score_dag_one = scoreSolution(self.matrix_input_dag_one, output_dag_one)
        file_string_one = "DAG, |V| = 4: Score = %.4f, Time = %.4f\n" % (score_dag_one, solving_time_dag_one)
        self.benchmark_file.write(file_string_one)
        print "Finished Benchmark 1, DAG"

        # |V| = 7
        pre_time_dag_two = time.time()
        output_dag_two = DAGSolver(self.matrix_input_dag_two).topological_sort()
        post_time_dag_two = time.time()
        solving_time_dag_two = post_time_dag_two - pre_time_dag_two
        self.assertIsNotNone(output_dag_two)
        score_dag_two = scoreSolution(self.matrix_input_dag_two, output_dag_two)
        file_string_two = "DAG, |V| = 7: Score = %.4f, Time = %.4f\n" % (score_dag_two, solving_time_dag_two)
        self.benchmark_file.write(file_string_two)
        print "Finished Benchmark 2, DAG"

        # |V| = 20
        pre_time_dag_three = time.time()
        output_dag_three = DAGSolver(self.matrix_input_dag_three).topological_sort()
        post_time_dag_three = time.time()
        solving_time_dag_three = post_time_dag_three - pre_time_dag_three
        self.assertIsNotNone(output_dag_three)
        score_dag_three = scoreSolution(self.matrix_input_dag_three, output_dag_three)
        file_string_three = "DAG, |V| = 20: Score = %.4f, Time = %.4f\n" % (score_dag_three, solving_time_dag_three)
        self.benchmark_file.write(file_string_three)
        print "Finished Benchmark 3, DAG"

        # |V| = 100
        pre_time_dag_four = time.time()
        output_dag_four = DAGSolver(self.matrix_input_dag_four).topological_sort()
        post_time_dag_four = time.time()
        solving_time_dag_four = post_time_dag_four - pre_time_dag_four
        self.assertIsNotNone(output_dag_four)
        score_dag_four = scoreSolution(self.matrix_input_dag_four, output_dag_four)
        file_string_four = "DAG, |V| = 100: Score = %.4f, Time = %.4f\n" % (score_dag_four, solving_time_dag_four)
        self.benchmark_file.write(file_string_four)
        print "Finished Benchmark 4, DAG"

        # |V| = 1000
        pre_time_dag_five = time.time()
        output_dag_five = DAGSolver(self.matrix_input_dag_five).topological_sort()
        post_time_dag_five = time.time()
        solving_time_dag_five = post_time_dag_five - pre_time_dag_five
        self.assertIsNotNone(output_dag_five)
        score_dag_five = scoreSolution(self.matrix_input_dag_five, output_dag_five)
        file_string_five = "DAG, |V| = 1000: Score = %.4f, Time = %.4f\n" % (score_dag_five, solving_time_dag_five)
        self.benchmark_file.write(file_string_five)
        print "Finished Benchmark 5, DAG"
コード例 #2
0
    def test_simulated_annealing(self):
        random.seed(170)

        observed_output_new_graph = SimulatedAnnealingSolver(
            self.initial_ordering_new_graph,
            self.matrix_new_graph
        ).maximum_acyclic_subgraph()

        expected_score_new_graph = 54.0
        observed_score_new_graph = scoreSolution(self.matrix_new_graph, observed_output_new_graph)

        self.assertEquals(observed_score_new_graph, expected_score_new_graph)

        observed_output_foster = SimulatedAnnealingSolver(
            self.initial_ordering_foster,
            self.matrix_foster
        ).maximum_acyclic_subgraph()

        expected_score_foster = 113.0
        observed_score_foster = scoreSolution(self.matrix_foster, observed_output_foster)
        self.assertEquals(observed_score_foster, expected_score_foster)

        expected_output_input_one = [0, 2, 1, 3]
        observed_output_input_one = SimulatedAnnealingSolver(
            self.initial_ordering_input_one,
            self.matrix_input_one
        ).maximum_acyclic_subgraph()
        self.assertEquals(observed_output_input_one, expected_output_input_one)

        expected_ouput_input_cycle = [0, 1, 2, 3]
        observed_output_input_cycle = SimulatedAnnealingSolver(
            self.initial_ordering_input_cycle,
            self.matrix_input_cycle
        ).maximum_acyclic_subgraph()
        self.assertEquals(observed_output_input_cycle, expected_ouput_input_cycle)

        expected_output_nonplanar_one = [7, 8, 9, 2, 12, 13, 3, 10, 11, 4, 5, 0, 1, 6]
        observed_output_nonplanar_one = SimulatedAnnealingSolver(
            self.initial_ordering_input_nonplanar_one,
            self.matrix_input_nonplanar_one
        ).maximum_acyclic_subgraph()
        self.assertEquals(observed_output_nonplanar_one, expected_output_nonplanar_one)

        expected_output_nonplanar_two = [1, 5, 7, 2, 0, 6, 4, 3]
        observed_output_nonplanar_two = SimulatedAnnealingSolver(
            self.initial_ordering_input_nonplanar_two,
            self.matrix_input_nonplanar_two
        ).maximum_acyclic_subgraph()
        self.assertEquals(observed_output_nonplanar_two, expected_output_nonplanar_two)

        observed_output_gray = SimulatedAnnealingSolver(
            self.initial_ordering_input_gray,
            self.matrix_input_gray
        ).maximum_acyclic_subgraph()

        expected_score_gray = 70.0
        observed_score_gray = scoreSolution(self.matrix_input_gray, observed_output_gray)
        self.assertEquals(observed_score_gray, expected_score_gray)
コード例 #3
0
ファイル: benchmark.py プロジェクト: afrancis13/MAS-Solver
    def test_benchmark_feedback_arc_set_eades(self):
        # |V| = 4
        pre_time_eades_one = time.time()
        output_solver_one = FinalSolver(self.matrix_input_brute_force_two)
        output_eades_one = output_solver_one.obtain_library_solution(output_solver_one.adj_matrix, force_eades=True)
        post_time_eades_one = time.time()
        solving_time_eades_one = post_time_eades_one - pre_time_eades_one
        self.assertIsNotNone(output_eades_one)
        score_eades_one = scoreSolution(self.matrix_input_brute_force_two, output_eades_one)
        file_string_one = "Eades Approximation, |V| = 4: Score = %.4f, Time = %.4f\n" % (
            score_eades_one,
            solving_time_eades_one,
        )
        self.benchmark_file.write(file_string_one)

        # |V| = 25
        pre_time_eades_two = time.time()
        output_solver_two = FinalSolver(self.matrix_input_brute_force_five)
        output_eades_two = output_solver_two.obtain_library_solution(output_solver_two.adj_matrix)
        post_time_eades_two = time.time()
        solving_time_eades_two = post_time_eades_two - pre_time_eades_two
        self.assertIsNotNone(output_eades_two)
        score_eades_two = scoreSolution(self.matrix_input_brute_force_five, output_eades_two)
        file_string_two = "Eades Approximation, |V| = 25: Score = %.4f, Time = %.4f\n" % (
            score_eades_two,
            solving_time_eades_two,
        )
        self.benchmark_file.write(file_string_two)

        # |V| = 100
        pre_time_eades_three = time.time()
        output_solver_three = FinalSolver(self.matrix_input_size_100)
        output_eades_three = output_solver_three.obtain_library_solution(output_solver_three.adj_matrix)
        post_time_eades_three = time.time()
        solving_time_eades_three = post_time_eades_three - pre_time_eades_three
        self.assertIsNotNone(output_eades_three)
        score_eades_three = scoreSolution(self.matrix_input_size_100, output_eades_three)
        file_string_three = "Eades Approximation, |V| = 100: Score = %.4f, Time = %.4f\n" % (
            score_eades_three,
            solving_time_eades_three,
        )
        self.benchmark_file.write(file_string_three)

        # |V| = 1000
        pre_time_eades_four = time.time()
        output_solver_four = FinalSolver(self.matrix_input_size_1000)
        output_eades_four = output_solver_four.obtain_library_solution(output_solver_four.adj_matrix)
        post_time_eades_four = time.time()
        solving_time_eades_four = post_time_eades_four - pre_time_eades_four
        self.assertIsNotNone(output_eades_four)
        score_eades_four = scoreSolution(self.matrix_input_size_1000, output_eades_four)
        file_string_four = "Eades Approximation, |V| = 1000: Score = %.4f, Time = %.4f\n" % (
            score_eades_four,
            solving_time_eades_four,
        )
        self.benchmark_file.write(file_string_four)
コード例 #4
0
ファイル: two_approx.py プロジェクト: afrancis13/MAS-Solver
 def maximum_acyclic_subgraph_helper_efficient(self, graph):
     vertices = [i for i in range(len(graph))]
     shuffle(vertices)
     score_vertices = scoreSolution(graph, vertices)
     reverse_vertices = vertices[::-1]
     score_reverse = scoreSolution(graph, reverse_vertices)
     if score_vertices > score_reverse:
         return vertices
     else:
         return reverse_vertices
コード例 #5
0
ファイル: benchmark.py プロジェクト: afrancis13/MAS-Solver
    def test_benchmark_two_approximation(self):
        # |V| = 4
        pre_time_two_approx_one = time.time()
        output_two_approx_one = TwoApproximationSolver(self.matrix_input_brute_force_two).maximum_acyclic_subgraph()
        post_time_two_approx_one = time.time()
        solving_time_two_approx_one = post_time_two_approx_one - pre_time_two_approx_one
        self.assertIsNotNone(output_two_approx_one)
        score_two_approx_one = scoreSolution(self.matrix_input_brute_force_two, output_two_approx_one)
        file_string_one = "Two Approximation, |V| = 4: Score = %.4f, Time = %.4f\n" % (
            score_two_approx_one,
            solving_time_two_approx_one,
        )
        self.benchmark_file.write(file_string_one)

        # |V| = 25
        pre_time_two_approx_two = time.time()
        output_two_approx_two = TwoApproximationSolver(self.matrix_input_brute_force_five).maximum_acyclic_subgraph()
        post_time_two_approx_two = time.time()
        solving_time_two_approx_two = post_time_two_approx_two - pre_time_two_approx_two
        self.assertIsNotNone(output_two_approx_two)
        score_two_approx_two = scoreSolution(self.matrix_input_brute_force_five, output_two_approx_two)
        file_string_two = "Two Approximation, |V| = 25: Score = %.4f, Time = %.4f\n" % (
            score_two_approx_two,
            solving_time_two_approx_two,
        )
        self.benchmark_file.write(file_string_two)

        # |V| = 100
        pre_time_two_approx_three = time.time()
        output_two_approx_three = TwoApproximationSolver(self.matrix_input_size_100).maximum_acyclic_subgraph()
        post_time_two_approx_three = time.time()
        solving_time_two_approx_three = post_time_two_approx_three - pre_time_two_approx_three
        self.assertIsNotNone(output_two_approx_three)
        score_two_approx_three = scoreSolution(self.matrix_input_size_100, output_two_approx_three)
        file_string_three = "Two Approximation, |V| = 100: Score = %.4f, Time = %.4f\n" % (
            score_two_approx_three,
            solving_time_two_approx_three,
        )
        self.benchmark_file.write(file_string_three)

        # |V| = 1000
        pre_time_two_approx_four = time.time()
        output_two_approx_four = TwoApproximationSolver(self.matrix_input_size_1000).maximum_acyclic_subgraph()
        post_time_two_approx_four = time.time()
        solving_time_two_approx_four = post_time_two_approx_four - pre_time_two_approx_four
        self.assertIsNotNone(output_two_approx_four)
        score_two_approx_four = scoreSolution(self.matrix_input_size_1000, output_two_approx_four)
        file_string_four = "Two Approximation, |V| = 1000: Score = %.4f, Time = %.4f\n" % (
            score_two_approx_four,
            solving_time_two_approx_four,
        )
        self.benchmark_file.write(file_string_four)
コード例 #6
0
ファイル: benchmark.py プロジェクト: afrancis13/MAS-Solver
    def test_benchmark_simulated_annealing(self):
        # |V| = 4
        pre_time_sa_one = time.time()
        output_sa_one = SimulatedAnnealingSolver(
            range(len(self.matrix_input_brute_force_two)), self.matrix_input_brute_force_two
        ).maximum_acyclic_subgraph()
        post_time_sa_one = time.time()
        solving_time_sa_one = post_time_sa_one - pre_time_sa_one
        self.assertIsNotNone(output_sa_one)
        score_sa_one = scoreSolution(self.matrix_input_brute_force_two, output_sa_one)
        file_string_one = "Simulated Annealing, |V| = 4: Score = %.4f, Time = %.4f\n" % (
            score_sa_one,
            solving_time_sa_one,
        )
        self.benchmark_file.write(file_string_one)

        # |V| = 25
        pre_time_sa_two = time.time()
        output_sa_two = SimulatedAnnealingSolver(
            range(len(self.matrix_input_brute_force_five)), self.matrix_input_brute_force_five
        ).maximum_acyclic_subgraph()
        post_time_sa_two = time.time()
        solving_time_sa_two = post_time_sa_two - pre_time_sa_two
        self.assertIsNotNone(output_sa_two)
        score_sa_two = scoreSolution(self.matrix_input_brute_force_five, output_sa_two)
        file_string_two = "Simulated Annealing, |V| = 25: Score = %.4f, Time = %.4f\n" % (
            score_sa_two,
            solving_time_sa_two,
        )
        self.benchmark_file.write(file_string_two)

        # |V| = 100
        pre_time_sa_three = time.time()
        output_sa_three = SimulatedAnnealingSolver(
            range(len(self.matrix_input_size_100)), self.matrix_input_size_100
        ).maximum_acyclic_subgraph()
        post_time_sa_three = time.time()
        solving_time_sa_three = post_time_sa_three - pre_time_sa_three
        self.assertIsNotNone(output_sa_three)
        score_sa_three = scoreSolution(self.matrix_input_size_100, output_sa_three)
        file_string_three = "Simulated Annealing, |V| = 100: Score = %.4f, Time = %.4f\n" % (
            score_sa_three,
            solving_time_sa_three,
        )
        self.benchmark_file.write(file_string_three)
コード例 #7
0
ファイル: benchmark.py プロジェクト: afrancis13/MAS-Solver
    def test_benchmark_brute_force(self):
        # |V| = 2
        pre_time_brute_force_one = time.time()
        output_brute_force_one = BruteForceSolver(self.matrix_input_brute_force_one).maximum_acyclic_subgraph()
        post_time_brute_force_one = time.time()
        solving_time_brute_force_one = post_time_brute_force_one - pre_time_brute_force_one
        self.assertIsNotNone(output_brute_force_one)
        score_brute_force_one = scoreSolution(self.matrix_input_brute_force_one, output_brute_force_one)
        file_string_one = "Brute Force, |V| = 2: Score = %.4f, Time = %.4f\n" % (
            score_brute_force_one,
            solving_time_brute_force_one,
        )
        self.benchmark_file.write(file_string_one)
        print ("Finished Benchmark 1, Brute Force")

        # |V| = 4
        pre_time_brute_force_two = time.time()
        output_brute_force_two = BruteForceSolver(self.matrix_input_brute_force_two).maximum_acyclic_subgraph()
        post_time_brute_force_two = time.time()
        solving_time_brute_force_two = post_time_brute_force_two - pre_time_brute_force_two
        self.assertIsNotNone(output_brute_force_two)
        score_brute_force_two = scoreSolution(self.matrix_input_brute_force_two, output_brute_force_two)
        file_string_two = "Brute Force, |V| = 4: Score = %.4f, Time = %.4f\n" % (
            score_brute_force_two,
            solving_time_brute_force_two,
        )
        self.benchmark_file.write(file_string_two)
        print "Finished Benchmark 2, Brute Force"

        # |V| = 8
        pre_time_brute_force_three = time.time()
        output_brute_force_three = BruteForceSolver(self.matrix_input_brute_force_three).maximum_acyclic_subgraph()
        post_time_brute_force_three = time.time()
        solving_time_brute_force_three = post_time_brute_force_three - pre_time_brute_force_three
        self.assertIsNotNone(output_brute_force_three)
        score_brute_force_three = scoreSolution(self.matrix_input_brute_force_three, output_brute_force_three)
        file_string_three = "Brute Force, |V| = 8: Score = %.4f, Time = %.4f\n" % (
            score_brute_force_three,
            solving_time_brute_force_three,
        )
        self.benchmark_file.write(file_string_three)
        print "Finished Benchmark 3, Brute Force"
コード例 #8
0
ファイル: brute_force.py プロジェクト: afrancis13/MAS-Solver
 def maximum_acyclic_subgraph(self):
     vertices = range(len(self.adj_matrix))
     vertex_permutations = permutations(vertices)
     max_score = 0
     max_ordering = vertices
     for permutation in vertex_permutations:
         score = scoreSolution(self.adj_matrix, permutation)
         if score > max_score:
             max_score = score
             max_ordering = permutation
     return list(max_ordering)
コード例 #9
0
ファイル: benchmark.py プロジェクト: afrancis13/MAS-Solver
    def test_benchmark_feedback_arc_set_ip(self):
        # |V| = 2
        pre_time_ip_one = time.time()
        output_solver_one = FinalSolver(self.matrix_input_brute_force_one)
        output_ip_one = output_solver_one.obtain_library_solution(output_solver_one.adj_matrix, force_ip=True)
        post_time_ip_one = time.time()
        solving_time_ip_one = post_time_ip_one - pre_time_ip_one
        self.assertIsNotNone(output_ip_one)
        score_ip_one = scoreSolution(self.matrix_input_brute_force_one, output_ip_one)
        file_string_one = "Ip Approximation, |V| = 2: Score = %.4f, Time = %.4f\n" % (score_ip_one, solving_time_ip_one)
        self.benchmark_file.write(file_string_one)

        # |V| = 4
        pre_time_ip_two = time.time()
        output_solver_two = FinalSolver(self.matrix_input_brute_force_two)
        output_ip_two = output_solver_two.obtain_library_solution(output_solver_two.adj_matrix, force_ip=True)
        post_time_ip_two = time.time()
        solving_time_ip_two = post_time_ip_two - pre_time_ip_two
        self.assertIsNotNone(output_ip_two)
        score_ip_two = scoreSolution(self.matrix_input_brute_force_two, output_ip_two)
        file_string_two = "Ip Approximation, |V| = 4: Score = %.4f, Time = %.4f\n" % (score_ip_two, solving_time_ip_two)
        self.benchmark_file.write(file_string_two)

        # |V| = 8
        pre_time_ip_three = time.time()
        output_solver_three = FinalSolver(self.matrix_input_brute_force_three)
        output_ip_three = output_solver_three.obtain_library_solution(output_solver_three.adj_matrix, force_ip=True)
        post_time_ip_three = time.time()
        solving_time_ip_three = post_time_ip_three - pre_time_ip_three
        self.assertIsNotNone(output_ip_three)
        score_ip_three = scoreSolution(self.matrix_input_brute_force_three, output_ip_three)
        file_string_three = "Ip Approximation, |V| = 8: Score = %.4f, Time = %.4f\n" % (
            score_ip_three,
            solving_time_ip_three,
        )
        self.benchmark_file.write(file_string_three)
コード例 #10
0
    def test_final_solver(self):
        '''
        TODO: Add more tests, especially on our own instances.

        Tests a variety of input graphs (the same as those tested for the two
        approximation). Since the algorithm is randomized, the seed is set,
        though this algorithm should converge towards an optimal solution at a
        much faster rate, especially on graphs of this size.

        Gyazo links are attached for the constructed graphs, and the first cut
        made is denoted for each graph (the seed is set accordingly).
        1. Test input one: https://gyazo.com/74dcc4c2eccd617381867274ce981859
        2. Test input DAG one: https://gyazo.com/eae09e06bf5f4b0150977bf487399001
        3. Test input DAG two: https://gyazo.com/8b241b60a8339d993fcda0b6ca6401a6
        4. Test input cycle: https://gyazo.com/48c0e885e8baca8c0bd34a2f290171c8
        5. Test input nonplanar one: https://gyazo.com/e91def6e27e59de97a5a779b87e659a9
        6. Test input nonplanar two: https://gyazo.com/1295ad7498c8f80ff7ff260287a8d0ae
        '''
        random.seed(170)
        self.maxDiff = None
        expected_output_one = [2, 1, 3, 0]
        observed_output_one = \
            FinalSolver(self.matrix_input_one).maximum_acyclic_subgraph()
        expected_score_one = 4.0
        observed_score_one = scoreSolution(self.matrix_input_one, observed_output_one)
        self.assertEquals(observed_output_one, expected_output_one)
        self.assertEquals(observed_score_one, expected_score_one)

        expected_output_dag_one = [0, 1, 2, 3]
        observed_output_dag_one = \
            FinalSolver(self.matrix_input_dag_one).maximum_acyclic_subgraph()
        expected_score_dag_one = 3.0
        observed_score_dag_one = scoreSolution(self.matrix_input_dag_one, observed_output_dag_one)
        self.assertEquals(observed_output_dag_one, expected_output_dag_one)
        self.assertEquals(observed_score_dag_one, expected_score_dag_one)

        expected_output_cycle = [3, 0, 1, 2]
        observed_output_cycle = \
            FinalSolver(self.matrix_input_cycle).maximum_acyclic_subgraph()
        expected_score_cycle = 3.0
        observed_score_cycle = scoreSolution(self.matrix_input_cycle, observed_output_cycle)
        self.assertEquals(observed_output_cycle, expected_output_cycle)
        self.assertEquals(observed_score_cycle, expected_score_cycle)

        # Could also be linearized as [1, 2, 0, 3, 4, 5, 6] but the algorithm
        # should break ties arbitrarily and this is chosen
        expected_output_dag_two = [1, 0, 2, 3, 4, 5, 6]
        observed_output_dag_two = \
            FinalSolver(self.matrix_input_dag_two).maximum_acyclic_subgraph()
        expected_score_dag_one = 8.0
        observed_score_dag_one = scoreSolution(self.matrix_input_dag_two, observed_output_dag_two)
        self.assertEquals(observed_output_dag_two, expected_output_dag_two)
        self.assertEquals(observed_score_dag_one, expected_score_dag_one)

        expected_output_nonplanar_one = [8, 9, 10, 13, 0, 1, 2, 3, 4, 5, 11, 6, 7, 12]
        observed_output_nonplanar_one = \
            FinalSolver(self.matrix_input_nonplanar_one).maximum_acyclic_subgraph()
        expected_score_nonplanar_one = 19.0
        observed_score_nonplanar_one = scoreSolution(
            self.matrix_input_nonplanar_one,
            observed_output_nonplanar_one
        )
        self.assertEquals(observed_output_nonplanar_one, expected_output_nonplanar_one)
        self.assertEquals(observed_score_nonplanar_one, expected_score_nonplanar_one)

        expected_output_nonplanar_two = [5, 0, 7, 6, 4, 3, 1, 2]
        observed_output_nonplanar_two = \
            FinalSolver(self.matrix_input_nonplanar_two).maximum_acyclic_subgraph()
        expected_score_nonplanar_two = 18.0
        observed_score_nonplanar_two = scoreSolution(
            self.matrix_input_nonplanar_two,
            observed_output_nonplanar_two
        )
        self.assertEquals(observed_output_nonplanar_two, expected_output_nonplanar_two)
        self.assertEquals(observed_score_nonplanar_two, expected_score_nonplanar_two)

        observed_output_foster = \
            FinalSolver(self.matrix_foster).maximum_acyclic_subgraph()
        expected_score_foster = 124.0
        observed_score_foster = scoreSolution(self.matrix_foster, observed_output_foster)
        self.assertEquals(observed_score_foster, expected_score_foster)

        observed_output_gray = \
            FinalSolver(self.matrix_input_gray).maximum_acyclic_subgraph()
        expected_score_gray = 75.0
        observed_score_gray = scoreSolution(self.matrix_input_gray, observed_output_gray)
        self.assertEquals(observed_score_gray, expected_score_gray)

        observed_output_new_graph = \
            FinalSolver(self.matrix_new_graph).maximum_acyclic_subgraph()
        expected_score_new_graph = 55.0
        observed_score_new_graph = scoreSolution(self.matrix_new_graph, observed_output_new_graph)
        self.assertEquals(observed_score_new_graph, expected_score_new_graph)
コード例 #11
0
ファイル: final_solver.py プロジェクト: afrancis13/MAS-Solver
    def maximum_acyclic_subgraph(self):
        topo_sort = DAGSolver(self.adj_matrix).topological_sort()

        if topo_sort is not None:
            print "Score is %.4f" % scoreSolution(self.adj_matrix, topo_sort)
            return topo_sort

        # For some reason, this is returned in reverse order by the algorithm.
        # So reverse to get the topologically sorted SCCs.
        scc_graph = self.find_strongly_connected_components()[::-1]

        solution = []

        for scc in scc_graph:
            scc_adj_matrix = self.create_scc_adj_matrix(scc)
            if len(scc_adj_matrix) <= 8:
                brute_force_solver = BruteForceSolver(scc_adj_matrix)
                brute_force_solution = brute_force_solver.maximum_acyclic_subgraph()
                scc_solution = [i for i in range(len(scc_adj_matrix))]
                for i in range(len(brute_force_solution)):
                    scc_conversion_index = brute_force_solution[i]
                    scc_solution[i] = scc[scc_conversion_index]
            else:
                pq = []
                library_solution = self.obtain_library_solution(scc_adj_matrix)
                library_score = scoreSolution(scc_adj_matrix, library_solution)

                print "Finished scoring using library"

                two_approx_solver = TwoApproximationSolver(scc_adj_matrix)
                for i in range(1000):
                    this_solution = two_approx_solver.maximum_acyclic_subgraph()
                    this_score = scoreSolution(scc_adj_matrix, this_solution)

                    # If pq still small, add this solution
                    # Otherwise, new score better than the worst one so far
                    if len(pq) < 5:
                        heapq.heappush(pq, (this_score, this_solution))
                    elif this_score > pq[0][0]:
                        heapq.heappushpop(pq, (this_score, this_solution))

                print "Finished Two Approximation"

                # Add library solution last so it doesn't get overwritten
                heapq.heappush(pq, (library_score, library_solution))

                annealing_score = -float('inf')
                annealing_solution = None
                while len(pq) > 0:
                    curr_soln = heapq.heappop(pq)
                    curr_ordering = curr_soln[1]
                    simulated_annealing_solver = SimulatedAnnealingSolver(
                        curr_ordering,
                        scc_adj_matrix
                    )
                    curr_annealing_solution = simulated_annealing_solver.maximum_acyclic_subgraph()
                    curr_annealing_score = scoreSolution(scc_adj_matrix, curr_annealing_solution)
                    if curr_annealing_score > annealing_score:
                        annealing_score = curr_annealing_score
                        annealing_solution = curr_annealing_solution

                scc_solution = [i for i in range(len(scc_adj_matrix))]
                for i in range(len(annealing_solution)):
                    scc_conversion_index = annealing_solution[i]
                    scc_solution[i] = scc[scc_conversion_index]

            solution.extend(scc_solution)

        print "Score is %.4f" % scoreSolution(self.adj_matrix, solution)
        return solution