Exemple #1
0
		static void Main(string[] args) {
			Graph graph = new Graph();

			// グラフ(隣接リスト)を標準入力から読み込む
			string adj_text = "";
			string line = Console.ReadLine();
			while(line.Length > 0) {	// while(line != null)から変更
				adj_text += line + "\n";
				line = Console.ReadLine();
			}
			graph.ParseAdjListText(adj_text); //隣接行列つくる

			// グラフの特徴をもつクラス
			//引数は(Graphクラス, グラフの始点, グラフの終点)
			State state = new State(graph, 1, graph.GetNumberOfVertices());

			// 入力グラフの頂点の数と辺の数を出力
			Console.Error.WriteLine("# of vertices = " + graph.GetNumberOfVertices()
				+ ", # of edges = " + graph.GetEdgeList().Count);

			ZDD zdd = FrontierAlgorithm.Construct(state); // フロンティア法によるZDD(怪)構築

			// 作成されたZDDのノード数と解の数を出力
			//Console.Error.WriteLine("# of nodes of ZDD = " + zdd.GetNumberOfNodes());
			Console.Error.WriteLine("# of solutions = " + zdd.GetNumberOfSolutions());

			// ZDDを標準出力に出力
			///Console.Write(zdd.GetZDDString());
			System.Console.ReadLine();
		}
Exemple #2
0
		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;
		}
Exemple #3
0
		public static ZDD Construct(State state) {
			List<Edge> edge_list = state.graph.GetEdgeList();
			int[] ZeroOne = new int[] { 0, 1 };
			List<ZDDNode>[] N = new List<ZDDNode>[edge_list.Count + 2];
			N[1] = new List<ZDDNode>();
			N[1].Add(ZDDNode.CreateRootNode(state.graph.GetNumberOfVertices()));

			for(int i = 1; i <= edge_list.Count; ++i) {
				N[i + 1] = new List<ZDDNode>();

				foreach(ZDDNode n_hat in N[i]) {
					foreach(int x in ZeroOne) {
						ZDDNode n_prime = CheckTerminal(n_hat, i, x, state);
						if(n_prime == null) {
							n_prime = n_hat.MakeCopy();
							UpdateInfo(n_prime, i, x, state);
							ZDDNode n_primeprime = Find(n_prime, N[i + 1], i, state);
							if(n_primeprime != null) {
								n_prime = n_primeprime;
							}
							else {
								n_prime.SetNextId();
								N[i + 1].Add(n_prime);
							}
						}
						n_hat.SetChild(n_prime, x);
					}
				}
			}
			return new ZDD(N);
		}
Exemple #4
0
		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;
		}
Exemple #5
0
		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;
		}
Exemple #6
0
		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];
					}
				}
			}
		}