284 lines
8.5 KiB
C++
284 lines
8.5 KiB
C++
#include "basekissat.hpp"
|
|
#include "sharer.hpp"
|
|
#include <thread>
|
|
#include <condition_variable>
|
|
|
|
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<std::chrono::milliseconds>(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<clause_store *> &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<clause_store *> &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<int> &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;
|
|
}
|