// Adds a forget bag before any introduce public void ForgetBeforeIntroduce(TDNode parent) { IEnumerable <TDNode> children = Adj.Where((n) => n != parent); if (children.Count() == 1) { TDNode child = children.First(); IEnumerable <Vertex> toForget = child.Bag.Where((v) => !this.BagContains(v)); IEnumerable <Vertex> toIntroduce = this.Bag.Where((v) => !child.BagContains(v)); if (toForget.Any() && toIntroduce.Any()) { TDNode newNode = new TDNode(0, ParentDecomposition, VertexByColor.Length); newNode.Bag = child.Bag.Where((v) => this.BagContains(v)).ToArray(); foreach (Vertex v in newNode.Bag) { newNode.VertexByColor[v.Color] = v; } this.Adj.Remove(child); this.Adj.Add(newNode); child.Adj.Remove(this); child.Adj.Add(newNode); newNode.Adj.Add(child); newNode.Adj.Add(this); ParentDecomposition.Nodes.Add(newNode); newNode.ForgetBeforeIntroduce(this); return; } child.ForgetBeforeIntroduce(this); return; } foreach (TDNode child in children) { child.ForgetBeforeIntroduce(this); } }
// Sets the node to pick as the root that results in the lowest cost. Randomly tries a small number of candidates if the decomposition is large. public void FindOptimalRoot() { List <TDNode> todo = new List <TDNode>(Nodes.Where((n) => n.Bag.Any((v) => v.IsTerminal))); int t = 0; while (t < 1000000 && todo.Count > 0) { int p = Program.r.Next(todo.Count); TDNode n = todo[p]; todo[p] = todo[todo.Count - 1]; todo.RemoveAt(todo.Count - 1); double cost = n.CalculateCost(); if (cost < EstimatedCost) { EstimatedCost = cost; Root = n; } t += Nodes.Count; } Root.CalculateCost(); foreach (TDNode n in Nodes) { n.SetBagsFinal(); } Root.PreJoinForget(null); Root.DeconstructJoins(null); Root.ForgetBeforeIntroduce(null); Root.IndexVertices(null); Root.FillSubtree(null); SetupEdges(); }