简单的群体测试方案C++代码(Group testing against Covid-19)

168 阅读2分钟

原理参考链接
www.econstor.eu/handle/1041…
www.magigen.com/h-nd-348.ht…
在这里插入图片描述

文章原理回顾

文章比较了两种估计人群中病毒流行率的方法:
1、个体测试,即对12000人的样本进行病毒测试,并采用标准二项测试得出95%的置信区间;
2、群体测试,即对500组35人进行测试(总人口涉及17500人)

关于置信区间(概率论的知识):

置信区间是从bai样本统计du量派生的值范围,可能包含zhi未知总体参dao数的值。由于置信区间zhuan具有随机性,因此来shu自特定总体的两个样本将不可能生成相同的置信区间。但是,如果将样本重复多次,则在所生成的置信区间中有特定百分比的置信区间将包含未知总体参数。
使用置信区间可以评估总体参数的估计值。例如,制造商想要知道他们生产的铅笔的平均长度是否不同于目标长度。制造商随机抽取铅笔样本,并确定样本的平均长度为 52 毫米,95% 置信区间为 (50,54)。因此,所有铅笔的平均长度介于 50 毫米和 54 毫米之间的可信度为 95%。

简单的群体测试方案代码

简单的群体测试方案需要样本池和第二轮RNA提取的所有样本阳性池。

#include <iostream>
#include<stdlib.h>
#include <vector>
#include <ctime>

using namespace std;
//函数1,生成一个长度为100的vector,输入M,生成的一维数组里面有M个1,100-M个0.
void Initial_Group(vector<int>& group,int M)
{
	if (group.empty())
	{
		cout <<"group initial failed"<<endl;
		return;
	}
	srand((unsigned)time(NULL));
	for(int i = 0;i < M;i++)
	{
		int num = rand() % group.size();
		//如果已经存在了,重新初始化一个num
		while (group[num] == 1)
		{
			num = rand() % group.size();
		}
		//如果不存在的话
		group[num] = 1;
	}
	return;
}
//函数2,打印函数
void Pirnt_Group(vector<int>& group)
{
	int length = sqrt(group.size());
	if (length * length == group.size())
	{
		for (int i = 0; i < length; i++)
		{
			for (int j = 0; j < length; j++)
			{
				cout << group[i * length + j] << " ";
			}
			cout << endl;
		}
	}
	else
	{
		for (int i = 0; i < group.size(); i++)
			cout << group[i] << " ";
		cout << endl;
	}
	return;
}
//函数3,分组函数
//输入:一维序列vector<int>Group ,分组大小num
//输出:二维数组vector<vector<int>>,将Group分割为大小num的子序列
//A.assign(B.begin(),B.end());将区间[first,last)的元素赋值到当前的vector容器中
void Split_Group(vector<int>& group , vector<vector<int>>& splited_group , int num)
{
	if (group.empty())
	{
		cout << "group split falied"<<endl;
		return;
	}
	vector<int>::iterator itr = group.begin();
	int it = 0;
	while (it < group.size())
	{
		vector<int> tmp;
		if (it + num <= group.size())
		{
			tmp.assign(itr, itr + num);
			splited_group.emplace_back(tmp);
		}
		it = it + num;
		if(it < group.size())
			itr = itr + num;
	}
	return;
}
//合成血液函数
//输入一维序列,只要其中有1,则结果为1
//输出结果矩阵
void Synthetic_Blood(vector<vector<int>>& splited_group, vector<int>& result)
{
	for (int i = 0; i < splited_group.size(); i++)
	{
		int flag = 0;
		for (int j = 0; j < splited_group[i].size(); j++)
		{
			if (splited_group[i][j] == 1)
			{
				flag = 1;
				break;
			}
		}
		result.emplace_back(flag);
	}
	for (int i = 0; i < result.size(); i++)
		cout << result[i] << " ";
	cout << endl;
	return;
}
//计算人力物力、时间消耗函数
int Cal_Times(int all_groups, int posi_group_nums,int group_nums_size)
{
	//计算检测的次数 = 组数 +阳性组数*阳性组中的样本大小
	int result = all_groups + group_nums_size * posi_group_nums;
	return result;
}
//将合成血液的结果中为阳性的序列进行单个测试,并记录结果到Positive_Samples
void Further_Test(vector<vector<int>>& splited_group, vector<int>& result,vector<int>& Positive_Samples)
{
	int posi_group_nums = 0;
	for (int i = 0; i < result.size(); i++)
	{
		//说明该分组中有阳性样本
		if (result[i] == 1)
		{
			posi_group_nums++;
			for (int j = 0; j < splited_group[i].size(); j++)
			{
				//记录在原序列中的坐标
				if (splited_group[i][j] == 1)
					Positive_Samples.emplace_back(i* splited_group[0].size()+j);
			}
		}
	}
	for (int i = 0; i < Positive_Samples.size(); i++)
		cout << Positive_Samples[i] + 1 << " ";
	cout << endl;
	int spend_time = Cal_Times(result.size(),posi_group_nums, splited_group[0].size());
	cout <<"时间花费" <<endl;
	cout << spend_time<<endl;
	return;
}


int Cal_Money()
{
	return 0;
}
int main()
{
	int sample_nums = 17500;
	int positive_sample_nums = 350;
	int sec_group_sample_nums = 35;
	vector<int> Positive_Samples;
	vector<int> Group(sample_nums,0);
	vector<int> Result;
	vector<vector<int>> Splited_Group;
	Initial_Group(Group, positive_sample_nums);
	//Pirnt_Group(Group);
	cout << endl;
	Split_Group(Group, Splited_Group, sec_group_sample_nums);
	//Pirnt_Split_Group(Splited_Group);
	cout << endl;
	Synthetic_Blood(Splited_Group,Result);
	Further_Test(Splited_Group,Result,Positive_Samples);
	return 0;
}

在这里插入图片描述