Ada - Column Matrix from 2D array type - ada

I'm new to Ada. I try to initialize the 2D array that have 2x1 dimension. But I don't know how to do this, if I do something like 1..1 I will get an error.
type Matrix is array(Integer range <>, Integer range <>) of Integer;
V : Matrix(1..2, 1..3) := (
(1, 4, 5),
(2, 5, 3)
);
-- Here is my problem !
U : Matrix(1..2, ???) := (
(1),
(1)
);

The solution,
U : Matrix(1..2, 1..1) := (
(1 => 1),
(1 => 1)
);

Related

How to perform arithmetic contract operations on function taking in 2D array type as parameter in Ada

I have a function that should return the count of Islands found.
I name this function Count_Islands that takes in a parameter of
Map_Array of type Map, of which Map is an array of Islands.
Islands is an enumerator type with set of Land, Water.
I have the function specification in the .ads and the body in the
.adb
The problem I face now is how to proof that my function
Count_Islands'Result will be less than (X * Y)
I have tried: with post => Count_Islands'Result < X * Y
-- Whenever I ran prove all I got: medium: postcondition might
fail cannot prove Count_Islands'Result < X * Y
Function in .ads:
function Count_Islands(Map_Array : Map)
return Integer with Pre => Map_Array'Length /= 0,
Post => Count_Islands'Result < X * Y;
Function in .adb:
function Count_Islands(Map_Array : Map) return Integer
is
Visited_Array : Visited := (others => (others=> False));
Count : Integer := 0;
begin
if (Map_Array'Length = 0)then
return 0;
end if;
for i in X_Range loop
for j in Y_Range loop
if (Map_Array(i, j) = Land and then not Visited_Array(i,j)) then
Visited_Array := Visit_Islands(Map_Array, i, j,Visited_Array);
Count := Count + 1;
end if;
end loop;
end loop;
return Count;
end Count_Islands;
In a matrix of 4 * 5 for instance,i.e my X = 4 And Y = 5:
I expect the output result of an Islands(Lands) found to be 1 which is less than 4 * 5. But GNATprove cannot prove my initial code to analyze that,using Post => Count_Islands'Result < X * Y;
Is there any better way to prove this arithmetic? Thanks for your help.
As the example is not complete, I took the liberty to change it a little bit. You can prove the post condition by adding loop invariants. The program below proves in GNAT CE 2019:
main.adb
procedure Main with SPARK_Mode is
-- Limit the range of the array indices in order to prevent
-- problems with overflow, i.e.:
--
-- Pos'Last * Pos'Last <= Natural'Last
--
-- Hence, as Natural'Last = 2**31 - 1,
--
-- Pos'Last <= Sqrt (2**31 - 1) =approx. 46340
--
-- If Pos'Last >= 46341, then overflow problems might occur.
subtype Pos is Positive range 1 .. 46340;
type Map_Item is (Water, Land);
type Map is
array (Pos range <>, Pos range <>) of Map_Item;
type Visited is
array (Pos range <>, Pos range <>) of Boolean;
function Count_Islands (Map_Array : Map) return Natural with
Post => Count_Islands'Result <= Map_Array'Length (1) * Map_Array'Length (2);
-------------------
-- Count_Islands --
-------------------
function Count_Islands (Map_Array : Map) return Natural is
Visited_Array : Visited (Map_Array'Range (1), Map_Array'Range (2)) :=
(others => (others => False));
Count : Natural := 0;
begin
for I in Map_Array'Range (1) loop
pragma Loop_Invariant
(Count <= (I - Map_Array'First (1)) * Map_Array'Length (2));
for J in Map_Array'Range (2) loop
pragma Loop_Invariant
(Count - Count'Loop_Entry <= J - Map_Array'First (2));
if Map_Array(I, J) = Land and then not Visited_Array(I, J) then
Visited_Array (I, J) := True; -- Simplified
Count := Count + 1;
end if;
end loop;
end loop;
return Count;
end Count_Islands;
begin
null;
end Main;

SPARK Integer overflow check

I have the following program:
procedure Main with SPARK_Mode is
F : array (0 .. 10) of Integer := (0, 1, others => 0);
begin
for I in 2 .. F'Last loop
F (I) := F (I - 1) + F (I - 2);
end loop;
end Main;
If I run gnatprove, I get the following result, pointing to the + sign:
medium: overflow check might fail
Does this mean that F (I - 1) could be equal to Integer'Last, and adding anything to that would overflow? If so, then is it not clear from the flow of the program that this is impossible? Or do I need to specify this with a contract? If not, then what does it mean?
A counterexample shows that indeed gnatprove in this case worries about the edges of Integer:
medium: overflow check might fail (e.g. when F = (1 => -1, others => -2147483648) and I = 2)
Consider adding a loop invariant to your code. The following is an example from the book "Building High Integrity Applications with Spark".
procedure Copy_Into(Buffer : out Buffer_Type;
Source : in String) is
Characters_To_Copy : Buffer.Count_Type := Maximum_Buffer_Size;
begin
Buffer := (Others => ' '); -- Initialize to all blanks
if Source'Length < Characters_To_Copy then
Characters_To_Copy := Source'Length;
end if;
for Index in Buffer.Count_Type range 1..Characters_To_Copy loop
pragma Loop_Invariant
(Characters_To_Copy <= Source'Length and
Characters_To_Copy = Characters_To_Copy'Loop_Entry);
Buffer (Index) := Source(Source'First + (Index - 1));
end loop;
end Copy_Into;
This is already an old question, but I would like to add an answer anyway (just for future reference).
With the advancement of provers, the example as stated in the question now proves out-the-box in GNAT CE 2019 (i.e. no loop invariant needed). A somewhat more advanced example can also be proven:
main.adb
procedure Main with SPARK_Mode is
-- NOTE: The theoretical upper bound for N is 46 as
--
-- Fib (46) < 2**31 - 1 < Fib (47)
-- 1_836_311_903 < 2_147_483_647 < 2_971_215_073
-- NOTE: Proved with Z3 only. Z3 is pretty good in arithmetic. Additional
-- options for gnatprove:
--
-- --prover=Z3 --steps=0 --timeout=10 --report=all
type Seq is array (Natural range <>) of Natural;
function Fibonacci (N : Natural) return Seq with
Pre => (N in 2 .. 46),
Post => (Fibonacci'Result (0) = 0)
and then (Fibonacci'Result (1) = 1)
and then (for all I in 2 .. N =>
Fibonacci'Result (I) = Fibonacci'Result (I - 1) + Fibonacci'Result (I - 2));
---------------
-- Fibonacci --
---------------
function Fibonacci (N : Natural) return Seq is
F : Seq (0 .. N) := (0, 1, others => 0);
begin
for I in 2 .. N loop
F (I) := F (I - 1) + F (I - 2);
pragma Loop_Invariant
(for all J in 2 .. I =>
F (J) = F (J - 1) + F (J - 2));
-- NOTE: The loop invariant below helps the prover to proof the
-- absence of overflow. It "reminds" the prover that all values
-- from iteration 3 onwards are strictly monotonically increasing.
-- Hence, if absence of overflow is proven in this iteration,
-- then absence is proven for all previous iterations.
pragma Loop_Invariant
(for all J in 3 .. I =>
F (J) > F (J - 1));
end loop;
return F;
end Fibonacci;
begin
null;
end Main;
This loop invariant should work - since 2^(n-1) + 2^(n-2) < 2^n - but I can't convince the provers:
procedure Fibonacci with SPARK_Mode is
F : array (0 .. 10) of Natural := (0 => 0,
1 => 1,
others => 0);
begin
for I in 2 .. F'Last loop
pragma Loop_Invariant
(for all J in F'Range => F (J) < 2 ** J);
F (I) := F (I - 1) + F (I - 2);
end loop;
end Fibonacci;
You can probably convince the provers with a bit of manual assistance (showing how 2^(n-1) + 2^(n-2) = 2^(n-2) * (2 + 1) = 3/4 * 2^n < 2^n).

Understanding XQuery position(): inclusive or exclusive end position

I have read a lot of XQuery position, but all examples are about >, <, or =. But you can also use x - y and I am confused as to what is inclusive and what is not.
[position() = $startPosition to $endPosition]
Let's say $startPosition is 1 (as I have read that position does not start with 0 but with 1), what will return the first hit? $endPosition set to 1 as well, or to 2?
In other words, given an expected return of n, what would be the formula for both variables? To make things more clear, we can add an incrementing loop ($iteration). Basically we are generating a search that will find all subsequent hits with position. (As an example.)
$endPosition = 1 + ($iteration * n);
$startPosition = $endPosition - n;
This is what I came up with. This will result in the following outcome, for $iteration starting from 1 and incrementing, and n of 3.
1:
$endPosition = 1 + (1 * 3); // 4
$startPosition = 4 - 3; // 1
2:
$endPosition = 1 + (2 * 3); // 7
$startPosition = 7 - 3; // 4
3:
$endPosition = 1 + (3 * 3); // 10
$startPosition = 10 - 3; // 7
But, is this correct? I am not sure. Is the $endPosition included? If not, my code is correct, if not - it isn't, and then I am interested in the correct formula.
The expression $sequence[position() = $a to $b] is equivalent to the following FLWOR expression (where $position start at 1):
for $x at $position in $seq
where $position >= $a and $position <= $b
return $x
So to skip the first two items and then return the following five, you need $seq[position() = 3 to 7].
Here is how you can go from this to a subsequence function that uses a 0-based offset and the number of items to return:
declare function local:subsequence(
$seq as item()*,
$offset as xs:integer,
$length as xs:integer
) as item()* {
let $start := $offset + 1,
$end := $offset + $length
return $seq[position() = $start to $end]
};
local:subsequence(1 to 100, 0, 5), (: returns (1, 2, 3, 4, 5) :)
local:subsequence(1 to 100, 13, 3) (: returns (14, 15, 16) :)
It's unclear the specific problem you're trying to solve, so I don't know if this answers your question, but let's unpack that expression first:
[position() = $startPosition to $endPosition]
Say $startPosition is 1 and $endPosition is 3. That will evaluate to:
[position() = (1, 2, 3)]
That predicate will return true any time position() equals any of the values in the sequence on the right.

VHDL concatenate array of vectors to vector

I have been trying to implement a method by which i can concatenate an array of vectors to a vector. Essentially i need something like:
data_received((rx_length_int + 5) * 8)downto 0) <= rx_ident & rx_length & rx_data & rx_checksum;
data_received(BUILD2_RX_PKT_LEN downto ((rx_length_int + 5) * 8)) <= (others => '0');
where BUILD2_RX_PKT_LEN is a constant size, rx_data has a variable number of bytes, but is defined as:
type t_rx_data is array (0 to MAX_PLD) of STD_LOGIC_VECTOR((ADDRESS_WIDTH - 1) downto 0)
I have implemented a few methods, such as a for loop to iterate through rx_data up to rx_length_int, but this has issues with concatenation to data_received as it grows in size... I'm sure there is a very simple solution to this, but I have been unable to come up with one. Any help would be appreciated.
Instead of an unconstrained aggregate, (others => 0), which relies on the result type to constrain the range, you can build an aggregate with a specified range, such as (7 downto 2 => '0').
So why not
data_received <= (BUILD2_RX_PKT_LEN downto ((rx_length_int + 5) * 8) => '0')
& rx_ident & rx_length & rx_data & rx_checksum;
However it's unreadably clumsy. A better approach would be a padding function:
function pad_packet (data : std_logic_vector) return std_logic_vector is
variable temp : std_logic_vector (BUILD2_RX_PKT_LEN downto 1) := (others => '0');
-- NB "downto 0" would be an off-by-1 error if LEN is actual length
-- Initialised vhole vector to zero
begin
temp (data'length downto 1) := data;
return temp;
end pad_packet;
...
data_received <= pad_packet ( rx_ident & rx_length & rx_data & rx_checksum );
Much clearer...

Backtracking in Pascal: finding maximal weighted branch

I've been learning Pascal (using the Free Pascal compiler) for a week now, and came across a seemingly easy exercise. Given a structure as shown below, find the maximal weighted branch:
1
4 9
7 0 2
4 8 6 3
A branch is any sequence of numbers, starting from the top (in this case: 1), when for every number the branch can expand either down-left or down-right. For example, the branch 1-4-0 can expand into either 1-4-0-8 or 1-4-0-6. All branches must start from the top and end at the bottom.
In this example, the maximal branch is 1-4-7-8, which gives us 20. In order to solve this question, I tried to use backtracking. The triangular structure was stored in an array of type 'triangle':
type triangle = array[1..MAX_NUM_OF_ROWS, 1..MAX_NUM_OF_ROWS] of integer;
Here's my implementation:
function findAux(data: triangle; dim: integer; i: integer; j:integer) : integer;
begin
if i = dim then
findAux := data[i][j]
else
if findAux(data, dim, i + 1, j + 1) > findAux(data, dim, i + 1, j) then
findAux := data[i+1][j+1] + findAux(data, dim, i + 1, j + 1);
else
findAux := data[i+1][j] + findAux(data, dim, i + 1, j);
end;
function find_heaviest_path(data: triangle; dim: integer) : integer;
begin
find_heaviest_path := findAux(data, dim, 1, 1);
end;
As you can see, I've used an auxiliary function. Unfortunately, it doesn't seem to give the right result. For the structure seen above, the result I get is 27, which is 7 points off. What am I missing? How does the implementation look overall? I should add that the maximal number of rows is 100, for this exercise. If clarification is needed, please don't hesitate to ask.
Your findAux is adding the wrong value to the recursively obtained result. As an aside, you can neaten the code a bit using some local variables. A corrected version of findAux:
uses math;
...
function findAux(data: triangle; dim: integer; i: integer; j:integer) : integer;
var
left, right: integer;
begin
if i = dim then
findAux := data[i][j]
else begin
left := findAux(data, dim, i + 1, j);
right := findAux(data, dim, i + 1, j + 1);
findAux := data[i][j] + Max(left, right);
end;
end;

Resources