#include "circuit.h" #include #include #include #include #include #include "assert.h" bool Circuit::local_search(std::unordered_set &faults) { //STEM_INC = 0; // 初始化并重置所有 ls 数据结构 ls_init_data_structs(); // 随机生成初始电路 ls_init_circuit(faults); printf("local search!\n"); while(true) { Gate* picked_stem = ls_pick_good_var(); if(picked_stem == nullptr) { ls_update_weight(); picked_stem = ls_pick_falsified_var(); printf("[UP] propagate: %lld, stem: %lld, fault:%lld. propagate_cnt: %d, stem_cnt: %d, fault_cnt:%d\n", propagate_total_cost, stem_total_cost, fault_total_cost, propagate_falsified_cnt, stem_falsified_cnt, fault_falsified_cnt); } else { printf("[LS] propagate: %lld, stem: %lld, fault:%lld. propagate_cnt: %d, stem_cnt: %d, fault_cnt:%d\n", propagate_total_cost, stem_total_cost, fault_total_cost, propagate_falsified_cnt, stem_falsified_cnt, fault_falsified_cnt); } ls_update(picked_stem); if(stem_falsified_cnt == 0 && propagate_falsified_cnt == 0) { printf("FIND SOLUTION!\n"); printf("[SOL] propagate: %lld, stem: %lld, fault:%lld. propagate_cnt: %d, stem_cnt: %d, fault_cnt:%d\n", propagate_total_cost, stem_total_cost, fault_total_cost, propagate_falsified_cnt, stem_falsified_cnt, fault_falsified_cnt); break; } } static int original_faults = -1; if(original_faults == - 1) { original_faults = faults.size(); } static int pattern = 0; std::unordered_set tmp = faults; for(Fault* f : tmp) { if(f->gate->fault_satisfied[f->type]) { faults.erase(f); } } if(tmp.size() == faults.size()) pattern--; printf("coverage: %.4f\tpattern: %d\tbefore: %ld\tnow: %ld\n", (double)(original_faults - faults.size()) / (original_faults), ++pattern, tmp.size(), faults.size()); //if(tmp.size() == faults.size()) return false; return true; } Gate* Circuit::ls_pick_falsified_var() { std::vector candidates; for(Gate *g : stems) { if(g->po) continue; if(g->stem_satisified) continue; candidates.push_back(g); } if(candidates.size() == 0) { candidates.push_back(stems[rand()%stems.size()]); } Gate* pick = candidates[rand()%candidates.size()]; return pick; } Gate* Circuit::ls_pick_good_var() { Gate* stem = nullptr; ll max_score = 0; std::vector stems_random; std::vector candidates; for(Gate* s : stems) { if(s->CC) { stems_random.push_back(s); } } for(int i=0; i max_score) { max_score = t_score; stem = t_stem; } if(t_score > 0) t++; if(i >= T) break; } if(max_score > 0) { return stem; } else { return nullptr; } } void Circuit::ls_update_weight() { //STEM_INC += 5; if(false) { } else { for(Gate* g : gates) { if(g->stem && !g->propagate_satisfied && (g->propagate_cost + PROPAGATE_INC <= PROPAGATE_COST_MAX)) { g->propagate_cost += PROPAGATE_INC; propagate_total_cost += PROPAGATE_INC; } if(g->stem && !g->stem_satisified && (g->stem_cost + STEM_INC <= STEM_COST_MAX)) { g->stem_cost += STEM_INC; stem_total_cost += STEM_INC; for(Gate* suc : g->suc_stems) { if(suc->stem_cost - STEM_INC >= 1) { suc->stem_cost -= STEM_INC; if(!suc->stem_satisified) { stem_total_cost -= STEM_INC; } } } } if(!g->fault_satisfied[0] && g->fault_cost[0] > 0 && (g->fault_cost[0] + FAULT_INC <= FAULT_COST_MAX)) { g->fault_cost[0] += FAULT_INC; fault_total_cost += FAULT_INC; } if(!g->fault_satisfied[1] && g->fault_cost[1] > 0 && (g->fault_cost[1] + FAULT_INC <= FAULT_COST_MAX)) { g->fault_cost[1] += FAULT_INC; fault_total_cost += FAULT_INC; } } } } bool cmp(Gate* a, Gate *b) { return a->id > b->id; } void Circuit::ls_update(Gate* stem) { stem->CC = 0; for(Gate* pre : stem->pre_stems) { pre->CC = 1; } for(Gate* suc : stem->suc_stems) { suc->CC = 1; } ls_block_recal(stem); } ll Circuit::ls_pick_score(Gate* stem) { ll old_score = ls_score(); //stem->value = !stem->value; ls_update(stem); ll new_score = ls_score(); //stem->value = !stem->value; ls_update(stem); old_score = std::max(old_score, ls_score()); return new_score - old_score; } ll Circuit::ls_score() { ll score = - propagate_total_cost - stem_total_cost - fault_total_cost; return score; } void Circuit::ls_init_circuit(const std::unordered_set &faults) { fault_falsified_cnt = faults.size(); stem_falsified_cnt = stems.size(); propagate_falsified_cnt = stems.size(); for(Gate* s : stems) { s->stem_cost = 1; stem_total_cost += s->stem_cost; s->propagate_cost = 1; propagate_total_cost += s->propagate_cost; } for(Fault* f : faults) { f->gate->fault_cost[f->type] = 1; fault_total_cost += f->gate->fault_cost[f->type]; } for(Gate* g : gates) { g->fault_satisfied[0] = 0; g->fault_satisfied[1] = 0; } for(Gate* s : stems) { s->value = rand() % 2; } for(int i=stems.size()-1; i>=0; i--) { ls_update(stems[i]); } assert(is_valid_circuit()); } void Circuit::ls_init_data_structs() { propagate_total_cost = 0; propagate_falsified_cnt = 0; stem_total_cost = 0; stem_falsified_cnt = 0; fault_total_cost = 0; fault_falsified_cnt = 0; for(Gate* g : gates) { g->CC = 0; g->propagate = 0; g->propagate_cost = 0; g->propagate_satisfied = 0; g->stem_cost = 0; g->stem_satisified = 0; g->fault_satisfied[0] = g->fault_satisfied[1] = 0; g->fault_cost[0] = g->fault_cost[1] = 0; } } void Circuit::ls_block_recal(Gate* stem) { if(stem->cal_value() == stem->value && !stem->stem_satisified) { stem->stem_satisified = true; stem_total_cost -= stem->stem_cost; stem_falsified_cnt -= 1; } if(stem->cal_value() != stem->value && stem->stem_satisified) { stem->stem_satisified = false; stem_total_cost += stem->stem_cost; stem_falsified_cnt += 1; } // 当 po 的值变化 if(stem->po) { if(stem->fault_satisfied[stem->value]) { stem->fault_satisfied[stem->value] = false; fault_total_cost += stem->fault_cost[stem->value]; fault_falsified_cnt += 1; } if(!stem->fault_satisfied[!stem->value]) { stem->fault_satisfied[!stem->value] = true; fault_total_cost -= stem->fault_cost[!stem->value]; fault_falsified_cnt -= 1; } } std::queue q; std::unordered_map used; q.push(stem); while(!q.empty()) { Gate* g = q.front(); q.pop(); used[g] = false; for(Gate* out : g->outputs) { if(out->stem) continue; out->value = out->cal_value(); if(!used[out]) { used[out] = true; q.push(out); } } } assert(q.empty()); used.clear(); for(Gate* stem : stem->suc_stems) { q.push(stem); if(stem->cal_value() == stem->value && !stem->stem_satisified) { stem->stem_satisified = true; stem_total_cost -= stem->stem_cost; stem_falsified_cnt -= 1; } if(stem->cal_value() != stem->value && stem->stem_satisified) { stem->stem_satisified = false; stem_total_cost += stem->stem_cost; stem_falsified_cnt += 1; } } while(!q.empty()) { Gate *g = q.front(); q.pop(); used[g] = false; bool right_value = (g->cal_value() == g->value); for(Gate* in : g->inputs) { in->value = !in->value; bool input_detected = (g->cal_value() != g->value); in->value = !in->value; bool sa0 = right_value && input_detected && g->fault_satisfied[!g->value] && in->value; bool sa1 = right_value && input_detected && g->fault_satisfied[!g->value] && !in->value; in->sa_by_out[g] = std::make_pair(sa0, sa1); bool new_sa[2]; new_sa[0] = new_sa[1] = 0; in->fault_satisfied[0] = in->fault_satisfied[1] = 0; for(Gate* out : in->outputs) { auto &p = in->sa_by_out[out]; new_sa[0] |= p.first; new_sa[1] |= p.second; } if(in->stem) { if(in->propagate_satisfied && (in->fault_satisfied[0] != new_sa[0] || in->fault_satisfied[1] != new_sa[1])) { in->propagate_satisfied = false; propagate_falsified_cnt++; propagate_total_cost += in->propagate_cost; } if(!in->propagate_satisfied && (in->fault_satisfied[0] == new_sa[0] && in->fault_satisfied[1] == new_sa[1])) { in->propagate_satisfied = true; propagate_falsified_cnt--; propagate_total_cost -= in->propagate_cost; } } else { if(!new_sa[0] != in->fault_satisfied[0]) { if(in->fault_satisfied[0]) { fault_total_cost += in->fault_cost[0]; fault_falsified_cnt += 1; } else { fault_total_cost -= in->fault_cost[0]; fault_falsified_cnt -= 1; } } if(!new_sa[1] != in->fault_satisfied[1]) { if(in->fault_satisfied[1]) { fault_total_cost += in->fault_cost[1]; fault_falsified_cnt += 1; } else { fault_total_cost -= in->fault_cost[1]; fault_falsified_cnt -= 1; } } in->fault_satisfied[0] = new_sa[0]; in->fault_satisfied[1] = new_sa[1]; if(!in->stem && !used[in]) { used[in] = true; q.push(in); } } } } }