initial commit
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
#include <functional>
|
||||
#include <ios>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
using json = nlohmann::json;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Structure : nom d'instance décomposé depuis le nom de fichier
|
||||
// Format : Site_SiteCr_Tracks_Rames_Jobs_ID
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
struct InstanceKey {
|
||||
int64_t site;
|
||||
int64_t site_cr;
|
||||
int64_t tracks;
|
||||
int64_t rames;
|
||||
int64_t jobs;
|
||||
int64_t id;
|
||||
std::string raw; // nom complet sans extension
|
||||
bool operator == (const InstanceKey& key) const
|
||||
{
|
||||
return key.raw == raw;
|
||||
}
|
||||
};
|
||||
|
||||
struct HashInstanceKey
|
||||
{
|
||||
size_t operator() (const InstanceKey& key) const{
|
||||
return std::hash<std::string>()(key.raw);
|
||||
}
|
||||
};
|
||||
|
||||
InstanceKey parse_instance_name(const std::string& stem) {
|
||||
InstanceKey k;
|
||||
k.raw = stem;
|
||||
std::vector<int64_t> parts;
|
||||
std::string token;
|
||||
for (char c : stem) {
|
||||
if (c == '_') {
|
||||
if (!token.empty()) { parts.push_back(std::stoll(token)); token.clear(); }
|
||||
} else {
|
||||
token += c;
|
||||
}
|
||||
}
|
||||
if (!token.empty()) parts.push_back(std::stoll(token));
|
||||
|
||||
if (parts.size() != 6)
|
||||
throw std::runtime_error("Nom d'instance invalide (attendu 6 entiers) : " + stem);
|
||||
|
||||
k.site = parts[0];
|
||||
k.site_cr = parts[1];
|
||||
k.tracks = parts[2];
|
||||
k.rames = parts[3];
|
||||
k.jobs = parts[4];
|
||||
k.id = parts[5];
|
||||
return k;
|
||||
}
|
||||
|
||||
struct InstanceTradeOff{
|
||||
int64_t nbBranchBest;
|
||||
double timeRatio;
|
||||
};
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Parse un fichier JSON et insère les résultats
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
void process_file(const fs::path& path, std::unordered_map<InstanceKey, std::pair<unsigned int, double>, HashInstanceKey>& references, std::unordered_map<InstanceKey, std::optional<InstanceTradeOff>, HashInstanceKey>& trades) {
|
||||
// -- Nom d'instance depuis le stem du fichier
|
||||
InstanceKey key = parse_instance_name(path.stem().string());
|
||||
|
||||
// -- Lecture JSON
|
||||
std::ifstream f(path);
|
||||
if (!f) throw std::runtime_error("Impossible d'ouvrir : " + path.string());
|
||||
|
||||
json doc;
|
||||
try { f >> doc; }
|
||||
catch (const json::exception& e) {
|
||||
throw std::runtime_error("JSON invalide dans " + path.string() + " : " + e.what());
|
||||
}
|
||||
|
||||
if (!doc.is_object())
|
||||
throw std::runtime_error("Le JSON doit être un objet à la racine : " + path.string());
|
||||
|
||||
// -- Chaque clé = un algo
|
||||
for (auto& [algo_name, obj] : doc.items()) {
|
||||
if (!obj.is_object()) continue;
|
||||
|
||||
if(algo_name == "rbs")
|
||||
{
|
||||
int64_t fct_obj = obj.value("fctObjectif", int64_t{0});
|
||||
double time_f = obj.value("timeFinal", 0.0);
|
||||
references[key] = {
|
||||
fct_obj,
|
||||
time_f
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
if(trades.find(key) != trades.end() && trades[key] != std::nullopt)
|
||||
{
|
||||
int64_t fct_obj = obj.value("fctObjectif", int64_t{0});
|
||||
int64_t nbBranch = obj.value("nbBranch", int64_t{0});
|
||||
|
||||
double time_f = obj.value("timeFinal", 0.0);
|
||||
auto& tradePrec = trades[key];
|
||||
auto& ref = references[key];
|
||||
if(fct_obj <= ref.first && tradePrec->nbBranchBest > nbBranch)
|
||||
{
|
||||
InstanceTradeOff tr = {
|
||||
nbBranch,
|
||||
time_f/ref.second
|
||||
};
|
||||
trades[key] = tr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t fct_obj = obj.value("fctObjectif", int64_t{0});
|
||||
int64_t nbBranch = obj.value("nbBranch", int64_t{0});
|
||||
|
||||
double time_f = obj.value("timeFinal", 0.0);
|
||||
|
||||
auto& ref = references[key];
|
||||
if(fct_obj <= ref.first)
|
||||
{
|
||||
InstanceTradeOff tr = {
|
||||
nbBranch,
|
||||
time_f/ref.second
|
||||
};
|
||||
trades[key] = tr;
|
||||
}
|
||||
else
|
||||
{
|
||||
trades[key] = std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Collecte récursive des .json dans un dossier
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
std::vector<fs::path> collect_json_files(const fs::path& dir) {
|
||||
std::vector<fs::path> files;
|
||||
if (!fs::is_directory(dir)) {
|
||||
std::cerr << "[WARN] Pas un dossier, ignoré : " << dir << "\n";
|
||||
return files;
|
||||
}
|
||||
for (auto& entry : fs::recursive_directory_iterator(dir)) {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".json")
|
||||
files.push_back(entry.path());
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
void export_to_csv(std::unordered_map<InstanceKey, std::optional<InstanceTradeOff>, HashInstanceKey>& trades)
|
||||
{
|
||||
std::ofstream oFile("export_tradeoff.csv", std::ios_base::out | std::ios_base::trunc);
|
||||
oFile << "Site;" << "SiteCr;" << "Tracks;" << "Rames;" << "Jobs;" << "ID;" << "NbBranch;" << "TimeRatio;\n";
|
||||
for(const auto& [ins, trade] : trades)
|
||||
{
|
||||
oFile << ins.site << ";" << ins.site_cr << ";" << ins.tracks << ";" << ins.rames << ";" << ins.jobs << ";" << ins.id << ";";
|
||||
if(trade)
|
||||
{
|
||||
oFile << trade->nbBranchBest << ";" << trade->timeRatio << ";\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
oFile << -1 << ";" << -1 << ";\n";
|
||||
}
|
||||
}
|
||||
oFile.close();
|
||||
}
|
||||
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Main
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " <dossier1> [dossier2 ...]\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<fs::path> dirs;
|
||||
for (int i = 1; i < argc; ++i) dirs.emplace_back(argv[i]);
|
||||
|
||||
// -- Collecte des fichiers
|
||||
unsigned int all_files = 0;
|
||||
std::unordered_map<InstanceKey, std::optional<InstanceTradeOff>, HashInstanceKey> trades;
|
||||
std::unordered_map<InstanceKey, std::pair<unsigned int, double>, HashInstanceKey> reference;
|
||||
for (auto& d : dirs) {
|
||||
auto files = collect_json_files(d);
|
||||
all_files+= files.size();
|
||||
try {
|
||||
int ok = 0, err = 0;
|
||||
|
||||
for (auto& path : files) {
|
||||
try {
|
||||
process_file(path, reference, trades);
|
||||
++ok;
|
||||
if (ok % 100 == 0)
|
||||
std::cout << " [" << ok << "/" << files.size() << "]\n";
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "[ERR] " << path.filename() << " : " << e.what() << "\n";
|
||||
++err;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "[DONE] " << ok << " ok, " << err << " erreur(s).\n";
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "[ERR] " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_files == 0) {
|
||||
std::cerr << "[INFO] Aucun fichier .json trouvé.\n";
|
||||
return 0;
|
||||
}
|
||||
std::cout << "[INFO] " << all_files << " fichier(s) trouvé(s).\n";
|
||||
|
||||
std::cout << "[INFO] " << "Exporting to CSV tradeoffs" << "\n";
|
||||
|
||||
export_to_csv(trades);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user