From a769963c285410147fac7e7c24af5b8faac789c1 Mon Sep 17 00:00:00 2001 From: szdytom Date: Thu, 18 Jan 2024 14:26:01 +0800 Subject: [PATCH] optimizer update --- .gitignore | 6 + .gitingore | 4 - optimizer/box-breaker.cpp | 468 +++++++++++++++++++++----------------- 3 files changed, 271 insertions(+), 207 deletions(-) create mode 100644 .gitignore delete mode 100644 .gitingore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..74779c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.exe +*.lexe +.vscode/ +*.swp +*.out +optimizer/*.txt diff --git a/.gitingore b/.gitingore deleted file mode 100644 index e39175e..0000000 --- a/.gitingore +++ /dev/null @@ -1,4 +0,0 @@ -*.exe -*.lexe -.vscode -*.swp diff --git a/optimizer/box-breaker.cpp b/optimizer/box-breaker.cpp index fd2eef7..6a14c21 100644 --- a/optimizer/box-breaker.cpp +++ b/optimizer/box-breaker.cpp @@ -1,23 +1,104 @@ #include using namespace std; -const int n = 20; -const int q_siz = 20; -const double keep_p = 0.97; +const int N = 20; -mt19937 mt(114514); -uniform_real_distribution<> d01(0, 1); +mt19937 rng(random_device{}()); +uniform_real_distribution d01(0, 1); +uniform_int_distribution rng10(0, 9); +uniform_int_distribution rngN(0, 19); -struct Question { - bitset<20> M[20]; - int sx, sy, tx, ty, bx, by; +enum { + POI_PERSON, + POI_BOX, + POI_TARGET, + POI_EXCEED, }; -Question start_question; +#define compiler_assume(condition) \ + do { \ + if (!(condition)) \ + __builtin_unreachable(); \ + } while (false); \ + +struct Maze { + bitset M[N]; + int poi[3][2]; + + int at(int x, int y) const { + return M[x][y]; + } + + void set(int x, int y, int v) { + M[x][y] = v; + } + + void flip(int x, int y) { + M[x].flip(y); + } + + bool isValid() const { + for (int i = 0; i < POI_EXCEED; ++i) { + for (int j : {0, 1}) { + if (poi[i][j] < 0 || poi[i][j] >= N) + return false; + } + + if (at(poi[i][0], poi[i][1]) == 0) + return false; + } + return true; + } +}; + +inline Maze loadMaze(std::FILE *f) { + char *s = new char[N + 5]; + Maze res; + for (int i = 0; i < N; ++i) { + std::fscanf(f, "%s", s); + for (int j = 0; j < N; ++j) { + res.set(i, j, s[j] != '#'); + switch (s[j]) { + case 'P': + res.poi[POI_PERSON][0] = i; + res.poi[POI_PERSON][1] = j; + break; + case '*': + res.poi[POI_BOX][0] = i; + res.poi[POI_BOX][1] = j; + break; + case 'O': + res.poi[POI_TARGET][0] = i; + res.poi[POI_TARGET][1] = j; + break; + } + } + } + delete[] s; + return res; +} + +inline void writeMaze(const Maze &m, std::FILE *f) { + for (int i = 0; i < N; ++i) { + for (int j = 0; j < N; ++j) { + if (i == m.poi[POI_PERSON][0] && j == m.poi[POI_PERSON][1]) + std::fputc('P', f); + else if (i == m.poi[POI_BOX][0] && j == m.poi[POI_BOX][1]) + std::fputc('*', f); + else if (i == m.poi[POI_TARGET][0] && j == m.poi[POI_TARGET][1]) + std::fputc('O', f); + else if (m.at(i, j) == 0) + std::fputc('#', f); + else + std::fputc('.', f); + } + std::fputc('\n', f); + } +} namespace Solve { -bitset<20> mp[20]; -int dis[20][20][20][20]; +bitset mp[N]; +int dis[N][N][N][N]; queue> qu; inline int bfs(int px, int py, int bx, int by, int tx, int ty) { @@ -26,13 +107,13 @@ inline int bfs(int px, int py, int bx, int by, int tx, int ty) { qu.pop(); auto expand = [&](int npx, int npy, int nbx, int nby, int d) { - if (npx < 0 || npx >= n) + if (npx < 0 || npx >= N) return; - if (npy < 0 || npy >= n) + if (npy < 0 || npy >= N) return; - if (nbx < 0 || nbx >= n) + if (nbx < 0 || nbx >= N) return; - if (nby < 0 || nby >= n) + if (nby < 0 || nby >= N) return; if (mp[npx][npy] == 0) return; @@ -53,8 +134,6 @@ inline int bfs(int px, int py, int bx, int by, int tx, int ty) { auto [npx, npy, nbx, nby] = qu.front(); int d = dis[npx][npy][nbx][nby]; qu.pop(); - // cout<<"Now player at ( "< &res, float t = initial_temperature) { + for (int i = 0; i < POI_EXCEED; ++i) { + for (int j : {0, 1}) { + for (int d : {-1, 1}) { + compiler_assume(q.poi[i][j] >= 0 && q.poi[i][j] < N); + int z = q.poi[i][j] + d; + if (0 <= z && z < N) { + q.poi[i][j] += d; + expand(q, res, t); + q.poi[i][j] -= d; } - fou << endl; } - fou.close(); - system("cp nowmax.txt nowmax-cp.txt"); } } + + for (int i = 0; i < 25; i++) { + compiler_assume(q.isValid()); + int x = rngN(rng), y = rngN(rng); + q.flip(x, y); + if (q.isValid()) + expand(q, res, t); + q.flip(x, y); + } + + for (int i = 0; i < 4; ++i) { + Maze qq = q; + for (int j = 0; j < 60; ++j) { + int x = rngN(rng), y = rngN(rng); + qq.set(x, y, 1); + } + expand(qq, res, initial_temperature_pv); + } + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + int x = (rng10(rng) <= 2); + if (x) + q.flip(i, j); + } + } + + for (int i = 0; i < POI_EXCEED; ++i) { + q.set(q.poi[i][0], q.poi[i][1], 1); + } + + if (q.isValid()) + expand(q, res, t); +}; + +inline void writeGene(const Gene &g, std::FILE *f) { + std::fprintf(f, "%d %lf\n", g.w, g.T); + writeMaze(g.m, f); +} + +inline Gene loadGene(std::FILE *f) { + Gene g; + std::fscanf(f, "%d %f", &g.w, &g.T); + g.m = loadMaze(f); + return g; +} + +inline void writePopulation(const std::vector &p, int best_w, std::FILE *f) { + std::fprintf(f, "%d %d\n", (int)p.size(), best_w); + for (const auto &g : p) { + writeGene(g, f); + } } -inline void init() { - fstream fin("nowmax.txt", ios::in); - for (int i = 0; i < n; i++) { - string s; - fin >> s; - for (int j = 0; j < n; j++) { - if (s[j] == '#') - start_question.M[i][j] = 0; - else - start_question.M[i][j] = 1; +inline void loadPopulation(std::vector &p, int &best_w, std::FILE *f) { + int pn; + std::fscanf(f, "%d %d", &pn, &best_w); + p.resize(pn); + for (int i = 0; i < pn; ++i) { + p[i] = loadGene(f); + } +} - if (s[j] == 'P') - start_question.sx = i, start_question.sy = j; - if (s[j] == '*') - start_question.bx = i, start_question.by = j; - if (s[j] == 'O') - start_question.tx = i, start_question.ty = j; +inline void constructMain() { + std::vector population; + int history_best_w; + + auto frecord = std::fopen("current.txt", "r"); + loadPopulation(population, history_best_w, frecord); + std::fclose(frecord); + + for (int iter_id = 1; ; ++iter_id) { + std::vector nxt; + for (auto &gene : population) { + expandAll(gene.m, nxt, std::max(gene.T, initial_temperature)); + nxt.push_back(std::move(gene)); + } + population.clear(); + + int best_w = 0, hbest_w = 0; + for (const auto &gene : nxt) { + best_w = std::max(best_w, gene.w); + if (gene.T > initial_temperature) + hbest_w = std::max(hbest_w, gene.w); + } + + std::vector Hpopulation, Lpopulation; + for (auto &gene : nxt) { + const bool is_ht = gene.T > initial_temperature; + const float dE = (is_ht ? hbest_w + 1 : best_w) - gene.w; + gene.eT = exp(-dE / gene.T); + if (gene.eT > d01(rng)) { + gene.T *= termperature_delta; + if (is_ht) + Hpopulation.push_back(std::move(gene)); + else + Lpopulation.push_back(std::move(gene)); + } + } + nxt.clear(); + + auto cmpET = [](const Gene &a, const Gene &b) { + return a.eT > b.eT; + }; + + if (Hpopulation.size() > population_limit) { + sort(Hpopulation.begin(), Hpopulation.end(), cmpET); + Hpopulation.resize(population_limit); + } + + if (Lpopulation.size() > population_limit) { + sort(Lpopulation.begin(), Lpopulation.end(), cmpET); + Lpopulation.resize(population_limit); + } + + population = std::move(Lpopulation); + for (auto &g : Hpopulation) { + population.push_back(std::move(g)); + } + Lpopulation.clear(); + Hpopulation.clear(); + + bool broke_record = best_w > history_best_w; + if (broke_record) { + history_best_w = best_w; + printf("New Record: %d!\n", best_w); + std::FILE *f = fopen("best.txt", "w"); + writePopulation(population, best_w, f); + fclose(f); + } + + if (true) { + printf("Iterated for %d times.\n", iter_id); + printf("Current Best=%d, History Best=%d, Population Size=%d\n" + , best_w, history_best_w, (int)population.size()); + + std::FILE *f = fopen("current.txt", "w"); + writePopulation(population, best_w, f); + fclose(f); } } - // cout<<"Start question : *********************"<