#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 #include #include namespace sa { using content = std::priority_queue, std::greater<>>; class box { content items; long long fullness{}; friend void swap(box &one, box &two) { using std::swap; swap(one.items, two.items); swap(one.fullness, two.fullness); } void pop() { fullness -= items.top(); items.pop(); } public: box() = default; box(const content &items, long long fullness): items(items), fullness(fullness) {} void add_item(long long item) { fullness += item; items.push(item); } void clear() { while (!items.empty()) { items.pop(); } fullness = 0; } auto swappable10(box &other, int capacity) -> bool { return items.top() + other.fullness <= capacity; } void swap10(box &other) { other.add_item(items.top()); pop(); } auto swappable11(box &other, int capacity) -> bool { long long choice1 = items.top(); long long choice2 = other.items.top(); return choice1 + other.fullness - choice2 <= capacity && choice2 + fullness - choice1 <= capacity; } void swap11(box &other) { long long choice1 = items.top(); long long choice2 = other.items.top(); pop(); other.pop(); add_item(choice2); other.add_item(choice1); } void print(int ind) { std::cout << "Caixa " << ind << ":"; content tmp; while (!items.empty()) { std::cout << ' ' << items.top(); items.pop(); } 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); } void random_swap(int choice, std::vector &sequence10, std::vector &sequence11) { typedef void (box::*swap)(box&); swap swaps[2] = { &box::swap10, &box::swap11 }; std::vector* sequences[2] = { &sequence10, &sequence11 }; std::uniform_real_distribution<> rand(0, 1); int now = rand(gen) > 0.3 ? 0 : 1; if (sequences[now]->empty()) { now ^= 1; if (sequences[now]->empty()) { return; } } std::uniform_int_distribution<> dist(0, (int)sequences[now]->size() - 1); (boxes[choice].*swaps[now])(boxes[(*sequences[now])[dist(gen)]]); } 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 int choice = std::uniform_int_distribution<>(0, (int)boxes.size() - 1)(gen); std::vector sequence10; std::vector sequence11; sequence10.reserve(boxes.size()); sequence11.reserve(boxes.size()); for (size_t i = 0; i < choice; i++) { if (boxes[choice].swappable10(boxes[i], capacity)) { sequence10.push_back((int)i); } if (boxes[choice].swappable11(boxes[i], capacity)) { sequence11.push_back((int)i); } } for (size_t i = choice + 1; i < boxes.size(); i++) { if (boxes[choice].swappable10(boxes[i], capacity)) { sequence10.push_back((int)i); } if (boxes[choice].swappable11(boxes[i], capacity)) { sequence11.push_back((int)i); } } random_swap(choice, sequence10, sequence11); if (boxes[choice].empty()) { swap(boxes[choice], boxes[boxes.size() - 1]); boxes.pop_back(); fitness = (int)boxes.size(); } } void randomize() { std::shuffle(boxes.begin(), boxes.end(), gen); } void print_sol(char flags = 0) { 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