with Set_Simple_Sequential_Bounded_Managed_Iterator;
generic
    type Item is private;
    type Attribute is private;
    Number_Of_Vertices : in Positive;
    Number_Of_Arcs : in Positive;
package Graph_Undirected_Bounded_Managed is

    type Graph (Total_Vertices : Positive; Total_Arcs : Positive) is
       limited private;
    type Vertex is private;
    type Arc is private;

    Null_Vertex : constant Vertex;
    Null_Arc : constant Arc;

    procedure Copy (From_The_Graph : in Graph; To_The_Graph : in out Graph);
    procedure Clear (The_Graph : in out Graph);
    procedure Add (The_Vertex : in out Vertex;
                   With_The_Item : in Item;
                   To_The_Graph : in out Graph);
    procedure Remove (The_Vertex : in out Vertex;
                      From_The_Graph : in out Graph);
    procedure Set_Item (Of_The_Vertex : in out Vertex; To_The_Item : in Item);
    procedure Create (The_Arc : in out Arc;
                      With_The_Attribute : in Attribute;
                      With_The_Vertex : in out Vertex;
                      And_The_Vertex : in Vertex;
                      In_The_Graph : in out Graph);
    procedure Destroy (The_Arc : in out Arc; In_The_Graph : in out Graph);
    procedure Set_Attribute (Of_The_Arc : in out Arc;
                             To_The_Attribute : in Attribute);

    function Is_Empty (The_Graph : in Graph) return Boolean;
    function Is_Null (The_Vertex : in Vertex) return Boolean;
    function Is_Null (The_Arc : in Arc) return Boolean;
    function Number_Of_Vertices_In (The_Graph : in Graph) return Natural;
    function Number_Of_Arcs_In (The_Graph : in Graph) return Natural;
    function Number_Of_Arcs_With (The_Vertex : in Vertex) return Natural;
    function Item_Of (The_Vertex : in Vertex) return Item;
    function Attribute_Of (The_Arc : in Arc) return Attribute;
    function First_Vertex_Of (The_Arc : in Arc) return Vertex;  
    function Second_Vertex_Of (The_Arc : in Arc) return Vertex;
    function Is_A_Member (The_Vertex : in Vertex; Of_The_Graph : in Graph)
                         return Boolean;
    function Is_A_Member
                (The_Arc : in Arc; Of_The_Graph : in Graph) return Boolean;

    generic
        with procedure Process (The_Vertex : in Vertex; Continue : out Boolean);
    procedure Iterate_Vertices (Over_The_Graph : in Graph);

    generic
        with procedure Process (The_Arc : in Arc; Continue : out Boolean);
    procedure Iterate_Arcs (Over_The_Graph : in Graph);

    generic
        with procedure Process (The_Arc : in Arc; Continue : out Boolean);
    procedure Reiterate (Over_The_Vertex : in Vertex);

    Overflow : exception;
    Vertex_Is_Null : exception;
    Vertex_Is_Not_In_Graph : exception;
    Arc_Is_Null : exception;
    Arc_Is_Not_In_Graph : exception;

private
    subtype Vertex_Index is Natural range 0 .. Number_Of_Vertices;
    type Vertex is
        record
            The_Head : Vertex_Index := 0;
        end record;
    package Vertex_Set is
       new Set_Simple_Sequential_Bounded_Managed_Iterator (Item => Vertex);
    subtype Arc_Index is Natural range 0 .. Number_Of_Arcs;
    type Arc is
        record
            The_Head : Arc_Index := 0;
        end record;
    package Arc_Set is
       new Set_Simple_Sequential_Bounded_Managed_Iterator (Item => Arc);
    type Graph (Total_Vertices : Positive; Total_Arcs : Positive) is
        record
            The_Vertices : Vertex_Set.Set (Total_Vertices);
            The_Arcs : Arc_Set.Set (Total_Arcs);
        end record;
    Null_Vertex : constant Vertex := Vertex'(The_Head => 0);
    Null_Arc : constant Arc := Arc'(The_Head => 0);
end Graph_Undirected_Bounded_Managed;