private static ZDDNode CheckTerminal(ZDDNode n_hat, int i, int x, State state) { Edge edge = state.graph.GetEdgeList()[i - 1]; if(x == 1) { // 辺でつないだときに,それぞれの連結成分の要素数が4超え(フォーセルズ的に破綻)したら if(n_hat.compCount[n_hat.comp[edge.src]] + n_hat.compCount[n_hat.comp[edge.dest]] > 4) { // 同じ連結成分ならセーフ if(n_hat.comp[edge.src] != n_hat.comp[edge.dest]) { return ZDDNode.ZeroTerminal; } } if(n_hat.mate[edge.src] != 0 || n_hat.mate[edge.dest] != 0) { int src = n_hat.mate[edge.src]; int dest = n_hat.mate[edge.dest]; if(src == 0) { src = edge.src; } if(dest == 0) { dest = edge.dest; } foreach(Edge ed in state.graph.GetEdgeList()) { if(ed.compare(src, dest)) { return ZDDNode.ZeroTerminal; } } } } else { // 四角のブロックはループさせる if(n_hat.comp[edge.src] == n_hat.comp[edge.dest]) { return ZDDNode.ZeroTerminal; } } ZDDNode n_prime = n_hat.MakeCopy(); UpdateInfo(n_prime, i, x, state); int[] src_dest = new int[] { edge.src, edge.dest }; bool check = false; // フロンティアに関して foreach(int u in src_dest) { // フロンティアを抜ける if(!state.F[i].Contains(u)) { if(n_prime.compCount[n_prime.comp[u]] < 4) { check = false; foreach(int f in state.F[i]) { if(n_prime.comp[f] == n_prime.comp[u]) { check = true; } } if(!check) { return ZDDNode.ZeroTerminal; } } } } // 最後の辺まで処理を終えたなら if(i == state.graph.GetEdgeList().Count) { return ZDDNode.OneTerminal; } // 0終端か1終端かまだ判定がつかない中継ノード return null; }
public ZDDNode MakeCopy() { ZDDNode node = new ZDDNode(); node.deg = (int[])deg.Clone(); node.comp = (int[])comp.Clone(); node.compCount = (int[])compCount.Clone(); node.mate = (int[])mate.Clone(); return node; }
public void SetChild(ZDDNode node, int child_num) { if(child_num == 0) { zero_child = node; } else { one_child = node; } }
public static ZDDNode CreateRootNode(int number_of_vertices) { ZDDNode node = new ZDDNode(); node.SetNextId(); node.deg = new int[number_of_vertices + 1]; node.comp = new int[number_of_vertices + 1]; node.compCount = new int[number_of_vertices + 1]; node.mate = new int[number_of_vertices + 1]; for(int i = 1; i <= number_of_vertices; ++i) { node.deg[i] = 0; node.comp[i] = i; node.compCount[i] = 1; node.mate[i] = 0; } return node; }
static ZDDNode() // static コンストラクタ。ZDDNode 使用開始直前に呼び出される { ZeroTerminal = new ZDDNode(); OneTerminal = new ZDDNode(); ZeroTerminal.id_ = 0; OneTerminal.id_ = 1; }
private static bool IsEquivalent(ZDDNode node1, ZDDNode node2, int i, State state) { foreach(int v in state.F[i]) // フロンティア上の頂点についてのみ比較 { if(node1.deg[v] != node2.deg[v]) { return false; } if(node1.comp[v] != node2.comp[v]) { return false; } } return true; }
private static ZDDNode Find(ZDDNode n_prime, List<ZDDNode> N_i, int i, State state) { foreach(ZDDNode n_primeprime in N_i) { if(IsEquivalent(n_prime, n_primeprime, i, state)) { return n_primeprime; } } return null; }
private static void UpdateInfo(ZDDNode n_hat, int i, int x, State state) { Edge edge = state.graph.GetEdgeList()[i - 1]; int[] src_dest = new int[] { edge.src, edge.dest }; // 初期化? //foreach(int u in src_dest) { // if(!state.F[i - 1].Contains(u)) { // n_hat.deg[u] = 0; // n_hat.comp[u] = u; // n_hat.compCount[u] = 1; // } //} if(x == 1) { // 次数の増加 ++n_hat.deg[edge.src]; ++n_hat.deg[edge.dest]; // 連結成分の変更 int c_min = Math.Min(n_hat.comp[edge.src], n_hat.comp[edge.dest]); int c_max = Math.Max(n_hat.comp[edge.src], n_hat.comp[edge.dest]); if(c_min != c_max) { n_hat.compCount[c_min] += n_hat.compCount[c_max]; foreach(int u in state.F[i]) { //for(int u = 1; u <= state.t; ++u) { if(n_hat.comp[u] == c_max) { n_hat.comp[u] = c_min; //n_hat.compCount[c_min]++; } } } // mate配列の更新 if(n_hat.mate[edge.dest] == 0) { if(n_hat.mate[edge.src] == 0) { n_hat.mate[edge.dest] = edge.src; } else { n_hat.mate[edge.dest] = n_hat.mate[edge.src]; } } } }