(保守群组测试 非保守群组测试 二次重复测试 自适应二次重复测试)四种群体测试的C++代码

目录

  • 原理
    • 保守组检测
    • 非保守组检测
    • 二次重复测试
    • 自适应二次重复测试
  • 四种测试方法的核心代码
    • 保守群组测试
    • 非保守群组测试
    • 二次重复测试与自适应二次重复测试
    • 测试代码
  • 参考文献

原理

假设该病在人群中的患病率(先验概率)为p,我们想用群体检验法检验N个独立样本组大小n,即样本数量。
单个试验的诊断方法的FNR用fN表示,FPR可忽略不计。
用G表示一组样本,G=0表示G中的所有样本均未感染。相反,G=1意味着G是一个阳性组;即,它至少有一个感染标本。通过观察不同方法的分组试验结果,我们将一个组分为感染组和未感染组,分别用Gˆ=1和Gˆ=0表示。

保守组检测

在这里插入图片描述
在这里插入图片描述

非保守组检测

在这里插入图片描述

步骤如下:
在这里插入图片描述
每个Group由三个sample人的血液组成。
这样能保证每个Group能被测试两次(也代表着每个sample人的血液能够被测试两次),fN表示单个试验的FNR(false negative rate),这样就能保证Sg(群体水平敏感度)= 1 - fN^2;
总的来说,Gi、Gi+1为阳性,则Mi,i+1也为阳性。
这样,图1中的M2,3和M3,4都是正的,很可能是因为G3=1。尽管在G2=1和G4=1的情况下也会出现这些阳性结果,但缺少M1,2=1和M4,1=1使得G2和G4都不太可能等于1。在这种方法中,例如,如果G2为真阳性,M1,2=0为假阴性结果,我们将忽略G2=1,从而导致灵敏度降低。

在非保守组检测中有以下规则:
在这里插入图片描述

二次重复测试

简单来说就是对分组之后检测的所有组都检测两遍,只要有一次为阳则说明这个组中有阳性。
在这里插入图片描述

自适应二次重复测试

第二次测试将第一次测试中为阴性的进行测试。
在这里插入图片描述

四种测试方法的核心代码

【0】保守群组测试 【1】非保守群组测试 【2】二次重复测试 【3】二次自适应重复测试

保守群组测试

