(保守群組測試 非保守群組測試 二次重復測試 自適應二次重復測試)四種群體測試的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.pswp.cn/news/377434.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/377434.shtml
英文地址,請注明出處:http://en.pswp.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;包括房子大小、房間數、距離…

Silverlight讀取與設置Cookies

Silverlight讀取與設置Cookies 設置Cookie DateTime expire DateTime.UtcNow TimeSpan.FromDays(30);string cookie string.Formate("{0}{1},expires{2}",key,value,expire)HtmlPage.SetProperty("cookie",cookie);讀取Cookie 由于讀取到的Cookie是一個…

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…

【C++基礎】異常處理機制概要

目錄C的異常處理方法知識要點踹扔抓的代碼塊示例兩種處理被0除的方法異常處理機制的優點其他語言中的異常處理C函數異常聲明C的異常處理方法知識要點 理解“踹扔抓”三部曲的結構&#xff0c;尤其是catch是怎么匹配異常的。 知道C標準庫中的異常類都是從exception繼承下來的&am…

[轉載]Struts2 獲得Session和Request

轉自http://www.blogjava.net/lyyb2001/archive/2008/03/07/184593.html 在struts1中&#xff0c;獲得到系統的request或者session對象非常方便&#xff0c;都是按照形參傳遞的&#xff0c;但是在struts2中&#xff0c;request和session都被隱藏了struts提供兩種方式訪問sessio…

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;使用對應異常異…

scala 訪問修飾符_Scala中的訪問修飾符

scala 訪問修飾符Access modifiers are used in order to restrict the usage of a member function to a class or a package. Using access modifiers data hiding takes place which is a very important concept of OOPs. 訪問修飾符用于將成員函數的使用限制為類或包。 使…

小試---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…

C++中比較兩個浮點數是否相等

來源&#xff1a; https://stackoverflow.com/a/37686/3242645 代碼&#xff1a; #include <cmath> #include <limits> bool AreSame(double a, double b) {return std::fabs(a - b) < std::numeric_limits<double>::epsilon(); }

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…

正則 去除html標記

//string regexstr "<[^>]*>"; //去除所有的標簽 //"<script[^>]*?>.*?</script>" //去除所有腳本&#xff0c;中間部分也刪除 // string regexstr "<img[^>]*>"; //去除圖片的正則 // string regexstr &…

自畫PopMenu彈出

BorderColor:TColor; //邊框顏色FillColor:TColor; //未選中填充顏色TextColor:TColor; //未選中字體顏色SelectTextColor:TColor; //選中字體顏色SelectFillColor:TColor; //選中填充顏色SideBuffer:Integer; //邊框寬度procedure TForm1.FormCreate(Sender: TObject); b…

安利一款倒計時插件---雨滴桌面

內容來自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…

int main(int argc,char* argv[])講解

分類&#xff1a; 學習筆記2011-11-07 21:502354人閱讀評論(0)收藏舉報dos編譯器pathunixcommandc在最近學習中老是遇到 int main(int argc,char* argv[])&#xff0c;以為就是簡單的參數應用了&#xff0c;但是看代碼是沒能理解參數的具體傳遞過程&#xff0c;上網…