├── .gitignore ├── README.md ├── homework ├── ch1习题.pdf ├── ch2习题.pdf ├── ch3习题.pdf ├── ch4习题.pdf ├── ch5习题.pdf ├── ch7习题.pdf ├── ch8习题.pdf └── ch9习题.pdf ├── lab ├── README.md ├── lab01 │ ├── BruteForceCH.hpp │ ├── ConvexHull.hpp │ ├── DivAndConCH.hpp │ ├── DivAndConCH2.hpp │ ├── GrahamScanCH.hpp │ ├── Makefile │ ├── Point.hpp │ ├── PointsSampler.hpp │ ├── README.md │ ├── data-old.txt │ ├── data.txt │ ├── draw.py │ ├── images │ │ ├── BruteForceCH.png │ │ ├── DivAndConCH-Merge.png │ │ ├── DivAndConCH2-Merge.png │ │ ├── Graham-Scan.png │ │ ├── benchmark-old.png │ │ └── benchmark.png │ ├── main.cpp │ └── testcases.txt ├── lab02 │ ├── README.md │ ├── astar.py │ ├── biastar.py │ ├── images │ │ ├── map01-astar.png │ │ ├── map01-biastar.png │ │ ├── map01.png │ │ ├── map02-astar.png │ │ ├── map02-biastar.png │ │ └── map02.png │ ├── map1.txt │ └── map2.txt ├── lab03 │ ├── GreedySetCover.hpp │ ├── LPRoundingSetCover.hpp │ ├── Makefile │ ├── README.md │ ├── Sampler.hpp │ ├── images │ │ ├── GreedySetCover.png │ │ ├── GreedySetCover2.png │ │ ├── LPRoundingSetCover.png │ │ └── SetCover2LP.png │ └── main.cpp ├── lab04 │ ├── Makefile │ ├── README.md │ ├── data1000k.txt │ ├── data100k.txt │ ├── data10k.txt │ ├── draw.py │ ├── images │ │ ├── 1000k.png │ │ ├── 100k.png │ │ └── 10k.png │ ├── main.cpp │ └── qsort.hpp ├── lab05 │ ├── BFPRT.hpp │ ├── Makefile │ ├── README.md │ ├── images │ │ ├── BFPRT.png │ │ └── lazyselect.png │ ├── lazyselect.hpp │ ├── main.cpp │ └── mrandom.hpp ├── setcover-tamara.pdf └── 算法实验指导书.pdf └── slides ├── ch0.pdf ├── ch1.pdf ├── ch10.pdf ├── ch2.pdf ├── ch3.pdf ├── ch4.pdf ├── ch5.pdf ├── ch6.pdf ├── ch7.pdf ├── ch8.pdf └── ch9.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .gdb_history -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HIT-Algo 2 | 3 | 哈工大研究生课程: 高级算法设计与分析 (Advanced algorithm design and analysis), [实验](lab/) [作业](homework/) [课件](slides/) 4 | 5 | ## 实验部分 6 | 7 | * [x] 实验一: 分治算法 8 | * [x] 实验二: 搜索算法 9 | * [x] 实验三: 近似算法 10 | * [x] 实验四: 快速排序 11 | * [ ] 实验五: 计算k位数的随机算法 12 | 13 | ## 作业部分 14 | 15 | * [ ] 第一章习题 16 | * [ ] 第二章习题 17 | * [ ] 第三章习题 18 | * [ ] 第四章习题 19 | * [ ] 第五章习题 20 | * [ ] 第六章习题 21 | * [ ] 第七章习题 22 | * [ ] 第八章习题 23 | * [ ] 第九章习题 24 | -------------------------------------------------------------------------------- /homework/ch1习题.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/homework/ch1习题.pdf -------------------------------------------------------------------------------- /homework/ch2习题.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/homework/ch2习题.pdf -------------------------------------------------------------------------------- /homework/ch3习题.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/homework/ch3习题.pdf -------------------------------------------------------------------------------- /homework/ch4习题.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/homework/ch4习题.pdf -------------------------------------------------------------------------------- /homework/ch5习题.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/homework/ch5习题.pdf -------------------------------------------------------------------------------- /homework/ch7习题.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/homework/ch7习题.pdf -------------------------------------------------------------------------------- /homework/ch8习题.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/homework/ch8习题.pdf -------------------------------------------------------------------------------- /homework/ch9习题.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/homework/ch9习题.pdf -------------------------------------------------------------------------------- /lab/README.md: -------------------------------------------------------------------------------- 1 | # 实验部分 2 | 3 | ## 实验一: 分治算法 4 | 5 | ### 实验目的 6 | 7 | * 掌握分治算法的设计思想与方法 8 | * 熟练使用高级编程语言实现分治算法 9 | * 通过对比简单算法以及不同的分治求解思想,理解算法复杂度 10 | 11 | ### 实验问题 12 | 13 | 求解凸包问题:输入是平面上 $n$ 个点的集合$Q$,凸包问题是要输出一个$Q$的凸包。其中,$Q$ 的凸包是一个凸多边形$P$,$Q$ 中的点或者在$P$上或者在$P$中。(详情请见课件) 14 | 15 | ### 实验步骤 16 | 17 | #### 实现基于枚举方法的凸包求解算法 18 | 19 | * 算法思想 20 | 21 | ![BruteForceCH](lab01/images/BruteForceCH.png) 22 | 算法需要四层循环,每层遍历所有点,复杂度为$O(n^4)$ 23 | 24 | * 实现如下,详见文件[BruteForceCH.hpp](lab01/BruteForceCH.hpp) 25 | 26 | ```c++ 27 | /** 28 | * time complexity: O(n^4+nlog(n)) 29 | */ 30 | vector> BruteForceCH::work() { 31 | int n = P.size(); 32 | if (n == 0) return vector>(); 33 | for (int a = 0; a < n; ++a) { 34 | if (P[a].x < 0) continue; // Point::x < 0 -> point deleted 35 | for (int b = 0; b < n; ++b) { 36 | if (P[a].x < 0) break; // important 37 | if (b == a || P[b].x < 0) continue; 38 | for (int c = 0; c < n; ++c) { 39 | if (P[b].x < 0 || P[a].x < 0) break; // important 40 | if (c == a || c == b || P[c].x < 0) continue; 41 | // check if abc on same line, if so, delete the middle point 42 | if (P[a].cross(P[b], P[c]) == 0) { 43 | int i = a, j = b, k = c; 44 | if (P[j] < P[i]) swap(i, j); 45 | if (P[j] < P[k]) P[j].x = -1; 46 | else if (P[i] < P[k]) P[k].x = -1; 47 | else P[i].x = -1; 48 | continue; 49 | } 50 | for (int d = 0; d < n; ++d) { 51 | if (d == a || d == b || d == c || P[d].x < 0) continue; 52 | if (P[a].cross(P[b], P[c])*P[a].cross(P[b], P[d]) >= 0 53 | && P[a].cross(P[c], P[b])*P[a].cross(P[c], P[d]) >= 0 54 | && P[b].cross(P[c], P[a])*P[b].cross(P[c], P[d]) >= 0 55 | ) { 56 | P[d].x = -1; // delete 57 | } 58 | } 59 | } 60 | } 61 | } 62 | // A, B, left most & right most 63 | int m = 1, i = 0; 64 | while (P[i].x < 0) ++i; 65 | int a = i, b = i; 66 | for (++i; i < n; ++i) { 67 | if (P[i].x < 0) continue; 68 | ++m; 69 | if (P[i] < P[a]) a = i; 70 | if (P[b] < P[i]) b = i; 71 | } 72 | vector> CH(m), S_U(m); 73 | CH[0] = P[a]; // A 74 | int il = 1, iu = 0; 75 | // S_L, S_U 76 | for (int i = 0; i < n; ++i) { 77 | if (P[i].x < 0 || i == a || i == b) continue; 78 | if (P[a].cross(P[b], P[i]) < 0) { // < 0, S_L 79 | CH[il++] = P[i]; 80 | } else { // > 0, S_U 81 | S_U[iu++] = P[i]; 82 | } 83 | } 84 | // A, S_L, B, reverse(S_U) 85 | sort(CH.begin() + 1, CH.begin() + il); // S_L 86 | sort(S_U.begin(), S_U.begin() + iu); 87 | CH[il] = P[b]; // B 88 | for (int i = 0; i < iu; ++i) CH[il+1+i] = S_U[iu-1-i]; // reverse(S_U) 89 | return CH; 90 | } 91 | ``` 92 | 93 | * 首先四层循环,不断删除点,如果这个点在某个三角形内的话,删除的点的$x$坐标标记为-1。 94 | * 需要注意和伪代码略有不同的是(伪代码只描述了主要逻辑,具体实现细节有的地方需要注意),三角形的三点如果共线,那么删除掉三点中中间的点,不进入4层循环,而是返回到删除点的那一层(向外可能多次break) 95 | * 最后就是图包点的顺序调整(和伪代码一致),返回 96 | 97 | #### 实现基于Graham-Scan的凸包求解算法 98 | 99 | * 算法思想 100 | 101 | ![Graham-Scan](lab01/images/Graham-Scan.png) 102 | 103 | 算法需要用到排序,每个点最多访问两次(加入,删除),所以最终复杂度为$O(n\log n)$ 104 | 105 | * 实现如下,详见文件[GrahamScanCH.hpp](lab01/GrahamScanCH.hpp) 106 | 107 | ```c++ 108 | /** 109 | * time complexity: O(nlog(n)) 110 | */ 111 | vector> GrahamScanCH::work() { 112 | int n = P.size(); 113 | if (n == 0) return vector>(); 114 | swap(P[0], *min_element(P.begin(), P.end())); 115 | if (n <= 2) return P; 116 | sort(P.begin()+1, P.end(), [&](const auto& a, const auto& b) { 117 | int c = P[0].cross(a, b); 118 | return c > 0 || (c == 0 && P[0].dist2(a) < P[0].dist2(b)); 119 | }); 120 | P.push_back(P[0]); // 处理最后一个点更简单 121 | vector> CH; 122 | int m = 0; 123 | for (int i = 0; i <= n; ++i) { 124 | while (m >= 2 && CH[m-2].cross(CH[m-1], P[i]) <= 0) { 125 | if (i == n && m == 2) break; // 防止所有点都共线,删除了一端端点 126 | CH.pop_back(), --m; 127 | } 128 | CH.push_back(P[i]); 129 | ++m; 130 | } 131 | CH.pop_back(); 132 | return CH; 133 | } 134 | ``` 135 | 136 | * 首先寻找左下角的点,按照它为极点将其余点按照极角排序(极角大小的判定通过叉积计算,比算角度方便) 137 | * 为了处理最后一个点方便,额外将极点再加入到末尾 138 | * 循环中注意所有点如果在同一条线上的话会多把一个端点删除掉,所以循环中有一行判断 139 | * 最后弹出额外加入的极点,返回凸包结果 140 | 141 | #### 实现基于分治思想的凸包求解算法 142 | 143 | * 算法思想 144 | 145 | * 实现了两种分治算法,分别见[DivAndConCH.hpp](lab01/DivAndConCH.hpp)和[DivAndConCH2.hpp](lab01/DivAndConCH2.hpp) 146 | 147 | * DivAndConCH2中的算法采用的是课件中的方式,主要在于merge步骤,前面部分都相同。 148 | 149 | ![image-20210513180123145](lab01/images/DivAndConCH-Merge.png) 150 | 151 | * DivAndConCH中的算法采用的[Convex Hull: Divide and Conquer](http://web.ntnu.edu.tw/~algo/ConvexHull.html#6)方式,merge过程通过找上下公切线实现,从左凸包的最右点和右凸包的最左点开始,不断旋转端点到下一点,直到卡死,复杂度也是$O(n)$ 152 | 153 | ![image-20210513180611937](lab01/images/DivAndConCH2-Merge.png) 154 | 155 | * 算法实现 156 | 157 | * DivAndConCH,找上下公切线方式merge 158 | 159 | ```c++ 160 | /** 161 | * time complexity: O(nlog(n)) 162 | */ 163 | vector> DivAndConCH::work() { 164 | int n = P.size(); 165 | if (n == 0) return vector>(); 166 | sort(P.begin(), P.end()); 167 | return _div_con(0, n); 168 | } 169 | 170 | vector> DivAndConCH::_div_con(int l, int r) { 171 | int m = r - l; 172 | if (m < 3) return vector>(P.begin()+l, P.begin()+r); 173 | vector> lCH = _div_con(l, l + m/2), rCH = _div_con(l + m/2, r); 174 | int lsz = lCH.size(), rsz = rCH.size(); 175 | // merge 176 | int a = 0, b = 0; 177 | for (int i = 0; i < lsz; ++i) { 178 | if (lCH[a] < lCH[i]) a = i; 179 | } 180 | for (int i = 0; i < rsz; ++i) { 181 | if (rCH[i] < rCH[b]) b = i; 182 | } 183 | int llb = a, lrb = a, rlb = b, rrb = b; 184 | // 下公切线 185 | while (true) { 186 | bool changed = false; 187 | for (int nlrb = (lrb-1+lsz)%lsz, cs = rCH[rlb].cross(lCH[lrb], lCH[nlrb]); 188 | cs > 0 || (cs == 0 && rCH[rlb].dist2(lCH[lrb]) < rCH[rlb].dist2(lCH[nlrb])); 189 | nlrb = (lrb-1+lsz)%lsz, cs = rCH[rlb].cross(lCH[lrb], lCH[nlrb])) { 190 | lrb = nlrb; 191 | changed = true; 192 | } 193 | for (int nrlb = (rlb+1)%rsz, cs = lCH[lrb].cross(rCH[rlb], rCH[nrlb]); 194 | cs < 0 || (cs == 0 && lCH[lrb].dist2(rCH[rlb]) < lCH[lrb].dist2(rCH[nrlb])); 195 | nrlb = (rlb+1)%rsz, cs = lCH[lrb].cross(rCH[rlb], rCH[nrlb])) { 196 | rlb = nrlb; 197 | changed = true; 198 | } 199 | if (!changed) break; 200 | } 201 | // 上公切线 202 | while (true) { 203 | bool changed = false; 204 | for (int nllb = (llb+1)%lsz, cs = rCH[rrb].cross(lCH[llb], lCH[nllb]); 205 | cs < 0 || (cs == 0 && rCH[rrb].dist2(lCH[llb]) < rCH[rrb].dist2(lCH[nllb])); 206 | nllb = (llb+1)%lsz, cs = rCH[rrb].cross(lCH[llb], lCH[nllb])) { 207 | llb = nllb; 208 | changed = true; 209 | } 210 | for (int nrrb = (rrb-1+rsz)%rsz, cs = lCH[llb].cross(rCH[rrb], rCH[nrrb]); 211 | cs > 0 || (cs == 0 && lCH[llb].dist2(rCH[rrb]) < lCH[llb].dist2(rCH[nrrb])); 212 | nrrb = (rrb-1+rsz)%rsz, cs = lCH[llb].cross(rCH[rrb], rCH[nrrb])) { 213 | rrb = nrrb; 214 | changed = true; 215 | } 216 | if (!changed) break; 217 | } 218 | vector> CH; 219 | CH.push_back(lCH[llb]); 220 | while (llb != lrb) { 221 | llb = (llb+1)%lsz; 222 | CH.push_back(lCH[llb]); 223 | } 224 | CH.push_back(rCH[rlb]); 225 | while (rlb != rrb) { 226 | rlb = (rlb+1)%rsz; 227 | CH.push_back(rCH[rlb]); 228 | } 229 | return CH; 230 | } 231 | ``` 232 | 233 | 这里的merge步骤需要寻找上下的公切线,公切线是凸包上下的两条线(注意公切线端点不一定是两个凸包的最高最低点,需要通过旋转方向来判定--求叉积),得到公切线后逆时针保存凸包即可,merge步骤复杂度为$O(n)$,总的算法复杂度根据master定理可求得为$n\log n$ 234 | 235 | * DivAndConCH2,课件中的方式,根据极角大小,逆时针方向merge 236 | 237 | ```c++ 238 | /** 239 | * time complexity: O(nlog(n)) 240 | */ 241 | vector> DivAndConCH2::work() { 242 | int n = P.size(); 243 | if (n == 0) return vector>(); 244 | sort(P.begin(), P.end()); 245 | return _div_con(0, n); 246 | } 247 | 248 | vector> DivAndConCH2::_div_con(int l, int r) { 249 | int m = r - l; 250 | if (m < 3) return vector>(P.begin()+l, P.begin()+r); 251 | vector> lCH = _div_con(l, l + m/2), rCH = _div_con(l + m/2, r); 252 | int lsz = lCH.size(), rsz = rCH.size(); 253 | // merge 254 | vector> P2; 255 | P2.push_back(lCH[0]); 256 | auto cmp = [&](const auto& a, const auto& b) { 257 | int c = P2[0].cross(a, b); 258 | return c > 0 || (c == 0 && P2[0].dist2(a) < P2[0].dist2(b)); 259 | }; 260 | // 寻找右边极角最大,最小的点的下标,对应rh, rl 261 | int rl = 0, rh = 0; 262 | for (int i = 1; i < rsz; ++i) { 263 | if (cmp(rCH[rh], rCH[i])) rh = i; 264 | else if (cmp(rCH[i], rCH[rl])) rl = i; 265 | } 266 | // 将三个序列的元素归并到P2,复杂度O(n) 267 | int i = 1, j = rl, k = (rl - 1 + rsz) % rsz; 268 | while (i != lsz || j != rh || k != (rh-1+rsz)%rsz) { 269 | int flag = 0; 270 | if (i == lsz || (j != rh && cmp(rCH[j], lCH[i]))) flag = 1; 271 | if (flag == 1) { 272 | if (j == rh || (k != (rh-1+rsz)%rsz && cmp(rCH[k], rCH[j]))) flag = 2; 273 | } else if ((k != (rh-1+rsz)%rsz && cmp(rCH[k], lCH[i]))) { 274 | flag = 2; 275 | } 276 | if (flag == 0) { 277 | P2.push_back(lCH[i++]); 278 | } else if (flag == 1) { 279 | P2.push_back(rCH[j++]); 280 | j %= rsz; 281 | } else { 282 | P2.push_back(rCH[k--]); 283 | k = (k+rsz) % rsz; 284 | } 285 | } 286 | // P2中的点已经按照极角排序(逆时针排序),极点为P2[0] 287 | // 下面复用GrahamScanCH代码,已经有序,复杂度为O(n) 288 | int n = P2.size(); 289 | P2.push_back(P2[0]); 290 | vector> CH; 291 | m = 0; 292 | for (int i = 0; i <= n; ++i) { 293 | while (m >= 2 && CH[m-2].cross(CH[m-1], P2[i]) <= 0) { 294 | if (i == n && m == 2) break; // 防止所有点都共线,删除了一端端点 295 | CH.pop_back(), --m; 296 | } 297 | CH.push_back(P2[i]); 298 | ++m; 299 | } 300 | CH.pop_back(); 301 | return CH; 302 | } 303 | ``` 304 | 305 | 这里主要就是在左边凸包随意选择一点作为极点,然后寻找右边极角最大最小的两个点,这极角的比较也是通过判断旋转方向来的。然后知道坐标范围后归并三个序列,最后在这个序列上直接复用之前的GrahamScanCH代码(已经有序,不需要额外的排序预处理)。所以merge步骤复杂度为$O(n)$,总的算法复杂度根据master定理可求得为$n\log n$ 306 | 307 | ### 对比三种凸包求解算法 308 | 309 | #### 样本生成 310 | 311 | [PointsSampler.hpp](lab01/PointsSampler.hpp)负责生成正方形(0,0)-(0,100)-(100,100)-(100,0)内的k个点,采用的算法是下面的水池抽样算法,参考[wiki: Reservoir sampling - An optimal algorithm](https://en.wikipedia.org/wiki/Reservoir_sampling#An_optimal_algorithm),它将从正方形中等概率地生成k个点 312 | 313 | ```c++ 314 | class PointsSampler 315 | { 316 | public: 317 | const static int R = 101, C = 101, N = R * C; 318 | /** 319 | * Reservoir Sampling, time complexity O(k(1+log(n/k))) 320 | */ 321 | static vector> sample_k(int k) { 322 | assert(k >= 0 && k <= N); 323 | vector> res; 324 | if (k == 0) return res; 325 | res.reserve(k); 326 | for (int i = 0; i < k; ++i) res.emplace_back(i/C, i%C); 327 | double W = exp(log(rand_real(0, 1))/k); 328 | for (int i = k; i < N;) { 329 | i += floor(log(rand_real(0, 1))/log(1-W)) + 1; 330 | if (i < N) { 331 | int idx = rand_int(0, k-1); 332 | res[idx].x = i/C; 333 | res[idx].y = i%C; 334 | W *= exp(log(rand_real(0, 1))/k); 335 | } 336 | } 337 | return res; 338 | } 339 | }; 340 | ``` 341 | 342 | 算法复杂度为$O(k(1+log(n/k)))$,n为总的点数,所以这里就是$101\times 101 = 10201$,$k$是需要的点数 343 | 344 | #### 运行结果对比 345 | 346 | 尝试随机生成了0到10000大小的样本(相邻样本大小间隔10),对四个凸包求解算法实现进行测试,然后用python的matplotlib进行绘图,得到如下结果 347 | 348 | ![benchmark](lab01/images/benchmark.png) 349 | 350 | 可以看出BruteForceCH的运行时间波动比较大,且运行时间随数据集增大增长更快,另外两种算法的运行时间随数据集增大增长比较平稳。也对应了他们各自的复杂度: BruteForceCH是$O(n^4)$, 另外三个是$nlog(n)$。两个分治算法运行时间基本相同,GrahamScan最优。主要分析是因为其只需要提前的一次排序,后面实际求图包过程是$O(n)$,而分治除了要预排序外,实际求解凸包的过程也是$O(n \log n)$,系数会更大,但都是同阶的$n \log n$。 351 | 352 | ### 参考 353 | 354 | * [Convex Hull 演算法笔记](http://web.ntnu.edu.tw/~algo/ConvexHull.html) 355 | * [wiki: 水池抽样算法](https://en.wikipedia.org/wiki/Reservoir_sampling) 356 | 357 | ## 实验二: 搜索算法 358 | 359 | ### 实验目的 360 | 361 | * 掌握搜索算法的基本设计思想与方法 362 | * 掌握A*算法的设计思想与方法 363 | * 熟练使用高级编程语言实现搜索算法 364 | * 利用实验测试给出的搜索算法的正确性 365 | 366 | ### 实验问题 367 | 368 | 寻路问题,给定网格,网格中有障碍,非障碍的格子可能带有额外代价,每一步可以去往相邻的8个格子,水平或垂直走代价为1,斜着走代价为`sqrt(2)`,寻找最小代价的路径。给定下面两个地图 369 | 370 | ![image-20210513184527013](lab02/images/map01.png) 371 | 372 | ![image-20210513184607808](lab02/images/map02.png) 373 | 374 | ### 实验步骤 375 | 376 | #### 单向A*算法 377 | 378 | * 算法思想:采用Best-first策略搜索树,节点$n$的代价函数为$f(n)=g(n)+h(n)$,$g(n)$是从根到当前节点的代价,$h^*(n)$是从$n$到目标节点的优化路径代价,$h(n)$是$h^*(n)$的估计(必须满足$h(n)\le h^*(n)$),这里采用的估计方式如下代码所示 379 | 380 | ```python 381 | def h(p1, p2): 382 | x1, y1 = p1 383 | x2, y2 = p2 384 | d = min(abs(x1 - x2), abs(y1 - y2)) 385 | return math.sqrt(2)*d + abs(x1 - x2) + abs(y1 - y2) - 2*d 386 | ``` 387 | 388 | 即设当前点到目标点的x, y坐标差的绝对值为$dx, dy$,则$h(n)=\sqrt{2}\min(dx, dy)+|dx-dy|=\sqrt{2}\min(dx, dy)+dx+dy-2\min(dx, dy)$ 389 | 390 | * 算法核心实现如下 391 | 392 | ```python 393 | def astar(draw, grid, start, end): 394 | # count = 0 395 | open_set = [] 396 | heapq.heappush(open_set, (0, start)) 397 | came_from = {} 398 | g_score = {spot: float("inf") for row in grid for spot in row} 399 | g_score[start] = 0 400 | f_score = {spot: float("inf") for row in grid for spot in row} 401 | f_score[start] = h(start.get_pos(), end.get_pos()) 402 | 403 | open_set_hash = {start} 404 | 405 | pause = 0 406 | while len(open_set): 407 | for event in pygame.event.get(): 408 | if event.type == pygame.QUIT: 409 | bye() 410 | elif event.type == pygame.KEYDOWN: 411 | if event.key == pygame.K_SPACE: 412 | pause ^= 1 413 | elif event.key == pygame.K_q: 414 | bye() 415 | 416 | if pause: continue 417 | current = heapq.heappop(open_set)[1] 418 | open_set_hash.remove(current) 419 | 420 | if current == end: 421 | reconstruct_path(came_from, end, draw) 422 | # end.make_end() 423 | return True 424 | 425 | for neighbor in current.neighbors: 426 | temp_g_score = g_score[current] + (1 if neighbor.row == current.row or neighbor.col == current.col else math.sqrt(2)) 427 | if neighbor.cost_idx: temp_g_score += EXTRA_COST[neighbor.cost_idx] 428 | if temp_g_score < g_score[neighbor]: 429 | came_from[neighbor] = current 430 | g_score[neighbor] = temp_g_score 431 | f_score[neighbor] = temp_g_score + h(neighbor.get_pos(), end.get_pos()) 432 | if neighbor not in open_set_hash: 433 | # count += 1 434 | heapq.heappush(open_set, (f_score[neighbor], neighbor)) 435 | open_set_hash.add(neighbor) 436 | neighbor.make_open() 437 | 438 | draw() 439 | 440 | if current != start: 441 | current.make_closed() 442 | 443 | return False 444 | ``` 445 | 446 | 采用堆维护节点的代价,当遇到目标点时,构建最优路径,然后返回True 447 | 448 | 构建最优路径比较简单,就是不断向上寻找父亲节点,代码如下 449 | 450 | ```python 451 | def reconstruct_path(came_from, current, draw): 452 | while current in came_from: 453 | current = came_from[current] 454 | current.make_path() 455 | draw() 456 | ``` 457 | 458 | #### 双向A*算法 459 | 460 | * 和单向A*算法总体思想一致,只是现在从起始点和目标点同时开始搜索,当两端搜索的点相遇时,表示找到了最短路径,向两端构建最短路径 461 | 462 | * 代码详情见[biastar.py](lab02/biastar.py) 463 | 464 | ```python 465 | def biastar(draw, grid, start, end): 466 | idx = 0 467 | open_set = [[], []] 468 | heapq.heappush(open_set[idx], (0, start)) 469 | heapq.heappush(open_set[idx^1], (0, end)) 470 | came_from = [{}, {}] 471 | g_score = [{spot: float("inf") for row in grid for spot in row}, {spot: float("inf") for row in grid for spot in row}] 472 | g_score[idx][start] = g_score[idx^1][end] = 0 473 | f_score = [{spot: float("inf") for row in grid for spot in row}, {spot: float("inf") for row in grid for spot in row}] 474 | f_score[idx][start] = f_score[idx^1][end] = h(start.get_pos(), end.get_pos()) 475 | 476 | open_set_hash = [{start}, {end}] 477 | 478 | pause = 0 479 | while len(open_set[0]) and len(open_set[1]): 480 | for event in pygame.event.get(): 481 | if event.type == pygame.QUIT: 482 | bye() 483 | elif event.type == pygame.KEYDOWN: 484 | if event.key == pygame.K_SPACE: 485 | pause ^= 1 486 | elif event.key == pygame.K_q: 487 | bye() 488 | if pause: continue 489 | if len(open_set[idx]) > len(open_set[idx^1]): idx ^= 1 490 | current = heapq.heappop(open_set[idx])[1] 491 | open_set_hash[idx].remove(current) 492 | 493 | if current in open_set_hash[idx^1]: 494 | print(current.row, current.col) 495 | reconstruct_path(came_from[0], current, draw) 496 | reconstruct_path(came_from[1], current, draw) 497 | # end.make_end() 498 | return True 499 | 500 | for neighbor in current.neighbors: 501 | temp_g_score = g_score[idx][current] + (1 if neighbor.row == current.row or neighbor.col == current.col else math.sqrt(2)) 502 | if neighbor.cost_idx: temp_g_score += EXTRA_COST[neighbor.cost_idx] 503 | if temp_g_score < g_score[idx][neighbor]: 504 | came_from[idx][neighbor] = current 505 | g_score[idx][neighbor] = temp_g_score 506 | f_score[idx][neighbor] = temp_g_score + h(neighbor.get_pos(), end.get_pos()) 507 | if neighbor not in open_set_hash[idx]: 508 | heapq.heappush(open_set[idx], (f_score[idx][neighbor], neighbor)) 509 | open_set_hash[idx].add(neighbor) 510 | neighbor.make_open() 511 | 512 | draw() 513 | 514 | if current != start and current != end: 515 | current.make_closed() 516 | 517 | return False 518 | ``` 519 | 520 | #### 图形化,用户交互 521 | 522 | * 为了便于展示与用户交互,采用pygame(一个python的游戏开发库)进行开发 523 | 524 | * 可视化代码借鉴 [ytb: A* Pathfinding Visualization Tutorial](https://www.youtube.com/watch?v=JtiK0DOeI4A) 525 | 526 | * 使用说明 527 | 528 | 两个程序`astar.py`和`biastar.py`分别对应了单向和双向的`A*`搜索,程序的使用方法完全一致 529 | 530 | * `pip install pygame` 安装依赖pygame 531 | 532 | * `python astar.py [mapfile.txt]` 533 | 534 | * 这里的地图文件可以通过按`s`键保存得到,参考下面的COMMANDS 535 | 536 | * 实验中要求的两个地图我已经保存了,对应`map1.txt`和`map2.txt`: `python astar.py map1.txt`运行 537 | 538 | * COMMANDS 操作方式 539 | 540 | * 鼠标左键 设置某个块儿 541 | * 默认情况或者按了`0`之后,左键会把点击的块儿设置为**起点**(不存在起点),**终点**(存在起点不存在终点),**障碍**(已存在起点和终点) 542 | * 按了`1`之后,为点击的块儿设置额外代价(经过这个块儿会有额外代价) 543 | * 按了`2`之后同理,只是额外代价不同 544 | * 额外的代价见代码中的变量: `EXTRA_COST = [0, 2, 4]`,如果还想有更多的代价往后面加就行了,因为采用一个数字按键对应不同代价,所以最多可以有9种额外代价,对应按键/下标: `1-9`. 545 | * 鼠标右键 清除某个块儿 546 | * 键盘`q` 退出程序 547 | * 键盘`s` 保存当前地图到当前目录,按时间命名(详细说明见下一节) 548 | * 键盘`` 开始/暂停/继续路径搜索 549 | * 键盘`c` 清除搜索痕迹(搜索过程中不可用) 550 | * 键盘`n` 清空地图(搜索过程中不可用) 551 | 552 | #### 地图保存,加载 553 | 554 | 程序实现了地图的保存与加载: 555 | 556 | * 按键盘的`s`键保存地图 557 | * `python astar.py map01.txt`加载地图`map01.txt`运行 558 | 559 | 下面对地图文件的格式做说明,比如对于第二个地图`map02.txt` 560 | 561 | ```txt 562 | 20 40 34 563 | 0 0 0 -1 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 T2 2 2 2 2 564 | 0 0 0 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 565 | -1 -1 -1 -1 -1 -1 0 -1 -1 -1 -1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 2 2 2 2 2 2 566 | 0 0 0 0 0 0 0 0 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 2 2 2 2 0 0 0 567 | 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 2 2 0 0 0 0 568 | 0 0 0 0 0 0 0 -1 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 0 0 0 0 0 569 | 0 0 -1 -1 -1 -1 -1 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 0 0 0 0 0 570 | 0 0 -1 0 0 -1 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 -1 0 0 0 571 | 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 572 | 0 0 0 0 0 -1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 -1 0 0 0 573 | 0 0 -1 0 S0 -1 0 -1 -1 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 -1 0 0 0 1 1 0 1 1 0 0 0 574 | 0 0 -1 -1 -1 -1 0 0 -1 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0 0 0 -1 1 0 1 1 0 0 0 0 575 | 0 0 0 -1 0 0 0 0 -1 0 0 0 -1 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 576 | 0 0 0 -1 0 0 0 0 -1 -1 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 577 | 0 0 0 -1 0 0 0 0 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 578 | 0 0 0 -1 -1 -1 -1 -1 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 579 | 0 0 0 -1 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 580 | 0 0 0 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 581 | 0 0 0 -1 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 582 | 0 0 0 -1 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 583 | ``` 584 | 585 | 第一行三个整数`m,n,gap`分别表示地图格子有`m`行,`n`列,每个格子都是`gap*gap`像素大小的正方形块儿 586 | 587 | 接下来的m行n列整数具体代表了地图信息,一共有三种格子: 588 | 589 | * `-1`表示障碍 590 | 591 | * `0`表示可以行走的块,并且没有额外代价 592 | 593 | * `1-9`代表了可以行走的块,但是具有额外代价,这个数字代表了额外代价的下标,比如程序中的额外代价定义如下,表示下标1对应代价为2,下标2对应代价为4 594 | 595 | ```python 596 | # LAND, RIVER, DESERT 597 | EXTRA_COST = [0, 2, 4] 598 | ``` 599 | 600 | ### 实验结果 601 | 602 | * 单向`A*`,使用`map01.txt` 603 | 604 | ![astar - map01.txt](lab02/images/map01-astar.png) 605 | 606 | * 双向`A*`,使用`map01.txt` 607 | 608 | ![biastar - map01.txt](lab02/images/map01-biastar.png) 609 | 610 | * 单向`A*`,使用`map02.txt` 611 | 612 | ![astar - map02.txt](lab02/images/map02-astar.png) 613 | 614 | * 双向`A*`,使用`map02.txt` 615 | 616 | ![biastar - map02.txt](lab02/images/map02-biastar.png) 617 | 618 | 可以看出双向A\*在地图比较复杂时可以很好地减少搜索的节点数目(比如对于这里的地图2),因为它在选择扩展哪一端的搜索节点的时候总是选择当前openset小的那一端。而单向的A\*则几乎搜完了整个地图。 619 | 620 | ## 实验三: 近似算法 621 | 622 | ### 实验目的 623 | 624 | * 掌握近似算法的基本设计思想与方法 625 | * 掌握集合覆盖问题近似算法的设计思想与方法 626 | * 熟练使用高级编程语言实现近似算法 627 | * 利用实验测试给出不同近似算法的性能以理解其优缺点。 628 | 629 | ### 实验问题 630 | 631 | 求解集合覆盖问题 632 | 633 | * 输入: 有限集$X$,$X$的子集合族$F$,$X=\cup_{S \in F}S$ 634 | * 输出: $C \subseteq F$,满足 635 | * $X = \cup_{S \in C}S$ 636 | * $C$是满足上一条件的最小集族, 即$|C|$最小. 637 | 638 | ### 实验步骤 639 | 640 | #### 实现基于贪心策略的近似算法 641 | 642 | * 算法思想 643 | 644 | ![GreedySetCover2](lab03/images/GreedySetCover2.png) 645 | 646 | 而对于本实验,集合的代价都一样,都是1,所以上面的代码等价于 647 | 648 | ![GreedySetCover](lab03/images/GreedySetCover.png) 649 | 650 | * 代码实现,见[GreedySetCover.hpp](lab03/GreedySetCover.hpp) 651 | 652 | ```c++ 653 | vector greedy_set_cover(vector> &F, vector &U) { 654 | int n = F.size(); 655 | unordered_set C; // 已经包含的集合,这里每个集合用它的下标表示 656 | unordered_set Us(U.begin(), U.end()); // 还剩下的元素 657 | vector res; // 返回集合的下标 658 | while (!Us.empty()) { 659 | int sz = 0, j = -1; // 这次新包含F[j]可以新加入sz个元素 660 | for (int i = 0; i < n; ++i) { 661 | if (C.count(i)) continue; // 已经包含了 662 | int cur_sz = 0; 663 | for (int x: F[i]) { 664 | if (Us.count(x)) ++cur_sz; 665 | } 666 | if (cur_sz > sz) j = i; 667 | } 668 | for (int x: F[j]) Us.erase(x); 669 | res.push_back(j); 670 | C.insert(j); 671 | } 672 | return res; 673 | } 674 | ``` 675 | 676 | #### 实现一个基于线性规划近似算法 677 | 678 | * 算法思想 679 | 680 | ![SetCover2LP](lab03/images/SetCover2LP.png) 681 | 682 | * 将集合覆盖问题转换为线性规划问题(将对$x$的约束从$\{0,1\}$松弛为$x\ge 0$),然后采用工具求解线性规划问题, 683 | 684 | * 之后再根据舍入法或者随机舍入法获得原问题的解 685 | 686 | * 舍入法思想 687 | 688 | ![LPRoundingSetCover](lab03/images/LPRoundingSetCover.png) 689 | 690 | * 代码实现,这里借助GLPK库求解线性规划问题,并采用舍入法转为原来问题的解,详见[LPRoundingSetCover.hpp](lab03/LPRoundingSetCover.hpp) 691 | 692 | ```c++ 693 | vector LP_rounding_set_cover(vector> &F, vector &U) { 694 | int n = F.size(); // x个数 695 | int m = U.size(); // 约束不等式个数 696 | unordered_map x2i; 697 | for (int i = 0; i < m; ++i) x2i.emplace(U[i], i); // 每个元素对应的下标(对应了m个不等式约束) 698 | glp_prob *lp = glp_create_prob(); 699 | glp_set_obj_dir(lp, GLP_MIN); // 最小化目标(设置优化方向) 700 | glp_add_rows(lp, m); // 不等式个数 701 | for (int i = 1; i <= m; ++i) glp_set_row_bnds(lp, i, GLP_LO, 1., 0.); // 都是 >= 1 702 | glp_add_cols(lp, n); // 变量x个数 703 | for (int i = 1; i <= n; ++i) { 704 | glp_set_col_bnds(lp, i, GLP_LO, 0., 0.); // x的约束都是 >= 0 705 | glp_set_obj_coef(lp, i, 1.); // 目标函数中的x的系数,都是1 706 | } 707 | // f是最高的元素频率 708 | int sz = 0; 709 | vector freq(m); 710 | for (auto &S: F) { 711 | sz += S.size(); 712 | for (int x: S) ++freq[x2i[x]]; 713 | } 714 | int f = *max_element(freq.begin(), freq.end()); 715 | int *ia = new int[sz+1]; 716 | int *ja = new int[sz+1]; 717 | double *ar = new double[sz+1]; 718 | int idx = 1; 719 | for (int i = 0; i < n; ++i) { 720 | for (int x: F[i]) { 721 | ia[idx] = x2i[x] + 1; 722 | ja[idx] = i + 1; 723 | ar[idx] = 1.; 724 | ++idx; 725 | } 726 | } 727 | glp_load_matrix(lp, sz, ia, ja, ar); 728 | // glp_write_mps,glp_read_mps也可以写读lp问题,但这里对于现生成的数据不用了 729 | // lp问题初始化完毕,开始求解 730 | glp_smcp smcp; 731 | glp_init_smcp(&smcp); 732 | // 默认GLP_MSG_ALL: full output (including informational messages). 733 | smcp.msg_lev = GLP_MSG_ERR; // error and warning messages only; 734 | smcp.msg_lev = GLP_MSG_ON; // error and warning messages only; 735 | // smcp.presolve = GLP_ON; 736 | glp_simplex(lp, &smcp); 737 | // glp_iptcp iptcp; 738 | // iptcp.msg_lev = GLP_MSG_ERR; 739 | // glp_interior(lp, &iptcp); 740 | 741 | // glp_simplex(lp, nullptr); // 单纯形法求,发现更快 742 | // glp_interior(lp, nullptr); // 内点法求(karmarkar) 743 | 744 | // 舍入法选择保留的集合 745 | vector res; // 返回集合的下标 746 | for (int i = 0; i < n; ++i) { 747 | if (1./f <= glp_get_col_prim(lp, i+1)) res.push_back(i); 748 | // cout << "x" << i << ": " << glp_get_col_prim(lp, i) << " "; 749 | } 750 | // cout << endl; 751 | delete [] ia; 752 | delete [] ja; 753 | delete [] ar; 754 | glp_delete_prob(lp); 755 | return res; 756 | } 757 | ``` 758 | 759 | #### 测试算法性能 760 | 761 | * 数据生成方式 762 | 763 | 为了方便,实验把全集定为0到N-1,按照指导书的方式生成一些集合保证有解,然后再随机生成剩余的集合,每个集合大小还是在1到20之间,集合元素从所有元素中随机取,这里的实现也使用了水池抽样算法,具体代码见[Sampler.hpp](lab03/Sampler.hpp) 764 | 765 | * 实现代码 766 | 767 | ```c++ 768 | /** 769 | * 集族 F 770 | * [0..N-1] 771 | */ 772 | vector> generate_subsets(int N) { 773 | assert(N >= 20); 774 | vector> F; 775 | int sz = 0; 776 | unordered_set U; // 剩下的 777 | // [0..N-1] 778 | for (int i = 0; i < N; ++i) U.insert(i); 779 | unordered_set C; // 已经包含的 780 | F.emplace_back(sample_k(20, N)); 781 | for (int x: F[0]) { 782 | U.erase(x); 783 | C.insert(x); 784 | } 785 | ++sz; 786 | while (!U.empty()) { 787 | if (U.size() < 20) { 788 | F.emplace_back(U.begin(), U.end()); 789 | ++sz; 790 | break; 791 | } 792 | int n = rand_int(1, 20); 793 | int k = rand_int(1, n); // 新元素个数 794 | F.emplace_back(sample_k(k, U)); 795 | vector old = sample_k(k, C); 796 | for (int x: F[sz]) { 797 | U.erase(x); 798 | C.insert(x); 799 | } 800 | F[sz].insert(F[sz].end(), old.begin(), old.end()); 801 | ++sz; 802 | } 803 | while (sz != N) { 804 | F.push_back(sample_k(rand_int(1, 20), N)); 805 | ++sz; 806 | } 807 | return F; 808 | } 809 | ``` 810 | 811 | ### 试验结果 812 | 813 | 分别对$|X|=|F|=100,1000,5000$ 三种情况进行了测试,记录了问题求解的时间并验证了求解的$C$是否覆盖了所有元素 814 | 815 | 某次运行结果如下所示,这里保留了GLPK的迭代信息输出 816 | 817 | ```txt 818 | ----N: 100 819 | took: 0.001194 second(s) 820 | size of C: 23 821 | valid cover: true 822 | ----N: 1000 823 | took: 0.126470 second(s) 824 | size of C: 274 825 | valid cover: true 826 | ----N: 5000 827 | took: 2.972539 second(s) 828 | size of C: 1324 829 | valid cover: true 830 | ---------------------- 831 | ----N: 100 832 | 0: obj = 0.000000000e+00 inf = 1.000e+02 (100) 833 | 13: obj = 1.100000000e+01 inf = 0.000e+00 (0) 834 | * 85: obj = 7.481971581e+00 inf = 0.000e+00 (0) 835 | took: 0.005796 second(s) 836 | size of C: 25 837 | valid cover: true 838 | ----N: 1000 839 | 0: obj = 0.000000000e+00 inf = 1.000e+03 (1000) 840 | 157: obj = 1.183333333e+02 inf = 1.332e-15 (0) 841 | * 1652: obj = 8.194573952e+01 inf = 0.000e+00 (0) 15 842 | took: 0.232819 second(s) 843 | size of C: 321 844 | valid cover: true 845 | ----N: 5000 846 | 0: obj = 0.000000000e+00 inf = 5.000e+03 (5000) 847 | 703: obj = 5.870000000e+02 inf = 0.000e+00 (0) 2 848 | * 5982: obj = 4.527092380e+02 inf = 0.000e+00 (2273) 52 849 | * 8251: obj = 4.301339718e+02 inf = 0.000e+00 (2282) 23 850 | * 9979: obj = 4.174880525e+02 inf = 0.000e+00 (2140) 17 851 | * 11587: obj = 4.094090563e+02 inf = 0.000e+00 (2178) 15 852 | * 13031: obj = 4.046629836e+02 inf = 0.000e+00 (2301) 15 853 | * 14449: obj = 4.013014280e+02 inf = 0.000e+00 (2211) 14 854 | * 15868: obj = 3.993408117e+02 inf = 0.000e+00 (1784) 13 855 | * 17296: obj = 3.986827901e+02 inf = 0.000e+00 (64) 15 856 | * 17355: obj = 3.986823266e+02 inf = 0.000e+00 (0) 857 | took: 40.719696 second(s) 858 | size of C: 1679 859 | valid cover: true 860 | ---------------------- 861 | ``` 862 | 863 | 上面三个是对第一个贪心求解方法的测试,下面三个是利用舍入法进行的求解,可以看出基于贪心的求解比较快,最终求解的覆盖集合$C$的大小两个方法相差不大,不过还是基于贪心策略的方法要小一些,可能是由于矩阵比较大,解起来花费时间较多。验证了两种方法在三个不同大小的数据集上都得到了有效的集合覆盖。 864 | 865 | ## 实验四: 快速排序 866 | 867 | ### 实验目的 868 | 869 | * 掌握快速排序随机算法的设计思想与方法 870 | * 熟练使用高级编程语言实现不同的快速排序算法 871 | * 利用实验测试给出不同快速排序算法的性能以理解其优缺点 872 | 873 | ### 实验问题 874 | 875 | 快速排序是算法导论中的经典算法。在本实验中,给定一个长为n的整数数组,要求将数组升序排序。 876 | 877 | ### 实验步骤 878 | 879 | #### 按照算法导论中给出的伪代码实现快速排序 880 | 881 | 根据伪代码实现的快排如下,见文件[qsort.hpp](lab04/qsort.hpp) 882 | 883 | ```c++ 884 | void qsort01(vector& A, int l, int r) { 885 | if (l >= r) return; 886 | int i = rand_int(l, r); 887 | swap(A[r], A[i]); 888 | i = l - 1; 889 | for (int j = l; j < r; ++j) { 890 | if (A[j] <= A[r]) swap(A[++i], A[j]); 891 | } 892 | swap(A[++i], A[r]); 893 | qsort01(A, l, i - 1); 894 | qsort01(A, i + 1, r); 895 | } 896 | ``` 897 | 898 | #### 使用三路划分进行改进 899 | 900 | 上面实现比较明显的弊端就是,虽然采用了随机的划分点,但是对于重复元素多的情况,仍然可能导致每次的划分很不均匀,进而导致复杂度退化到$O(n^2)$的情况 901 | 902 | 对此可以采用三路划分进行改进,每次不是将数据划分为小于和大于等于两个部分,而是划分为小于,等于,大于三个部分,对于重复元素多的情况复杂度甚至会降低,提升到$O(n)$ 903 | 904 | 算法实现如下,见文件[qsort.hpp](lab04/qsort.hpp) 905 | 906 | ```c++ 907 | /** 908 | * use three way partition 909 | * T(n) = 2T(n/2) + n 910 | */ 911 | void qsort02(vector& A, int l, int r) { 912 | if (l >= r) return; 913 | int i = rand_int(l, r); 914 | int x = A[i], lo = l, hi = r; 915 | i = l; 916 | while (i <= hi) { 917 | if (A[i] == x) ++i; 918 | else if (A[i] < x) swap(A[i++], A[lo++]); 919 | else swap(A[i], A[hi--]); 920 | } 921 | // ----[x]xx[x]++++ 922 | // lo hi 923 | qsort02(A, l, lo - 1); 924 | qsort02(A, hi + 1, r); 925 | } 926 | ``` 927 | 928 | #### 测试算法在不同输入下的表现 929 | 930 | 测试了N为10K,100K,1000K下的运行时间数据,可以使用`python draw.py`进行绘图(这里N为1000k的时候第一种快排实现运行过慢,没有包含它),`std::sort`为C++的标准库的sort 931 | 932 | * 绘图如下 933 | * `N=10k` 934 | 935 | ![10k](lab04/images/10k.png) 936 | 937 | * `N=100k` 938 | 939 | ![100k](lab04/images/100k.png) 940 | 941 | * `N=1000k` 942 | 943 | ![1000k](lab04/images/1000k.png) 944 | 945 | ### 结果分析 946 | 947 | * 可以看出当元素重复率逐渐增高时,第一种快排实现运行时间上升非常快(是由于在partition时,分得不均匀,一侧可能只有一个或几个元素,时间复杂度降为O(n^2)) 948 | * 而系统的快排实现中规中矩,运行时间比较稳定,因为它并不是单纯的快排实现,而是几种排序方法的混合体,叫做introsort 949 | * 它开始于快排 950 | * 如果递归层数过深会改用heapsort 951 | * 当数据量小于某个阈值改为插入排序 952 | * 采用三数取中划分(Median-of-3 partition) 953 | * 采用三路划分优化的快排对于重复元素的优化特别好,重复率越高,复杂度越趋于`O(n)` 954 | 955 | ## 实验五: 计算k位数的随机算法 956 | 957 | ### 实验目的 958 | 959 | * 掌握分治算法和随机算法的设计思想与方法 960 | * 熟练使用高级编程语言实现分治算法和随机算法 961 | * 通过对比不同参数,理解算法具体原理,理解分治算法和随机算法。 962 | 963 | ### 实验问题 964 | 965 | 输入:乱序实数数组$A=\{x_1,x_2,...,x_n\}$ 966 | 967 | 输出:$A$的第$k$小元素(详情请见课件分治算法、随机算法) 968 | 969 | ### 实验步骤 970 | 971 | #### 实现基于分治方法的k位数算法 972 | 973 | * 算法思想 974 | 975 | ![BFPRT](lab05/images/BFPRT.png) 976 | 977 | ​ 把数据以5个一组,每次选取它们的中位数的中位数作为pivot值进行划分 978 | 979 | * 算法复杂度为$O(n)$,证明如下 980 | 981 | * 假设$T(n)=tn$ 982 | $$ 983 | \begin{align*} 984 | T(n) =tn&\le tn/5 + 7tn/10 + an \\ 985 | &= tn - tn/10 + an 986 | \end{align*} 987 | \Rightarrow t \le 10a 988 | $$ 989 | 990 | * 所以只需要令$t \le 10a$即可,所以算法复杂度为$O(n)$ 991 | 992 | * 算法实现 993 | 994 | ```c++ 995 | int pick(vector &L, int l, int r, int k) { 996 | if (l == r) return L[l]; 997 | 998 | // get median of medians 999 | for (int i = l; i <= r; i += 5) { 1000 | int j = min(r, i + 5); 1001 | for (int ii = i + 1; ii <= j; ++ii) { 1002 | for (; ii > i && L[ii - 1] > L[ii]; --ii) swap(L[ii], L[ii - 1]); 1003 | } 1004 | swap(L[l + (i - l) / 5], L[(i + j) / 2]); 1005 | } 1006 | int nr = l + (r - l) / 5; 1007 | int median = pick(L, l, nr, (nr + l) / 2); 1008 | 1009 | // three way partition with the approximate median 1010 | // ---[=]=[=]+++ 1011 | // low high 1012 | int i = l, low = l, high = r; 1013 | while (i <= high) { 1014 | if (L[i] == median) 1015 | ++i; 1016 | else if (L[i] < median) 1017 | swap(L[i++], L[low++]); 1018 | else 1019 | swap(L[i], L[high--]); 1020 | } 1021 | 1022 | if (k < low) { 1023 | return pick(L, l, low - 1, k); 1024 | } else if (k <= high) { 1025 | return L[k]; 1026 | } else { 1027 | return pick(L, high + 1, r, k); 1028 | } 1029 | } 1030 | ``` 1031 | 1032 | #### 实现基于随机方法的k位数算法 1033 | 1034 | * 算法原理 1035 | 1036 | ![lazyselect](lab05/images/lazyselect.png) 1037 | 1038 | * 算法实现 1039 | 1040 | ```c++ 1041 | /** 1042 | * n = A.size() 1043 | * k in [0..n-1] 1044 | */ 1045 | int lazyselect(const vector &A, int k) { 1046 | int n = A.size(), m = pow(n, 3./4); // size of A, R 1047 | int x = k*pow(n, -1./4), l = max(int(x-sqrt(n)), 0), h = min(int(x+sqrt(n)), m-1); 1048 | int loops = 0; 1049 | while (1) { 1050 | ++loops; 1051 | // cout << "loop: " << ++loops << endl; 1052 | vector R = sample_k(A, m); 1053 | sort(R.begin(), R.end()); 1054 | int L = R[l], H = R[h]; 1055 | int cnt = 0; // count number of elements that are smaller than L in A 1056 | vector P; 1057 | for (int i = 0; i < n; ++i) { 1058 | if (A[i] < L) ++cnt; 1059 | else if (A[i] <= H) P.push_back(A[i]); 1060 | } 1061 | int sz = P.size(); 1062 | if (k >= cnt && k < cnt + sz && sz <= 4*m+1) { 1063 | sort(P.begin(), P.end()); 1064 | return P[k-cnt]; 1065 | } 1066 | } 1067 | } 1068 | ``` 1069 | 1070 | #### 对比两种k位数算法 1071 | 1072 | 采用不同大小的随机序列进行测试,每个序列运行1000次取运行时间的平均值,结果如下 1073 | 1074 | ```txt 1075 | (N=1000) lazyselect: 0.000148354 1076 | (N=1000) BFPRT : 0.000172629 1077 | (N=2000) lazyselect: 0.000245446 1078 | (N=2000) BFPRT : 0.000349101 1079 | (N=5000) lazyselect: 0.000543804 1080 | (N=5000) BFPRT : 0.000897497 1081 | (N=10000) lazyselect: 0.000987361 1082 | (N=10000) BFPRT : 0.00176972 1083 | (N=20000) lazyselect: 0.00178929 1084 | (N=20000) BFPRT : 0.00353356 1085 | (N=50000) lazyselect: 0.0039252 1086 | (N=50000) BFPRT : 0.009168 1087 | (N=100000) lazyselect: 0.0070601 1088 | (N=100000) BFPRT : 0.018703 1089 | ``` 1090 | 1091 | 可以看出二者运行时间均随N的增大而线性增加,BFPRT略慢于lazyselect,主要是因为BFPRT的常数项比较大,而lazyselect有可能一轮就找到正确答案。 1092 | 1093 | #### 随机算法参数分析 1094 | 1095 | TODO 暂未实现 -------------------------------------------------------------------------------- /lab/lab01/BruteForceCH.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_BruteForceCH_HPP 2 | #define INCLUDED_BruteForceCH_HPP 3 | 4 | #include 5 | #include 6 | #include "ConvexHull.hpp" 7 | using namespace std; 8 | 9 | class BruteForceCH: public ConvexHull { 10 | public: 11 | BruteForceCH() {} 12 | BruteForceCH(const vector> &points): ConvexHull(points) {} 13 | vector> work(); 14 | ~BruteForceCH() { 15 | // cout << "BruteForceCH destroyed\n"; 16 | } 17 | }; 18 | 19 | /** 20 | * time complexity: O(n^4+nlog(n)) 21 | */ 22 | vector> BruteForceCH::work() { 23 | int n = P.size(); 24 | if (n == 0) return vector>(); 25 | for (int a = 0; a < n; ++a) { 26 | if (P[a].x < 0) continue; // Point::x < 0 -> point deleted 27 | for (int b = 0; b < n; ++b) { 28 | if (P[a].x < 0) break; // important 29 | if (b == a || P[b].x < 0) continue; 30 | for (int c = 0; c < n; ++c) { 31 | if (P[b].x < 0 || P[a].x < 0) break; // important 32 | if (c == a || c == b || P[c].x < 0) continue; 33 | // check if abc on same line, if so, delete the middle point 34 | if (P[a].cross(P[b], P[c]) == 0) { 35 | int i = a, j = b, k = c; 36 | if (P[j] < P[i]) swap(i, j); 37 | if (P[j] < P[k]) P[j].x = -1; 38 | else if (P[i] < P[k]) P[k].x = -1; 39 | else P[i].x = -1; 40 | continue; 41 | } 42 | for (int d = 0; d < n; ++d) { 43 | if (d == a || d == b || d == c || P[d].x < 0) continue; 44 | if (P[a].cross(P[b], P[c])*P[a].cross(P[b], P[d]) >= 0 45 | && P[a].cross(P[c], P[b])*P[a].cross(P[c], P[d]) >= 0 46 | && P[b].cross(P[c], P[a])*P[b].cross(P[c], P[d]) >= 0 47 | ) { 48 | P[d].x = -1; // delete 49 | } 50 | } 51 | } 52 | } 53 | } 54 | // A, B, left most & right most 55 | int m = 1, i = 0; 56 | while (P[i].x < 0) ++i; 57 | int a = i, b = i; 58 | for (++i; i < n; ++i) { 59 | if (P[i].x < 0) continue; 60 | ++m; 61 | if (P[i] < P[a]) a = i; 62 | if (P[b] < P[i]) b = i; 63 | } 64 | vector> CH(m), S_U(m); 65 | CH[0] = P[a]; // A 66 | int il = 1, iu = 0; 67 | // S_L, S_U 68 | for (int i = 0; i < n; ++i) { 69 | if (P[i].x < 0 || i == a || i == b) continue; 70 | if (P[a].cross(P[b], P[i]) < 0) { // < 0, S_L 71 | CH[il++] = P[i]; 72 | } else { // > 0, S_U 73 | S_U[iu++] = P[i]; 74 | } 75 | } 76 | // A, S_L, B, reverse(S_U) 77 | sort(CH.begin() + 1, CH.begin() + il); // S_L 78 | sort(S_U.begin(), S_U.begin() + iu); 79 | CH[il] = P[b]; // B 80 | for (int i = 0; i < iu; ++i) CH[il+1+i] = S_U[iu-1-i]; // reverse(S_U) 81 | return CH; 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /lab/lab01/ConvexHull.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_ConvexHull_HPP 2 | #define INCLUDED_ConvexHull_HPP 3 | 4 | #include "Point.hpp" 5 | using namespace std; 6 | 7 | class ConvexHull { 8 | protected: 9 | vector> P; 10 | 11 | public: 12 | ConvexHull() {} 13 | ConvexHull(const vector> &points): P(points) {} 14 | virtual vector> work() = 0; 15 | void upadte(const vector> &points) { P = points; } 16 | virtual ~ConvexHull() {}; 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /lab/lab01/DivAndConCH.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_DivAndConCH_HPP 2 | #define INCLUDED_DivAndConCH_HPP 3 | 4 | // #include 5 | #include 6 | #include 7 | #include 8 | #include "ConvexHull.hpp" 9 | using namespace std; 10 | 11 | class DivAndConCH: public ConvexHull { 12 | private: 13 | vector> _div_con(int l, int r); 14 | public: 15 | DivAndConCH() {} 16 | DivAndConCH(const vector> &points): ConvexHull(points) {} 17 | vector> work(); 18 | ~DivAndConCH() { 19 | // cout << "DivAndConCH destroyed\n"; 20 | } 21 | }; 22 | 23 | /** 24 | * time complexity: O(nlog(n)) 25 | */ 26 | vector> DivAndConCH::work() { 27 | int n = P.size(); 28 | if (n == 0) return vector>(); 29 | sort(P.begin(), P.end()); 30 | return _div_con(0, n); 31 | } 32 | 33 | vector> DivAndConCH::_div_con(int l, int r) { 34 | int m = r - l; 35 | if (m < 3) return vector>(P.begin()+l, P.begin()+r); 36 | vector> lCH = _div_con(l, l + m/2), rCH = _div_con(l + m/2, r); 37 | int lsz = lCH.size(), rsz = rCH.size(); 38 | // merge 39 | int a = 0, b = 0; 40 | for (int i = 0; i < lsz; ++i) { 41 | if (lCH[a] < lCH[i]) a = i; 42 | } 43 | for (int i = 0; i < rsz; ++i) { 44 | if (rCH[i] < rCH[b]) b = i; 45 | } 46 | int llb = a, lrb = a, rlb = b, rrb = b; 47 | // 下公切线 48 | while (true) { 49 | bool changed = false; 50 | for (int nlrb = (lrb-1+lsz)%lsz, cs = rCH[rlb].cross(lCH[lrb], lCH[nlrb]); 51 | cs > 0 || (cs == 0 && rCH[rlb].dist2(lCH[lrb]) < rCH[rlb].dist2(lCH[nlrb])); 52 | nlrb = (lrb-1+lsz)%lsz, cs = rCH[rlb].cross(lCH[lrb], lCH[nlrb])) { 53 | lrb = nlrb; 54 | changed = true; 55 | } 56 | for (int nrlb = (rlb+1)%rsz, cs = lCH[lrb].cross(rCH[rlb], rCH[nrlb]); 57 | cs < 0 || (cs == 0 && lCH[lrb].dist2(rCH[rlb]) < lCH[lrb].dist2(rCH[nrlb])); 58 | nrlb = (rlb+1)%rsz, cs = lCH[lrb].cross(rCH[rlb], rCH[nrlb])) { 59 | rlb = nrlb; 60 | changed = true; 61 | } 62 | if (!changed) break; 63 | } 64 | // 上公切线 65 | while (true) { 66 | bool changed = false; 67 | for (int nllb = (llb+1)%lsz, cs = rCH[rrb].cross(lCH[llb], lCH[nllb]); 68 | cs < 0 || (cs == 0 && rCH[rrb].dist2(lCH[llb]) < rCH[rrb].dist2(lCH[nllb])); 69 | nllb = (llb+1)%lsz, cs = rCH[rrb].cross(lCH[llb], lCH[nllb])) { 70 | llb = nllb; 71 | changed = true; 72 | } 73 | for (int nrrb = (rrb-1+rsz)%rsz, cs = lCH[llb].cross(rCH[rrb], rCH[nrrb]); 74 | cs > 0 || (cs == 0 && lCH[llb].dist2(rCH[rrb]) < lCH[llb].dist2(rCH[nrrb])); 75 | nrrb = (rrb-1+rsz)%rsz, cs = lCH[llb].cross(rCH[rrb], rCH[nrrb])) { 76 | rrb = nrrb; 77 | changed = true; 78 | } 79 | if (!changed) break; 80 | } 81 | vector> CH; 82 | CH.push_back(lCH[llb]); 83 | while (llb != lrb) { 84 | llb = (llb+1)%lsz; 85 | CH.push_back(lCH[llb]); 86 | } 87 | CH.push_back(rCH[rlb]); 88 | while (rlb != rrb) { 89 | rlb = (rlb+1)%rsz; 90 | CH.push_back(rCH[rlb]); 91 | } 92 | return CH; 93 | } 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /lab/lab01/DivAndConCH2.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_DivAndConCH2_HPP 2 | #define INCLUDED_DivAndConCH2_HPP 3 | 4 | // #include 5 | #include 6 | #include 7 | #include 8 | #include "ConvexHull.hpp" 9 | using namespace std; 10 | 11 | class DivAndConCH2: public ConvexHull { 12 | private: 13 | vector> _div_con(int l, int r); 14 | public: 15 | DivAndConCH2() {} 16 | DivAndConCH2(const vector> &points): ConvexHull(points) {} 17 | vector> work(); 18 | ~DivAndConCH2() { 19 | // cout << "DivAndConCH2 destroyed\n"; 20 | } 21 | }; 22 | 23 | /** 24 | * time complexity: O(nlog(n)) 25 | */ 26 | vector> DivAndConCH2::work() { 27 | int n = P.size(); 28 | if (n == 0) return vector>(); 29 | sort(P.begin(), P.end()); 30 | return _div_con(0, n); 31 | } 32 | 33 | vector> DivAndConCH2::_div_con(int l, int r) { 34 | int m = r - l; 35 | if (m < 3) return vector>(P.begin()+l, P.begin()+r); 36 | vector> lCH = _div_con(l, l + m/2), rCH = _div_con(l + m/2, r); 37 | int lsz = lCH.size(), rsz = rCH.size(); 38 | // merge 39 | vector> P2; 40 | P2.push_back(lCH[0]); 41 | auto cmp = [&](const auto& a, const auto& b) { 42 | int c = P2[0].cross(a, b); 43 | return c > 0 || (c == 0 && P2[0].dist2(a) < P2[0].dist2(b)); 44 | }; 45 | // 寻找右边极角最大,最小的点的下标,对应rh, rl 46 | int rl = 0, rh = 0; 47 | for (int i = 1; i < rsz; ++i) { 48 | if (cmp(rCH[rh], rCH[i])) rh = i; 49 | else if (cmp(rCH[i], rCH[rl])) rl = i; 50 | } 51 | // 将三个序列的元素归并到P2,复杂度O(n) 52 | int i = 1, j = rl, k = (rl - 1 + rsz) % rsz; 53 | while (i != lsz || j != rh || k != (rh-1+rsz)%rsz) { 54 | int flag = 0; 55 | if (i == lsz || (j != rh && cmp(rCH[j], lCH[i]))) flag = 1; 56 | if (flag == 1) { 57 | if (j == rh || (k != (rh-1+rsz)%rsz && cmp(rCH[k], rCH[j]))) flag = 2; 58 | } else if ((k != (rh-1+rsz)%rsz && cmp(rCH[k], lCH[i]))) { 59 | flag = 2; 60 | } 61 | if (flag == 0) { 62 | P2.push_back(lCH[i++]); 63 | } else if (flag == 1) { 64 | P2.push_back(rCH[j++]); 65 | j %= rsz; 66 | } else { 67 | P2.push_back(rCH[k--]); 68 | k = (k+rsz) % rsz; 69 | } 70 | } 71 | // P2中的点已经按照极角排序(逆时针排序),极点为P2[0] 72 | // 下面复用GrahamScanCH代码,已经有序,复杂度为O(n) 73 | int n = P2.size(); 74 | P2.push_back(P2[0]); 75 | vector> CH; 76 | m = 0; 77 | for (int i = 0; i <= n; ++i) { 78 | while (m >= 2 && CH[m-2].cross(CH[m-1], P2[i]) <= 0) { 79 | if (i == n && m == 2) break; // 防止所有点都共线,删除了一端端点 80 | CH.pop_back(), --m; 81 | } 82 | CH.push_back(P2[i]); 83 | ++m; 84 | } 85 | CH.pop_back(); 86 | return CH; 87 | } 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /lab/lab01/GrahamScanCH.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_GrahamScanCH_HPP 2 | #define INCLUDED_GrahamScanCH_HPP 3 | 4 | // #include 5 | #include 6 | #include 7 | #include 8 | #include "ConvexHull.hpp" 9 | using namespace std; 10 | 11 | class GrahamScanCH: public ConvexHull { 12 | public: 13 | GrahamScanCH() {} 14 | GrahamScanCH(const vector> &points): ConvexHull(points) {} 15 | vector> work(); 16 | ~GrahamScanCH() { 17 | // cout << "GrahamScanCH destroyed\n"; 18 | } 19 | }; 20 | 21 | /** 22 | * time complexity: O(nlog(n)) 23 | */ 24 | vector> GrahamScanCH::work() { 25 | int n = P.size(); 26 | if (n == 0) return vector>(); 27 | swap(P[0], *min_element(P.begin(), P.end())); // 极点放到P[0]处 28 | if (n <= 2) return P; 29 | // 按照极角排序,极点为P[0] 30 | sort(P.begin()+1, P.end(), [&](const auto& a, const auto& b) { 31 | int c = P[0].cross(a, b); 32 | return c > 0 || (c == 0 && P[0].dist2(a) < P[0].dist2(b)); 33 | }); 34 | // GrahamScan 35 | P.push_back(P[0]); // 处理最后一个点更简单 36 | vector> CH; 37 | int m = 0; 38 | for (int i = 0; i <= n; ++i) { 39 | while (m >= 2 && CH[m-2].cross(CH[m-1], P[i]) <= 0) { 40 | if (i == n && m == 2) break; // 防止所有点都共线,删除了一端端点 41 | CH.pop_back(), --m; 42 | } 43 | CH.push_back(P[i]); 44 | ++m; 45 | } 46 | CH.pop_back(); 47 | return CH; 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /lab/lab01/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | CXXFLAGS = -g -Wall -std=c++14 3 | SOURCES = main.cpp 4 | OBJECTS = $(SOURCES:.cpp=.o) 5 | BINARY = main 6 | 7 | all: $(BINARY) 8 | 9 | $(BINARY): $(OBJECTS) 10 | $(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ 11 | 12 | main.o: Point.hpp PointsSampler.hpp ConvexHull.hpp BruteForceCH.hpp GrahamScanCH.hpp DivAndConCH.hpp DivAndConCH2.hpp 13 | 14 | clean: 15 | $(RM) $(BINARY) $(OBJECTS) 16 | -------------------------------------------------------------------------------- /lab/lab01/Point.hpp: -------------------------------------------------------------------------------- 1 | #ifndef Included_Point_HPP 2 | #define Included_Point_HPP 3 | 4 | #include 5 | 6 | using namespace std; 7 | 8 | template 9 | struct Point { 10 | typedef Point P; 11 | T x, y; 12 | Point(T x=0, T y=0) : x(x), y(y) {} 13 | bool operator<(P p) const { return tie(x,y) < tie(p.x,p.y); } 14 | bool operator==(P p) const { return tie(x,y)==tie(p.x,p.y); } 15 | P operator-(P p) const { return P(x-p.x, y-p.y); } 16 | T cross(P p) const { return x*p.y - y*p.x; } 17 | T cross(P a, P b) const { return (a-*this).cross(b-*this); } 18 | T dist2() const { return x*x + y*y; } 19 | T dist2(P o) const { return (o-*this).dist2(); } 20 | double dist() const { return sqrt((double)dist2()); } 21 | friend ostream& operator<<(ostream& os, P p) { return os << "(" << p.x << "," << p.y << ")"; } 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /lab/lab01/PointsSampler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_PointsSampler_HPP 2 | #define INCLUDED_PointsSampler_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Point.hpp" 8 | using namespace std; 9 | 10 | random_device rd; 11 | mt19937 g(rd()); 12 | // default_random_engine g; 13 | 14 | /** 15 | * get uniformly distributed random int from [lo...hi] 16 | */ 17 | int rand_int(int lo, int hi) { 18 | uniform_int_distribution distribution(lo, hi); 19 | return distribution(g); 20 | } 21 | 22 | /** 23 | * get uniformly distributed real number from [lo, hi) 24 | */ 25 | double rand_real(double lo, double hi) { 26 | uniform_real_distribution distribution(lo, hi); 27 | return distribution(g); 28 | } 29 | 30 | class PointsSampler 31 | { 32 | public: 33 | const static int R = 101, C = 101, N = R * C; 34 | /** 35 | * Reservoir Sampling, time complexity O(k(1+log(n/k))) 36 | */ 37 | static vector> sample_k(int k) { 38 | assert(k >= 0 && k <= N); 39 | vector> res; 40 | if (k == 0) return res; 41 | res.reserve(k); 42 | for (int i = 0; i < k; ++i) res.emplace_back(i/C, i%C); 43 | double W = exp(log(rand_real(0, 1))/k); 44 | for (int i = k; i < N;) { 45 | i += floor(log(rand_real(0, 1))/log(1-W)) + 1; 46 | if (i < N) { 47 | int idx = rand_int(0, k-1); 48 | res[idx].x = i/C; 49 | res[idx].y = i%C; 50 | W *= exp(log(rand_real(0, 1))/k); 51 | } 52 | } 53 | return res; 54 | } 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /lab/lab01/README.md: -------------------------------------------------------------------------------- 1 | # 实验一: 分治算法 2 | 3 | * 实现了水池抽样用来随机生成大小为k的样本点 4 | * 实现了三种凸包算法: 基于枚举方法(BruteForce), Graham-Scan算法, 分治算法(Divide and Conquer) -- (两种归并方法) 5 | * 记录不同算法在不同规模数据集上求解凸包的时间,并绘制算法性能曲线 6 | 7 | ## 文件说明 8 | 9 | * `Point.hpp` 中定义了点类,包含了点的x,y坐标以及坐标间的一些运算 10 | * `PointSampler.hpp` 中的`vector> PointSampler::sample_k(int k)`用于从正方形`(0,0)-(0,100)-(100,100)-(100,0)`内的点中随机取k个点。采用了水池抽样算法,比较高效,复杂度`O(k(1+log(n/k)))` 11 | * `BruteForceCH.hpp` `GrahamScanCH.hpp` `DivAndConCH.hpp` 分别对应的三种凸包算法的实现,他们共同继承自`ConvexHull.hpp` 12 | * `main.cpp` 负责在生成的不同大小数据集上调用凸包函数,并记录凸包求解时间 13 | * `Makefile` 使用`make`进行编译,`make clean`清除编译的文件 14 | 15 | ## 程序编译与运行 16 | 17 | * 使用`make`进行编译 18 | * `./main > data.txt`运行,针对三个凸包算法,在`0, 10, 20, ... 10000`个点上求凸包,记录每次求解时间 19 | * 输出格式每个数据集合一行: `数据集大小(样本点个数k) BruteForceCH时间 GrahamScanCH时间 DivAndConCH时间` 20 | * 输出重定向到`data.txt`是为了下一步使用python绘图时读取这个数据 21 | 22 | ### 绘图 23 | 24 | * 需要安装`matplotlib`和`numpy` 25 | * 运行`python draw.py [datafile]`即会读取上面生成的`data.txt`进行绘图 26 | ![benchmark-old](images/benchmark-old.png) 27 | * 可以看出BruteForceCH的运行时间波动比较大,且运行时间随数据集增大增长更快,另外两种算法的运行时间随数据集增大增长比较平稳。也对应了他们各自的复杂度: BruteForceCH是`O(n^4)`, 另外两个是`nlog(n)`. 28 | * 在修复BruteForceCH中的bug之后([commit: fix bug in BruteForceCH](https://github.com/sky-bro/HIT-Algo/commit/c8d9082a97aba99b796b51aed4c9f525d0f53115)),因为如果外层循环的点被标记了删除,那么内层循环会break到上一层,所以实际的复杂度很难达到`n^4`,所以新的时间-样本大小的绘图如下 29 | ![benchmark](images/benchmark.png) 30 | 31 | ## Refs 32 | 33 | * [Convex Hull 演算法笔记](http://web.ntnu.edu.tw/~algo/ConvexHull.html) 包含各种求解凸包问题的算法 34 | * 我实现的分治算法[DivAndConCH.hpp](./DivAndConCH.hpp)是参考的这里的[Convex Hull: Divide and Conquer](http://web.ntnu.edu.tw/~algo/ConvexHull.html#6) 和课件中的比较一致,这里归并采用的是找上下切线,~~课件里面的归并步骤我没看懂。~~网上好多用quick hull也是属于分治,不过和课件的分治区别较大 35 | * 也已实现课件里的分治,见[DivAndConCH2.hpp](./DivAndConCH2.hpp) 36 | * [Reservoir Sampling: An optimal algorithm](https://en.wikipedia.org/wiki/Reservoir_sampling#An_optimal_algorithm) 水池抽样算法参考 37 | -------------------------------------------------------------------------------- /lab/lab01/data-old.txt: -------------------------------------------------------------------------------- 1 | 0 0.000001 0.000001 0.000000 2 | 10 0.000030 0.000008 0.000049 3 | 20 0.000195 0.000011 0.000023 4 | 30 0.000245 0.000012 0.000033 5 | 40 0.000722 0.000019 0.000058 6 | 50 0.000852 0.000022 0.000064 7 | 60 0.000502 0.000025 0.000074 8 | 70 0.000895 0.000032 0.000138 9 | 80 0.002798 0.000035 0.000107 10 | 90 0.002303 0.000039 0.000125 11 | 100 0.000689 0.000046 0.000141 12 | 110 0.002485 0.000048 0.000146 13 | 120 0.001330 0.000117 0.000150 14 | 130 0.002530 0.000077 0.000168 15 | 140 0.004696 0.000061 0.000182 16 | 150 0.007181 0.000070 0.000202 17 | 160 0.004808 0.000079 0.000231 18 | 170 0.007967 0.000091 0.000244 19 | 180 0.007512 0.000084 0.000270 20 | 190 0.004209 0.000092 0.000288 21 | 200 0.004755 0.000095 0.000294 22 | 210 0.003295 0.000098 0.000300 23 | 220 0.003944 0.000107 0.000308 24 | 230 0.005750 0.000120 0.000329 25 | 240 0.009144 0.000115 0.000328 26 | 250 0.003977 0.000131 0.000338 27 | 260 0.006452 0.000128 0.000391 28 | 270 0.003154 0.000129 0.000369 29 | 280 0.005700 0.000136 0.000390 30 | 290 0.002905 0.000141 0.000406 31 | 300 0.007465 0.000146 0.000426 32 | 310 0.012819 0.000153 0.000443 33 | 320 0.002842 0.000170 0.000467 34 | 330 0.010067 0.000168 0.000514 35 | 340 0.006707 0.000173 0.000553 36 | 350 0.006962 0.000172 0.000528 37 | 360 0.006959 0.000176 0.000539 38 | 370 0.008219 0.000192 0.000572 39 | 380 0.008042 0.000239 0.000592 40 | 390 0.018291 0.000202 0.000624 41 | 400 0.007990 0.000202 0.000632 42 | 410 0.006627 0.000219 0.000668 43 | 420 0.009924 0.000217 0.000634 44 | 430 0.008177 0.000238 0.000637 45 | 440 0.003532 0.000225 0.000658 46 | 450 0.004948 0.000228 0.000662 47 | 460 0.006348 0.000238 0.000723 48 | 470 0.008648 0.000237 0.000749 49 | 480 0.008839 0.000259 0.000709 50 | 490 0.014313 0.000251 0.000706 51 | 500 0.006932 0.000251 0.000759 52 | 510 0.010265 0.000269 0.000738 53 | 520 0.011733 0.000265 0.000738 54 | 530 0.015016 0.000273 0.000762 55 | 540 0.009553 0.000278 0.000797 56 | 550 0.004628 0.000293 0.000807 57 | 560 0.015397 0.000294 0.000828 58 | 570 0.008762 0.000300 0.000835 59 | 580 0.009478 0.000301 0.000860 60 | 590 0.005627 0.000305 0.000878 61 | 600 0.008610 0.000313 0.000903 62 | 610 0.006087 0.000320 0.000945 63 | 620 0.011628 0.000329 0.000965 64 | 630 0.005452 0.000328 0.000984 65 | 640 0.009323 0.000336 0.000977 66 | 650 0.009099 0.000352 0.000995 67 | 660 0.011318 0.000350 0.001035 68 | 670 0.012209 0.000352 0.001050 69 | 680 0.006893 0.000357 0.001058 70 | 690 0.009913 0.000363 0.001079 71 | 700 0.008916 0.000359 0.001121 72 | 710 0.007187 0.000397 0.001175 73 | 720 0.009033 0.000379 0.001140 74 | 730 0.005541 0.000391 0.001160 75 | 740 0.009293 0.000403 0.001208 76 | 750 0.008551 0.000418 0.001229 77 | 760 0.007089 0.000404 0.001253 78 | 770 0.005994 0.000421 0.001236 79 | 780 0.014286 0.000420 0.001246 80 | 790 0.010154 0.000421 0.001275 81 | 800 0.006033 0.000442 0.001285 82 | 810 0.012020 0.000445 0.001315 83 | 820 0.006752 0.000448 0.001271 84 | 830 0.012496 0.000475 0.001319 85 | 840 0.004869 0.000451 0.001316 86 | 850 0.010423 0.000461 0.001336 87 | 860 0.010871 0.000470 0.001333 88 | 870 0.013529 0.000490 0.001348 89 | 880 0.005794 0.000477 0.001369 90 | 890 0.014421 0.000481 0.001379 91 | 900 0.016782 0.000481 0.001406 92 | 910 0.014568 0.000504 0.001402 93 | 920 0.005194 0.000504 0.001420 94 | 930 0.008224 0.000510 0.001436 95 | 940 0.007942 0.000523 0.001423 96 | 950 0.007570 0.000532 0.001451 97 | 960 0.015462 0.000536 0.001473 98 | 970 0.006917 0.000541 0.001464 99 | 980 0.014459 0.000549 0.001462 100 | 990 0.013958 0.000554 0.001471 101 | 1000 0.009335 0.000572 0.001543 102 | 1010 0.014905 0.000569 0.001480 103 | 1020 0.008324 0.000579 0.001511 104 | 1030 0.014407 0.000557 0.001575 105 | 1040 0.016894 0.000578 0.001524 106 | 1050 0.020125 0.000577 0.001581 107 | 1060 0.019477 0.000584 0.001587 108 | 1070 0.022103 0.000599 0.001630 109 | 1080 0.017438 0.000589 0.001617 110 | 1090 0.007618 0.000610 0.001648 111 | 1100 0.030542 0.000616 0.001693 112 | 1110 0.010906 0.000622 0.001702 113 | 1120 0.007816 0.000637 0.001740 114 | 1130 0.014757 0.000648 0.001753 115 | 1140 0.011344 0.000642 0.001737 116 | 1150 0.013401 0.000649 0.001787 117 | 1160 0.009857 0.000680 0.001808 118 | 1170 0.022579 0.000675 0.001821 119 | 1180 0.039952 0.000674 0.001829 120 | 1190 0.012872 0.000675 0.001889 121 | 1200 0.009008 0.000685 0.001902 122 | 1210 0.004044 0.000681 0.001934 123 | 1220 0.021354 0.000687 0.001921 124 | 1230 0.006042 0.000691 0.001931 125 | 1240 0.011774 0.000726 0.001945 126 | 1250 0.014728 0.000713 0.001995 127 | 1260 0.013500 0.000713 0.002031 128 | 1270 0.009616 0.000721 0.002046 129 | 1280 0.016141 0.000767 0.002053 130 | 1290 0.018734 0.000783 0.002089 131 | 1300 0.013155 0.000780 0.002138 132 | 1310 0.010393 0.000724 0.002097 133 | 1320 0.010092 0.000867 0.002409 134 | 1330 0.011225 0.000760 0.002193 135 | 1340 0.018969 0.000770 0.002212 136 | 1350 0.017266 0.000780 0.002271 137 | 1360 0.022404 0.000773 0.002269 138 | 1370 0.014619 0.000801 0.002273 139 | 1380 0.024211 0.000781 0.002276 140 | 1390 0.023982 0.000805 0.002274 141 | 1400 0.017769 0.000824 0.002313 142 | 1410 0.022516 0.000836 0.002308 143 | 1420 0.019410 0.000804 0.002351 144 | 1430 0.023319 0.000856 0.002385 145 | 1440 0.010632 0.000829 0.002433 146 | 1450 0.025830 0.000851 0.002411 147 | 1460 0.015685 0.000837 0.002447 148 | 1470 0.016056 0.000863 0.002426 149 | 1480 0.023598 0.000850 0.002469 150 | 1490 0.012170 0.000865 0.002534 151 | 1500 0.012764 0.001008 0.002708 152 | 1510 0.031797 0.000869 0.002586 153 | 1520 0.021739 0.000885 0.002756 154 | 1530 0.006793 0.000893 0.002775 155 | 1540 0.019534 0.000897 0.002624 156 | 1550 0.016123 0.000906 0.002650 157 | 1560 0.015635 0.001019 0.002656 158 | 1570 0.015970 0.000951 0.002962 159 | 1580 0.029478 0.000929 0.002692 160 | 1590 0.022623 0.000945 0.002723 161 | 1600 0.015817 0.000934 0.002667 162 | 1610 0.027450 0.000943 0.002712 163 | 1620 0.009778 0.000953 0.002693 164 | 1630 0.022528 0.000969 0.002755 165 | 1640 0.011868 0.000960 0.002812 166 | 1650 0.014510 0.001249 0.003036 167 | 1660 0.022244 0.001116 0.003648 168 | 1670 0.032066 0.001019 0.003513 169 | 1680 0.038451 0.001073 0.003373 170 | 1690 0.016710 0.000989 0.002976 171 | 1700 0.033401 0.001009 0.003670 172 | 1710 0.019452 0.000994 0.002804 173 | 1720 0.021906 0.001009 0.002776 174 | 1730 0.013554 0.001031 0.002817 175 | 1740 0.048899 0.001065 0.002825 176 | 1750 0.015451 0.001036 0.002806 177 | 1760 0.053834 0.001055 0.002916 178 | 1770 0.034394 0.001041 0.002857 179 | 1780 0.026944 0.001047 0.002903 180 | 1790 0.015445 0.001107 0.002847 181 | 1800 0.015498 0.001074 0.002930 182 | 1810 0.019739 0.001065 0.002915 183 | 1820 0.021793 0.001072 0.002909 184 | 1830 0.023163 0.001096 0.003024 185 | 1840 0.014820 0.001117 0.002975 186 | 1850 0.038971 0.001116 0.002943 187 | 1860 0.029418 0.001147 0.003040 188 | 1870 0.019704 0.001123 0.003062 189 | 1880 0.012169 0.001168 0.003064 190 | 1890 0.022749 0.001161 0.003015 191 | 1900 0.025855 0.001169 0.003053 192 | 1910 0.028243 0.001184 0.003033 193 | 1920 0.010989 0.001147 0.003139 194 | 1930 0.044556 0.001241 0.003092 195 | 1940 0.022668 0.001169 0.003088 196 | 1950 0.022180 0.001172 0.003171 197 | 1960 0.043968 0.001211 0.003103 198 | 1970 0.007066 0.001225 0.003159 199 | 1980 0.013508 0.001184 0.003167 200 | 1990 0.031242 0.001205 0.003188 201 | 2000 0.049210 0.001256 0.003180 202 | 2010 0.012646 0.001224 0.003150 203 | 2020 0.014725 0.001225 0.003153 204 | 2030 0.025781 0.001246 0.003232 205 | 2040 0.014966 0.001270 0.003244 206 | 2050 0.033621 0.001279 0.003141 207 | 2060 0.033653 0.001297 0.003181 208 | 2070 0.036095 0.001247 0.003247 209 | 2080 0.012004 0.001298 0.003315 210 | 2090 0.017243 0.001298 0.003347 211 | 2100 0.033727 0.001284 0.003309 212 | 2110 0.025308 0.001299 0.003364 213 | 2120 0.015974 0.001298 0.003350 214 | 2130 0.021232 0.001355 0.003380 215 | 2140 0.015034 0.001340 0.003377 216 | 2150 0.022966 0.001384 0.003829 217 | 2160 0.015533 0.001278 0.003475 218 | 2170 0.027211 0.001362 0.003587 219 | 2180 0.020916 0.001361 0.003534 220 | 2190 0.047856 0.001324 0.003609 221 | 2200 0.004289 0.001319 0.003556 222 | 2210 0.025219 0.001340 0.003628 223 | 2220 0.017553 0.001376 0.003554 224 | 2230 0.025827 0.001362 0.003638 225 | 2240 0.023068 0.001419 0.003573 226 | 2250 0.027657 0.001446 0.003672 227 | 2260 0.020959 0.001355 0.003665 228 | 2270 0.052146 0.001411 0.003655 229 | 2280 0.018968 0.001382 0.003780 230 | 2290 0.017463 0.001409 0.003703 231 | 2300 0.006554 0.001454 0.003746 232 | 2310 0.015262 0.001410 0.003765 233 | 2320 0.014342 0.001412 0.003796 234 | 2330 0.029371 0.001444 0.003779 235 | 2340 0.012376 0.001458 0.004019 236 | 2350 0.036013 0.001483 0.003975 237 | 2360 0.040992 0.001444 0.003886 238 | 2370 0.016940 0.001528 0.004106 239 | 2380 0.033686 0.001499 0.003869 240 | 2390 0.075259 0.001483 0.003902 241 | 2400 0.008198 0.001470 0.004008 242 | 2410 0.016128 0.001522 0.003994 243 | 2420 0.008678 0.001482 0.004003 244 | 2430 0.021520 0.001490 0.004182 245 | 2440 0.020816 0.001588 0.004069 246 | 2450 0.012735 0.001654 0.004158 247 | 2460 0.026506 0.001512 0.004104 248 | 2470 0.024240 0.001534 0.004188 249 | 2480 0.023002 0.001569 0.004125 250 | 2490 0.019717 0.001529 0.004157 251 | 2500 0.027194 0.001601 0.004118 252 | 2510 0.037667 0.001540 0.004271 253 | 2520 0.025334 0.001584 0.004297 254 | 2530 0.020587 0.001580 0.004260 255 | 2540 0.044488 0.001606 0.004324 256 | 2550 0.036962 0.001572 0.004313 257 | 2560 0.018639 0.001602 0.004375 258 | 2570 0.050845 0.001627 0.004312 259 | 2580 0.037370 0.001642 0.004323 260 | 2590 0.013068 0.001663 0.004340 261 | 2600 0.028252 0.001619 0.004465 262 | 2610 0.015165 0.001624 0.004520 263 | 2620 0.014016 0.001705 0.004548 264 | 2630 0.020595 0.001655 0.004481 265 | 2640 0.018088 0.001621 0.004562 266 | 2650 0.041770 0.001711 0.004491 267 | 2660 0.015973 0.001685 0.004561 268 | 2670 0.017485 0.001634 0.004554 269 | 2680 0.035818 0.001677 0.004586 270 | 2690 0.041954 0.001749 0.005355 271 | 2700 0.034994 0.001686 0.004700 272 | 2710 0.034466 0.001683 0.004822 273 | 2720 0.059753 0.001707 0.004625 274 | 2730 0.106341 0.001702 0.004693 275 | 2740 0.025097 0.001693 0.004650 276 | 2750 0.024703 0.001738 0.004801 277 | 2760 0.045819 0.001765 0.004776 278 | 2770 0.056418 0.001737 0.004866 279 | 2780 0.022681 0.001795 0.004868 280 | 2790 0.019609 0.001740 0.004825 281 | 2800 0.097374 0.001758 0.004847 282 | 2810 0.045064 0.001862 0.004909 283 | 2820 0.026609 0.001929 0.004859 284 | 2830 0.038540 0.001805 0.004861 285 | 2840 0.012481 0.001800 0.004932 286 | 2850 0.035252 0.001859 0.004939 287 | 2860 0.023523 0.001814 0.004981 288 | 2870 0.040493 0.001818 0.004972 289 | 2880 0.021880 0.001868 0.005166 290 | 2890 0.025477 0.001915 0.005104 291 | 2900 0.073628 0.001832 0.005083 292 | 2910 0.043973 0.001853 0.005088 293 | 2920 0.018372 0.001937 0.005115 294 | 2930 0.087524 0.001841 0.005329 295 | 2940 0.031364 0.001893 0.005269 296 | 2950 0.022073 0.001850 0.005389 297 | 2960 0.030955 0.001893 0.005311 298 | 2970 0.004871 0.001896 0.005345 299 | 2980 0.076140 0.001908 0.005312 300 | 2990 0.013235 0.001915 0.005292 301 | 3000 0.024205 0.001915 0.005406 302 | 3010 0.089418 0.001940 0.005228 303 | 3020 0.056369 0.001951 0.005625 304 | 3030 0.026613 0.001933 0.005364 305 | 3040 0.046016 0.001943 0.005495 306 | 3050 0.105231 0.001975 0.005411 307 | 3060 0.016614 0.001949 0.005447 308 | 3070 0.072510 0.001951 0.005549 309 | 3080 0.043100 0.002014 0.005512 310 | 3090 0.043532 0.001941 0.005499 311 | 3100 0.026109 0.001985 0.005575 312 | 3110 0.012316 0.001956 0.005686 313 | 3120 0.095889 0.001967 0.005596 314 | 3130 0.029202 0.001995 0.005517 315 | 3140 0.025724 0.002079 0.005662 316 | 3150 0.038914 0.002012 0.005737 317 | 3160 0.259861 0.002170 0.005584 318 | 3170 0.032892 0.002043 0.005520 319 | 3180 0.024222 0.002029 0.005514 320 | 3190 0.030780 0.002064 0.005506 321 | 3200 0.016993 0.002025 0.005594 322 | 3210 0.051735 0.002062 0.005634 323 | 3220 0.056149 0.001994 0.005547 324 | 3230 0.029890 0.002112 0.005637 325 | 3240 0.053268 0.002127 0.005613 326 | 3250 0.062224 0.002127 0.005626 327 | 3260 0.046782 0.002084 0.005633 328 | 3270 0.030954 0.002070 0.005615 329 | 3280 0.036253 0.002098 0.005692 330 | 3290 0.021630 0.002224 0.005708 331 | 3300 0.036093 0.002119 0.005738 332 | 3310 0.031998 0.002094 0.005650 333 | 3320 0.037827 0.002112 0.005784 334 | 3330 0.114969 0.002158 0.005670 335 | 3340 0.014981 0.002103 0.005681 336 | 3350 0.036587 0.002143 0.005790 337 | 3360 0.056077 0.002228 0.005659 338 | 3370 0.022896 0.002153 0.005716 339 | 3380 0.279157 0.002245 0.005813 340 | 3390 0.052362 0.002128 0.005828 341 | 3400 0.026913 0.002257 0.005804 342 | 3410 0.052171 0.002177 0.005802 343 | 3420 0.023050 0.002239 0.005814 344 | 3430 0.055129 0.002270 0.005959 345 | 3440 0.030622 0.002268 0.005925 346 | 3450 0.020993 0.002157 0.005852 347 | 3460 0.015421 0.002180 0.005873 348 | 3470 0.043608 0.002253 0.005957 349 | 3480 0.049396 0.002314 0.006118 350 | 3490 0.035996 0.002213 0.005865 351 | 3500 0.047852 0.002277 0.005883 352 | 3510 0.011926 0.002333 0.005889 353 | 3520 0.033020 0.002258 0.005883 354 | 3530 0.046832 0.002298 0.005883 355 | 3540 0.038134 0.002243 0.006059 356 | 3550 0.023031 0.002277 0.005999 357 | 3560 0.027308 0.002339 0.005999 358 | 3570 0.030327 0.002354 0.006079 359 | 3580 0.043662 0.002313 0.006072 360 | 3590 0.050717 0.002351 0.006031 361 | 3600 0.023788 0.002279 0.006215 362 | 3610 0.078292 0.002303 0.006036 363 | 3620 0.035417 0.002314 0.006161 364 | 3630 0.013579 0.002337 0.006162 365 | 3640 0.057196 0.002495 0.006048 366 | 3650 0.040005 0.002373 0.006279 367 | 3660 0.038029 0.002405 0.006109 368 | 3670 0.060746 0.002326 0.006075 369 | 3680 0.023484 0.002390 0.006183 370 | 3690 0.035155 0.002361 0.006130 371 | 3700 0.042578 0.002421 0.006109 372 | 3710 0.086845 0.002405 0.006170 373 | 3720 0.021992 0.002363 0.006226 374 | 3730 0.049858 0.002481 0.006335 375 | 3740 0.032388 0.002399 0.006383 376 | 3750 0.037427 0.002391 0.006240 377 | 3760 0.044731 0.002381 0.006345 378 | 3770 0.033611 0.002411 0.006338 379 | 3780 0.026883 0.002411 0.006296 380 | 3790 0.030012 0.002444 0.006218 381 | 3800 0.054773 0.002433 0.006235 382 | 3810 0.080038 0.002545 0.006312 383 | 3820 0.025176 0.002525 0.006365 384 | 3830 0.024120 0.002494 0.006284 385 | 3840 0.022617 0.002484 0.006469 386 | 3850 0.298345 0.002494 0.006328 387 | 3860 0.043254 0.002505 0.006293 388 | 3870 0.064969 0.002461 0.006336 389 | 3880 0.019397 0.002541 0.006385 390 | 3890 0.030427 0.002520 0.006445 391 | 3900 0.067140 0.002515 0.006396 392 | 3910 0.033585 0.002538 0.006504 393 | 3920 0.060700 0.002548 0.006529 394 | 3930 0.019621 0.002629 0.006456 395 | 3940 0.046563 0.002562 0.006413 396 | 3950 0.003397 0.002589 0.006692 397 | 3960 0.017675 0.002543 0.006523 398 | 3970 0.048124 0.002556 0.006438 399 | 3980 0.042341 0.002610 0.006562 400 | 3990 0.041160 0.002622 0.006424 401 | 4000 0.040863 0.002569 0.006526 402 | 4010 0.033962 0.002580 0.006524 403 | 4020 0.012008 0.002581 0.006632 404 | 4030 0.097037 0.002625 0.006634 405 | 4040 0.049663 0.002770 0.006499 406 | 4050 0.017153 0.002671 0.006598 407 | 4060 0.122935 0.002627 0.006510 408 | 4070 0.021111 0.002614 0.006527 409 | 4080 0.037101 0.002686 0.006600 410 | 4090 0.043589 0.002655 0.006628 411 | 4100 0.097855 0.002675 0.006673 412 | 4110 0.025498 0.002670 0.006636 413 | 4120 0.013074 0.002737 0.006699 414 | 4130 0.031136 0.002760 0.006610 415 | 4140 0.029379 0.002678 0.006660 416 | 4150 0.019013 0.002704 0.006726 417 | 4160 0.023661 0.002664 0.006757 418 | 4170 0.036775 0.002728 0.006733 419 | 4180 0.013690 0.002790 0.006782 420 | 4190 0.041435 0.002759 0.006726 421 | 4200 0.029796 0.002769 0.006815 422 | 4210 0.030246 0.002739 0.006897 423 | 4220 0.026788 0.002842 0.006920 424 | 4230 0.018278 0.002778 0.006826 425 | 4240 0.018511 0.002804 0.006953 426 | 4250 0.046024 0.002759 0.006950 427 | 4260 0.047224 0.002825 0.007204 428 | 4270 0.021956 0.002809 0.007246 429 | 4280 0.042471 0.002790 0.007157 430 | 4290 0.067674 0.002820 0.007247 431 | 4300 0.120161 0.002806 0.007046 432 | 4310 0.419814 0.003163 0.007242 433 | 4320 0.037512 0.002919 0.007002 434 | 4330 0.021670 0.002824 0.007203 435 | 4340 0.365988 0.002953 0.007282 436 | 4350 0.012455 0.002840 0.007111 437 | 4360 0.124021 0.002968 0.007271 438 | 4370 0.146623 0.003001 0.007443 439 | 4380 0.063907 0.002856 0.007461 440 | 4390 0.042478 0.002965 0.007798 441 | 4400 0.296773 0.002904 0.007295 442 | 4410 0.043448 0.002885 0.007540 443 | 4420 0.034120 0.002916 0.007425 444 | 4430 0.028124 0.002999 0.007354 445 | 4440 0.051660 0.002877 0.007371 446 | 4450 0.172541 0.002932 0.007438 447 | 4460 0.050338 0.002952 0.007465 448 | 4470 0.024975 0.002946 0.007363 449 | 4480 0.020974 0.003122 0.007539 450 | 4490 0.016270 0.002998 0.007493 451 | 4500 0.067603 0.002945 0.007674 452 | 4510 0.099058 0.002941 0.007443 453 | 4520 0.039928 0.003035 0.007543 454 | 4530 0.071249 0.002988 0.007604 455 | 4540 0.069573 0.002972 0.007770 456 | 4550 0.060554 0.003011 0.007685 457 | 4560 0.468304 0.002983 0.007733 458 | 4570 0.025417 0.003085 0.007776 459 | 4580 0.031648 0.003028 0.007627 460 | 4590 0.031615 0.003017 0.007963 461 | 4600 0.047565 0.003013 0.007784 462 | 4610 0.076364 0.003038 0.007693 463 | 4620 0.334573 0.003040 0.008028 464 | 4630 0.063350 0.003312 0.008381 465 | 4640 0.481812 0.003073 0.007789 466 | 4650 0.103591 0.003244 0.007858 467 | 4660 0.036953 0.003112 0.007828 468 | 4670 0.019673 0.003134 0.007807 469 | 4680 0.033289 0.003103 0.008065 470 | 4690 0.056522 0.003044 0.007869 471 | 4700 0.062776 0.003073 0.007937 472 | 4710 0.015098 0.003068 0.007961 473 | 4720 0.020820 0.003096 0.008069 474 | 4730 0.095922 0.003154 0.008053 475 | 4740 0.058843 0.003201 0.008168 476 | 4750 0.042204 0.003220 0.008055 477 | 4760 0.021152 0.003151 0.008104 478 | 4770 0.175242 0.003184 0.008159 479 | 4780 0.038885 0.003183 0.008104 480 | 4790 0.358968 0.003138 0.008106 481 | 4800 0.045667 0.003140 0.008227 482 | 4810 0.061138 0.003155 0.008573 483 | 4820 0.036436 0.003210 0.008176 484 | 4830 0.041694 0.003217 0.008251 485 | 4840 0.025189 0.003239 0.008183 486 | 4850 0.335520 0.003372 0.008253 487 | 4860 0.022932 0.003308 0.008253 488 | 4870 0.105415 0.003193 0.008422 489 | 4880 0.080230 0.003507 0.008249 490 | 4890 0.031551 0.003348 0.008569 491 | 4900 0.029142 0.003321 0.008328 492 | 4910 0.024238 0.003284 0.008368 493 | 4920 0.028764 0.003262 0.008445 494 | 4930 0.205973 0.003231 0.008408 495 | 4940 0.028435 0.003343 0.009992 496 | 4950 0.225383 0.003406 0.008527 497 | 4960 0.011763 0.003411 0.008535 498 | 4970 0.043595 0.003308 0.008530 499 | 4980 0.047954 0.003295 0.008553 500 | 4990 0.041430 0.003335 0.008631 501 | 5000 0.034869 0.003306 0.008633 502 | 5010 0.667299 0.003282 0.008551 503 | 5020 0.026047 0.003298 0.009293 504 | 5030 0.058811 0.003309 0.008718 505 | 5040 0.574549 0.003904 0.008828 506 | 5050 0.336987 0.003466 0.008693 507 | 5060 0.037900 0.003448 0.008824 508 | 5070 0.027710 0.003484 0.008709 509 | 5080 0.118315 0.003408 0.008731 510 | 5090 0.118394 0.003384 0.008856 511 | 5100 0.036194 0.003405 0.008737 512 | 5110 0.043337 0.003355 0.009054 513 | 5120 0.058105 0.003421 0.008852 514 | 5130 0.044018 0.003438 0.008937 515 | 5140 0.044112 0.003413 0.008981 516 | 5150 0.052687 0.003532 0.008928 517 | 5160 0.028533 0.003538 0.009120 518 | 5170 0.037718 0.003452 0.008955 519 | 5180 0.018003 0.003500 0.008989 520 | 5190 0.032656 0.003560 0.008926 521 | 5200 0.041929 0.003447 0.009499 522 | 5210 0.047568 0.003493 0.008991 523 | 5220 0.167359 0.003502 0.009334 524 | 5230 0.054723 0.003439 0.009000 525 | 5240 0.028508 0.003502 0.009078 526 | 5250 0.044518 0.003511 0.009063 527 | 5260 0.031099 0.003603 0.009247 528 | 5270 0.166149 0.003561 0.009352 529 | 5280 0.137015 0.003586 0.009284 530 | 5290 0.614569 0.003563 0.009298 531 | 5300 0.048740 0.003541 0.009359 532 | 5310 0.039193 0.003600 0.009502 533 | 5320 0.619608 0.003512 0.009335 534 | 5330 0.628658 0.003549 0.009346 535 | 5340 0.056910 0.003612 0.009250 536 | 5350 0.027927 0.003582 0.009352 537 | 5360 0.118334 0.003558 0.009337 538 | 5370 0.026659 0.003590 0.009498 539 | 5380 0.034232 0.003617 0.009427 540 | 5390 0.176879 0.003563 0.009361 541 | 5400 0.027743 0.003560 0.009613 542 | 5410 0.098038 0.003649 0.009435 543 | 5420 0.040948 0.003628 0.009527 544 | 5430 0.028276 0.003560 0.009565 545 | 5440 0.030424 0.003732 0.009626 546 | 5450 0.644285 0.003649 0.009583 547 | 5460 0.103845 0.003811 0.009535 548 | 5470 0.030887 0.003728 0.009765 549 | 5480 0.068079 0.003780 0.010403 550 | 5490 0.647371 0.003718 0.009620 551 | 5500 0.029037 0.003677 0.009695 552 | 5510 0.048769 0.003693 0.009824 553 | 5520 0.054809 0.003775 0.009868 554 | 5530 0.670805 0.003735 0.009777 555 | 5540 0.066721 0.003762 0.009865 556 | 5550 0.017306 0.003785 0.010010 557 | 5560 0.038866 0.003748 0.009925 558 | 5570 0.029754 0.003788 0.009800 559 | 5580 0.049602 0.003788 0.009843 560 | 5590 0.151491 0.003712 0.009899 561 | 5600 0.190166 0.003740 0.009942 562 | 5610 0.224020 0.003779 0.009976 563 | 5620 0.024276 0.003798 0.009969 564 | 5630 0.055101 0.003759 0.009929 565 | 5640 0.674813 0.003760 0.009858 566 | 5650 0.032515 0.003869 0.009939 567 | 5660 0.049920 0.004256 0.010199 568 | 5670 0.678436 0.003771 0.010441 569 | 5680 0.025501 0.003872 0.010180 570 | 5690 0.202559 0.003822 0.010240 571 | 5700 0.017407 0.003816 0.010057 572 | 5710 0.064755 0.003977 0.010421 573 | 5720 0.120912 0.003874 0.010094 574 | 5730 0.079289 0.003885 0.010366 575 | 5740 0.030163 0.003839 0.010236 576 | 5750 0.030993 0.003842 0.010243 577 | 5760 0.155868 0.003977 0.010230 578 | 5770 0.720030 0.003917 0.010273 579 | 5780 0.020626 0.003917 0.010494 580 | 5790 0.030955 0.003889 0.010331 581 | 5800 0.038292 0.003910 0.010611 582 | 5810 0.067871 0.004036 0.010414 583 | 5820 0.027892 0.003906 0.010356 584 | 5830 0.187336 0.003951 0.010401 585 | 5840 0.034804 0.003906 0.010556 586 | 5850 0.047936 0.004074 0.010374 587 | 5860 0.752172 0.003965 0.010481 588 | 5870 0.025199 0.004108 0.010343 589 | 5880 0.057801 0.003980 0.010719 590 | 5890 0.049421 0.003945 0.010541 591 | 5900 0.029146 0.003947 0.010636 592 | 5910 0.746149 0.004030 0.010518 593 | 5920 0.041069 0.003983 0.010674 594 | 5930 0.026566 0.004076 0.010870 595 | 5940 0.027066 0.003990 0.010661 596 | 5950 0.034604 0.004086 0.010914 597 | 5960 0.487896 0.004173 0.011638 598 | 5970 0.734689 0.004010 0.010770 599 | 5980 0.054041 0.004029 0.010653 600 | 5990 0.047308 0.004022 0.011022 601 | 6000 0.020893 0.004151 0.010847 602 | 6010 0.009720 0.004101 0.011014 603 | 6020 0.030603 0.004079 0.010842 604 | 6030 0.061266 0.004033 0.010915 605 | 6040 0.028289 0.004022 0.010779 606 | 6050 0.026158 0.004051 0.010847 607 | 6060 0.787569 0.004090 0.010810 608 | 6070 0.050135 0.004180 0.010856 609 | 6080 0.287045 0.004238 0.010958 610 | 6090 0.070066 0.004210 0.011011 611 | 6100 0.085593 0.004175 0.010994 612 | 6110 0.195190 0.004115 0.011508 613 | 6120 0.024777 0.004129 0.011075 614 | 6130 0.046365 0.004341 0.011089 615 | 6140 0.054742 0.004213 0.011034 616 | 6150 0.045088 0.004158 0.010992 617 | 6160 0.787475 0.004248 0.011139 618 | 6170 0.211421 0.004134 0.011125 619 | 6180 0.046016 0.004201 0.011136 620 | 6190 0.805427 0.004140 0.011035 621 | 6200 0.055217 0.004263 0.011234 622 | 6210 0.823492 0.004143 0.011510 623 | 6220 0.159195 0.004182 0.011152 624 | 6230 0.389896 0.004198 0.011196 625 | 6240 0.029176 0.004256 0.011318 626 | 6250 0.818851 0.004318 0.011243 627 | 6260 0.086046 0.004331 0.011292 628 | 6270 0.050538 0.004331 0.011359 629 | 6280 0.032578 0.004329 0.011417 630 | 6290 0.032218 0.004351 0.011289 631 | 6300 0.041734 0.004362 0.011317 632 | 6310 0.118983 0.004269 0.011368 633 | 6320 0.037106 0.004195 0.011430 634 | 6330 0.130549 0.004221 0.011660 635 | 6340 0.143883 0.004351 0.011382 636 | 6350 0.843972 0.004234 0.011364 637 | 6360 0.316187 0.004392 0.011419 638 | 6370 0.852242 0.004571 0.011360 639 | 6380 0.055347 0.004396 0.011429 640 | 6390 0.015162 0.004413 0.011743 641 | 6400 0.111932 0.004356 0.011584 642 | 6410 0.049264 0.004402 0.011515 643 | 6420 0.027488 0.004411 0.011480 644 | 6430 0.878771 0.004432 0.011399 645 | 6440 0.532999 0.004369 0.011469 646 | 6450 0.272733 0.004516 0.011693 647 | 6460 0.060067 0.004390 0.011490 648 | 6470 0.023674 0.004483 0.011661 649 | 6480 0.891343 0.004514 0.011550 650 | 6490 0.099673 0.004444 0.011510 651 | 6500 0.910844 0.004461 0.011482 652 | 6510 0.078428 0.004450 0.011688 653 | 6520 0.907721 0.004474 0.011695 654 | 6530 0.519196 0.004517 0.011679 655 | 6540 0.028008 0.004473 0.011536 656 | 6550 0.048574 0.004484 0.012437 657 | 6560 0.052269 0.004534 0.011954 658 | 6570 0.034865 0.004695 0.011671 659 | 6580 0.053769 0.004472 0.011842 660 | 6590 0.916040 0.004524 0.011944 661 | 6600 0.370702 0.004442 0.011862 662 | 6610 0.032692 0.004595 0.011637 663 | 6620 0.043851 0.004526 0.011651 664 | 6630 0.030013 0.004558 0.011832 665 | 6640 0.129854 0.004530 0.012195 666 | 6650 0.120441 0.004501 0.011688 667 | 6660 0.961097 0.004679 0.011808 668 | 6670 0.932504 0.005021 0.011967 669 | 6680 0.024569 0.004563 0.011754 670 | 6690 0.016517 0.004643 0.011702 671 | 6700 0.041447 0.004553 0.011785 672 | 6710 0.987396 0.004632 0.011830 673 | 6720 0.420747 0.004772 0.012038 674 | 6730 0.036746 0.004568 0.012013 675 | 6740 0.956135 0.004695 0.011956 676 | 6750 0.046455 0.004642 0.011691 677 | 6760 0.030176 0.004596 0.012171 678 | 6770 0.061488 0.004606 0.011947 679 | 6780 0.124324 0.004616 0.012003 680 | 6790 0.118129 0.005035 0.012287 681 | 6800 1.010787 0.004688 0.012294 682 | 6810 0.096048 0.004717 0.014846 683 | 6820 0.035368 0.004748 0.012607 684 | 6830 0.028858 0.004727 0.016837 685 | 6840 0.040009 0.004689 0.012202 686 | 6850 0.286429 0.004744 0.011954 687 | 6860 0.284612 0.004796 0.011971 688 | 6870 0.020761 0.004951 0.012050 689 | 6880 0.030193 0.004893 0.011991 690 | 6890 0.803076 0.004848 0.012007 691 | 6900 0.624855 0.004827 0.012118 692 | 6910 0.045664 0.004746 0.012242 693 | 6920 1.035688 0.004644 0.012002 694 | 6930 0.070400 0.004832 0.012057 695 | 6940 0.288708 0.004766 0.012534 696 | 6950 0.056016 0.004895 0.011976 697 | 6960 0.405225 0.004872 0.012021 698 | 6970 0.043426 0.004763 0.012095 699 | 6980 0.706269 0.004819 0.012180 700 | 6990 0.063662 0.004778 0.012030 701 | 7000 0.042343 0.004759 0.012161 702 | 7010 1.032905 0.004831 0.012059 703 | 7020 1.049591 0.004808 0.012230 704 | 7030 0.031587 0.004929 0.012434 705 | 7040 0.012459 0.004825 0.012174 706 | 7050 0.034316 0.004827 0.012535 707 | 7060 0.052669 0.004902 0.012269 708 | 7070 1.060919 0.005180 0.012128 709 | 7080 0.044573 0.004998 0.012294 710 | 7090 0.325724 0.004926 0.012216 711 | 7100 0.039470 0.004948 0.012416 712 | 7110 0.060871 0.005058 0.012486 713 | 7120 0.329227 0.004826 0.012216 714 | 7130 1.139379 0.005041 0.012249 715 | 7140 1.092157 0.004951 0.012420 716 | 7150 1.096692 0.005028 0.012488 717 | 7160 1.112511 0.005059 0.012479 718 | 7170 0.054144 0.004942 0.012619 719 | 7180 0.027483 0.005029 0.014568 720 | 7190 0.051519 0.005130 0.012612 721 | 7200 0.037199 0.005027 0.012683 722 | 7210 0.037742 0.004965 0.012459 723 | 7220 0.050643 0.005140 0.012437 724 | 7230 1.140620 0.005009 0.012264 725 | 7240 0.038609 0.004988 0.012482 726 | 7250 0.044890 0.005030 0.012483 727 | 7260 0.190270 0.005032 0.013048 728 | 7270 0.044428 0.005026 0.012523 729 | 7280 1.163644 0.005287 0.012454 730 | 7290 1.111654 0.005249 0.012419 731 | 7300 0.053076 0.005220 0.013084 732 | 7310 0.026716 0.005162 0.012402 733 | 7320 0.048242 0.005088 0.013144 734 | 7330 0.105109 0.005110 0.012625 735 | 7340 0.059944 0.005229 0.012710 736 | 7350 1.192783 0.005096 0.013366 737 | 7360 1.172942 0.005176 0.012562 738 | 7370 0.062271 0.005020 0.012467 739 | 7380 1.220461 0.005408 0.012582 740 | 7390 0.082287 0.005079 0.012778 741 | 7400 0.039166 0.005125 0.013103 742 | 7410 0.313522 0.005251 0.012770 743 | 7420 0.059397 0.005125 0.013172 744 | 7430 0.045792 0.005185 0.013180 745 | 7440 0.060835 0.005338 0.012798 746 | 7450 1.152449 0.005193 0.012696 747 | 7460 0.833629 0.005040 0.012767 748 | 7470 1.196933 0.005538 0.012816 749 | 7480 0.050965 0.005327 0.012710 750 | 7490 0.073374 0.005438 0.012672 751 | 7500 0.259241 0.005185 0.012874 752 | 7510 0.149519 0.005420 0.014410 753 | 7520 0.074851 0.005230 0.012705 754 | 7530 1.227992 0.005247 0.013059 755 | 7540 0.462800 0.005213 0.013447 756 | 7550 0.047632 0.005227 0.013293 757 | 7560 0.017861 0.005257 0.012759 758 | 7570 0.033150 0.005227 0.012880 759 | 7580 1.234919 0.005291 0.013082 760 | 7590 1.261493 0.005224 0.012757 761 | 7600 0.077491 0.005272 0.012840 762 | 7610 0.033675 0.005235 0.013130 763 | 7620 0.306418 0.005284 0.013110 764 | 7630 0.073846 0.005348 0.013275 765 | 7640 0.070410 0.005725 0.012924 766 | 7650 1.291493 0.005210 0.013301 767 | 7660 1.293994 0.005221 0.012901 768 | 7670 0.013715 0.005357 0.012899 769 | 7680 0.042735 0.005607 0.013507 770 | 7690 0.168043 0.005325 0.013026 771 | 7700 0.723387 0.005539 0.013408 772 | 7710 0.174228 0.005463 0.013236 773 | 7720 1.296848 0.005330 0.012949 774 | 7730 0.126708 0.005278 0.013501 775 | 7740 1.324159 0.005467 0.012907 776 | 7750 0.331408 0.005371 0.013061 777 | 7760 0.175451 0.005446 0.014181 778 | 7770 1.294206 0.005440 0.013086 779 | 7780 0.069564 0.005368 0.013095 780 | 7790 0.040222 0.005363 0.013298 781 | 7800 0.056317 0.005405 0.013330 782 | 7810 1.334161 0.005417 0.013058 783 | 7820 1.338861 0.005471 0.013191 784 | 7830 0.512935 0.005529 0.013154 785 | 7840 1.067702 0.005433 0.013056 786 | 7850 0.034158 0.005513 0.013228 787 | 7860 0.387996 0.005532 0.013604 788 | 7870 0.653182 0.005576 0.013861 789 | 7880 0.058486 0.005934 0.013144 790 | 7890 0.071548 0.005620 0.013179 791 | 7900 0.044159 0.005576 0.013546 792 | 7910 0.048257 0.005583 0.013666 793 | 7920 0.186350 0.005785 0.013620 794 | 7930 0.379399 0.005712 0.013388 795 | 7940 0.058817 0.005635 0.014086 796 | 7950 0.598256 0.005550 0.013348 797 | 7960 0.053621 0.005584 0.013275 798 | 7970 0.039586 0.005707 0.013394 799 | 7980 1.458578 0.005557 0.013415 800 | 7990 1.431665 0.005738 0.013313 801 | 8000 0.041797 0.005554 0.013433 802 | 8010 1.423562 0.005538 0.013278 803 | 8020 0.068714 0.005506 0.013528 804 | 8030 0.712857 0.005645 0.013804 805 | 8040 0.604138 0.005729 0.013529 806 | 8050 1.425605 0.005936 0.013761 807 | 8060 0.217017 0.005603 0.013584 808 | 8070 1.475625 0.005684 0.013560 809 | 8080 0.061685 0.005683 0.013459 810 | 8090 0.062487 0.005876 0.013687 811 | 8100 0.053033 0.005772 0.013526 812 | 8110 0.361019 0.005617 0.013511 813 | 8120 0.060412 0.005809 0.013569 814 | 8130 0.453688 0.005711 0.013512 815 | 8140 0.052052 0.005642 0.013426 816 | 8150 0.055246 0.005661 0.013547 817 | 8160 1.472457 0.005874 0.013739 818 | 8170 0.046403 0.005689 0.013553 819 | 8180 0.044749 0.005781 0.013575 820 | 8190 0.061526 0.005738 0.013975 821 | 8200 0.051864 0.005760 0.013621 822 | 8210 1.520834 0.005642 0.013686 823 | 8220 0.371614 0.005734 0.013559 824 | 8230 0.040682 0.005777 0.013595 825 | 8240 0.076675 0.005771 0.013542 826 | 8250 1.581201 0.005728 0.013985 827 | 8260 0.053323 0.006128 0.013936 828 | 8270 0.061537 0.005738 0.013842 829 | 8280 1.549015 0.005920 0.014196 830 | 8290 0.056442 0.006037 0.014211 831 | 8300 0.057100 0.006079 0.016897 832 | 8310 1.598349 0.005961 0.013874 833 | 8320 0.040882 0.005891 0.015701 834 | 8330 0.068974 0.006545 0.014773 835 | 8340 1.560223 0.005800 0.013772 836 | 8350 0.061418 0.005835 0.014049 837 | 8360 1.570207 0.005799 0.013804 838 | 8370 1.547809 0.005856 0.014094 839 | 8380 0.462077 0.005862 0.013991 840 | 8390 0.060395 0.005956 0.014012 841 | 8400 1.585453 0.005870 0.014124 842 | 8410 0.032702 0.005948 0.014161 843 | 8420 1.608091 0.005867 0.014422 844 | 8430 1.622208 0.006444 0.015830 845 | 8440 0.042435 0.005848 0.014551 846 | 8450 1.329776 0.005942 0.014099 847 | 8460 0.599872 0.005974 0.014288 848 | 8470 1.618055 0.005871 0.014309 849 | 8480 0.050725 0.005947 0.014466 850 | 8490 0.067835 0.006168 0.015173 851 | 8500 1.639354 0.006137 0.014295 852 | 8510 1.646673 0.005944 0.014399 853 | 8520 1.655751 0.006082 0.014285 854 | 8530 1.356231 0.006002 0.015550 855 | 8540 1.639190 0.006033 0.015056 856 | 8550 1.675363 0.006020 0.014297 857 | 8560 1.703005 0.006000 0.014529 858 | 8570 0.664786 0.005894 0.014476 859 | 8580 1.661459 0.005929 0.014503 860 | 8590 0.059554 0.006109 0.014671 861 | 8600 0.533370 0.006035 0.014565 862 | 8610 0.070468 0.006232 0.014666 863 | 8620 1.763030 0.006141 0.014547 864 | 8630 0.066643 0.006053 0.014479 865 | 8640 1.692162 0.006477 0.014701 866 | 8650 1.757595 0.006007 0.014893 867 | 8660 0.050208 0.005950 0.014786 868 | 8670 0.807176 0.006148 0.014693 869 | 8680 0.038720 0.005994 0.015072 870 | 8690 0.072317 0.007255 0.014799 871 | 8700 0.032777 0.006468 0.014705 872 | 8710 1.755907 0.006094 0.014886 873 | 8720 1.735653 0.006395 0.014732 874 | 8730 0.163961 0.006113 0.014951 875 | 8740 1.829375 0.006271 0.014847 876 | 8750 1.810416 0.006205 0.015067 877 | 8760 1.762853 0.006222 0.014855 878 | 8770 0.046968 0.006189 0.015257 879 | 8780 1.805921 0.006135 0.015187 880 | 8790 1.862750 0.006119 0.015060 881 | 8800 0.458638 0.006129 0.014945 882 | 8810 1.878075 0.006390 0.015099 883 | 8820 0.060342 0.006215 0.015465 884 | 8830 0.077444 0.006119 0.016859 885 | 8840 1.809205 0.006458 0.015687 886 | 8850 0.062583 0.006234 0.015166 887 | 8860 1.948473 0.006268 0.015234 888 | 8870 0.079385 0.006312 0.015183 889 | 8880 1.878431 0.006249 0.015220 890 | 8890 1.890723 0.006162 0.015165 891 | 8900 1.920919 0.006291 0.015668 892 | 8910 0.354880 0.006493 0.015758 893 | 8920 1.924734 0.006499 0.015407 894 | 8930 0.070993 0.006250 0.015467 895 | 8940 1.929792 0.006495 0.016090 896 | 8950 0.063614 0.006236 0.015643 897 | 8960 1.943164 0.006400 0.015710 898 | 8970 1.952579 0.006271 0.015649 899 | 8980 1.950599 0.006343 0.015421 900 | 8990 0.402880 0.006312 0.015472 901 | 9000 0.028668 0.006288 0.015830 902 | 9010 1.954831 0.006313 0.015484 903 | 9020 0.073938 0.006398 0.015953 904 | 9030 0.055423 0.006393 0.015826 905 | 9040 2.002382 0.006406 0.015810 906 | 9050 0.172004 0.006329 0.015647 907 | 9060 0.093190 0.006341 0.015925 908 | 9070 0.145542 0.006407 0.017793 909 | 9080 2.047223 0.006895 0.019580 910 | 9090 2.003831 0.006388 0.016087 911 | 9100 2.038362 0.006644 0.015873 912 | 9110 0.085542 0.006564 0.015793 913 | 9120 2.051197 0.006439 0.016097 914 | 9130 2.113431 0.006396 0.016006 915 | 9140 2.116444 0.006385 0.015913 916 | 9150 2.028703 0.006478 0.015701 917 | 9160 2.072286 0.006390 0.015892 918 | 9170 0.087736 0.006338 0.018801 919 | 9180 2.149825 0.006445 0.016047 920 | 9190 0.559094 0.006382 0.018574 921 | 9200 0.054173 0.006390 0.016243 922 | 9210 0.072731 0.006415 0.015985 923 | 9220 0.139150 0.006424 0.016608 924 | 9230 2.260019 0.006455 0.016224 925 | 9240 1.067121 0.006508 0.016991 926 | 9250 2.200075 0.006520 0.016632 927 | 9260 2.194751 0.006443 0.016196 928 | 9270 2.167185 0.006586 0.016545 929 | 9280 2.209372 0.006583 0.016276 930 | 9290 2.164022 0.006597 0.016613 931 | 9300 2.200333 0.006798 0.016514 932 | 9310 2.075298 0.006834 0.016581 933 | 9320 2.257995 0.006928 0.016516 934 | 9330 2.265836 0.006648 0.016841 935 | 9340 2.314038 0.006721 0.017000 936 | 9350 0.027728 0.006662 0.016986 937 | 9360 2.308588 0.006707 0.017298 938 | 9370 2.391144 0.006604 0.016661 939 | 9380 0.466967 0.006653 0.017178 940 | 9390 2.333364 0.006606 0.016692 941 | 9400 2.300418 0.006446 0.016853 942 | 9410 0.094620 0.006598 0.016815 943 | 9420 1.803161 0.006822 0.016836 944 | 9430 2.389184 0.006532 0.016881 945 | 9440 2.336234 0.006568 0.016805 946 | 9450 2.437968 0.006634 0.016926 947 | 9460 2.435179 0.006698 0.017246 948 | 9470 0.066004 0.006649 0.017457 949 | 9480 2.437616 0.006709 0.017045 950 | 9490 2.410051 0.006996 0.017332 951 | 9500 2.410161 0.007149 0.016970 952 | 9510 2.430439 0.007280 0.017310 953 | 9520 2.515101 0.007169 0.017760 954 | 9530 0.073792 0.006973 0.018057 955 | 9540 2.512979 0.006799 0.017662 956 | 9550 2.521218 0.006655 0.017385 957 | 9560 2.576398 0.006774 0.017173 958 | 9570 2.551120 0.006693 0.017452 959 | 9580 2.640930 0.006841 0.017765 960 | 9590 0.596436 0.006763 0.017667 961 | 9600 0.059996 0.007236 0.018018 962 | 9610 2.662012 0.006891 0.017917 963 | 9620 2.663088 0.006999 0.017989 964 | 9630 0.235960 0.006859 0.017851 965 | 9640 2.723527 0.006738 0.018081 966 | 9650 2.724697 0.007039 0.018236 967 | 9660 2.657940 0.006815 0.017999 968 | 9670 2.675012 0.006684 0.018113 969 | 9680 2.732544 0.006788 0.017862 970 | 9690 2.744273 0.007199 0.018303 971 | 9700 2.723814 0.007173 0.018529 972 | 9710 2.879832 0.007490 0.019601 973 | 9720 2.779240 0.006920 0.018165 974 | 9730 2.904731 0.006969 0.018387 975 | 9740 3.032282 0.006905 0.018560 976 | 9750 2.899429 0.006963 0.018476 977 | 9760 2.855799 0.006770 0.018375 978 | 9770 2.968144 0.007122 0.018784 979 | 9780 3.102763 0.006967 0.018631 980 | 9790 3.077601 0.007027 0.019029 981 | 9800 3.046069 0.006865 0.018941 982 | 9810 2.977305 0.006840 0.018673 983 | 9820 3.098152 0.007072 0.018978 984 | 9830 2.999108 0.006980 0.018959 985 | 9840 0.168441 0.006848 0.018946 986 | 9850 3.156040 0.006899 0.019358 987 | 9860 3.089238 0.007086 0.019299 988 | 9870 3.112905 0.007028 0.019229 989 | 9880 3.307528 0.007028 0.019513 990 | 9890 3.178633 0.007097 0.019285 991 | 9900 3.246257 0.007474 0.019740 992 | 9910 0.872399 0.007243 0.020635 993 | 9920 3.454012 0.007456 0.020052 994 | 9930 3.616309 0.007037 0.020937 995 | 9940 3.430376 0.007058 0.020398 996 | 9950 3.559193 0.007250 0.021326 997 | 9960 0.121504 0.006925 0.021948 998 | 9970 3.820444 0.006978 0.022345 999 | 9980 3.609674 0.006913 0.021133 1000 | 9990 3.967390 0.007299 0.022372 1001 | 10000 3.965548 0.007164 0.021855 1002 | -------------------------------------------------------------------------------- /lab/lab01/data.txt: -------------------------------------------------------------------------------- 1 | 0 0.000002 0.000001 0.000001 0.000001 2 | 10 0.000170 0.000014 0.000031 0.000034 3 | 20 0.000866 0.000023 0.000099 0.000064 4 | 30 0.001220 0.000036 0.000105 0.000127 5 | 40 0.000654 0.000048 0.000152 0.000189 6 | 50 0.002059 0.000045 0.000140 0.000169 7 | 60 0.002569 0.000055 0.000167 0.000205 8 | 70 0.005788 0.000082 0.000193 0.000230 9 | 80 0.004892 0.000104 0.000318 0.000383 10 | 90 0.005114 0.000115 0.000355 0.000321 11 | 100 0.008092 0.000128 0.000438 0.000503 12 | 110 0.003339 0.000048 0.000143 0.000174 13 | 120 0.001404 0.000051 0.000149 0.000194 14 | 130 0.001238 0.000057 0.000161 0.000198 15 | 140 0.006017 0.000063 0.000179 0.000221 16 | 150 0.003453 0.000068 0.000201 0.000242 17 | 160 0.002997 0.000081 0.000217 0.000259 18 | 170 0.004874 0.000077 0.000234 0.000278 19 | 180 0.002416 0.000082 0.000256 0.000298 20 | 190 0.003600 0.000086 0.000280 0.000321 21 | 200 0.002694 0.000090 0.000293 0.000357 22 | 210 0.003957 0.000100 0.000301 0.000351 23 | 220 0.006470 0.000105 0.000306 0.000365 24 | 230 0.004047 0.000113 0.000313 0.000377 25 | 240 0.004546 0.000107 0.000327 0.000389 26 | 250 0.003202 0.000115 0.000333 0.000395 27 | 260 0.005741 0.000121 0.000355 0.000421 28 | 270 0.004703 0.000132 0.000365 0.000435 29 | 280 0.004217 0.000128 0.000379 0.000458 30 | 290 0.000866 0.000136 0.000418 0.000478 31 | 300 0.006289 0.000144 0.000424 0.000491 32 | 310 0.007232 0.000145 0.000438 0.000524 33 | 320 0.003414 0.000156 0.000463 0.000546 34 | 330 0.004649 0.000173 0.000502 0.000585 35 | 340 0.003236 0.000163 0.000502 0.000586 36 | 350 0.009103 0.000176 0.000527 0.000600 37 | 360 0.007891 0.000179 0.000541 0.000627 38 | 370 0.008317 0.000186 0.000562 0.000649 39 | 380 0.003278 0.000184 0.000590 0.000666 40 | 390 0.007691 0.000200 0.000604 0.000697 41 | 400 0.008260 0.000199 0.000603 0.000693 42 | 410 0.010230 0.000207 0.000632 0.000722 43 | 420 0.006789 0.000229 0.000622 0.000720 44 | 430 0.008483 0.000221 0.000643 0.000740 45 | 440 0.015200 0.000221 0.000656 0.000754 46 | 450 0.008442 0.000230 0.000658 0.000754 47 | 460 0.006789 0.000241 0.000684 0.000792 48 | 470 0.008612 0.000234 0.000674 0.000787 49 | 480 0.007582 0.000251 0.000686 0.000793 50 | 490 0.009115 0.000253 0.000683 0.000800 51 | 500 0.006385 0.000267 0.000713 0.000822 52 | 510 0.005264 0.000255 0.000751 0.000831 53 | 520 0.006188 0.000272 0.000719 0.000849 54 | 530 0.009669 0.000287 0.000781 0.000897 55 | 540 0.008094 0.000278 0.000796 0.000918 56 | 550 0.006343 0.000289 0.000833 0.001025 57 | 560 0.006280 0.000295 0.000805 0.000939 58 | 570 0.018362 0.000313 0.000838 0.001063 59 | 580 0.005325 0.000358 0.000975 0.000986 60 | 590 0.007787 0.000306 0.000875 0.001000 61 | 600 0.007290 0.000307 0.000891 0.001016 62 | 610 0.012347 0.000325 0.000929 0.001045 63 | 620 0.009880 0.000361 0.000949 0.001128 64 | 630 0.014051 0.000334 0.000957 0.001156 65 | 640 0.011420 0.000354 0.000994 0.001106 66 | 650 0.011029 0.000343 0.000987 0.001104 67 | 660 0.007372 0.000351 0.001005 0.001126 68 | 670 0.013859 0.000351 0.001019 0.001154 69 | 680 0.013044 0.000361 0.001049 0.001171 70 | 690 0.015341 0.000365 0.001069 0.001257 71 | 700 0.010786 0.000375 0.001135 0.001242 72 | 710 0.016671 0.000387 0.001163 0.001225 73 | 720 0.018125 0.000386 0.001144 0.001286 74 | 730 0.004219 0.000403 0.001184 0.001328 75 | 740 0.011733 0.000411 0.001187 0.001300 76 | 750 0.009348 0.000393 0.001254 0.001339 77 | 760 0.014871 0.000402 0.001221 0.001338 78 | 770 0.007021 0.000405 0.001249 0.001383 79 | 780 0.017994 0.000445 0.001256 0.001366 80 | 790 0.009607 0.000423 0.001298 0.001452 81 | 800 0.009618 0.000434 0.001284 0.001412 82 | 810 0.014668 0.000435 0.001299 0.001441 83 | 820 0.011004 0.000450 0.001296 0.001446 84 | 830 0.008071 0.000453 0.001309 0.001503 85 | 840 0.009702 0.000461 0.001299 0.001446 86 | 850 0.011870 0.000456 0.001337 0.001488 87 | 860 0.021891 0.000460 0.001337 0.001512 88 | 870 0.015305 0.000467 0.001337 0.001734 89 | 880 0.008245 0.000474 0.001391 0.001531 90 | 890 0.007340 0.000489 0.001352 0.001620 91 | 900 0.018420 0.000484 0.001385 0.001533 92 | 910 0.015057 0.000510 0.001397 0.001542 93 | 920 0.014248 0.000520 0.001440 0.001594 94 | 930 0.012568 0.000552 0.001418 0.001603 95 | 940 0.006449 0.000517 0.001406 0.001571 96 | 950 0.021092 0.000514 0.001424 0.001580 97 | 960 0.015632 0.000543 0.001496 0.001606 98 | 970 0.009206 0.000534 0.001452 0.001603 99 | 980 0.003781 0.000550 0.001476 0.001640 100 | 990 0.015251 0.000536 0.001469 0.001625 101 | 1000 0.006164 0.000590 0.001528 0.001693 102 | 1010 0.011547 0.000569 0.001585 0.001651 103 | 1020 0.014518 0.000560 0.001517 0.001713 104 | 1030 0.028410 0.000575 0.001515 0.001700 105 | 1040 0.021230 0.000585 0.001543 0.001722 106 | 1050 0.025004 0.000591 0.001585 0.001750 107 | 1060 0.020483 0.000592 0.001569 0.001761 108 | 1070 0.012168 0.000641 0.001596 0.001794 109 | 1080 0.009224 0.000604 0.001678 0.001831 110 | 1090 0.013582 0.000600 0.001687 0.001868 111 | 1100 0.013606 0.000609 0.001657 0.001843 112 | 1110 0.009894 0.000609 0.001681 0.001864 113 | 1120 0.009586 0.000619 0.001695 0.001885 114 | 1130 0.016721 0.000668 0.001722 0.001921 115 | 1140 0.010149 0.000634 0.001757 0.001934 116 | 1150 0.008346 0.000647 0.001781 0.001965 117 | 1160 0.014194 0.000655 0.001855 0.002046 118 | 1170 0.022733 0.000641 0.001818 0.002001 119 | 1180 0.018241 0.000652 0.001908 0.002103 120 | 1190 0.033037 0.000656 0.001845 0.002069 121 | 1200 0.028698 0.000662 0.001946 0.002054 122 | 1210 0.012093 0.000661 0.001883 0.002072 123 | 1220 0.012137 0.000686 0.001965 0.002157 124 | 1230 0.016058 0.000694 0.001940 0.002113 125 | 1240 0.016240 0.000686 0.001972 0.002153 126 | 1250 0.025465 0.000718 0.001997 0.002199 127 | 1260 0.014664 0.000736 0.001997 0.002218 128 | 1270 0.008774 0.000756 0.002081 0.002255 129 | 1280 0.019732 0.000784 0.002050 0.002245 130 | 1290 0.032029 0.000728 0.002056 0.002227 131 | 1300 0.013905 0.000736 0.002081 0.002268 132 | 1310 0.029498 0.000752 0.002103 0.002294 133 | 1320 0.032501 0.000745 0.002136 0.002334 134 | 1330 0.040680 0.000757 0.002167 0.002371 135 | 1340 0.011742 0.000771 0.002170 0.002355 136 | 1350 0.016209 0.000760 0.002246 0.002437 137 | 1360 0.032287 0.000769 0.002216 0.002391 138 | 1370 0.039999 0.000770 0.002206 0.002390 139 | 1380 0.012974 0.000819 0.002362 0.002563 140 | 1390 0.039859 0.000784 0.002272 0.002446 141 | 1400 0.020968 0.000815 0.002309 0.002489 142 | 1410 0.024182 0.000814 0.002329 0.002529 143 | 1420 0.038013 0.000822 0.002366 0.002541 144 | 1430 0.008755 0.000825 0.002399 0.002600 145 | 1440 0.007637 0.000841 0.002368 0.002544 146 | 1450 0.030063 0.000829 0.002460 0.002647 147 | 1460 0.026974 0.000831 0.002446 0.002597 148 | 1470 0.036815 0.000833 0.002474 0.002704 149 | 1480 0.024496 0.000837 0.002461 0.002634 150 | 1490 0.017926 0.000896 0.002490 0.002682 151 | 1500 0.013059 0.000874 0.002631 0.002811 152 | 1510 0.007839 0.000865 0.002621 0.002746 153 | 1520 0.022289 0.000879 0.002608 0.002801 154 | 1530 0.012205 0.000878 0.002596 0.002757 155 | 1540 0.018009 0.000878 0.002595 0.002748 156 | 1550 0.028391 0.000899 0.002587 0.002775 157 | 1560 0.016282 0.000893 0.002576 0.002766 158 | 1570 0.045780 0.000906 0.002627 0.002768 159 | 1580 0.058777 0.000919 0.002649 0.002823 160 | 1590 0.019477 0.000919 0.002692 0.002847 161 | 1600 0.008054 0.000912 0.002680 0.002863 162 | 1610 0.006090 0.000975 0.002796 0.002984 163 | 1620 0.014301 0.000957 0.002686 0.002876 164 | 1630 0.011162 0.000961 0.002691 0.002892 165 | 1640 0.022234 0.000946 0.002689 0.002882 166 | 1650 0.016100 0.000973 0.002701 0.002891 167 | 1660 0.010053 0.000952 0.002795 0.003023 168 | 1670 0.014765 0.000968 0.002802 0.003015 169 | 1680 0.029164 0.000977 0.002738 0.002953 170 | 1690 0.039708 0.000983 0.002729 0.002938 171 | 1700 0.024295 0.000998 0.002773 0.002999 172 | 1710 0.027817 0.000999 0.002782 0.002989 173 | 1720 0.006562 0.000987 0.002859 0.003095 174 | 1730 0.047479 0.001002 0.002824 0.003045 175 | 1740 0.034800 0.001021 0.002883 0.003104 176 | 1750 0.028230 0.001031 0.002877 0.003074 177 | 1760 0.053164 0.001059 0.002908 0.003141 178 | 1770 0.018128 0.001064 0.002873 0.003112 179 | 1780 0.037435 0.001055 0.002837 0.003068 180 | 1790 0.004313 0.001061 0.002882 0.003126 181 | 1800 0.008557 0.001057 0.002893 0.003136 182 | 1810 0.026521 0.001052 0.002957 0.003200 183 | 1820 0.023690 0.001068 0.002937 0.003203 184 | 1830 0.047883 0.001074 0.002934 0.003184 185 | 1840 0.054736 0.001072 0.003274 0.003230 186 | 1850 0.019136 0.001099 0.002979 0.003227 187 | 1860 0.030983 0.001098 0.002931 0.003179 188 | 1870 0.027798 0.001104 0.002936 0.003212 189 | 1880 0.006892 0.001111 0.002977 0.003279 190 | 1890 0.036034 0.001131 0.002981 0.003246 191 | 1900 0.047246 0.001126 0.003023 0.003265 192 | 1910 0.008368 0.001140 0.003094 0.003356 193 | 1920 0.015311 0.001126 0.002994 0.003259 194 | 1930 0.017642 0.001198 0.003002 0.003275 195 | 1940 0.015515 0.001138 0.003053 0.003322 196 | 1950 0.015225 0.001146 0.003102 0.003372 197 | 1960 0.013232 0.001147 0.003066 0.003362 198 | 1970 0.018959 0.001189 0.003051 0.003336 199 | 1980 0.021142 0.001210 0.003140 0.003428 200 | 1990 0.021534 0.001195 0.003172 0.003460 201 | 2000 0.028761 0.001195 0.003135 0.003427 202 | 2010 0.026297 0.001209 0.003108 0.003373 203 | 2020 0.020005 0.001198 0.003187 0.003509 204 | 2030 0.061970 0.001268 0.003139 0.003405 205 | 2040 0.020772 0.001224 0.003191 0.003470 206 | 2050 0.018822 0.001234 0.003123 0.003402 207 | 2060 0.022033 0.001233 0.003140 0.003416 208 | 2070 0.018897 0.001212 0.003187 0.003482 209 | 2080 0.026123 0.001260 0.003214 0.003520 210 | 2090 0.042129 0.001253 0.003280 0.003520 211 | 2100 0.018077 0.001287 0.003240 0.003549 212 | 2110 0.017882 0.001298 0.003274 0.003686 213 | 2120 0.028333 0.001288 0.003351 0.003670 214 | 2130 0.032631 0.001283 0.003374 0.003708 215 | 2140 0.039032 0.001269 0.003413 0.003775 216 | 2150 0.009029 0.001288 0.003421 0.003711 217 | 2160 0.013214 0.001304 0.003549 0.003827 218 | 2170 0.025517 0.001300 0.003565 0.003762 219 | 2180 0.041696 0.001312 0.003429 0.003766 220 | 2190 0.048617 0.001346 0.003443 0.003736 221 | 2200 0.019093 0.001381 0.003442 0.003713 222 | 2210 0.032570 0.001322 0.003555 0.003810 223 | 2220 0.012688 0.001350 0.003545 0.003873 224 | 2230 0.022818 0.001341 0.003565 0.003870 225 | 2240 0.015108 0.001341 0.003656 0.003956 226 | 2250 0.009897 0.001345 0.003689 0.003925 227 | 2260 0.025927 0.001348 0.003626 0.003934 228 | 2270 0.040157 0.001381 0.003688 0.004024 229 | 2280 0.019987 0.001445 0.003732 0.004056 230 | 2290 0.061688 0.001341 0.003712 0.004011 231 | 2300 0.043992 0.001393 0.003739 0.004003 232 | 2310 0.034877 0.001383 0.003768 0.004088 233 | 2320 0.011791 0.001389 0.003835 0.004116 234 | 2330 0.016545 0.001373 0.003859 0.004194 235 | 2340 0.029256 0.001447 0.003831 0.004132 236 | 2350 0.020440 0.001419 0.003885 0.004165 237 | 2360 0.016100 0.001449 0.003905 0.004109 238 | 2370 0.009456 0.001455 0.003911 0.004183 239 | 2380 0.013654 0.001451 0.003930 0.004203 240 | 2390 0.036440 0.001469 0.003914 0.004175 241 | 2400 0.033335 0.001447 0.003942 0.004222 242 | 2410 0.026325 0.001494 0.003894 0.004208 243 | 2420 0.056354 0.001482 0.004039 0.004285 244 | 2430 0.068428 0.001475 0.004022 0.004315 245 | 2440 0.048567 0.001463 0.004057 0.004418 246 | 2450 0.032021 0.001469 0.003988 0.004270 247 | 2460 0.046137 0.001476 0.004071 0.004372 248 | 2470 0.077851 0.001502 0.004134 0.004422 249 | 2480 0.057627 0.001496 0.004023 0.004579 250 | 2490 0.019554 0.001525 0.004123 0.004311 251 | 2500 0.036518 0.001513 0.004149 0.004419 252 | 2510 0.024296 0.001530 0.004194 0.004452 253 | 2520 0.041219 0.001584 0.004185 0.004470 254 | 2530 0.043207 0.001534 0.004221 0.004499 255 | 2540 0.044549 0.001531 0.004276 0.004576 256 | 2550 0.027136 0.001551 0.004307 0.004601 257 | 2560 0.033055 0.001622 0.004278 0.004586 258 | 2570 0.051564 0.001565 0.004329 0.004596 259 | 2580 0.035421 0.001567 0.004341 0.004593 260 | 2590 0.025433 0.001576 0.004307 0.004567 261 | 2600 0.047223 0.001631 0.004389 0.004652 262 | 2610 0.019227 0.001593 0.004377 0.006796 263 | 2620 0.086666 0.001580 0.004400 0.004630 264 | 2630 0.026163 0.001626 0.004422 0.004718 265 | 2640 0.045526 0.001630 0.004430 0.004690 266 | 2650 0.068252 0.001616 0.004399 0.004626 267 | 2660 0.019645 0.001643 0.004530 0.004733 268 | 2670 0.014770 0.001642 0.004539 0.004825 269 | 2680 0.045701 0.001676 0.004480 0.004728 270 | 2690 0.025031 0.001646 0.004560 0.004798 271 | 2700 0.036422 0.001669 0.004618 0.004877 272 | 2710 0.029879 0.001678 0.004611 0.004908 273 | 2720 0.051956 0.001649 0.004619 0.004903 274 | 2730 0.038670 0.001668 0.004642 0.004883 275 | 2740 0.020695 0.001696 0.004689 0.004950 276 | 2750 0.025215 0.001808 0.004727 0.005255 277 | 2760 0.053379 0.001729 0.004730 0.005237 278 | 2770 0.016999 0.002051 0.006636 0.007219 279 | 2780 0.028798 0.001762 0.004823 0.005079 280 | 2790 0.038015 0.001736 0.004798 0.005029 281 | 2800 0.054081 0.001842 0.004856 0.005055 282 | 2810 0.032876 0.001715 0.004816 0.005062 283 | 2820 0.022387 0.001705 0.004863 0.005096 284 | 2830 0.014365 0.001755 0.004847 0.005047 285 | 2840 0.039504 0.001789 0.004851 0.005382 286 | 2850 0.038387 0.001765 0.004914 0.005100 287 | 2860 0.036510 0.001769 0.005013 0.005291 288 | 2870 0.043077 0.001835 0.005008 0.005226 289 | 2880 0.077303 0.001786 0.005035 0.005282 290 | 2890 0.020733 0.001806 0.005056 0.005312 291 | 2900 0.088529 0.001782 0.004971 0.005247 292 | 2910 0.057616 0.001805 0.005037 0.005328 293 | 2920 0.065710 0.001840 0.005017 0.005257 294 | 2930 0.018097 0.001834 0.005085 0.005379 295 | 2940 0.026978 0.001798 0.005174 0.005485 296 | 2950 0.044938 0.001826 0.005188 0.005441 297 | 2960 0.047153 0.001810 0.005187 0.005460 298 | 2970 0.028435 0.001883 0.005106 0.005398 299 | 2980 0.088853 0.001870 0.005205 0.005451 300 | 2990 0.036988 0.001841 0.005368 0.005729 301 | 3000 0.042890 0.001849 0.005194 0.005437 302 | 3010 0.037817 0.001921 0.005223 0.005472 303 | 3020 0.086217 0.001891 0.005183 0.005455 304 | 3030 0.055648 0.001905 0.005354 0.005601 305 | 3040 0.023349 0.001886 0.005300 0.005548 306 | 3050 0.042354 0.001907 0.005305 0.005596 307 | 3060 0.016526 0.001933 0.005469 0.005711 308 | 3070 0.058743 0.001869 0.005444 0.005682 309 | 3080 0.051626 0.001910 0.005595 0.005937 310 | 3090 0.047748 0.001927 0.005525 0.005598 311 | 3100 0.032594 0.001935 0.005436 0.005746 312 | 3110 0.057805 0.001985 0.005626 0.006009 313 | 3120 0.021740 0.001962 0.005564 0.005839 314 | 3130 0.038834 0.001997 0.005533 0.005814 315 | 3140 0.055213 0.001965 0.005566 0.005858 316 | 3150 0.043703 0.002072 0.005897 0.005917 317 | 3160 0.024867 0.001966 0.005535 0.005783 318 | 3170 0.041911 0.001972 0.005521 0.005853 319 | 3180 0.061299 0.001975 0.005649 0.005932 320 | 3190 0.024187 0.002030 0.005595 0.005890 321 | 3200 0.039955 0.002008 0.005614 0.005933 322 | 3210 0.024120 0.002093 0.005661 0.005917 323 | 3220 0.038423 0.002029 0.005608 0.005892 324 | 3230 0.065315 0.001990 0.005638 0.005932 325 | 3240 0.073331 0.002042 0.005670 0.005965 326 | 3250 0.059584 0.002125 0.005554 0.005881 327 | 3260 0.042835 0.002114 0.005691 0.006002 328 | 3270 0.029747 0.002065 0.005690 0.005977 329 | 3280 0.028277 0.002066 0.005565 0.005867 330 | 3290 0.053523 0.002072 0.005691 0.006015 331 | 3300 0.071384 0.002086 0.005668 0.005982 332 | 3310 0.016201 0.002050 0.005642 0.005976 333 | 3320 0.048069 0.002320 0.005804 0.006075 334 | 3330 0.037161 0.002121 0.005721 0.005981 335 | 3340 0.057905 0.002149 0.005611 0.005925 336 | 3350 0.016182 0.002107 0.005738 0.005997 337 | 3360 0.023498 0.002122 0.006032 0.006173 338 | 3370 0.038019 0.002180 0.005800 0.006276 339 | 3380 0.066378 0.002144 0.005805 0.006127 340 | 3390 0.029923 0.002117 0.005827 0.006131 341 | 3400 0.035553 0.002167 0.005833 0.006333 342 | 3410 0.063247 0.002185 0.005841 0.006092 343 | 3420 0.050820 0.002132 0.005741 0.006073 344 | 3430 0.031355 0.002116 0.005840 0.006178 345 | 3440 0.065142 0.002233 0.006029 0.006338 346 | 3450 0.040863 0.002210 0.005992 0.006361 347 | 3460 0.032487 0.002206 0.005819 0.006179 348 | 3470 0.033139 0.002140 0.005834 0.006205 349 | 3480 0.026912 0.002197 0.005915 0.006307 350 | 3490 0.022416 0.002209 0.005998 0.006344 351 | 3500 0.028468 0.002224 0.005943 0.006306 352 | 3510 0.016195 0.002289 0.005926 0.006282 353 | 3520 0.024913 0.002312 0.006033 0.006390 354 | 3530 0.060335 0.002241 0.005921 0.006344 355 | 3540 0.074495 0.002250 0.005967 0.006333 356 | 3550 0.063095 0.002220 0.006071 0.006388 357 | 3560 0.136878 0.002265 0.005870 0.006230 358 | 3570 0.028704 0.002312 0.005970 0.006310 359 | 3580 0.047075 0.002280 0.006032 0.006380 360 | 3590 0.040314 0.002275 0.006047 0.006407 361 | 3600 0.018421 0.002296 0.006030 0.006416 362 | 3610 0.028072 0.002287 0.006167 0.006486 363 | 3620 0.056919 0.002270 0.006016 0.006401 364 | 3630 0.078169 0.002284 0.006166 0.006522 365 | 3640 0.039255 0.002304 0.006040 0.006446 366 | 3650 0.014844 0.002320 0.006027 0.006396 367 | 3660 0.064148 0.002297 0.006181 0.006564 368 | 3670 0.052950 0.002347 0.006107 0.006430 369 | 3680 0.058078 0.002355 0.006139 0.006464 370 | 3690 0.042492 0.002345 0.006261 0.006581 371 | 3700 0.040215 0.002327 0.006160 0.006566 372 | 3710 0.042993 0.002320 0.006164 0.006510 373 | 3720 0.059743 0.002364 0.006203 0.006567 374 | 3730 0.102475 0.002531 0.006064 0.006467 375 | 3740 0.038149 0.002421 0.006157 0.006708 376 | 3750 0.026797 0.002381 0.006163 0.006554 377 | 3760 0.087800 0.002385 0.006146 0.006563 378 | 3770 0.025372 0.002472 0.006236 0.006705 379 | 3780 0.020213 0.002438 0.006266 0.006613 380 | 3790 0.022584 0.002432 0.006365 0.006725 381 | 3800 0.029005 0.002426 0.006148 0.006625 382 | 3810 0.052723 0.002480 0.006300 0.006761 383 | 3820 0.026985 0.002575 0.007098 0.006563 384 | 3830 0.027830 0.002411 0.006238 0.006648 385 | 3840 0.074934 0.002551 0.006168 0.006576 386 | 3850 0.028129 0.002474 0.006319 0.006729 387 | 3860 0.047390 0.002465 0.006273 0.006621 388 | 3870 0.021956 0.002494 0.006468 0.006913 389 | 3880 0.093300 0.002547 0.006527 0.006916 390 | 3890 0.015508 0.002472 0.006380 0.006749 391 | 3900 0.098820 0.002502 0.006266 0.006668 392 | 3910 0.022713 0.002495 0.006364 0.006780 393 | 3920 0.058865 0.002517 0.006476 0.006746 394 | 3930 0.044331 0.002607 0.006680 0.007036 395 | 3940 0.032061 0.002517 0.006444 0.006858 396 | 3950 0.041831 0.002610 0.006433 0.006895 397 | 3960 0.036307 0.002537 0.006568 0.007128 398 | 3970 0.090267 0.002526 0.006476 0.006981 399 | 3980 0.035653 0.002613 0.006519 0.007162 400 | 3990 0.059751 0.002640 0.006514 0.006896 401 | 4000 0.075723 0.002604 0.006740 0.006918 402 | 4010 0.040397 0.002541 0.006441 0.007091 403 | 4020 0.035220 0.002605 0.006433 0.006941 404 | 4030 0.039796 0.002585 0.006503 0.007102 405 | 4040 0.097632 0.002641 0.006538 0.006863 406 | 4050 0.017034 0.002622 0.006840 0.007263 407 | 4060 0.023645 0.002689 0.006485 0.006946 408 | 4070 0.038282 0.002697 0.006530 0.007264 409 | 4080 0.033427 0.002663 0.006609 0.007070 410 | 4090 0.019046 0.002631 0.006624 0.007050 411 | 4100 0.054747 0.002600 0.006622 0.007055 412 | 4110 0.027798 0.002734 0.006652 0.007065 413 | 4120 0.114795 0.002657 0.006622 0.007918 414 | 4130 0.025020 0.002728 0.006873 0.007002 415 | 4140 0.036994 0.002678 0.006588 0.008137 416 | 4150 0.046283 0.003661 0.010146 0.011314 417 | 4160 0.030034 0.002751 0.006787 0.007272 418 | 4170 0.018300 0.002781 0.006645 0.007019 419 | 4180 0.107629 0.002662 0.006703 0.007163 420 | 4190 0.063637 0.002739 0.006969 0.007523 421 | 4200 0.033594 0.002759 0.006734 0.007255 422 | 4210 0.021938 0.002723 0.007022 0.007540 423 | 4220 0.038172 0.002870 0.006739 0.007227 424 | 4230 0.087552 0.002780 0.006933 0.007459 425 | 4240 0.043699 0.002790 0.006869 0.007356 426 | 4250 0.051798 0.002792 0.006951 0.007408 427 | 4260 0.017339 0.002737 0.006918 0.007360 428 | 4270 0.023248 0.002763 0.006943 0.007342 429 | 4280 0.054302 0.002761 0.007001 0.007958 430 | 4290 0.044017 0.002856 0.007435 0.007929 431 | 4300 0.025199 0.002870 0.007346 0.007474 432 | 4310 0.042941 0.002848 0.006999 0.007496 433 | 4320 0.030685 0.002870 0.007119 0.007474 434 | 4330 0.066535 0.002825 0.007187 0.007534 435 | 4340 0.021479 0.002871 0.007143 0.007547 436 | 4350 0.035642 0.002843 0.007804 0.008998 437 | 4360 0.080459 0.002887 0.007191 0.007540 438 | 4370 0.022451 0.002824 0.007257 0.007682 439 | 4380 0.027606 0.002802 0.007179 0.007698 440 | 4390 0.063602 0.002918 0.007619 0.008112 441 | 4400 0.062667 0.002851 0.007277 0.007694 442 | 4410 0.099336 0.002807 0.007227 0.007610 443 | 4420 0.043102 0.002913 0.007364 0.007666 444 | 4430 0.014160 0.002906 0.007462 0.007868 445 | 4440 0.016756 0.003035 0.007525 0.007935 446 | 4450 0.074372 0.002919 0.007372 0.007749 447 | 4460 0.062929 0.002956 0.007546 0.008033 448 | 4470 0.109834 0.002962 0.007587 0.008153 449 | 4480 0.017079 0.002927 0.007799 0.008228 450 | 4490 0.028234 0.002913 0.007377 0.007854 451 | 4500 0.055661 0.002930 0.007523 0.007936 452 | 4510 0.056695 0.003009 0.007687 0.008049 453 | 4520 0.020005 0.002911 0.007517 0.007911 454 | 4530 0.039308 0.003009 0.007665 0.008151 455 | 4540 0.047710 0.003002 0.007922 0.008079 456 | 4550 0.143576 0.003042 0.007974 0.009115 457 | 4560 0.051268 0.002981 0.007670 0.008043 458 | 4570 0.044659 0.002995 0.008067 0.008394 459 | 4580 0.077490 0.003049 0.007717 0.008159 460 | 4590 0.016617 0.003015 0.007766 0.008203 461 | 4600 0.076596 0.002999 0.007628 0.008040 462 | 4610 0.034715 0.003074 0.007457 0.008033 463 | 4620 0.049712 0.002970 0.007729 0.008178 464 | 4630 0.029434 0.003090 0.008125 0.008669 465 | 4640 0.038813 0.003168 0.008274 0.008676 466 | 4650 0.034944 0.003013 0.008096 0.008494 467 | 4660 0.074417 0.003152 0.008333 0.008358 468 | 4670 0.033589 0.003179 0.008368 0.008865 469 | 4680 0.031773 0.003163 0.008350 0.008555 470 | 4690 0.038092 0.003292 0.008031 0.008583 471 | 4700 0.048913 0.003096 0.008184 0.008691 472 | 4710 0.042122 0.003147 0.008333 0.008762 473 | 4720 0.029917 0.003103 0.007935 0.008243 474 | 4730 0.079800 0.003085 0.008027 0.008396 475 | 4740 0.147367 0.003069 0.007947 0.008333 476 | 4750 0.124539 0.003096 0.007889 0.008379 477 | 4760 0.031097 0.003140 0.008154 0.008531 478 | 4770 0.052231 0.003178 0.008234 0.008607 479 | 4780 0.018012 0.003124 0.008389 0.008708 480 | 4790 0.060501 0.003264 0.008211 0.008584 481 | 4800 0.056226 0.003171 0.008067 0.008377 482 | 4810 0.053895 0.003166 0.008231 0.008617 483 | 4820 0.060197 0.003237 0.008331 0.008672 484 | 4830 0.136506 0.003162 0.008235 0.008659 485 | 4840 0.026019 0.003224 0.008377 0.008720 486 | 4850 0.027595 0.003142 0.008221 0.008635 487 | 4860 0.043179 0.003308 0.008127 0.008622 488 | 4870 0.044274 0.003242 0.008240 0.008589 489 | 4880 0.019841 0.003187 0.008193 0.008581 490 | 4890 0.062231 0.003180 0.008506 0.009003 491 | 4900 0.133941 0.003173 0.008262 0.008683 492 | 4910 0.076098 0.003247 0.008245 0.008669 493 | 4920 0.031549 0.003181 0.008692 0.009102 494 | 4930 0.027840 0.003362 0.008608 0.008659 495 | 4940 0.122777 0.003413 0.008592 0.008974 496 | 4950 0.048635 0.003273 0.008410 0.008925 497 | 4960 0.077881 0.003371 0.008542 0.008726 498 | 4970 0.040676 0.003242 0.008467 0.008878 499 | 4980 0.033631 0.003406 0.008708 0.009181 500 | 4990 0.065444 0.003278 0.008645 0.009124 501 | 5000 0.048184 0.003373 0.008568 0.009065 502 | 5010 0.052623 0.003357 0.008527 0.008925 503 | 5020 0.099046 0.003278 0.008504 0.008955 504 | 5030 0.030152 0.003363 0.008796 0.009177 505 | 5040 0.075249 0.003302 0.008898 0.009248 506 | 5050 0.040489 0.003331 0.008806 0.009307 507 | 5060 0.048037 0.003303 0.009049 0.009339 508 | 5070 0.020181 0.003370 0.008599 0.009062 509 | 5080 0.044300 0.003376 0.008540 0.008937 510 | 5090 0.024865 0.003345 0.008575 0.009010 511 | 5100 0.042647 0.003346 0.008546 0.009028 512 | 5110 0.036611 0.004109 0.012701 0.013464 513 | 5120 0.070298 0.003432 0.008762 0.009192 514 | 5130 0.020335 0.003389 0.008764 0.009129 515 | 5140 0.047088 0.003418 0.009158 0.009429 516 | 5150 0.037172 0.003450 0.008678 0.009027 517 | 5160 0.062811 0.003394 0.008846 0.009313 518 | 5170 0.126817 0.003399 0.008861 0.009269 519 | 5180 0.051448 0.003458 0.008905 0.009317 520 | 5190 0.050133 0.003427 0.008940 0.009250 521 | 5200 0.028399 0.003446 0.008950 0.009360 522 | 5210 0.028926 0.003515 0.009151 0.009458 523 | 5220 0.123933 0.003427 0.009097 0.009444 524 | 5230 0.098270 0.003427 0.009063 0.009524 525 | 5240 0.093663 0.003446 0.009007 0.009404 526 | 5250 0.062843 0.003422 0.008999 0.009392 527 | 5260 0.069705 0.003442 0.009059 0.009429 528 | 5270 0.041734 0.003471 0.008979 0.009287 529 | 5280 0.033794 0.003521 0.009115 0.009519 530 | 5290 0.039382 0.003457 0.009191 0.009622 531 | 5300 0.077985 0.003488 0.009327 0.009697 532 | 5310 0.060102 0.003552 0.009306 0.009696 533 | 5320 0.049033 0.003619 0.009288 0.009633 534 | 5330 0.215095 0.003530 0.009223 0.009615 535 | 5340 0.184572 0.003656 0.009398 0.009816 536 | 5350 0.047381 0.003544 0.009272 0.009652 537 | 5360 0.042211 0.003593 0.009094 0.009549 538 | 5370 0.056832 0.003596 0.009339 0.009628 539 | 5380 0.052969 0.003639 0.009386 0.009829 540 | 5390 0.066164 0.003571 0.009605 0.010156 541 | 5400 0.040623 0.003627 0.009648 0.010131 542 | 5410 0.032671 0.003628 0.009511 0.009970 543 | 5420 0.044952 0.003606 0.009419 0.009869 544 | 5430 0.101021 0.003629 0.009697 0.010067 545 | 5440 0.109144 0.003579 0.009534 0.009813 546 | 5450 0.040901 0.003747 0.009632 0.010022 547 | 5460 0.044019 0.003720 0.009686 0.010049 548 | 5470 0.117144 0.003655 0.009690 0.010066 549 | 5480 0.077072 0.003787 0.009612 0.010029 550 | 5490 0.038195 0.003656 0.009554 0.009960 551 | 5500 0.060079 0.003716 0.009759 0.010469 552 | 5510 0.091350 0.003588 0.009686 0.010508 553 | 5520 0.029413 0.004512 0.010581 0.010119 554 | 5530 0.043204 0.003729 0.009827 0.010239 555 | 5540 0.041558 0.003647 0.009901 0.010243 556 | 5550 0.031358 0.003797 0.009805 0.010085 557 | 5560 0.106259 0.003769 0.009749 0.010186 558 | 5570 0.036293 0.003740 0.009818 0.010086 559 | 5580 0.097228 0.003672 0.009818 0.010108 560 | 5590 0.078710 0.003813 0.010032 0.010357 561 | 5600 0.055629 0.003754 0.009685 0.010006 562 | 5610 0.051808 0.003838 0.009797 0.010187 563 | 5620 0.120564 0.003743 0.009877 0.010213 564 | 5630 0.049832 0.003992 0.009970 0.010281 565 | 5640 0.087102 0.003809 0.010402 0.010756 566 | 5650 0.156345 0.003803 0.009958 0.010238 567 | 5660 0.048999 0.003925 0.009952 0.010217 568 | 5670 0.083477 0.003788 0.010222 0.010676 569 | 5680 0.052430 0.003746 0.010068 0.010408 570 | 5690 0.072320 0.003797 0.009975 0.010430 571 | 5700 0.085579 0.003826 0.010242 0.011753 572 | 5710 0.058016 0.003802 0.010047 0.010375 573 | 5720 0.077426 0.003880 0.010321 0.010643 574 | 5730 0.041423 0.003897 0.010200 0.010441 575 | 5740 0.038857 0.004005 0.010408 0.010618 576 | 5750 0.030337 0.003821 0.010287 0.010603 577 | 5760 0.037504 0.003779 0.010201 0.010531 578 | 5770 0.036794 0.003820 0.010175 0.010473 579 | 5780 0.029452 0.003903 0.010186 0.010496 580 | 5790 0.041549 0.003863 0.009959 0.010263 581 | 5800 0.055382 0.003970 0.010298 0.010638 582 | 5810 0.051261 0.003888 0.010503 0.010882 583 | 5820 0.047585 0.004028 0.010458 0.010855 584 | 5830 0.148994 0.003996 0.010520 0.010771 585 | 5840 0.058768 0.003882 0.010484 0.010655 586 | 5850 0.020604 0.003893 0.010538 0.010733 587 | 5860 0.053478 0.003961 0.010550 0.010821 588 | 5870 0.052767 0.004047 0.010409 0.010641 589 | 5880 0.079145 0.003950 0.010522 0.011006 590 | 5890 0.093032 0.003911 0.010328 0.010535 591 | 5900 0.055371 0.003976 0.010597 0.010809 592 | 5910 0.072320 0.003927 0.010689 0.011005 593 | 5920 0.074741 0.004133 0.010733 0.011154 594 | 5930 0.050121 0.003942 0.010681 0.010922 595 | 5940 0.041268 0.004052 0.010765 0.011170 596 | 5950 0.068012 0.004000 0.010752 0.010933 597 | 5960 0.078675 0.004032 0.010493 0.010699 598 | 5970 0.064785 0.004270 0.010777 0.011372 599 | 5980 0.086305 0.004127 0.011099 0.011304 600 | 5990 0.104880 0.004075 0.010642 0.010921 601 | 6000 0.063677 0.004070 0.010679 0.011075 602 | 6010 0.082017 0.004026 0.010868 0.011167 603 | 6020 0.046121 0.004030 0.010793 0.011079 604 | 6030 0.059361 0.004096 0.011001 0.011327 605 | 6040 0.045357 0.004221 0.011067 0.011248 606 | 6050 0.135546 0.004134 0.011430 0.011707 607 | 6060 0.048720 0.004075 0.011325 0.011781 608 | 6070 0.040213 0.004204 0.011408 0.011413 609 | 6080 0.033791 0.004313 0.010901 0.011277 610 | 6090 0.065005 0.004126 0.011317 0.011707 611 | 6100 0.045364 0.004205 0.011333 0.011889 612 | 6110 0.217052 0.004114 0.011871 0.011510 613 | 6120 0.160112 0.004085 0.011269 0.011630 614 | 6130 0.031568 0.004164 0.011090 0.012566 615 | 6140 0.050004 0.004152 0.011353 0.011580 616 | 6150 0.094427 0.004329 0.011396 0.011594 617 | 6160 0.065655 0.004199 0.011031 0.011321 618 | 6170 0.040973 0.004206 0.010847 0.011109 619 | 6180 0.068786 0.004229 0.011831 0.011699 620 | 6190 0.063769 0.004291 0.011376 0.011775 621 | 6200 0.074655 0.004287 0.011240 0.011739 622 | 6210 0.064793 0.004300 0.011524 0.011748 623 | 6220 0.085304 0.004335 0.011456 0.011802 624 | 6230 0.045075 0.004137 0.011188 0.011529 625 | 6240 0.067153 0.004251 0.011718 0.012141 626 | 6250 0.053066 0.004230 0.011421 0.011695 627 | 6260 0.077699 0.004284 0.011129 0.011716 628 | 6270 0.028645 0.004228 0.011573 0.011948 629 | 6280 0.211335 0.004436 0.011668 0.011940 630 | 6290 0.061135 0.004275 0.011307 0.011662 631 | 6300 0.059720 0.004345 0.011189 0.011558 632 | 6310 0.070944 0.004226 0.011184 0.011535 633 | 6320 0.050783 0.004377 0.011488 0.011885 634 | 6330 0.060640 0.004196 0.011445 0.011710 635 | 6340 0.094428 0.004501 0.011356 0.011837 636 | 6350 0.061853 0.004288 0.011410 0.011693 637 | 6360 0.084271 0.004288 0.011488 0.011818 638 | 6370 0.062060 0.004435 0.011669 0.012030 639 | 6380 0.062067 0.004498 0.011459 0.011765 640 | 6390 0.202109 0.004386 0.011606 0.011963 641 | 6400 0.062600 0.004408 0.011263 0.011647 642 | 6410 0.071715 0.004451 0.011283 0.011701 643 | 6420 0.034467 0.004779 0.011524 0.011910 644 | 6430 0.084778 0.004449 0.011456 0.012009 645 | 6440 0.080851 0.004295 0.011513 0.012089 646 | 6450 0.055193 0.004509 0.011600 0.011886 647 | 6460 0.188018 0.004386 0.012041 0.012719 648 | 6470 0.037530 0.004380 0.011577 0.011881 649 | 6480 0.082943 0.004370 0.011550 0.011990 650 | 6490 0.078351 0.004387 0.011396 0.011788 651 | 6500 0.057025 0.004396 0.011380 0.011940 652 | 6510 0.091024 0.004525 0.011772 0.012198 653 | 6520 0.046554 0.004375 0.011498 0.011963 654 | 6530 0.281349 0.004442 0.012033 0.012387 655 | 6540 0.106327 0.004556 0.011915 0.012696 656 | 6550 0.086148 0.004427 0.011804 0.012278 657 | 6560 0.037938 0.004472 0.011454 0.011921 658 | 6570 0.081257 0.004487 0.011375 0.011862 659 | 6580 0.053941 0.004530 0.011537 0.012046 660 | 6590 0.066566 0.004448 0.011677 0.011954 661 | 6600 0.054853 0.004497 0.011848 0.012128 662 | 6610 0.050931 0.004465 0.011757 0.012115 663 | 6620 0.042537 0.004502 0.012069 0.012430 664 | 6630 0.085725 0.004674 0.012085 0.012509 665 | 6640 0.053969 0.004658 0.011637 0.012255 666 | 6650 0.077773 0.004532 0.011718 0.012075 667 | 6660 0.089583 0.004526 0.011601 0.012083 668 | 6670 0.060661 0.004653 0.011708 0.012055 669 | 6680 0.060357 0.004500 0.011861 0.012264 670 | 6690 0.041790 0.004566 0.012303 0.012413 671 | 6700 0.069648 0.004617 0.011747 0.012020 672 | 6710 0.051155 0.004497 0.011894 0.012410 673 | 6720 0.076303 0.004568 0.011818 0.012173 674 | 6730 0.061692 0.004626 0.012475 0.012406 675 | 6740 0.165551 0.004867 0.012202 0.012843 676 | 6750 0.041278 0.004702 0.012226 0.012732 677 | 6760 0.081111 0.004675 0.011749 0.012178 678 | 6770 0.070131 0.004678 0.011748 0.012251 679 | 6780 0.048764 0.004607 0.011942 0.012208 680 | 6790 0.051985 0.004683 0.011772 0.012079 681 | 6800 0.093697 0.004624 0.011964 0.012505 682 | 6810 0.069518 0.004794 0.012135 0.012635 683 | 6820 0.046866 0.004747 0.012190 0.012650 684 | 6830 0.052333 0.004589 0.012047 0.012480 685 | 6840 0.041616 0.004794 0.011856 0.012399 686 | 6850 0.068111 0.004668 0.012401 0.012892 687 | 6860 0.089028 0.004743 0.012447 0.012933 688 | 6870 0.063880 0.004900 0.011718 0.012197 689 | 6880 0.132996 0.004711 0.012176 0.012559 690 | 6890 0.079298 0.004694 0.012376 0.013408 691 | 6900 0.201733 0.004703 0.012104 0.012562 692 | 6910 0.051235 0.004657 0.011765 0.012200 693 | 6920 0.062398 0.004786 0.012041 0.012728 694 | 6930 0.040635 0.004630 0.011606 0.012060 695 | 6940 0.081611 0.004748 0.011882 0.012342 696 | 6950 0.066531 0.004755 0.012128 0.012669 697 | 6960 0.073264 0.004711 0.012020 0.012445 698 | 6970 0.043111 0.004716 0.011800 0.012256 699 | 6980 0.049306 0.004686 0.011943 0.012358 700 | 6990 0.084630 0.004795 0.011989 0.012320 701 | 7000 0.057516 0.004827 0.012120 0.012664 702 | 7010 0.069711 0.004782 0.012052 0.012528 703 | 7020 0.097650 0.004800 0.011923 0.012425 704 | 7030 0.067241 0.004854 0.011839 0.012356 705 | 7040 0.053071 0.004839 0.012160 0.012750 706 | 7050 0.076844 0.004971 0.012154 0.012638 707 | 7060 0.097508 0.004856 0.012058 0.012607 708 | 7070 0.085727 0.004831 0.012324 0.012773 709 | 7080 0.052505 0.004803 0.011901 0.012381 710 | 7090 0.065401 0.004901 0.012515 0.013118 711 | 7100 0.077921 0.004812 0.012143 0.012661 712 | 7110 0.079615 0.004869 0.012050 0.012511 713 | 7120 0.078729 0.004898 0.012409 0.012697 714 | 7130 0.089438 0.004791 0.012195 0.012706 715 | 7140 0.052481 0.004908 0.012301 0.012662 716 | 7150 0.135401 0.004870 0.012705 0.013279 717 | 7160 0.069713 0.004904 0.012143 0.012777 718 | 7170 0.042956 0.004826 0.011937 0.012411 719 | 7180 0.095404 0.004901 0.012048 0.012711 720 | 7190 0.062391 0.005144 0.012551 0.013107 721 | 7200 0.089356 0.004874 0.012061 0.012616 722 | 7210 0.078724 0.004898 0.012065 0.012419 723 | 7220 0.052215 0.004932 0.012550 0.013203 724 | 7230 0.059308 0.005077 0.013337 0.012935 725 | 7240 0.056212 0.004908 0.012749 0.013155 726 | 7250 0.074388 0.004963 0.012888 0.013410 727 | 7260 0.071855 0.004867 0.012407 0.012950 728 | 7270 0.068971 0.004935 0.012881 0.013392 729 | 7280 0.076685 0.004915 0.012271 0.012861 730 | 7290 0.075572 0.004913 0.012524 0.013102 731 | 7300 0.090362 0.004977 0.012621 0.013210 732 | 7310 0.073152 0.004911 0.012261 0.012743 733 | 7320 0.058497 0.004973 0.012451 0.012971 734 | 7330 0.164673 0.004960 0.013018 0.014067 735 | 7340 0.072114 0.004949 0.012332 0.012879 736 | 7350 0.086653 0.005162 0.012521 0.013110 737 | 7360 0.072612 0.004953 0.012297 0.012852 738 | 7370 0.357032 0.005076 0.012862 0.013468 739 | 7380 0.047185 0.005061 0.012488 0.013039 740 | 7390 0.061994 0.005027 0.012271 0.012914 741 | 7400 0.076102 0.005201 0.012608 0.013152 742 | 7410 0.047006 0.005121 0.012448 0.013017 743 | 7420 0.052479 0.005072 0.012612 0.013197 744 | 7430 0.073147 0.005118 0.012384 0.012879 745 | 7440 0.147795 0.005099 0.012882 0.013466 746 | 7450 0.052038 0.005110 0.012460 0.013117 747 | 7460 0.034067 0.004996 0.012492 0.013057 748 | 7470 0.082571 0.005126 0.012925 0.013616 749 | 7480 0.177539 0.005212 0.013258 0.013878 750 | 7490 0.068554 0.005250 0.012498 0.013056 751 | 7500 0.049179 0.005195 0.012628 0.013042 752 | 7510 0.066564 0.005145 0.012573 0.013009 753 | 7520 0.071788 0.005140 0.012704 0.013342 754 | 7530 0.109282 0.005192 0.012707 0.013382 755 | 7540 0.050219 0.005147 0.013223 0.013810 756 | 7550 0.088904 0.005133 0.012773 0.013361 757 | 7560 0.068859 0.005130 0.012772 0.013463 758 | 7570 0.080951 0.005465 0.012918 0.013357 759 | 7580 0.077037 0.005193 0.012730 0.013295 760 | 7590 0.043008 0.005182 0.012721 0.013320 761 | 7600 0.083680 0.005890 0.012819 0.013387 762 | 7610 0.054765 0.005136 0.012579 0.013227 763 | 7620 0.066001 0.005319 0.012621 0.013283 764 | 7630 0.044789 0.005216 0.012848 0.013402 765 | 7640 0.069516 0.005328 0.012698 0.013361 766 | 7650 0.088873 0.005334 0.012783 0.013487 767 | 7660 0.066888 0.005322 0.012583 0.013251 768 | 7670 0.061225 0.005351 0.012740 0.013359 769 | 7680 0.073776 0.005355 0.012622 0.013232 770 | 7690 0.077424 0.005292 0.012953 0.013589 771 | 7700 0.081048 0.005278 0.013076 0.013716 772 | 7710 0.049997 0.005316 0.012933 0.013542 773 | 7720 0.114490 0.005321 0.012903 0.013623 774 | 7730 0.054711 0.005459 0.013322 0.014071 775 | 7740 0.109347 0.005239 0.012965 0.013694 776 | 7750 0.095822 0.005296 0.012888 0.013618 777 | 7760 0.096352 0.005291 0.013067 0.013711 778 | 7770 0.118977 0.005416 0.012930 0.013660 779 | 7780 0.039813 0.005536 0.012770 0.013476 780 | 7790 0.054240 0.006199 0.013179 0.013779 781 | 7800 0.049580 0.005325 0.012914 0.013592 782 | 7810 0.058754 0.005402 0.013093 0.013795 783 | 7820 0.072132 0.005458 0.012931 0.013707 784 | 7830 0.083431 0.005471 0.012827 0.013527 785 | 7840 0.068625 0.005405 0.012832 0.013572 786 | 7850 0.076644 0.005526 0.013047 0.013759 787 | 7860 0.080255 0.005406 0.013233 0.013662 788 | 7870 0.092393 0.005876 0.013039 0.013840 789 | 7880 0.065295 0.005745 0.013255 0.013868 790 | 7890 0.105464 0.005669 0.013129 0.013761 791 | 7900 0.149011 0.005408 0.013904 0.014640 792 | 7910 0.095333 0.005504 0.013299 0.014007 793 | 7920 0.058081 0.005487 0.013934 0.014889 794 | 7930 0.091099 0.005502 0.013375 0.013897 795 | 7940 0.121730 0.005429 0.013056 0.013904 796 | 7950 0.118311 0.005521 0.013975 0.014573 797 | 7960 0.072185 0.005508 0.013215 0.015988 798 | 7970 0.065218 0.005414 0.013160 0.013862 799 | 7980 0.082483 0.005580 0.013099 0.013770 800 | 7990 0.104134 0.005731 0.013003 0.013668 801 | 8000 0.065000 0.005536 0.013053 0.013727 802 | 8010 0.080237 0.005490 0.013149 0.013785 803 | 8020 0.072215 0.006198 0.014144 0.014530 804 | 8030 0.072344 0.005513 0.013315 0.014170 805 | 8040 0.092369 0.006086 0.014051 0.013603 806 | 8050 0.094107 0.005650 0.013488 0.014216 807 | 8060 0.077730 0.005491 0.013456 0.014173 808 | 8070 0.061796 0.005595 0.013123 0.013865 809 | 8080 0.056178 0.005559 0.013314 0.013999 810 | 8090 0.092720 0.005807 0.013225 0.013939 811 | 8100 0.090521 0.005574 0.012913 0.013692 812 | 8110 0.073764 0.005878 0.013328 0.014004 813 | 8120 0.114440 0.005902 0.013705 0.014562 814 | 8130 0.063155 0.005701 0.014493 0.014171 815 | 8140 0.086069 0.005724 0.013288 0.014010 816 | 8150 0.198338 0.005593 0.014568 0.014773 817 | 8160 0.072935 0.005668 0.013584 0.014336 818 | 8170 0.087754 0.005612 0.013438 0.014129 819 | 8180 0.100328 0.005690 0.014265 0.014845 820 | 8190 0.069364 0.005753 0.013651 0.014385 821 | 8200 0.070376 0.005805 0.013468 0.014272 822 | 8210 0.051073 0.005697 0.013449 0.014246 823 | 8220 0.079074 0.005709 0.013867 0.014597 824 | 8230 0.071797 0.005753 0.013701 0.014503 825 | 8240 0.067412 0.005812 0.013543 0.014330 826 | 8250 0.176088 0.005629 0.014516 0.015309 827 | 8260 0.178569 0.005671 0.014824 0.015460 828 | 8270 0.096512 0.005739 0.013319 0.014101 829 | 8280 0.055141 0.005714 0.013893 0.014571 830 | 8290 0.074275 0.006222 0.013715 0.014862 831 | 8300 0.051852 0.005883 0.013908 0.014486 832 | 8310 0.077123 0.005909 0.014137 0.014622 833 | 8320 0.077783 0.005888 0.015074 0.015629 834 | 8330 0.071839 0.005924 0.013995 0.014516 835 | 8340 0.079958 0.005854 0.014063 0.014575 836 | 8350 0.085895 0.005925 0.014539 0.015335 837 | 8360 0.055990 0.005749 0.013952 0.014955 838 | 8370 0.051123 0.005810 0.014060 0.014617 839 | 8380 0.054749 0.005879 0.014158 0.015061 840 | 8390 0.037757 0.005999 0.014423 0.015175 841 | 8400 0.127041 0.005811 0.014406 0.015906 842 | 8410 0.054327 0.005925 0.014422 0.014906 843 | 8420 0.118244 0.005900 0.014050 0.014848 844 | 8430 0.118951 0.005810 0.015312 0.016116 845 | 8440 0.085571 0.006043 0.014396 0.015610 846 | 8450 0.091445 0.006307 0.014841 0.015080 847 | 8460 0.079562 0.006201 0.014292 0.015010 848 | 8470 0.084296 0.006005 0.013922 0.014567 849 | 8480 0.098505 0.005917 0.014291 0.015006 850 | 8490 0.055797 0.006170 0.014153 0.014839 851 | 8500 0.087442 0.005772 0.014478 0.015198 852 | 8510 0.069060 0.005869 0.014408 0.015151 853 | 8520 0.091558 0.006046 0.014496 0.015223 854 | 8530 0.058611 0.005859 0.014150 0.014789 855 | 8540 0.088393 0.005882 0.014533 0.015367 856 | 8550 0.106303 0.005883 0.014084 0.015129 857 | 8560 0.064800 0.005982 0.014179 0.014876 858 | 8570 0.122174 0.006026 0.014604 0.015300 859 | 8580 0.086720 0.005912 0.014376 0.015234 860 | 8590 0.090456 0.005919 0.014813 0.015654 861 | 8600 0.085137 0.005913 0.014543 0.015556 862 | 8610 0.101941 0.006083 0.014586 0.014749 863 | 8620 0.050875 0.006124 0.014497 0.015175 864 | 8630 0.096694 0.005965 0.014502 0.015251 865 | 8640 0.057746 0.006017 0.014615 0.015439 866 | 8650 0.058718 0.005998 0.014324 0.014972 867 | 8660 0.095075 0.006130 0.014630 0.015445 868 | 8670 0.055255 0.006153 0.014526 0.015324 869 | 8680 0.082235 0.006145 0.014587 0.015519 870 | 8690 0.089099 0.006629 0.014527 0.015247 871 | 8700 0.052299 0.006517 0.014380 0.015506 872 | 8710 0.103171 0.006266 0.014723 0.015458 873 | 8720 0.102206 0.006112 0.014591 0.015363 874 | 8730 0.036599 0.006108 0.014745 0.015511 875 | 8740 0.094533 0.006063 0.014698 0.015301 876 | 8750 0.081525 0.006201 0.015193 0.015480 877 | 8760 0.121578 0.005939 0.015326 0.016046 878 | 8770 0.156033 0.005990 0.016842 0.017426 879 | 8780 0.045788 0.005988 0.014674 0.015371 880 | 8790 0.101319 0.006100 0.015116 0.015804 881 | 8800 0.078838 0.006056 0.014883 0.015491 882 | 8810 0.094517 0.006171 0.014799 0.015520 883 | 8820 0.065574 0.006120 0.015195 0.015867 884 | 8830 0.057076 0.006024 0.015199 0.015929 885 | 8840 0.067638 0.006144 0.015217 0.016615 886 | 8850 0.079394 0.006100 0.016554 0.016429 887 | 8860 0.095390 0.006157 0.015224 0.016000 888 | 8870 0.078808 0.006266 0.015266 0.015900 889 | 8880 0.089467 0.006366 0.015285 0.016031 890 | 8890 0.097315 0.006243 0.015410 0.015996 891 | 8900 0.065574 0.006158 0.015144 0.015706 892 | 8910 0.105500 0.006221 0.015152 0.015818 893 | 8920 0.096948 0.006226 0.015263 0.015893 894 | 8930 0.096540 0.006197 0.015406 0.016009 895 | 8940 0.049766 0.006126 0.015594 0.016281 896 | 8950 0.098248 0.006231 0.015493 0.016157 897 | 8960 0.069257 0.006165 0.015775 0.016444 898 | 8970 0.103150 0.006308 0.016607 0.016203 899 | 8980 0.093015 0.006377 0.015636 0.016404 900 | 8990 0.112989 0.006285 0.015814 0.016172 901 | 9000 0.079358 0.006162 0.015520 0.016297 902 | 9010 0.065441 0.006227 0.015624 0.015894 903 | 9020 0.056693 0.006345 0.015502 0.016182 904 | 9030 0.110981 0.006443 0.015887 0.016558 905 | 9040 0.053707 0.006245 0.015654 0.016333 906 | 9050 0.101576 0.006419 0.015554 0.016332 907 | 9060 0.122505 0.006275 0.015909 0.016629 908 | 9070 0.076814 0.006264 0.015736 0.016400 909 | 9080 0.083615 0.006455 0.015707 0.016420 910 | 9090 0.104617 0.006338 0.016109 0.016869 911 | 9100 0.094138 0.006460 0.015831 0.016519 912 | 9110 0.110473 0.006547 0.015867 0.016553 913 | 9120 0.076382 0.006388 0.015969 0.016742 914 | 9130 0.042744 0.006546 0.016244 0.016666 915 | 9140 0.105988 0.006311 0.015875 0.016629 916 | 9150 0.123443 0.006306 0.015878 0.016525 917 | 9160 0.054292 0.006409 0.015910 0.016679 918 | 9170 0.084717 0.006367 0.016008 0.016588 919 | 9180 0.103645 0.006427 0.015841 0.016603 920 | 9190 0.041301 0.006387 0.016442 0.017029 921 | 9200 0.058782 0.006579 0.016076 0.016769 922 | 9210 0.079699 0.006772 0.015920 0.016597 923 | 9220 0.071054 0.006374 0.016014 0.016712 924 | 9230 0.117419 0.006405 0.016336 0.017008 925 | 9240 0.119160 0.006541 0.016217 0.016903 926 | 9250 0.074566 0.006614 0.016598 0.017162 927 | 9260 0.120442 0.006582 0.016210 0.016948 928 | 9270 0.097396 0.006662 0.016927 0.017590 929 | 9280 0.060902 0.006749 0.016728 0.017727 930 | 9290 0.077674 0.006590 0.016637 0.017272 931 | 9300 0.114811 0.006836 0.016641 0.017305 932 | 9310 0.089315 0.006849 0.016592 0.017253 933 | 9320 0.114745 0.006588 0.016922 0.017957 934 | 9330 0.100502 0.006693 0.016649 0.017429 935 | 9340 0.114381 0.006623 0.016653 0.017147 936 | 9350 0.098566 0.006489 0.016984 0.017615 937 | 9360 0.080928 0.006479 0.016661 0.017241 938 | 9370 0.053770 0.006518 0.016744 0.017583 939 | 9380 0.075973 0.006610 0.016802 0.017480 940 | 9390 0.100014 0.006801 0.016853 0.017539 941 | 9400 0.076224 0.006617 0.016892 0.020173 942 | 9410 0.073590 0.006975 0.018067 0.018744 943 | 9420 0.043092 0.006568 0.017038 0.017626 944 | 9430 0.090435 0.006470 0.016816 0.017586 945 | 9440 0.063244 0.006759 0.017612 0.019030 946 | 9450 0.084691 0.006652 0.017170 0.017927 947 | 9460 0.067609 0.006819 0.017895 0.018089 948 | 9470 0.125636 0.006479 0.017209 0.017817 949 | 9480 0.094884 0.006758 0.017731 0.018329 950 | 9490 0.106080 0.006815 0.017412 0.018070 951 | 9500 0.093168 0.007107 0.017377 0.017840 952 | 9510 0.094940 0.006846 0.017329 0.017985 953 | 9520 0.071572 0.006856 0.017321 0.018017 954 | 9530 0.096520 0.006722 0.017211 0.017836 955 | 9540 0.103679 0.006707 0.017136 0.017758 956 | 9550 0.124520 0.006692 0.017705 0.018241 957 | 9560 0.088906 0.006720 0.017272 0.017901 958 | 9570 0.097870 0.006850 0.017404 0.018135 959 | 9580 0.046125 0.006757 0.017674 0.018211 960 | 9590 0.094349 0.006953 0.017613 0.018252 961 | 9600 0.102275 0.006714 0.017767 0.018397 962 | 9610 0.072027 0.006826 0.017829 0.018376 963 | 9620 0.121130 0.006647 0.017640 0.018250 964 | 9630 0.120027 0.006804 0.017880 0.018576 965 | 9640 0.140595 0.006956 0.017860 0.018403 966 | 9650 0.072752 0.006807 0.017880 0.018293 967 | 9660 0.086717 0.006850 0.018056 0.018892 968 | 9670 0.072812 0.006701 0.018107 0.018654 969 | 9680 0.033701 0.006929 0.018065 0.018498 970 | 9690 0.088285 0.006876 0.018036 0.018822 971 | 9700 0.107282 0.007395 0.018526 0.019015 972 | 9710 0.107741 0.006718 0.018645 0.019441 973 | 9720 0.065916 0.006991 0.018573 0.019096 974 | 9730 0.123780 0.006964 0.018475 0.019090 975 | 9740 0.099284 0.006793 0.018317 0.019012 976 | 9750 0.098481 0.007043 0.018482 0.018958 977 | 9760 0.101933 0.006887 0.018691 0.019453 978 | 9770 0.077499 0.006876 0.018749 0.019256 979 | 9780 0.137798 0.006797 0.018695 0.019264 980 | 9790 0.101323 0.006838 0.018643 0.019275 981 | 9800 0.058340 0.006787 0.019172 0.019434 982 | 9810 0.085594 0.006897 0.018876 0.019286 983 | 9820 0.075561 0.007446 0.018823 0.019372 984 | 9830 0.105793 0.007013 0.018908 0.019533 985 | 9840 0.058216 0.006984 0.019192 0.020400 986 | 9850 0.065318 0.006965 0.019862 0.020270 987 | 9860 0.127420 0.006916 0.019285 0.020021 988 | 9870 0.037362 0.006875 0.019616 0.020240 989 | 9880 0.053893 0.007092 0.020698 0.020885 990 | 9890 0.111503 0.007058 0.019910 0.020601 991 | 9900 0.060876 0.007373 0.020475 0.021018 992 | 9910 0.012758 0.007359 0.020673 0.021242 993 | 9920 0.098723 0.007055 0.020436 0.021002 994 | 9930 0.048065 0.007003 0.021272 0.021996 995 | 9940 0.167250 0.007108 0.020901 0.021575 996 | 9950 0.047288 0.007080 0.021791 0.022212 997 | 9960 0.063468 0.006887 0.021752 0.022368 998 | 9970 0.107576 0.007058 0.021424 0.022069 999 | 9980 0.081532 0.007390 0.021585 0.022303 1000 | 9990 0.099561 0.007396 0.021736 0.022388 1001 | 10000 0.105080 0.007982 0.022872 0.023100 1002 | -------------------------------------------------------------------------------- /lab/lab01/draw.py: -------------------------------------------------------------------------------- 1 | # encoding=utf-8 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import math 5 | import sys 6 | 7 | datafile = 'data.txt' 8 | if len(sys.argv) > 1: 9 | datafile = sys.argv[1] 10 | 11 | fig = plt.figure() 12 | ax = fig.add_subplot(121) 13 | ax2 = fig.add_subplot(122) 14 | ax.set(title='t - K', 15 | ylabel='time took in seconds (t)', xlabel='sample size (K)') 16 | 17 | ax2.set(title='log(t) - K', 18 | ylabel='log(t)', xlabel='sample size (K)') 19 | 20 | ys = [[], [], [], []] 21 | ys2 = [[], [], [], []] 22 | with open(datafile, 'r') as f: 23 | line = f.readline() 24 | lo = int(line.split()[0]) 25 | while line: 26 | [k, a, b, c, d] = [float(x) for x in line.split()] 27 | hi = k 28 | ys2[0].append(math.log(max(a, 1e-6))) # 防止时间为0 29 | ys2[1].append(math.log(max(b, 1e-6))) 30 | ys2[2].append(math.log(max(c, 1e-6))) 31 | ys2[3].append(math.log(max(d, 1e-6))) 32 | ys[0].append(a) 33 | ys[1].append(b) 34 | ys[2].append(c) 35 | ys[3].append(d) 36 | line = f.readline() 37 | sz = len(ys[0]) 38 | x = np.linspace(lo, hi, sz) 39 | # y1 = x/100 40 | 41 | ax.plot(x, ys[0], label='BruteForceCH') 42 | ax.plot(x, ys[1], label='GrahamScanCH') 43 | ax.plot(x, ys[2], label='DivAndConCH') 44 | ax.plot(x, ys[3], label='DivAndConCH2') 45 | ax.legend() 46 | ax2.plot(x, ys2[0], label='BruteForceCH') 47 | ax2.plot(x, ys2[1], label='GrahamScanCH') 48 | ax2.plot(x, ys2[2], label='DivAndConCH') 49 | ax2.plot(x, ys2[3], label='DivAndConCH2') 50 | ax2.legend() 51 | plt.show() 52 | -------------------------------------------------------------------------------- /lab/lab01/images/BruteForceCH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab01/images/BruteForceCH.png -------------------------------------------------------------------------------- /lab/lab01/images/DivAndConCH-Merge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab01/images/DivAndConCH-Merge.png -------------------------------------------------------------------------------- /lab/lab01/images/DivAndConCH2-Merge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab01/images/DivAndConCH2-Merge.png -------------------------------------------------------------------------------- /lab/lab01/images/Graham-Scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab01/images/Graham-Scan.png -------------------------------------------------------------------------------- /lab/lab01/images/benchmark-old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab01/images/benchmark-old.png -------------------------------------------------------------------------------- /lab/lab01/images/benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab01/images/benchmark.png -------------------------------------------------------------------------------- /lab/lab01/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "PointsSampler.hpp" 6 | #include "ConvexHull.hpp" 7 | #include "BruteForceCH.hpp" 8 | #include "GrahamScanCH.hpp" 9 | #include "DivAndConCH.hpp" 10 | #include "DivAndConCH2.hpp" 11 | using namespace std; 12 | 13 | template 14 | void printArr(const vector &arr) { 15 | for (const T &t : arr) cout << t << " "; 16 | cout << endl; 17 | } 18 | 19 | vector> time_it(function>()> f) { 20 | auto begin = std::chrono::steady_clock::now(); 21 | auto res = f(); 22 | auto end = std::chrono::steady_clock::now(); 23 | cout << fixed << setprecision(6) 24 | << (std::chrono::duration_cast(end - begin).count()) / 1e6 25 | << " "; 26 | return res; 27 | } 28 | 29 | int main(int argc, char const *argv[]) { 30 | vector> CHs; 31 | CHs.emplace_back(make_unique()); 32 | CHs.emplace_back(make_unique()); 33 | CHs.emplace_back(make_unique()); 34 | CHs.emplace_back(make_unique()); 35 | int step = 10, k0 = 0, k1 = 10000; 36 | // int step = 1, k0 = 0, k1 = 1000; 37 | for (int k = k0; k <= k1; k += step) { 38 | vector> P = PointsSampler::sample_k(k); 39 | // P = {{29,45}, {75,8}, {32,50}, {78,78}, {24,26}}; 40 | // cout << "sample size: " << k << endl; 41 | // printArr(P); 42 | cout << P.size() << " "; 43 | bool flag = false; 44 | size_t pre = 0; 45 | for (auto& ch: CHs) { 46 | ch->upadte(P); 47 | auto res = time_it(bind(&ConvexHull::work, ref(*ch))); 48 | // printArr(res); 49 | if (flag) { 50 | if (res.size() != pre) { 51 | printArr(res); 52 | printArr(P); 53 | return -1; // 发现求得凸包大小不同,算法实现有误 54 | } 55 | } 56 | pre = res.size(); 57 | flag = true; 58 | } 59 | cout << endl; 60 | } 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /lab/lab01/testcases.txt: -------------------------------------------------------------------------------- 1 | {{0,0}, {1,1}, {2,2}, {3,3}}; // 四点共线 2 | {{0,0}, {1,1}, {2,2}}; // 三点共线 3 | {{0,0}, {1,1}}; // 二点 4 | {{0,0}}; // 一点 5 | {}; // 0个点 6 | -------------------------------------------------------------------------------- /lab/lab02/README.md: -------------------------------------------------------------------------------- 1 | # 实验二: 搜索算法 2 | 3 | * 实现了单双向的`A*`搜索算法 4 | * 实现了可视化 5 | * 可通过鼠标键盘控制 6 | * 地图并可以保存到文件,方便下次直接使用 7 | 8 | ## 使用说明 9 | 10 | 两个程序`astar.py`和`biastar.py`分别对应了单向和双向的`A*`搜索,程序的使用方法完全一致 11 | 12 | * `pip install pygame` 安装依赖pygame 13 | * `python astar.py [mapfile.txt]` 14 | * 这里的地图文件可以通过按`s`键保存得到,参考下面的COMMANDS 15 | * 实验中要求的两个地图我已经保存了,对应`map1.txt`和`map2.txt`: `python astar.py map1.txt`运行 16 | 17 | ## COMMANDS 操作方式 18 | 19 | * 鼠标左键 设置某个块儿 20 | * 默认情况或者按了`0`之后,左键会把点击的块儿设置为**起点**(不存在起点),**终点**(存在起点不存在终点),**障碍**(已存在起点和终点) 21 | * 按了`1`之后,为点击的块儿设置**额外代价**(经过这个块儿会有额外代价) 22 | * 按了`2`之后同理,只是额外代价不同 23 | * 额外的代价见代码中的变量: `EXTRA_COST = [0, 2, 4]`,如果还想有更多的代价往后面加就行了,因为采用一个数字按键对应不同代价,所以最多可以有9种额外代价,对应按键/下标: `1-9`. 24 | 25 | * 鼠标右键 清除某个块儿 26 | 27 | * 键盘`q` 退出程序 28 | 29 | * 键盘`s` 保存当前地图到当前目录,按时间命名 30 | 31 | * `python astar.py map01.txt`加载地图`map01.txt`运行 32 | 33 | * 下面对地图文件的格式做说明,比如对于第二个地图`map02.txt` 34 | 35 | ```txt 36 | 20 40 34 37 | 0 0 0 -1 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 T2 2 2 2 2 38 | 0 0 0 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 39 | -1 -1 -1 -1 -1 -1 0 -1 -1 -1 -1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 2 2 2 2 2 2 40 | 0 0 0 0 0 0 0 0 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 2 2 2 2 0 0 0 41 | 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 2 2 0 0 0 0 42 | 0 0 0 0 0 0 0 -1 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 0 0 0 0 0 43 | 0 0 -1 -1 -1 -1 -1 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 0 0 0 0 0 44 | 0 0 -1 0 0 -1 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 -1 0 0 0 45 | 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 46 | 0 0 0 0 0 -1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 -1 0 0 0 47 | 0 0 -1 0 S0 -1 0 -1 -1 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 -1 0 0 0 1 1 0 1 1 0 0 0 48 | 0 0 -1 -1 -1 -1 0 0 -1 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0 0 0 -1 1 0 1 1 0 0 0 0 49 | 0 0 0 -1 0 0 0 0 -1 0 0 0 -1 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 50 | 0 0 0 -1 0 0 0 0 -1 -1 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 51 | 0 0 0 -1 0 0 0 0 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 52 | 0 0 0 -1 -1 -1 -1 -1 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 53 | 0 0 0 -1 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 54 | 0 0 0 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 55 | 0 0 0 -1 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 56 | 0 0 0 -1 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 57 | ``` 58 | 59 | 第一行三个整数`m,n,gap`分别表示地图格子有`m`行,`n`列,每个格子都是`gap*gap`像素大小的正方形块儿 60 | 61 | 接下来的m行n列整数具体代表了地图信息,一共有三种格子: 62 | 63 | * `-1`表示障碍 64 | 65 | * `0`表示可以行走的块,并且没有额外代价 66 | 67 | * `1-9`代表了可以行走的块,但是具有额外代价,这个数字代表了额外代价的下标,比如程序中的额外代价定义如下,表示下标1对应代价为2,下标2对应代价为4 68 | 69 | ```python 70 | # LAND, RIVER, DESERT 71 | EXTRA_COST = [0, 2, 4] 72 | ``` 73 | 74 | * 键盘`` 开始/暂停/继续路径搜索 75 | 76 | * 键盘`c` 清除搜索痕迹(搜索过程中不可用) 77 | 78 | * 键盘`n` 清空地图(搜索过程中不可用) 79 | 80 | ## 运行效果 81 | 82 | * 单向`A*`,使用`map01.txt` 83 | 84 | ![astar - map01.txt](images/map01-astar.png) 85 | 86 | * 双向`A*`,使用`map01.txt` 87 | 88 | ![biastar - map01.txt](images/map01-biastar.png) 89 | 90 | * 单向`A*`,使用`map02.txt` 91 | 92 | ![astar - map02.txt](images/map02-astar.png) 93 | 94 | * 双向`A*`,使用`map02.txt` 95 | 96 | ![biastar - map02.txt](images/map02-biastar.png) 97 | 98 | ## REFS 99 | 100 | * 可视化代码借鉴 [ytb: A* Pathfinding Visualization Tutorial](https://www.youtube.com/watch?v=JtiK0DOeI4A) 101 | -------------------------------------------------------------------------------- /lab/lab02/astar.py: -------------------------------------------------------------------------------- 1 | # from os import close 2 | import sys 3 | import pygame 4 | import math 5 | import time 6 | from queue import PriorityQueue 7 | import heapq 8 | 9 | # Colors 10 | RED = (255, 0, 0) 11 | GREEN = (0, 255, 0) 12 | LIGHT_GREEN = (152, 251, 152) 13 | BLUE = (0, 255, 0) 14 | LIGHT_BLUE = (175, 238, 238) 15 | YELLOW = (255, 255, 0) 16 | WHITE = (255, 255, 255) 17 | BLACK = (0, 0, 0) 18 | PURPLE = (128, 0, 128) 19 | ORANGE = (255, 165 ,0) 20 | GREY = (128, 128, 128) 21 | TURQUOISE = (64, 224, 208) 22 | 23 | COLORS = { 24 | 'closed': LIGHT_BLUE, 25 | 'open': LIGHT_GREEN, 26 | 'barrier': BLACK, 27 | # 'desert': YELLOW, 28 | # 'river': BLUE, 29 | 'land': WHITE, 30 | 'start': ORANGE, 31 | 'end': RED 32 | } 33 | 34 | # LAND, RIVER, DESERT 35 | EXTRA_COST = [0, 2, 4] 36 | 37 | def bye(): 38 | pygame.quit() 39 | exit() 40 | 41 | class Spot: 42 | def __init__(self, row, col, gap, ROWS, COLS, cost_idx = 0): 43 | self.row = row 44 | self.col = col 45 | self.y = row * gap 46 | self.x = col * gap 47 | self.color = COLORS['land'] 48 | self.cost_idx = cost_idx 49 | self.neighbors = [] 50 | self.gap = gap 51 | self.total_rows = ROWS 52 | self.total_cols = COLS 53 | 54 | def get_pos(self): 55 | return self.row, self.col 56 | 57 | def is_closed(self): 58 | return self.color == COLORS['closed'] 59 | 60 | def is_open(self): 61 | return self.color == COLORS['open'] 62 | 63 | def is_barrier(self): 64 | return self.color == COLORS['barrier'] 65 | 66 | def is_start(self): 67 | # return hasattr(self, 'start') 68 | return self.color == COLORS['start'] 69 | 70 | def is_end(self): 71 | # return hasattr(self, 'end') 72 | return self.color == COLORS['end'] 73 | 74 | def reset(self): 75 | self.color = COLORS['land'] 76 | self.cost_idx = 0 77 | 78 | def reset_color(self): 79 | self.color = COLORS['land'] 80 | 81 | def make_start(self): 82 | self.color = COLORS['start'] 83 | 84 | def make_end(self): 85 | self.color = COLORS['end'] 86 | 87 | def make_closed(self): 88 | self.color = COLORS['closed'] 89 | 90 | def make_open(self): 91 | if not self.is_end(): self.color = COLORS['open'] 92 | 93 | def make_barrier(self): 94 | self.color = COLORS['barrier'] 95 | self.cost_idx = 0 # ? 96 | 97 | def make_path(self): 98 | if not self.is_start(): self.color = YELLOW 99 | # if not self.is_start() and not self.is_end(): self.color = YELLOW 100 | 101 | def draw(self, win): 102 | # 绘制矩形 103 | pygame.draw.rect(win, self.color, (self.x, self.y, self.gap, self.gap)) 104 | if self.cost_idx: 105 | font = pygame.font.Font(None, self.gap) 106 | text = font.render(str(EXTRA_COST[self.cost_idx]), 1, GREY) 107 | textpos = text.get_rect() 108 | textpos.topleft = (self.x + self.gap // 4, self.y + self.gap // 4) 109 | win.blit(text, textpos) 110 | # if self.is_start(): 111 | # font = pygame.font.Font(None, self.gap*3//2) 112 | # text = font.render("S", 1, GREY) 113 | # textpos = text.get_rect() 114 | # textpos.topleft = (self.x + self.gap // 4, self.y + self.gap // 4) 115 | # # textpos.bottomright = (self.x + self.gap // 2, self.y + self.gap // 2) 116 | # win.blit(text, textpos) 117 | # # print("textpos:", textpos) 118 | # if self.is_end(): 119 | # font = pygame.font.Font(None, self.gap*3//2) 120 | # text = font.render("T", 1, GREY) 121 | # textpos = text.get_rect() 122 | # textpos.topleft = (self.x + self.gap // 4, self.y + self.gap // 4) 123 | # # textpos.bottomright = (self.x + self.gap // 2, self.y + self.gap // 2) 124 | # win.blit(text, textpos) 125 | 126 | def update_neighbors(self, grid): 127 | self.neighbors = [] 128 | di = [0, 0, -1, 1] 129 | dj = [1, -1, 0, 0] 130 | K = 4 131 | di = [0, 0, -1, -1, -1, 1, 1, 1] 132 | dj = [1, -1, -1, 0, 1, -1, 0, 1] 133 | K = 8 134 | for k in range(K): 135 | ni = self.row + di[k] 136 | nj = self.col + dj[k] 137 | if ni >= 0 and ni < self.total_rows \ 138 | and nj >= 0 and nj < self.total_cols \ 139 | and not grid[ni][nj].is_barrier(): 140 | self.neighbors.append(grid[ni][nj]) 141 | 142 | def __lt__(self, other): 143 | return self.row * self.total_cols + self.col 144 | # return False # ? 145 | 146 | 147 | def h(p1, p2): 148 | x1, y1 = p1 149 | x2, y2 = p2 150 | d = min(abs(x1 - x2), abs(y1 - y2)) 151 | return math.sqrt(2)*d + abs(x1 - x2) + abs(y1 - y2) - 2*d 152 | 153 | 154 | def reconstruct_path(came_from, current, draw): 155 | while current in came_from: 156 | current = came_from[current] 157 | current.make_path() 158 | draw() 159 | 160 | 161 | def astar(draw, grid, start, end): 162 | # count = 0 163 | open_set = [] 164 | heapq.heappush(open_set, (0, start)) 165 | came_from = {} 166 | g_score = {spot: float("inf") for row in grid for spot in row} 167 | g_score[start] = 0 168 | f_score = {spot: float("inf") for row in grid for spot in row} 169 | f_score[start] = h(start.get_pos(), end.get_pos()) 170 | 171 | open_set_hash = {start} 172 | 173 | pause = 0 174 | while len(open_set): 175 | for event in pygame.event.get(): 176 | if event.type == pygame.QUIT: 177 | bye() 178 | elif event.type == pygame.KEYDOWN: 179 | if event.key == pygame.K_SPACE: 180 | pause ^= 1 181 | elif event.key == pygame.K_q: 182 | bye() 183 | 184 | if pause: continue 185 | current = heapq.heappop(open_set)[1] 186 | open_set_hash.remove(current) 187 | 188 | if current == end: 189 | reconstruct_path(came_from, end, draw) 190 | # end.make_end() 191 | return True 192 | 193 | for neighbor in current.neighbors: 194 | temp_g_score = g_score[current] + (1 if neighbor.row == current.row or neighbor.col == current.col else math.sqrt(2)) 195 | if neighbor.cost_idx: temp_g_score += EXTRA_COST[neighbor.cost_idx] 196 | if temp_g_score < g_score[neighbor]: 197 | came_from[neighbor] = current 198 | g_score[neighbor] = temp_g_score 199 | f_score[neighbor] = temp_g_score + h(neighbor.get_pos(), end.get_pos()) 200 | if neighbor not in open_set_hash: 201 | # count += 1 202 | heapq.heappush(open_set, (f_score[neighbor], neighbor)) 203 | open_set_hash.add(neighbor) 204 | neighbor.make_open() 205 | 206 | draw() 207 | 208 | if current != start: 209 | current.make_closed() 210 | 211 | return False 212 | 213 | 214 | def make_grid(rows, cols, gap): 215 | grid = [] 216 | for i in range(rows): 217 | grid.append([]) 218 | for j in range(cols): 219 | spot = Spot(i, j, gap, rows, cols) 220 | grid[i].append(spot) 221 | return grid 222 | 223 | 224 | # 画网格线 225 | def draw_grid(win, rows, cols, gap): 226 | width = cols * gap 227 | height = rows * gap 228 | for i in range(rows): 229 | # 横线 230 | pygame.draw.line(win, GREY, (0, i * gap), (width, i * gap)) 231 | # 竖线 232 | for j in range(cols): 233 | pygame.draw.line(win, GREY, (j * gap, 0), (j * gap, height)) 234 | 235 | 236 | def draw(win, grid, rows, cols, gap): 237 | # 背景填充为WHITE 238 | # 需要吗? 239 | win.fill(WHITE) 240 | 241 | # 每个格子填充对应颜色 242 | for row in grid: 243 | for spot in row: 244 | spot.draw(win) 245 | # 画网格线 246 | draw_grid(win, rows, cols, gap) 247 | pygame.display.update() 248 | 249 | # x 水平向右 250 | # y 水平向下 251 | def get_clicked_pos(pos, gap): 252 | x, y = pos 253 | 254 | row = y // gap 255 | col = x // gap 256 | 257 | return row, col 258 | 259 | def clear_trace(grid): 260 | for row in grid: 261 | for spot in row: 262 | if not spot.is_start() and not spot.is_end() and not spot.is_barrier(): 263 | spot.reset_color() 264 | 265 | def save_map(filename, grid): 266 | with open(filename, 'w') as f: 267 | rows = grid[0][0].total_rows 268 | cols = grid[0][0].total_cols 269 | gap = grid[0][0].gap 270 | f.write("{} {} {}\n".format(rows, cols, gap)) 271 | for row in grid: 272 | for spot in row: 273 | if spot.is_barrier(): 274 | s = '-1' 275 | else: 276 | if spot.is_start(): 277 | s = 'S' 278 | elif spot.is_end(): 279 | s = 'T' 280 | else: 281 | s = '' 282 | s += str(spot.cost_idx) 283 | f.write(s+' ') 284 | f.write('\n') 285 | 286 | def load_map(filename): 287 | grid = [] 288 | f = open(filename, 'r') 289 | [rows, cols, gap] = [ int(s) for s in f.readline().split()] 290 | start = None 291 | end = None 292 | for i in range(rows): 293 | line = f.readline().split() 294 | grid.append([]) 295 | for j in range(cols): 296 | grid[i].append(Spot(i, j, gap, rows, cols)) 297 | cost_idx = 0 298 | if line[j][0] == 'S': 299 | grid[i][j].make_start() 300 | start = grid[i][j] 301 | cost_idx = int(line[j][1:]) 302 | elif line[j][0] == 'T': 303 | grid[i][j].make_end() 304 | end = grid[i][j] 305 | cost_idx = int(line[j][1:]) 306 | elif line[j] == '-1': 307 | grid[i][j].make_barrier() 308 | else: 309 | cost_idx = int(line[j]) 310 | grid[i][j].cost_idx = cost_idx 311 | f.close() 312 | return grid, start, end, rows, cols, gap 313 | 314 | def main(win, ROWS, COLS, GAP, grid, start = None, end = None): 315 | # 黄色格子代表沙漠,经过它的代价为 4 -- idx 2 316 | # 蓝色格子代表溪流,经过它的代价为 2 -- idx 1 317 | # 白色格子为普通地形,经过它的代价为 0 -- idx 0 318 | cost_idx = 0 319 | 320 | run = True 321 | while run: 322 | draw(win, grid, ROWS, COLS, GAP) 323 | for event in pygame.event.get(): 324 | if event.type == pygame.QUIT: 325 | run = False 326 | 327 | if pygame.mouse.get_pressed()[0]: # LEFT 328 | pos = pygame.mouse.get_pos() 329 | row, col = get_clicked_pos(pos, GAP) 330 | print("pressed: ", row, col) 331 | spot = grid[row][col] 332 | if cost_idx: 333 | if not spot.is_barrier(): spot.cost_idx = cost_idx 334 | continue 335 | if not start and spot != end: 336 | start = spot 337 | start.make_start() 338 | 339 | elif not end and spot != start: 340 | end = spot 341 | end.make_end() 342 | 343 | elif spot != end and spot != start: 344 | spot.make_barrier() 345 | 346 | elif pygame.mouse.get_pressed()[2]: # RIGHT 347 | pos = pygame.mouse.get_pos() 348 | row, col = get_clicked_pos(pos, GAP) 349 | spot = grid[row][col] 350 | spot.reset() 351 | if spot == start: 352 | start = None 353 | elif spot == end: 354 | end = None 355 | 356 | if event.type == pygame.KEYDOWN: 357 | print("key", event.key) 358 | if event.key == pygame.K_SPACE and start and end: 359 | for row in grid: 360 | for spot in row: 361 | spot.update_neighbors(grid) 362 | clear_trace(grid) 363 | astar(lambda: draw(win, grid, ROWS, COLS, GAP), grid, start, end) 364 | elif event.key >= pygame.K_0 and event.key <= pygame.K_9: 365 | idx = event.key - pygame.K_0 366 | if idx < len(EXTRA_COST): 367 | cost_idx = idx 368 | # save map 369 | elif event.key == pygame.K_s: 370 | filename = time.strftime("%Y%m%d-%H%M%S.txt") 371 | save_map(filename, grid) 372 | # new grid 373 | elif event.key == pygame.K_n: 374 | start = None 375 | end = None 376 | grid = make_grid(ROWS, COLS, GAP) 377 | # clear trace 378 | elif event.key == pygame.K_c: 379 | clear_trace(grid) 380 | # `q` to quit 381 | elif event.key == pygame.K_q: 382 | run = False 383 | 384 | pygame.quit() 385 | 386 | if __name__ == "__main__": 387 | # 一个ROW*ROW的网格,ROW*gap = WIDTH像素 388 | # gap是每个方格的宽度 389 | ROWS = 20 390 | COLS = 40 391 | GAP = 34 392 | 393 | if len(sys.argv) > 1: 394 | grid, start, end, ROWS, COLS, GAP = load_map(sys.argv[1]) 395 | else: 396 | start = None 397 | end = None 398 | grid = make_grid(ROWS, COLS, GAP) 399 | 400 | # 设置窗口宽和高 401 | pygame.init() 402 | WIDTH = COLS*GAP 403 | HEIGHT = ROWS*GAP 404 | WIN = pygame.display.set_mode((WIDTH, HEIGHT)) 405 | pygame.display.set_caption("A* Path Finding Algorithm") 406 | 407 | main(WIN, ROWS, COLS, GAP, grid, start, end) 408 | -------------------------------------------------------------------------------- /lab/lab02/biastar.py: -------------------------------------------------------------------------------- 1 | # from os import close 2 | import sys 3 | import pygame 4 | import math 5 | import time 6 | from queue import PriorityQueue 7 | import heapq 8 | 9 | # Colors 10 | RED = (255, 0, 0) 11 | GREEN = (0, 255, 0) 12 | LIGHT_GREEN = (152, 251, 152) 13 | BLUE = (0, 255, 0) 14 | LIGHT_BLUE = (175, 238, 238) 15 | YELLOW = (255, 255, 0) 16 | WHITE = (255, 255, 255) 17 | BLACK = (0, 0, 0) 18 | PURPLE = (128, 0, 128) 19 | ORANGE = (255, 165 ,0) 20 | GREY = (128, 128, 128) 21 | TURQUOISE = (64, 224, 208) 22 | 23 | COLORS = { 24 | 'closed': LIGHT_BLUE, 25 | 'open': LIGHT_GREEN, 26 | 'barrier': BLACK, 27 | # 'desert': YELLOW, 28 | # 'river': BLUE, 29 | 'land': WHITE, 30 | 'start': ORANGE, 31 | 'end': RED 32 | } 33 | 34 | # LAND, RIVER, DESERT 35 | EXTRA_COST = [0, 2, 4] 36 | 37 | def bye(): 38 | pygame.quit() 39 | exit() 40 | 41 | class Spot: 42 | def __init__(self, row, col, gap, ROWS, COLS, cost_idx = 0): 43 | self.row = row 44 | self.col = col 45 | self.y = row * gap 46 | self.x = col * gap 47 | self.color = COLORS['land'] 48 | self.cost_idx = cost_idx 49 | self.neighbors = [] 50 | self.gap = gap 51 | self.total_rows = ROWS 52 | self.total_cols = COLS 53 | 54 | def get_pos(self): 55 | return self.row, self.col 56 | 57 | def is_closed(self): 58 | return self.color == COLORS['closed'] 59 | 60 | def is_open(self): 61 | return self.color == COLORS['open'] 62 | 63 | def is_barrier(self): 64 | return self.color == COLORS['barrier'] 65 | 66 | def is_start(self): 67 | # return hasattr(self, 'start') 68 | return self.color == COLORS['start'] 69 | 70 | def is_end(self): 71 | # return hasattr(self, 'end') 72 | return self.color == COLORS['end'] 73 | 74 | def reset(self): 75 | self.color = COLORS['land'] 76 | self.cost_idx = 0 77 | 78 | def reset_color(self): 79 | self.color = COLORS['land'] 80 | 81 | def make_start(self): 82 | self.color = COLORS['start'] 83 | 84 | def make_end(self): 85 | self.color = COLORS['end'] 86 | 87 | def make_closed(self): 88 | self.color = COLORS['closed'] 89 | 90 | def make_open(self): 91 | if not self.is_end(): self.color = COLORS['open'] 92 | 93 | def make_barrier(self): 94 | self.color = COLORS['barrier'] 95 | self.cost_idx = 0 # ? 96 | 97 | def make_path(self): 98 | # if not self.is_start(): self.color = YELLOW 99 | if not self.is_start() and not self.is_end(): self.color = YELLOW 100 | 101 | def draw(self, win): 102 | # 绘制矩形 103 | pygame.draw.rect(win, self.color, (self.x, self.y, self.gap, self.gap)) 104 | if self.cost_idx: 105 | font = pygame.font.Font(None, self.gap) 106 | text = font.render(str(EXTRA_COST[self.cost_idx]), 1, GREY) 107 | textpos = text.get_rect() 108 | textpos.topleft = (self.x + self.gap // 4, self.y + self.gap // 4) 109 | win.blit(text, textpos) 110 | # if self.is_start(): 111 | # font = pygame.font.Font(None, self.gap*3//2) 112 | # text = font.render("S", 1, GREY) 113 | # textpos = text.get_rect() 114 | # textpos.topleft = (self.x + self.gap // 4, self.y + self.gap // 4) 115 | # # textpos.bottomright = (self.x + self.gap // 2, self.y + self.gap // 2) 116 | # win.blit(text, textpos) 117 | # # print("textpos:", textpos) 118 | # if self.is_end(): 119 | # font = pygame.font.Font(None, self.gap*3//2) 120 | # text = font.render("T", 1, GREY) 121 | # textpos = text.get_rect() 122 | # textpos.topleft = (self.x + self.gap // 4, self.y + self.gap // 4) 123 | # # textpos.bottomright = (self.x + self.gap // 2, self.y + self.gap // 2) 124 | # win.blit(text, textpos) 125 | 126 | def update_neighbors(self, grid): 127 | self.neighbors = [] 128 | di = [0, 0, -1, 1] 129 | dj = [1, -1, 0, 0] 130 | K = 4 131 | di = [0, 0, -1, -1, -1, 1, 1, 1] 132 | dj = [1, -1, -1, 0, 1, -1, 0, 1] 133 | K = 8 134 | for k in range(K): 135 | ni = self.row + di[k] 136 | nj = self.col + dj[k] 137 | if ni >= 0 and ni < self.total_rows \ 138 | and nj >= 0 and nj < self.total_cols \ 139 | and not grid[ni][nj].is_barrier(): 140 | self.neighbors.append(grid[ni][nj]) 141 | 142 | def __lt__(self, other): 143 | return self.row * self.total_cols + self.col 144 | # return False # ? 145 | 146 | 147 | def h(p1, p2): 148 | x1, y1 = p1 149 | x2, y2 = p2 150 | d = min(abs(x1 - x2), abs(y1 - y2)) 151 | return math.sqrt(2)*d + abs(x1 - x2) + abs(y1 - y2) - 2*d 152 | 153 | 154 | def reconstruct_path(came_from, current, draw): 155 | current.make_path() 156 | while current in came_from: 157 | current = came_from[current] 158 | current.make_path() 159 | draw() 160 | 161 | 162 | def biastar(draw, grid, start, end): 163 | idx = 0 164 | open_set = [[], []] 165 | heapq.heappush(open_set[idx], (0, start)) 166 | heapq.heappush(open_set[idx^1], (0, end)) 167 | came_from = [{}, {}] 168 | g_score = [{spot: float("inf") for row in grid for spot in row}, {spot: float("inf") for row in grid for spot in row}] 169 | g_score[idx][start] = g_score[idx^1][end] = 0 170 | f_score = [{spot: float("inf") for row in grid for spot in row}, {spot: float("inf") for row in grid for spot in row}] 171 | f_score[idx][start] = f_score[idx^1][end] = h(start.get_pos(), end.get_pos()) 172 | 173 | open_set_hash = [{start}, {end}] 174 | 175 | pause = 0 176 | while len(open_set[0]) and len(open_set[1]): 177 | for event in pygame.event.get(): 178 | if event.type == pygame.QUIT: 179 | bye() 180 | elif event.type == pygame.KEYDOWN: 181 | if event.key == pygame.K_SPACE: 182 | pause ^= 1 183 | elif event.key == pygame.K_q: 184 | bye() 185 | if pause: continue 186 | if len(open_set[idx]) > len(open_set[idx^1]): idx ^= 1 187 | current = heapq.heappop(open_set[idx])[1] 188 | open_set_hash[idx].remove(current) 189 | 190 | if current in open_set_hash[idx^1]: 191 | print(current.row, current.col) 192 | reconstruct_path(came_from[0], current, draw) 193 | reconstruct_path(came_from[1], current, draw) 194 | # end.make_end() 195 | return True 196 | 197 | for neighbor in current.neighbors: 198 | temp_g_score = g_score[idx][current] + (1 if neighbor.row == current.row or neighbor.col == current.col else math.sqrt(2)) 199 | if neighbor.cost_idx: temp_g_score += EXTRA_COST[neighbor.cost_idx] 200 | if temp_g_score < g_score[idx][neighbor]: 201 | came_from[idx][neighbor] = current 202 | g_score[idx][neighbor] = temp_g_score 203 | f_score[idx][neighbor] = temp_g_score + h(neighbor.get_pos(), end.get_pos()) 204 | if neighbor not in open_set_hash[idx]: 205 | heapq.heappush(open_set[idx], (f_score[idx][neighbor], neighbor)) 206 | open_set_hash[idx].add(neighbor) 207 | neighbor.make_open() 208 | 209 | draw() 210 | 211 | if current != start and current != end: 212 | current.make_closed() 213 | 214 | return False 215 | 216 | 217 | def make_grid(rows, cols, gap): 218 | grid = [] 219 | for i in range(rows): 220 | grid.append([]) 221 | for j in range(cols): 222 | spot = Spot(i, j, gap, rows, cols) 223 | grid[i].append(spot) 224 | return grid 225 | 226 | 227 | # 画网格线 228 | def draw_grid(win, rows, cols, gap): 229 | width = cols * gap 230 | height = rows * gap 231 | for i in range(rows): 232 | # 横线 233 | pygame.draw.line(win, GREY, (0, i * gap), (width, i * gap)) 234 | # 竖线 235 | for j in range(cols): 236 | pygame.draw.line(win, GREY, (j * gap, 0), (j * gap, height)) 237 | 238 | 239 | def draw(win, grid, rows, cols, gap): 240 | # 背景填充为WHITE 241 | # 需要吗? 242 | win.fill(WHITE) 243 | 244 | # 每个格子填充对应颜色 245 | for row in grid: 246 | for spot in row: 247 | spot.draw(win) 248 | # 画网格线 249 | draw_grid(win, rows, cols, gap) 250 | pygame.display.update() 251 | 252 | # x 水平向右 253 | # y 水平向下 254 | def get_clicked_pos(pos, gap): 255 | x, y = pos 256 | 257 | row = y // gap 258 | col = x // gap 259 | 260 | return row, col 261 | 262 | def clear_trace(grid): 263 | for row in grid: 264 | for spot in row: 265 | if not spot.is_start() and not spot.is_end() and not spot.is_barrier(): 266 | spot.reset_color() 267 | 268 | def save_map(filename, grid): 269 | with open(filename, 'w') as f: 270 | rows = grid[0][0].total_rows 271 | cols = grid[0][0].total_cols 272 | gap = grid[0][0].gap 273 | f.write("{} {} {}\n".format(rows, cols, gap)) 274 | for row in grid: 275 | for spot in row: 276 | if spot.is_barrier(): 277 | s = '-1' 278 | else: 279 | if spot.is_start(): 280 | s = 'S' 281 | elif spot.is_end(): 282 | s = 'T' 283 | else: 284 | s = '' 285 | s += str(spot.cost_idx) 286 | f.write(s+' ') 287 | f.write('\n') 288 | 289 | def load_map(filename): 290 | grid = [] 291 | f = open(filename, 'r') 292 | [rows, cols, gap] = [ int(s) for s in f.readline().split()] 293 | start = None 294 | end = None 295 | for i in range(rows): 296 | line = f.readline().split() 297 | grid.append([]) 298 | for j in range(cols): 299 | grid[i].append(Spot(i, j, gap, rows, cols)) 300 | cost_idx = 0 301 | if line[j][0] == 'S': 302 | grid[i][j].make_start() 303 | start = grid[i][j] 304 | cost_idx = int(line[j][1:]) 305 | elif line[j][0] == 'T': 306 | grid[i][j].make_end() 307 | end = grid[i][j] 308 | cost_idx = int(line[j][1:]) 309 | elif line[j] == '-1': 310 | grid[i][j].make_barrier() 311 | else: 312 | cost_idx = int(line[j]) 313 | grid[i][j].cost_idx = cost_idx 314 | f.close() 315 | return grid, start, end, rows, cols, gap 316 | 317 | def main(win, ROWS, COLS, GAP, grid, start = None, end = None): 318 | # 黄色格子代表沙漠,经过它的代价为 4 -- idx 2 319 | # 蓝色格子代表溪流,经过它的代价为 2 -- idx 1 320 | # 白色格子为普通地形,经过它的代价为 0 -- idx 0 321 | cost_idx = 0 322 | 323 | while True: 324 | draw(win, grid, ROWS, COLS, GAP) 325 | for event in pygame.event.get(): 326 | if event.type == pygame.QUIT: 327 | bye() 328 | 329 | if pygame.mouse.get_pressed()[0]: # LEFT 330 | pos = pygame.mouse.get_pos() 331 | row, col = get_clicked_pos(pos, GAP) 332 | print("pressed: ", row, col) 333 | spot = grid[row][col] 334 | if cost_idx: 335 | if not spot.is_barrier(): spot.cost_idx = cost_idx 336 | continue 337 | if not start and spot != end: 338 | start = spot 339 | start.make_start() 340 | 341 | elif not end and spot != start: 342 | end = spot 343 | end.make_end() 344 | 345 | elif spot != end and spot != start: 346 | spot.make_barrier() 347 | 348 | elif pygame.mouse.get_pressed()[2]: # RIGHT 349 | pos = pygame.mouse.get_pos() 350 | row, col = get_clicked_pos(pos, GAP) 351 | spot = grid[row][col] 352 | spot.reset() 353 | if spot == start: 354 | start = None 355 | elif spot == end: 356 | end = None 357 | 358 | if event.type == pygame.KEYDOWN: 359 | print("key", event.key) 360 | if event.key == pygame.K_SPACE and start and end: 361 | for row in grid: 362 | for spot in row: 363 | spot.update_neighbors(grid) 364 | clear_trace(grid) 365 | biastar(lambda: draw(win, grid, ROWS, COLS, GAP), grid, start, end) 366 | elif event.key >= pygame.K_0 and event.key <= pygame.K_9: 367 | idx = event.key - pygame.K_0 368 | if idx < len(EXTRA_COST): 369 | cost_idx = idx 370 | # save map 371 | elif event.key == pygame.K_s: 372 | filename = time.strftime("%Y%m%d-%H%M%S.txt") 373 | save_map(filename, grid) 374 | # new grid 375 | elif event.key == pygame.K_n: 376 | start = None 377 | end = None 378 | grid = make_grid(ROWS, COLS, GAP) 379 | # clear trace 380 | elif event.key == pygame.K_c: 381 | clear_trace(grid) 382 | # `q` to quit 383 | elif event.key == pygame.K_q: 384 | bye() 385 | 386 | pygame.quit() 387 | 388 | if __name__ == "__main__": 389 | # 一个ROW*ROW的网格,ROW*gap = WIDTH像素 390 | # gap是每个方格的宽度 391 | ROWS = 20 392 | COLS = 40 393 | GAP = 34 394 | 395 | if len(sys.argv) > 1: 396 | grid, start, end, ROWS, COLS, GAP = load_map(sys.argv[1]) 397 | else: 398 | start = None 399 | end = None 400 | grid = make_grid(ROWS, COLS, GAP) 401 | 402 | # 设置窗口宽和高 403 | pygame.init() 404 | WIDTH = COLS*GAP 405 | HEIGHT = ROWS*GAP 406 | WIN = pygame.display.set_mode((WIDTH, HEIGHT)) 407 | pygame.display.set_caption("Bidirectional A* Path Finding Algorithm") 408 | 409 | main(WIN, ROWS, COLS, GAP, grid, start, end) 410 | -------------------------------------------------------------------------------- /lab/lab02/images/map01-astar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab02/images/map01-astar.png -------------------------------------------------------------------------------- /lab/lab02/images/map01-biastar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab02/images/map01-biastar.png -------------------------------------------------------------------------------- /lab/lab02/images/map01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab02/images/map01.png -------------------------------------------------------------------------------- /lab/lab02/images/map02-astar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab02/images/map02-astar.png -------------------------------------------------------------------------------- /lab/lab02/images/map02-biastar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab02/images/map02-biastar.png -------------------------------------------------------------------------------- /lab/lab02/images/map02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab02/images/map02.png -------------------------------------------------------------------------------- /lab/lab02/map1.txt: -------------------------------------------------------------------------------- 1 | 20 40 34 2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 | 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 | 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 | 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 | 0 0 0 0 0 0 0 0 0 S0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 | 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 T0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 17 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 | -------------------------------------------------------------------------------- /lab/lab02/map2.txt: -------------------------------------------------------------------------------- 1 | 20 40 34 2 | 0 0 0 -1 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 T2 2 2 2 2 3 | 0 0 0 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 4 | -1 -1 -1 -1 -1 -1 0 -1 -1 -1 -1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 2 2 2 2 2 2 5 | 0 0 0 0 0 0 0 0 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 2 2 2 2 0 0 0 6 | 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 2 2 0 0 0 0 7 | 0 0 0 0 0 0 0 -1 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 0 0 0 0 0 8 | 0 0 -1 -1 -1 -1 -1 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 0 0 0 0 0 9 | 0 0 -1 0 0 -1 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 -1 0 0 0 10 | 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 11 | 0 0 0 0 0 -1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 -1 0 0 0 12 | 0 0 -1 0 S0 -1 0 -1 -1 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 -1 0 0 0 1 1 0 1 1 0 0 0 13 | 0 0 -1 -1 -1 -1 0 0 -1 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0 0 0 -1 1 0 1 1 0 0 0 0 14 | 0 0 0 -1 0 0 0 0 -1 0 0 0 -1 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 15 | 0 0 0 -1 0 0 0 0 -1 -1 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 16 | 0 0 0 -1 0 0 0 0 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 17 | 0 0 0 -1 -1 -1 -1 -1 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 18 | 0 0 0 -1 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 19 | 0 0 0 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 20 | 0 0 0 -1 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 21 | 0 0 0 -1 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 22 | -------------------------------------------------------------------------------- /lab/lab03/GreedySetCover.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_GreedySetCover_HPP 2 | #define INCLUDED_GreedySetCover_HPP 3 | 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | vector greedy_set_cover(vector> &F, vector &U) { 9 | int n = F.size(); 10 | unordered_set C; // 已经包含的集合,这里每个集合用它的下标表示 11 | unordered_set Us(U.begin(), U.end()); // 还剩下的元素 12 | vector res; // 返回集合的下标 13 | while (!Us.empty()) { 14 | int sz = 0, j = -1; // 这次新包含F[j]可以新加入sz个元素 15 | for (int i = 0; i < n; ++i) { 16 | if (C.count(i)) continue; // 已经包含了 17 | int cur_sz = 0; 18 | for (int x: F[i]) { 19 | if (Us.count(x)) ++cur_sz; 20 | } 21 | if (cur_sz > sz) j = i; 22 | } 23 | for (int x: F[j]) Us.erase(x); 24 | res.push_back(j); 25 | C.insert(j); 26 | } 27 | return res; 28 | } 29 | 30 | #endif -------------------------------------------------------------------------------- /lab/lab03/LPRoundingSetCover.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_LPRoundingSetCover_HPP 2 | #define INCLUDED_LPRoundingSetCover_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "glpk.h" 10 | using namespace std; 11 | 12 | vector LP_rounding_set_cover(vector> &F, vector &U) { 13 | int n = F.size(); // x个数 14 | int m = U.size(); // 约束不等式个数 15 | unordered_map x2i; 16 | for (int i = 0; i < m; ++i) x2i.emplace(U[i], i); // 每个元素对应的下标(对应了m个不等式约束) 17 | glp_prob *lp = glp_create_prob(); 18 | glp_set_obj_dir(lp, GLP_MIN); // 最小化目标(设置优化方向) 19 | glp_add_rows(lp, m); // 不等式个数 20 | for (int i = 1; i <= m; ++i) glp_set_row_bnds(lp, i, GLP_LO, 1., 0.); // 都是 >= 1 21 | glp_add_cols(lp, n); // 变量x个数 22 | for (int i = 1; i <= n; ++i) { 23 | glp_set_col_bnds(lp, i, GLP_LO, 0., 0.); // x的约束都是 >= 0 24 | glp_set_obj_coef(lp, i, 1.); // 目标函数中的x的系数,都是1 25 | } 26 | // f是最高的元素频率 27 | int sz = 0; 28 | vector freq(m); 29 | for (auto &S: F) { 30 | sz += S.size(); 31 | for (int x: S) ++freq[x2i[x]]; 32 | } 33 | int f = *max_element(freq.begin(), freq.end()); 34 | int *ia = new int[sz+1]; 35 | int *ja = new int[sz+1]; 36 | double *ar = new double[sz+1]; 37 | int idx = 1; 38 | for (int i = 0; i < n; ++i) { 39 | for (int x: F[i]) { 40 | ia[idx] = x2i[x] + 1; 41 | ja[idx] = i + 1; 42 | ar[idx] = 1.; 43 | ++idx; 44 | } 45 | } 46 | glp_load_matrix(lp, sz, ia, ja, ar); 47 | // glp_write_mps,glp_read_mps也可以写读lp问题,但这里对于现生成的数据不用了 48 | // lp问题初始化完毕,开始求解 49 | glp_smcp smcp; 50 | glp_init_smcp(&smcp); 51 | // 默认GLP_MSG_ALL: full output (including informational messages). 52 | smcp.msg_lev = GLP_MSG_ERR; // error and warning messages only; 53 | smcp.msg_lev = GLP_MSG_ON; // error and warning messages only; 54 | // smcp.presolve = GLP_ON; 55 | glp_simplex(lp, &smcp); 56 | // glp_iptcp iptcp; 57 | // iptcp.msg_lev = GLP_MSG_ERR; 58 | // glp_interior(lp, &iptcp); 59 | 60 | // glp_simplex(lp, nullptr); // 单纯形法求,发现更快 61 | // glp_interior(lp, nullptr); // 内点法求(karmarkar) 62 | 63 | // 舍入法选择保留的集合 64 | vector res; // 返回集合的下标 65 | for (int i = 0; i < n; ++i) { 66 | if (1./f <= glp_get_col_prim(lp, i+1)) res.push_back(i); 67 | // cout << "x" << i << ": " << glp_get_col_prim(lp, i) << " "; 68 | } 69 | // cout << endl; 70 | delete [] ia; 71 | delete [] ja; 72 | delete [] ar; 73 | glp_delete_prob(lp); 74 | return res; 75 | } 76 | 77 | #endif -------------------------------------------------------------------------------- /lab/lab03/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | CXXFLAGS = -g -Wall -std=c++11 -lglpk 3 | SOURCES = main.cpp 4 | OBJECTS = $(SOURCES:.cpp=.o) 5 | BINARY = main 6 | 7 | all: $(BINARY) 8 | 9 | $(BINARY): $(OBJECTS) 10 | $(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ 11 | 12 | main.o: Sampler.hpp LPRoundingSetCover.hpp 13 | 14 | clean: 15 | $(RM) $(BINARY) $(OBJECTS) 16 | -------------------------------------------------------------------------------- /lab/lab03/README.md: -------------------------------------------------------------------------------- 1 | # 实验三: 近似算法 2 | 3 | * 实现了两种用于求解集合覆盖问题的近似算法:基于贪心策略和基于线性规划(舍入法) 4 | * 测试了两种算法在三种不同规模数据下的运行时间,验证了覆盖的正确性 5 | 6 | ## Set Cover问题 7 | 8 | * 除了参考老师的课件我还参考了[setcover-tamara](https://math.mit.edu/~goemans/18434S06/setcover-tamara.pdf) (好像是mit一个老师的课程的资料,可以直接google: setcover tamara),这里面的将set cover问题转换为线性规划问题的例子很清晰 9 | * 集合覆盖问题就是要求从集族`F`中挑选一些集合覆盖全集U中的所有元素,挑选的每个集合都有对应的代价(当然实验中每个集合代价都是1,所以就是使集合数量尽可能小) 10 | * 近似算法求解来求set cover问题挑选出的集合(用`C`表示,也是集合的集合,我的代码中就是对应的F中集合的下标)不一定是最优的(代价最小),甚至不保证能覆盖所有元素(随机舍入法可能不会覆盖所有元素) 11 | 12 | ## glpk安装使用 13 | 14 | * GNU线性规划工具集(GNU Linear Programming Kit, GLPK)是用来求解大规模之线性规划(LP)、混合整数规划(MIP),跟其他相关问题的软件包 15 | * 官网: [GLPK (GNU Linear Programming Kit)](https://www.gnu.org/software/glpk/), 可以[下载源码](http://ftp.gnu.org/gnu/glpk/),解压后里面doc目录中有pdf文档 16 | * arch用户 17 | * 安装: `sudo pacman -Sy glpk` 18 | * 文档: `/usr/share/doc/glpk/glpk.pdf` 19 | * 关于glpk的使用我主要就看了: 1 Introduction -> 1.3 Using the package -> 1.3.1 Brief example 的例子(我使用的是5.0版本 - December 2020) 20 | * 课件上说的采用内点法求(karmarkar)线性规划问题,也可以用单纯形法(simplex)来求,实际发现后者更快。两者使用方法基本一致,参考`LPRoundingSetCover.hpp`文件中调用`glp_interior/glp_simplex`函数部分 21 | 22 | ## 程序使用说明 23 | 24 | * `Sampler.hpp` 是用于从`[0..N-1]`这`N`个元素(所以我的全集`U`就是`[0..N-1]`)生成集族`F`,其中采用了水池抽样算法,思路和实验指导书中的一致 25 | * `GreedySetCover.hpp` 中实现了基于贪心策略的近似算法 26 | * `LPRoundingSetCover.hpp` 中实现了基于线性规划的近似算法,使用的是舍入法 27 | * 使用`make`进行编译,`./main`运行 28 | * 程序针对两种近似算法,在三种不同大小数据集上运行 29 | * 记录了运行时间,并且验证了求得的`C`是否覆盖了所有元素 30 | * 运行输出示例 31 | 32 | ```txt 33 | ❯ ./main 34 | ----N: 100 35 | took: 0.001353 second(s) 36 | size of C: 28 37 | valid cover: true 38 | ----N: 1000 39 | took: 0.117102 second(s) 40 | size of C: 247 41 | valid cover: true 42 | ----N: 5000 43 | took: 3.037254 second(s) 44 | size of C: 1332 45 | valid cover: true 46 | ---------------------- 47 | ----N: 100 48 | 0: obj = 0.000000000e+00 inf = 1.000e+02 (100) 49 | 10: obj = 8.000000000e+00 inf = 0.000e+00 (0) 50 | * 70: obj = 7.150618982e+00 inf = 0.000e+00 (0) 51 | took: 0.001229 second(s) 52 | size of C: 31 53 | valid cover: true 54 | ----N: 1000 55 | 0: obj = 0.000000000e+00 inf = 1.000e+03 (1000) 56 | 141: obj = 1.200000000e+02 inf = 0.000e+00 (0) 57 | * 1651: obj = 8.365233954e+01 inf = 0.000e+00 (0) 15 58 | took: 0.251094 second(s) 59 | size of C: 330 60 | valid cover: true 61 | ----N: 5000 62 | 0: obj = 0.000000000e+00 inf = 5.000e+03 (5000) 63 | 688: obj = 5.770000000e+02 inf = 0.000e+00 (0) 2 64 | * 6030: obj = 4.603771142e+02 inf = 0.000e+00 (2154) 52 65 | * 8478: obj = 4.374617213e+02 inf = 0.000e+00 (2247) 25 66 | * 10406: obj = 4.254588314e+02 inf = 0.000e+00 (2205) 19 67 | * 12036: obj = 4.188238957e+02 inf = 0.000e+00 (2299) 16 68 | * 13664: obj = 4.138036006e+02 inf = 0.000e+00 (2152) 16 69 | * 15358: obj = 4.105492542e+02 inf = 0.000e+00 (2034) 16 70 | * 17140: obj = 4.089063507e+02 inf = 0.000e+00 (1452) 18 71 | * 17981: obj = 4.086769912e+02 inf = 0.000e+00 (0) 8 72 | took: 37.794325 second(s) 73 | size of C: 1636 74 | valid cover: true 75 | ---------------------- 76 | ``` 77 | -------------------------------------------------------------------------------- /lab/lab03/Sampler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_Sampler_HPP 2 | #define INCLUDED_Sampler_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | random_device rd; 12 | mt19937 g(rd()); 13 | // default_random_engine g; 14 | 15 | /** 16 | * get uniformly distributed random int from [lo...hi] 17 | */ 18 | int rand_int(int lo, int hi) { 19 | uniform_int_distribution distribution(lo, hi); 20 | return distribution(g); 21 | } 22 | 23 | /** 24 | * get uniformly distributed real number from [lo, hi) 25 | */ 26 | double rand_real(double lo, double hi) { 27 | uniform_real_distribution distribution(lo, hi); 28 | return distribution(g); 29 | } 30 | 31 | /** 32 | * O(st.size()) 33 | */ 34 | vector sample_k(int k, unordered_set &st) { 35 | vector res; 36 | res.reserve(k); 37 | int i = 0, n = st.size(); 38 | auto it = st.begin(); 39 | for (; i < k; ++it, ++i) res.push_back(*it); 40 | for (; i < n; ++i, ++it) { 41 | int j = rand_int(0, i); 42 | if (j < k) res[j] = *it; 43 | } 44 | return res; 45 | } 46 | 47 | /** 48 | * O(k(1+log(n/k))) 49 | * get k elements from [0..N-1] 50 | */ 51 | vector sample_k(int k, int n) { 52 | vector res; 53 | res.reserve(k); 54 | for (int i = 0; i < k; ++i) res.push_back(i); 55 | double W = exp(log(rand_real(0, 1))/k); 56 | for (int i = k; i < n;) { 57 | i += floor(log(rand_real(0, 1))/log(1-W)) + 1; 58 | if (i < n) { 59 | res[rand_int(0, k-1)] = i; 60 | W *= exp(log(rand_real(0, 1))/k); 61 | } 62 | } 63 | return res; 64 | } 65 | 66 | /** 67 | * 集族 F 68 | * [0..N-1] 69 | */ 70 | vector> generate_subsets(int N) { 71 | assert(N >= 20); 72 | vector> F; 73 | int sz = 0; 74 | unordered_set U; // 剩下的 75 | // [0..N-1] 76 | for (int i = 0; i < N; ++i) U.insert(i); 77 | unordered_set C; // 已经包含的 78 | F.emplace_back(sample_k(20, N)); 79 | for (int x: F[0]) { 80 | U.erase(x); 81 | C.insert(x); 82 | } 83 | ++sz; 84 | while (!U.empty()) { 85 | if (U.size() < 20) { 86 | F.emplace_back(U.begin(), U.end()); 87 | ++sz; 88 | break; 89 | } 90 | int n = rand_int(1, 20); 91 | int k = rand_int(1, n); // 新元素个数 92 | F.emplace_back(sample_k(k, U)); 93 | vector old = sample_k(k, C); 94 | for (int x: F[sz]) { 95 | U.erase(x); 96 | C.insert(x); 97 | } 98 | F[sz].insert(F[sz].end(), old.begin(), old.end()); 99 | ++sz; 100 | } 101 | while (sz != N) { 102 | F.push_back(sample_k(rand_int(1, 20), N)); 103 | ++sz; 104 | } 105 | return F; 106 | } 107 | 108 | #endif -------------------------------------------------------------------------------- /lab/lab03/images/GreedySetCover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab03/images/GreedySetCover.png -------------------------------------------------------------------------------- /lab/lab03/images/GreedySetCover2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab03/images/GreedySetCover2.png -------------------------------------------------------------------------------- /lab/lab03/images/LPRoundingSetCover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab03/images/LPRoundingSetCover.png -------------------------------------------------------------------------------- /lab/lab03/images/SetCover2LP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab03/images/SetCover2LP.png -------------------------------------------------------------------------------- /lab/lab03/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Sampler.hpp" 7 | #include "GreedySetCover.hpp" 8 | #include "LPRoundingSetCover.hpp" 9 | using namespace std; 10 | 11 | vector time_it(function()> f) { 12 | auto begin = std::chrono::steady_clock::now(); 13 | auto C = f(); 14 | auto end = std::chrono::steady_clock::now(); 15 | cout << "took: " << fixed << setprecision(6) 16 | << (std::chrono::duration_cast(end - begin).count()) / 1e6 17 | << " second(s)\n"; 18 | cout << "size of C: " << C.size() << endl; 19 | return C; 20 | } 21 | 22 | int main(int argc, char const *argv[]) 23 | { 24 | for (auto f: {greedy_set_cover, LP_rounding_set_cover}) { 25 | for (int N: {100, 1000, 5000}) { 26 | cout << "----N: " << N << endl; 27 | // [0..N-1] 28 | vector> F = generate_subsets(N); 29 | vector U; U.reserve(N); 30 | for (int i = 0; i < N; ++i) U.push_back(i); 31 | // f(F, U); 32 | // time it 33 | // time_it(bind(f, ref(F), ref(U))); 34 | 35 | // check answer is correct 36 | vector C = time_it(bind(f, ref(F), ref(U))); 37 | vector st(N); 38 | for (int i: C) { 39 | for (int x: F[i]) { 40 | st[x] = true; 41 | } 42 | } 43 | cout << "valid cover: " << boolalpha 44 | << all_of(st.begin(), st.end(), [](bool x){ return x; }) 45 | << endl; 46 | } 47 | cout << "----------------------\n"; 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /lab/lab04/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | CXXFLAGS = -g -Wall -std=c++14 #-fsanitize=address,undefined 3 | SOURCES = main.cpp 4 | OBJECTS = $(SOURCES:.cpp=.o) 5 | BINARY = main 6 | 7 | all: $(BINARY) 8 | 9 | $(BINARY): $(OBJECTS) 10 | $(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ 11 | 12 | main.o: qsort.hpp 13 | 14 | clean: 15 | $(RM) $(BINARY) $(OBJECTS) 16 | -------------------------------------------------------------------------------- /lab/lab04/README.md: -------------------------------------------------------------------------------- 1 | # 实验四: 快速排序 2 | 3 | * 根据指导书提供的伪代码实现快速排序 4 | * 使用三路划分改进了排序 5 | * 测试上面两个快速排序和`std::sort`在不同重复率数据上的运行时间,进行对比 6 | 7 | ## 程序使用说明 8 | 9 | * 使用`make`进行编译,`./main [N]`运行,默认N为1e5,N是待排序的数组大小,测试重复率为`0%,10%,...,100%`下的运行时间 10 | * 保存了N为10K,100K,1000K下的运行时间数据,可以使用`python draw.py`进行绘图(这里N为1000k的时候第一种快排实现运行过慢,没有包含它) 11 | * 绘图如下 12 | * `N=10k` 13 | 14 | ![10k](images/10k.png) 15 | 16 | * `N=100k` 17 | 18 | ![100k](images/100k.png) 19 | 20 | * `N=1000k` 21 | 22 | ![1000k](images/1000k.png) 23 | 24 | ## 结果分析 25 | 26 | * 可以看出当元素重复率逐渐增高时,第一种快排实现运行时间上升非常快(是由于在partition时,分得不均匀,一侧可能只有一个或几个元素,时间复杂度降为O(n^2)) 27 | * 而系统的快排实现中规中矩,运行时间比较稳定,因为它并不是单纯的快排实现,而是几种排序方法的混合体,叫做introsort 28 | * 它开始于快排 29 | * 如果递归层数过深会改用heapsort 30 | * 当数据量小于某个阈值改为插入排序 31 | * 采用三数取中划分(Median-of-3 partition) 32 | * 采用三路划分优化的快排对于重复元素的优化特别好,重复率越高,复杂度越趋于`O(n)` 33 | -------------------------------------------------------------------------------- /lab/lab04/data1000k.txt: -------------------------------------------------------------------------------- 1 | 0.347587 0.256988 2 | 0.321169 0.247112 3 | 0.281422 0.242722 4 | 0.246230 0.239426 5 | 0.220887 0.233011 6 | 0.183969 0.228654 7 | 0.141302 0.237243 8 | 0.105868 0.225624 9 | 0.068725 0.213168 10 | 0.033967 0.203381 11 | 0.001792 0.194333 -------------------------------------------------------------------------------- /lab/lab04/data100k.txt: -------------------------------------------------------------------------------- 1 | 0.024706 0.029495 0.022575 2 | 0.650250 0.025341 0.021599 3 | 2.504488 0.023537 0.021076 4 | 5.625149 0.020664 0.020543 5 | 9.948128 0.017537 0.019988 6 | 15.535263 0.014900 0.018932 7 | 22.468349 0.012013 0.019092 8 | 30.809346 0.008782 0.018086 9 | 40.644119 0.005501 0.017429 10 | 50.498948 0.002895 0.017076 11 | 62.662867 0.000215 0.015647 -------------------------------------------------------------------------------- /lab/lab04/data10k.txt: -------------------------------------------------------------------------------- 1 | 0.005969 0.006999 0.005551 2 | 0.023449 0.002083 0.001756 3 | 0.026597 0.001928 0.001713 4 | 0.057341 0.001595 0.001676 5 | 0.100846 0.001368 0.001628 6 | 0.156393 0.001162 0.001522 7 | 0.224411 0.000974 0.001460 8 | 0.304931 0.000660 0.001376 9 | 0.398023 0.000441 0.001401 10 | 0.503171 0.000206 0.001297 11 | 0.621208 0.000019 0.001262 -------------------------------------------------------------------------------- /lab/lab04/draw.py: -------------------------------------------------------------------------------- 1 | # encoding=utf-8 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import math 5 | 6 | fig1 = plt.figure(1) 7 | ax1 = fig1.add_subplot(111) 8 | fig2 = plt.figure(2) 9 | ax2 = fig2.add_subplot(111) 10 | fig3 = plt.figure(3) 11 | ax3 = fig3.add_subplot(111) 12 | ax1.set(title='N = 10k', ylabel='time took in seconds (t)', xlabel='rep rate (%)') 13 | ax2.set(title='N = 100k', ylabel='time took in seconds (t)', xlabel='rep rate (%)') 14 | ax3.set(title='N = 1000k', ylabel='time took in seconds (t)', xlabel='rep rate (%)') 15 | 16 | ys1 = [[], [], []] 17 | with open('data10k.txt', 'r') as f: 18 | line = f.readline() 19 | while line: 20 | [a, b, c] = [float(x) for x in line.split()] 21 | ys1[0].append(a) 22 | ys1[1].append(b) 23 | ys1[2].append(c) 24 | line = f.readline() 25 | x = np.linspace(0, 100, 11) 26 | ax1.plot(x, ys1[0], label='qsort01') 27 | ax1.plot(x, ys1[1], label='qsort02') 28 | ax1.plot(x, ys1[2], label='std::sort') 29 | ax1.legend() 30 | 31 | ys2 = [[], [], []] 32 | with open('data100k.txt', 'r') as f: 33 | line = f.readline() 34 | while line: 35 | [a, b, c] = [float(x) for x in line.split()] 36 | ys2[0].append(a) 37 | ys2[1].append(b) 38 | ys2[2].append(c) 39 | line = f.readline() 40 | x = np.linspace(0, 100, 11) 41 | ax2.plot(x, ys2[0], label='qsort01') 42 | ax2.plot(x, ys2[1], label='qsort02') 43 | ax2.plot(x, ys2[2], label='std::sort') 44 | ax2.legend() 45 | 46 | ys3 = [[], []] 47 | with open('data1000k.txt', 'r') as f: 48 | line = f.readline() 49 | while line: 50 | [a, b] = [float(x) for x in line.split()] 51 | ys3[0].append(a) 52 | ys3[1].append(b) 53 | line = f.readline() 54 | x = np.linspace(0, 100, 11) 55 | ax3.plot(x, ys3[0], label='qsort02') 56 | ax3.plot(x, ys3[1], label='std::sort') 57 | ax3.legend() 58 | 59 | plt.show() 60 | -------------------------------------------------------------------------------- /lab/lab04/images/1000k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab04/images/1000k.png -------------------------------------------------------------------------------- /lab/lab04/images/100k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab04/images/100k.png -------------------------------------------------------------------------------- /lab/lab04/images/10k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab04/images/10k.png -------------------------------------------------------------------------------- /lab/lab04/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "qsort.hpp" 8 | 9 | using namespace std; 10 | 11 | // std::random_device rd; 12 | // std::mt19937 g(rd()); 13 | default_random_engine g; 14 | 15 | void time_it(function f) { 16 | auto begin = std::chrono::steady_clock::now(); 17 | f(); 18 | auto end = std::chrono::steady_clock::now(); 19 | cout << fixed << setprecision(6) << (std::chrono::duration_cast(end - begin).count()) /1000000.0 << " "; 20 | } 21 | 22 | int main(int argc, char const *argv[]) 23 | { 24 | int N = 1e5; 25 | if (argc > 1) N = stoi(argv[1]); 26 | vector A0(N); 27 | iota(A0.begin(), A0.end(), 1); 28 | for (int rep = 0; rep <= N; rep += N/10) { 29 | auto A = A0; 30 | fill_n(A.begin(), rep, 1); 31 | shuffle(A.begin(), A.end(), g); 32 | auto A2 = A, A3 = A; 33 | // 根据指导书上的伪代码实现的qsort 34 | time_it(bind(qsort01, ref(A), 0, N-1)); 35 | assert(is_sorted(A.begin(), A.end())); 36 | // 改进的三路划分的qsort 37 | time_it(bind(qsort02, ref(A2), 0, N-1)); 38 | assert(is_sorted(A2.begin(), A2.end())); 39 | // C++的sort 40 | time_it(bind(static_cast::iterator, std::vector::iterator)>(sort), 41 | A3.begin(), A3.end())); 42 | assert(is_sorted(A3.begin(), A3.end())); 43 | cout << endl; 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /lab/lab04/qsort.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_qsort01_HPP 2 | #define INCLUDED_qsort02_HPP 3 | 4 | // #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | default_random_engine generator; 11 | 12 | /** 13 | * get uniformly distributed random int from [lo...hi] 14 | */ 15 | int rand_int(int lo, int hi) { 16 | uniform_int_distribution distribution(lo, hi); 17 | return distribution(generator); 18 | } 19 | 20 | void qsort01(vector& A, int l, int r) { 21 | if (l >= r) return; 22 | int i = rand_int(l, r); 23 | swap(A[r], A[i]); 24 | i = l - 1; 25 | for (int j = l; j < r; ++j) { 26 | if (A[j] <= A[r]) swap(A[++i], A[j]); 27 | } 28 | swap(A[++i], A[r]); 29 | qsort01(A, l, i - 1); 30 | qsort01(A, i + 1, r); 31 | } 32 | 33 | /** 34 | * use three way partition 35 | * T(n) = 2T(n/2) + n 36 | */ 37 | void qsort02(vector& A, int l, int r) { 38 | if (l >= r) return; 39 | int i = rand_int(l, r); 40 | int x = A[i], lo = l, hi = r; 41 | i = l; 42 | while (i <= hi) { 43 | if (A[i] == x) ++i; 44 | else if (A[i] < x) swap(A[i++], A[lo++]); 45 | else swap(A[i], A[hi--]); 46 | } 47 | // ----[x]xx[x]++++ 48 | // lo hi 49 | qsort02(A, l, lo - 1); 50 | qsort02(A, hi + 1, r); 51 | } 52 | 53 | #endif -------------------------------------------------------------------------------- /lab/lab05/BFPRT.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_BFPRT_HPP 2 | #define INCLUDED_BFPRT_HPP 3 | 4 | #include 5 | 6 | using namespace std; 7 | 8 | int pick(vector &L, int l, int r, int k) { 9 | if (l == r) return L[l]; 10 | 11 | // get median of medians 12 | for (int i = l; i <= r; i += 5) { 13 | int j = min(r, i + 5); 14 | for (int ii = i + 1; ii <= j; ++ii) { 15 | for (; ii > i && L[ii - 1] > L[ii]; --ii) swap(L[ii], L[ii - 1]); 16 | } 17 | swap(L[l + (i - l) / 5], L[(i + j) / 2]); 18 | } 19 | int nr = l + (r - l) / 5; 20 | int median = pick(L, l, nr, (nr + l) / 2); 21 | 22 | // three way partition with the approximate median 23 | // ---[=]=[=]+++ 24 | // low high 25 | int i = l, low = l, high = r; 26 | while (i <= high) { 27 | if (L[i] == median) 28 | ++i; 29 | else if (L[i] < median) 30 | swap(L[i++], L[low++]); 31 | else 32 | swap(L[i], L[high--]); 33 | } 34 | 35 | if (k < low) { 36 | return pick(L, l, low - 1, k); 37 | } else if (k <= high) { 38 | return L[k]; 39 | } else { 40 | return pick(L, high + 1, r, k); 41 | } 42 | } 43 | 44 | #endif -------------------------------------------------------------------------------- /lab/lab05/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | CXXFLAGS = -g -Wall -std=c++14 #-fsanitize=address,undefined 3 | SOURCES = main.cpp 4 | OBJECTS = $(SOURCES:.cpp=.o) 5 | BINARY = main 6 | 7 | all: $(BINARY) 8 | 9 | $(BINARY): $(OBJECTS) 10 | $(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ 11 | 12 | main.o: BFPRT.hpp lazyselect.hpp mrandom.hpp 13 | 14 | clean: 15 | $(RM) $(BINARY) $(OBJECTS) 16 | -------------------------------------------------------------------------------- /lab/lab05/README.md: -------------------------------------------------------------------------------- 1 | # 实验五: 计算k位数的随机算法 2 | 3 | * 任务就是实现找第k大元素,实现两个算法 4 | * 实现O(n)复杂度的select,也就是BFPRT算法: 参考 [blog](https://www.jianshu.com/p/3905983674f3), [BFPRT-simple.cpp](https://github.com/sky-bro/AC/blob/master/Algorithms/Median%20of%20medians/BFPRT-simple.cpp) 5 | * 实现随机算法lazyselect,能以$1 - O(n^{-1/4})$的概率在一轮中找到第k大,一轮找不到就两轮,三轮直到找到 6 | 7 | ## BFPRT 8 | 9 | * 参考博客[中位数的中位数 - Median of Medians,选取近似的中位数作为pivot元素](https://www.jianshu.com/p/3905983674f3) 10 | * 博客对应代码[Median of medians](https://github.com/sky-bro/AC/tree/master/Algorithms/Median%20of%20medians) 11 | 12 | ## Lazyselect 13 | 14 | * 默认的采样比例n^(3/4)已实现 15 | * 其它采样比例的对比未实现 TODO 16 | * refs 17 | * https://people.cs.umass.edu/~mcgregor/711S09/lec04.pdf 18 | * https://www2.cs.sfu.ca/CourseCentral/405/petra/Current/random2-4up.pdf 19 | 20 | ## 对比两种k位数算法 21 | 22 | 采用不同大小的随机序列进行测试,每个序列运行1000次取运行时间的平均值,结果如下 23 | 24 | ```txt 25 | (N=1000) lazyselect: 0.000148354 26 | (N=1000) BFPRT : 0.000172629 27 | (N=2000) lazyselect: 0.000245446 28 | (N=2000) BFPRT : 0.000349101 29 | (N=5000) lazyselect: 0.000543804 30 | (N=5000) BFPRT : 0.000897497 31 | (N=10000) lazyselect: 0.000987361 32 | (N=10000) BFPRT : 0.00176972 33 | (N=20000) lazyselect: 0.00178929 34 | (N=20000) BFPRT : 0.00353356 35 | (N=50000) lazyselect: 0.0039252 36 | (N=50000) BFPRT : 0.009168 37 | (N=100000) lazyselect: 0.0070601 38 | (N=100000) BFPRT : 0.018703 39 | ``` 40 | 41 | 可以看出二者运行时间均随N的增大而线性增加,BFPRT略慢于lazyselect,主要是因为BFPRT的常数项比较大,而lazyselect有可能一轮就找到正确答案。 42 | 43 | ## 随机算法参数分析 44 | 45 | TODO 暂未实现 -------------------------------------------------------------------------------- /lab/lab05/images/BFPRT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab05/images/BFPRT.png -------------------------------------------------------------------------------- /lab/lab05/images/lazyselect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/lab05/images/lazyselect.png -------------------------------------------------------------------------------- /lab/lab05/lazyselect.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_lazyselect_HPP 2 | #define INCLUDED_lazyselect_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "mrandom.hpp" 9 | 10 | using namespace std; 11 | 12 | /** 13 | * n = A.size() 14 | * k in [0..n-1] 15 | */ 16 | int lazyselect(const vector &A, int k) { 17 | int n = A.size(), m = pow(n, 3./4); // size of A, R 18 | int x = k*pow(n, -1./4), l = max(int(x-sqrt(n)), 0), h = min(int(x+sqrt(n)), m-1); 19 | int loops = 0; 20 | while (1) { 21 | ++loops; 22 | // cout << "loop: " << ++loops << endl; 23 | vector R = sample_k(A, m); 24 | sort(R.begin(), R.end()); 25 | int L = R[l], H = R[h]; 26 | int cnt = 0; // count number of elements that are smaller than L in A 27 | vector P; 28 | for (int i = 0; i < n; ++i) { 29 | if (A[i] < L) ++cnt; 30 | else if (A[i] <= H) P.push_back(A[i]); 31 | } 32 | int sz = P.size(); 33 | if (k >= cnt && k < cnt + sz && sz <= 4*m+1) { 34 | sort(P.begin(), P.end()); 35 | return P[k-cnt]; 36 | } 37 | } 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /lab/lab05/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "BFPRT.hpp" 7 | #include "lazyselect.hpp" 8 | #include "mrandom.hpp" 9 | 10 | using namespace std; 11 | 12 | double time_it(function f, int ans) { 13 | auto begin = std::chrono::steady_clock::now(); 14 | int ret = f(); 15 | auto end = std::chrono::steady_clock::now(); 16 | // cout << fixed << setprecision(6) << (std::chrono::duration_cast(end - begin).count()) /1000000.0 << " "; 17 | assert(ret == ans); // make sure selection algo is correct 18 | double t = (std::chrono::duration_cast(end - begin).count()) / 1e6; 19 | return t; 20 | } 21 | 22 | int main(int argc, char const *argv[]) 23 | { 24 | for (int N: {1000, 2000, 5000, 10000, 20000, 50000, 100000}) { 25 | vector A(N); 26 | int k = N/2; 27 | iota(A.begin(), A.end(), 1); 28 | int ans = A[k]; 29 | shuffle(A.begin(), A.end(), g); 30 | int loops = 1e3; 31 | double t1 = 0, t2 = 0; 32 | for (int i = 0; i < loops; ++i) { 33 | vector B = A; 34 | t1 += time_it(bind(lazyselect, ref(B), k), ans); // will not change B 35 | t2 += time_it(bind(pick, ref(B), 0, N-1, k), ans); // will change B 36 | } 37 | t1 /= loops; 38 | t2 /= loops; 39 | cout << "(N=" << N << ")\tlazyselect:\t" << t1 << endl; 40 | cout << "(N=" << N << ")\tBFPRT :\t" << t2 << endl; 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /lab/lab05/mrandom.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_mrandom_HPP 2 | #define INCLUDED_mrandom_HPP 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | random_device rd; 10 | mt19937 g(rd()); 11 | // default_random_engine g; 12 | 13 | /** 14 | * get uniformly distributed random int from [lo...hi] 15 | */ 16 | int rand_int(int lo, int hi) { 17 | uniform_int_distribution distribution(lo, hi); 18 | return distribution(g); 19 | } 20 | 21 | /** 22 | * get uniformly distributed real number from [lo, hi) 23 | */ 24 | double rand_real(double lo, double hi) { 25 | uniform_real_distribution distribution(lo, hi); 26 | return distribution(g); 27 | } 28 | 29 | /** 30 | * Algorithm L improves upon this algorithm by 31 | * computing how many items are discarded before 32 | * the next item enters the reservoir 33 | * time complexity O(k(1+log(n/k))) 34 | */ 35 | vector sample_k(const vector &S, int k) { 36 | vector R; R.reserve(k); 37 | for (int i = 0; i < k; ++i) R.push_back(S[i]); 38 | double W = exp(log(rand_real(0, 1))/k); 39 | for (int i = k, n = S.size(); i < n;) { 40 | i += floor(log(rand_real(0, 1))/log(1-W)) + 1; 41 | if (i < n) { 42 | R[rand_int(0, k-1)] = S[i]; 43 | W *= exp(log(rand_real(0, 1))/k); 44 | } 45 | } 46 | return R; 47 | } 48 | 49 | #endif -------------------------------------------------------------------------------- /lab/setcover-tamara.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/setcover-tamara.pdf -------------------------------------------------------------------------------- /lab/算法实验指导书.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/lab/算法实验指导书.pdf -------------------------------------------------------------------------------- /slides/ch0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch0.pdf -------------------------------------------------------------------------------- /slides/ch1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch1.pdf -------------------------------------------------------------------------------- /slides/ch10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch10.pdf -------------------------------------------------------------------------------- /slides/ch2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch2.pdf -------------------------------------------------------------------------------- /slides/ch3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch3.pdf -------------------------------------------------------------------------------- /slides/ch4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch4.pdf -------------------------------------------------------------------------------- /slides/ch5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch5.pdf -------------------------------------------------------------------------------- /slides/ch6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch6.pdf -------------------------------------------------------------------------------- /slides/ch7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch7.pdf -------------------------------------------------------------------------------- /slides/ch8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch8.pdf -------------------------------------------------------------------------------- /slides/ch9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sky-bro/HIT-Algo/8cabd43e823ed7a1b2ccf1357d1dbf8c6fe4b46d/slides/ch9.pdf --------------------------------------------------------------------------------