模拟滞后

时间:2015-04-01 20:34:28

标签: java performance simulation agent-based-modeling

大家好,我已经制作了一个基于代理的模型。代理可以随机移动并使用A *算法移动到地点的位置。有两个主要的集合1)到达队列(arraylist)和2)主要代理(arraylist)。最初将所有代理放入到达队列中,将代理以特定时间间隔放入模拟中,例如,每400个模拟步骤100个代理商)。

我得到的问题是,每当我将代理人数从3000+增加到模拟开始滞后时。我还使用Java 2D库来显示代理的2D数组。 Bellow ive添加了我的应用程序的visualVM的屏幕截图,显示了被调用最多的方法(CPU时间)。

ScreenShot Here

Model code:

package Model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;




import Model.Grid;
import Agent.*;

public class Model extends AbstractModel implements Runnable{

    private Grid grid;
    private Constants modelConstants;
    private RandomGenerator randGenerator;
    private GridMapLayout Maplayout;
    private RoomController roomController;
    private AgentFactory agentFacory;
    private Statistics stats;

    private ArrayList<AbstractAgent> agents;
    private Queue<Patient> patientArrivalQueue;
    private List<Patient> dischargedPatients;
    private Queue<Doctor> doctorsQueue;
    private Queue<Nurse> nursesQueue;

    private int patientPopulation;
    private int doctorPopulation;
    private int receptionNurses;
    private int aNeNurses;
    private int ward1Nurses;
    private int ward2Nurses;
    private int ward3Nurses;

    private boolean running;
    private int currentSimCycle;
    private int simArrivalCounter;

    public CTimer timer = new CTimer();

    public Model() {
        super();
        this.grid = new Grid(150, 150); //if no given size grid uses default size 
        this.modelConstants = new Constants();
        this.randGenerator = new RandomGenerator(modelConstants.getSEED());
        this.Maplayout = new GridMapLayout(this);
        this.roomController = new RoomController(this);
        this.agentFacory = new AgentFactory(this);
        this.stats = new Statistics(this);
        this.currentSimCycle = 0;
        this.simArrivalCounter = 0;

        this.agents = new ArrayList<AbstractAgent>();
        this.patientArrivalQueue = new LinkedList<Patient>();
        this.dischargedPatients = new LinkedList<Patient>();
        this.doctorsQueue = new LinkedList<Doctor>();
        this.nursesQueue =  new LinkedList<Nurse>();

        loadModelConstants();
        loadMapLayout();
        roomController.readyRoomCollections();
        createAllAgents();
        loadDoctorsInRooms();
        loadNursesInRooms();
        loadNextPatientArrival();
//      randomlyPopulateGrid();
        stats.updateStatistics();
        stats.setDataValid(false);

//      Room entrance = roomController.getAllRooms().get("Entrance");
//      Room reception = roomController.getAllRooms().get("Reception");
//      Room aNe = roomController.getAllRooms().get("A&E");
//      Room ward1 = roomController.getAllRooms().get("Ward 1");
//      Room ward2 = roomController.getAllRooms().get("Ward 2");
//      Room ward3 = roomController.getAllRooms().get("Ward 3");
//      Room canteen = roomController.getAllRooms().get("Canteen");
//      Room toilet = roomController.getAllRooms().get("Toilet");
//      
//      System.out.println(toilet);

//      System.out.println(entrance.getDoorLocations().size());
//      System.out.println("Reception: " + reception.getRoomLocations().size());
//      System.out.println("A&E: " + aNe.getRoomLocations().size());
//      System.out.println("Ward 1: " + ward1.getRoomLocations().size());
//      System.out.println("Ward 2: " + ward2.getRoomLocations().size());
//      System.out.println("Ward 3: " + ward3.getRoomLocations().size());
//      System.out.println("Canteen: " + canteen.getRoomLocations().size());
//      System.out.println("Toilet: " + toilet.getRoomLocations().size());
    }

