/** * Find the best paths with cost at most OPT + costSlack, where OPT is the optimal solution. At most maxCount paths will be returned. The paths are ordered by cost in ascending order. * * @param lattice the result of a build method * @param maxCount the maximum number of paths to find * @param costSlack the maximum cost slack of a path * @return MultiSearchResult containing the shortest paths and their costs */ public MultiSearchResult SearchMultiple(ViterbiLattice lattice, int maxCount, int costSlack) { CalculatePathCosts(lattice); MultiSearchResult result = multiSearcher.GetShortestPaths(lattice, maxCount, costSlack); return(result); }
private List <MergeBuilder> MergeStep(List <MergeBuilder> builders, List <MultiSearchResult> results, int currentIndex) { MultiSearchResult nextResult = results[currentIndex]; PriorityQueue <MergePair> pairHeap = new PriorityQueue <MergePair>(); List <MergeBuilder> ret = new List <MultiSearchMerger.MergeBuilder>(); if ((builders.Count == 0) || (nextResult.Count == 0)) { return(ret); } pairHeap.Add(new MergePair(0, 0, builders[0].Cost + nextResult.GetCost(0))); HashSet <int> visited = new HashSet <int>(); while (ret.Count < maxCount && pairHeap.Count > 0) { MergePair top = pairHeap.Poll(); if (GetCostLowerBound(top.Cost, currentIndex) - baseCost > costSlack) { break; } int i = top.LeftIndex; int j = top.RightIndex; MergeBuilder nextBuilder = new MergeBuilder(results, builders[i].Indices); nextBuilder.Add(j); ret.Add(nextBuilder); if (i + 1 < builders.Count) { MergePair newMergePair = new MergePair(i + 1, j, builders[i + 1].Cost + nextResult.GetCost(j)); int positionValue = GetPositionValue(i + 1, j); if (!visited.Contains(positionValue)) { pairHeap.Add(newMergePair); visited.Add(positionValue); } } if (j + 1 < nextResult.Count) { MergePair newMergePair = new MergePair(i, j + 1, builders[i].Cost + nextResult.GetCost(j + 1)); int positionValue = GetPositionValue(i, j + 1); if (!visited.Contains(positionValue)) { pairHeap.Add(newMergePair); visited.Add(positionValue); } } } return(ret); }
public MultiSearchResult Merge(List <MultiSearchResult> results) { if (results.Count == 0) { return(new MultiSearchResult()); } suffixCostLowerBounds = new List <int>(); for (int i = 0; i < results.Count; i++) { suffixCostLowerBounds.Add(0); } suffixCostLowerBounds[suffixCostLowerBounds.Count - 1] = results[results.Count - 1].GetCost(0); for (int i = results.Count - 2; i >= 0; i--) { suffixCostLowerBounds[i] = results[i].GetCost(0) + suffixCostLowerBounds[i + 1]; } baseCost = suffixCostLowerBounds[0]; MultiSearchResult ret = new MultiSearchResult(); List <MergeBuilder> builders = new List <MultiSearchMerger.MergeBuilder>(); for (int i = 0; i < results[0].Count; i++) { if (GetCostLowerBound(results[0].GetCost(i), 0) - baseCost > costSlack || i == maxCount) { break; } MergeBuilder newBuilder = new MergeBuilder(results); newBuilder.Add(i); builders.Add(newBuilder); } for (int i = 1; i < results.Count; i++) { builders = MergeStep(builders, results, i); } foreach (MergeBuilder builder in builders) { ret.Add(builder.BuildList(), builder.Cost); } return(ret); }
/** * Get up to maxCount shortest paths with cost at most OPT + costSlack, where OPT is the optimal solution. The results are ordered in ascending order by cost. * * @param lattice an instance of ViterbiLattice prosecced by a ViterbiSearcher * @param maxCount the maximum number of results * @param costSlack the maximum cost slack of a path * @return the shortest paths and their costs */ public MultiSearchResult GetShortestPaths(ViterbiLattice lattice, int maxCount, int costSlack) { pathCosts = new List <int>(); sidetracks = new Dictionary <ViterbiNode, MultiSearcher.SidetrackEdge>(); MultiSearchResult multiSearchResult = new MultiSearchResult(); BuildSidetracks(lattice); ViterbiNode eos = lattice.EndIndexArr[0][0]; baseCost = eos.PathCost; List <SidetrackEdge> paths = GetPaths(eos, maxCount, costSlack); int i = 0; foreach (SidetrackEdge path in paths) { LinkedList <ViterbiNode> nodes = GeneratePath(eos, path); multiSearchResult.Add(nodes, pathCosts[i]); i += 1; } return(multiSearchResult); }