Chapter 4: ADA Data Structures

ADA Programming language

One of the aspects that make ADA programming language an attractive language for system and application programming, especially in the aerospace industry, is its powerful support for data structures. In this post, we’ll delve into arrays, records, sets, queues, and stacks.

Arrays

Arrays in Ada are homogeneous data structures that allow storing multiple values of the same type in contiguous memory locations. They can be one-dimensional (a simple list of values) or multi-dimensional (e.g., a matrix of values or a 3D array).

Declaring an array in Ada involves specifying the type of the elements, and the range of the indices. Here’s a simple example of a one-dimensional array:

type Integer_Array is array (1 .. 5) of Integer;
My_Array : Integer_Array := (10, 20, 30, 40, 50);

For multi-dimensional arrays, the declaration may look like this:

type Matrix is array (1 .. 3, 1 .. 3) of Integer;
My_Matrix : Matrix := ((1, 2, 3), (4, 5, 6), (7, 8, 9));

To make an illustrative use of arrays in an aerospace context, we can consider the task of a Flight Management System (FMS). The FMS plays a crucial role in guiding an aircraft from departure to destination, so it needs to maintain a flight plan composed of a series of waypoints. We can model each waypoint and the flight plan itself as arrays.

with Ada.Text_IO; use Ada.Text_IO;

procedure Flight_Management_System is
   -- Define a waypoint with latitude, longitude, and altitude
   type Waypoint is record
      Latitude  : Float;
      Longitude : Float;
      Altitude  : Integer;
   end record;
   
   -- An array of waypoints will represent our flight plan
   type Flight_Plan is array (1 .. 100) of Waypoint;

   -- Now, let's instantiate a flight plan
   My_Flight_Plan : Flight_Plan;

   -- Procedure to populate flight plan with waypoints
   procedure Initialize_Flight_Plan is
   begin
      for I in My_Flight_Plan'Range loop
         My_Flight_Plan(I).Latitude := 0.0;  -- These values would be replaced by actual coordinates
         My_Flight_Plan(I).Longitude := 0.0;  -- These values would be replaced by actual coordinates
         My_Flight_Plan(I).Altitude := 0;  -- This would be replaced by the actual altitude
      end loop;
   end Initialize_Flight_Plan;
   
