Bruh, rm
This commit is contained in:
parent
2f3c0c82b7
commit
7b3b1eb23e
45
main.cpp
45
main.cpp
@ -1,45 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "sa.hpp"
|
|
||||||
|
|
||||||
#ifndef TEMP
|
|
||||||
#define TEMP 1000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ALPHA
|
|
||||||
#define ALPHA 0.999
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TEMP_MIN
|
|
||||||
#define TEMP_MIN 10
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
char flags = 0;
|
|
||||||
for(int i = 1; i < argc; i++){
|
|
||||||
if(argv[i][0] == '-'){
|
|
||||||
int j = 1;
|
|
||||||
while(argv[i][j] != '\0'){
|
|
||||||
if(argv[i][j] == 'i') flags |= SIMULATED_ANNEALING_DISABLE_SHOWITRNUM;
|
|
||||||
else if(argv[i][j] == 'c') flags |= SIMULATED_ANNEALING_DISABLE_SHOWCRATES;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
ALPHA, TEMP, TEMP_MIN);
|
|
||||||
|
|
||||||
act.print_sol(flags);
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
#include "random.hpp"
|
|
||||||
|
|
||||||
std::random_device rdevice;
|
|
||||||
std::mt19937_64 rng::rng(rdevice());
|
|
||||||
24
random.hpp
24
random.hpp
@ -1,24 +0,0 @@
|
|||||||
#ifndef RANDOM_HPP_RANDOMNESS_WHATEVER_HEADER_238947837827_H
|
|
||||||
#define RANDOM_HPP_RANDOMNESS_WHATEVER_HEADER_238947837827_H
|
|
||||||
|
|
||||||
#include <random>
|
|
||||||
|
|
||||||
namespace rng {
|
|
||||||
extern std::mt19937_64 rng;
|
|
||||||
|
|
||||||
template<long long start, long long end>
|
|
||||||
auto random_int() -> int
|
|
||||||
{
|
|
||||||
static std::uniform_int_distribution<> rint(start, end);
|
|
||||||
return rint(rng);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int start, int end>
|
|
||||||
auto random_double() -> double
|
|
||||||
{
|
|
||||||
static std::uniform_real_distribution<> rdouble(start, end);
|
|
||||||
return rdouble(rng);
|
|
||||||
}
|
|
||||||
} // namespace rng
|
|
||||||
|
|
||||||
#endif
|
|
||||||
32
sa.cpp
32
sa.cpp
@ -1,32 +0,0 @@
|
|||||||
#include "sa.hpp"
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
auto sa::solution::simulated_annealing(int capacity, const std::vector<long long> &items,
|
|
||||||
const double alpha, double temp,
|
|
||||||
const double temp_min)->sa::solution
|
|
||||||
{
|
|
||||||
sa::solution best(items, capacity);
|
|
||||||
sa::solution prev = best;
|
|
||||||
|
|
||||||
int iteration = 0;
|
|
||||||
|
|
||||||
while (temp > temp_min) {
|
|
||||||
iteration++;
|
|
||||||
sa::solution neighbor(prev, iteration);
|
|
||||||
neighbor.setneighbor();
|
|
||||||
|
|
||||||
long long diff = neighbor.fitness - prev.fitness;
|
|
||||||
if (diff < 0 || rng::random_double<0, 1>() / temp < 0.8) {
|
|
||||||
swap(prev, neighbor);
|
|
||||||
}
|
|
||||||
|
|
||||||
temp *= alpha;
|
|
||||||
|
|
||||||
if (prev.fitness < best.fitness) {
|
|
||||||
best = prev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
best.setiterations(iteration);
|
|
||||||
return best;
|
|
||||||
}
|
|
||||||
235
sa.hpp
235
sa.hpp
@ -1,235 +0,0 @@
|
|||||||
#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 <algorithm>
|
|
||||||
#include <iostream>
|
|
||||||
#include <queue>
|
|
||||||
#include <random>
|
|
||||||
#include <set>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "random.hpp"
|
|
||||||
|
|
||||||
namespace sa {
|
|
||||||
|
|
||||||
using content = std::priority_queue<long long, std::vector<long long>, 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 != choice2 &&
|
|
||||||
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<box> boxes;
|
|
||||||
long long fitness;
|
|
||||||
int capacity;
|
|
||||||
int iterations;
|
|
||||||
int iteration;
|
|
||||||
|
|
||||||
friend void swap(solution &one, solution &two) {
|
|
||||||
using std::swap;
|
|
||||||
|
|
||||||
swap(one.boxes, two.boxes);
|
|
||||||
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<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
|
|
||||||
};
|
|
||||||
|
|
||||||
int now = rng::random_double<0, 1>() > 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(rng::rng)]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
solution() = default;
|
|
||||||
|
|
||||||
solution(const solution &other, int itr): boxes(other.boxes), fitness(other.fitness),
|
|
||||||
capacity(other.capacity), iteration(itr) {}
|
|
||||||
|
|
||||||
solution(const std::vector<long long> &items, int capacity): // Gera a solução inicial
|
|
||||||
capacity(capacity), iteration(0) {
|
|
||||||
std::multiset<long long> 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)(rng::rng);
|
|
||||||
std::vector<int> sequence10;
|
|
||||||
std::vector<int> 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 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<long long> &items,
|
|
||||||
double alpha, double temp,
|
|
||||||
double temp_min) -> solution;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace sa
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Loading…
x
Reference in New Issue
Block a user