Ada random Integer in range of array length

Viewed 267

It's a simple question, yet I can't find anything that could help me... I want to create some random connection between graph nodes. To do this I want do two random indexes and then connect the nodes.

declare
        type randRange is range 0..100000;
        n1: randRange;
        n2: randRange;
    
        package Rand_Int is new ada.numerics.discrete_random(randRange);
        use Rand_Int;
        gen : Generator;

        begin
          n1 := random(gen) mod n; -- first node
          n2 := random(gen) mod n;

I wanted to define the range with length of my array but I got errors. Still, it doesn't compile. Also I can't perform modulo as n is natural.

75:15: "Generator" is not visible
75:15: multiple use clauses cause hiding
75:15: hidden declaration at a-nudira.ads:50, instance at line 73
75:15: hidden declaration at a-nuflra.ads:47

And I have no idea what these errors mean - obviously, something is wrong with my generator. I would appreciate if someone showed me a proper way to do this simple thing.

3 Answers

As others have answered, the invisibility of Generator is due to you having several "use" clauses for packages all of which have a Generator. So you must specify "Rand_Int.Generator" to show that you want the Generator from the Rand_Int package.

The problem with the "non-static expression" happens because you try to define a new type randRange, and that means the compiler has to decide how many bits it needs to use for each value of the type, and for that the type must have compile-time, i.e. static, bounds. You can instead define it as a subtype:

subtype randRange is Natural range 0 .. n-1;

and then the compiler knows that it can use the same number of bits as it uses for the Natural type. (I assume here that "n" is an Integer, or Natural or Positive; otherwise, use whatever type "n" is.)

Using a subtype should also resolve the problem with the "expected type".

You don't show us the whole code neccessary to reproduce the errors, but the error messages suggest you have another use clause somewhere, a use Ada.Numerics.Float_Random;. Either remove that, or specify which generator you want, ie. gen : Rand_Int.Generator;.

As for mod, you should specify the exact range you want when instantiating Discrete_Random instead:

type randRange is 0..n-1; -- but why start at 0? A list of nodes is better decribed with 1..n

package Rand_Int is new ada.numerics.discrete_random(randRange);

Now, there's no need for mod

The error messages you mention have to do with concept of visibility in Ada, which differs from most other languages. Understanding visibility is key to understanding Ada. I recommend that beginners avoid use <package> in order to avoid the visibility issues involved with such use clauses. As you gain experience with the language you can experiment with using common pkgs such as Ada.Text_IO.

As you seem to come from a language in which arrays have to have integer indices starting from zero, I recommend Ada Distilled, which does an excellent job of describing visibility in Ada. It is ISO/IEC 8652:2007, but you should have no difficulty picking up Ada-12 from that basis.

If you're interested in the issues involved in obtaining a random integer value in a subrange of an RNG's result range, or from a floating-point random value, you can look at PragmARC.Randomness.Real_Ranges and PragmARC.Randomness.U32_Ranges in the PragmAda Reusable Components.

Related