//非保守测试
//输入:splited_group 、 分组混合血液 、 假阴率 fnr
//输出:检测出来的阳性样本数、总检测次数
int No_Conservative_Group_Detection(vector<vector<int>>& splited_group,vector<int>& result, float fnr, vector<int>& Positive_Group, vector<int>& PositiveSamples)
{//将Gi、Gi+1混合到一起为Mi//如果相邻两个M(Mj,Mj+1)检测结果是阳性,则认定是Gj+1是阳性。//如果只有单独的Mj检测结果是阳性,则将Gj与Gj+1都检测一遍。int All_Test_Times = 0;//【step1】将G血液结果两两混合到M中vector<int> Mixed_Group_Result;for (int i = 0; i < result.size() - 1; i++){if (result[i] == 1 || result[i + 1] == 1)Mixed_Group_Result.emplace_back(1);else Mixed_Group_Result.emplace_back(0);}//第一个样本与最后一个样本混合if(result[0] == 1 || result[result.size()-1] == 1) Mixed_Group_Result.emplace_back(1);else Mixed_Group_Result.emplace_back(0);//【step2】对M结果进行检测,需要考虑到假阴性影响,得到阳性G序号vector<int> Blured_Mixed_Group_Result;Test_Synthetic_Blood(Mixed_Group_Result, Blured_Mixed_Group_Result, fnr);All_Test_Times += Mixed_Group_Result.size();//寻找检测结果为阳性的Mfor (int j = 0; j < Blured_Mixed_Group_Result.size() - 1; j++){//如果是两个连在一起的为阳性,取交集的Gif (Blured_Mixed_Group_Result[j] == 1 && Blured_Mixed_Group_Result[j + 1] == 1){Positive_Group.emplace_back(j+1);}else if(Blured_Mixed_Group_Result[j] == 1 && Blured_Mixed_Group_Result[j + 1] == 0){//如果Gj已经被送入结果,那么只需要再送入Gj+1if (!Positive_Group.empty() && Positive_Group.back() == j){Positive_Group.emplace_back(j + 1);}//否则,将两个都送入else{Positive_Group.emplace_back(j);Positive_Group.emplace_back(j + 1);}}}cout << "非保守测试可能为阳性的Group个数" << Positive_Group.size() << endl;//对每个可能阳性的Group进行核酸检测for (int i = 0; i < Positive_Group.size(); i++){int pos_index = Positive_Group[i];//对可能阳性Group中每个样本都进行检测,要考虑到假阴性的影响,得到阳性的样本的序号。vector<int> Blured_Splited_GroupResult;Test_Synthetic_Blood(splited_group[pos_index], Blured_Splited_GroupResult, fnr);//对检测结果进行记录,记录下在原序列中的坐标for (int j = 0; j < Blured_Splited_GroupResult.size(); j++){if (Blured_Splited_GroupResult[j] == 1){PositiveSamples.emplace_back(pos_index* splited_group[0].size() + j);}	}}All_Test_Times += Positive_Group.size() * splited_group[0].size();return All_Test_Times;}

非保守群组测试

//保守测试
//输入:splited_group 、 分组混合血液 、 假阴率 fnr
//输出:检测出来的阳性样本数、总检测次数
int Conservative_Group_Detection(vector<vector<int>>& splited_group, vector<int>& result, float fnr, vector<int>& Positive_Group, vector<int>& PositiveSamples)
{//将Gi、Gi+1混合到一起为Mi//如果M检测结果是阳性,则认定是Gj,Gj+1是阳性。int All_Test_Times = 0;//【step1】将G血液结果两两混合到M中vector<int> Mixed_Group_Result;for (int i = 0; i < result.size() - 1; i++){if (result[i] == 1 || result[i + 1] == 1)Mixed_Group_Result.emplace_back(1);elseMixed_Group_Result.emplace_back(0);}//第一个样本与最后一个样本混合if (result[0] == 1 || result[result.size() - 1] == 1) Mixed_Group_Result.emplace_back(1);else Mixed_Group_Result.emplace_back(0);//【step2】对M结果进行检测,需要考虑到假阴性影响,得到阳性G序号vector<int> Blured_Mixed_Group_Result;Test_Synthetic_Blood(Mixed_Group_Result, Blured_Mixed_Group_Result, fnr);All_Test_Times += Mixed_Group_Result.size();//寻找检测结果为阳性的Mfor (int j = 0; j < Blured_Mixed_Group_Result.size() - 1; j++){if (Blured_Mixed_Group_Result[j] == 1){if (!Positive_Group.empty() && Positive_Group.back() == j){Positive_Group.emplace_back(j + 1);}else{Positive_Group.emplace_back(j);Positive_Group.emplace_back(j + 1);}}}//对每个可能阳性的Group进行核酸检测cout << "保守测试可能为阳性的Group个数"<< Positive_Group.size() <<endl;for (int i = 0; i < Positive_Group.size(); i++){int pos_index = Positive_Group[i];//对可能阳性Group中每个样本都进行检测,要考虑到假阴性的影响,得到阳性的样本的序号。vector<int> Blured_Splited_GroupResult;Test_Synthetic_Blood(splited_group[pos_index], Blured_Splited_GroupResult, fnr);//对检测结果进行记录,记录下在原序列中的坐标for (int j = 0; j < Blured_Splited_GroupResult.size(); j++){if (Blured_Splited_GroupResult[j] == 1){PositiveSamples.emplace_back(pos_index * splited_group[0].size() + j);}}}All_Test_Times += Positive_Group.size() * splited_group[0].size();return All_Test_Times;}

二次重复测试与自适应二次重复测试

/*
* 重复二次测量
* 输入:result实际感染情况,blured_result第一次检测情况,rep_blured_result第二次检测情况
* 输出:
*/
void Replicate_Test(vector<int>& result, vector<int>& blured_result, vector<int>& rep_blured_result, float fnr)
{rep_blured_result.clear();srand((unsigned)time(NULL));int fnr_100 = fnr * 100;for (int i = 0; i < result.size(); i++) //第二次全覆盖测试{//对每个阳性样本进行混淆处理if (result[i] == 1){int num = rand() % 100;// r % 概率检测为阴性if (num <= fnr_100){rep_blured_result.emplace_back(0);}//1-fnr%概率检测为阳性else{rep_blured_result.emplace_back(1);}}//由于covid-19不存在假阳性,这里对阴性样本不做处理else{rep_blured_result.emplace_back(0);}}for (int i = 0; i < result.size(); i++) { //将第一第二次的检测结果合并if (blured_result[i] == 1) {rep_blured_result[i] = 1;}}return;
}
/*
* 自适应重复二次测量,对象为第一次测量中为阴性的组
* 输入:result实际感染情况,blured_result第一次检测情况,rep_blured_result第二次检测情况
* 输出:二次测量的测量数
*/
int Adt_Replicate_Test(vector<int>& result, vector<int>& blured_result, vector<int>& rep_blured_result, float fnr) {rep_blured_result.clear();srand((unsigned)time(NULL));int fnr_100 = fnr * 100;int Test_Times = 0;for (int i = 0; i < blured_result.size(); i++){//对第一次检测结果再进行挑选检测if (blured_result[i] == 1) //第一次检测为阳性,跳过检测{rep_blured_result.emplace_back(1);}else  //第一次检测为阴性,再次检测{Test_Times++;if (result[i] == 1) {int num = rand() % 100;// r % 概率检测为阴性if (num <= fnr_100){rep_blured_result.emplace_back(0);}//1-fnr%概率检测为阳性else{rep_blured_result.emplace_back(1);}}else rep_blured_result.emplace_back(0);}}return Test_Times;
}/*
* 重复二次测量
* 输入:splited_group分组,result实际感染情况,fnr假阴率,Positive_Group二次测量后的阳性组,PositiveSamples二次测量后的阳性样本,Mode方法模式,0为重复二次测量,1为自适应重复二次测量
* 输出:
*/
int Replicate_TestDetection(vector<vector<int>>& splited_group, vector<int>& result, float fnr, vector<int>& Positive_Group, vector<int>& PositiveSamples,int Mode)
{//将Gi、Gi+1混合到一起为Mi//如果M检测结果是阳性,则认定是Gj,Gj+1是阳性。int All_Test_Times = 0;//【step1】将G血液结果两两混合到M中vector<int> Mixed_Group_Result;for (int i = 0; i < result.size() - 1; i++){if (result[i] == 1 || result[i + 1] == 1)Mixed_Group_Result.emplace_back(1);elseMixed_Group_Result.emplace_back(0);}//第一个样本与最后一个样本混合if (result[0] == 1 || result[result.size() - 1] == 1) Mixed_Group_Result.emplace_back(1);else Mixed_Group_Result.emplace_back(0);vector<int> Blured_Mixed_Group_Result;//第一次检测Test_Synthetic_Blood(Mixed_Group_Result, Blured_Mixed_Group_Result, fnr);All_Test_Times += Mixed_Group_Result.size();vector<int> Sec_Blured_Mixed_Group_Result;if (Mode == 0){//第二次检测,采用重复二次测量Replicate_Test(result, Blured_Mixed_Group_Result, Sec_Blured_Mixed_Group_Result, fnr);All_Test_Times += Blured_Mixed_Group_Result.size();}else{//第二次检测,采用自适应重复二次测量,对象为第一次测量中为阴性的组int Sec_Test_Times = Adt_Replicate_Test(result, Blured_Mixed_Group_Result, Sec_Blured_Mixed_Group_Result, fnr);All_Test_Times += Sec_Test_Times;}//记录二次结果后的阳性组for (int i = 0; i < Sec_Blured_Mixed_Group_Result.size(); i++){if (Sec_Blured_Mixed_Group_Result[i] == 1) Positive_Group.emplace_back(i);}//对每个可能阳性的Group进行核酸检测cout << "二次重复测试可能为阳性的Group个数" << Positive_Group.size() << endl;for (int i = 0; i < Positive_Group.size(); i++){int pos_index = Positive_Group[i];//对可能阳性Group中每个样本都进行检测,要考虑到假阴性的影响,得到阳性的样本的序号。vector<int> Blured_Splited_GroupResult;Test_Synthetic_Blood(splited_group[pos_index], Blured_Splited_GroupResult, fnr);//对检测结果进行记录,记录下在原序列中的坐标for (int j = 0; j < Blured_Splited_GroupResult.size(); j++){if (Blured_Splited_GroupResult[j] == 1){PositiveSamples.emplace_back(pos_index * splited_group[0].size() + j);}}}All_Test_Times += Positive_Group.size() * splited_group[0].size();return All_Test_Times;
}

测试代码

	//检测总人数int sample_nums = 175000;//流行率设定double p = 0.04;//分组设定int sec_group_sample_nums =2;//假阴率设定float FNR = 0.2;int positive_sample_nums = p * sample_nums;if (sample_nums <= 0){cout <<"error1" <<endl;return 0;}sec_group_sample_nums = pow(2, i + 1);vector<int> Group(sample_nums, 0);//混合血液后的真实结果vector<int> Result;//受到假阴性影响后的混合血液测试结果vector<int> Blured_Result;vector<vector<int>> Splited_Group;//【1】初始化样本序列Initial_Group(Group, positive_sample_nums);//Pirnt_Group(Group);cout << endl;//【2】Pooling操作Split_Group(Group, Splited_Group, sec_group_sample_nums);//Pirnt_Split_Group(Splited_Group);cout << endl;//【3】混合血液Synthetic_Blood(Splited_Group, Result);vector<int> Positive_Group;vector<int> PositiveSamples;int All_Test_Times = 0;int Methods = 3;//【4】使用不同的测试方法switch (Methods){//【0】保守群组测试case 0:{All_Test_Times = Conservative_Group_Detection(Splited_Group, Result, FNR, Positive_Group, PositiveSamples);cout << "重复性测试总检测次数" << All_Test_Times << endl;if (positive_sample_nums != 0)cout << "检测出的阳性样本个数为" << PositiveSamples.size() << "准确率" << PositiveSamples.size() * 1.0f / positive_sample_nums << endl;elsecout << "error2" << endl;}break;//【1】非保守群组测试case 1:{All_Test_Times = No_Conservative_Group_Detection(Splited_Group, Result, FNR, Positive_Group, PositiveSamples);cout << "非重复性测试总检测次数" << All_Test_Times << endl;if (positive_sample_nums != 0)cout << "检测出的阳性样本个数为" << PositiveSamples.size() << "准确率" << PositiveSamples.size() * 1.0f / positive_sample_nums << endl;elsecout << "error2" << endl;}break;//【2】二次重复测试case 2:{All_Test_Times = Replicate_TestDetection(Splited_Group, Result, FNR, Positive_Group, PositiveSamples, 0);cout << "重复性测试总检测次数" << All_Test_Times << endl;cout << "阳性样本组数" << Positive_Group.size() << endl;if (positive_sample_nums != 0)cout << "检测出的阳性样本个数为" << PositiveSamples.size() << "准确率" << PositiveSamples.size() * 1.0f / positive_sample_nums << endl;elsecout << "error2" << endl;}break;//【3】二次自适应重复测试case 3:{All_Test_Times = Replicate_TestDetection(Splited_Group, Result, FNR, Positive_Group, PositiveSamples, 1);cout << "重复性测试总检测次数" << All_Test_Times << endl;if (positive_sample_nums != 0)cout << "检测出的阳性样本个数为" << PositiveSamples.size() << "准确率" << PositiveSamples.size() * 1.0f / positive_sample_nums << endl;elsecout << "error2" << endl;}break;default:break;}//根据仿真得出一个测试实际社会成本(即找出最后为阴性的组数/总组数*每组多少人*每个人的闲置成本)int Neg_Groups = Splited_Group.size() - Positive_Group.size();double Neg_rate = Neg_Groups * 1.0f / Splited_Group.size();cout << "Neg_rate " << Neg_rate << endl;cout << "总样本个数 " << Splited_Group.size() << endl;

参考文献

https://www.medrxiv.org/content/10.1101/2020.07.31.20154070v1

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AngularJS中的表达式

AngularJS表达式 (AngularJS Expressions) In AngularJS, expressions are solved to give a result. It outputs the result of the expression in the html element that called it. Expressions in AngularJS contain literals, constants, operators and variables with re…

学习总结:机器学习(一)

有监督学习&#xff08;Supervised Learning&#xff09;所谓有监督学习&#xff0c;是区别于无监督学习而言的。其过程如下&#xff1a;给定一系列样本&#xff0c;样本是由一系列特征值和输出值组成。比如&#xff0c;某个地方的商品房&#xff0c;包括房子大小、房间数、距离…

WPS双栏格式下插入单栏图片

以一个我认识的西工大博士大佬的一篇SCI为例&#xff0c;期刊是双栏&#xff0c;图片过大&#xff0c;需要单栏进行展示&#xff0c;效果图如下&#xff1a; 一、双栏内容 二、插入单栏图像 随便敲几个字&#xff0c;选中&#xff0c; 页面布局----分栏---一栏 这行字就会…

JavaScript中的数组

Here we are discussing one of the most useful data structure, Array. 在这里&#xff0c;我们讨论最有用的数据结构之一Array 。 By conventional definition of arrays, "Arrays are the homogeneous collection of data types. But in JS, Arrays simply are the c…

WPS根据章节编号依次排序

第Ⅲ章节有四小部分&#xff0c;分别为A、B、C、D 第Ⅳ章节要重新开始编号&#xff0c;从A开始 操作步骤&#xff1a; ①再D后面回车&#xff08;红线位置回车&#xff09;&#xff0c;生成E ②把Ⅳ中待写内容写到E中 ③将E复制到Ⅳ下&#xff0c;这里需要注意D的换行也要复制…

【C++基础】异常匹配与内建异常类

目录异常匹配catch: 按异常类型匹配为何要使用异常类内建异常类标准库中的异常基类标准库中的异常类例1&#xff1a;vector下标访问越界out_of_range异常例2&#xff1a;内存分配失败bad_alloc异常例3&#xff1a;侧向转换失败bad_cast异常类几种情况&#xff0c;使用对应异常异…

小试---EF5.0入门实例1

现在做个小练习吧~~~ 第一步&#xff1a;首先新建一个数据库名字为Test;数据库里面只有一个表UserTable 脚本为&#xff1a; USE [master] GO /****** 对象: Database [Test] 脚本日期: 12/15/2013 18:51:54 ******/ CREATE DATABASE [Test] ON PRIMARY ( NAME NTest, F…

iScroll4 禁止select等页面元素默认事件的解决方法 转

iScroll4 禁止select等页面元素默认事件的解决方法起因在于onBeforeScrollStart : function(e){ e.preventDefault(); },这一行&#xff0c;iSroll禁止了事件的默认行为&#xff0c;导致select&#xff0c;option&#xff0c;textarea等元素无法点击。解决方法也很简单&#xf…

MPEG的完整形式是什么?

MPEG&#xff1a;运动图像专家组 (MPEG: Moving Picture Experts Group) MPEG is an abbreviation of Moving Picture Experts Group. It is a working group of authorities that is founded to establish standards for audio and video compression and transmission. The a…

安利一款倒计时插件---雨滴桌面

内容来自B站(搜索Rainmeter即可)&#xff0c;里面教程很多&#xff0c;因为视频看的有点麻烦&#xff0c;故进行了整理 一、下载安装包、解压、安装 免费下载连接&#xff0c;不需要积分 skin文件夹存放皮肤的一些配置文件&#xff0c;因为原本皮肤太low了 第二个是可执行文…

【C++基础】自定义异常类与多重捕获

目录自定义异常类构建过程例&#xff1a;Vec3D类的数组下标越界的异常类捕获多种无关异常不同的异常的捕获捕获派生异常异常处理的次序例子&#xff1a;多重捕获异常类catch块的参数类型可以不用引用类型吗?自定义异常类 自定义异常类通常由exception或其后代类派生。这样我们…

gprs 睡眠模式_GPRS的完整形式是什么?

gprs 睡眠模式GPRS&#xff1a;通用分组无线业务 (GPRS: General Packet Radio Service) GPRS is an abbreviation of General Packet Radio Service. It is a non-voice, high-level speed packet switching technology planned for GSM networks. On 2G and 3G cellular tran…

【C++基础】C++11的noexcept声明符 与 异常传播

目录C noexcept&#xff1a;1、用途2、用法1、noexcept声明符的用法&#xff1a;2、noexcept运算符的用法异常传播1、异常传播的定义2、异常传播中的规则3、异常传播的代价C noexcept&#xff1a; 1、用途 C11使用noexcept指明函数是否抛出异常&#xff1a; 若函数不抛异常&a…

CSS中的文本格式

CSS文字格式 (CSS text formatting) CSS text properties allow you to style your text in various ways very easily. Such as color, alignment, spacing, direction, etc. CSS文本属性使您可以轻松地以各种方式设置文本样式。 例如颜色 &#xff0c; 对齐方式 &#xff0c;…

CSS简写指南

1.margin 1.1 margin:1px 2px 3px(上 左右 下) 1.2 margin:2px 3px(上下 左右) 1.2 margin:1px 3px 2px 3px(上右下左) 2.padding(同上) 3.border border:1px red solid (border-width border-color border-style) 1 2 3border-width&#xff1a;1px 2px 3px; //最多可用四个值…

【C++基础】模板基础与函数模板

目录初识模板函数模板函数模板实例化显式实例化隐式实例化初识模板 求两个int、float、char类型的数据的最大值&#xff1a; C里面要这样写&#xff1a; int maxInt(int x, int y); double maxDouble(double x, double y); char maxChar(char x, char y);C使用函数重载&#…

TAFE的完整形式是什么?

TAFE&#xff1a;拖拉机和农用设备 (TAFE: Tractors and Farm Equipment) TAFE is an abbreviation of Tractors and Farm Equipment Limited. It is an Indian tractor manufacturer which is founded at Chennai in 1960. It is the second-largest tractor manufacturer in …

【C++基础】 类模板

类模板 模板是将类中某些类型变为泛型&#xff0c;从而定义一个模板。 如下&#xff1a; 类模板的语法 直接进行对比&#xff1a; 泛型化之前 泛型化之后类模板的实例化 注意&#xff1a;只要是对类模版进行实例化&#xff0c;编译器就会生成一个类&#xff01;&#xff0…

cocos2d-x游戏开发系列教程-中国象棋02-main函数和欢迎页面

之前两个博客讲述了象棋的规格和工程文件之后&#xff0c;我们继续深入的从代码开始学习cocos2dx首先从程序入口main函数开始main函数int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow) {UNREFERENCED_PARAMETER(h…

【C++基础】模板参数与模板继承

模板参数 默认类型参数 函数参数可以设定一个默认值&#xff0c;我们现在可以对类模板的类型参数设定一个默认类型。 指定泛型Stack的默认类型参数为 int template<typename T int> class Stack{... };当我们这样定义一个对象时&#xff1a; Stack<> stack;使…