Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 56 additions & 55 deletions demo/02_QuickstartKP_SA/mainKP-fcore-ex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,65 +15,66 @@ using namespace scannerpp; // NOLINT
// using namespace KP_fcore;

int main(int argc, char** argv) {
std::cout << "======== Carregando Problema ========" << std::endl;
// semente pseudo-aleatória fixa em zero
srand(time(NULL));
std::cout << "======== Carregando Problema ========" << std::endl;
// semente pseudo-aleatória fixa em zero
srand(time(NULL));

std::string sinstance = "knapsack-example.txt";
File f{sinstance};
std::string sinstance = "knapsack-example.txt";
File f{sinstance};

if (!f.isOpen()) {
std::cerr << "Problema '" << sinstance << "' não encontrado no diretório!"
<< std::endl;
return 1;
}
if (!f.isOpen()) {
std::cerr << "Problema '" << sinstance << "' não encontrado no diretório!"
<< std::endl;
return 1;
}

Scanner scanner{std::move(f)};
Scanner scanner{std::move(f)};

sref<ProblemContext> pKP{new ProblemContext{}};
pKP->load(scanner);
std::cout << "número de elementos na mochila:" << pKP->n << std::endl;
sref<ProblemContext> pKP{new ProblemContext{}};
pKP->load(scanner);
std::cout << "número de elementos na mochila:" << pKP->n << std::endl;

OptFrameDemoKP demo{pKP};
std::cout << "======== Testa Construtivo Aleatório ========" << std::endl;
// invoca método 'generateSolution' do FCore 'FConstructive' para construtivo
// aleatório
std::vector<bool> sol = *demo.randomConstructive.generateSolution(0.0);
// imprime solução inicial
std::cout << sol << std::endl;
//
std::cout << "======== Testa Avaliador ========" << std::endl;
// avalia solução inicial e cria um par 'ESolution'
ESolutionKP esol(sol, demo.evalKP.evaluate(sol));
// imprime avaliação da solução inicial
esol.second.print();
OptFrameDemoKP demo{pKP};
std::cout << "======== Testa Construtivo Aleatório ========" << std::endl;
// invoca método 'generateSolution' do FCore 'FConstructive' para construtivo
// aleatório
std::vector<bool> sol = *demo.randomConstructive.generateSolution(0.0);
// imprime solução inicial
std::cout << sol << std::endl;
//
std::cout << "======== Testa Avaliador ========" << std::endl;
// avalia solução inicial e cria um par 'ESolution'
ESolutionKP esol(sol, demo.evalKP.evaluate(sol));
// imprime avaliação da solução inicial
esol.second.print();

std::cout << "======== Executa Simulated Annealing ========" << std::endl;
// Especifica um gerador aleatório para o Simulated Annealing
RandGen rg;
//
// Cria objeto da classe 'InitialSearch' (parecido com 'construtivoAleatório')
BasicInitialSearch<ESolutionKP> initRand(nnptr::copy(demo.randomConstructive),
nnptr::copy(demo.evalKP));
// Instancia um Simulated Annealing com alpha=98%, iterações na temp = 100,
// temperatura inicial = 99999
BasicSA<ESolutionKP> sa(nnptr::copy(demo.evalKP), nnptr::copy(initRand),
nnptr::copy(demo.nsFlip), 0.98, 100, 99999,
nnptr::copy(rg));
// executa o SA e coleta o 'status' de saída
// passa um 'Criterio de Parada' por tempo (= 10 segundos)
optframe::Timer t;
auto searchOut = sa.search(
StopCriteria<ESolutionKP::second_type>{10.0}); // 10.0 seconds max
std::cout << "spent time: " << t.now() << "s" << std::endl;
// pega melhor solução do método SA
ESolutionKP melhor = *searchOut.best; //*sa.getBestSolution();
std::cout << "======== Imprime melhor solução do SA ========" << std::endl;
// imprime representação da melhor solução
cout << melhor.first << std::endl;
// imprime avaliação da melhor solução
melhor.second.print();

std::cout << "======== Executa Simulated Annealing ========" << std::endl;
// Especifica um gerador aleatório para o Simulated Annealing
RandGen rg;
//
// Cria objeto da classe 'InitialSearch' (parecido com 'construtivoAleatório')
BasicInitialSearch<ESolutionKP> initRand(nnptr::copy(demo.randomConstructive),
nnptr::copy(demo.evalKP));
// Instancia um Simulated Annealing com alpha=98%, iterações na temp = 100,
// temperatura inicial = 99999
BasicSA<ESolutionKP> sa(nnptr::copy(demo.evalKP), nnptr::copy(initRand),
nnptr::copy(demo.nsFlip), 0.98, 100, 99999,
nnptr::copy(rg));
// executa o SA e coleta o 'status' de saída
// passa um 'Criterio de Parada' por tempo (= 10 segundos)
optframe::Timer t;
auto searchOut = sa.search(
StopCriteria<ESolutionKP::second_type>{10.0}); // 10.0 seconds max
std::cout << "spent time: " << t.now() << "s" << std::endl;
// pega melhor solução do método SA
ESolutionKP melhor = *searchOut.best; //*sa.getBestSolution();
std::cout << "======== Imprime melhor solução do SA ========" << std::endl;
// imprime representação da melhor solução
cout << melhor.first << std::endl;
// imprime avaliação da melhor solução
melhor.second.print();

std::cout << "======== Fim da Execução ========" << std::endl;
return 0;
} // main
std::cout << "======== Fim da Execução ========" << std::endl;
return 0;
} // main
40 changes: 20 additions & 20 deletions demo/03_QuickstartTSP_VNS_BRKGA/mainTSP-fcore-ils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,24 +79,24 @@ int main() {

VND<ESolutionTSP> VND(demo.eval, ns_list);
// VND.setVerbose();//
ILSLPerturbationLPlus2<ESolutionTSP> pert(demo.eval, demo.nsSwap, rg2);

ILSL<ESolutionTSP> ils(demo.eval, nnptr::copy(initRand), nnptr::copy(VND),
nnptr::copy(pert), 10, 5);
// ils.setVerbose();

std::cout << "will start ILS for 10 seconds" << std::endl;

optframe::Timer t;
ils.setVerbose();
auto status = ils.search(
StopCriteria<ESolutionTSP::second_type>{10.0}); // 3.0 seconds max
ESolutionTSP best = *status.best;
std::cout << "spent time: " << t.now() << "s" << std::endl;
// best solution value
best.second.print();
std::cout << "solution: " << best.first << std::endl;

std::cout << "FINISHED" << std::endl;
return 0;
ILSLPerturbationLPlus2<ESolutionTSP> pert(demo.eval, demo.nsSwap, rg2);

ILSL<ESolutionTSP> ils(demo.eval, nnptr::copy(initRand), nnptr::copy(VND),
nnptr::copy(pert), 10, 5);
// ils.setVerbose();

std::cout << "will start ILS for 10 seconds" << std::endl;

optframe::Timer t;
ils.setVerbose();
auto status = ils.search(
StopCriteria<ESolutionTSP::second_type>{10.0}); // 3.0 seconds max
ESolutionTSP best = *status.best;
std::cout << "spent time: " << t.now() << "s" << std::endl;
// best solution value
best.second.print();
std::cout << "solution: " << best.first << std::endl;

std::cout << "FINISHED" << std::endl;
return 0;
}
65 changes: 46 additions & 19 deletions include/OptFrame-Core-Examples/FCore-TSP/TSP-fcore-c-lib.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ using TSP_fcore::Move2Opt;
using TSP_fcore::MoveSwap;
using TSP_fcore::MoveSwapDelta;

