Raise temperature and do some more changes

This commit is contained in:
Segcolt 2024-10-14 00:03:11 -03:00
parent 5c9ba9cfdf
commit d3b3e682db
2 changed files with 86 additions and 49 deletions

View File

@ -4,11 +4,11 @@
#include "sa.hpp" #include "sa.hpp"
#ifndef TEMP #ifndef TEMP
#define TEMP 1000000 #define TEMP 1000
#endif #endif
#ifndef ALPHA #ifndef ALPHA
#define ALPHA 0.99 #define ALPHA 0.999
#endif #endif
#ifndef TEMP_MIN #ifndef TEMP_MIN

131
sa.hpp
View File

@ -8,12 +8,16 @@
#include <iostream> #include <iostream>
#include <random> #include <random>
#include <set> #include <set>
#include <utility>
#include <vector> #include <vector>
#include <queue>
namespace sa { namespace sa {
using content = std::priority_queue<long long, std::vector<long long>, std::greater<>>;
class box { class box {
std::multiset<long long> items; content items;
long long fullness{}; long long fullness{};
friend void swap(box &one, box &two) { friend void swap(box &one, box &two) {
@ -23,56 +27,62 @@ class box {
swap(one.fullness, two.fullness); swap(one.fullness, two.fullness);
} }
void pop() {
fullness -= items.top();
items.pop();
}
public: public:
box() = default; box() = default;
box(const std::multiset<long long> &multiset, long long fullness): box(const content &items, long long fullness):
items(multiset), fullness(fullness) {} items(items), fullness(fullness) {}
void add_item(long long item) { void add_item(long long item) {
fullness += item; fullness += item;
items.insert(item); items.push(item);
} }
void clear() { void clear() {
items.clear(); while (!items.empty()) {
items.pop();
}
fullness = 0; fullness = 0;
} }
void pop() { auto swappable10(box &other, int capacity) -> bool {
fullness -= *items.begin(); return items.top() + other.fullness <= capacity;
items.erase(items.begin());
} }
auto swap10(box &other, int capacity) -> bool { void swap10(box &other) {
if (*items.begin() + other.fullness > capacity) { other.add_item(items.top());
return false; pop();
} }
other.add_item(*items.begin());
pop(); return true; }
auto swap11(box &other, int capacity) -> bool { auto swappable11(box &other, int capacity) -> bool {
long long choice1 = *items.begin(); long long choice1 = items.top();
long long choice2 = *other.items.begin(); long long choice2 = other.items.top();
return choice1 + other.fullness - choice2 <= capacity &&
choice2 + fullness - choice1 <= capacity;
}
if (choice1 + other.fullness - choice2 > capacity || void swap11(box &other) {
choice2 + fullness - choice1 > capacity) { long long choice1 = items.top();
return false; long long choice2 = other.items.top();
}
pop(); pop();
other.pop(); other.pop();
add_item(choice2); add_item(choice2);
other.add_item(choice1); other.add_item(choice1);
return true;
} }
void print(int ind) const { void print(int ind) {
std::cout << "Caixa " << ind << ":"; std::cout << "Caixa " << ind << ":";
for (auto item : items) { content tmp;
std::cout << ' ' << item; while (!items.empty()) {
std::cout << ' ' << items.top();
items.pop();
} }
std::cout << '\n'; std::cout << '\n';
} }
@ -101,6 +111,31 @@ class solution {
swap(one.iteration, two.iteration); swap(one.iteration, two.iteration);
} }
void random_swap(int choice, std::vector<int> &sequence10, std::vector<int> &sequence11) {
typedef void (box::*swap)(box&);
swap swaps[2] = {
&box::swap10,
&box::swap11
};
std::vector<int>* 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: public:
solution() = default; solution() = default;
@ -142,33 +177,35 @@ class solution {
} }
void setneighbor() { // Gera um vizinho da solução void setneighbor() { // Gera um vizinho da solução
std::uniform_int_distribution<> dist(0, (int)boxes.size() - 1); int choice = std::uniform_int_distribution<>(0, (int)boxes.size() - 1)(gen);
std::vector<int> sequence10;
std::vector<int> sequence11;
sequence10.reserve(boxes.size());
sequence11.reserve(boxes.size());
int choice = dist(gen);
std::vector<int> sequence(boxes.size() - 1);
for (size_t i = 0; i < choice; i++) { for (size_t i = 0; i < choice; i++) {
sequence[i] = 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++) { for (size_t i = choice + 1; i < boxes.size(); i++) {
sequence[i - 1] = i; if (boxes[choice].swappable10(boxes[i], capacity)) {
} sequence10.push_back((int)i);
}
shuffle(sequence.begin(), sequence.end(), gen); if (boxes[choice].swappable11(boxes[i], capacity)) {
sequence11.push_back((int)i);
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) { random_swap(choice, sequence10, sequence11);
if (boxes[choice].swap11(boxes[ind], capacity)) { if (boxes[choice].empty()) {
return; swap(boxes[choice], boxes[boxes.size() - 1]);
} boxes.pop_back();
fitness = (int)boxes.size();
} }
} }
@ -176,7 +213,7 @@ class solution {
std::shuffle(boxes.begin(), boxes.end(), gen); std::shuffle(boxes.begin(), boxes.end(), gen);
} }
void print_sol(char flags = 0) const { void print_sol(char flags = 0) {
if(!(flags & SIMULATED_ANNEALING_DISABLE_SHOWITRNUM)){ if(!(flags & SIMULATED_ANNEALING_DISABLE_SHOWITRNUM)){
std::cout << "Iteração da solução: " << iteration << '\n'; std::cout << "Iteração da solução: " << iteration << '\n';
std::cout << "Número de iterações calculadas: " << iterations << '\n'; std::cout << "Número de iterações calculadas: " << iterations << '\n';