蒙特卡洛的应用软件统计——小李子LC

1、应用软件统计

软件

名称

开发

单位

模拟方向

是否开源

优点

备注

Geant4

欧洲核子研究组织

模拟粒子在物质中输运的物理过程的模拟;微观粒子与物质相互作用过程

考虑电子与靶碰撞发生的康普顿效应、光电效应、瑞利散射、轫致辐射和电离等物理过程,可以模拟各种能量的粒子传输,其他蒙卡模拟软件一般受能量限制

C++面向对象,用户可以根据实际需要更改、扩充程序,Geant4可以调节、优化以及输出的信息更多,同时可视化方面也比Mcnp默认要强不少,至少可以输出高质量的带电粒子径迹的矢量图片。这点Mcnp不容易做到。

Mcnp

美国洛斯阿拉莫斯国家实验室

模拟粒子在材料中的输运过程,如三维复杂几何结构中的中子、光子、电子或者耦合中子/光子/电子输运问题的通用计算

适用于复杂的几何结构

Mcnp输入文件结构复杂,几何模型的描述工作又极为抽象、不直观和容易出错,这样使得描述工作费时、复杂和效率低

Egs4

美国斯坦福直线加速器中心

模拟电磁相互作用过程,如光子和电子的输运过程

适用于任何材料

Egsnrc

美国斯坦福直线加速器中心

模拟电磁相互作用过程,如光子和电子的输运过程

适用于任何材料

EGS4的升级扩展版

Fluka

Fluka公司,欧洲核子研究组织参与

模拟蒙卡粒子输运过程,如质子、电子加速器屏蔽设计,量热计,活化,剂量学,探测器设计,宇宙射线,中微子物理,还有放射治疗等

大部分情况FLUKA使用者不需要编写程序。针对特别的需求,可以通过Fortran 77程序接口来实现

Srim

美国科技领先的Srim企业有限责任公司

模拟计算离子在靶材中能量损失和分布的程序组

可以选择特定的入射离子及靶材种类,并可设置合适的加速电压[53]。可以算不同粒子,以不同的能量,从不同的位置,以不同的角度入射到靶中的情况

离子注入常用的模拟软件

Lammps

美国能源部

分子动力学软件,用于对原子建模、原子或连续尺度的并行粒子进行模拟

着重于材料建模,适用于固态材料(金属,半导体)和软物质(生物分子,聚合物)以及粗粒或介观系统,是金属原子级模拟的首选

加了蒙卡接口。命名是大规模原子/分子大规模并行模拟器的首字母缩写

Spparks

美国能源部圣地亚哥课题组

用于晶格模型和非晶格模型的并行蒙特卡罗计算

能够进行点阵中和离散点阵计算,主要用以缺陷点阵和杂质迁移的演化过程模拟,可用来研究研究与异常晶粒生长相关的机制和统计数据。

