大家好,我已经制作了一个基于代理的模型。代理可以随机移动并使用A *算法移动到地点的位置。有两个主要的集合1)到达队列(arraylist)和2)主要代理(arraylist)。最初将所有代理放入到达队列中,将代理以特定时间间隔放入模拟中,例如,每400个模拟步骤100个代理商)。
我得到的问题是,每当我将代理人数从3000+增加到模拟开始滞后时。我还使用Java 2D库来显示代理的2D数组。 Bellow ive添加了我的应用程序的visualVM的屏幕截图,显示了被调用最多的方法(CPU时间)。
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;
}
}
答案 0 :(得分:1)
这是基于时间步长的基于代理的建模的特征。由于n个代理中的每一个原则上可以与任何其他代理进行交互,因此在每个时间步都有n 选择 2个交互进行评估,这些交互增长为O(n 2 )。您的基本选择是:1)保持代理人数量小; 2)增加你的时间步长(这通常会引入建模错误,因为更粗略地估计正在发生的事情); 3)“本地化”交互的范围(对于你的建模,这可能是也可能不是现实的);或者4)重写你的模型以使用discrete event scheduling而不是时间步进。