LvlGraph: Speed up TMinXGraph. In StoreAsBest only update nodes that changed. This massively speeds up big graphs with several thousand (including hidden) nodes, were StoreAsBest did always copy all those nodes.

This commit is contained in:
Martin 2021-12-22 11:39:48 +01:00
parent 42d6e0bc85
commit fcd8b1721b

View File

@ -738,6 +738,7 @@ type
Graph: TMinXGraph; Graph: TMinXGraph;
Index: integer; Index: integer;
PrevSameSwitchPair, NextSameSwitchPair: TMinXPair; PrevSameSwitchPair, NextSameSwitchPair: TMinXPair;
NextChangedSinceBestStored: TMinXPair;
constructor Create(aLevel: TMinXLevel; aIndex: integer); constructor Create(aLevel: TMinXLevel; aIndex: integer);
destructor Destroy; override; destructor Destroy; override;
procedure UnbindFromSwitchList; procedure UnbindFromSwitchList;
@ -753,11 +754,13 @@ type
TMinXGraph = class TMinXGraph = class
private private
FGraphNodeToNode: TPointerToPointerTree; // TLvlGraphNode to TMinXNode FGraphNodeToNode: TPointerToPointerTree; // TLvlGraphNode to TMinXNode
PairsChangedSinceBestStored: TMinXPair;
procedure InitPairs; procedure InitPairs;
procedure UnbindPairs; procedure UnbindPairs;
procedure BindPairs; procedure BindPairs;
function ComputeCrossCount: integer; function ComputeCrossCount: integer;
procedure StoreAsBest(CheckIfBetter: boolean); procedure StoreAsBest(CheckIfBetter: boolean);
procedure StoreAsBest(APair: TMinXPair);
function ComputeHighestSwitchDiff(StartAtOld: boolean; IgnorePair: TMinXPair): integer; function ComputeHighestSwitchDiff(StartAtOld: boolean; IgnorePair: TMinXPair): integer;
public public
Graph: TLvlGraph; Graph: TLvlGraph;
@ -1735,9 +1738,17 @@ var
Level: TMinXLevel; Level: TMinXLevel;
n: Integer; n: Integer;
begin begin
if CheckIfBetter then begin // e.g. after Shuffly => a new full StoreAsBest is needed
PairsChangedSinceBestStored := TMinXPair(PtrUInt(-1));
end;
if CheckIfBetter and (BestCrossCount>=0) and (BestCrossCount<CrossCount) then if CheckIfBetter and (BestCrossCount>=0) and (BestCrossCount<CrossCount) then
exit; exit;
PairsChangedSinceBestStored := nil;
BestCrossCount:=CrossCount; BestCrossCount:=CrossCount;
for l:=0 to length(Pairs)-1 do
Pairs[l].NextChangedSinceBestStored := nil;
for l:=0 to length(Levels)-1 do begin for l:=0 to length(Levels)-1 do begin
Level:=Levels[l]; Level:=Levels[l];
for n:=0 to length(Level.Nodes)-1 do for n:=0 to length(Level.Nodes)-1 do
@ -1745,6 +1756,37 @@ begin
end; end;
end; end;
procedure TMinXGraph.StoreAsBest(APair: TMinXPair);
var
idx: Integer;
NextPair: TMinXPair;
begin
if PairsChangedSinceBestStored = TMinXPair(PtrUInt(-1)) then begin
StoreAsBest(True);
exit;
end;
if (BestCrossCount>=0) and (BestCrossCount<CrossCount) then begin
if APair.NextChangedSinceBestStored = nil then begin
APair.NextChangedSinceBestStored := PairsChangedSinceBestStored;
PairsChangedSinceBestStored := APair;
end;
exit;
end;
BestCrossCount:=CrossCount;
while APair <> nil do begin
with APair.Level do begin
idx := APair.Index;
BestNodes[idx]:=Nodes[idx].GraphNode;
inc(idx);
BestNodes[idx]:=Nodes[idx].GraphNode;
end;
NextPair := APair.NextChangedSinceBestStored;
APair.NextChangedSinceBestStored := nil;
APair := NextPair;
end;
end;
function TMinXGraph.ComputeHighestSwitchDiff(StartAtOld: boolean; function TMinXGraph.ComputeHighestSwitchDiff(StartAtOld: boolean;
IgnorePair: TMinXPair): integer; IgnorePair: TMinXPair): integer;
var var
@ -1955,7 +1997,7 @@ 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]);
StoreAsBest(true); StoreAsBest(Pair);
{$IFDEF CheckMinXGraph} {$IFDEF CheckMinXGraph}
ConsistencyCheck; ConsistencyCheck;