Search code examples
agent-based-modelingrepast-simphony

Repast: how to count the total number of agents satisfying the specific condition


Each agent has a private boolean variable "Happy?". how to count the agents with [Happy? = True]?

Is there a direct method available in repast? Or I have iterate through all agents and count them individually?

Update:

I have tried the global scheduling method: https://repast.github.io/docs/RepastReference/RepastReference.html#schedule-global

It's not working when I put below code using the @ScheduledMethods in the ContextBuilder.

grid.moveTo(this_girl, group_x,group_y);
            }
        }       
        return context;
    }

    @ScheduledMethod(start = 1, interval = 1, shuffle=true)
    public void step () {
        Context<Object> context = ContextUtils.getContext(this);
        Query<Object> query = new PropertyEquals<Object>(context, "happy", true);
        int end_count = 0;
        System.out.println(end_count);
        for (Object o : query.query()) {
           if (o instanceof Boy) {
               end_count ++;               
           }
           if (o instanceof Girl) {
               end_count ++;               
           }
        }
        System.out.println(end_count);
        if (end_count == 70) {
            RunEnvironment.getInstance().endRun();
        }
    }
}

It's working if I put above code in either boy agent or girl agent actions.

@ScheduledMethod(start = 1, interval = 1,shuffle=true)
    public void step() {
        relocation();
        update_happiness();
        endRun();

    }

    public void endRun( ) {
        Context<Object> context = ContextUtils.getContext(this);
        Query<Object> query = new PropertyEquals<Object>(context, "happy", true);
        int end_count = 0;
        System.out.println(end_count);
        for (Object o : query.query()) {
           if (o instanceof Boy) {
               end_count ++;               
           }
           if (o instanceof Girl) {
               end_count ++;               
           }
        }
        System.out.println(end_count);
        if (end_count == 70) {
            RunEnvironment.getInstance().endRun();
        }
    }

Solution

  • You can use a Query for this -- see the query answer to this question:

    Repast: how to get a particular agent set based on the specific conditions?

    You could also use the query method in a Context where you pass it a predicate where the predicate returns true if happy.

    In both of these cases, you'll need an accessor method for the private boolean happy field -- e.g.

    public boolean isHappy() {
       return happy;
    }
    

    Also in both cases, the queries return an iterable over all the agents where happy is true, rather than a collection where you could take the size to get the count. So, you'll have to iterate through that and increment a counter.

    Update:

    Your current problem is with the scheduling. You can't easily schedule a method on the ConetextBuilder as its not really part of the model, but rather used to initialize it. The easiest way to schedule what you want is to schedule it explicitly in the ContextBuilder with something like:

    RunEnvironment.getInstance().getCurrentSchedule().schedule(ScheduleParameters.createRepeating(1, 1, ScheduleParameters.LAST_PRIORITY), () -> {
                Query<Object> query = new PropertyEquals<Object>(context, "happy", true);
                int end_count = 0;
                System.out.println(end_count);
                for (Object o : query.query()) {
                    if (o instanceof Boy) {
                        end_count++;
                    }
                    if (o instanceof Girl) {
                        end_count++;
                    }
                }
                System.out.println(end_count);
                if (end_count == 70) {
                    RunEnvironment.getInstance().endRun();
                }
        });
    

    The LAST_PRIORITY should insure that all the agent behavior will have taken place before the happiness count is polled.