小众软件,包括动力学蒙特卡罗(Kmc)、拒绝动力学蒙特卡罗(Rkmc)和大都会蒙特卡罗(Mmc)算法

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于C语言的五子棋蒙特卡洛树搜索(MCTS)示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define BOARD_SIZE 15 #define MAX_PLAYS 225 #define UCB_C 1.96 typedef struct { int x; int y; } Point; typedef struct Node Node; struct Node { int wins; int plays; Point move; Node *parent; Node *children[MAX_PLAYS]; }; typedef struct { int board[BOARD_SIZE][BOARD_SIZE]; int next_player; } GameState; int opposite(int player) { return 3 - player; } int legal_moves(GameState *state, Point moves[]) { int count = 0; for (int x = 0; x < BOARD_SIZE; x++) { for (int y = 0; y < BOARD_SIZE; y++) { if (state->board[x][y] == 0) { moves[count].x = x; moves[count].y = y; count++; } } } return count; } int winner(GameState *state) { int lines[BOARD_SIZE][BOARD_SIZE][5][2] = {{{{0}}}}; int counts[3] = {0}; for (int x = 0; x < BOARD_SIZE; x++) { for (int y = 0; y < BOARD_SIZE; y++) { int p = state->board[x][y]; if (p == 0) { continue; } for (int i = 0; i < 5; i++) { if (x + i < BOARD_SIZE) { lines[x][y][i][0] = state->board[x + i][y]; } if (y + i < BOARD_SIZE) { lines[x][y][i][1] = state->board[x][y + i]; } } counts[p]++; } } if (counts[1] > counts[2] + 1) { return 2; } if (counts[2] > counts[1]) { return 1; } for (int x = 0; x < BOARD_SIZE; x++) { for (int y = 0; y < BOARD_SIZE; y++) { for (int i = 0; i < 5; i++) { int j; for (j = 0; j < 5; j++) { if (lines[x][y][j][0] != (i + j < 5 ? 0 : lines[x + j - i][y][i + j - 5][0])) { break; } } if (j == 5) { return lines[x][y][0][0]; } for (j = 0; j < 5; j++) { if (lines[x][y][j][1] != (i + j < 5 ? 0 : lines[x][y + j - i][i + j - 5][1])) { break; } } if (j == 5) { return lines[x][y][0][1]; } } } } if (counts[1] + counts[2] == BOARD_SIZE * BOARD_SIZE) { return 0; } return -1; } void play_move(GameState *state, Point move) { state->board[move.x][move.y] = state->next_player; state->next_player = opposite(state->next_player); } Node *new_node(Node *parent, Point move) { Node *node = (Node *) malloc(sizeof(Node)); node->wins = 0; node->plays = 0; node->move = move; node->parent = parent; for (int i = 0; i < MAX_PLAYS; i++) { node->children[i] = NULL; } return node; } void free_tree(Node *node) { for (int i = 0; i < MAX_PLAYS; i++) { if (node->children[i] != NULL) { free_tree(node->children[i]); } } free(node); } int random_playout(GameState *state) { GameState *copy = (GameState *) malloc(sizeof(GameState)); *copy = *state; int result = -1; while (result == -1) { Point moves[MAX_PLAYS]; int count = legal_moves(copy, moves); if (count == 0) { break; } Point move = moves[rand() % count]; play_move(copy, move); result = winner(copy); } free(copy); if (result == -1) { return 0; } if (result == 0) { return 1; } return result == 1 ? -1 : 1; } Node *best_child(Node *node) { double best_score = -1; Node *best_child = NULL; for (int i = 0; i < MAX_PLAYS; i++) { Node *child = node->children[i]; if (child == NULL) { continue; } double score = (double) child->wins / child->plays + UCB_C * sqrt(log(node->plays) / child->plays); if (score > best_score) { best_score = score; best_child = child; } } return best_child; } Node *tree_policy(GameState *state, Node *node) { while (winner(state) == -1) { Point moves[MAX_PLAYS]; int count = legal_moves(state, moves); if (count == 0) { break; } int unexplored = 0; for (int i = 0; i < count; i++) { Point move = moves[i]; int found = 0; for (int j = 0; j < MAX_PLAYS; j++) { if (node->children[j] != NULL && node->children[j]->move.x == move.x && node->children[j]->move.y == move.y) { node = node->children[j]; found = 1; break; } } if (!found) { unexplored = 1; break; } } if (unexplored) { Point move = moves[rand() % count]; node->children[node->plays] = new_node(node, move); node = node->children[node->plays]; } else { node = best_child(node); } play_move(state, node->move); node->plays++; } return node; } void backpropagate(Node *node, int result) { while (node != NULL) { node->wins += result; node->plays++; node = node->parent; result = -result; } } Point select_move(GameState *state, int iterations) { Node *root = new_node(NULL, (Point) {0, 0}); root->plays = 1; for (int i = 0; i < iterations; i++) { GameState *copy = (GameState *) malloc(sizeof(GameState)); *copy = *state; Node *node = tree_policy(copy, root); int result = random_playout(copy); backpropagate(node, result); free(copy); } double best_score = -1; Point best_move = (Point) {-1, -1}; for (int i = 0; i < MAX_PLAYS; i++) { Node *child = root->children[i]; if (child == NULL) { continue; } double score = (double) child->wins / child->plays; if (score > best_score) { best_score = score; best_move = child->move; } } free_tree(root); return best_move; } void print_board(GameState *state) { for (int y = 0; y < BOARD_SIZE; y++) { for (int x = 0; x < BOARD_SIZE; x++) { printf("%c", state->board[x][y] == 1 ? 'X' : state->board[x][y] == 2 ? 'O' : '-'); } printf("\n"); } } int main() { srand(time(NULL)); GameState state = {0}; while (winner(&state) == -1) { print_board(&state); if (state.next_player == 1) { Point move; printf("Enter move: "); scanf("%d %d", &move.x, &move.y); play_move(&state, move); } else { Point move = select_move(&state, 10000); printf("Computer plays: %d %d\n", move.x, move.y); play_move(&state, move); } } print_board(&state); int w = winner(&state); printf("%s wins\n", w == 0 ? "Draw" : w == 1 ? "X" : "O"); return 0; } ``` 该示例代码实现了五子棋蒙特卡洛树搜索,包括游戏状态表示、棋盘的打印、对局的进行(玩家输入和AI自动选择)、胜负判断等功能。其核心是通过蒙特卡洛树搜索来选择AI的下一步棋子位置,具体实现包括: - `new_node`:创建一个新的节点。 - `legal_moves`:获取当前状态下所有合法的落子位置。 - `winner`:判断当前状态下的胜负情况。 - `play_move`:在当前状态下落子。 - `random_playout`:执行一次随机模拟,返回胜负结果。 - `best_child`:找到当前节点中最优的子节点。 - `tree_policy`:根据当前状态和节点,选择下一个要扩展的节点,并返回最终的节点。 - `backpropagate`:在树中回溯更新节点的胜负统计信息。 - `select_move`:根据当前状态,执行多次蒙特卡洛树搜索,返回AI的落子位置。 该示例代码使用了UCB算法来计算节点选择的得分,即使用节点的胜率和置信度上限来决定节点的优先级。经过大量的模拟对局,蒙特卡洛树搜索可以搜索到更深的状态空间,从而提高AI的胜率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值