    public void loadModelConstants() {
        this.patientPopulation = modelConstants.getPatientPopulation();
        this.doctorPopulation = modelConstants.getDoctorPopulation();
        this.receptionNurses = modelConstants.getReceptionNursePopulation();
        this.aNeNurses =  modelConstants.getaNeNursePopulation();
        this.ward1Nurses =  modelConstants.getWard1NursePopulation();
        this.ward2Nurses =  modelConstants.getWard2NursePopulation();
        this.ward3Nurses =  modelConstants.getWard3NursePopulation();

//      System.out.println(this.patientPopulation);
//      System.out.println(this.doctorPopuation);
//      System.out.println(this.nursePopulation);
        System.out.println("Loaded Model Constants");
    }

    public void loadMapLayout() {
        Maplayout.loadMapImage();
        Maplayout.loadRGBfileAndRooms();
        Maplayout.readPixels();
        Maplayout.addMapLayout();
//      layout.printCells();
        System.out.println("Loaded Map Layout");
    }

    public void createAllAgents() {
        ArrayList<Patient> tempPatient = new ArrayList<Patient>();
        ArrayList<Doctor> tempDoctor = new ArrayList<Doctor>();
        ArrayList<Nurse> tempNurse = new ArrayList<Nurse>();

        int totalNurses = + (modelConstants.getReceptionNursePopulation()
                          +  modelConstants.getaNeNursePopulation()
                          +  modelConstants.getWard1NursePopulation()
                          +  modelConstants.getWard2NursePopulation()
                          +  modelConstants.getWard3NursePopulation()
                            );

        int noOfAgentLeftToCreate = modelConstants.getPatientPopulation() + modelConstants.getDoctorPopulation() 
                                  + totalNurses;

        while(tempPatient.size() != this.patientPopulation) {
            Patient newPatient = (Patient) this.agentFacory.createAgent("PATIENT", noOfAgentLeftToCreate);
            tempPatient.add(newPatient);
            noOfAgentLeftToCreate--;
        }

        while(tempDoctor.size() != this.doctorPopulation) {
            Doctor newDoctor = (Doctor)this.agentFacory.createAgent("DOCTOR", noOfAgentLeftToCreate);
            tempDoctor.add(newDoctor);
            noOfAgentLeftToCreate--;
        }

        while(tempNurse.size() != totalNurses) {
            Nurse newNurse = (Nurse)this.agentFacory.createAgent("NURSE", noOfAgentLeftToCreate);
            tempNurse.add(newNurse);
            noOfAgentLeftToCreate--;
        }

        this.patientArrivalQueue.addAll(tempPatient); //Add total patients to arrive queue 
        this.doctorsQueue.addAll(tempDoctor); //Add all doctors to the doctors agent collection
        this.nursesQueue.addAll(tempNurse); //Add all nurses to the nurse agent collection
        System.out.println("All agents created");
    }

    public void loadDoctorsInRooms() {
        for(Map.Entry<String, Room> pair : roomController.getDoctorRooms().entrySet()) {
            String key = pair.getKey();
            Room value = pair.getValue();

            if(value.isRoomEmpty()) {
                Doctor newDoctor = doctorsQueue.remove();
                Location randFreeRoomLoc = value.getRandomFreeRoomLocation();
                grid.moveAgentToNewLocation(newDoctor, newDoctor.getLocation(), randFreeRoomLoc);
                newDoctor.setLocation(randFreeRoomLoc);

                newDoctor.setAllocatedRoom(value);
                newDoctor.getAgentController().setCurrentRoom(value);
                newDoctor.getAgentController().setTargetRoom(value);
                //Tell the room that this agent is now a occupant of the room
                value.getCurrentOccupantsMap().put(newDoctor.getAgentID(), newDoctor);
                agents.add(newDoctor);
            }
        }
        Room aNeRoom = roomController.getAllRooms().get("A&E");
        if(aNeRoom.isRoomEmpty()) {
            Doctor aNeDoc = doctorsQueue.remove();
            Location randFreeRoomLoc = aNeRoom.getRandomFreeRoomLocation();
            grid.moveAgentToNewLocation(aNeDoc, aNeDoc.getLocation(), randFreeRoomLoc);
            aNeDoc.setLocation(randFreeRoomLoc);

            aNeDoc.setAllocatedRoom(aNeRoom);
            aNeDoc.getAgentController().setCurrentRoom(aNeRoom);
            aNeDoc.getAgentController().setTargetRoom(aNeRoom);
            //Tell the room that this agent is now a occupant of the room
            aNeRoom.getCurrentOccupantsMap().put(aNeDoc.getAgentID(), aNeDoc);
            agents.add(aNeDoc);
        }

        System.out.println("All Doctors are placed");
    }

