#include "sweep.hpp" #include "circuit.hpp" #include "src/cadical.hpp" extern "C" { #include "aiger.h" } void Sweep::propagate(int* input, int* result) { std::queue q; for(int i=0; inum_inputs; i++) { result[aig->inputs[i].lit] = input[i]; result[aig->inputs[i].lit+1] = !input[i]; q.push(aiger_lit2var(aig->inputs[i].lit)); } static int* topo_counter = new int[maxvar + 1]; memset(topo_counter, 0, (maxvar + 1) * sizeof(int)); while(!q.empty()) { int cur = q.front(); q.pop(); for(auto& edge : graph.edge[cur]) { int v = edge.to; topo_counter[v]++; if(topo_counter[v] == 2) { q.push(v); //cout << "redge: " << v << " " << graph.redge[v][0].to << " " << graph.redge[v][1].to << endl; Graph::Edge rhs0_edge = graph.redge[v][0]; int rhs0 = aiger_var2lit(rhs0_edge.to); Graph::Edge rhs1_edge = graph.redge[v][1]; int rhs1 = aiger_var2lit(rhs1_edge.to); result[aiger_var2lit(v)] = result[rhs0 + rhs0_edge.neg] & result[rhs1 + rhs1_edge.neg]; result[aiger_var2lit(v)+1] = !result[aiger_var2lit(v)]; //cout << "var: " << aiger_var2lit(v) << " = " << rhs0 + rhs0_edge.neg << " " << rhs1 + rhs1_edge.neg << " : " << result[aiger_var2lit(v)] << endl; } } } } void Sweep::circuit_propagate(int *input, int* result) { std::queue q; for(int i=1; i<=aig->num_inputs; i++) { result[i] = input[i - 1]; q.push(i); // printf("%d %d\n", i, result[i]); } for (int i = 1; i <= maxvar; i++) seen[i] = 0; while(!q.empty()) { int x = q.front(); q.pop(); for (int i = 0; i < inv_C[x].size(); i++) { int v = inv_C[x][i]; seen[v]++; if (seen[v] == C[v].sz) { q.push(v); if (C[v].type == And) { result[v] = 1; for (int j = 0; j < C[v].sz; j++) { int x = C[v][j]; result[v] &= x > 0 ? result[abs(x)] : !result[abs(x)]; } } else if (C[v].type == Xor) { result[v] = 0; for (int j = 0; j < C[v].sz; j++) { int x = C[v][j]; result[v] ^= x > 0 ? result[abs(x)] : !result[abs(x)]; } } else if (C[v].type == Majority) { int s[2] = {0, 0}; for (int j = 0; j < C[v].sz; j++) { int x = C[v][j]; s[x > 0 ? result[abs(x)] : !result[abs(x)]]++; } result[v] = s[1] > s[0] ? 1 : 0; } else if (C[v].type == HA) { assert(C[v].sz == 2); int s = 0; for (int j = 0; j < C[v].sz; j++) { int x = C[v][j]; s += x > 0 ? result[abs(x)] : !result[abs(x)]; } result[v] = s % 2; result[abs(C[v].carrier)] = s >> 1; if (C[v].carrier < 0) result[abs(C[v].carrier)] = !result[abs(C[v].carrier)]; q.push(abs(C[v].carrier)); } else if (C[v].type == FA) { assert(C[v].sz == 3); int s = 0; for (int j = 0; j < C[v].sz; j++) { int x = C[v][j]; s += x > 0 ? result[abs(x)] : !result[abs(x)]; } result[v] = s % 2; result[abs(C[v].carrier)] = s >> 1; if (C[v].carrier < 0) result[abs(C[v].carrier)] = !result[abs(C[v].carrier)]; q.push(abs(C[v].carrier)); } if (C[v].neg) result[v] = !result[v]; // printf("%d %d\n", v, result[v]); } } } } // int Sweep::seen_cut_points(aiger* aig, int x, int y) { // std::queue q; // int *used = // x = x & 1 ? -aiger_lit2var(x) : aiger_lit2var(x); // y = y & 1 ? -aiger_lit2var(y) : aiger_lit2var(y); // if (!used[abs(x)]) // q.push(abs(x)), used[abs(x)] = true; // if(!used[abs(y)]) // q.push(abs(y)), used[abs(y)] = true; // } bool Sweep::check_var_equal(int x, int y, int assume) { std::queue q; x = x & 1 ? -aiger_lit2var(x) : aiger_lit2var(x); y = y & 1 ? -aiger_lit2var(y) : aiger_lit2var(y); if (!used[abs(x)]) q.push(abs(x)), used[abs(x)] = true; if(!used[abs(y)]) q.push(abs(y)), used[abs(y)] = true; int can_del = 2; while(!q.empty()) { int u = q.front(); q.pop(); /* (u => a & b) <=> ~u | (a & b) <=> (~u | a) & (~u | b) (u <= a & b) <=> ~(a & b) | u <=> ~a | ~b | u */ if(graph.redge[u].size() == 0) continue; int a = graph.redge[u][0].to; int b = graph.redge[u][1].to; //cout << "AND " << aiger_var2lit(u) << " " << (aiger_var2lit(a) + graph.redge[u][0].neg) << " " << (aiger_var2lit(b) + graph.redge[u][1].neg) << endl; if(graph.redge[u][0].neg) a = -a; if(graph.redge[u][1].neg) b = -b; solver->add(-u), solver->add( a), solver->add(0); solver->add(-u), solver->add( b), solver->add(0); solver->add(-a), solver->add(-b), solver->add(u), solver->add(0); a = abs(a), b = abs(b); if(!used[a]) q.push(a), used[a] = true, can_del++; if(!used[b]) q.push(b), used[b] = true, can_del++; } //Assume -NV solver->add(-assume), solver->add(-x), solver->add(-y), solver->add(0); solver->add(-assume), solver->add(x), solver->add(y), solver->add(0); solver->assume (assume); int result = solver->solve (); // if (result == 20) printf("can delete %d vars\n", can_del); return result == 20; } bool Sweep::check_constant(int x, int val) { std::queue q; x = x & 1 ? -aiger_lit2var(x) : aiger_lit2var(x); if (!used[abs(x)]) q.push(abs(x)), used[abs(x)] = true; while(!q.empty()) { int u = q.front(); q.pop(); if(graph.redge[u].size() == 0) continue; int a = graph.redge[u][0].to; int b = graph.redge[u][1].to; if(graph.redge[u][0].neg) a = -a; if(graph.redge[u][1].neg) b = -b; solver->add(-u), solver->add( a), solver->add(0); solver->add(-u), solver->add( b), solver->add(0); solver->add(-a), solver->add(-b), solver->add(u), solver->add(0); a = abs(a), b = abs(b); if(!used[a]) q.push(a), used[a] = true; if(!used[b]) q.push(b), used[b] = true; } solver->assume (x * (val ? -1 : 1)); int result = solver->solve(); return result == 20; } void Sweep::random_simulation() { int* result = new int[2 * maxvar + 2]; int* circuit_res = new int[maxvar + 1]; int* input_vector = new int[aig->num_inputs]; for(int i=0; inum_inputs; i++) { input_vector[i] = rand() % 2; } for (int i=0; inum_inputs) input_vector[abs(det_v[i]) - 1] = det_v[i] > 0 ? 1 : 0; } memset(result, -1, (2 * maxvar + 2) * sizeof(int)); memset(circuit_res, -1, (maxvar + 1) * sizeof(int)); propagate(input_vector, result); circuit_propagate(input_vector, circuit_res); if (result[output] != !circuit_res[output >> 1]) { printf("wrong %d %d %d\n", output, !result[output], circuit_res[output >> 1]); for (int i = 1; i <= maxvar; i++) { if (circuit_res[i] == -1) continue; if (result[i * 2] != circuit_res[i]) printf("%d %d %d\n", i, result[i * 2], circuit_res[i]); printf("%d %d\n", i, result[i << 1]); } return; } std::vector> tmp; for(auto& clas : classes) { std::vector v0; std::vector v1; for(auto &v : clas) { if(result[v]) v1.push_back(v), sum_pos[v] += 1; else v0.push_back(v), sum_neg[v] += 1; } if(v0.size() > 1) tmp.push_back(v0); if(v1.size() > 1) tmp.push_back(v1); } classes = tmp; } printf("c Number of equivalent classes: %d\n", classes.size()); // printf("classes: \n"); // for(auto& clas : classes) { // int lit = clas[0]; // printf("[ "); // for(auto &v : clas) { // printf("%d ", v); // } // printf("] %d %d\n", sum_pos[lit], sum_neg[lit]); // } } void Sweep::simulation() { //printf("c =================================== detect =================================\n"); seen = new int[maxvar + 1]; classes.push_back(std::vector()); for(int i=2; i<=maxvar*2+1; i++) { classes[0].push_back(i); } random_simulation(); }