gama-platform / gama.old

Main repository for developing the 1.x versions of GAMA
GNU General Public License v3.0
304 stars 99 forks source link

The agents_at_distance function outputs array in different order for the same seed #3214

Closed gitting-around closed 3 years ago

gitting-around commented 3 years ago

I noticed that when called in the same context, this function won't always return the same array. For example, if I make two calls of this function one after the other, I will get two lists with the same elements but in different order.

list agents_close_by_1 <- agents_at_distance(communication_range) of_species simAgents;
list agents_close_by_2 <- agents_at_distance(communication_range) of_species simAgents;

where agents_close_by_1 could contain {simAgents(1), simAgents(2)}, and agents_close_by_2 could contain {simAgents(2), simAgents(1)}. Now, if I fix the seed of an experiment, and have a function that picks randomly one of the agents in such list, I expect that the same agent is picked. My solution to this was to order the list by agent name, and then apply the random function to pick one of them.

I don't know whether this is smth that can be solved at the function level. However, I would suggest that the documentation is updated to describe better its behaviour.

AlexisDrogoul commented 3 years ago

HI,

Thanks for your explanation. Just to be sure, are you talking about the execution of the same agents_at_distance operator in two different experiments with the same seed, or about the execution of two consecutive agents_at_distance in the same experiment ?

gitting-around commented 3 years ago

In both cases, actually. I see now that it wasn't clear in the description above.

This is my setting: I run sets of simulations, and I fix the seeds, e.g. 1,2,3,4... Across the different sets, for specific values of the parameters, I expect the simulation to develop in the same way for the same seed.

Now, if at a run with seed 1 for cycle 3133 I call agents_at_distance, I will get a list, e.g. {simAgents(1), simAgents(2)}. If I run this again with the same seed, at the same cycle, the list could be {simAgents(1), simAgents(2)} or {simAgents(2), simAgents(1)}. So it is the same list in terms of its elements. However if I need to pick an agent randomly from this list, I won't necessarily pick the same agent, thus leading to different outcomes for the same seed. If I order the lists before randomly picking an element, I can get rid of the randomness.

After observing this, I started making smaller tests, in which I make calls to that function within one experiment, one after the other. Agents don't move in between the calls, and nothing else takes place in between those calls.

AlexisDrogoul commented 3 years ago

Hi, the last case is normal: if you call this function at different steps (or even at the same step) several times with the same arguments in the same simulation, it will return different orders for the agents. This should probably be documented.

However, the first case is a bit of a concern as we precisely developed a whole infrastructure to get rid of "uncontrolled randomness" (like the one exhibited by some data structures like HashSet in Java). Are you certain that you do not have a preference related to parallelism turned on ?

Would it be possible for you to share (1) the version of GAMA you are using; (2) A minimal model that reproduces this bug in your setup. Thanks in advance !

gitting-around commented 3 years ago

I will try to set smth up today, and share it with you guys.

gitting-around commented 3 years ago

So I am able to reproduce the issue with a much smaller piece of code -- the actual code is a bit harder to share or minimize as it also relies on external components that communicate with gama via tcp...

Here it is:

/**
* Name: small
* Based on the internal empty template. 
* Author: Super PC
* Tags: 
*/

model agentsatdistancetest

/* Insert your model definition here */

global{
    int run_number <- 1;
    float seed  <- 1;
    init{
        write "creating";

        write seed;
        int i <- 1;
        create simAgents number: 5
            {
                id <-  i;
                i <- i + 1;
                name <- string(i);
            }
        write simAgents.population;
    }

}

species simAgents  skills: [moving]{
    point location <- {1.25,2.0};
    int id <- -1;

     reflex pinging{

            if id=1{
                write agents_at_distance(1.0);
            }
    }

    reflex testWander{

        do wander;

    }
}

experiment "small test" type: batch repeat: 1 until: cycle>10 {
    float minimum_cycle_duration <- 1.0#s;
    float step <- 1#s;
    init{
        write "creating from exp";
    }
}

Basically I create 5 agents, that wander at each step. For agent with id equal to 1, the agents within distance of 1 are printed. The seed is set to 1. If you run this several times you'll see that the arrays produced are not in the same order, for the same time step that is.

I am running this with Gama V1.8.1, on a win10. I am also able to reproduce this on macos catalina with the same Gama version.

Hope this helps!

AlexisDrogoul commented 3 years ago

Hi,

I've briefly tested the code on GAMA 1.8.2, with and without batch (to make sure it was not a consequence of this particular type of experiment) and I obtain exactly the same sequence either when I run a sequence of these experiments, or even when I run simulations in parallel (with the same seed).

So my assumption is that this issue has been fixed in 1.8.2, in one of the few commits made on CompoundSpatialIndex and GamaQuadTree (where I remember actually removing the use of HashSet somewhere -- but I cant find where exactly !).

Not exactly a good news for you, as it also means that we won't issue a fix for the 1.8.1 branch ...

gitting-around commented 3 years ago

It's good that it doesn't happen for 1.8.2. I would think it still needs to be mentioned somewhere in the doc for 1.8.1 how this function behaves. On my side, I have a workaround to fix the issue for now, and I will consider moving to 1.8.2 at some point.

AlexisDrogoul commented 3 years ago

Hi, thanks in any case for your thorough investigation on this complex matter ! We will document this in the future documentation that will detail the differences between 1.8.1 and 1.8.2. I then close this issue -- feel free to reopen if anything pops up on this subject !