Compare commits

..

5 Commits

4 changed files with 112 additions and 9 deletions

29
main.cpp Normal file
View File

@ -0,0 +1,29 @@
#include <iostream>
#include <vector>
#include "sa.hpp"
#ifndef TEMP
#define TEMP 1000
#endif
#ifndef ALPHA
#define ALPHA 0.99
#endif
int main(int argc, char *argv[])
{
int number_of_items = 0;
int capacity = 0;
std::cin >> number_of_items >> capacity;
std::vector<long long> items(number_of_items);
for (auto &i : items) {
std::cin >> i;
}
sa::solution act = sa::solution::simulated_annealing(capacity, items,
TEMP, ALPHA);
act.print_sol();
}

7
run.sh Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
IFS=$'\n'
for file in $(find test -type f); do
build/main.out < $file
done

33
sa.cpp Normal file
View File

@ -0,0 +1,33 @@
#include "sa.hpp"
#include <cmath>
auto sa::solution::simulated_annealing(int capacity, const std::vector<long long> &items,
const double alpha, double temp)->sa::solution
{
sa::solution best(items, capacity);
best.randomize();
sa::solution prev = best;
std::random_device rdevice;
std::default_random_engine eng(rdevice());
std::uniform_real_distribution<> rand(0, 1);
const double temp_min = 0.30;
while (temp < temp_min) {
sa::solution neighbor(prev);
neighbor.setneighbor();
int diff = prev.fitness - neighbor.fitness;
if (diff <= 0 || std::exp(-diff / temp) > rand(eng)) {
prev.swap(neighbor);
}
temp *= alpha;
if (prev.fitness < best.fitness) {
best = prev;
}
}
return best;
}

52
sa.hpp
View File

@ -1,9 +1,11 @@
#ifndef SIMULATED_ANNEALING_HEADER_12647_H #ifndef SIMULATED_ANNEALING_HEADER_12647_H
#define SIMULATED_ANNEALING_HEADER_12647_H #define SIMULATED_ANNEALING_HEADER_12647_H
#include <vector>
#include <algorithm> #include <algorithm>
#include <iostream>
#include <queue>
#include <random> #include <random>
#include <vector>
namespace sa { namespace sa {
@ -14,7 +16,7 @@ class solution {
int fitness; int fitness;
auto calculate_boxes()->int { auto calculate_boxes()->int {
int count = 0; int count = 1;
long long now = 0; long long now = 0;
for (auto i : items) { for (auto i : items) {
@ -29,16 +31,23 @@ class solution {
return count; return count;
} }
public: static void print_box(int box, std::queue<long long> &stored) {
solution(const std::vector<long long> &items, int capacity): // Gera a solução inicial std::cout << "Caixa " << box << ":";
items(items), capacity(capacity), fitness(calculate_boxes()) { while (!stored.empty()) {
std::random_device rdevice; std::cout << ' ' << stored.front();
gen.seed(rdevice()); stored.pop();
}
std::cout << '\n';
} }
solution(const solution &sol): public:
items(sol.items), gen(sol.gen), capacity(sol.capacity) { // Gera um vizinho da solução solution() = default;
solution(const std::vector<long long> &items, int capacity): // Gera a solução inicial
items(items), gen(std::random_device()()), capacity(capacity),
fitness(calculate_boxes()) {}
void setneighbor() { // Gera um vizinho da solução
std::uniform_int_distribution<> dist(0, items.size() - 1); std::uniform_int_distribution<> dist(0, items.size() - 1);
int first = dist(gen); int first = dist(gen);
int second = 0; int second = 0;
@ -60,6 +69,31 @@ class solution {
std::swap(capacity, other.capacity); std::swap(capacity, other.capacity);
std::swap(gen, other.gen); std::swap(gen, other.gen);
} }
void print_sol() const {
std::cout << "Número de caixas: " << fitness << '\n';
int box_now = 1;
long long now = 0;
std::queue<long long> items_stored;
for (auto i : items) {
if (now + i > capacity) {
print_box(box_now, items_stored);
box_now++;
now = i;
} else {
now += i;
}
items_stored.push(i);
}
print_box(box_now, items_stored);
std::cout << '\n';
}
static auto simulated_annealing(int capacity, const std::vector<long long> &items,
double alpha, double temp)->solution;
}; };
} // namespace sa } // namespace sa