218 lines
7.4 KiB
C++
Raw Normal View History

2023-02-24 07:58:40 +00:00
#include "preprocess.hpp"
int preprocess::find(int x) {
if (f[x] == x) return x;
int fa = f[x];
f[x] = find(fa);
val[x] = val[fa] * val[x];
return f[x];
}
bool preprocess::preprocess_binary() {
HashMap *C = new HashMap();
for (int i = 1; i <= clauses; i++) {
int l = clause[i].size();
for (int j = 0; j < l; j++) {
clause[i][j] = tolit(clause[i][j]);
}
}
2023-03-03 08:01:45 +00:00
printf("c sz %d\n", clause[1].size());
2023-02-24 07:58:40 +00:00
nlit = (vars << 1) + 2;
2023-03-03 08:01:45 +00:00
for (int i = 1; i <= vars; i++) f[i] = i, val[i] = 1, varval[i] = color[i] = resseen[tolit(i)] = resseen[tolit(-i)] = 0;
2023-02-24 07:58:40 +00:00
for (int i = 1; i <= clauses; i++) clause_delete[i] = 0;
int len = 0;
for (int i = 1; i <= clauses; i++) {
if (clause[i].size() != 2) continue;
nxtc[++len] = i;
ll id1 = mapv(clause[i][0], clause[i][1]),
id2 = mapv(clause[i][1], clause[i][0]);
C->insert(id1, i);
C->insert(id2, i);
}
int simplify = 1, turn = 0;
while (simplify) {
simplify = 0;
++turn;
int s1 = 0, s2 = 0, s3 = 0;
for (int k = 1; k <= len; k++) {
int i = nxtc[k];
if (clause[i].size() != 2 || clause_delete[i]) continue;
ll id1 = mapv(negative(clause[i][0]), negative(clause[i][1])),
id2 = mapv(clause[i][0], negative(clause[i][1])),
id3 = mapv(negative(clause[i][0]), clause[i][1]);
int r = C->get(id1, 0);
if (r) {
simplify = 1;
++s1;
clause_delete[r] = clause_delete[i] = 1;
int u = toiidx(clause[i][0]), v = toiidx(clause[i][1]);
int fa = find(u), fb = find(v);
int sig = sign(clause[i][0]) * sign(clause[i][1]) * (-1);
//sig == 1 : a = b -1 : a = -b
if (fa != fb) {
if (fa < fb) {
f[fa] = fb;
val[fa] = sig / (val[u] * val[v]);
if (varval[fa])
varval[fb] = val[fa] * varval[fa];
}
else if (fa > fb) {
f[fb] = fa;
val[fb] = sig / (val[u] * val[v]);
if (varval[fb])
varval[fa] = val[fb] * varval[fb];
}
}
else {
if (sig != val[u] * val[v])
return false;
}
}
int d1 = C->get(id2, 0);
if (d1) {
int v = toiidx(clause[i][0]);
if (varval[v] && varval[v] != sign(clause[i][0])) {
return false;
}
clause_delete[d1] = clause_delete[i] = 1;
simplify = 1;
varval[v] = sign(clause[i][0]);
}
int d2 = C->get(id3, 0);
if (d2) {
int v = toiidx(clause[i][1]);
if (varval[v] && varval[v] != sign(clause[i][1])) {
return false;
}
clause_delete[d2] = clause_delete[i] = 1;
simplify = 1;
varval[v] = sign(clause[i][1]);
}
}
for (int i = 1; i <= vars; i++) {
int x = find(i);
if (varval[i] && x != i) {
if (varval[x]) {
if (varval[x] != varval[i] * val[i])
return false;
}
else varval[x] = varval[i] * val[i];
}
}
for (int i = 1; i <= vars; i++)
if (varval[f[i]]) {
if (varval[i]) {
if (varval[f[i]] != varval[i] * val[i])
return false;
}
else varval[i] = varval[f[i]] * val[i];
}
len = 0;
for (int i = 1; i <= clauses; i++) {
if (clause_delete[i]) continue;
int l = clause[i].size(), oril = l;
for (int j = 0; j < l; j++) {
int v = toiidx(clause[i][j]), fa = f[v];
a[j] = tolit(sign(clause[i][j]) * val[v] * fa);
}
int t = 0;
for (int j = 0; j < l; j++) {
int x = varval[toiidx(a[j])];
if (x) {
int k = x * sign(a[j]);
if (k == 1) {
if (!clause_delete[i]) simplify = 1;
clause_delete[i] = 1, a[t++] = a[j];
}
}
else a[t++] = a[j];
}
if (t == 0) return false;
if (t != l) simplify = 1, l = t;
2023-03-03 08:01:45 +00:00
2023-02-24 07:58:40 +00:00
t = 0;
for (int j = 0; j < l; j++) {
if (resseen[a[j]] == i) continue;
resseen[a[j]] = i, a[t++] = a[j];
}
if (t != l) simplify = 1, l = t;
for (int j = 0; j < l; j++)
if (resseen[negative(a[j])] == i && !clause_delete[i]) {
clause_delete[i] = 1, simplify = 1;
}
for (int j = 0; j < l; j++) resseen[a[j]] = 0;
if (l == 1) {
if (sign(a[0]) * varval[toiidx(a[0])] == -1) return false;
varval[toiidx(a[0])] = sign(a[0]);
simplify = 1;
}
if (!clause_delete[i] && l == 2 && oril != 2) {
nxtc[++len] = i;
ll id1 = mapv(a[0], a[1]),
id2 = mapv(a[1], a[0]);
C->insert(id1, i);
C->insert(id2, i);
}
else if (!clause_delete[i] && l == 2 && oril == 2) {
if (a[0] == clause[i][0] && a[1] == clause[i][1]) ;
else if (a[1] == clause[i][0] && a[0] == clause[i][1]) ;
else {
nxtc[++len] = i;
ll id1 = mapv(a[0], a[1]),
id2 = mapv(a[1], a[0]);
C->insert(id1, i);
C->insert(id2, i);
}
}
clause[i].clear();
for (int j = 0; j < l; j++)
clause[i].push(a[j]);
}
2023-03-03 08:01:45 +00:00
2023-02-24 07:58:40 +00:00
for (int i = 1; i <= vars; i++) {
int x = find(i);
if (varval[i] && x != i) {
if (varval[x]) {
if (varval[x] != varval[i] * val[i])
return false;
}
else varval[x] = varval[i] * val[i];
}
}
for (int i = 1; i <= vars; i++)
if (varval[f[i]]) {
if (varval[i]) {
if (varval[f[i]] != varval[i] * val[i])
return false;
}
else varval[i] = varval[f[i]] * val[i];
}
}
2023-03-03 08:01:45 +00:00
printf("c turns: %d\n", turn);
2023-02-24 07:58:40 +00:00
for (int i = 1; i <= clauses; i++) {
if (clause_delete[i]) continue;
int l = clause[i].size();
for (int j = 0; j < l; j++) {
clause[i][j] = toeidx(clause[i][j]);
}
}
update_var_clause_label();
for (int i = 1; i <= orivars; i++) {
if (mapval[i]) continue;
int v = mapto[i], fa = find(v);
if (varval[v] || varval[fa]) {
mapval[i] = varval[v];
mapto[i] = 0;
}
else if (color[fa]) mapto[i] = color[fa] * val[v];
else {mapval[i] = val[v], mapto[i] = 0;}
}
return true;
}