javamodelsimulationrepast-simphony

Repast Simphony: How to set Scheduling priority based on agent id


I am making a Repast Simphony model of passengers boarding an airplane, and it is important for me to have the agents be iterated over in a certain, constant order. I have set the random seed to 1, and so the order is constant, however not trivial. It would be easiest for me if the agents were iterated over either from back to front or front to back.

As written in this post: Repast: Agent execution order

one way to achieve this certain order would be to set the priority of each agent's ScheduledMethod to be dependent on their ID. I have tried doing this in the @ScheduledMethod annotation, like this:

@ScheduledMethod(start = 1, interval = 1, priority = boardingID)

(boarding ID is the agent ID) however it gives me this warning:

The value for annotation attribute ScheduledMethod.priority must be a constant expression

Since the agent id is a variable of that class, this doesn't work. However, I believe it should be possible to do this in some way, as the id will never change once initialised, and so if I manage to pass it as the priority it shouldn't cause any harm as it will never change. However, how do I do this? How do I set the scheduling priority based on agent ID? Should I do it somewhere else?


Solution

  • If the agent population is constant throughout the life the simulation, you could put all the agents into an ArrayList during initialization and sort that list by agent id. To execute the agent behavior, just iterate through the list calling method you are annotating with @ScheduledMethod on each agent.

    Alternatively, you could Java streams for this. See,

    https://stackabuse.com/java-8-how-to-sort-list-with-stream-sorted/

    Context.getObjectsAsStream (https://repast.github.io/docs/api/repast_simphony/repast/simphony/context/Context.html#getObjectsAsStream(java.lang.Class)) returns a Stream, that you can sort with sorted, and then call forEach with the method name that you are annotating with @ScheduledMethod. So, something like:

    myContext.getObjectsAsStream(Passenger.class).sorted(X).forEach(Y)
    

    where X is a Comparator that sorts by Passenger agent id and Y is the method to call on each Passenger.

    You can schedule this to execute each tick in your ContextBuilder.build with

    ISchedule schedule = RunEnvironment.getInstance().getCurrentSchedule();
          schedule.schedule(ScheduleParameters.createRepeating(1, 1), ->
          { 
              
                  // Your code goes here: e.g.,
                  // myContext.getObjectsAsStream(Passenger.class).sorted(X).forEach(Y);
          });
    

    That creates an IAction lambda and schedules it directly rather than using an annotation.