begin
   -- Initialize the flight plan
   Initialize_Flight_Plan;
   
   -- Print each waypoint
   for I in My_Flight_Plan'Range loop
      Put_Line("Waypoint " & I'Image & ": ");
      Put("Latitude: " & My_Flight_Plan(I).Latitude'Image);
      Put(", Longitude: " & My_Flight_Plan(I).Longitude'Image);
      Put(", Altitude: " & My_Flight_Plan(I).Altitude'Image);
      New_Line;
   end loop;
   
end Flight_Management_System;

In this example, a waypoint is represented by a record containing the latitude, longitude, and altitude. A flight plan is an array of waypoints. The Initialize_Flight_Plan procedure populates the flight plan with waypoints, although it uses placeholder values in this simplified example. The main part of the program then prints each waypoint in the flight plan.

The arrays in this program are one-dimensional, but Ada supports multi-dimensional arrays as well, which would allow for more complex models such as a 3D grid of airspace sectors.

Records

Records in Ada are similar to structures in C or objects in many OOP languages. They allow you to define a complex data type with different types of fields. This feature can be used to encapsulate related data, making Ada a good fit for large systems like aerospace software.

Here’s how to define and use a record in Ada:

type Aircraft is record
   Model : String(1 .. 20);
   Altitude : Integer;
   Speed : Float;
end record;

My_Aircraft : Aircraft;
My_Aircraft.Model := "Boeing 747";
My_Aircraft.Altitude := 35000;
My_Aircraft.Speed := 570.0;

Now, let’s look into an example which uses the record in ADA.

Let’s build on the previous Flight Management System (FMS) example, this time focusing on the use of records.

In Ada, a record is a collection of related data elements, potentially of different types, grouped together under a single name. Records can be likened to a struct in C or an object in object-oriented programming languages.

For a flight management system, we can define a more sophisticated Waypoint record and a Flight_Plan record to encapsulate the series of waypoints and additional information about the flight.

with Ada.Text_IO; use Ada.Text_IO;

procedure Flight_Management_System is
   -- Define a waypoint with ID, latitude, longitude, and altitude
   type Waypoint is record
      ID        : String(1..20);
      Latitude  : Float;
      Longitude : Float;
      Altitude  : Integer;
   end record;

   -- An array of waypoints will represent our flight plan's route
   type Route is array (1 .. 100) of Waypoint;

   -- Define a flight plan as a record
   type Flight_Plan is record
      Aircraft_ID : String(1..20);
      Departure_Time : String(1..20);
      Estimated_Arrival_Time : String(1..20);
      Route : Route;
   end record;

   -- Now, let's instantiate a flight plan
   My_Flight_Plan : Flight_Plan;

   -- Procedure to populate flight plan with waypoints and details
   procedure Initialize_Flight_Plan is
   begin
      My_Flight_Plan.Aircraft_ID := "Boeing 747";
      My_Flight_Plan.Departure_Time := "0800";
      My_Flight_Plan.Estimated_Arrival_Time := "1400";

      for I in My_Flight_Plan.Route'Range loop
         My_Flight_Plan.Route(I).ID := "WP" & I'Img;  -- Waypoint IDs would be replaced by actual IDs
         My_Flight_Plan.Route(I).Latitude := 0.0;  -- These values would be replaced by actual coordinates
         My_Flight_Plan.Route(I).Longitude := 0.0;  -- These values would be replaced by actual coordinates
         My_Flight_Plan.Route(I).Altitude := 0;  -- This would be replaced by the actual altitude
      end loop;
   end Initialize_Flight_Plan;

begin
   -- Initialize the flight plan
   Initialize_Flight_Plan;

   -- Print flight plan details and each waypoint
   Put_Line("Aircraft ID: " & My_Flight_Plan.Aircraft_ID);
   Put_Line("Departure Time: " & My_Flight_Plan.Departure_Time);
   Put_Line("Estimated Arrival Time: " & My_Flight_Plan.Estimated_Arrival_Time);
   
   for I in My_Flight_Plan.Route'Range loop
      Put_Line("Waypoint " & I'Image & ": ");
      Put("ID: " & My_Flight_Plan.Route(I).ID);
      Put(", Latitude: " & My_Flight_Plan.Route(I).Latitude'Image);
      Put(", Longitude: " & My_Flight_Plan.Route(I).Longitude'Image);
      Put(", Altitude: " & My_Flight_Plan.Route(I).Altitude'Image);
      New_Line;
   end loop;

end Flight_Management_System;

In this example, the Waypoint record includes an ID, latitude, longitude, and altitude. The Flight_Plan record includes an aircraft ID, departure time, estimated arrival time, and a route consisting of an array of waypoints.

The Initialize_Flight_Plan procedure populates the flight plan with details and waypoints. Note that this is a simplified example, so it uses placeholder values for the waypoints.

The main part of the program then prints out the details of the flight plan and each waypoint in the route. This demonstrates how records can help encapsulate related pieces of data and simplify the structure of the program.

Sets

While Ada does not have built-in support for sets as some other languages do, they can be easily implemented using arrays or other data structures. An array-based set implementation may involve an array and an integer to keep track of the last index used:

type Set is array (1 .. 100) of Integer;
My_Set : Set;
Last_Index : Integer := 0;

You can then define procedures to add an element, remove an element, check if an element exists in the set, etc.

Although Ada does not natively support the set data structure unlike some other languages, we can construct and implement a set using an array as discussed before. Let’s consider the aerospace context again. For the Flight Management System (FMS), we might want to maintain a set of unique waypoints.

In this example, we define a waypoint as before and create a “set” of waypoints, ensuring each waypoint is unique in the set.

with Ada.Text_IO; use Ada.Text_IO;

procedure Flight_Management_System is
   -- Define a waypoint with ID, latitude, longitude, and altitude
   type Waypoint is record
      ID        : String(1..20);
      Latitude  : Float;
      Longitude : Float;
      Altitude  : Integer;
   end record;

   -- A "set" of unique waypoints implemented as an array
   type Waypoint_Set is array (1 .. 100) of Waypoint;

   -- Now, let's instantiate a waypoint set
   My_Waypoint_Set : Waypoint_Set;
   Last_Index : Integer := 0;

   -- Procedure to add a unique waypoint to the set
   procedure Add_Waypoint(New_Waypoint : Waypoint) is
      Exists : Boolean := False;
   begin
      -- Check if the waypoint is already in the set
      for I in 1 .. Last_Index loop
         if My_Waypoint_Set(I).ID = New_Waypoint.ID then
            Exists := True;
            exit;
         end if;
      end loop;

      -- If the waypoint is not in the set, add it
      if not Exists then
         Last_Index := Last_Index + 1;
         My_Waypoint_Set(Last_Index) := New_Waypoint;
      end if;
   end Add_Waypoint;

   -- A sample waypoint
   Waypoint1 : Waypoint := (ID => "WP1", Latitude => 40.7128, Longitude => -74.0060, Altitude => 35000);

begin
   -- Add the waypoint to the set
   Add_Waypoint(Waypoint1);

   -- Print each waypoint in the set
   for I in 1 .. Last_Index loop
      Put_Line("Waypoint " & I'Image & ": ");
      Put("ID: " & My_Waypoint_Set(I).ID);
      Put(", Latitude: " & My_Waypoint_Set(I).Latitude'Image);
      Put(", Longitude: " & My_Waypoint_Set(I).Longitude'Image);
      Put(", Altitude: " & My_Waypoint_Set(I).Altitude'Image);
      New_Line;
   end loop;
   
end Flight_Management_System;

In this program, the Waypoint_Set is an array of waypoints which we use to implement a set. We define an Add_Waypoint procedure which checks if a new waypoint already exists in the set before adding it. This ensures that the set of waypoints remains unique.

This is a simplified example and assumes that the ID of a waypoint is enough to determine its uniqueness. In a more complex system, you might need to compare other properties or use a more sophisticated data structure to ensure efficiency when the set becomes large.

Queues and Stacks

Ada provides powerful facilities for manipulating more complex data structures like queues and stacks, which are essential for many algorithms and procedures in aerospace software.

A stack can be implemented in Ada using an array and an index to the top element. Here’s a simple integer stack:

type Stack is array (1 .. 100) of Integer;
My_Stack : Stack;
Top : Integer := 0;

The push and pop operations can then be implemented as procedures.

Queues, on the other hand, can be implemented using an array and two indices (to the front and rear elements). Operations like enqueue and dequeue can then be implemented as procedures.

type Queue is array (1 .. 100) of Integer;
My_Queue : Queue;
Front, Rear : Integer := 1;

The use of these data structures, along with Ada’s support for abstraction and strong typing, enables efficient and reliable software development, which is crucial in the aerospace industry.

Let’s focus on stacks for this section, as they are useful for many operations in a Flight Management System (FMS). An “Undo” stack might be used in a flight planning context, where changes to the flight plan could be pushed onto a stack, and an “Undo” operation would simply involve popping the stack to revert the latest change.

First, we define the stack and its operations. Ada doesn’t have native support for stack data structures, but we can create them using arrays:

with Ada.Text_IO; use Ada.Text_IO;

procedure Flight_Management_System is
   -- Define a waypoint with ID, latitude, longitude, and altitude
   type Waypoint is record
      ID        : String(1..20);
      Latitude  : Float;
      Longitude : Float;
      Altitude  : Integer;
   end record;

   -- Define a "Stack" of Waypoints
   type Waypoint_Stack is record
      Data : array (1 .. 100) of Waypoint;
      Top : Integer := 0;
   end record;

   -- Function to check if the stack is empty
   function Is_Empty(S : Waypoint_Stack) return Boolean is
   begin
      return S.Top = 0;
   end Is_Empty;

   -- Procedure to push a waypoint onto the stack
   procedure Push(S : in out Waypoint_Stack; W : Waypoint) is
   begin
      S.Top := S.Top + 1;
      S.Data(S.Top) := W;
   end Push;

   -- Procedure to pop a waypoint from the stack
   procedure Pop(S : in out Waypoint_Stack; W : out Waypoint) is
   begin
      W := S.Data(S.Top);
      S.Top := S.Top - 1;
   end Pop;

   -- A sample waypoint
   Waypoint1 : Waypoint := (ID => "WP1", Latitude => 40.7128, Longitude => -74.0060, Altitude => 35000);

   -- Create a stack of waypoints
   Stack : Waypoint_Stack;

begin
   -- Push the waypoint onto the stack
   Push(Stack, Waypoint1);

   -- Now let's pop the waypoint and print it
   declare
      W : Waypoint;
   begin
      Pop(Stack, W);
      Put_Line("Popped waypoint: ");
      Put("ID: " & W.ID);
      Put(", Latitude: " & W.Latitude'Image);
      Put(", Longitude: " & W.Longitude'Image);
      Put(", Altitude: " & W.Altitude'Image);
      New_Line;
   end;
   
end Flight_Management_System;

This program defines a Waypoint as before, and creates a Waypoint_Stack that can store waypoints. The Push and Pop procedures allow us to add and remove waypoints from the stack, respectively, while the Is_Empty function checks if the stack is empty.

In the main part of the program, we create a stack, push a waypoint onto it, then pop the waypoint and print its details. This could form the basis for a more complex “Undo” operation in a flight planning system.

Similarly, queues could be used in contexts where operations need to be processed in a first-in, first-out (FIFO) order, such as managing a sequence of commands or tasks in an avionics system. Like stacks, queues can be implemented using arrays in Ada.

For example, a Flight Management System (FMS) may have to manage a queue of flight instructions.

Firstly, let’s define a basic queue structure and its operations. As Ada doesn’t have built-in support for queue data structures, we’ll create them using arrays:

with Ada.Text_IO; use Ada.Text_IO;

procedure Flight_Management_System is
    -- Define a flight instruction with ID and description
    type Flight_Instruction is record
        ID          : String(1..20);
        Description : String(1..100);
    end record;

    -- Define a "Queue" of Flight Instructions
    type Flight_Instruction_Queue is record
        Data  : array (1 .. 100) of Flight_Instruction;
        Front : Integer := 1;
        Rear  : Integer := 0;
    end record;

    -- Function to check if the queue is empty
    function Is_Empty(Q : Flight_Instruction_Queue) return Boolean is
    begin
        return Q.Rear < Q.Front;
    end Is_Empty;

    -- Procedure to enqueue a flight instruction
    procedure Enqueue(Q : in out Flight_Instruction_Queue; FI : Flight_Instruction) is
    begin
        Q.Rear := Q.Rear + 1;
        Q.Data(Q.Rear) := FI;
    end Enqueue;

    -- Procedure to dequeue a flight instruction
    procedure Dequeue(Q : in out Flight_Instruction_Queue; FI : out Flight_Instruction) is
    begin
        FI := Q.Data(Q.Front);
        Q.Front := Q.Front + 1;
    end Dequeue;

    -- A sample flight instruction
    Flight_Instruction1 : Flight_Instruction := (ID => "FI1", Description => "Climb to 35000 feet");

    -- Create a queue of flight instructions
    Queue : Flight_Instruction_Queue;

begin
    -- Enqueue the flight instruction
    Enqueue(Queue, Flight_Instruction1);

    -- Now let's dequeue the flight instruction and print it
    declare
        FI : Flight_Instruction;
    begin
        Dequeue(Queue, FI);
        Put_Line("Dequeued flight instruction: ");
        Put("ID: " & FI.ID);
        Put(", Description: " & FI.Description);
        New_Line;
    end;

end Flight_Management_System;

In this program, a Flight_Instruction is defined with an ID and a description. The Flight_Instruction_Queue can store such instructions. The Enqueue and Dequeue procedures allow us to add and remove flight instructions from the queue, respectively, while the Is_Empty function checks if the queue is empty.

In the main part of the program, we create a queue, enqueue a flight instruction, then dequeue it and print its details. This could form the basis of a more complex system that manages a sequence of flight instructions in an aircraft’s FMS.

The queue here is a simple static implementation. For more dynamic queues or larger systems, a different implementation using dynamic data structures such as linked lists might be more suitable.

Chapter 4: ADA Data Structures
Scroll to top
error: Content is protected !!