    public void loadNursesInRooms() {
        HashMap<String, Room> nurseRooms = new HashMap<String, Room>();
        nurseRooms.putAll( roomController.getAllRooms());
        nurseRooms.remove("Toilet");
        nurseRooms.remove("Canteen");
        nurseRooms.remove("Staff");
        nurseRooms.remove("Corridor");
        nurseRooms.remove("ISOL Entrance");
        nurseRooms.remove("Entrance");
        nurseRooms.remove("Exit");

        for(Map.Entry<String, Room> drPair :  roomController.getDoctorRooms().entrySet()) {
            String drKey = drPair.getKey();
            Room drValue = drPair.getValue();
            for(Map.Entry<String, Room> isolPair :  roomController.getIsolRooms().entrySet()) {
                String isolKey = isolPair.getKey();
                Room isolValue = isolPair.getValue();

                if(nurseRooms.containsKey(drKey)) {
                    nurseRooms.remove(drKey);
                }
                if(nurseRooms.containsKey(isolKey)) {
                    nurseRooms.remove(isolKey);
                }
            }
        }

        for(Map.Entry<String, Room> pair : nurseRooms.entrySet()) {
            String key = pair.getKey();
            Room value = pair.getValue();

            int noOfNurseToCreate = 0;

            if(key.contentEquals("Reception")) {
                noOfNurseToCreate = modelConstants.getReceptionNursePopulation();
            }
            else if(key.contentEquals("A&E")) {
                noOfNurseToCreate = modelConstants.getaNeNursePopulation();
            }
            else if(key.contentEquals("Ward 1")) {
                noOfNurseToCreate = modelConstants.getWard1NursePopulation();
            }
            else if(key.contentEquals("Ward 2")) {
                noOfNurseToCreate = modelConstants.getWard2NursePopulation();
            }
            else if(key.contentEquals("Ward 3")) {
                noOfNurseToCreate = modelConstants.getWard3NursePopulation();
            }

            for(int i=0; i != noOfNurseToCreate; i++) {
                Nurse newNurse = nursesQueue.remove();
                Location roomLocation = value.getRandomFreeRoomLocation();
                grid.moveAgentToNewLocation(newNurse, newNurse.getLocation(), roomLocation);
                newNurse.setLocation(roomLocation);

                newNurse.setAllocatedRoom(value);
                newNurse.getAgentController().setCurrentRoom(value);
                newNurse.getAgentController().setTargetRoom(value);
                //Tell the room controller that this agent is now an occupant of the room
                value.getCurrentOccupantsMap().put(newNurse.getAgentID(), newNurse);
                agents.add(newNurse);
            }
        }

        System.out.println("All Nurses are placed");
    }

    public void loadNextPatientArrival() {
        if(this.simArrivalCounter == 0) {
            int removeThemPatients = 0;
            //If there are more patients in the arrival queue then the specified simPatientarrival rate then 
            //remove the specified amount of patients per simPatient arrival rate 
            if(patientArrivalQueue.size() >= modelConstants.getPatientArrivalRate()) { 
                removeThemPatients = modelConstants.getPatientArrivalRate();
            }
            //Number of patient to place on the grid is less then the patient arrival rate, just place the rest into the entrance
            else {
                removeThemPatients = patientArrivalQueue.size();
            }

            Room reception = roomController.getAllRooms().get("Reception");
            Room aNe = roomController.getAllRooms().get("A&E");

            for(int i=removeThemPatients; i !=0; i--) { 
                Patient nextPatient = patientArrivalQueue.remove();
//              if(nextPatient.getPatientType().contains("Normal") & nextPatient.getLocation() != null) {
                if(grid.checkEmptyAt(nextPatient.getLocation())) {
                    grid.placeAgent(nextPatient, nextPatient.getLocation());
                    agents.add(nextPatient);
                }
                else {
                     patientArrivalQueue.add(nextPatient);
                }
//              }
            }

            //IMPORTANT need to reset the simArrivalCounter back to the specified count
            this.simArrivalCounter = this.modelConstants.getSimArrivalCounter();
            //              System.out.println("More patients have arrived");
        }
    }

