Comments re-added

This commit is contained in:
Daneck1988 2024-10-15 22:45:20 -03:00
parent 7b3b1eb23e
commit 10b10a4f61
3 changed files with 73 additions and 11 deletions

View File

@ -15,6 +15,12 @@
#define TEMP_MIN 10 #define TEMP_MIN 10
#endif #endif
/*
* Função main.
* Usada apenas para ler os items, a capacidade máxima e
* imprimir os dados da melhor solução encontrada.
*/
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char flags = 0; char flags = 0;

View File

@ -1,6 +1,10 @@
#include "sa.hpp" #include "sa.hpp"
#include <cmath> #include <cmath>
/*
* Implementação do algoritmo de SA.
*/
auto sa::solution::simulated_annealing(int capacity, const std::vector<long long> &items, auto sa::solution::simulated_annealing(int capacity, const std::vector<long long> &items,
const double alpha, double temp, const double alpha, double temp,
const double temp_min)->sa::solution const double temp_min)->sa::solution

View File

@ -22,6 +22,7 @@ class box {
content items; content items;
long long fullness{}; long long fullness{};
/* Troca uma caixa com a outra. */
friend void swap(box &one, box &two) { friend void swap(box &one, box &two) {
using std::swap; using std::swap;
@ -29,6 +30,7 @@ class box {
swap(one.fullness, two.fullness); swap(one.fullness, two.fullness);
} }
/* Remove o menor item da caixa. */
void pop() { void pop() {
fullness -= items.top(); fullness -= items.top();
items.pop(); items.pop();
@ -38,14 +40,20 @@ class box {
box() = default; box() = default;
box(const content &items, long long fullness): /*
items(items), fullness(fullness) {} * Inicialia uma caixa a partir de um conjunto de items e da soma total
* dos items.
*/
box(content items, long long fullness):
items(std::move(items)), fullness(fullness) {}
/* Adiciona um item a caixa. */
void add_item(long long item) { void add_item(long long item) {
fullness += item; fullness += item;
items.push(item); items.push(item);
} }
/* Limpa a caixa. */
void clear() { void clear() {
while (!items.empty()) { while (!items.empty()) {
items.pop(); items.pop();
@ -53,15 +61,27 @@ class box {
fullness = 0; fullness = 0;
} }
/*
* Verifica se é possível move o menor item da caixa atual para a
* caixa "other" sem violar as restrições de capacidade.
*/
auto swappable10(box &other, int capacity) -> bool { auto swappable10(box &other, int capacity) -> bool {
return items.top() + other.fullness <= capacity; return items.top() + other.fullness <= capacity;
} }
/*
* Move o menor item da caixa atual para a caixa "other".
*/
void swap10(box &other) { void swap10(box &other) {
other.add_item(items.top()); other.add_item(items.top());
pop(); pop();
} }
/*
* Verifica se é possivel realizar "swap11" com a caixa "other" sem
* violar as restrições de capacidade, também verificando se ambos os menores
* items são os mesmos.
*/
auto swappable11(box &other, int capacity) -> bool { auto swappable11(box &other, int capacity) -> bool {
long long choice1 = items.top(); long long choice1 = items.top();
long long choice2 = other.items.top(); long long choice2 = other.items.top();
@ -70,6 +90,10 @@ class box {
choice2 + fullness - choice1 <= capacity; choice2 + fullness - choice1 <= capacity;
} }
/*
* Troca o menor item da caixa atual com o menor item da caixa
* "other"
*/
void swap11(box &other) { void swap11(box &other) {
long long choice1 = items.top(); long long choice1 = items.top();
long long choice2 = other.items.top(); long long choice2 = other.items.top();
@ -80,6 +104,7 @@ class box {
other.add_item(choice1); other.add_item(choice1);
} }
/* Imprime todos os items da caixa junto com um identificador. */
void print(int ind) { void print(int ind) {
std::cout << "Caixa " << ind << ":"; std::cout << "Caixa " << ind << ":";
content tmp; content tmp;
@ -90,6 +115,7 @@ class box {
std::cout << '\n'; std::cout << '\n';
} }
/* Retorna um booleano indicando se a caixa está vazia. */
[[nodiscard]] auto empty() const -> bool { [[nodiscard]] auto empty() const -> bool {
return fullness == 0; return fullness == 0;
} }
@ -102,6 +128,10 @@ class solution {
int iterations; int iterations;
int iteration; int iteration;
/*
* Função para trocar duas soluções.
* Overload da função std::swap.
*/
friend void swap(solution &one, solution &two) { friend void swap(solution &one, solution &two) {
using std::swap; using std::swap;
@ -112,6 +142,10 @@ class solution {
swap(one.iteration, two.iteration); swap(one.iteration, two.iteration);
} }
/*
* Função para usar o swap10 ou swap11 aleatoriamente quando
* possível.
*/
void random_swap(int choice, std::vector<int> &sequence10, std::vector<int> &sequence11) { void random_swap(int choice, std::vector<int> &sequence10, std::vector<int> &sequence11) {
typedef void (box::*swap)(box&); typedef void (box::*swap)(box&);
swap swaps[2] = { swap swaps[2] = {
@ -139,28 +173,30 @@ class solution {
public: public:
solution() = default; solution() = default;
/* Inicializa uma solução a partir da outra. */
solution(const solution &other, int itr): boxes(other.boxes), fitness(other.fitness), solution(const solution &other, int itr): boxes(other.boxes), fitness(other.fitness),
capacity(other.capacity), iteration(itr) {} capacity(other.capacity), iteration(itr) {}
solution(const std::vector<long long> &items, int capacity): // Gera a solução inicial /* Gera a solução inicial a partir dos items disponíveis. */
solution(const std::vector<long long> &items, int capacity):
capacity(capacity), iteration(0) { capacity(capacity), iteration(0) {
std::multiset<long long> its; std::multiset<long long> its; // Items ordenados.
for (auto i : items) { for (auto i : items) {
its.insert(i); its.insert(i);
} }
long long cap = capacity; long long cap = capacity; // Capacidade restante da caixa atual.
box tmp; box tmp; // Caixa atual.
while (!its.empty()) { while (!its.empty()) {
auto itr = its.upper_bound(cap); auto itr = its.upper_bound(cap);
if (itr == its.begin()) { if (itr == its.begin()) { // Caixa está cheia, cria-se outra.
cap = capacity; cap = capacity;
cap -= *its.begin(); cap -= *its.begin();
itr = its.begin(); itr = its.begin();
this->boxes.emplace_back(tmp); this->boxes.emplace_back(tmp);
tmp.clear(); tmp.clear();
} else { } else { // Caixa consegue colocar outro elemento.
itr--; itr--;
cap -= *itr; cap -= *itr;
} }
@ -174,10 +210,11 @@ class solution {
fitness = (int)this->boxes.size(); fitness = (int)this->boxes.size();
} }
void setneighbor() { // Gera um vizinho da solução /* Muda a solução atual para um de seus vizinhos. */
void setneighbor() {
int choice = std::uniform_int_distribution<>(0, (int)boxes.size() - 1)(rng::rng); int choice = std::uniform_int_distribution<>(0, (int)boxes.size() - 1)(rng::rng);
std::vector<int> sequence10; std::vector<int> sequence10; // Possíveis candidatos para swap10
std::vector<int> sequence11; std::vector<int> sequence11; // Possíveis candidatos para swap11
sequence10.reserve(boxes.size()); sequence10.reserve(boxes.size());
sequence11.reserve(boxes.size()); sequence11.reserve(boxes.size());
@ -201,12 +238,22 @@ class solution {
random_swap(choice, sequence10, sequence11); random_swap(choice, sequence10, sequence11);
if (boxes[choice].empty()) { if (boxes[choice].empty()) {
/*
* Caixa agora está vazia, é possível remove-la.
*/
swap(boxes[choice], boxes[boxes.size() - 1]); swap(boxes[choice], boxes[boxes.size() - 1]);
boxes.pop_back(); boxes.pop_back();
fitness = (int)boxes.size(); fitness = (int)boxes.size();
} }
} }
/*
* Imprime todas as informações da solução:
* - Número de caixas
* - Items em cada caixa
* - Iteração onde foi encontrada a solução
* - Iterações totais ate o fim do algoritmo
*/
void print_sol(char flags = 0) { 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';
@ -221,10 +268,15 @@ class solution {
} }
} }
/* Pôe o número de iterações totais para a solução. */
void setiterations(int itr) { void setiterations(int itr) {
iterations = itr; iterations = itr;
} }
/*
* Declaração do algoritmo, sua implementação está no arquivo
* sa.cpp.
*/
static auto simulated_annealing(int capacity, const std::vector<long long> &items, static auto simulated_annealing(int capacity, const std::vector<long long> &items,
double alpha, double temp, double alpha, double temp,
double temp_min) -> solution; double temp_min) -> solution;