#ifndef ENGINE_H #define ENGINE_H #include #include #include"Arguments.h" #include"Model.h" #include #include #define MARK 9.0e99 // Substitutes la += log(1+exp(lb-la)) <=> a = a + b. #define LOGADD(la,lb) if(la>8e99||lb-la>100) la=lb;else la+=log(1+exp(lb-la)); #define LOG_ZERO -1.0e101 using namespace std; #include"UpdateHR.h" //---------------- // Fast Möbius transform routines. void sub_fumt(int j, int d, int S, int overlap, double *t, double *s, int n, int k){ if (d < n && overlap < k){ sub_fumt(j, d+1, S, overlap, t, s, n, k); S |= (1 << d); overlap += (d >= j+1); sub_fumt(j, d+1, S, overlap, t, s, n, k); } else{ //base case: //since s[S] = MARK initially, and the following 3 cases, s[S] must be assigned some score (neither MARK nor undecided) s[S] = MARK; //jinS: j is in S int jinS = ((S >> j) & 1); if (overlap + jinS <= k) s[S] = t[S]; //if (jinS) LOGADD(s[S], t[S - (1 << j)]); if (jinS) logAdd_New(s[S], t[S - (1 << j)]); } } // Fast upward Möbius transform: // s(S) := \sum_{T \subseteq S : |T| \leq k} t(T). void fumt(double *t, double *s, int n, int k){ double *tmp, *sprev = new double[1 << n]; for (int T = 0; T < (1<log_lcp(0, T)<num_layers(); h ++){ int *Vh, *Vu, *Vl; int nh, nu, nl; model->layer(h, &Vh, &nh); model->upper_layers(h, &Vu, &nu); model->lower_layers(h, &Vl, &nl); cerr<<"Layer "<num_layers(); //Arguments::option == 0 means the rebel method with new Dirichlet hyper-param (see sub_beta) if(Arguments::option == 0){ compute_edge_probabilities(0); } //Arguments::option == 1 means the forward method else if(Arguments::option == 1){ compute_edge_probabilities_forward(0); } //Arguments::option == 2 means the backward method else if(Arguments::option == 2){ compute_edge_probabilities_backward(0); } //Arguments::option == 3 means the mix method in the UAI paper else if(Arguments::option == 3){ compute_edge_probabilities_mixIndegree(0); //compute_edge_probabilities_mixIndegreeNoLog(0); } //Arguments::option == 4 means the computation used in top-k else if(Arguments::option == 4){ compute_edge_probabilities_top_k(0); } //Arguments::option == 5 means the computation required for in and out features else if(Arguments::option == 5){ //For In_Out features compute_edge_probabilities_in_out_features(0); } } // Computes probabilities for edges pointing to the h-th layer. void compute_edge_probabilities(int h){ cerr<<"\nREBEL Method:" << endl; cerr<<" Compute edge probabilities for Layer "<layer(h, &Vh, &nh); model->upper_layers(h-1, &Vu, &nu); beta = new double*[nh]; alpha = new double*[nh]; k = model->max_indegree(); cerr<<" . "<makeADTree(); } for (int j = 0; j < nh; j ++){ beta[j] = new double[1 << nh]; //int i = Vh[j]; compute_beta(j, Vh, nh, Vu, nu); } //If Arguments::ADtree == 1, then delete the whole tree if(Arguments::ADtree == 1){ model->freeADTree(); } gettimeofday(&endTime, &myTimeZone); betaTime = (endTime.tv_sec - startTime.tv_sec) + (endTime.tv_usec - startTime.tv_usec) / 1000000.0 ; cerr<<" . Tables beta are now ready."<print_edge_prob( cout, Vh[i], Vh[j], exp(log_prob - gb[(1<layer(h, &Vh, &nh); model->upper_layers(h-1, &Vu, &nu); beta = new double*[nh]; alpha = new double*[nh]; betaNume = new double*[nh]; alphaNume = new double*[nh]; k = model->max_indegree(); cerr<<" . "<print_edge_prob(cout, Vh[vv], Vh[uu], exp(gfNume[(1<layer(h, &Vh, &nh); model->upper_layers(h-1, &Vu, &nu); //If Arguments::ADtree == 1, user wants to use ADtree, then make the whole tree first if(Arguments::ADtree == 1){ model->makeADTree(); } beta = new double*[nh]; alpha = new double*[nh]; betaNume = new double*[nh]; alphaNume = new double*[nh]; k = model->max_indegree(); cerr<<" . "<print_edge_prob(cout, Vh[vv], Vh[uu], exp(hFuncNume[(1<freeADTree(); } delete [] hFunc; //it better to move the following line inside the double for loop delete [] hFuncNume; for (int j = 0; j < nh; j ++){ delete [] beta[j]; delete [] betaNume[j]; delete [] alpha[j]; delete [] alphaNume[j]; } delete [] beta; delete [] betaNume; delete [] alpha; delete [] alphaNume; cerr<<" Edge probabilities now computed."<layer(h, &Vh, &nh); model->upper_layers(h-1, &Vu, &nu); //If Arguments::ADtree == 1, user wants to use ADtree, then make the whole tree first if(Arguments::ADtree == 1){ model->makeADTree(); } beta = new double*[nh]; alpha = new double*[nh]; betaNume = new double*[nh]; alphaNume = new double*[nh]; k = model->max_indegree(); cerr<<" . "<print_edge_prob(cout, Vh[vv], Vh[uu], exp(RRFuncNume[(1<freeADTree(); } delete [] RRFunc; //it better to move the following line inside the double for loop delete [] RRFuncNume; for (int j = 0; j < nh; j ++){ delete [] beta[j]; delete [] betaNume[j]; delete [] alpha[j]; delete [] alphaNume[j]; } delete [] beta; delete [] betaNume; delete [] alpha; delete [] alphaNume; cerr<<" Edge probabilities now computed."<layer(h, &Vh, &nh); model->upper_layers(h-1, &Vu, &nu); beta = new double*[nh]; alpha = new double*[nh]; betaInOut = new double*[nh]; alphaInOut = new double*[nh]; k = model->max_indegree(); cerr<<" . "<makeADTree(); } for (int j = 0; j < nh; j ++){ beta[j] = new double[1 << nh]; compute_beta(j, Vh, nh, Vu, nu); alpha[j] = new double[1 << nh]; compute_alpha(j, Vh, nh); cerr<<" . Tables beta and alpha computed for node "<print_edge_prob(cout, Vh[vv], Vh[uu], exp(RRFuncNume[(1<freeADTree(); } delete [] RRFunc; delete [] RRFuncInOut; delete [] inFeatureEdges; delete [] outFeatureEdges; for (int j = 0; j < nh; j ++){ delete [] beta[j]; delete [] betaInOut[j]; delete [] alpha[j]; delete [] alphaInOut[j]; } delete [] beta; delete [] betaInOut; delete [] alpha; delete [] alphaInOut; cerr<<" Poster probabilities now computed."<layer(h, &Vh, &nh); model->upper_layers(h-1, &Vu, &nu); beta = new double*[nh]; alpha = new double*[nh]; //betaNume = new double*[nh]; //alphaNume = new double*[nh]; k = model->max_indegree(); cerr<<" . "<makeADTree(); } for (int j = 0; j < nh; j ++){ beta[j] = new double[1 << nh]; //cerr<<" Start compute_beta for node "<freeADTree(); } RRFunc = new double[1 << nh]; cerr<<"\n Compute_RR_Fast(): "<layer(h, &Vh, &nh); model->upper_layers(h-1, &Vu, &nu); //Step 1(a) (b) beta = new double*[nh]; alpha = new double*[nh]; k = model->max_indegree(); cerr<<" . "<makeADTree(); } else{ //cout << "Arguments::ADtree == 0" << endl; } for (int j = 0; j < nh; j ++){ beta[j] = new double[1 << nh]; //int i = Vh[j]; compute_beta(j, Vh, nh, Vu, nu); //cerr<<" . Tables beta and alpha computed for node "<freeADTree(); } gettimeofday(&endTime, &myTimeZone); betaTime = (endTime.tv_sec - startTime.tv_sec) + (endTime.tv_usec - startTime.tv_usec) / 1000000.0 ; cerr<<" . Tables beta have been computed" << endl; //HR: Add for Top-k inside void compute_edge_probabilities_mixIndegree(int h) //HR: Use the Poster tool to compute the local scores for all the families of each variable (without max-indegree // restriction). So for each of n variables, there are 2^(n-1) family scores. write_family_scores_to_files(nh); //step 1(b) gettimeofday(&startTime, &myTimeZone); for (int j = 0; j < nh; j ++){ alpha[j] = new double[1 << nh]; compute_alpha(j, Vh, nh); //cerr<<" . Tables beta and alpha computed for node "<>v) & 1){ Gfb[U] = LOG_ZERO; } else{ //Gfb[U] = hFunc[U] + KFunc[v][U]; if(KFunc[v][U] == LOG_ZERO){ Gfb[U] = LOG_ZERO; } //note that KFunc[v][U] == 0 is possible else if(KFunc[v][U] <= 0){ Gfb[U] = hFunc[U] + KFunc[v][U]; } else{ //Now if Gfb[U] > 0, then Gfb[U] Gfb[U] = -(hFunc[U] - KFunc[v][U]); } //cerr<<" j = "<print_edge_prob( cout, Vh[i], Vh[v], exp(log_prob_nume - RRFunc[(1<layer(h, &Vh, &nh); model->upper_layers(h-1, &Vu, &nu); //Step 1(a) (b) beta = new double*[nh]; alpha = new double*[nh]; k = model->max_indegree(); cerr<<" . "<>v) & 1){ //Gfb[U] = LOG_ZERO; //Gfb[U] = 0; Gfb[U] = LOG_ZERO;// } else{ //Gfb[U] = hFunc[U] + KFunc[v][U]; if(KFunc[v][U] == LOG_ZERO){ Gfb[U] = exp(hFunc[U]); } else if (KFunc[v][U] > 0){ Gfb[U] = - exp(hFunc[U] - KFunc[v][U]); } else{ Gfb[U] = exp(hFunc[U] + KFunc[v][U]); } // if(Gfb[U] == 0){ Gfb[U] = LOG_ZERO; } else{ Gfb[U] = log(Gfb[U]); } // //cerr<<" j = "<print_edge_prob( cout, Vh[i], Vh[v], exp(log_prob_nume - RRFunc[(1<log_prior(i, S, d) + model->log_lcpHR(i, S, d); if(Arguments::ADtree == 0){ lb = model->log_prior(i, S, d) + model->log_lcpHR(i, S, d); } else{ lb = model->log_prior(i, S, d) + model->log_lcpHR_ADtree(i, S, d); } } else if(Arguments::option >= 1) { //lb = 0 + model->log_lcpHR(i, S, d); if(Arguments::ADtree == 0){ lb = 0 + model->log_lcpHR(i, S, d); } else{ lb = 0 + model->log_lcpHR_ADtree(i, S, d); } } //LOGADD(b[T], lb); logAdd_New(b[T], lb); // if (d < k){ for (int j = jprev + 1; j < nu; j ++){ if (Vu[j] != i){ S[d] = Vu[j]; if (j < nh) { sub_beta(j, nh, b, d+1, S, i, Vu, nu, T | (1 << j)); } else{ sub_beta(j, nh, b, d+1, S, i, Vu, nu, T); } } } } } void sub_betaNume(int jprev, int nh, double *b, int d, int *S, int i, int *Vu, int nu, int T, int uu, int vv){ //cerr<<" S:"; print_nodes(cerr, S, d); //cerr<<"; T:"; print_nodes(cerr, T, Vu, nu); cerr<log_prior(i, S, d) + model->log_lcpHR(i, S, d); if(Arguments::ADtree == 0){ lb = model->log_prior(i, S, d) + model->log_lcpHR(i, S, d); } else{ lb = model->log_prior(i, S, d) + model->log_lcpHR_ADtree(i, S, d); } } else if(Arguments::option >= 1) { //HR: for 1 prior for q(G_i) and new Dirichlet hyper-param //lb = 0 + model->log_lcpHR(i, S, d); if(Arguments::ADtree == 0){ lb = 0 + model->log_lcpHR(i, S, d); } else{ lb = 0 + model->log_lcpHR_ADtree(i, S, d); } } //double lb = model->log_prior(i, S, d) + model->log_lcp(i, S, d); //double lb = 0 + model->log_lcpHR(i, S, d); //LOGADD(b[T], lb); logAdd_New(b[T], lb); } else{ //how to set? 0-no, MARK-no; log(0) = -inf = LOG_ZERO //LOGADD(b[T], LOG_ZERO); double tempLogB = LOG_ZERO; logAdd_New(b[T], tempLogB); } if (d < k){ for (int j = jprev + 1; j < nu; j ++){ if (Vu[j] != i){ S[d] = Vu[j]; if (j < nh) { sub_betaNume(j, nh, b, d+1, S, i, Vu, nu, T | (1 << j), uu, vv); } else{ sub_betaNume(j, nh, b, d+1, S, i, Vu, nu, T, uu, vv); } } } } } void getInOutFeatures(int no_vars){ for(int i = 0; i < no_vars; i++){ inFeatureEdges[i] = 0; } for(int i = 0; i < no_vars; i++){ outFeatureEdges[i] = 0; } FILE * fpIn = fopen(Arguments::inFeasFileName, "r"); int fromNode; int toNode; //char c; //int i=0; while(!feof(fpIn)){ fromNode = -1; toNode = -1; //c = -1; fscanf(fpIn,"%d->%d\n",&fromNode, &toNode); //cout << "fromNode = "<< fromNode << endl; //cout << "toNode = "<< toNode << endl; //To guard against toNode == -1 if(toNode == -1){ break; } else{ inFeatureEdges[toNode] += (1 << fromNode); } } fclose(fpIn); // for(int i = 0; i < no_vars; i++){ // cout << "inFeatureEdges[" << i << "] " << inFeatureEdges[i] << endl; // } FILE *fp2 = fopen(Arguments::outFeasFileName, "r"); while(!feof(fp2)){ fromNode = -1; toNode = -1; fscanf(fp2,"%d->%d\n",&fromNode, &toNode); //cout << "fromNode = "<< fromNode << endl; //cout << "toNode = "<< toNode << endl; if(toNode == -1){ break; } else{ outFeatureEdges[toNode] += (1 << fromNode); } } fclose(fp2); // for(int i = 0; i < no_vars; i++){ // cout << "outFeatureEdges[" << i << "] " << outFeatureEdges[i] << endl; // } } //end of getInOutFeatures void sub_betaInOut(int jprev, int nh, double *b, int d, int *S, int i, int *Vu, int nu, int T){ // cerr<< "Start sub_betaInOut()" << endl; // cerr<<" S:"; print_nodes(cerr, S, d); // cerr<<" T: " << T << endl; // cerr<<" d: " << d << endl; //cerr<<"; T:"; print_nodes(cerr, T, Vu, nu); cerr<log_prior(i, S, d) + model->log_lcpHR(i, S, d); if(Arguments::ADtree == 0){ lb = model->log_prior(i, S, d) + model->log_lcpHR(i, S, d); } else{ lb = model->log_prior(i, S, d) + model->log_lcpHR_ADtree(i, S, d); } } else if(Arguments::option >= 1) { //HR: for 1 prior for q(G_i) and new Dirichlet hyper-param //cerr << "start: double lb = 0 + model->log_lcpHR(i, S, d)" << endl; //lb = 0 + model->log_lcpHR(i, S, d); if(Arguments::ADtree == 0){ lb = 0 + model->log_lcpHR(i, S, d); } else{ lb = 0 + model->log_lcpHR_ADtree(i, S, d); } //cerr << "end: double lb = 0 + model->log_lcpHR(i, S, d)" << endl; } //LOGADD(b[T], lb); logAdd_New(b[T], lb); } else{ //LOGADD(b[T], LOG_ZERO); double tempLogB = LOG_ZERO; logAdd_New(b[T], tempLogB); } if (d < k){ for (int j = jprev + 1; j < nu; j ++){ if (Vu[j] != i){ S[d] = Vu[j]; if (j < nh) { sub_betaInOut(j, nh, b, d+1, S, i, Vu, nu, T | (1 << j)); } else{ sub_betaInOut(j, nh, b, d+1, S, i, Vu, nu, T); } } } } } //end of sub_betaInOut void sub_init(int d, int S, double *a, double value, int ones, int nh){ //cerr<<" d: "<>= 1; J <<= 1; } if (S == 0) gf[0] = 0; else gf[S] = sum; } } void sub_gfNume(int d, int nh, int S){ if (d < nh){ sub_gfNume(d+1, nh, S); sub_gfNume(d+1, nh, S | (1 << d)); } else { double sum = MARK; int T = S, J = 1; for (int j = 0; j < nh; j ++){ if (T & 1){ // Now S - J is a subset of S. double w = alphaNume[j][S - J] + gfNume[S - J]; //LOGADD(sum, w); logAdd_New(sum, w); } T >>= 1; J <<= 1; } if (S == 0) gfNume[0] = 0; else gfNume[S] = sum; } } void compute_g_backward(int nh){ sub_gb(0, nh, 0); } void sub_gb(int d, int nh, int S){ if (d < nh){ sub_gb(d+1, nh, S); sub_gb(d+1, nh, S | (1 << d)); } else { double sum = MARK; int T = S, J = 1, complS = (1 << nh) - 1 - S; for (int j = 0; j < nh; j ++){ if (T & 1){ // Now S - J is a subset of S. double w = alpha[j][complS] + gb[S - J]; //LOGADD(sum, w); logAdd_New(sum, w); } T >>= 1; J <<= 1; } if (S == 0) gb[0] = 0; else gb[S] = sum; } } double eval_edge(int i, int j, double *a, double *b, int nh, int k){ int T = 1 << i; return sub_eval_edge(-1, 1, T, i, j, a, b, nh, k); } double sub_eval_edge( int tprev, int d, int T, int i, int j, double *a, double *b, int nh, int k){ //cerr<<" T:"; print_set(cerr, T); //cerr<<": "< 0 "; sumRes = - ( Beta_j[T] - Gamma[T] ); } return sumRes; } //if T < k, can add more //double sum = Gamma[T] + Beta_j[T]; double sum; if(Beta_j[T] == MARK){ cerr<<"\n**** Beta_j[T] == MARK "; } if(Gamma[T] == LOG_ZERO){ sum = LOG_ZERO; } else if(Gamma[T] <= 0){ sum = Beta_j[T] + Gamma[T]; } else{ cerr<<"\n**** Gamma[T] > 0 "; sum = - ( Beta_j[T] - Gamma[T] ); } for (int t = tprev + 1; t < nh; t ++){ if (t == i || t == j) continue; int Tnext = T | (1 << t); double w = sub_eval_edge_mixIndegree(t, d+1, Tnext, i, j, Gamma, Beta_j, nh, k); logAddComp(sum, w); } return sum; } double eval_edge_mixIndegreeNoLog(int i, int j, double * Gamma, double * Beta_j, int nh, int k){ int T = 1 << i; return sub_eval_edge_mixIndegreeNoLog(-1, 1, T, i, j, Gamma, Beta_j, nh, k); } double sub_eval_edge_mixIndegreeNoLog( int tprev, int d, int T, int i, int j, double * Gamma, double * Beta_j, int nh, int k){ //cerr<<" T:"; print_set(cerr, T); //cerr<<": "< 0){ product_res = exp(Beta_j[T] + log(Gamma[T])); } else{ product_res = - exp(Beta_j[T] + log(-Gamma[T])); } } return product_res; } //if T < k, can add more //double sum = Gamma[T] * exp(Beta_j[T]); double sum; double product_res; //if Beta_j[T] has not been initialized if(Beta_j[T] == MARK){ cerr<<"***Beta_j[T] has not been initialized" << endl; product_res = 0; } else{ if(Gamma[T] == 0){ product_res = exp(Beta_j[T]); } else if(Gamma[T] > 0){ product_res = exp(Beta_j[T] + log(Gamma[T])); } else{ product_res = - exp(Beta_j[T] + log(-Gamma[T])); } } sum = product_res; for (int t = tprev + 1; t < nh; t ++){ if (t == i || t == j) continue; int Tnext = T | (1 << t); double w = sub_eval_edge_mixIndegreeNoLog(t, d+1, Tnext, i, j, Gamma, Beta_j, nh, k); //LOGADD(sum, w); sum += w; } return sum; } Model *model; double **alpha, **beta; double **alphaNume, **betaNume; double *gf, *gb; double *gfNume; int k; double **alphaInOut, **betaInOut; int * inFeatureEdges; int * outFeatureEdges; }; #endif