2022-10-14 14:04:57 +08:00
|
|
|
#include "sweep.hpp"
|
|
|
|
#include "circuit.hpp"
|
|
|
|
|
|
|
|
bool Sweep::match_xor(int x) { // check clause x, -y, -z <==> xor
|
|
|
|
int y = C[x][0], z = C[x][1];
|
|
|
|
if (y >= 0 || z >= 0) return false;
|
|
|
|
if (del[-y] || del[-z] || !C[-y].sz || !C[-z].sz) return false;
|
|
|
|
int u1 = C[-y][0], v1 = C[-y][1];
|
|
|
|
int u2 = C[-z][0], v2 = C[-z][1];
|
|
|
|
if (u1 == -u2 && v1 == -v2) goto doit;
|
|
|
|
if (u1 == -v2 && v1 == -u2) goto doit;
|
|
|
|
return false;
|
|
|
|
doit:
|
|
|
|
del[x] = 1;
|
|
|
|
if (C[-y].outs <= 1) del[-y] = 2;
|
|
|
|
if (C[-z].outs <= 1) del[-z] = 2;
|
|
|
|
C[x][0] = C[-y][0], C[x][1] = C[-y][1];
|
|
|
|
C[x].type = Xor;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sweep::match_majority(int x) {
|
|
|
|
// x = -y & z
|
|
|
|
// z = -v & -w
|
|
|
|
// y = a1 & a2
|
|
|
|
// v = a1 & a3
|
|
|
|
// w = a2 & a3
|
|
|
|
int y = C[x][0], z = C[x][1];
|
|
|
|
if (y > 0) std::swap(y, z);
|
|
|
|
if (y >= 0 || z <= 0) return false;
|
|
|
|
if (del[-y] || del[z] || !C[-y].sz || !C[z].sz) return false;
|
|
|
|
int v = C[z][0], w = C[z][1];
|
|
|
|
if (v >= 0 || w >= 0) return false;
|
|
|
|
if (del[-v] || del[-w] || !C[-v].sz || !C[-w].sz) return false;
|
|
|
|
// -y, -w, -v
|
|
|
|
int a = C[-y][0], b = C[-y][1];
|
|
|
|
if (C[-v][1] == a || C[-v][1] == b) std::swap(C[-v][0], C[-v][1]);
|
|
|
|
if (C[-w][1] == a || C[-w][1] == b) std::swap(C[-w][0], C[-w][1]);
|
|
|
|
if (C[-v][0] != a && C[-w][0] != a) return false;
|
|
|
|
if (C[-v][0] != b && C[-w][0] != b) return false;
|
|
|
|
if (C[-v][1] != C[-w][1]) return false;
|
|
|
|
del[x] = 1;
|
|
|
|
if (C[-y].outs <= 1) del[-y] = 2;
|
|
|
|
if (C[z].outs <= 1) del[z] = 2;
|
|
|
|
if (C[-v].outs <= 1) del[-v] = 2;
|
|
|
|
if (C[-w].outs <= 1) del[-w] = 2;
|
|
|
|
|
2022-10-21 19:34:18 +08:00
|
|
|
C[x][0] = -a; C[x][1] = -b;
|
|
|
|
C[x].push(-C[-w][1]);
|
2022-10-14 14:04:57 +08:00
|
|
|
C[x].type = Majority;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sweep::adjust_not() {
|
|
|
|
int *pos = new int[maxvar + 1];
|
|
|
|
int *neg = new int[maxvar + 1];
|
|
|
|
for (int i = 1; i <= maxvar; i++)
|
|
|
|
pos[i] = neg[i] = 0;
|
|
|
|
for (int i = 1; i <= maxvar; i++) {
|
|
|
|
if (!C[i].sz || del[i] == 2) continue;
|
|
|
|
for (int j = 0; j < C[i].sz; j++) {
|
|
|
|
int v = C[i][j];
|
|
|
|
if (v > 0) pos[v]++;
|
|
|
|
else neg[-v]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 1; i <= maxvar; i++) {
|
|
|
|
if (!C[i].sz || del[i] == 2) continue;
|
|
|
|
if (C[i].type == Xor && pos[i] == 0 && neg[i] > 0) {
|
|
|
|
for (int j = 0; j < C[i].sz; j++)
|
|
|
|
if (C[i][j] < 0 && C[-C[i][j]].neg == 0) {C[i][j] = -C[i][j]; C[i].neg = 1; break;}
|
|
|
|
}
|
|
|
|
// if (C[i].type == Xor) {
|
|
|
|
// int z = 0;
|
|
|
|
// for (int j = 0; j < C[i].sz; j++)
|
|
|
|
// if (C[i][j] < 0) {C[i][j] = -C[i][j]; z ^= 1;}
|
|
|
|
// if (z) C[i].neg = 1;
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sweep::match_HA() {
|
|
|
|
std::map<int, int> M;
|
|
|
|
int lits = maxvar << 1 | 1;
|
|
|
|
for (int i = 1; i <= maxvar; i++) {
|
|
|
|
if (!C[i].sz || del[i] == 2 || C[i].type != And) continue;
|
|
|
|
int mapid = C[i][0] * lits + C[i][1];
|
|
|
|
M[mapid] = i;
|
|
|
|
}
|
|
|
|
for (int i = 1; i <= maxvar; i++) {
|
|
|
|
if (!C[i].sz || del[i] == 2 || C[i].type != Xor) continue;
|
|
|
|
int mapid = C[i][0] * lits + C[i][1];
|
|
|
|
int id = M[mapid];
|
|
|
|
if (id) {
|
|
|
|
C[i].type = HA;
|
|
|
|
C[i].carrier = id;
|
|
|
|
del[id] = 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
mapid = (-C[i][0]) * lits - C[i][1];
|
|
|
|
id = M[mapid];
|
|
|
|
if (id) {
|
|
|
|
C[i].type = HA;
|
|
|
|
C[i].carrier = id;
|
|
|
|
C[i][0] = -C[i][0];
|
|
|
|
C[i][1] = -C[i][1];
|
|
|
|
del[id] = 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
mapid = C[i][0] * lits - C[i][1];
|
|
|
|
id = M[mapid];
|
|
|
|
if (id) {
|
|
|
|
C[i].type = HA;
|
|
|
|
C[i].carrier = id;
|
|
|
|
C[i][1] = -C[i][1];
|
|
|
|
C[i].neg = 1;
|
|
|
|
del[id] = 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
mapid = (-C[i][0]) * lits + C[i][1];
|
|
|
|
id = M[mapid];
|
|
|
|
if (id) {
|
|
|
|
C[i].type = HA;
|
|
|
|
C[i].carrier = id;
|
|
|
|
C[i][0] = -C[i][0];
|
|
|
|
C[i].neg = 1;
|
|
|
|
del[id] = 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sweep::line_positive(int to) {
|
|
|
|
return (to < 0) == C[abs(to)].neg;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sweep::recalculate_outs() {
|
|
|
|
for (int i = 1; i <= maxvar; i++)
|
|
|
|
C[i].outs = 0;
|
|
|
|
for (int i = 1; i <= maxvar; i++) {
|
|
|
|
circuit *c = &C[i];
|
|
|
|
if (!c->sz || del[i] == 2) continue;
|
|
|
|
for (int j = 0; j < c->sz; j++) {
|
|
|
|
C[abs(c->to[j])].outs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sweep::match_FA() {
|
|
|
|
for (int i = 1; i <= maxvar; i++) {
|
|
|
|
circuit *c = &C[i];
|
|
|
|
if (!c->sz || del[i] == 2) continue;
|
|
|
|
if (c->type != HA) continue;
|
|
|
|
C[abs(c->carrier)].to.clear();
|
|
|
|
C[abs(c->carrier)].to.push(i);
|
|
|
|
C[abs(c->carrier)].sz = 1;
|
|
|
|
C[abs(c->carrier)].neg = c->carrier < 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i=1; i<=maxvar; i++) {
|
|
|
|
if (!C[i].sz || del[i] == 2) continue;
|
|
|
|
|
|
|
|
circuit *c = &C[i];
|
|
|
|
|
|
|
|
if(c->type != And) continue;
|
|
|
|
|
|
|
|
if(c->sz != 2) continue;
|
|
|
|
|
|
|
|
if(c->to[0] >= 0) continue;
|
|
|
|
if(c->to[1] >= 0) continue;
|
|
|
|
|
|
|
|
if(C[abs(c->to[0])].sz != 1) continue;
|
|
|
|
if(C[abs(c->to[1])].sz != 1) continue;
|
|
|
|
|
|
|
|
int ha1 = C[abs(c->to[0])][0];
|
|
|
|
int ha2 = C[abs(c->to[1])][0];
|
|
|
|
|
|
|
|
ha1 = abs(ha1);
|
|
|
|
ha2 = abs(ha2);
|
|
|
|
|
|
|
|
if(C[ha1].type != HA) continue;
|
|
|
|
if(C[ha2].type != HA) continue;
|
|
|
|
|
|
|
|
bool check_link = true;
|
|
|
|
for(int k=0; k<C[ha1].sz; k++) {
|
|
|
|
int t = C[ha1].to[k];
|
|
|
|
if(abs(t) == ha2) std::swap(ha1, ha2);
|
|
|
|
if(abs(t) == ha2 && !line_positive(t))
|
|
|
|
check_link = false;
|
|
|
|
}
|
|
|
|
for(int k=0; k<C[ha2].sz; k++) {
|
|
|
|
int t = C[ha2].to[k];
|
|
|
|
if(abs(t) == ha1 && !line_positive(t))
|
|
|
|
check_link = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!check_link) continue;
|
|
|
|
|
|
|
|
//printf("FA %d(%d) %d(%d)\n", ha1, C[ha1].neg, ha2, C[ha2].neg);
|
|
|
|
|
|
|
|
if(C[ha1].outs == 2) del[ha1] = 2;
|
|
|
|
|
|
|
|
circuit* fa = &C[ha2];
|
|
|
|
fa->type = FA;
|
|
|
|
fa->carrier = -i;
|
|
|
|
vec<int> new_vec;
|
|
|
|
for(int k=0; k<C[ha1].sz; k++) {
|
|
|
|
int t = C[ha1].to[k];
|
|
|
|
if(abs(t) == ha2) continue;
|
|
|
|
new_vec.push(t);
|
|
|
|
//printf("push: %d\n", t);
|
|
|
|
}
|
|
|
|
for(int k=0; k<C[ha2].sz; k++) {
|
|
|
|
int t = C[ha2].to[k];
|
|
|
|
if(abs(t) == ha1) continue;
|
|
|
|
//printf("push: %d\n", k, t);
|
|
|
|
new_vec.push(t);
|
|
|
|
}
|
|
|
|
new_vec.copyTo(fa->to);
|
|
|
|
fa->sz = fa->to.size();
|
|
|
|
|
|
|
|
C[i].to.clear();
|
|
|
|
C[i].sz = 0;
|
|
|
|
C[i].neg = !C[i].neg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sweep::to_multi_input_gates() {
|
|
|
|
//printf("hello\n %d\n", maxvar);
|
|
|
|
std::queue<int> q;
|
|
|
|
q.push(maxvar);
|
|
|
|
while(!q.empty()) {
|
|
|
|
int u = q.front();
|
|
|
|
q.pop();
|
|
|
|
|
|
|
|
circuit *c = &C[u];
|
|
|
|
|
|
|
|
if(u == maxvar) {
|
|
|
|
for(int i=0; i<c->sz; i++) {
|
|
|
|
if (!C[abs(c->to[i])].sz || del[abs(c->to[i])] == 2) continue;
|
|
|
|
q.push(abs(c->to[i]));
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i=0; i<c->sz; i++) {
|
|
|
|
circuit *t = &C[abs(c->to[i])];
|
|
|
|
if(t->type != c->type) continue;
|
|
|
|
vec<int> new_vec;
|
|
|
|
if(c->type == Xor) {
|
|
|
|
//printf("XOR: %d %d\n", u, c->to[i]);
|
|
|
|
for(int j=0; j<t->sz; j++) {
|
|
|
|
new_vec.push(t->to[j]);
|
|
|
|
//printf("add %d\n", t->to[j]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int j=0; j<c->sz; j++) {
|
|
|
|
if(i == j) {
|
|
|
|
if(!line_positive(c->to[j]))
|
|
|
|
new_vec[0] = -new_vec[0];
|
|
|
|
} else {
|
|
|
|
new_vec.push(c->to[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t->outs == 1) {
|
|
|
|
del[abs(c->to[i])] = 2;
|
|
|
|
//printf("del: %d\n", c->to[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
new_vec.copyTo(c->to);
|
|
|
|
c->sz = new_vec.size();
|
|
|
|
|
|
|
|
q.push(u);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(c->type == And && line_positive(c->to[i])) {
|
|
|
|
if(t->to.size() == 0) continue;
|
|
|
|
|
|
|
|
//printf("AND: %d %d\n", u, c->to[i]);
|
|
|
|
t->to.copyTo(new_vec);
|
|
|
|
//printf("new_vec %d\n", new_vec.size());
|
|
|
|
|
|
|
|
for(int j=0; j<c->sz; j++) {
|
|
|
|
if(i != j) {
|
|
|
|
new_vec.push(c->to[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(C[abs(c->to[i])].outs == 1) {
|
|
|
|
del[abs(c->to[i])] = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_vec.copyTo(c->to);
|
|
|
|
c->sz = new_vec.size();
|
|
|
|
|
|
|
|
q.push(u);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(int i=0; i<c->sz; i++) {
|
|
|
|
if (!C[abs(c->to[i])].sz || del[abs(c->to[i])] == 2) continue;
|
|
|
|
q.push(abs(c->to[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sweep::to_dot_graph(const char* filename, int end_point) {
|
|
|
|
std::ofstream file(filename);
|
|
|
|
std::queue<int> q;
|
|
|
|
q.push(abs(end_point));
|
|
|
|
std::set<int> used;
|
|
|
|
used.insert(abs(end_point));
|
|
|
|
file << "digraph \"graph\" {\n";
|
|
|
|
|
|
|
|
char str[1024];
|
|
|
|
|
|
|
|
while(!q.empty()) {
|
|
|
|
int u = q.front();
|
|
|
|
q.pop();
|
|
|
|
circuit *c = &C[u];
|
|
|
|
|
|
|
|
if(!c->sz || del[u] == 2) continue;
|
|
|
|
|
|
|
|
sprintf(str, "A%d[label=\"%d (%s)\"];\n", u, u, gate_type[c->type].c_str());
|
|
|
|
file << str;
|
|
|
|
if (c->type == HA || c->type == FA) {
|
|
|
|
int a = u * (C[u].neg ? -1 : 1);
|
|
|
|
int b = c->carrier;
|
|
|
|
sprintf(str, "A%d->A%d[arrowhead=%s]\n", u, abs(b), !line_positive(b) ? "dot" : "none");
|
|
|
|
file << str;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int t = u * (C[u].neg ? -1 : 1);
|
|
|
|
}
|
|
|
|
for (int j = 0; j < c->sz; j++) {
|
|
|
|
/**
|
|
|
|
* 删除初始输入
|
|
|
|
*/
|
2022-10-21 19:34:18 +08:00
|
|
|
if(abs(c->to[j]) <= 14) continue;
|
2022-10-14 14:04:57 +08:00
|
|
|
|
|
|
|
sprintf(str, "A%d->A%d[arrowhead=%s]\n", abs(c->to[j]), u, !line_positive(c->to[j]) ? "dot" : "none");
|
|
|
|
file << str;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int j=0; j<c->sz; j++) {
|
|
|
|
int x = abs(c->to[j]);
|
|
|
|
if(used.count(x)) continue;
|
|
|
|
used.insert(x);
|
|
|
|
q.push(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
file << "}\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sweep::identify() {
|
2022-10-21 19:34:18 +08:00
|
|
|
|
2022-10-14 14:04:57 +08:00
|
|
|
del = new int[maxvar + 1];
|
|
|
|
for (int i = 1; i <= maxvar; i++) del[i] = 0;
|
|
|
|
recalculate_outs();
|
|
|
|
for (int i = 1; i <= maxvar; i++) {
|
|
|
|
if (!C[i].sz || del[i] == 2) continue;
|
|
|
|
if (match_xor(i)) continue;
|
|
|
|
}
|
|
|
|
|
2022-10-21 19:34:18 +08:00
|
|
|
// recalculate_outs();
|
2022-10-14 14:04:57 +08:00
|
|
|
|
2022-10-21 19:34:18 +08:00
|
|
|
// for (int i = 1; i <= maxvar; i++) {
|
|
|
|
// if (!C[i].sz || del[i] == 2) continue;
|
|
|
|
// if (match_majority(i)) continue;
|
|
|
|
// }
|
2022-10-14 14:04:57 +08:00
|
|
|
|
|
|
|
recalculate_outs();
|
2022-10-21 19:34:18 +08:00
|
|
|
//adjust_not();
|
|
|
|
//match_HA();
|
2022-10-14 14:04:57 +08:00
|
|
|
|
2022-10-21 19:34:18 +08:00
|
|
|
//to_multi_input_gates();
|
|
|
|
//match_FA();
|
2022-10-14 14:04:57 +08:00
|
|
|
|
|
|
|
// printf("digraph \"graph\" {\n");
|
|
|
|
// for (int i = 1; i <= maxvar; i++) {
|
|
|
|
// circuit *c = &C[i];
|
|
|
|
// if (!c->sz || del[i] == 2) continue;
|
|
|
|
|
|
|
|
// printf("A%d[label=\"%d (%s)\"];\n", i, i, gate_type[c->type].c_str());
|
|
|
|
|
|
|
|
// if (c->type == HA || c->type == FA) {
|
|
|
|
// int a = i * (C[i].neg ? -1 : 1);
|
|
|
|
// int b = c->carrier;
|
|
|
|
// printf("A%d->A%d[arrowhead=%s]\n", i, abs(b), !line_positive(b) ? "dot" : "none");
|
|
|
|
// }
|
|
|
|
// else {
|
|
|
|
// int t = i * (C[i].neg ? -1 : 1);
|
|
|
|
// }
|
|
|
|
// for (int j = 0; j < c->sz; j++) {
|
|
|
|
// if(abs(c->to[j]) <= 14) continue;
|
|
|
|
// printf("A%d->A%d[arrowhead=%s]\n", abs(c->to[j]), i, !line_positive(c->to[j]) ? "dot" : "none");
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// printf("}\n");
|
|
|
|
|
2022-10-21 19:34:18 +08:00
|
|
|
recalculate_outs();
|
|
|
|
// for (int i = 1; i <= maxvar; i++) {
|
|
|
|
// circuit *c = &C[i];
|
|
|
|
// if (!c->sz || del[i] == 2) continue;
|
|
|
|
|
|
|
|
// if (c->type == HA || c->type == FA)
|
|
|
|
// printf("( %d %d )", i * (C[i].neg ? -1 : 1), c->carrier);
|
|
|
|
// else
|
|
|
|
// printf("%d", i * (C[i].neg ? -1 : 1));
|
|
|
|
|
|
|
|
// printf(" = %s ( ", gate_type[c->type].c_str());
|
|
|
|
|
|
|
|
// for (int j = 0; j < c->sz; j++) {
|
|
|
|
// printf("%d ", c->to[j]);
|
|
|
|
// }
|
|
|
|
|
|
|
|
// puts(")");
|
|
|
|
// }
|
|
|
|
|
|
|
|
inv_C = new vec<int>[maxvar + 1];
|
|
|
|
for (int i = 1; i <= maxvar; i++) {
|
|
|
|
circuit *c = &C[i];
|
|
|
|
if (!c->sz || del[i] == 2) continue;
|
|
|
|
for (int j = 0; j < c->sz; j++) {
|
|
|
|
inv_C[abs(c->to[j])].push(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// to_dot_graph("graph1.dot", 291);
|
|
|
|
// to_dot_graph("graph2.dot", 175);
|
2022-10-14 14:04:57 +08:00
|
|
|
|
|
|
|
// recalculate_outs();
|
|
|
|
// for (int i = 1; i <= maxvar; i++) {
|
|
|
|
// circuit *c = &C[i];
|
|
|
|
// if (del[i] == 2) continue;
|
|
|
|
// printf("%d : %d (outs)\n", i, c->outs);
|
|
|
|
// }
|
2022-10-21 19:34:18 +08:00
|
|
|
|
2022-10-14 14:04:57 +08:00
|
|
|
}
|