使用蒙特卡洛模拟和并查集求解渗透阈值

代码由C++语言编写

我使用了三个类,分别如下

第一个类,实现了并查集的基本操作。

#pragma once#include<iostream>
#include<vector>
using namespace std;class UnionFind
{
public:vector<int> parent; // 用于存储父节点vector<int> rank; // 结点所在集合的树高// 构造函数UnionFind(int size);// 查询根节点int find(int x);// 合并集合void unionSets(int x, int y);// 检查两个结点是否在同一个集合中bool connected(int x, int y);};
#include "UnionFind.h"// 构造函数,初始化parent和rank数组
UnionFind::UnionFind(int size) : parent(size), rank(size, 1) 
{for (int i = 0; i < size; ++i) parent[i] = i;
}// find函数,返回父节点的同时实现路径压缩
// 压缩:将路径上所有的节点都连接到最终的根节点上
// 递归实现
int UnionFind::find(int x)
{if (parent[x] != x)parent[x] = find(parent[x]);return parent[x];
}// 合并集合
// 将集合树低的集合并到树高的集合上,避免树太高
void UnionFind::unionSets(int x, int y) 
{int rootX = find(x);int rootY = find(y);if (rootX != rootY) {if (rank[rootX] < rank[rootY]) parent[rootX] = rootY;else if (rank[rootX] > rank[rootY])parent[rootY] = rootX;else {parent[rootX] = rootY;rank[rootX]++;}}
}// 单纯检查两个结点是否在同一个集合里
bool UnionFind::connected(int x, int y)
{return find(x) == find(y);
}

第二个类,实现给定具体矩阵时,判断是否渗透。

#pragma once
#include<iostream>
#include<vector>
using namespace std;
# include "UnionFind.h"class Solve
{
public:int m_rows; // 成员变量,给定矩阵的行和列int m_cols;vector<vector<int>> m_grid; // 拷贝一份给定矩阵// 利用并查集的方法将矩阵中的0划分为几个集合Solve(vector<vector<int>> grid);// 判断头结点和尾结点是否在一个集合里,也就是返回是否渗透bool isConnected();};
#include "Solve.h"Solve::Solve(vector<vector<int>> grid)
{m_grid = grid;m_rows = m_grid.size();m_cols = m_grid[0].size();
}bool Solve::isConnected()
{// 额外两个节点,分别用于连接第一行和最后一行//  m_rows * m_cols连接第一行,m_rows * m_cols + 1连接最后一行// 给矩阵编号为// m_rows * m_cols// 0	1	 2// 3	4	 5// 6	7	 8// m_rows * m_cols + 1UnionFind uf(m_rows * m_cols + 2);int head = m_rows * m_cols;int tail = m_rows * m_cols + 1;// unionSets函数最终是以第二个参数的根节点作为合并后的根节点的// 初始化第一行for (int i = 0; i < m_cols; i++){if (m_grid[0][i] == 0)uf.unionSets(i, head);}// 初始化最后一行for (int i = 0; i < m_cols; i++){if (m_grid[m_rows - 1][i] == 0)uf.unionSets((m_rows - 1) * m_cols + i, tail);}for (int i = 1; i < m_rows; i++){for (int j = 0; j < m_cols; j++){if (m_grid[i][j] == 0){// 将相邻的0合并为一个集合if (m_grid[i - 1][j] == 0)uf.unionSets(i * m_cols + j, (i - 1) * m_cols + j);if (j - 1 >= 0 && m_grid[i][j - 1] == 0)uf.unionSets(i * m_cols + j, i * m_cols + j - 1);}}}return uf.connected(head, tail);
}

第三个类,用于生成随机矩阵

#pragma once
#include <iostream>
#include <vector>  
#include <random>  
using namespace std;class CreatMatrix
{
public:int m_rows;int m_cols;double m_prob_zero;CreatMatrix(int rows, int cols, double prob_zero);vector<vector<int>> creatMatrix();};
#include "CreatMatrix.h"CreatMatrix::CreatMatrix(int rows, int cols, double prob_zero)
{// 假设的数组大小  m_rows = rows;m_cols = cols;// 0出现的概率  m_prob_zero = prob_zero;
}vector<vector<int>> CreatMatrix::creatMatrix()
{// 创建一个二维vector  vector<vector<int>> matrix(m_rows, vector<int>(m_cols));// 初始化随机数生成器  random_device rd;  // 用于获取随机数种子  mt19937 gen(rd()); // 以随机数种子初始化Mersenne Twister生成器  uniform_real_distribution<> dis(0.0, 1.0); // 分布范围在[0.0, 1.0)  // 填充二维数组  for (int i = 0; i < m_rows; ++i) {for (int j = 0; j < m_cols; ++j) {// 生成一个[0.0, 1.0)之间的随机数  double random_value = dis(gen);// 根据概率决定是0还是1  if (random_value < m_prob_zero) {matrix[i][j] = 0;}else {matrix[i][j] = 1;}}}return matrix;
}

主函数

#include "UnionFind.h"
#include "Solve.h"
#include "example.h"
#include "CreatMatrix.h"
#include <chrono>  
#include <fstream>
#include <string>using namespace std;int main()
{double path_length = 0.01; // 步长,用于for循环中0结点出现概率的递增int num_experiment = 1000; //对每种概率下的矩阵判断渗透的次数int matrix_row = 200; // 矩阵行int matrix_col = 200; // 矩阵列// 记录开始时间  auto start = std::chrono::high_resolution_clock::now();// 创建csv文件// CSV(逗号分隔值)文件是一种非常通用的文件格式,可以被多种程序读取,包括Python。// 定义CSV文件的路径  string csvFilePath = "your_path";// 创建一个ofstream对象来写入文件  ofstream csvFile(csvFilePath);if (!csvFile.is_open()) {cerr << "Unable to open file";return 1;}// 创建两个数组// 第一个是每次零出现的概率// 第二个是在这个概率下,实验一千次有多少次成功连通int documents = 1.0 / path_length; // 记录次数vector<double> probabilities;probabilities.reserve(documents);vector<int> counts;counts.reserve(documents);// 写入CSV头部csvFile << "Probability,Connected Count\n";for (double prob = 0; prob <= 1; prob += path_length){// 用于记录成功渗透的次数int count = 0;for (int times = 0; times < num_experiment; times++){CreatMatrix cm(matrix_row, matrix_col, prob);vector<vector<int>> grid = cm.creatMatrix();Solve solve(grid);if (solve.isConnected())count++;cout << "这是" << prob << "概率下第" << times << "次实验" << endl;}probabilities.push_back(prob);counts.push_back(count);}for (size_t i = 0; i < documents; i++) {csvFile << probabilities[i] << "," << counts[i] << "\n";}csvFile.close();std::cout << "CSV文件已创建并写入数据。" << std::endl;//if (solve.isConnected()) //	cout << "第一行和最后一行的0是连通的" << endl;//else //	cout << "第一行和最后一行的0不是连通的" << endl;// 记录结束时间  auto end = std::chrono::high_resolution_clock::now();// 计算时间差  std::chrono::duration<double, std::milli> elapsed = end - start;// 输出运行时间(以毫秒为单位)  std::cout << "程序运行时间: " << elapsed.count() << " 毫秒" << std::endl;return 0;
}

csv文件部分截图

最后使用python读取这个文件,并绘图

确保你的python安装了pandas和matplotlib库

pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple
import pandas as pd
import matplotlib.pyplot as plt# 读取CSV文件
path = r"your_path"
data = pd.read_csv(path)# 绘图
# 长10,宽5
plt.figure(figsize=(10, 6))
plt.plot(data['Probability'], data['Connected Count'], marker='o')
plt.title('Connectivity Counts vs Probability')
plt.xlabel('Probability')
plt.ylabel('Connected Count')
plt.grid(True)
plt.show()

结果截图(200 * 200 , 0.01, 1000)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1540884.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

生物信息常用编辑器:轻量高效的VS Code

在生物信息学中&#xff0c;编写和调试代码是日常工作的一部分&#xff0c;选择一个合适的编辑器能极大提升效率。Visual Studio Code&#xff08;简称VS Code&#xff09;是一款轻量、灵活且功能强大的代码编辑器&#xff0c;广受开发者欢迎。本文将为大家介绍VS Code的主要功…

50.面向对象进阶训练-学生类

//定义一个长度为3的数组&#xff0c;存储1-3名学生对象作为初始数据 //学生属性&#xff1a;学号 姓名 年龄&#xff0c;其中学号姓名各不相同 //要求&#xff1a;1.再次添加一个学生对象&#xff0c;并在添加的时候进行学号的唯一性判断//2.添加完毕之后&#xff0c;遍历所有…

企业急于采用人工智能,忽视了安全强化

对主要云提供商基础设施上托管的资产的安全分析显示&#xff0c;许多公司为了急于构建和部署 AI 应用程序而打开安全漏洞。常见的发现包括对 AI 相关服务使用默认且可能不安全的设置、部署易受攻击的 AI 软件包以及不遵循安全强化指南。 这项分析由 Orca Security 的研究人员进…

重回极简:华为如何走向全面智能化?

“人类发现地球只是宇宙一员的时候&#xff0c;也是我们距离群星最遥远的时候。” 这个来自天文领域的喟叹&#xff0c;今天同样出现在行业与企业的智能化之路上。在这个时代坐标上&#xff0c;AI大模型技术极速成熟&#xff0c;AIGC和AI Agent等应用受到了各个行业的巨大期待。…

SpringBoot 数据库表结构文档生成

官方地址&#xff1a;https://github.com/pingfangushi/screw screw 螺丝钉&#xff0c;支持以下数据库 MySQL MariaDB TIDB Oracle SqlServer PostgreSQL Cache DB&#xff08;2016&#xff09; 生产文档支持 html word markdown 开始 添加依赖 <!-- 螺丝钉 --><…

PyCharm部分快捷键冲突问题

1.问题起因 今天在用PyCharm&#xff0c;编写python程序的时候&#xff0c;发现快捷间冲突&#xff0c;随后在CSDN上查找了一些资料&#xff0c;博主第一个说是搜狗输入法冲突&#xff0c;经过其内容尝试之后发现并不是这样啊&#xff0c;然后我有进行了一些资料案例的查询&am…

【第十三章:Sentosa_DSML社区版-机器学习聚类】

目录 【第十三章&#xff1a;Sentosa_DSML社区版-机器学习聚类】 13.1 KMeans聚类 13.2 二分KMeans聚类 13.3 高斯混合聚类 13.4 模糊C均值聚类 13.5 Canopy聚类 13.6 Canopy-KMeans聚类 13.7 文档主题生成模型聚类 13.8 谱聚类 【第十三章&#xff1a;Sentosa_DSML社…

VUE3配置路由(超级详细)

第一步创建vue3的项目

低代码可视化工具--vue条件判断v-if可视化设置-代码生成器

在Vue UniApp中&#xff0c;条件判断通常是通过指令v-if、v-else-if、v-else来实现的。这些机制允许你根据表达式的真假值来决定是否渲染某个元素或元素组&#xff0c;或者执行特定的逻辑。 条件判断说明 v-if 是惰性的&#xff1a;如果在初始渲染时条件为假&#xff0c;则什么…

Obsidian 全部笔记共享配置文件,obsidian仓库-文件夹配置统一化

obsidian仓库-文件夹配置统一化 在每次新建obsidian仓库(vaults)时&#xff0c;仓库的主题和快捷键等都需要重新设置&#xff0c;这是因为每次创建新的仓库时 新仓库的配置文件都是默认配置但是如果通过复制粘贴旧配置文件来达到新仓库的配置和旧仓库一致的话&#xff0c;无法…

Shiro-721—漏洞分析(CVE-2019-12422)

文章目录 Padding Oracle Attack 原理PKCS5填充怎么爆破攻击 漏洞原理源码分析漏洞复现 本文基于shiro550漏洞基础上分析&#xff0c;建议先看上期内容&#xff1a; https://blog.csdn.net/weixin_60521036/article/details/142373353 Padding Oracle Attack 原理 网上看了很多…

cmake--get_filename_component

作用 按照指定的方式获取文件或者目录的信息。 使用 get_filename_component(<variable> <filename> <component>) variable: 用于保存提取的信息。 filename: 指定路径的文件或者目录。 component: 链接1 component DIRECTORY: 提取文件或者目录的父…

Qwen 个人笔记

Qwen 个人笔记 Qwen的整体架构与Llama2类似&#xff0c;如下图所示: 1 Qwen2Config 1.1 Model 1.1.1 初始化 设置了模型的两个属性:padding_idx&#xff08;用于指定填充标记的索引&#xff09;&#xff0c;vocab_size&#xff08;词汇表的大小&#xff09;初始化了模型的…

关于“华为杯”第二十一届中国研究生数学建模竞赛赛题下载及提交作品的重要提醒

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 各参赛队伍&#xff1a; “华为杯”第二十一届中国研究生数学建模竞赛即将于2024年…

java重点学习-设计模式

十三 设计模式 工厂模式&#xff1a;spring中使用&#xff08;目的是&#xff1a;解耦&#xff09; 1.简单工厂 所有的产品都共有一个工厂&#xff0c;如果新增产品&#xff0c;则需要修改代码&#xff0c;违反开闭原则是一种编程习惯&#xff0c;可以借鉴这种编程思路 2.工厂方…

Transformer模型-5-Multi-Head Attention

上图红色圈中的部分为 Multi-Head Attention&#xff0c;是由多个Self-Attention组成的&#xff0c;虽然Encoder与Decoder中都有Multi-Head Attention&#xff0c;但他们略有区别。Encoder block包含一个 Multi-Head Attention&#xff0c; 而Decoder block包含两个 Multi-Head…

jenkins声明式流水线语法详解

最基本的语法包含 pipeline&#xff1a;所有有效的声明式流水线必须包含在一个 pipeline 块中stages&#xff1a;包含一系列一个或多个stage指令stage&#xff1a;stage包含在stages中进行&#xff0c;比如某个阶段steps&#xff1a;在阶段中具体得执行操作&#xff0c;一个或…

gcc配合cython编译python源代码

以前我们一般用Nuitka或者Pyinstaller来将python源码编译成二进制可执行文件。今天我们学习如何直接用gcc来编译。 很简单的一个python程序&#xff0c;结构如下。包含一个model.py和main.py 步骤1&#xff1a;处理main.py 处理main.py。即主程序入口 cython -D -2 --embe…

界面控件Telerik UI for WinForms 2024 Q3概览 - 支持合并单元格等

Telerik UI for WinForms拥有适用Windows Forms的110多个令人惊叹的UI控件。所有的UI for WinForms控件都具有完整的主题支持&#xff0c;可以轻松地帮助开发人员在桌面和平板电脑应用程序提供一致美观的下一代用户体验。 本文将介绍界面组件Telerik UI for WinForms在今年第一…

Linux 系统进程理解——标识符,状态

目录 进程描述-pcb 并行与并发 概念&#xff1a; 课本概念&#xff1a;程序的一个执行实例&#xff0c;正在执行的程序等 内核观点&#xff1a;担当分配系统资源&#xff08;CPU时间&#xff0c;内存&#xff09;的实体 这短短的两行就概括了进程&#xff0c;但是进程的内在…