#include "basekissat.hpp" #include "sharer.hpp" #include #include extern "C" { #include "src/application.h" #include "src/parse.h" #include "src/internal.h" #include "src/witness.h" #include "src/import.h" } void basekissat::add(int l) { kissat_add(solver, l); } void basekissat::configure(const char* name, int id) { kissat_set_option(solver, name, id); } int basekissat::solve() { return kissat_solve(solver); } void basekissat::terminate() { kissat_terminate(solver); } int basekissat::val(int l) { int v = abs(l); int tmp = kissat_value(solver, v); if (!tmp) tmp = v; if (l < 0) tmp = -tmp; return tmp; } void basekissat::exp_clause(void* cl, int lbd) { cvec *c = (cvec *) cl; clause_store* cls = new clause_store(c->sz); for (int i = 0; i < c->sz; i++) { int v = cvec_data(c, i); int eidx = PEEK_STACK(solver->exportk, (v >> 1)); cls->data[i] = v & 1 ? -eidx : eidx; } // ++S->x2; // if (S->id == 0) puts(""); cls->lbd = lbd; export_clause.push(cls); } void call_back_out(void *solver, int lbd, cvec *c) { basekissat* S = (basekissat *) solver; // ++S->x1; // if (S->solver->nconflict != S->x1 - 1) printf("%d %d\n", S->solver->nconflict, S->x1); if (lbd <= S->good_clause_lbd) { S->exp_clause(c, lbd); } } bool basekissat::imp_clause(clause_store *cls, void *cl) { cvec *c = (cvec *) cl; for (int i = 0; i < cls->size; i++) { // S->outimport << cls->data[i] << std::endl; int eidx = abs(cls->data[i]); if (eidx >= SIZE_STACK(solver->import)) printf("c wrong %d\n", eidx); import *import = &PEEK_STACK (solver->import, eidx); if (import->eliminated) return false; else { int ilit = import->lit; if (cls->data[i] < 0) ilit = ilit ^ 1; cvec_push(c, ilit); } } return true; } int call_back_in(void *solver, int *lbd, cvec *c) { basekissat* S = (basekissat *) solver; clause_store* cls = NULL; if (S->import_clause.pop(cls) == false) return -1; *lbd = cls->lbd; bool res = S->imp_clause(cls, c); if (S->solver->share_dps != 2) { cls->free_clause(); } if (!res) return -10; return 1; } int kissat_wait_sharing(void *solver) { auto clk_st = std::chrono::high_resolution_clock::now(); basekissat* S = (basekissat *) solver; sharer *share = S->in_sharer; int should_free = 1; if (S->solver->share_dps == 1) { // printf("c %d into Light wait\n", S->id); S->x1 = S->x2 = 0; { boost::mutex::scoped_lock lock(share->mtx); if (share->terminated) return true; share->waitings += 1; lock.unlock(); // printf("c %d start wait with number %d\n", S->id, s->waitings); } if (share->should_sharing()) share->cond.notify_one(); boost::mutex::scoped_lock lock(share->mtx); while (share->waitings > 0) { share->cond.wait(lock); } } else if (S->solver->share_dps == 2) { //share_dps = 2 if (S->period >= S->controller->get_winner_period()) { S->set_winner_period(); return -1; } // printf("c thread %d into select %d\n", S->id, S->period); S->select_clauses(); // printf("c %d now finish period %d\n", S->id, S->get_period()); S->inc_period(); // printf("c thread %d start import at %d\n", S->id, S->period); should_free = share->import_clauses(S->id); // printf("c thread %d finish import at %d\n", S->id, S->period); } auto clk_now = std::chrono::high_resolution_clock::now(); int solve_time = std::chrono::duration_cast(clk_now - clk_st).count(); S->waiting_time += 0.001 * solve_time; return should_free; // printf("c %d wait for %d.%03ds\n", S->id, solve_time / 1000, solve_time % 1000); // printf("c %d finish sharing\n", S->id); } void call_back_free(void *solver) { basekissat* S = (basekissat *) solver; sharer *share = S->in_sharer; int current_period = S->get_period() - 1, import_period = current_period - share->margin; if (import_period < 0) return; for (int i = 0; i < share->producers.size(); i++) { if (i == S->id) continue; basesolver *s = share->producers[i]; period_clauses *pc = s->pq.find(import_period); if (pc->period != import_period) puts("*******************************************************"); if (pc->free_clause()) { s->pq.pop(import_period); // printf("thread %d enter, %d is free\n", S->id, i); } } // printf("end finish\n"); } void basekissat::select_clauses() { sharer *share = in_sharer; cls.clear(); export_clauses_to(cls); for (int i = 0; i < cls.size(); i++) { int sz = cls[i]->size; while (sz > bucket.size()) bucket.push(); if (sz * (bucket[sz - 1].size() + 1) <= share->share_lits) bucket[sz - 1].push(cls[i]); } period_clauses *pcls = new period_clauses(period); int space = share->share_lits; for (int i = 0; i < bucket.size(); i++) { int clause_num = space / (i + 1); if (!clause_num) break; if (clause_num >= bucket[i].size()) { space -= bucket[i].size() * (i + 1); for (int j = 0; j < bucket[i].size(); j++) pcls->push(bucket[i][j]); bucket[i].clear(); } else { space -= clause_num * (i + 1); for (int j = 0; j < clause_num; j++) { pcls->push(bucket[i].last()); bucket[i].pop(); } } } int percent = (share->share_lits - space) * 100 / share->share_lits; if (percent < 75) broaden_export_limit(); if (percent > 98) restrict_export_limit(); //sort finish pcls->increase_refs(share->producers.size() - 1); pq.push(pcls); } basekissat::basekissat(int id, light* light) : basesolver(id, light) { good_clause_lbd = 2; period = 0; margin = 0; // outexport.open("export.txt"); // outimport.open("import.txt"); // outfree.open("free.txt"); solver = kissat_init(); solver -> issuer = this; solver -> cbkImportClause = NULL; solver -> cbkExportClause = NULL; solver -> cbkWaitSharing = NULL; if (light->opt->share) { solver -> cbkImportClause = call_back_in; solver -> cbkExportClause = call_back_out; solver -> cbkWaitSharing = kissat_wait_sharing; solver -> cbkFreeClause = call_back_free; solver -> share_dps = light->opt->DPS; solver -> share_dps_period= light->opt->DPS_period; } } basekissat::~basekissat(){ delete solver; } void basekissat::parse_from_CNF(char* filename) { strictness strict = NORMAL_PARSING; file in; uint64_t lineno; kissat_open_to_read_file(&in, filename); kissat_parse_dimacs(solver, strict, &in, &lineno, &solver->max_var); kissat_close_file(&in); } void basekissat::parse_from_PAR(preprocess* pre) { solver->max_var = pre->vars; kissat_reserve(solver, pre->vars); for (int i = 1; i <= pre->clauses; i++) { int l = pre->clause[i].size(); for (int j = 0; j < l; j++) add(pre->clause[i][j]); add(0); } } void basekissat::export_clauses_to(vec &clauses) { clause_store *cls; while (export_clause.pop(cls)) { clauses.push(cls); // outexport << id << ": "; // for (int i = 0; i < cls->size; i++) // outexport << cls->data[i] << " "; // outexport << std::endl; } } void basekissat::import_clauses_from(vec &clauses) { for (int i = 0; i < clauses.size(); i++) { import_clause.push(clauses[i]); // outimport << id << ": "; // for (int j = 0; j < clauses[i]->size; j++) // outimport << clauses[i]->data[j] << " "; // outimport << std::endl; } } void basekissat::get_model(vec &model) { printf("111\n"); model.clear(); for (int i = 1; i <= solver->max_var; i++) { model.push(val(i)); } printf("222\n"); } void basekissat::broaden_export_limit() { ++good_clause_lbd; } void basekissat::restrict_export_limit() { if (good_clause_lbd > 2) --good_clause_lbd; } int basekissat::get_conflicts() { return solver->nconflict; } double basekissat::get_waiting_time() { return waiting_time; }