optimizer update
This commit is contained in:
parent
bd38e5d9ec
commit
a769963c28
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
*.exe
|
||||||
|
*.lexe
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.out
|
||||||
|
optimizer/*.txt
|
@ -1,4 +0,0 @@
|
|||||||
*.exe
|
|
||||||
*.lexe
|
|
||||||
.vscode
|
|
||||||
*.swp
|
|
@ -1,23 +1,104 @@
|
|||||||
#include <bits/stdc++.h>
|
#include <bits/stdc++.h>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const int n = 20;
|
const int N = 20;
|
||||||
const int q_siz = 20;
|
|
||||||
const double keep_p = 0.97;
|
|
||||||
|
|
||||||
mt19937 mt(114514);
|
mt19937 rng(random_device{}());
|
||||||
uniform_real_distribution<> d01(0, 1);
|
uniform_real_distribution<float> d01(0, 1);
|
||||||
|
uniform_int_distribution<int> rng10(0, 9);
|
||||||
|
uniform_int_distribution<int> rngN(0, 19);
|
||||||
|
|
||||||
struct Question {
|
enum {
|
||||||
bitset<20> M[20];
|
POI_PERSON,
|
||||||
int sx, sy, tx, ty, bx, by;
|
POI_BOX,
|
||||||
|
POI_TARGET,
|
||||||
|
POI_EXCEED,
|
||||||
};
|
};
|
||||||
|
|
||||||
Question start_question;
|
#define compiler_assume(condition) \
|
||||||
|
do { \
|
||||||
|
if (!(condition)) \
|
||||||
|
__builtin_unreachable(); \
|
||||||
|
} while (false); \
|
||||||
|
|
||||||
|
struct Maze {
|
||||||
|
bitset<N> 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 {
|
namespace Solve {
|
||||||
bitset<20> mp[20];
|
bitset<N> mp[N];
|
||||||
int dis[20][20][20][20];
|
int dis[N][N][N][N];
|
||||||
queue<tuple<int, int, int, int>> qu;
|
queue<tuple<int, int, int, int>> qu;
|
||||||
|
|
||||||
inline int bfs(int px, int py, int bx, int by, int tx, int ty) {
|
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();
|
qu.pop();
|
||||||
|
|
||||||
auto expand = [&](int npx, int npy, int nbx, int nby, int d) {
|
auto expand = [&](int npx, int npy, int nbx, int nby, int d) {
|
||||||
if (npx < 0 || npx >= n)
|
if (npx < 0 || npx >= N)
|
||||||
return;
|
return;
|
||||||
if (npy < 0 || npy >= n)
|
if (npy < 0 || npy >= N)
|
||||||
return;
|
return;
|
||||||
if (nbx < 0 || nbx >= n)
|
if (nbx < 0 || nbx >= N)
|
||||||
return;
|
return;
|
||||||
if (nby < 0 || nby >= n)
|
if (nby < 0 || nby >= N)
|
||||||
return;
|
return;
|
||||||
if (mp[npx][npy] == 0)
|
if (mp[npx][npy] == 0)
|
||||||
return;
|
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();
|
auto [npx, npy, nbx, nby] = qu.front();
|
||||||
int d = dis[npx][npy][nbx][nby];
|
int d = dis[npx][npy][nbx][nby];
|
||||||
qu.pop();
|
qu.pop();
|
||||||
// cout<<"Now player at ( "<<npx<<" , "<<npy<<" ) and box at ( "<<nbx<<"
|
|
||||||
// , "<<nby<<" ) and dis = "<<d<<endl;
|
|
||||||
|
|
||||||
if (nbx == tx && nby == ty)
|
if (nbx == tx && nby == ty)
|
||||||
return d;
|
return d;
|
||||||
@ -75,208 +154,191 @@ inline int bfs(int px, int py, int bx, int by, int tx, int ty) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int solve(Question q) {
|
inline int solve(Maze q) {
|
||||||
memcpy(mp, q.M, sizeof(q.M));
|
for (int i = 0; i < 20; ++i)
|
||||||
return bfs(q.sx, q.sy, q.bx, q.by, q.tx, q.ty);
|
mp[i] = q.M[i];
|
||||||
|
return bfs(q.poi[POI_PERSON][0], q.poi[POI_PERSON][1]
|
||||||
|
, q.poi[POI_BOX][0], q.poi[POI_BOX][1], q.poi[POI_TARGET][0], q.poi[POI_TARGET][1]);
|
||||||
}
|
}
|
||||||
}; // namespace Solve
|
}; // namespace Solve
|
||||||
|
|
||||||
vector<pair<Question, int>> prq, nwq;
|
const float initial_temperature = 10;
|
||||||
|
const float initial_temperature_pv = 70;
|
||||||
|
const float termperature_delta = .98;
|
||||||
|
const int population_limit = 30;
|
||||||
|
|
||||||
inline void constructMain() {
|
struct Gene {
|
||||||
auto expand = [&](Question q) {
|
Maze m;
|
||||||
if (q.sx < 0 || q.sx >= n)
|
int w;
|
||||||
return;
|
float T, eT;
|
||||||
if (q.sy < 0 || q.sy >= n)
|
Gene() {}
|
||||||
return;
|
Gene(const Maze &m, int w, float T) : m(m), w(w), T(T) {}
|
||||||
if (q.bx < 0 || q.bx >= n)
|
};
|
||||||
return;
|
|
||||||
if (q.by < 0 || q.by >= n)
|
|
||||||
return;
|
|
||||||
if (q.tx < 0 || q.tx >= n)
|
|
||||||
return;
|
|
||||||
if (q.ty < 0 || q.ty >= n)
|
|
||||||
return;
|
|
||||||
if (q.M[q.sx][q.sy] == 0)
|
|
||||||
return;
|
|
||||||
if (q.M[q.bx][q.by] == 0)
|
|
||||||
return;
|
|
||||||
if (q.M[q.tx][q.ty] == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int d = Solve::solve(q);
|
inline void expand(const Maze &q, std::vector<Gene> &res, float t) {
|
||||||
nwq.push_back({q, d});
|
int s = Solve::solve(q);
|
||||||
};
|
if (s != -1)
|
||||||
auto expandAll = [&](Question q) {
|
res.emplace_back(q, s, t);
|
||||||
expand(q);
|
}
|
||||||
|
|
||||||
q.sx--;
|
inline void expandAll(Maze q, std::vector<Gene> &res, float t = initial_temperature) {
|
||||||
expand(q);
|
for (int i = 0; i < POI_EXCEED; ++i) {
|
||||||
q.sx++;
|
for (int j : {0, 1}) {
|
||||||
|
for (int d : {-1, 1}) {
|
||||||
q.sx++;
|
compiler_assume(q.poi[i][j] >= 0 && q.poi[i][j] < N);
|
||||||
expand(q);
|
int z = q.poi[i][j] + d;
|
||||||
q.sx--;
|
if (0 <= z && z < N) {
|
||||||
|
q.poi[i][j] += d;
|
||||||
q.sy--;
|
expand(q, res, t);
|
||||||
expand(q);
|
q.poi[i][j] -= d;
|
||||||
q.sy++;
|
|
||||||
|
|
||||||
q.sy++;
|
|
||||||
expand(q);
|
|
||||||
q.sy--;
|
|
||||||
|
|
||||||
q.bx--;
|
|
||||||
expand(q);
|
|
||||||
q.bx++;
|
|
||||||
|
|
||||||
q.bx++;
|
|
||||||
expand(q);
|
|
||||||
q.bx--;
|
|
||||||
|
|
||||||
q.by--;
|
|
||||||
expand(q);
|
|
||||||
q.by++;
|
|
||||||
|
|
||||||
q.by++;
|
|
||||||
expand(q);
|
|
||||||
q.by--;
|
|
||||||
|
|
||||||
q.tx--;
|
|
||||||
expand(q);
|
|
||||||
q.tx++;
|
|
||||||
|
|
||||||
q.tx++;
|
|
||||||
expand(q);
|
|
||||||
q.tx--;
|
|
||||||
|
|
||||||
q.ty--;
|
|
||||||
expand(q);
|
|
||||||
q.ty++;
|
|
||||||
|
|
||||||
q.ty++;
|
|
||||||
expand(q);
|
|
||||||
q.ty--;
|
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
for (int j = 0; j < n; j++) {
|
|
||||||
q.M[i][j] = !q.M[i][j];
|
|
||||||
expand(q);
|
|
||||||
q.M[i][j] = !q.M[i][j];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Question q1 = q;
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
for (int j = 0; j < n; j++) {
|
|
||||||
int x = (d01(mt) <= 0.3);
|
|
||||||
q1.M[i][j] = q1.M[i][j] ^ x;
|
|
||||||
if ((i == q1.sx && j == q1.sy) || (i == q1.bx && j == q1.by)
|
|
||||||
|| (i == q1.tx && j == q1.ty))
|
|
||||||
q1.M[i][j] = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expand(q1);
|
|
||||||
};
|
|
||||||
|
|
||||||
prq.push_back({start_question, Solve::solve(start_question)});
|
for (int i = 0; i < 25; i++) {
|
||||||
for (int _ = 1;; _++, swap(prq, nwq)) {
|
compiler_assume(q.isValid());
|
||||||
for (pair<Question, int> pr : prq)
|
int x = rngN(rng), y = rngN(rng);
|
||||||
expandAll(pr.first);
|
q.flip(x, y);
|
||||||
sort(nwq.begin(),
|
if (q.isValid())
|
||||||
nwq.end(),
|
expand(q, res, t);
|
||||||
[&](const pair<Question, int>& a, const pair<Question, int>& b) {
|
q.flip(x, y);
|
||||||
return a.second > b.second;
|
|
||||||
});
|
|
||||||
vector<pair<Question, int>> tmp(0);
|
|
||||||
double nwpw = 1;
|
|
||||||
for (int i = 0; i < nwq.size(); i++) {
|
|
||||||
if (d01(mt) <= nwpw)
|
|
||||||
tmp.push_back(nwq[i]);
|
|
||||||
nwpw *= keep_p;
|
|
||||||
}
|
}
|
||||||
nwq = tmp;
|
|
||||||
|
|
||||||
if (_ % 1 == 0) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
cout << "Iterated for " << _ << " times" << endl;
|
Maze qq = q;
|
||||||
Question mxq = nwq.front().first;
|
for (int j = 0; j < 60; ++j) {
|
||||||
cout << "Max step = " << nwq.front().second << endl;
|
int x = rngN(rng), y = rngN(rng);
|
||||||
|
qq.set(x, y, 1);
|
||||||
|
}
|
||||||
|
expand(qq, res, initial_temperature_pv);
|
||||||
|
}
|
||||||
|
|
||||||
// cout<<"***************************"<<endl;
|
for (int i = 0; i < N; i++) {
|
||||||
// for(int i=0;i<n;i++)
|
for (int j = 0; j < N; j++) {
|
||||||
// {
|
int x = (rng10(rng) <= 2);
|
||||||
// for(int j=0;j<n;j++)
|
if (x)
|
||||||
// {
|
q.flip(i, j);
|
||||||
// if(i==mxq.sx&&j==mxq.sy) cout<<"P";
|
}
|
||||||
// else if(i==mxq.tx&&j==mxq.ty) cout<<"O";
|
}
|
||||||
// else if(i==mxq.bx&&j==mxq.by) cout<<"*";
|
|
||||||
// else if(mxq.M[i][j]==0) cout<<"#";
|
|
||||||
// else cout<<".";
|
|
||||||
// }
|
|
||||||
// cout<<endl;
|
|
||||||
// }
|
|
||||||
// cout<<"***************************"<<endl;
|
|
||||||
|
|
||||||
fstream fou("nowmax.txt", ios::out);
|
for (int i = 0; i < POI_EXCEED; ++i) {
|
||||||
for (int i = 0; i < n; i++) {
|
q.set(q.poi[i][0], q.poi[i][1], 1);
|
||||||
for (int j = 0; j < n; j++) {
|
|
||||||
if (i == mxq.sx && j == mxq.sy)
|
|
||||||
fou << "P";
|
|
||||||
else if (i == mxq.tx && j == mxq.ty)
|
|
||||||
fou << "O";
|
|
||||||
else if (i == mxq.bx && j == mxq.by)
|
|
||||||
fou << "*";
|
|
||||||
else if (mxq.M[i][j] == 0)
|
|
||||||
fou << "#";
|
|
||||||
else
|
|
||||||
fou << ".";
|
|
||||||
}
|
|
||||||
fou << endl;
|
|
||||||
}
|
|
||||||
fou.close();
|
|
||||||
system("cp nowmax.txt nowmax-cp.txt");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<Gene> &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() {
|
inline void loadPopulation(std::vector<Gene> &p, int &best_w, std::FILE *f) {
|
||||||
fstream fin("nowmax.txt", ios::in);
|
int pn;
|
||||||
for (int i = 0; i < n; i++) {
|
std::fscanf(f, "%d %d", &pn, &best_w);
|
||||||
string s;
|
p.resize(pn);
|
||||||
fin >> s;
|
for (int i = 0; i < pn; ++i) {
|
||||||
for (int j = 0; j < n; j++) {
|
p[i] = loadGene(f);
|
||||||
if (s[j] == '#')
|
}
|
||||||
start_question.M[i][j] = 0;
|
}
|
||||||
else
|
|
||||||
start_question.M[i][j] = 1;
|
|
||||||
|
|
||||||
if (s[j] == 'P')
|
inline void constructMain() {
|
||||||
start_question.sx = i, start_question.sy = j;
|
std::vector<Gene> population;
|
||||||
if (s[j] == '*')
|
int history_best_w;
|
||||||
start_question.bx = i, start_question.by = j;
|
|
||||||
if (s[j] == 'O')
|
auto frecord = std::fopen("current.txt", "r");
|
||||||
start_question.tx = i, start_question.ty = j;
|
loadPopulation(population, history_best_w, frecord);
|
||||||
|
std::fclose(frecord);
|
||||||
|
|
||||||
|
for (int iter_id = 1; ; ++iter_id) {
|
||||||
|
std::vector<Gene> 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<Gene> 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 : *********************"<<endl;
|
|
||||||
// for(int i=0;i<n;i++)
|
|
||||||
// {
|
|
||||||
// for(int j=0;j<n;j++)
|
|
||||||
// {
|
|
||||||
// cout<<start_question.M[i][j];
|
|
||||||
// }
|
|
||||||
// cout<<endl;
|
|
||||||
// }
|
|
||||||
// cout<<"sx = "<<start_question.sx<<" , sy = "<<start_question.sy<<endl;
|
|
||||||
// cout<<"bx = "<<start_question.bx<<" , by = "<<start_question.by<<endl;
|
|
||||||
// cout<<"tx = "<<start_question.tx<<" , ty = "<<start_question.ty<<endl;
|
|
||||||
// cout<<"**************************************"<<endl;
|
|
||||||
fin.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
init();
|
|
||||||
|
|
||||||
// cout<<Solve::solve(start_question)<<endl;
|
|
||||||
|
|
||||||
constructMain();
|
constructMain();
|
||||||
|
return 0;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user