def test_solution_valid_with_required_cities(self):
        required_cities = [self.possible_cities["Cordoba"]]
        max_trip_time = 14
        route = [
            self.possible_cities["Cordoba"], self.possible_cities["Rosario"],
            self.possible_cities["Ushuaia"]
        ]
        solution = Solution(origin_city=self.origin_city,
                            cities=route,
                            required_cities=required_cities,
                            max_trip_time=max_trip_time)

        expected_total_stay_time = 6
        self.assertEqual(expected_total_stay_time,
                         solution.get_total_stay_time())

        expected_total_travel_time = 1 + 1 + 3 + 3
        self.assertEqual(expected_total_travel_time,
                         solution.get_total_travel_time())

        expected_total_trip_time = expected_total_stay_time + expected_total_travel_time
        self.assertEqual(expected_total_trip_time,
                         solution.get_total_trip_time())

        self.assertTrue(solution.is_valid_required_city())

        self.assertTrue(solution.is_valid_knapsack_time())

        self.assertTrue(solution.is_valid_total_trip_time())

        self.assertTrue(solution.is_valid())
    def test_solution_valid_with_just_origin_city(self):
        required_cities = []
        max_trip_time = 999999
        route = []
        solution = Solution(origin_city=self.origin_city,
                            cities=route,
                            required_cities=required_cities,
                            max_trip_time=max_trip_time)

        expected_total_stay_time = 0
        self.assertEqual(expected_total_stay_time,
                         solution.get_total_stay_time())

        expected_total_travel_time = 0
        self.assertEqual(expected_total_travel_time,
                         solution.get_total_travel_time())

        expected_total_trip_time = expected_total_stay_time + expected_total_travel_time
        self.assertEqual(expected_total_trip_time,
                         solution.get_total_trip_time())

        self.assertTrue(solution.is_valid_required_city())

        self.assertTrue(solution.is_valid_knapsack_time())

        self.assertTrue(solution.is_valid_total_trip_time())

        self.assertTrue(solution.is_valid())
    def solve(self):
        best_solution_fitness = 0
        best_solution_trip_time = 0
        if self.should_print_stats():
            self.print_stats()
        for x in range(1, len(self.possible_trip_cities) + 1):
            for cities in combinations(self.possible_trip_cities, x):
                self.current_iteration += 1
                if self.should_print_stats():
                    self.print_stats()

                solution = Solution(self.origin_city, cities, self.required_cities,
                                    self.max_trip_time)
                if not solution.is_valid_knapsack_time() or not solution.is_valid_required_city():
                    continue

                # Apply construction heuristic
                optimizer = TSPOptimizerClosestCityStrategy(self.origin_city, solution.cities)
                solution.cities = optimizer.optimize()

                if not solution.is_valid_total_trip_time():
                    continue

                if solution.fitness > best_solution_fitness:
                    # Update best_solution as first objective fitness is better
                    best_solution = solution
                    self.set_best_solution(best_solution)
                    best_solution_fitness = solution.fitness
                    best_solution_trip_time = solution.get_total_travel_time()
                elif solution.fitness == best_solution_fitness:
                    if solution.get_total_travel_time() < best_solution_trip_time:
                        # Update best_solution as first objective fitness is same but
                        # second objective travel time is better
                        best_solution = solution
                        self.set_best_solution(best_solution)
                        best_solution_fitness = solution.fitness
                        best_solution_trip_time = solution.get_total_travel_time()
                # self.add_good_solution(solution)
        self.improve_solutions()
        # return self.best_solution, self.good_solutions
        return self.best_solution
 def get_travel_time(self, cities):
     solution = Solution(self.origin_city, cities, required_cities=[], max_trip_time=0)
     return solution.get_total_travel_time()