293 lines
9.0 KiB
C++
293 lines
9.0 KiB
C++
#include "clause.h"
|
|
|
|
#include <fstream>
|
|
|
|
ll Clause::total_cost;
|
|
|
|
void Clause::update_satisfied_lit_count() {
|
|
|
|
using namespace ClauseLS;
|
|
|
|
ll old_lit_count = satisfied_lit_count;
|
|
|
|
satisfied_lit_count = 0;
|
|
|
|
for(auto& lit : lits) {
|
|
if(lit_value[abs(lit)]) {
|
|
satisfied_lit_count += (lit > 0);
|
|
} else {
|
|
satisfied_lit_count += (lit < 0);
|
|
}
|
|
}
|
|
|
|
if(old_lit_count == 0 && satisfied_lit_count > 0) {
|
|
falsified_clauses.erase(this);
|
|
total_cost -= weight;
|
|
satisfied_clauses.insert(this);
|
|
}
|
|
|
|
if(old_lit_count > 0 && satisfied_lit_count == 0) {
|
|
satisfied_clauses.erase(this);
|
|
total_cost += weight;
|
|
falsified_clauses.insert(this);
|
|
}
|
|
}
|
|
|
|
namespace ClauseLS {
|
|
|
|
int num_vars;
|
|
int num_clauses;
|
|
|
|
std::unordered_set<Clause*> satisfied_clauses;
|
|
std::unordered_set<Clause*> falsified_clauses;
|
|
|
|
std::vector<Clause*> clauses;
|
|
std::vector<Clause*> *lit_related_clauses;
|
|
int *lit_value;
|
|
int *CC;
|
|
|
|
void write_cnf() {
|
|
std::ofstream f("test.cnf");
|
|
|
|
f << "p cnf " << num_vars << " " << num_clauses << std::endl;
|
|
|
|
for(auto& c : clauses) {
|
|
for(auto &lit : c->lits) {
|
|
f << lit << " ";
|
|
}
|
|
f << "0" << std::endl;
|
|
}
|
|
|
|
f.close();
|
|
}
|
|
|
|
void flip(int var) {
|
|
|
|
// printf("value: [ ");
|
|
|
|
// for(int i=1; i<=num_vars; i++) {
|
|
// printf("%d ", lit_value[i]);
|
|
// }
|
|
|
|
// printf("]\n");
|
|
|
|
// for(auto& c : clauses) {
|
|
|
|
// printf("lits: [ ");
|
|
// for(auto& lit : c->lits) {
|
|
// printf("%d ", lit);
|
|
// }
|
|
// printf(" ] satifs_cnt: %d\n", c->satisfied_lit_count);
|
|
|
|
// }
|
|
|
|
lit_value[var] = !lit_value[var];
|
|
|
|
for(auto& clause : lit_related_clauses[var]) {
|
|
clause->update_satisfied_lit_count();
|
|
for(auto& lit : clause->lits) {
|
|
CC[abs(lit)] = 1;
|
|
}
|
|
}
|
|
CC[var] = 0;
|
|
|
|
}
|
|
|
|
void add_to_tmp_clause(int x) {
|
|
static std::vector<int> lits;
|
|
if(x != 0) {
|
|
lits.push_back(x);
|
|
} else {
|
|
Clause* clause = new Clause();
|
|
clause->lits = lits;
|
|
clause->satisfied_lit_count = 0;
|
|
clauses.push_back(clause);
|
|
lits.clear();
|
|
}
|
|
}
|
|
|
|
void init_data_structs(Circuit* circuit) {
|
|
build_clauses(circuit);
|
|
|
|
printf("====== Clause Statistics ====== \n");
|
|
printf("num_vars:\t%d\n", num_vars);
|
|
printf("num_clauses:\t%ld\n", num_clauses);
|
|
printf("================================ \n");
|
|
|
|
lit_related_clauses = new std::vector<Clause*>[num_vars + 1];
|
|
lit_value = new int[num_vars + 1];
|
|
CC = new int[num_vars + 1];
|
|
|
|
for(int i=1; i<=num_vars; i++) {
|
|
lit_value[i] = 0;
|
|
CC[i] = 1;
|
|
}
|
|
|
|
for(auto& clause : clauses) {
|
|
clause->weight = 1;
|
|
Clause::total_cost += clause->weight;
|
|
falsified_clauses.insert(clause);
|
|
|
|
//printf("fs: %d. ss: %d\n", falsified_clauses.size(), satisfied_clauses.size());
|
|
|
|
clause->update_satisfied_lit_count();
|
|
|
|
for(auto& lit : clause->lits) {
|
|
lit_related_clauses[abs(lit)].push_back(clause);
|
|
}
|
|
}
|
|
|
|
write_cnf();
|
|
}
|
|
|
|
void reset_data_structs() {
|
|
for(int i=1; i<=num_vars; i++) {
|
|
lit_value[i] = rand() % 2;
|
|
CC[i] = 1;
|
|
}
|
|
}
|
|
|
|
void build_clauses(Circuit* circuit) {
|
|
|
|
int extra_variable = circuit->gates.size();
|
|
|
|
int last_id, last_v;
|
|
|
|
for(Gate* g : circuit->gates) {
|
|
if(g->pi) continue;
|
|
|
|
switch(g->type) {
|
|
case Gate::NOT:
|
|
add_to_tmp_clause(-g->id);
|
|
add_to_tmp_clause(-(g->fan_ins[0]->id));
|
|
add_to_tmp_clause(0);
|
|
|
|
add_to_tmp_clause(g->id);
|
|
add_to_tmp_clause(g->fan_ins[0]->id);
|
|
add_to_tmp_clause(0);
|
|
break;
|
|
case Gate::BUF:
|
|
add_to_tmp_clause(-g->id);
|
|
add_to_tmp_clause((g->fan_ins[0]->id));
|
|
add_to_tmp_clause(0);
|
|
|
|
add_to_tmp_clause(g->id);
|
|
add_to_tmp_clause(-(g->fan_ins[0]->id));
|
|
add_to_tmp_clause(0);
|
|
break;
|
|
case Gate::AND:
|
|
for(int i=0; i<g->fan_ins.size(); i++) {
|
|
add_to_tmp_clause(-g->id);
|
|
add_to_tmp_clause(g->fan_ins[i]->id);
|
|
add_to_tmp_clause(0);
|
|
}
|
|
|
|
for(int i=0; i<g->fan_ins.size(); i++) {
|
|
add_to_tmp_clause(-g->fan_ins[i]->id);
|
|
}
|
|
add_to_tmp_clause(g->id);
|
|
add_to_tmp_clause(0);
|
|
break;
|
|
case Gate::NAND:
|
|
for(int i=0; i<g->fan_ins.size(); i++) {
|
|
add_to_tmp_clause(g->id);
|
|
add_to_tmp_clause(g->fan_ins[i]->id);
|
|
add_to_tmp_clause(0);
|
|
}
|
|
|
|
for(int i=0; i<g->fan_ins.size(); i++) {
|
|
add_to_tmp_clause(-g->fan_ins[i]->id);
|
|
}
|
|
add_to_tmp_clause(-g->id);
|
|
add_to_tmp_clause(0);
|
|
break;
|
|
case Gate::OR:
|
|
for(int i=0; i<g->fan_ins.size(); i++) {
|
|
add_to_tmp_clause(g->fan_ins[i]->id);
|
|
}
|
|
add_to_tmp_clause(-g->id);
|
|
add_to_tmp_clause(0);
|
|
|
|
for(int i=0; i<g->fan_ins.size(); i++) {
|
|
add_to_tmp_clause(g->id);
|
|
add_to_tmp_clause(-g->fan_ins[i]->id);
|
|
add_to_tmp_clause(0);
|
|
}
|
|
break;
|
|
case Gate::NOR:
|
|
for(int i=0; i<g->fan_ins.size(); i++) {
|
|
add_to_tmp_clause(g->fan_ins[i]->id);
|
|
}
|
|
add_to_tmp_clause(g->id);
|
|
add_to_tmp_clause(0);
|
|
|
|
for(int i=0; i<g->fan_ins.size(); i++) {
|
|
add_to_tmp_clause(-g->id);
|
|
add_to_tmp_clause(-g->fan_ins[i]->id);
|
|
add_to_tmp_clause(0);
|
|
}
|
|
break;
|
|
case Gate::XOR:
|
|
last_v = g->fan_ins[0]->id;
|
|
for(int i=1; i<g->fan_ins.size() - 1; i++) {
|
|
int new_v = ++extra_variable;
|
|
add_to_tmp_clause(-g->fan_ins[i]->id); add_to_tmp_clause(-last_v); add_to_tmp_clause(-new_v);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(-g->fan_ins[i]->id); add_to_tmp_clause(last_v); add_to_tmp_clause(new_v);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(g->fan_ins[i]->id); add_to_tmp_clause(-last_v); add_to_tmp_clause(new_v);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(g->fan_ins[i]->id); add_to_tmp_clause(last_v); add_to_tmp_clause(-new_v);
|
|
add_to_tmp_clause(0);
|
|
last_v = new_v;
|
|
}
|
|
|
|
last_id = g->fan_ins[g->fan_ins.size() - 1]->id;
|
|
|
|
add_to_tmp_clause(-g->id); add_to_tmp_clause(-last_v); add_to_tmp_clause(-last_id);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(-g->id); add_to_tmp_clause(last_v); add_to_tmp_clause(last_id);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(g->id); add_to_tmp_clause(-last_v); add_to_tmp_clause(last_id);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(g->id); add_to_tmp_clause(last_v); add_to_tmp_clause(-last_id);
|
|
add_to_tmp_clause(0);
|
|
|
|
break;
|
|
case Gate::XNOR:
|
|
last_v = g->fan_ins[0]->id;
|
|
for(int i=1; i<g->fan_ins.size() - 1; i++) {
|
|
int new_v = ++extra_variable;
|
|
add_to_tmp_clause(-g->fan_ins[i]->id); add_to_tmp_clause(-last_v); add_to_tmp_clause(-new_v);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(-g->fan_ins[i]->id); add_to_tmp_clause(last_v); add_to_tmp_clause(new_v);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(g->fan_ins[i]->id); add_to_tmp_clause(-last_v); add_to_tmp_clause(new_v);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(g->fan_ins[i]->id); add_to_tmp_clause(last_v); add_to_tmp_clause(-new_v);
|
|
add_to_tmp_clause(0);
|
|
last_v = new_v;
|
|
}
|
|
|
|
last_id = g->fan_ins[g->fan_ins.size() - 1]->id;
|
|
|
|
add_to_tmp_clause(g->id); add_to_tmp_clause(-last_v); add_to_tmp_clause(-last_id);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(g->id); add_to_tmp_clause(last_v); add_to_tmp_clause(last_id);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(-g->id); add_to_tmp_clause(-last_v); add_to_tmp_clause(last_id);
|
|
add_to_tmp_clause(0);
|
|
add_to_tmp_clause(-g->id); add_to_tmp_clause(last_v); add_to_tmp_clause(-last_id);
|
|
add_to_tmp_clause(0);
|
|
break;
|
|
default:
|
|
exit(-1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
num_vars = extra_variable;
|
|
num_clauses = clauses.size();
|
|
}
|
|
|
|
} |