cody: lvlgraph: shuffle and apply best

git-svn-id: trunk@40420 -
This commit is contained in:
mattias 2013-02-26 18:22:53 +00:00
parent 7070a7dd26
commit 5f3d6729b0

View File

@ -232,7 +232,7 @@ type
end; end;
{$DEFINE CheckMinXGraph} {off $DEFINE CheckMinXGraph}
type type
TLvlGraph = class; TLvlGraph = class;
TLvlGraphEdge = class; TLvlGraphEdge = class;
@ -693,8 +693,10 @@ type
TMinXGraph = class TMinXGraph = class
private private
FGraphNodeToNode: TPointerToPointerTree; // TLvlGraphNode to TMinXNode FGraphNodeToNode: TPointerToPointerTree; // TLvlGraphNode to TMinXNode
procedure CreatePairs; procedure UnbindPairs;
procedure BindPairs;
function ComputeCrossCount: integer; function ComputeCrossCount: integer;
procedure StoreAsBest;
public public
Graph: TLvlGraph; Graph: TLvlGraph;
Levels: array of TMinXLevel; Levels: array of TMinXLevel;
@ -706,8 +708,10 @@ type
constructor Create(aGraph: TLvlGraph); constructor Create(aGraph: TLvlGraph);
destructor Destroy; override; destructor Destroy; override;
procedure InitSearch; procedure InitSearch;
procedure StoreAsBest;
function FindBestPair: TMinXPair; function FindBestPair: TMinXPair;
procedure SwitchCrossingPairs(MaxRun: int64; var Run: int64);
procedure Shuffle;
procedure SwitchAndShuffle(MaxSingleRun, MaxTotalRun: int64);
procedure SwitchPair(Pair: TMinXPair); procedure SwitchPair(Pair: TMinXPair);
procedure Apply; // reorder Graph nodes procedure Apply; // reorder Graph nodes
function GraphNodeToNode(GraphNode: TLvlGraphNode): TMinXNode; inline; function GraphNodeToNode(GraphNode: TLvlGraphNode): TMinXNode; inline;
@ -717,19 +721,15 @@ type
procedure LvlGraphMinimizeCrossings(Graph: TLvlGraph); procedure LvlGraphMinimizeCrossings(Graph: TLvlGraph);
var var
g: TMinXGraph; g: TMinXGraph;
Pair: TMinXPair; {%H-}Run: int64;
i: Integer;
begin begin
if (Graph.LevelCount<2) or (Graph.NodeCount<3) then exit; if (Graph.LevelCount<2) or (Graph.NodeCount<3) then exit;
g:=TMinXGraph.Create(Graph); g:=TMinXGraph.Create(Graph);
try try
g.InitSearch; g.InitSearch;
for i:=1 to 100 do begin Run:=0;
Pair:=g.FindBestPair; g.SwitchAndShuffle(Graph.NodeCount*Graph.NodeCount div 3,
if Pair=nil then break; Max(1000,Graph.NodeCount*Graph.NodeCount));
//debugln(['LvlGraphMinimizeCrossings ',Pair.AsString]);
g.SwitchPair(Pair);
end;
g.Apply; g.Apply;
finally finally
g.Free; g.Free;
@ -1043,9 +1043,7 @@ begin
end; end;
end; end;
CreatePairs; BindPairs;
CrossCount:=ComputeCrossCount;
{$IFDEF CheckMinXGraph} {$IFDEF CheckMinXGraph}
ConsistencyCheck; ConsistencyCheck;
@ -1067,37 +1065,52 @@ begin
inherited Destroy; inherited Destroy;
end; end;
procedure TMinXGraph.CreatePairs; procedure TMinXGraph.UnbindPairs;
var
i: Integer;
begin
for i:=0 to length(Pairs)-1 do
Pairs[i].UnbindFromSwitchList;
end;
procedure TMinXGraph.BindPairs;
var var
Cnt: Integer; Cnt: Integer;
i: Integer; i: Integer;
Level: TMinXLevel; Level: TMinXLevel;
n: Integer; n: Integer;
Pair: TMinXPair; Pair: TMinXPair;
Crossing, SwitchedCrossing: integer; First: Boolean;
begin begin
First:=length(Pairs)=0;
if First then begin
Cnt:=0;
for i:=0 to length(Levels)-1 do
Cnt+=Max(0,length(Levels[i].Nodes)-1);
SetLength(Pairs,Cnt);
end;
Cnt:=0; Cnt:=0;
for i:=0 to length(Levels)-1 do
Cnt+=Max(0,length(Levels[i].Nodes)-1);
SetLength(Pairs,Cnt);
Cnt:=0;
SameSwitchDiffPair0:=0;
for i:=0 to length(Levels)-1 do begin for i:=0 to length(Levels)-1 do begin
Level:=Levels[i]; Level:=Levels[i];
SetLength(Level.Pairs,length(Level.Nodes)-1); SetLength(Level.Pairs,length(Level.Nodes)-1);
for n:=0 to length(Level.Pairs)-1 do begin for n:=0 to length(Level.Pairs)-1 do begin
Pair:=TMinXPair.Create(Level,n); if First then begin
Pairs[Cnt]:=Pair; Pair:=TMinXPair.Create(Level,n);
Level.Pairs[n]:=Pair; Pairs[Cnt]:=Pair;
Pair.ComputeCrossingCount(Crossing,SwitchedCrossing); Level.Pairs[n]:=Pair;
Pair.FSwitchDiff:=SwitchedCrossing-Crossing; end else
SameSwitchDiffPair0:=Max(SameSwitchDiffPair0,Crossing+SwitchedCrossing); Pair:=Pairs[Cnt];
Pair.FSwitchDiff:=Pair.ComputeSwitchDiff;
Cnt+=1; Cnt+=1;
end; end;
end; end;
SetLength(SameSwitchDiffPairs,2*SameSwitchDiffPair0+1); if First then begin
SameSwitchDiffPair0:=Graph.NodeCount;
SetLength(SameSwitchDiffPairs,2*SameSwitchDiffPair0+1);
end;
for i:=0 to length(Pairs)-1 do for i:=0 to length(Pairs)-1 do
Pairs[i].BindToSwitchList; Pairs[i].BindToSwitchList;
CrossCount:=ComputeCrossCount;
end; end;
function TMinXGraph.ComputeCrossCount: integer; function TMinXGraph.ComputeCrossCount: integer;
@ -1135,8 +1148,7 @@ end;
procedure TMinXGraph.InitSearch; procedure TMinXGraph.InitSearch;
begin begin
BestCrossCount:=-1; StoreAsBest;
end; end;
procedure TMinXGraph.StoreAsBest; procedure TMinXGraph.StoreAsBest;
@ -1165,6 +1177,61 @@ begin
Result:=nil; Result:=nil;
end; end;
procedure TMinXGraph.SwitchCrossingPairs(MaxRun: int64; var Run: int64);
var
i: int64;
Pair: TMinXPair;
begin
for i:=1 to MaxRun do begin
Pair:=FindBestPair;
Run+=1;
if (Pair=nil) or (Pair.SwitchDiff=0) then exit;
SwitchPair(Pair);
end;
end;
procedure TMinXGraph.Shuffle;
var
l: Integer;
Level: TMinXLevel;
n1: Integer;
n2: Integer;
Node: TMinXNode;
begin
{$IFDEF CheckMinXGraph}
ConsistencyCheck;
{$ENDIF}
UnbindPairs;
for l:=0 to length(Levels)-1 do begin
Level:=Levels[l];
for n1:=0 to length(Level.Nodes)-1 do begin
n2:=Random(length(Level.Nodes));
if n1=n2 then continue;
Node:=Level.Nodes[n1];
Level.Nodes[n1]:=Level.Nodes[n2];
Level.Nodes[n2]:=Node;
Level.Nodes[n1].IndexInLevel:=n1;
Level.Nodes[n2].IndexInLevel:=n2;
end;
end;
BindPairs;
{$IFDEF CheckMinXGraph}
ConsistencyCheck;
{$ENDIF}
end;
procedure TMinXGraph.SwitchAndShuffle(MaxSingleRun, MaxTotalRun: int64);
var
Run: int64;
begin
Run:=1;
repeat
SwitchCrossingPairs(MaxSingleRun,Run);
if Run>MaxTotalRun then exit;
Shuffle;
until false;
end;
procedure TMinXGraph.SwitchPair(Pair: TMinXPair); procedure TMinXGraph.SwitchPair(Pair: TMinXPair);
procedure UpdateSwitchDiff(TargetOfNode1, TargetOfNode2: TMinXNode); procedure UpdateSwitchDiff(TargetOfNode1, TargetOfNode2: TMinXNode);
@ -1229,6 +1296,9 @@ begin
for j:=0 to length(Node2.InEdges)-1 do for j:=0 to length(Node2.InEdges)-1 do
UpdateSwitchDiff(Node1.InEdges[i],Node2.InEdges[j]); UpdateSwitchDiff(Node1.InEdges[i],Node2.InEdges[j]);
if (BestCrossCount<0) or (BestCrossCount>CrossCount) then
StoreAsBest;
{$IFDEF CheckMinXGraph} {$IFDEF CheckMinXGraph}
ConsistencyCheck; ConsistencyCheck;
{$ENDIF} {$ENDIF}
@ -1239,14 +1309,11 @@ var
i: Integer; i: Integer;
Level: TMinXLevel; Level: TMinXLevel;
j: Integer; j: Integer;
Node: TMinXNode;
begin begin
for i:=0 to length(Levels)-1 do begin for i:=0 to length(Levels)-1 do begin
Level:=Levels[i]; Level:=Levels[i];
for j:=0 to length(Level.Nodes)-1 do begin for j:=0 to length(Level.BestNodes)-1 do
Node:=Level.Nodes[j]; Level.BestNodes[j].IndexInLevel:=j;
Node.GraphNode.IndexInLevel:=Node.IndexInLevel;
end;
end; end;
end; end;