Compare commits
No commits in common. "6fb7e5bf68146d27a918e08f550f2cc85d75fa79" and "dd2aacb284a4c381d6bcc0423dd6d710b1971cdc" have entirely different histories.
6fb7e5bf68
...
dd2aacb284
2
main.cpp
2
main.cpp
@ -8,7 +8,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ALPHA
|
#ifndef ALPHA
|
||||||
#define ALPHA 0.999
|
#define ALPHA 0.99
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TEMP_MIN
|
#ifndef TEMP_MIN
|
||||||
|
|||||||
43
run.bat
43
run.bat
@ -1,46 +1,19 @@
|
|||||||
:: Uso: [set EXEC="caminho\do\executavel.exe"]&&[set TEST_FOLDER=caminho\dos\casetests]&&[set ARGS=ic]&&[set SOLUTIONS_FILE=arquivo\de\solucoes.txt]&&run.bat
|
:: Uso: [set EXEC="caminho/do/executavel.exe"] && [set TEST_FOLDER=caminho/dos/casetests] && [set ARGS=ic] && run.bat
|
||||||
@ECHO off
|
@ECHO off
|
||||||
setlocal enabledelayedexpansion
|
|
||||||
echo %TIME%
|
|
||||||
if not defined EXEC (
|
if not defined EXEC (
|
||||||
set EXEC="build\solucao.exe"
|
set EXEC="build/solucao.exe"
|
||||||
)
|
)
|
||||||
|
|
||||||
if not defined TEST_FOLDER (
|
if not defined TEST_FOLDER (
|
||||||
set TEST_FOLDER=Teste\Casos
|
set TEST_FOLDER=test
|
||||||
)
|
|
||||||
|
|
||||||
if not defined SOLUTIONS_FILE (
|
|
||||||
set SOLUTIONS_FILE=Teste\Solucoes.txt
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for %%g in (%TEST_FOLDER%/*) do (
|
||||||
|
echo Arquivo de teste: %TEST_FOLDER%/%%g
|
||||||
if defined ARGS (
|
if defined ARGS (
|
||||||
set ARGS=-%ARGS%
|
%EXEC% -%ARGS% < %TEST_FOLDER%/%%g
|
||||||
)
|
|
||||||
|
|
||||||
for /f "tokens=1,2 skip=1" %%a in (%SOLUTIONS_FILE%) do (
|
|
||||||
set solutions[%%a]=%%b
|
|
||||||
)
|
|
||||||
|
|
||||||
for %%g in (%TEST_FOLDER%\*) do (
|
|
||||||
for %%h in (%%g) do set testname=%%~nxh
|
|
||||||
for /f "delims=" %%h in ("!testname!") do set optimal=!solutions[%%h]!
|
|
||||||
|
|
||||||
echo Arquivo de teste: %%g
|
|
||||||
for /f "tokens=4" %%h in ('!EXEC! !ARGS! ^< %%g') do set res=%%h
|
|
||||||
echo Resultado do programa: !res!
|
|
||||||
echo Resultado ótimo: !optimal!
|
|
||||||
if !res! EQU !optimal! (
|
|
||||||
echo Resultado ótimo^^!
|
|
||||||
) else (
|
) else (
|
||||||
set /a diff= !res!-!optimal!
|
%EXEC% < %TEST_FOLDER%/%%g
|
||||||
echo Diferença de !diff!
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
echo %TIME%
|
|
||||||
endlocal
|
|
||||||
set EXEC=
|
|
||||||
set TEST_FOLDER=
|
|
||||||
set SOLUTIONS_FILE=
|
|
||||||
set ARGS=
|
|
||||||
goto :eof
|
|
||||||
19
run.sh
19
run.sh
@ -10,24 +10,7 @@ if [[ -z $TEST_FOLDER ]]; then
|
|||||||
TEST_FOLDER="test"
|
TEST_FOLDER="test"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z $SOLUTIONS_FILE ]]; then
|
|
||||||
SOLUTIONS_FILE=solucoes.txt
|
|
||||||
fi
|
|
||||||
|
|
||||||
declare -A solutions
|
|
||||||
while read line; do
|
|
||||||
solutions[$(awk '{print $1}' <<< "$line")]=$(awk '{print $2}' <<< "$line")
|
|
||||||
done < "$SOLUTIONS_FILE"
|
|
||||||
|
|
||||||
for file in $(find "$TEST_FOLDER" -type f); do
|
for file in $(find "$TEST_FOLDER" -type f); do
|
||||||
echo "Arquivo de teste: $file"
|
echo "Arquivo de teste: $file"
|
||||||
res=$("$EXEC" -i -c < "$file" | awk '{print $4}')
|
"$EXEC" < "$file"
|
||||||
optimal=${solutions[$(basename "$file")]}
|
|
||||||
echo "Resultado do programa: ${res}"
|
|
||||||
echo "Resultado ótimo: ${optimal}"
|
|
||||||
if [[ $res = $optimal ]]; then
|
|
||||||
echo "Resultado ótimo!"
|
|
||||||
else
|
|
||||||
echo "Diferença de $(bc <<< "${res} - ${optimal}")"
|
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
|||||||
3
sa.cpp
3
sa.cpp
@ -21,12 +21,13 @@ auto sa::solution::simulated_annealing(int capacity, const std::vector<long long
|
|||||||
|
|
||||||
int diff = neighbor.fitness - prev.fitness;
|
int diff = neighbor.fitness - prev.fitness;
|
||||||
if (diff <= 0 || std::exp(-diff / temp) > rand(eng)) {
|
if (diff <= 0 || std::exp(-diff / temp) > rand(eng)) {
|
||||||
swap(prev, neighbor);
|
prev.swap(neighbor);
|
||||||
}
|
}
|
||||||
|
|
||||||
temp *= alpha;
|
temp *= alpha;
|
||||||
|
|
||||||
if (prev.fitness < best.fitness) {
|
if (prev.fitness < best.fitness) {
|
||||||
|
std::cout << prev.fitness << ' ' << best.fitness << '\n';
|
||||||
best = prev;
|
best = prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
218
sa.hpp
218
sa.hpp
@ -1,145 +1,54 @@
|
|||||||
#ifndef SIMULATED_ANNEALING_HEADER_12647_H
|
#ifndef SIMULATED_ANNEALING_HEADER_12647_H
|
||||||
#define SIMULATED_ANNEALING_HEADER_12647_H
|
#define SIMULATED_ANNEALING_HEADER_12647_H
|
||||||
|
|
||||||
#define SIMULATED_ANNEALING_DISABLE_SHOWCRATES 1
|
#define SIMULATED_ANNEALING_DISABLE_SHOWCRATES 1
|
||||||
#define SIMULATED_ANNEALING_DISABLE_SHOWITRNUM 2
|
#define SIMULATED_ANNEALING_DISABLE_SHOWITRNUM 2
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <random>
|
|
||||||
#include <set>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <random>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace sa {
|
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 + 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 {
|
class solution {
|
||||||
std::vector<box> boxes;
|
std::vector<long long> items;
|
||||||
std::default_random_engine gen;
|
std::default_random_engine gen;
|
||||||
int capacity;
|
int capacity;
|
||||||
int fitness;
|
int fitness;
|
||||||
int iterations;
|
int iterations;
|
||||||
int iteration;
|
int iteration;
|
||||||
|
|
||||||
friend void swap(solution &one, solution &two) {
|
auto calculate_boxes()->int {
|
||||||
using std::swap;
|
int count = 1;
|
||||||
|
long long now = 0;
|
||||||
|
|
||||||
swap(one.boxes, two.boxes);
|
for (auto i : items) {
|
||||||
swap(one.gen, two.gen);
|
if (now + i > capacity) {
|
||||||
swap(one.capacity, two.capacity);
|
count++;
|
||||||
swap(one.fitness, two.fitness);
|
now = i;
|
||||||
swap(one.iterations, two.iterations);
|
continue;
|
||||||
swap(one.iteration, two.iteration);
|
}
|
||||||
|
now += i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void random_swap(int choice, std::vector<int> &sequence10, std::vector<int> &sequence11) {
|
return count;
|
||||||
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);
|
static void print_box(int box, std::queue<long long> &stored) {
|
||||||
(boxes[choice].*swaps[now])(boxes[(*sequences[now])[dist(gen)]]);
|
std::cout << "Caixa " << box << ":";
|
||||||
|
while (!stored.empty()) {
|
||||||
|
std::cout << ' ' << stored.front();
|
||||||
|
stored.pop();
|
||||||
|
}
|
||||||
|
std::cout << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
solution() = default;
|
solution() = default;
|
||||||
|
|
||||||
solution(const solution &other, int itr): boxes(other.boxes), gen(other.gen),
|
solution(const solution &other, int itr): items(other.items), gen(other.gen),
|
||||||
capacity(other.capacity), fitness(other.fitness),
|
capacity(other.capacity), fitness(other.fitness),
|
||||||
iteration(itr) {}
|
iteration(itr) {}
|
||||||
|
|
||||||
@ -151,8 +60,10 @@ class solution {
|
|||||||
its.insert(i);
|
its.insert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->items.resize(items.size());
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
long long cap = capacity;
|
long long cap = capacity;
|
||||||
box tmp;
|
|
||||||
|
|
||||||
while (!its.empty()) {
|
while (!its.empty()) {
|
||||||
auto itr = its.upper_bound(cap);
|
auto itr = its.upper_bound(cap);
|
||||||
@ -160,60 +71,43 @@ class solution {
|
|||||||
cap = capacity;
|
cap = capacity;
|
||||||
cap -= *its.begin();
|
cap -= *its.begin();
|
||||||
itr = its.begin();
|
itr = its.begin();
|
||||||
this->boxes.emplace_back(tmp);
|
|
||||||
tmp.clear();
|
|
||||||
} else {
|
} else {
|
||||||
itr--;
|
itr--;
|
||||||
cap -= *itr;
|
cap -= *itr;
|
||||||
}
|
}
|
||||||
tmp.add_item(*itr);
|
this->items[i] = *itr;
|
||||||
its.erase(itr);
|
its.erase(itr);
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tmp.empty()) {
|
fitness = calculate_boxes();
|
||||||
this->boxes.emplace_back(tmp);
|
|
||||||
}
|
|
||||||
fitness = (int)this->boxes.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setneighbor() { // Gera um vizinho da solução
|
void setneighbor() { // Gera um vizinho da solução
|
||||||
int choice = std::uniform_int_distribution<>(0, (int)boxes.size() - 1)(gen);
|
std::uniform_int_distribution<> dist(0, items.size() - 1);
|
||||||
std::vector<int> sequence10;
|
int first = dist(gen);
|
||||||
std::vector<int> sequence11;
|
int second = 0;
|
||||||
|
while ((second = dist(gen)) == first) {}
|
||||||
|
|
||||||
sequence10.reserve(boxes.size());
|
std::swap(items[first], items[second]);
|
||||||
sequence11.reserve(boxes.size());
|
fitness = calculate_boxes();
|
||||||
|
|
||||||
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 randomize() {
|
void randomize() {
|
||||||
std::shuffle(boxes.begin(), boxes.end(), gen);
|
std::shuffle(items.begin(), items.end(), gen);
|
||||||
|
|
||||||
|
fitness = calculate_boxes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_sol(char flags = 0) {
|
void swap(solution &other) {
|
||||||
|
std::swap(fitness, other.fitness);
|
||||||
|
std::swap(items, other.items);
|
||||||
|
std::swap(capacity, other.capacity);
|
||||||
|
std::swap(gen, other.gen);
|
||||||
|
std::swap(iteration, other.iteration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_sol(char flags = 0) const {
|
||||||
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';
|
||||||
@ -221,9 +115,23 @@ class solution {
|
|||||||
std::cout << "Número de caixas: " << fitness << '\n';
|
std::cout << "Número de caixas: " << fitness << '\n';
|
||||||
|
|
||||||
if(!(flags & SIMULATED_ANNEALING_DISABLE_SHOWCRATES)){
|
if(!(flags & SIMULATED_ANNEALING_DISABLE_SHOWCRATES)){
|
||||||
for (size_t i = 0; i < boxes.size(); i++) {
|
int box_now = 1;
|
||||||
boxes[i].print((int)i + 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';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user