// Simple and efficient memory management
#include <vector>
#include <memory>

// Global registry for automatic cleanup
static std::vector<std::unique_ptr<std::vector<int>>> solution_registry;

// directly testing optframe C library (static)

double fevaluate_c(FakeProblemPtr p_ptr, FakeSolutionPtr s_ptr) {
Expand All @@ -30,7 +37,10 @@ FakeSolutionPtr fconstructive_c(FakeProblemPtr p_ptr) {
std::shared_ptr<PTSP> problem_view{(PTSP*)p_ptr, [](PTSP*) {}};
sref<PTSP> problem{problem_view};
auto v = TSP_fcore::frandom(problem);
return new std::vector<int>(std::move(v));
auto ptr = std::make_unique<std::vector<int>>(std::move(v));
auto* raw_ptr = ptr.get();
solution_registry.push_back(std::move(ptr));
return raw_ptr;
}

// ==================
Expand Down Expand Up @@ -58,7 +68,7 @@ FakeMovePtr fnsrand_c_2opt(FakeProblemPtr p_ptr, FakeSolutionPtr s_ptr) {
}

FakeMovePtr fmove_apply_c(FakeProblemPtr p_ptr, FakeMovePtr m_ptr,
FakeSolutionPtr s_ptr) {
FakeSolutionPtr s_ptr) {
auto* m = (MoveSwap*)m_ptr;
int i = m->i;
int j = m->j;
Expand Down Expand Up @@ -222,27 +232,27 @@ PairMoveDoubleLib fmove_applyupdate_delta_c(FakeProblemPtr p_ptr,
double diff = 0;
int i = m->i;
int j = m->j;
auto* pv = (std::vector<int>*)s_ptr;
auto& v = *pv;
auto* v = (std::vector<int>*)s_ptr;
auto& vec = *v;

int before_i = (pTSP->n + i - 1) % pTSP->n;
int before_j = (pTSP->n + j - 1) % pTSP->n;
int after_i = (pTSP->n + i + 1) % pTSP->n;
int after_j = (pTSP->n + j + 1) % pTSP->n;

diff -= pTSP->dist(v[before_i], v[i]);
diff -= pTSP->dist(v[i], v[after_i]);
diff -= pTSP->dist(v[before_j], v[j]);
diff -= pTSP->dist(v[j], v[after_j]);
diff += pTSP->dist(v[before_i], v[j]);
diff += pTSP->dist(v[j], v[after_i]);
diff += pTSP->dist(v[before_j], v[i]);
diff += pTSP->dist(v[i], v[after_j]);
diff -= pTSP->dist(vec[before_i], vec[i]);
diff -= pTSP->dist(vec[i], vec[after_i]);
diff -= pTSP->dist(vec[before_j], vec[j]);
diff -= pTSP->dist(vec[j], vec[after_j]);
diff += pTSP->dist(vec[before_i], vec[j]);
diff += pTSP->dist(vec[j], vec[after_i]);
diff += pTSP->dist(vec[before_j], vec[i]);
diff += pTSP->dist(vec[i], vec[after_j]);

// perform swap of clients i and j
int aux = v[j];
v[j] = v[i];
v[i] = aux;
int aux = vec[j];
vec[j] = vec[i];
vec[i] = aux;

return PairMoveDoubleLib{.first = new MoveSwapDelta{pTSP, j, i},
.second = diff};
Expand Down Expand Up @@ -294,7 +304,10 @@ FakeMovePtr fCurrent_delta_c(FakeProblemPtr p_ptr, FakePythonObjPtr it_ptr) {

FakeSolutionPtr f_sol_deepcopy(FakeSolutionPtr s_ptr) {
auto* v = (std::vector<int>*)(s_ptr);
return new std::vector<int>(*v);
auto ptr = std::make_unique<std::vector<int>>(*v);
auto* raw_ptr = ptr.get();
solution_registry.push_back(std::move(ptr));
return raw_ptr;
}

size_t f_sol_tostring(FakeSolutionPtr s_ptr, char* str, size_t str_size) {
Expand All @@ -307,13 +320,27 @@ size_t f_sol_tostring(FakeSolutionPtr s_ptr, char* str, size_t str_size) {
}

int f_decref_solution(FakeSolutionPtr s_ptr) {
auto* v = (std::vector<int>*)(s_ptr);
delete v;
return true;
if (s_ptr == nullptr) {
return 0; // Already deleted or null
}
// Remove from registry if present
auto it = std::find_if(solution_registry.begin(), solution_registry.end(),
[s_ptr](const std::unique_ptr<std::vector<int>>& ptr) {
return ptr.get() == s_ptr;
});
if (it != solution_registry.end()) {
solution_registry.erase(it);
}
return 0; // Always return 0
}

int f_decref_move(FakeMovePtr m_ptr) {
auto* m = (Move<ESolutionTSP>*)(m_ptr);
delete m;
return true;
}

// Simple and reliable cleanup function
void cleanup_remaining_solutions() {
solution_registry.clear(); // unique_ptr automatically deletes objects
}
3 changes: 3 additions & 0 deletions tests/OptFrameLib-test/optframelib_tsp_clean.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,8 @@ int main() {

bool b = optframe_api1d_destroy_engine(engine);

// Clean up any remaining allocated solutions
cleanup_remaining_solutions();

return 0;
}
Loading