Ada array aggregate initialization - ada

I am trying to initialize a simple Ada array using an aggregate, and I would like the compiler to determine the array bounds. However, When trying to use Test_2 below, I cannot simply use integer subscripts. Is there a way to allow the compiler to determine the array bounds arrays, and yet access them using the simple "Test_2(0)" notation?
I am using gnat.
Thanks.
with Interfaces; use Interfaces;
procedure Test_Init is
type U16_a is array(Integer range <>) of Unsigned_16;
-- array aggregate initialization
Test_1 : U16_a(0..1) := (16#1234#, 16#5678#); -- ok, but...
Test_2 : U16_a := (16#8765#, 16#4321#); -- let compiler create bounds
Test_3 : Unsigned_16;
begin
-- Test_1 obviously works
Test_3 := Test_1(0);
-- warning: value not in range of subtype of "Standard.Integer" defined at line 8
-- This produces a constraint.
-- What is the subtype that is defined at line 8? It is not Integer (0..1)
Test_3 := Test_2(0);
-- this works though
Test_3 := Test_2(Test_2'First);
-- and this works
Test_3 := Test_2(Test_2'Last);
-- and this works
Test_3 := Test_2(Test_2'First + 1);
end Test_Init;

If you don't specify the bounds, the lower bound of the array is the lower bound of the index type. (You may be accustomed to languages like C, where arrays always have a lower bound of 0. That's not the case in Ada.)
In this case, the lower bounds is Integer'First, which is probably -2147483648.
If you want the array bounds to start at 0, you can use the subtype Natural:
type U16_a is array(Natural range <>) of Unsigned_16;
Or you can use the subtype Positive to set the array's lower bound to 1.
You can also specify the index of each element:
Test_2 : U16_a := (0 => 16#8765#, 1 => 16#4321#);
but that may not scale as well; if there are a large number of elements, you have to specify the index for each one, since positional associations can't follow named associations.
Instead of using positional or named aggregate initializers you can use array concatenation to specify the first index:
Test_3 : U16_a := (0 => 0) & (1, 2, 3, 4, 5, 6, 7);
The reference manual states:
If the ultimate ancestor of the array type was defined by an
unconstrained_array_definition, then the lower bound of the result is
that of the left operand.
It's cleaner to pick an index subtype with the desired lower bound.

Related

Fortran doesn't keep lower/upper array bounds after copy to another allocatable array

This doesn't work
program main
implicit none
integer :: nx = 3
integer :: ny = 5
integer :: nz = 8
real, allocatable, dimension(:,:,:) :: A
real, allocatable, dimension(:,:) :: B
allocate(A(nx,0:ny,nz) )
! ...do something with array A and at some point cope a slice of A to B:
B = A(:,:,1)
! in this case B is (1:nx, 1: ny+1)
end program main
The code above automatically allocates B and copies A(:,:,1) to B. However it doesn't keep the lower/upper bound of 0/ny, instead B has its lower bound to 1 and upper bound to ny+1.
The only way I found to keep the lower/upper bound of A 2dn-dim is by explicitly allocate B as:
allocate(B(nx, 0:ny))
B = A(:,:,1)
! in this case B is (1:nx, 0:ny)
Given that I have many more variables than in this simple example, is there a way to assign like B=A(:,:,1) and also keep the bounds of A without explicitly allocating B?
A(:,:,1) is an expression. It has bounds (1:nx, 1:ny), BOTH ranks start at 1. It is not the original array, it is a new expression.
However, even if it was an array that had some other lower bounds, automatic allocation always allocates indexes starting from 1. Basically, the right hand side is an expression again.
For your case you do have to allocate explicitly.
You can use:
allocate(B(lbound(A,1):ubound(A,1), lbound(A,2):ubound(A,2)))

How to check equality of two FStar.Set's

How can you check whether two sets are equal in FStar? The following expression is of type Type0 not Tot Prims.bool so I'm not sure how to use it to determine if the sets are equal (for example in a conditional). Is there a different function that should be used instead of Set.equal?
Set.equal (Set.as_set [1; 2; 3]) Set.empty
The sets defined in FStar.Set are using functions as representation.
Therefore, a set s of integers for instance, is nothing else than a function mapping integers to booleans.
For instance, the set {1, 2} is represented as the following function:
// {1, 2}
fun x -> if x = 1 then true
else (
if x = 2 then true
else false
)
You can add/remove value (that is, crafting a new lambda), or asks for a value being a member (that is, applying the function).
However, when it comes to comparing two sets of type T, you're out of luck : for s1 and s2 two sets, s1 = s2 means that for any value x : T, s1 x = s2 x. When the set of T's inhabitants is inifinite, this is not computable.
Solution The function representation is not suitable for you. You should have a representation whose comparaison is computable. FStar.OrdSet.fst defines sets as lists: you should use that one instead.
Note that this OrdSet module requires a total order on the values held in the set. (If you want have set of non-ordered values, I implemented that a while ago, but it's a bit hacky...)

Need review of scheduling model logic, suggestions for constraint creation and fixes for syntax errors

I am creating a scheduling model for a blending facility in Mini Zinc. I have asked a similar question earlier but I have since progressed. I will summarize what I think my existing model should do, it would be super helpful if someone could correct any logical or syntax errors I have made. The model currently errors, with several instances of "expecting end of file". It seems way to simplistic in comparison to several other sequence dependent scheduling models I have found. Below you will find the model code commented with my understanding of each line.
Besides an overview of the logic and syntax, I am looking for help with the "missing constraint" in this model, which needs to require that the array of blends [y] contain no more than the declared integer quantity of each blend.
Notable future goals for this model include automatic generation of the blendcost matrix, output the schedule array given a starting day into a 5 column matrix representing weekdays, and showing the blend name as opposed to blend number.
enum Blends = { A, B, C, D, E, F};
%Establish names for each blend and link them to their order number.
int: nb = count([Blends])
%Count the number of blends, plan to use later.
int: qA; %Error: syntax error, unexpected int, expecting end of file
int: qB;
int: qC;
int: qD;
int: qE;
int: qF;
int: sb;
%Call for inputs of the quantity of each of the blends needed, as well as the number/letter of the blend currently in the machine.
int: mc = qA + qB + qC + qD + qE + qF;
%Sum the blend quantities to determine total number of blends
[Blendcost] : [|1,2,2,2,2,2,|1,1,1,1,1,1,|1,1,1,1,1,1,|2,2,2,1,2,2,|1,1,1,1,1,1,|1,1,1,1,1,1,|]; %Error: syntax error, unexpected [|, expecting identifier
%Establishes a blend cost matrix, 6X6 depicting the transition costs from any blend A-F to any other blend A-F
array [Blends] of int: 1..6;
%Is this line needed to establish the link between A/1, B/2, C/3 etc;? Or is that taken care of when Blends is enumerated?
array [0..mc] of var 1..6: y;
%Create an array from 0 to the number of blends with potential values from 1-6, corresponding to the blend numbers.
%Missing constraint: [y] can contain no more than the quantity of each blend declared above, except for the blend declared in the starting blend, which will be allowed that blend quantity + 1
constraint y(0) = sb
%y(0) is set equal to the starting blend Letter/Number Defined earlier, used to determine the first transitionary cost.
array [1..mc] of int: x(i); %Error: syntax error, unexpected array, expecting end of file
%Create an array from 1 to number of blends, which will be filled with the transition costs in response to variations in y
constraint forall(i in x)(x(i) = Blendcost(y(i-1),y(i)))
%For each space in x, x will equal the blend cost value obtained from the previous blend in the y array vs the next blend in the y array
solve minimize sum (x); %Error: syntax error, unexpected solve, expecting end of file
%Solves this model attempting to minimize the sum of the x array, which should be filled with the transition costs.
show(y):
%Print the final array of blend numbers that has minimized blend cost transition.
%Error: unexpected end of file, expecting identifier.
Here is a basic version of your CP-model that runs (assuming some demand q):
enum BLEND = { A, B, C, D, E, F};
array[BLEND] of int: q = [1, 2, 4, 6, 8, 1];
array[BLEND, BLEND] of int: Blendcost =
[|1,2,2,2,2,2|1,1,1,1,1,1|1,1,1,1,1,1|2,2,2,1,2,2|1,1,1,1,1,1|1,1,1,1,1,1|];
int: mc = sum(q);
array[1..mc] of var BLEND: y;
include "global_cardinality.mzn";
constraint global_cardinality(y, BLEND, q);
var int: obj = sum(p in 1..mc-1)(Blendcost[y[p],y[p+1]]) + 1;
array[int] of var opt BLEND: day = [y[p] | p in 1..mc-1, q in 1..max(Blendcost) where q <= Blendcost[y[p],y[p+1]]] ++ [y[mc]];
array[int] of var opt int: wash = [bool2int(q > 1) | p in 1..mc-1, q in 1..max(Blendcost) where q <= Blendcost[y[p],y[p+1]]] ++ [0];
solve minimize obj;
output ["obj=\(obj)\n"] ++
["day=\n"] ++ [
show(day[d]) ++ if fix(wash[d]) > 0 then "W" else "" endif ++ " " ++
if d mod 5 = 0 then "\n" else "" endif | d in 1..length(day)
] ++ ["\nmc=\(mc)\n"] ++ ["y=\(y)\n"] ++ ["wash=\(wash)\n"]
Have a look at https://www.minizinc.org/doc-2.2.3/en/lib-globals.html#counting-constraints for alternative versions of the counting constraint.
For larger instances a MIP-model might show better performance.

comparing of mix,max values of two sub types in Ada using ASIS

I want to compare min, max of values of two subtypes. In Ada language it is possible to assign between two different subtypes, for example
procedure Example_1 is
subtype Type_1 is Integer range 0 .. 10;
subtype Type_2 is Integer range 0 .. 30;
A : Type_1 := 0;
B : Type_2 := 12;
begin
A := B;
end Example_1;
At run time A := B can give range overflow error. In ASIS, is it possible to compare subtypes, min/max values of subtypes (integer, real, enumeration types) so that I can identify overflow problem before run-time?
The compiler detects this problem when compiled with -gnatVa -gnat12
Yes, it is possible to check this with ASIS.
See the answer to this question for how to extract 'First and 'Last for a subtype.

Ada programing array of records

I’m new in Ada and I’m trying to create an array of records and then put some records to the array but I got error nested array aggregate expected. Here is my code:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_Io;
with Ada.unchecked_conversion;
procedure main is
type Byte is range 0..255;
for Byte'Size use 8;
type Pixel is record
R:Byte;
G:Byte;
B:Byte;
end record;
for Pixel'Size use 24;
r1:Pixel := (1,2,5);
r2:Pixel := (1,2,3);
r3:Pixel := (1,2,3);
type Image is array(Positive range <>, Positive range <>) of Pixel;
Pragma Pack(Image);
Left:Image(1..3, 1..1) := (r1, r2, r3);
begin
null;
end main;
A two-dimensional array needs a two-dimensional aggregate, i.e. an aggregate where each element is also an aggregate. For example:
type Integer_Matrix is array (Positive range <>, Positive range <>) of Integer;
M : Integer_Matrix (1..2, 1..2) := ( (1, 2), (3, 4) );
When either dimension has length 1, it needs special handling, because a single value in parentheses isn't treated as an aggregate. A one-element aggregate needs to be written as (1=>Value) [use the actual index in place of 1 if necessary]. In your case, each row of Image has length 1. So you aggregate will have three elements, and each element will be another aggregate of length 1. It will need to look like this:
Left : Image (1..3, 1..1) := ( (1=>r1), (1=>r2), (1=>r3) );

Resources