1

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();
        }
    }
Jack
  • 1,339
  • 1
  • 12
  • 31

1 Answers1

3

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.

Nick Collier
  • 1,786
  • 9
  • 10
  • Hi I actually want to know how to schedule a global action method/procedure that is outside of each type of agent's method. Like this one, I have two types of agents (boys and girls). I want to count the total number of persons who are happy and this method does not need to iterate through every boy and girl agent, but to be performed at the global level right after all agents have made an action. – Jack Aug 21 '19 at 05:55
  • thanks it's working. But this is not modular in my eyes. Is there more structural way to schedule the global behavior using method()? Eventually, I want a structure with some methods() for particular agents and some methods for global behaviors and all of them follows a particular execution sequence. How to achieve this? thanks – Jack Aug 22 '19 at 03:11
  • I haven't done this in a while, but I think it should work. Create a custom context by extending DefaultContext and in your ContextBuilder ignore the passed in Context, create, fill and return yours. Use the schedule annotations on methods in your custom context for the global behavior. You could also move the "happy" code above to a separate class that implements IAction and schedule that manually as above. – Nick Collier Aug 23 '19 at 13:20
  • would you mind if I open a new question specifically addressing this issue? this is quite important for me to build my agent-based model. – Jack Aug 26 '19 at 01:50