//routeSpanTree.bcpl
// Cheap wire router that sets up a pretty good (at worst 2x optimum)
// permutation for the heuristic router.
//last edited by McCreight, July 2, 1981 3:37 PM
get "route.defs"
let GenerateGoodPerm() be
[ let BUSpanDest = Allocate(swapZone, n+2)
MakeMinSpanTree(BUSpanDest)
let Root = ReRoot(BUSpanDest)
let TDSpanSons = Allocate(swapZone, n+2)
let TDSpanBros = Allocate(swapZone, n+2)
ReRepresent(BUSpanDest, TDSpanSons, TDSpanBros)
Free(swapZone, BUSpanDest)
TreeWalk(Root, TDSpanSons, TDSpanBros, Perm)
Free(swapZone, TDSpanSons)
Free(swapZone, TDSpanBros)
CycleToRemoveLongest(Perm)
]
and MakeMinSpanTree(BUSpanDest) be
[ let InCluster = Allocate(swapZone, n+2)
let NearestEltInCluster = Allocate(swapZone, n+2)
let DistToCluster = Allocate(swapZone, n+2)
let NearestOutsideElt = 0
let ShortestDistToCluster = nil
for i=1 to n do
[ InCluster!i = (i eq 1)
if InCluster!i then
[ BUSpanDest!i = 0
loop
]
NearestEltInCluster!i = 1
DistToCluster!i = ArcLength(1, i)
if (NearestOutsideElt eq 0) %
(DistToCluster!i ls ShortestDistToCluster)
then
[ NearestOutsideElt = i
ShortestDistToCluster = DistToCluster!i
]
]
while NearestOutsideElt ne 0 do
[ BUSpanDest!NearestOutsideElt = NearestEltInCluster!NearestOutsideElt
InCluster!NearestOutsideElt = true
let NewClusterElt = NearestOutsideElt
NearestOutsideElt = 0
for i=1 to n do
[ if InCluster!i then loop
let DistToNewClusterElt = ArcLength(i, NewClusterElt)
if DistToNewClusterElt ls DistToCluster!i then
[ DistToCluster!i = DistToNewClusterElt
NearestEltInCluster!i = NewClusterElt
]
if (NearestOutsideElt eq 0) %
(DistToCluster!i ls ShortestDistToCluster)
then
[ NearestOutsideElt = i
ShortestDistToCluster = DistToCluster!i
]
]
]
Free(swapZone, InCluster)
Free(swapZone, NearestEltInCluster)
Free(swapZone, DistToCluster)
]
and ReRoot(BUDest) = valof
[ let Root = 1// re-root the spanning tree at a unary node
let Into = Allocate(swapZone, n+2)
unless forceFirstNodeToEnd do
[ Zero(Into+1, n)
for i=1 to n do
Into!(BUDest!i)=Into!(BUDest!i)+1
for i=1 to n do
if Into!i eq 0 then
[ Root = i
break
]
]
let Father = Into
let CurNode = Root
let CurAlt = 0
while BUDest!CurNode ne 0 do
[ Father!CurAlt = CurNode
CurAlt = CurAlt+1
CurNode = BUDest!CurNode
]
while CurAlt gr 0 do
[ CurAlt = CurAlt-1
BUDest!CurNode = Father!CurAlt
CurNode = Father!CurAlt
]
Free(swapZone, Father)
BUDest!Root = 0
resultis Root
]
and ReRepresent(BUDest, TDSons, TDBros) be
[ Zero(TDSons+1, n)
Zero(TDBros+1, n)
for i=1 to n do
[ let Father = BUDest!i
if Father eq 0 then loop// this is the root
TDBros!i = TDSons!Father
TDSons!Father = i
]
]
and TreeWalk(Root, TDSons, TDBros, Perm) be
[ let BroStack = Allocate(swapZone, n+2)
let Depth = 0
let NodesInPerm = 0
while Depth ge 0 do
[ NodesInPerm = NodesInPerm+1
Perm!NodesInPerm = Root
let Son = TDSons!Root
if Son ne 0 then
[ BroStack!Depth = TDBros!Root
if BroStack!Depth ne 0 then Depth = Depth+1
Root = Son
loop
]
Root = TDBros!Root
if Root ne 0 then loop
Depth = Depth-1
Root = BroStack!Depth
]
Free(swapZone, BroStack)
]
and CycleToRemoveLongest(Perm) be
[ let NewPerm = Allocate(swapZone, n+2)
let LongestArcPos = nil
let LongestArcLen = -1
test forceFirstNodeToEnd
ifnot[ for i=1 to n do
[ let ThisArcLen = ArcLength(Perm!i,
Perm!((i rem n)+1))
if ThisArcLen gr LongestArcLen then
[ LongestArcLen = ThisArcLen
LongestArcPos = i
]
]
MoveBlock(lv (NewPerm!1), lv (Perm!(LongestArcPos+1)),
n-LongestArcPos)
MoveBlock(lv (NewPerm!((n-LongestArcPos)+1)), lv (Perm!1),
LongestArcPos)
MoveBlock(lv (Perm!1), lv (NewPerm!1), n)
]
ifso if ArcLength(Perm!1, Perm!2) gr
ArcLength(Perm!n, Perm!1) then // reverse Perm!2..Perm!n
for i=1 to (n-1)/2 do
[ let T = Perm!(i+1)
Perm!(i+1) = Perm!(n+1-i)
Perm!(n+1-i) = T
]
Free(swapZone, NewPerm)
]