private static IEnumerable <InstantiationPath> AllDownPaths(InstantiationPath basePath, Node node, int nodesToGo) { if (nodesToGo <= 0 || !node.OutEdges.Any()) { return(Enumerable.Repeat(basePath, 1)); } return(node.OutEdges.SelectMany(e => { var copy = new InstantiationPath(basePath); copy.append((Instantiation)e.TargetNode.UserData); return AllDownPaths(copy, e.TargetNode, nodesToGo - 1); })); }
private InstantiationPath BestDownPath(Node node) { var curNode = node; var curPath = new InstantiationPath(); curPath.append((Instantiation)node.UserData); while (curNode.OutEdges.Any()) { curPath = AllDownPaths(curPath, curNode, pathSegmentSize).OrderByDescending(path => InstantiationPathScoreFunction(path, false, true)).First(); curNode = graph.FindNode(curPath.getInstantiations().Last().uniqueID); } return(curPath); }
private static InstantiationPath deepestPathStartingFrom(Instantiation instantiation) { var current = instantiation; var path = new InstantiationPath(current); while (current.DependantInstantiations.Count != 0) { var next = current.DependantInstantiations.First(inst => inst.DeepestSubpathDepth == current.DeepestSubpathDepth - 1); path.append(next); current = next; } return(path); }
/// <summary> /// Assigns a score to instantiation paths based on the predicted likelyhood that it conatins a matching loop. /// </summary> /// <returns>Higher values indicate a higher likelyhood of the path containing a matching loop.</returns> /// <remarks>All constants were determined experimentally.</remarks> private static double InstantiationPathScoreFunction(InstantiationPath instantiationPath, bool eliminatePrefix, bool eliminatePostfix) { //There may be some "outiers" before or after a matching loop. //We first identify quantifiers that occur at most outlierThreshold times as often as the most common quantifier in the path... var statistics = instantiationPath.Statistics(); var eliminationTreshhold = (statistics == null || !statistics.Any()) ? 1 : Math.Max(statistics.Max(dp => dp.Item2) * outlierThreshold, 1); var nonEliminatableQuantifiers = new HashSet <Tuple <Quantifier, Term, Term> >(statistics .Where(dp => dp.Item2 > eliminationTreshhold) .Select(dp => dp.Item1)); //...find the longest contigous subsequence that does not contain eliminatable quantifiers... var pathInstantiations = instantiationPath.getInstantiations(); var instantiations = pathInstantiations.Zip(pathInstantiations.Skip(1), (prev, next) => !next.bindingInfo.IsPatternMatch() ? Enumerable.Repeat(Tuple.Create <Quantifier, Term, Term>(next.Quant, null, null), 1) : next.bindingInfo.bindings.Where(kv => prev.concreteBody.isSubterm(kv.Value.Item2.id)) .Select(kv => Tuple.Create(next.Quant, next.bindingInfo.fullPattern, kv.Key))).ToArray(); var maxStartIndex = 0; var maxLength = 0; var lastMaxStartIndex = 0; var firstKept = nonEliminatableQuantifiers.Any(q => q.Item1 == pathInstantiations.First().Quant&& q.Item2 == pathInstantiations.First().bindingInfo.fullPattern); var curStartIndex = firstKept ? 0 : 1; var curLength = firstKept ? 1 : 0; for (var i = 0; i < instantiations.Count(); ++i) { if (instantiations[i].Any(q => nonEliminatableQuantifiers.Contains(q))) { ++curLength; } else { if (curLength > maxLength) { maxStartIndex = curStartIndex; lastMaxStartIndex = curStartIndex; maxLength = curLength; } else if (curLength == maxLength) { lastMaxStartIndex = curStartIndex; } curStartIndex = i + 2; curLength = 0; } } if (curLength > maxLength) { maxStartIndex = curStartIndex; lastMaxStartIndex = curStartIndex; maxLength = curLength; } else if (curLength == maxLength) { lastMaxStartIndex = curStartIndex; } //...and eliminate the prefix/postfix of that subsequence var remainingStart = eliminatePrefix ? maxStartIndex : 0; var remainingLength = (eliminatePostfix ? lastMaxStartIndex + maxLength : instantiations.Count()) - remainingStart; var remainingInstantiations = instantiationPath.getInstantiations().ToList().GetRange(remainingStart, remainingLength); if (remainingInstantiations.Count() == 0) { return(-1); } var remainingPath = new InstantiationPath(); foreach (var inst in remainingInstantiations) { remainingPath.append(inst); } /* We count the number of incoming edges (responsible instantiations that are not part of the path) and penalize them. * This ensures that we choose the best path. E.g. in the triangular case (A -> B, A -> C, B -> C) we want to choose A -> B -> C * and not A -> B which would have an incoming edge (B -> C). */ var numberIncomingEdges = 0; foreach (var inst in remainingInstantiations) { numberIncomingEdges += inst.ResponsibleInstantiations.Where(i => !instantiationPath.getInstantiations().Contains(i)).Count(); } /* the score is given by the number of remaining instantiations devided by the number of remaining quantifiers * which is an approximation for the number of repetitions of a matching loop occuring in that path. */ return((remainingPath.Length() - numberIncomingEdges * incomingEdgePenalizationFactor) / remainingPath.NumberOfDistinctQuantifierFingerprints()); }