#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; void shuffle(int**& DNF, long*& dnf_ind, int*& dnf, int*& dnfMax, int*& set_vars, int& current_var ,int& level, int& m, unsigned long& form_size, unsigned long& current_loc, unsigned long& w_tot, int& w_min, double& beta, double& rand_clause, int& min_loc) { int swap; rand_clause = drand48(); int* k = 0; int clause_size; unsigned long clause_loc; int var = 0; int sign = 1; // decide whether to swap with a random clause or with the least remaining ordered clause if (rand_clause < 1.0-(1.0-beta)*min(1.0,w_tot/((m-level)*static_cast(w_min)))) { while (true) { swap = rand() % (m - min_loc) + min_loc; // random remaining clause k = DNF[swap]; if (k!=0) { break; } } clause_loc = form_size - current_loc; dnf_ind[level] = clause_loc; DNF[swap] = 0; clause_size = k[0]; dnf[clause_loc] = clause_size; w_tot -= clause_size; // remap variables for tracking max var up to this clause for (int i=1; i 0) { sign = 1; } else { sign = -1; } if (set_vars[var] == 0) { set_vars[var] = current_var; dnf[clause_loc + i] = sign * current_var; ++current_var; } else { dnf[clause_loc + i] = sign * set_vars[var]; } } // sort clause vars and store max var sort(dnf + clause_loc + 1, dnf + clause_loc + clause_size + 1, [](int a, int b) {return abs(a) < abs(b);}); dnfMax[level] = current_var-1; current_loc -= k[0]+1; // calculate least remaining clause if (swap == min_loc) { while (true) { min_loc += 1; k = DNF[min_loc]; if (k!=0) { break; } } w_min = DNF[min_loc][0]; } } else { k = DNF[min_loc]; // least remaining clause clause_loc = form_size - current_loc; dnf_ind[level] = clause_loc; DNF[min_loc] = 0; clause_size = k[0]; dnf[clause_loc] = clause_size; w_tot -= k[0]; // remap variables for tracking max var up to this clause for (int i=1; i 0) { sign = 1; } else { sign = -1; } if (set_vars[var] == 0) { set_vars[var] = current_var; dnf[clause_loc + i] = sign * current_var; ++current_var; } else { dnf[clause_loc + i] = sign * set_vars[var]; } } // sort clause vars and store max var sort(dnf + clause_loc + 1, dnf + clause_loc + clause_size + 1, [](int a, int b) {return abs(a) < abs(b);}); current_loc -= clause_size+1; dnfMax[level] = current_var-1; // calculate least remaining clause while(true) { min_loc += 1; k = DNF[min_loc]; if (k!=0) { break; } } w_min = DNF[min_loc][0]; } } double ouralg(int*& dnf, long*& dnf_ind, int*& dnfMax, int& maxvar, int*& A, mpf_t*& Pr, int& nz, mpf_t& z, int& nvars, int& m, double& eps, double& delta, bit_array_read& bitRead, bit_array_write& bitWrite, mt19937& gen, mt19937_64& gen64, uniform_real_distribution& dis, uniform_int_distribution& idis, int Thresh) { int Y = 0; long count = 0; int bytesize = int(ceil(maxvar/8.0)); // set_vars stores the affirmation or negation of the variable as a 1 or 0 bit gmt::byte* set_vars = new gmt::byte[bytesize]; // clause_vars stores which variables have been assigned gmt::byte* clause_vars = new gmt::byte[bytesize](); uniform_int_distribution dist(numeric_limits::min(), numeric_limits::max()); int index; long test_ind; long C_ind; bool clause_true; unsigned long buff = 0; int buff_length = 0; // Trial loop while (Y < Thresh) { // Select a clause with probability proportional to its weight index = select_clause(index, A, Pr, z, nz, m, gen, dis, idis); C_ind = dnf_ind[index]; int max_var = -1; // assign only variables from the selected clause lazyassign(dnf, C_ind, nvars, bytesize, clause_vars, set_vars, bitWrite, bitRead); double t1 = 1; bool abort = false; double u1 = generate_random_real(gen,dis); // step loop for (int level=0; level= 1/u1) { abort = true; max_var = dnfMax[level]; break; } } } if (abort == false) { Y += 1; max_var = maxvar; } for (int i=dnf[C_ind]; i>0; --i) { if (abs(dnf[C_ind+i])-1 <= max_var) { break; } bitWrite.clear_byte(clause_vars,abs(dnf[C_ind+i])-1); } memset(clause_vars, 0, ceil((max_var)/8.0)); count += 1; } delete[] set_vars; delete[] clause_vars; return 1.0*Y/count; } int main() { int exp = 0; int nvars = 4; double eps = .05; double delta = .05; mpf_set_default_prec(128); bit_array_read bitRead; bit_array_write bitWrite; srand(time(0)); random_device rd; mt19937 gen(rd()); mt19937_64 gen64(rd()); tuple DNFINFO = readDNF("test.dnf"); int** DNF = get<0>(DNFINFO); int n = get<1>(DNFINFO); int m = get<2>(DNFINFO); unsigned long w_tot = get<3>(DNFINFO); uniform_real_distribution dis(0.0,1.0); double beta = 0.01; unsigned long form_size = w_tot + m; timeval start; timeval end; gettimeofday(&start,0); double rand_clause; // create the ordered partition sort(DNF, DNF+m, [](int* a, int* b) {return a[0] < b[0];}); int w_min = DNF[0][0]; long* dnf_ind = new long[m]; int* dnfMax = new int[m]; int* dnf = new int[form_size]; int min_loc = 0; unsigned long current_loc = form_size; // during the shuffling, set_vars will remap unique vars as encountered to keep track of the maximum variable encountered up to a given clause. int* set_vars = new int[n+1](); int current_var = 1; unsigned long randN = 0; for (int j=0; j 0) { sign = 1; } else { sign = -1; } if (set_vars[var] == 0) { set_vars[var] = current_var; dnf[clause_loc + i] = sign * current_var; ++current_var; } else { dnf[clause_loc + i] = sign * set_vars[var]; } } dnfMax[m-1] = --current_var; // Calculate the threshold T for the number of successful trials needed int T = ceil( log(2/delta) / (log(1+eps) - eps/(1+eps)) ); double upper = std::exp(eps/(1+eps)) / (1+eps); double lower = std::exp(-eps/(1-eps)) / (1-eps); while (pow(upper,T) + pow(lower,T) <= delta) { T--; } T++; // Compute the clause selection distribution mpf_pair prob_table1 = prob_CG(dnf, dnf_ind, m, n); mpf_t* Pr1 = prob_table1.Pr; mpf_t z_mpf1; mpf_init(z_mpf1); mpf_set(z_mpf1, prob_table1.z); double z1 = mpf_get_d(z_mpf1); // Form the data structure for efficient sampling pair SAMPLING1 = sample_info(Pr1, m, z_mpf1); int* A1 = SAMPLING1.first; int nz1 = SAMPLING1.second; uniform_int_distribution idis(0,nz1-1); double overlap = ouralg(dnf, dnf_ind, dnfMax, current_var, A1, Pr1, nz1, z_mpf1, n, m, eps, delta, bitRead, bitWrite, gen, gen64, dis, idis, T); double approx = overlap * z1; cout << approx << endl; return 0; } // g++ -lgmp -I include/ -O3 -o count count.cpp rand.cpp counthelp.cpp