private Hop FindSpliceHop(SortedSet <SegLink> segset, SegLink max, long joinTime, long delayDec) { long spliceTime = joinTime - delayDec - 1; var query = new SegLink() { pos = null, time = spliceTime + 1 }; var spliceSet = segset.GetViewBetween(query, max); Debug.Assert(spliceSet.Any()); var spliceLink = spliceSet.First(); Pipe spliceSeg = spliceLink.pos.Value; long segEndTime = spliceLink.time; long segDelay = spliceSeg.GetDelay(_a); long segStartTime = spliceLink.time - segDelay; Debug.Assert(segStartTime <= spliceTime); Debug.Assert(segEndTime > spliceTime); Hop spliceHop; if (segStartTime == spliceTime) { spliceHop = spliceSeg.GetSource(_a); } else { spliceHop = new InsertionHop(_a, spliceSeg, spliceTime - segStartTime, segEndTime - spliceTime); } return(spliceHop); }
private long ShortcutPath(Path path, long delayDec, out Path xpath) { var segset = new SortedSet <SegLink>(); var seglist = new LinkedList <Pipe>(); long time = 0; for (int i = 0; i < path.Segments.Length; i++) { Pipe seg = path.Segments[i]; time += seg.GetDelay(_a); var pos = seglist.AddLast(seg); segset.Add(new SegLink() { pos = pos, time = time }); } SegLink max = new SegLink() { pos = null, time = time + 1 }; SegLink minJoin = new SegLink() { pos = null, time = delayDec + 1 }; var joinset = segset.GetViewBetween(minJoin, max); Debug.Assert(joinset.Any()); Hop bestSpliceHop = null; Hop bestJoinHop = null; long bestCost = long.MaxValue; long bestJoinTime = -1; foreach (var seglink in joinset) { long joinTime = seglink.time; Pipe seg = seglink.pos.Value; Hop joinHop = seg.GetSink(_a); long joinCost = _a.Preds[joinHop.Node].Count(); if (joinCost < bestCost) { bestCost = joinCost; bestJoinHop = joinHop; bestJoinTime = joinTime; bestSpliceHop = FindSpliceHop(segset, max, joinTime, delayDec); } long segDelay = seg.GetDelay(_a); --joinTime; if (segDelay > 1 && joinTime > delayDec && bestCost > 1) { bestCost = 1; var insHop = new InsertionHop(_a, seg, segDelay - 1, 1); bestJoinHop = insHop; bestJoinTime = joinTime; var left = seglist.AddBefore(seglink.pos, insHop.LeftPipe); var right = seglist.AddAfter(seglink.pos, insHop.RightPipe); seglist.Remove(seglink.pos); segset.Remove(seglink); var leftLink = new SegLink() { pos = left, time = seglink.time - 1 }; segset.Add(leftLink); var rightLink = new SegLink() { pos = right, time = seglink.time }; segset.Add(rightLink); bestSpliceHop = FindSpliceHop(segset, max, joinTime, delayDec); break; } } long bestSpliceTime = bestJoinTime - delayDec - 1; var newSegments = new List <Pipe>(); var wormhole = new InsertionPipe(bestSpliceHop, bestJoinHop, 1); time = 0; var curpos = seglist.First; while (curpos != null) { Pipe seg = curpos.Value; long nextTime = time + seg.GetDelay(_a); if (nextTime <= bestSpliceTime || time >= bestJoinTime) { newSegments.Add(seg); } else if (time == bestSpliceTime) { newSegments.Add(wormhole); } else if (time < bestSpliceTime && nextTime > bestSpliceTime) { var joinHop = (InsertionHop)bestSpliceHop; newSegments.Add(joinHop.LeftPipe); newSegments.Add(wormhole); } time = nextTime; curpos = curpos.Next; } xpath = new Path(_a, newSegments.ToArray()); return(bestCost + 1); }