粒子群优化(微粒群算法)

· · 个人记录

迭代公式

v_i = v_i * w + c * rand() * (pbest_i + gbest - 2 x_i)

其中:

$w$ 是惯性因子 $w \in [0, 1]$,和学习因子相反,就是该粒子原来的速度的 参考权重 。比如这个程序里取的是 $0.5$,而据说从大到小衰减会更好。因为大的时候会重视每个个体的价值,可以更全面的寻找可行解,而越趋于 $0$ 就越注重社会的价值就是所有粒子中的最优解。 $C$ 是学习因子也就是权重一般取 $2

我们可以通过这个速度向量来更新位置

b[i]_x += b[i].v

上面这段话 cvyuy\_ 的题解

```cpp #include <bits/stdc++.h> using namespace std; #define rg register #define gc getchar #define rep(i, a, b) for(int i = a; i <= b; ++i) inline int read(){ rg char ch = gc(); rg int x = 0, f = 0; while(!isdigit(ch)) f |= (ch == '-'), ch = gc(); while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc(); return f ? -x : x; } const int N = 105; int n; double xs[15]; double l, r, len; inline double calc(double x){ double res = 0; rep(i, 0, n) res += pow(x, i) * xs[i]; return res; } inline double Rand(){ return (double) rand() / RAND_MAX; } double by = -1e100, bx;//best of all struct node{ double v, x, y, besty, bestx; } b[N]; inline void update(int a){ b[a].v = b[a].v * 0.5 + Rand() * 2 * (bx + b[a].bestx - b[a].x * 2); b[a].x += b[a].v; if(b[a].x < l) b[a].x = l, b[a].v *= -1; if(b[a].x > r) b[a].x = r, b[a].v *= -1; b[a].y = calc(b[a].x); if(b[a].y > b[a].besty){ b[a].bestx = b[a].x; b[a].besty = b[a].y; } if(b[a].y > by){ by = b[a].y; bx = b[a].x; } } signed main(){ n = read(); scanf("%lf %lf", &l, &r); len = r - l; for(int i = n; ~i; --i) scanf("%lf", &xs[i]); srand(time(0)); for(int i = 0; i < N; ++i){ b[i].x = b[i].bestx = l + Rand() * len; b[i].v = 0; b[i].y = b[i].besty = calc(b[i].x); if(by < b[i].y) bx = b[i].x, by = b[i].y; } rep(k, 1, 100) for(int i = 0; i < N; ++i) update(i); printf("%.5lf\n", bx); gc(), gc(); return 0; } ``` $code$ [P2571 [SCOI2010]传送带](https://www.luogu.com.cn/problem/P2571) ```cpp #include <bits/stdc++.h> using namespace std; #define rg register #define gc getchar #define rep(i, a, b) for(int i = a; i <= b; ++i) inline double read(){ rg char ch = gc(); rg int x = 0, f = 0; while(!isdigit(ch)) f |= (ch == '-'), ch = gc(); while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc(); if(ch == '.'){ double res = x, pos = .1; ch = gc(); while(isdigit(ch)) res += pos * (ch ^ 48), pos /= 10, ch = gc(); return f ? -res : res; } return f ? -x : x; } const int N = 25; struct vec{ double x, y; vec(){} vec(double x, double y): x(x), y(y) {} inline vec operator + (vec rhs) { return vec(x + rhs.x, y + rhs.y); } inline vec operator - (vec rhs) { return vec(x - rhs.x, y - rhs.y); } inline vec operator * (double k){ return vec(x * k, y * k); } inline double dis(){ return sqrt(x * x + y * y); } inline double dis(const vec &rhs){ return sqrt((rhs.x - x) * (rhs.x - x) + (rhs.y - y) * (rhs.y - y)); } }sa, sb, ta, tb, ans_xy; double ax, bx, ay, by, cx, cy, dx, dy, da, db; double ans_z = 1e100; struct node{ double bstz; double x, vx, y, vy, bstx, bsty, z; }b[N]; double p, q, r; inline double Rand(){ return (double) rand() / RAND_MAX; } inline double calc(double x, double y){ return x / p + y / q + (sa + (ta * x)).dis(sb + (tb * y)) / r; } inline void update(node &a){ a.vx = a.vx * 0.5 + Rand() * 2 * (ans_xy.x + a.bstx - 2 * a.x); a.vy = a.vy * 0.5 + Rand() * 2 * (ans_xy.y + a.bsty - 2 * a.y); a.x += a.vx; a.y += a.vy; if(a.x > da) a.x = da, a.vx *= -1; if(a.y > db) a.y = db, a.vy *= -1; if(a.x < 0) a.x = 0, a.vx *= -1; if(a.y < 0) a.y = 0, a.vy *= -1; a.z = calc(a.x, a.y); if(a.z < a.bstz){ a.bstz = a.z; a.bstx = a.x; a.bsty = a.y; } if(a.z < ans_z){ ans_z = a.z; ans_xy = vec(a.x, a.y); } } #define eps 1e-8 signed main(){ ax = read(), ay = read(), bx = read(), by = read(); sa = vec(ax, ay); ta = vec(bx - ax, by - ay); da = ta.dis() + eps; ta = ta * (1 / da); cx = read(), cy = read(), dx = read(), dy = read(); sb = vec(dx, dy); tb = vec(cx - dx, cy - dy); db = tb.dis() + eps; tb = tb * (1 / db); p = read(), q = read(), r = read(); for(int i = 0; i < N; ++i){ b[i].bstx = b[i].x = Rand() * da; b[i].y = b[i].bsty = Rand() * db; b[i].bstz = b[i].z = calc(b[i].x, b[i].y); if(b[i].z < ans_z){ ans_xy = vec(b[i].x, b[i].y); ans_z = b[i].z; } } rep(k, 1, 20) for(int i = 0; i < N; ++i) update(b[i]); printf("%.2lf\n", ans_z); gc(), gc(); return 0; } /* 2 2 2 2 3 3 3 3 1 1 1 */ ```