    public void removeDischargedPatients() {
        //Just iterate through the exit room door locations and remove 
        //the the discharged patients waiting there into the patient discharge list
        Room exit = roomController.getAllRooms().get("Exit");
        for(Location loc : exit.getDoorLocations()) {
            if(!grid.checkEmptyAt(loc)) {
                Patient dischargedPatient = (Patient) grid.getAgentAtLocation(loc);
                grid.clearLocationAt(loc);
                agents.remove(dischargedPatient);
                dischargedPatients.add(dischargedPatient);
            }
        }
    }

    public void randomlyPopulateGrid() {
        Room reception =  roomController.getAllRooms().get("Reception");
        while(!this.patientArrivalQueue.isEmpty()) {
            Location freeLoc = reception.getRandomFreeRoomLocation();
            Patient nextPatient = this.patientArrivalQueue.remove();
            grid.moveAgentToNewLocation(nextPatient, nextPatient.getLocation(), freeLoc);
            nextPatient.setLocation(freeLoc);

            nextPatient.getAgentController().setCurrentRoom(reception);
            nextPatient.getAgentController().setTargetRoom(reception);
            agents.add(nextPatient);
        }

        System.out.println("Populate Grid");
    }

    public void simulateCycles(int maxCycles) {
        for(int i=0; i != maxCycles; i++) {
            loadNextPatientArrival();
            removeDischargedPatients();
            updateAgents();
            stats.updateStatistics();
            stats.setDataValid(false);


            this.currentSimCycle++;
            this.simArrivalCounter--;
        }

        notifyViews();
    }

    public void updateAgents() {
//      Iterator<AbstractAgent> it = agents.iterator();
//      while(it.hasNext()) {
//          AbstractAgent nextAgent = it.next();
//          nextAgent.act();
//      }
        for(AbstractAgent agent : agents) {
            agent.act();
        }
    }

    @Override
    public void startSimulation() {
        new Thread(this).start();
        System.out.println("Running Simulation");
    }

    @Override
    public void stopSimulation() {
        running = false;
        System.out.println("Simulation has stoped");
    }

    @Override
    public void resetSimulation() {
        System.out.println("Model Constant set to default");
    }

    public void run() {
        running = true;
//      int loop = 0;
        while(running) {
//          System.out.println("loop: "+ loop);
//          loop++;
            simulateCycles(1);
            try {
                Thread.sleep(5);
            } 
            catch (Exception e) {

            }
        }
    }

    public Grid getGrid() {
        return grid;
    }

    public List<AbstractAgent> getAgentsCollection() {
        return agents;
    }

    public GridMapLayout getGridMayLayout() {
        return Maplayout;
    }

    public RoomController getRoomController() {
        return roomController;
    }

    public Constants getModelConstants() {
        return modelConstants;
    }

    public RandomGenerator getRandGenerator() {
        return randGenerator;
    }

    public int getCurrentSimCycle() {
        return currentSimCycle;
    }

    public Statistics getStats() {
        return stats;
    }
}

1 个答案:

答案 0 :(得分:1)

这是基于时间步长的基于代理的建模的特征。由于n个代理中的每一个原则上可以与任何其他代理进行交互,因此在每个时间步都有n 选择 2个交互进行评估,这些交互增长为O(n 2 )。您的基本选择是:1)保持代理人数量小; 2)增加你的时间步长(这通常会引入建模错误,因为更粗略地估计正在发生的事情); 3)“本地化”交互的范围(对于你的建模,这可能是也可能不是现实的);或者4)重写你的模型以使用discrete event scheduling而不是时间步进。