Comments re-added
This commit is contained in:
parent
7b3b1eb23e
commit
10b10a4f61
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
74
src/sa.hpp
74
src/sa.hpp
@ -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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user