#ifndef SIMULATED_ANNEALING_HEADER_12647_H #define SIMULATED_ANNEALING_HEADER_12647_H #define SIMULATED_ANNEALING_DISABLE_SHOWCRATES 1 #define SIMULATED_ANNEALING_DISABLE_SHOWITRNUM 2 #include #include #include #include #include namespace sa { class box { std::multiset items; long long fullness{}; friend void swap(box &one, box &two) { using std::swap; swap(one.items, two.items); swap(one.fullness, two.fullness); } public: box() = default; box(const std::multiset &multiset, long long fullness): items(multiset), fullness(fullness) {} void add_item(long long item) { fullness += item; items.insert(item); } void clear() { items.clear(); fullness = 0; } void pop() { fullness -= *items.begin(); items.erase(items.begin()); } auto swap10(box &other, int capacity) -> bool { if (*items.begin() + other.fullness > capacity) { return false; } other.add_item(*items.begin()); pop(); return true; } auto swap11(box &other, int capacity) -> bool { long long choice1 = *items.begin(); long long choice2 = *other.items.begin(); if (choice1 + other.fullness - choice2 > capacity || choice2 + fullness - choice1 > capacity) { return false; } pop(); other.pop(); add_item(choice2); other.add_item(choice1); return true; } void print(int ind) const { std::cout << "Caixa " << ind << ":"; for (auto item : items) { std::cout << ' ' << item; } std::cout << '\n'; } [[nodiscard]] auto empty() const -> bool { return fullness == 0; } }; class solution { std::vector boxes; std::default_random_engine gen; int capacity; int fitness; int iterations; int iteration; friend void swap(solution &one, solution &two) { using std::swap; swap(one.boxes, two.boxes); swap(one.gen, two.gen); swap(one.capacity, two.capacity); swap(one.fitness, two.fitness); swap(one.iterations, two.iterations); swap(one.iteration, two.iteration); } public: solution() = default; solution(const solution &other, int itr): boxes(other.boxes), gen(other.gen), capacity(other.capacity), fitness(other.fitness), iteration(itr) {} solution(const std::vector &items, int capacity): // Gera a solução inicial gen(std::random_device()()), capacity(capacity), iteration(0) { std::multiset its; for (auto i : items) { its.insert(i); } long long cap = capacity; box tmp; while (!its.empty()) { auto itr = its.upper_bound(cap); if (itr == its.begin()) { cap = capacity; cap -= *its.begin(); itr = its.begin(); this->boxes.emplace_back(tmp); tmp.clear(); } else { itr--; cap -= *itr; } tmp.add_item(*itr); its.erase(itr); } if (!tmp.empty()) { this->boxes.emplace_back(tmp); } fitness = (int)this->boxes.size(); } void setneighbor() { // Gera um vizinho da solução std::uniform_int_distribution<> dist(0, (int)boxes.size() - 1); int choice = dist(gen); std::vector sequence(boxes.size() - 1); for (size_t i = 0; i < choice; i++) { sequence[i] = i; } for (size_t i = choice + 1; i < boxes.size(); i++) { sequence[i - 1] = i; } shuffle(sequence.begin(), sequence.end(), gen); for (auto ind : sequence) { if (boxes[choice].swap10(boxes[ind], capacity)) { if (boxes[choice].empty()) { boxes.erase(boxes.begin() + choice); } fitness = (int)boxes.size(); return; } } for (auto ind : sequence) { if (boxes[choice].swap11(boxes[ind], capacity)) { return; } } } void randomize() { std::shuffle(boxes.begin(), boxes.end(), gen); } void print_sol(char flags = 0) const { if(!(flags & SIMULATED_ANNEALING_DISABLE_SHOWITRNUM)){ std::cout << "Iteração da solução: " << iteration << '\n'; std::cout << "Número de iterações calculadas: " << iterations << '\n'; } std::cout << "Número de caixas: " << fitness << '\n'; if(!(flags & SIMULATED_ANNEALING_DISABLE_SHOWCRATES)){ for (size_t i = 0; i < boxes.size(); i++) { boxes[i].print((int)i + 1); } } } void setiterations(int itr) { iterations = itr; } static auto simulated_annealing(int capacity, const std::vector &items, double alpha, double temp, double temp_min) -> solution; }; } // namespace sa #endif