#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; //Uses mpi to output a lev file of pairwise distances between packet sequences //Lev file should be processed by clgen-stratify to retrieve results //Lu-Lev requires positive and negative packets to be calculated separately //Two pairwise distances are computed, instead of one //In older implementations, we output two files lev-pos and lev-neg //For simplicity, we output only one file in this implementation //We denote positive sequences as sites 0-CLOSED_SITENUM, and negative ones as sites CLOSED_SITENUM+1 to 2 * CLOSED_SITENUM + 2. #define UNIT 512 #define INCREMENT 600 typedef struct _cord{ int x; int y; }CORD; typedef int TRACE; int CLOSED_SITENUM, CLOSED_INSTNUM, OPEN_INSTNUM, CORE, CORE_TOTAL, TOTAL_NUM, degree; map d; int sinste_to_ind(int site, int inst) { int ind = 0; while (site > CLOSED_SITENUM) { site -= CLOSED_SITENUM + 1; ind += CLOSED_SITENUM * CLOSED_INSTNUM + OPEN_INSTNUM; } ind += site * CLOSED_INSTNUM + inst; return ind; } class Levenshtein{ public: vector buffer; vector sizes; vector pool; TRACE* str1; TRACE* str2; int method; public: Levenshtein(string folder, int metr); ~Levenshtein(); CORD inverse_cantor(int z); int Parse_data(char* fname, int method); TRACE* fetch_pool(int index); double DLdis(int ms, int ns); double minimum(double a, double b, double c); int DLdel(int ms, int ns, int delele); double newDLdis(int ms, int ns); }; Levenshtein :: Levenshtein(string folder, int metr){ pool.clear(); buffer.clear(); sizes.clear(); str1 = str2 = NULL; method = metr; char fname[200]; for(int web = 0; web < CLOSED_SITENUM; web++){ for(int trial = 0; trial < CLOSED_INSTNUM; trial++){ memset(fname, 0, 200); sprintf(fname,"%s%d-%d.cell", folder.c_str(),web,trial); Parse_data(fname, method); } } for(int trial = 0; trial < OPEN_INSTNUM; trial++){ memset(fname, 0, 200); sprintf(fname,"%s%d.cell", folder.c_str(),trial); Parse_data(fname, method); } if (method == 0) {//LuLev needs to load data twice, one for all positive packets in each paacket sequence, and one for negative for(int web = 0; web < CLOSED_SITENUM; web++){ for(int trial = 0; trial < CLOSED_INSTNUM; trial++){ memset(fname, 0, 200); sprintf(fname,"%s%d-%d.cell", folder.c_str(),web,trial); Parse_data(fname, -1); } } for(int trial = 0; trial < OPEN_INSTNUM; trial++){ memset(fname, 0, 200); sprintf(fname,"%s%d.cell", folder.c_str(),trial); Parse_data(fname, -1); } } cout<<"constructor finished, size of pool is: "<= pool.size()){ printf("fetch_pool error [index=%d poolsize=%lu]", index, pool.size()); exit(1); } return pool.at(index); } int Levenshtein::Parse_data(char *fname, int method){ //method 0 is for positive packets for LuLev, and method -1 is for negative packets //other ones are normal FILE* fp = NULL; int length,size; float time; int i, round; buffer.clear(); buffer.push_back(0); fp = fopen(fname, "r"); if(!fp){ cout< fscanf(fp,"%f\t%d",&time, &length)) continue; if (method == 0) { //LuLev, positive if (length >= 0) { length = length/abs(length); buffer.push_back(length); count++; } } else if (method == -1) { //LuLev, negative if (length < 0) { length = length/abs(length); buffer.push_back(length); count++; } } else { //other algorithms, take both length = length/abs(length); buffer.push_back(length); count++; } } fclose(fp); TRACE* tmp = new TRACE[buffer.size()]; for(int x = 0; x < buffer.size(); x++) tmp[x] = buffer.at(x); pool.push_back(tmp); sizes.push_back(buffer.size()); return 0; } int contains(int* str1, int element, int len) { int toret = -1; for (int i = 0; i < len; i++) { if (str1[i] == element) toret = i; } return toret; } double Levenshtein::DLdis(int ms, int ns){ //method 0: Lu-Lev //method 1: Ca-OSAD //method 2: Wa-OSAD //method 3: Wa-FLev (handled ny newDLdis) //method 4: Wa-OSAD, but only disabling substitution //method 5: Wa-OSAD, but only increasing outgoing cost //method 6: Wa-OSAD, but only changing transcost double ret = 0; int min; int m = ms; int n = ns; min = m < n ? m : n; min = min == 0 ? 1 : min; int i,j; float subcost,transcost; float** dis = new float*[m]; for(i=0;i maxpacket) maxpacket = pt[i]; if (pt[i] < minpacket) minpacket = pt[i]; } } for(i=0; i (float)j/n ? (float)j/n : (float)i/m; transcost = (1-P*0.9) * (1-P*0.9); //goes from 1 to 0.01; } if (method == 6) { P = (float)i/m > (float)j/n ? (float)j/n : (float)i/m; transcost = 1; for (int d = 0; d < (int)degree; d++) { transcost *= (1-P*0.9); } // transcost = pow((1-P*0.9), degree * 10 + 0.1); } //printf("%d %d %d %d %d\n", METRIC, i, j, x1, y1); if (str1[i] == str2[j]) { dis[i][j] = minimum ( dis[i-1][j] + idcost[(str1[i] > 0 ? 0 : 1)], //abs(str1[i]), // a deletion dis[i][j-1] + idcost[(str2[j] > 0 ? 0 : 1)], //abs(str2[j]), // an insertion dis[i-1][j-1] // a substitution ); db = j; } else { dis[i][j] = minimum ( dis[i-1][j] + idcost[(str1[i] > 0 ? 0 : 1)], //abs(str1[i]), // a deletion dis[i][j-1] + idcost[(str2[j] > 0 ? 0 : 1)], //abs(str2[j]), // an insertion dis[i-1][j-1] + subcost // a substitution ); if(i > 1 && j > 1 && str1[i] == str2[j-1] && str1[i-1] == str2[j]) { dis[i][j] = dis[i][j] < dis[i-2][j-2] + transcost ? dis[i][j] : dis[i-2][j-2] + transcost; } } //printf("%d %d %d %d \n", i, j, dis[i][j], dis); } } ret = dis[m-1][n-1]/min; for(i = 0 ; i < m; i++) { delete[] dis[i]; } delete[] dis; return ret; } int abs(int k) { if (k > 0) return k; else return -k; } double Levenshtein::newDLdis(int ms, int ns) { //from transcost = 0.01, 0.02, 0.03 x posdelcost = 2, 4, 6, 4 * 0.01 is the best // double transcost = (1+(METRIC))*0.001; double transcost = 0.01; double posdelcost = 4; double negdelcost = 1; int i = 0; int poscount = 0; int negcount = 0; int min = 0; min = ms < ns ? ms : ns; min = min == 0 ? 1 : min; for (i = 0; i < ms; i++) { if (str1[i] > 0) poscount += 1; else negcount += 1; } for (i = 0; i < ns; i++) { if (str2[i] > 0) poscount += 1; else negcount += 1; } if (ns == 0) { return 0; } int* dicn = new int[ms]; //dictionary of all elements in str1 int dicnlen = 0; //true size of dictionary; saves memory. for (i = 0; i < ms; i++) { int a = contains(dicn, str1[i], dicnlen); if (a == -1) { dicn[dicnlen] = str1[i]; dicnlen += 1; } } int** dicncount = new int*[dicnlen]; //location of all elements in str1 int* dicncountlen = new int[dicnlen]; int* dicncountlentemp = new int[dicnlen]; int count = 0; int dist = 0; for (i = 0; i < dicnlen; i++) { dicncount[i] = new int[ms]; dicncountlen[i] = 0; } for (i = 0; i < ms; i++) { int a = contains(dicn, str1[i], dicnlen); dicncount[a][dicncountlen[a]] = i; dicncountlen[a] += 1; } for (i = 0; i < dicnlen; i++) { dicncountlentemp[i] = dicncountlen[i]; } for (i = 0; i < ns; i++) { int a = contains(dicn, str2[i], dicnlen); if (a != -1) { count = dicncountlen[a] - dicncountlentemp[a]; if (count < dicncountlen[a]) { if (str2[i] > 0) dist += (dicncount[a][count] - i > 0)? dicncount[a][count] - i : i - dicncount[a][count]; dicncountlentemp[a] -= 1; if (str2[i] > 0) poscount -= 1; else negcount -= 1; } } } double cost = poscount * posdelcost + negcount * negdelcost + dist * transcost; for (int i = 0; i < dicnlen; i++) { delete[] dicncount[i]; } delete[] dicncount; delete[] dicn; delete[] dicncountlen; delete[] dicncountlentemp; return cost/min; } double Levenshtein::minimum(double a, double b, double c){ double min = a; if(b < min) min = b; if(c < min) min = c; return min; } CORD Levenshtein::inverse_cantor(int z){ CORD ret; int w = floor((sqrt(8.0*z+1)-1)/2); int t = (w*w+w)/2; ret.y = z-t; ret.x = w-ret.y; return ret; } void read_options(string fname) { // std::map d; ifstream fread; fread.open(fname.c_str()); while (fread.peek() != EOF) { string str = ""; getline(fread, str); string optname = str.substr(0, str.find_first_of("\t")); string optval = str.substr(str.find_first_of("\t")+1); d[optname] = optval; } fread.close(); } string itoa(int val) { string ret; ostringstream converter; converter << val; ret = converter.str(); return ret; } int main(int argc, char** argv){ // if(argc != 2){ cout <<"call: ./clLev