MODULE GDHeurCreator; IMPORT Random, Wr, Thread, FileRd, Rd, Text, OSError; FROM Stdio IMPORT stdin, stderr; IMPORT GDGraph AS Graph; IMPORT GDHeurX, GDHeurY, GDHeurDir; IMPORT GDDrawing AS Dwg; IMPORT GDLayeredDrawing AS LDwg; IMPORT GDHeuristicTools AS HTools; FROM GDGraph IMPORT Dir, Slot, NoNode; FROM GDDrawing IMPORT BaseNode; FROM GDGeometry IMPORT Point, Points, LONG, NAT, BOOL; <* FATAL Thread.Alerted, Wr.Failure *> PROCEDURE WiseRandom( G: Graph.T; <*UNUSED*> dr: LDwg.T; rnd: Random.T; <*UNUSED*> inertia: LONG; <*UNUSED*> count: NAT; <*UNUSED*> name: TEXT; ): LDwg.T = BEGIN WITH nBaseV = G.nV, pp = ChoosePositions(G, rnd)^, dr = NEW(Dwg.T).init(G, injective := TRUE), dir = 2*rnd.integer(0,1) - 1 DO (* Assign Y coordinates: *) dr.moveAllNodes(pp); (* Now add polylines representing the edges of "G". *) FOR u := 0 TO nBaseV-1 DO FOR ku := 0 TO G.degree(u,+dir)-1 DO WITH v = G.nbor(u,+dir,ku), kv = G.findSlot(v,-dir,u) DO (* Wr.PutText(stderr, "join " & FISI(u,+dir,ku) & " - " & FISI(v,-dir,kv) & "\n"); *) <* ASSERT (dr.D.nbor(u,+dir,ku) = NoNode) = (dr.D.nbor(v,-dir,kv) = NoNode) *> HTools.WiseAddPolyLine(dr, dir, u, ku, v, kv, rnd); END END END; RETURN dr END END WiseRandom; PROCEDURE ChoosePositions(G: Graph.T; rnd: Random.T): REF Points = (* Returns a vector "pos[u]" with suggested positions for the base nodes "[0..G.nV-1]". *) BEGIN WITH posR = NEW(REF Points, G.nV), pos = posR^ DO HTools.ChooseYCoords(G, pos, rnd); HTools.ChooseXCoords(G, pos, rnd); RETURN posR END END ChoosePositions; PROCEDURE FastRandom( G: Graph.T; dr: LDwg.T; rnd: Random.T; <*UNUSED*> inertia: LONG; <*UNUSED*> count: NAT; <*UNUSED*> name: TEXT; ): LDwg.T = PROCEDURE LazyAddPoly(dr: LDwg.T; dir: Dir; u: BaseNode; ku: Slot; v: BaseNode; kv: Slot) = BEGIN HTools.LazyAddPolyLine(dr, dir, u, ku, v, kv, rnd) END LazyAddPoly; BEGIN <* ASSERT dr = NIL *> RETURN GenRandom(G, rnd, LazyAddPoly) END FastRandom; PROCEDURE NewRandom( G: Graph.T; <*UNUSED*> dr: LDwg.T; rnd: Random.T; <*UNUSED*> inertia: LONG; <*UNUSED*> count: NAT; <*UNUSED*> name: TEXT; ): LDwg.T = PROCEDURE AddPoly(dr: LDwg.T; dir: Dir; u: BaseNode; ku: Slot; v: BaseNode; kv: Slot) = BEGIN HTools.FancyAddPolyLine(dr, dir, u, ku, v, kv, rnd) END AddPoly; BEGIN RETURN GenRandom(G, rnd, AddPoly) END NewRandom; PROCEDURE GenRandom( G: Graph.T; rnd: Random.T; addPolyLine: LDwg.AddPolyLineProc; ): LDwg.T = BEGIN WITH nV = G.nV, uu = HTools.RandomPerm(nV, rnd)^, yy = HTools.RandomPerm(nV, rnd)^, pp = NEW(REF Points, nV)^, dc = NEW(LDwg.T).init(G, injective := TRUE), dir = 2*rnd.integer(0,1) - 1 DO (* Randomize the layers: *) FOR k := 0 TO nV-1 DO pp[k] := Point{0,yy[k]} END; dc.moveNodes(uu, pp); (* Now add polylines representing the edges of "G". *) FOR k := 0 TO nV-1 DO WITH u = uu[k] DO FOR ku := 0 TO G.degree(u,+dir)-1 DO WITH v = G.nbor(u,+dir,ku), kv = G.findSlot(v,-dir,u) DO addPolyLine(dc, dir, u, ku, v, kv) END END END END; RETURN dc END END GenRandom; PROCEDURE SmartRandom( G: Graph.T; <*UNUSED*> dr: LDwg.T; rnd: Random.T; inertia: LONG; count: NAT; <*UNUSED*> name: TEXT; ): LDwg.T = VAR dc: LDwg.T := NewRandom(G, NIL, rnd, inertia, 1, ""); dt: LDwg.T; doAdjustY: NAT; yChanged: BOOL; BEGIN Wr.PutText(stderr, "SmartRandom = ("); doAdjustY := count; yChanged := TRUE; WHILE doAdjustY > 0 AND yChanged DO yChanged := FALSE; Wr.PutText(stderr, "Y"); CASE rnd.integer(0,3) OF | 0 => Wr.PutText(stderr, "fl"); dt := GDHeurY.AdjustYFlip (G, dc, rnd, inertia, 1, ""); | 1 => Wr.PutText(stderr, "pk"); dt := GDHeurY.AdjustYPackOt(G, dc, rnd, inertia, 1, ""); | 2 => Wr.PutText(stderr, "mn"); dt := GDHeurY.AdjustYMean (G, dc, rnd, inertia, 1, ""); | 3 => Wr.PutText(stderr, "md"); dt := GDHeurY.AdjustYMedian(G, dc, rnd, inertia, 1, ""); ELSE <* ASSERT FALSE *> END; IF dt # NIL THEN dc := dt; yChanged := TRUE END; DEC(doAdjustY); Wr.PutText(stderr, "E"); WITH df = GDHeurDir.FixEDirs(G, dc, rnd, 0.0d0, 2, "") DO IF df # NIL THEN dc := df; yChanged := TRUE END END; Wr.PutText(stderr, "X"); WITH df = GDHeurX.AdjustXDn(G, dc, rnd, inertia, 1, "") DO IF df # NIL THEN dc := df END END; WITH df = GDHeurX.AdjustXUp(G, dc, rnd, inertia, 1, "") DO IF df # NIL THEN dc := df END END; WITH df = GDHeurX.AdjustXOt(G, dc, rnd, inertia, 2, "") DO IF df # NIL THEN dc := df END END; END; Wr.PutText(stderr, ")\n"); RETURN dc END SmartRandom; PROCEDURE ReadFile( G: Graph.T; <*UNUSED*> dr: LDwg.T; <*UNUSED*> rnd: Random.T; <*UNUSED*> inertia: LONG; <*UNUSED*> count: NAT; name: TEXT; ): LDwg.T = BEGIN WITH rd = OpenRead(name), dc = Dwg.Read(rd, allocJoints := G.nV) DO IF NOT Graph.Identical(G, dc.G) THEN Wr.PutText(stderr, "** drawing does not correspond to base graph\n"); <* ASSERT FALSE *> END; WITH pos = SUBARRAY(dc.pos^, 0, dc.D.nV) DO LDwg.VerifyPolylineMonotonicity(dc.D, dc.G.nV, pos) END; (* No use keeping multiple copies of the base graph: *) dc.G := G; RETURN dc END END ReadFile; PROCEDURE OpenRead(name: TEXT): Rd.T = (* Opens file "name" for reading, bombs out on errors. *) BEGIN IF Text.Equal(name, "-") THEN RETURN stdin ELSE TRY RETURN FileRd.Open(name) EXCEPT | OSError.E => Wr.PutText(stderr, "** could not open \"" & name & "\"\n"); <* ASSERT FALSE *> END END END OpenRead; BEGIN END GDHeurCreator. (* Last edited on 2000-01-12 18:28:48 by stolfi *)