Data update
This commit is contained in:
parent
5150844a7d
commit
4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions
|
|
@ -1,52 +0,0 @@
|
|||
with Ada.Containers.Vectors; use Ada.Containers;
|
||||
|
||||
package Digraphs is
|
||||
|
||||
type Node_Idx_With_Null is new Natural;
|
||||
subtype Node_Index is Node_Idx_With_Null range 1 .. Node_Idx_With_Null'Last;
|
||||
-- a Node_Index is a number from 1, 2, 3, ... and the representative of a node
|
||||
|
||||
type Graph_Type is tagged private;
|
||||
|
||||
-- make sure Node is in Graph (possibly without connections)
|
||||
procedure Add_Node
|
||||
(Graph: in out Graph_Type'Class; Node: Node_Index);
|
||||
|
||||
-- insert an edge From->To into Graph; do nothing if already there
|
||||
procedure Add_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index);
|
||||
|
||||
-- get the largest Node_Index used in any Add_Node or Add_Connection op.
|
||||
-- iterate over all nodes of Graph: "for I in 1 .. Graph.Node_Count loop ..."
|
||||
function Node_Count(Graph: Graph_Type) return Node_Idx_With_Null;
|
||||
|
||||
-- remove an edge From->To from Fraph; do nothing if not there
|
||||
-- Graph.Node_Count is not changed
|
||||
procedure Del_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index);
|
||||
|
||||
-- check if an edge From->to exists in Graph
|
||||
function Connected
|
||||
(Graph: Graph_Type; From, To: Node_Index) return Boolean;
|
||||
|
||||
-- data structure to store a list of nodes
|
||||
package Node_Vec is new Vectors(Positive, Node_Index);
|
||||
|
||||
-- get a list of all nodes From->Somewhere in Graph
|
||||
function All_Connections
|
||||
(Graph: Graph_Type; From: Node_Index) return Node_Vec.Vector;
|
||||
|
||||
Graph_Is_Cyclic: exception;
|
||||
|
||||
-- a depth-first search to find a topological sorting of the nodes
|
||||
-- raises Graph_Is_Cyclic if no topological sorting is possible
|
||||
function Top_Sort
|
||||
(Graph: Graph_Type) return Node_Vec.Vector;
|
||||
|
||||
private
|
||||
|
||||
package Conn_Vec is new Vectors(Node_Index, Node_Vec.Vector, Node_Vec."=");
|
||||
|
||||
type Graph_Type is new Conn_Vec.Vector with null record;
|
||||
|
||||
end Digraphs;
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
package body Digraphs is
|
||||
|
||||
function Node_Count(Graph: Graph_Type) return Node_Idx_With_Null is
|
||||
begin
|
||||
return Node_Idx_With_Null(Graph.Length);
|
||||
end Node_Count;
|
||||
|
||||
procedure Add_Node(Graph: in out Graph_Type'Class; Node: Node_Index) is
|
||||
begin
|
||||
for I in Node_Index range Graph.Node_Count+1 .. Node loop
|
||||
Graph.Append(Node_Vec.Empty_Vector);
|
||||
end loop;
|
||||
end Add_Node;
|
||||
|
||||
procedure Add_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index) is
|
||||
begin
|
||||
Graph.Add_Node(Node_Index'Max(From, To));
|
||||
declare
|
||||
Connection_List: Node_Vec.Vector := Graph.Element(From);
|
||||
begin
|
||||
for I in Connection_List.First_Index .. Connection_List.Last_Index loop
|
||||
if Connection_List.Element(I) >= To then
|
||||
if Connection_List.Element(I) = To then
|
||||
return; -- if To is already there, don't add it a second time
|
||||
else -- I is the first index with Element(I)>To, insert To here
|
||||
Connection_List.Insert(Before => I, New_Item => To);
|
||||
Graph.Replace_Element(From, Connection_List);
|
||||
return;
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
-- there was no I with no Element(I) > To, so insert To at the end
|
||||
Connection_List.Append(To);
|
||||
Graph.Replace_Element(From, Connection_List);
|
||||
return;
|
||||
end;
|
||||
end Add_Connection;
|
||||
|
||||
procedure Del_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index) is
|
||||
Connection_List: Node_Vec.Vector := Graph.Element(From);
|
||||
begin
|
||||
for I in Connection_List.First_Index .. Connection_List.Last_Index loop
|
||||
if Connection_List.Element(I) = To then
|
||||
Connection_List.Delete(I);
|
||||
Graph.Replace_Element(From, Connection_List);
|
||||
return; -- we are done
|
||||
end if;
|
||||
end loop;
|
||||
end Del_Connection;
|
||||
|
||||
function Connected
|
||||
(Graph: Graph_Type; From, To: Node_Index) return Boolean is
|
||||
Connection_List: Node_Vec.Vector renames Graph.Element(From);
|
||||
begin
|
||||
for I in Connection_List.First_Index .. Connection_List.Last_Index loop
|
||||
if Connection_List.Element(I) = To then
|
||||
return True;
|
||||
end if;
|
||||
end loop;
|
||||
return False;
|
||||
end Connected;
|
||||
|
||||
function All_Connections
|
||||
(Graph: Graph_Type; From: Node_Index) return Node_Vec.Vector is
|
||||
begin
|
||||
return Graph.Element(From);
|
||||
end All_Connections;
|
||||
|
||||
function Top_Sort
|
||||
(Graph: Graph_Type) return Node_Vec.Vector is
|
||||
|
||||
Result: Node_Vec.Vector;
|
||||
Visited: array(1 .. Graph.Node_Count) of Boolean := (others => False);
|
||||
Active: array(1 .. Graph.Node_Count) of Boolean := (others => False);
|
||||
|
||||
procedure Visit(Node: Node_Index) is
|
||||
begin
|
||||
if not Visited(Node) then
|
||||
Visited(Node) := True;
|
||||
Active(Node) := True;
|
||||
declare
|
||||
Cons: Node_Vec.Vector := All_Connections(Graph, Node);
|
||||
begin
|
||||
for Idx in Cons.First_Index .. Cons.Last_Index loop
|
||||
Visit(Cons.Element(Idx));
|
||||
end loop;
|
||||
end;
|
||||
Active(Node) := False;
|
||||
Result.Append(Node);
|
||||
else
|
||||
if Active(Node) then
|
||||
raise Constraint_Error with "Graph is Cyclic";
|
||||
end if;
|
||||
end if;
|
||||
end Visit;
|
||||
|
||||
begin
|
||||
for Some_Node in Visited'Range loop
|
||||
Visit(Some_Node);
|
||||
end loop;
|
||||
return Result;
|
||||
end Top_Sort;
|
||||
|
||||
end Digraphs;
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
private with Ada.Containers.Indefinite_Vectors;
|
||||
|
||||
generic
|
||||
type Index_Type_With_Null is new Natural;
|
||||
package Set_Of_Names is
|
||||
subtype Index_Type is Index_Type_With_Null
|
||||
range 1 .. Index_Type_With_Null'Last;
|
||||
-- manage a set of strings;
|
||||
-- each string in the set is assigned a unique index of type Index_Type
|
||||
|
||||
type Set is tagged private;
|
||||
|
||||
-- inserts Name into Names; do nothing if already there;
|
||||
procedure Add(Names: in out Set; Name: String);
|
||||
|
||||
-- Same operation, additionally emiting Index=Names.Idx(Name)
|
||||
procedure Add(Names: in out Set; Name: String; Index: out Index_Type);
|
||||
|
||||
-- remove Name from Names; do nothing if not found
|
||||
-- the removal may change the index of other strings in Names
|
||||
procedure Sub(Names: in out Set; Name: String);
|
||||
|
||||
-- returns the unique index of Name in Set; or 0 if Name is not there
|
||||
function Idx(Names: Set; Name: String) return Index_Type_With_Null;
|
||||
|
||||
-- returns the unique name of Index;
|
||||
function Name(Names: Set; Index: Index_Type) return String;
|
||||
|
||||
-- first index, last index and total number of names in set
|
||||
-- to iterate over Names, use "for I in Names.Start .. Names.Stop loop ...
|
||||
function Start(Names: Set) return Index_Type;
|
||||
function Stop(Names: Set) return Index_Type_With_Null;
|
||||
function Size(Names: Set) return Index_Type_With_Null;
|
||||
|
||||
private
|
||||
|
||||
package Vecs is new Ada.Containers.Indefinite_Vectors
|
||||
(Index_Type => Index_Type, Element_Type => String);
|
||||
|
||||
type Set is new Vecs.Vector with null record;
|
||||
|
||||
end Set_Of_Names;
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
package body Set_Of_Names is
|
||||
|
||||
use type Ada.Containers.Count_Type, Vecs.Cursor;
|
||||
|
||||
function Start(Names: Set) return Index_Type is
|
||||
begin
|
||||
if Names.Length = 0 then
|
||||
return 1;
|
||||
else
|
||||
return Names.First_Index;
|
||||
end if;
|
||||
end Start;
|
||||
|
||||
function Stop(Names: Set) return Index_Type_With_Null is
|
||||
begin
|
||||
if Names.Length=0 then
|
||||
return 0;
|
||||
else
|
||||
return Names.Last_Index;
|
||||
end if;
|
||||
end Stop;
|
||||
|
||||
function Size(Names: Set) return Index_Type_With_Null is
|
||||
begin
|
||||
return Index_Type_With_Null(Names.Length);
|
||||
end Size;
|
||||
|
||||
procedure Add(Names: in out Set; Name: String; Index: out Index_Type) is
|
||||
I: Index_Type_With_Null := Names.Idx(Name);
|
||||
begin
|
||||
if I = 0 then -- Name is not yet in Set
|
||||
Names.Append(Name);
|
||||
Index := Names.Stop;
|
||||
else
|
||||
Index := I;
|
||||
end if;
|
||||
end Add;
|
||||
|
||||
procedure Add(Names: in out Set; Name: String) is
|
||||
I: Index_Type;
|
||||
begin
|
||||
Names.Add(Name, I);
|
||||
end Add;
|
||||
|
||||
procedure Sub(Names: in out Set; Name: String) is
|
||||
I: Index_Type_With_Null := Names.Idx(Name);
|
||||
begin
|
||||
if I /= 0 then -- Name is in set
|
||||
Names.Delete(I);
|
||||
end if;
|
||||
end Sub;
|
||||
|
||||
function Idx(Names: Set; Name: String) return Index_Type_With_Null is
|
||||
begin
|
||||
for I in Names.First_Index .. Names.Last_Index loop
|
||||
if Names.Element(I) = Name then
|
||||
return I;
|
||||
end if;
|
||||
end loop;
|
||||
return 0;
|
||||
end Idx;
|
||||
|
||||
function Name(Names: Set; Index: Index_Type) return String is
|
||||
begin
|
||||
return Names.Element(Index);
|
||||
end Name;
|
||||
|
||||
end Set_Of_Names;
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
with Ada.Text_IO, Digraphs, Set_Of_Names, Ada.Command_Line;
|
||||
|
||||
procedure Toposort is
|
||||
|
||||
-- shortcuts for package names, intantiation of generic package
|
||||
package TIO renames Ada.Text_IO;
|
||||
package DG renames Digraphs;
|
||||
package SN is new Set_Of_Names(DG.Node_Idx_With_Null);
|
||||
|
||||
-- reat the graph from the file with the given Filename
|
||||
procedure Read(Filename: String; G: out DG.Graph_Type; N: out SN.Set) is
|
||||
|
||||
-- finds the first word in S(Start .. S'Last), delimited by spaces
|
||||
procedure Find_Token(S: String; Start: Positive;
|
||||
First: out Positive; Last: out Natural) is
|
||||
|
||||
begin
|
||||
First := Start;
|
||||
while First <= S'Last and then S(First)= ' ' loop
|
||||
First := First + 1;
|
||||
end loop;
|
||||
Last := First-1;
|
||||
while Last < S'Last and then S(Last+1) /= ' ' loop
|
||||
Last := Last + 1;
|
||||
end loop;
|
||||
end Find_Token;
|
||||
|
||||
File: TIO.File_Type;
|
||||
begin
|
||||
TIO.Open(File, TIO.In_File, Filename);
|
||||
TIO.Skip_Line(File, 2);
|
||||
-- the first two lines contain header and "===...==="
|
||||
while not TIO.End_Of_File(File) loop
|
||||
declare
|
||||
Line: String := TIO.Get_Line(File);
|
||||
First: Positive;
|
||||
Last: Natural;
|
||||
To, From: DG.Node_Index;
|
||||
begin
|
||||
Find_Token(Line, Line'First, First, Last);
|
||||
if Last >= First then
|
||||
N.Add(Line(First .. Last), From);
|
||||
G.Add_Node(From);
|
||||
loop
|
||||
Find_Token(Line, Last+1, First, Last);
|
||||
exit when Last < First;
|
||||
N.Add(Line(First .. Last), To);
|
||||
G.Add_Connection(From, To);
|
||||
end loop;
|
||||
end if;
|
||||
end;
|
||||
end loop;
|
||||
TIO.Close(File);
|
||||
end Read;
|
||||
|
||||
Graph: DG.Graph_Type;
|
||||
Names: SN.Set;
|
||||
|
||||
begin
|
||||
Read(Ada.Command_Line.Argument(1), Graph, Names);
|
||||
|
||||
-- eliminat self-cycles
|
||||
for Start in 1 .. Graph.Node_Count loop
|
||||
Graph.Del_Connection(Start, Start);
|
||||
end loop;
|
||||
|
||||
-- perform the topological sort and output the result
|
||||
declare
|
||||
Result: DG.Node_Vec.Vector;
|
||||
begin
|
||||
Result := Graph.Top_Sort;
|
||||
for Index in Result.First_Index .. Result.Last_Index loop
|
||||
TIO.Put(Names.Name(Result.Element(Index)));
|
||||
if Index < Result.Last_Index then
|
||||
TIO.Put(" -> ");
|
||||
end if;
|
||||
end loop;
|
||||
TIO.New_Line;
|
||||
exception
|
||||
when DG.Graph_Is_Cyclic =>
|
||||
TIO.Put_Line("There is no topological sorting -- the Graph is cyclic!");
|
||||
end;
|
||||
end Toposort;
|
||||
Loading…
Add table
Add a link
Reference in a new issue