public T Compute <T>(IDPAlgorithm <T> algorithm, TDNode parent, Dictionary <Tuple <TDNode, TDNode>, T> lookup) { T result; if (lookup.TryGetValue(Tuple.Create(this, parent), out result)) { return(result); } IEnumerable <TDNode> children = Adj.Where((n) => n != parent); if (!children.Any()) { result = algorithm.Introduce(this, Bag, algorithm.Leaf(ParentDecomposition.Width)); } else { TDNode first = children.First(); result = AdjustBag(algorithm, first, first.Compute(algorithm, this, lookup)); foreach (TDNode next in children.Skip(1)) { result = algorithm.Join(this, result, AdjustBag(algorithm, next, next.Compute(algorithm, this, lookup))); } } // Only cache if the result might be reused, prevents caching in all nodes of a long chain if (parent == null || parent.Adj.Count() > 2) { lookup[Tuple.Create(this, parent)] = result; } return(result); }
public T Compute <T>(IDPAlgorithm <T> algorithm, TDNode parent) { VertexSubset.ClearLookup(); // Note: through preprocessing, certain subtrees might have become empty. Do not consider. IEnumerable <TDNode> children = Adj.Where((n) => n != parent && n.Subtree.Any()); if (children.Count() == 0) { return(algorithm.IntroduceEdges(algorithm.Introduce(this, Bag, algorithm.Leaf(ParentDecomposition.Width)), introduceEdges)); } if (children.Count() == 1) { TDNode child = children.First(); Vertex[] toForget = child.Bag.Where((v) => !this.BagContains(v)).OrderBy((v) => v.Adj.Where((w) => BagContains(w.To)).Count()).Reverse().ToArray(); Vertex[] toIntroduce = this.Bag.Where((v) => !child.BagContains(v)).ToArray(); if (toIntroduce.Length > 0) { return(algorithm.IntroduceEdges(algorithm.Introduce(this, toIntroduce, child.Compute(algorithm, this)), introduceEdges)); } if (toForget.Length > 0) { return(algorithm.IntroduceEdges(algorithm.Forget(this, toForget, child.Compute(algorithm, this)), introduceEdges)); } // No change? return(algorithm.IntroduceEdges(child.Compute(algorithm, this), introduceEdges)); } if (children.Count() > 2) { throw new Exception("TD not preprocessed!"); } TDNode left = children.ElementAt(0), right = children.ElementAt(1); return(algorithm.IntroduceEdges(algorithm.Join(this, IntroduceIfNecessary(algorithm, left, left.Compute(algorithm, this)), IntroduceIfNecessary(algorithm, right, right.Compute(algorithm, this))), introduceEdges)); }