#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; C[x][0] = -a; C[x][1] = -b; C[x].push(-C[-w][1]); 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 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; ktype = FA; fa->carrier = -i; vec new_vec; for(int k=0; kto); 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 q; q.push(maxvar); while(!q.empty()) { int u = q.front(); q.pop(); circuit *c = &C[u]; if(u == maxvar) { for(int i=0; isz; 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; isz; i++) { circuit *t = &C[abs(c->to[i])]; if(t->type != c->type) continue; vec new_vec; if(c->type == Xor) { //printf("XOR: %d %d\n", u, c->to[i]); for(int j=0; jsz; j++) { new_vec.push(t->to[j]); //printf("add %d\n", t->to[j]); } for(int j=0; jsz; 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; jsz; 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; isz; 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 q; q.push(abs(end_point)); std::set 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++) { /** * 删除初始输入 */ if(abs(c->to[j]) <= 14) continue; 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; jsz; j++) { int x = abs(c->to[j]); if(used.count(x)) continue; used.insert(x); q.push(x); } } file << "}\n"; } void Sweep::identify() { 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; } // recalculate_outs(); // for (int i = 1; i <= maxvar; i++) { // if (!C[i].sz || del[i] == 2) continue; // if (match_majority(i)) continue; // } recalculate_outs(); //adjust_not(); //match_HA(); //to_multi_input_gates(); //match_FA(); // 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"); 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[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); // 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); // } }