负数据库数据生成算法|青训营笔记

213 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记

负数据库数据生成算法

负数据库介绍

正数据库(Positive database ,DB) :传统的数据库,负数据库(Negative database ,NDB ) : 由Esponda等人于2004年提出 DB的补集的压缩表示 全集U={01}LU=\{0,1\}^{L}

负数据库(NDB):

  1. 通配符 * 可任意表示 ‘0’ 、 ‘1’
  2. 确定位0、1;不确定位*
  3. 使用 * 缩补集UDB
  4. NDB的大小可以压缩到合理范围内o(DB)
  5. 不是所有负数据库都存储UDB中 的所有内容 如图: image.png

隐藏串:

  1. 藏串对应位相同的确定位称为取正位,反之则叫做取反位。
  2. 藏串的个数:单串负数据库、多串负数据库。

单串数据库常用生成算法

  1. q-hidden算法([1] Jia H, Moore C, Strain D. Generating hard satisfiable formulas by hiding solutions deceptively[C]. National Conference on Artificial Intelligence, 2005: 384-389)
  2. p-hidden算法 ([2] Ran Liu, Wenjian Luo and Lihua Yue. "The p-hidden Algorithm: Hiding Single Databases More Deeply." Immune Computation, vol. 2(1), pp. 43-55, 2014)
  3. K-hidden算法(Dongdong Zhao, Wenjian Luo and Lihua Yue. "A fine-grained algorithm for generating hard-to-reverse negative databases." 2015 International Workshop on Artificial Immune Systems (AIS). IEEE, 201)

k-hidden算法原理与实现

算法原理

image.png

c++实现

#define K_HIDDEN 
#include <vector>
#include<string>
#include <unordered_set> 
class k_hidden {
public:	
	k_hidden(double r,int k,std::string s);
private:
	int N;
	int m;
	double r;
	int k;
	std::vector<double> Qi;
	std::string s;
	std::string ndbs;
	int findI(double qi, std::vector<double> q);
	std::string generateKString(int k);
public:
	std::unordered_set<std::string> NDB;
	void generateNDB();

};

#endif // !K_HIDDEN
#include <iostream>
#include <fstream>
#include <windows.h>
#include"k-hidden.h"

k_hidden::k_hidden(double r,int k, std::string s):r(r),s(s),k(k) {
	this->m = s.length();
	this->N = m * r;
	ndbs = std::string(m, '*');
	Qi.resize(k);
	Qi[0]= 1 / double(k);
	for (int i = 1;i < k - 1;i++) {
		Qi[i] =Qi[i-1]+ 1 / double(k);
	}
	Qi[k - 1] = 1;

}
void k_hidden::generateNDB() {
	srand(unsigned(time(NULL)));
	while (NDB.size() < N) {
		double qi = rand() / double(RAND_MAX);
		int i = findI(qi, Qi);
		std::string ndbstr=generateKString(i+1);
		NDB.insert(ndbstr);

	}
}
int k_hidden::findI(double qi,std::vector<double> q) {
	int l = 0, r = q.size() - 1;
	while (l < r) {
		int mid = (l + r) >> 1;
		if (q[mid] < qi) {
			l = mid + 1;
		}
		else {
			r = mid;
		}
	}
	return l;

}
std::string k_hidden::generateKString(int category){
	std::string kstr=ndbs;
	std::unordered_set<int> st;
	std::vector<int> randCertain;
	srand(unsigned(time(NULL)));
	int j = 0;
	while (st.size() != k) {
		j = rand() % m;
		if (st.count(j)) {
			continue;
		}
		else {
			kstr[j] = s[j];
			st.insert(j);
			randCertain.emplace_back(j);
		}
	}
	st.clear();
	while (st.size() != category) {
		j = rand() % k;
		if (st.count(j)) {
			continue;
		}
		else {
			st.insert(j);
			kstr[randCertain[j]] = kstr[randCertain[j]] == '0' ? '1' : '0';
		}
	}
	return kstr;
}
int main() {
	std::string s = "1111010101101";
	std::fstream myFile;
	DWORD t1, t2;
	myFile.open("saldina.txt", std::ios::out);
	t1 = GetTickCount();
	k_hidden khd(6.5,4,s);
	khd.generateNDB();
	t2 = GetTickCount();
	for (auto s : khd.NDB) {
		myFile << s << std::endl;
	}
	myFile.close();
	std::cout << (double)(t2 - t1) << std::endl;
}