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); }