List <SidetrackEdge> GetPaths(ViterbiNode eos, int maxCount, int costSlack) { var result = new List <SidetrackEdge>(); result.Add(null); PathCosts.Add(BaseCost); var sidetrackHeap = new PriorityQueue <SidetrackEdge>(); var sideTrackEdge = Sidetracks[eos]; while (sideTrackEdge != null) { sidetrackHeap.Add(sideTrackEdge); sideTrackEdge = sideTrackEdge.NextOption; } for (var i = 1; i < maxCount; i++) { if (sidetrackHeap.Count == 0) { break; } sideTrackEdge = sidetrackHeap.Dequeue(); if (sideTrackEdge.Cost > costSlack) { break; } result.Add(sideTrackEdge); PathCosts.Add(BaseCost + sideTrackEdge.Cost); var nextSidetrack = Sidetracks[sideTrackEdge.Tail]; while (nextSidetrack != null) { var next = new SidetrackEdge(nextSidetrack.Cost, nextSidetrack.Tail, nextSidetrack.Head); next.Parent = sideTrackEdge; sidetrackHeap.Add(next); nextSidetrack = nextSidetrack.NextOption; } } return(result); }
/// <summary> /// 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. /// </summary> /// <param name="lattice">an instance of ViterbiLattice prosecced by a ViterbiSearcher</param> /// <param name="maxCount">the maximum number of results</param> /// <param name="costSlack">the maximum cost slack of a path</param> /// <returns>the shortest paths and their costs</returns> public MultiSearchResult GetShortestPaths(ViterbiLattice lattice, int maxCount, int costSlack) { PathCosts.Clear(); Sidetracks.Clear(); var multiSearchResult = new MultiSearchResult(); BuildSidetracks(lattice); var eos = lattice.EndIndexArr[0][0]; BaseCost = eos.PathCost; var paths = GetPaths(eos, maxCount, costSlack); foreach (var(path, cost) in paths.Zip(Enumerable.Range(0, paths.Count), (p, i) => Tuple.Create(p, PathCosts[i]))) { var nodes = GeneratePath(eos, path); multiSearchResult.Add(nodes, cost); } return(multiSearchResult); }