Simulation.java :  » Mobile » gt-mobisim » edu » gatech » lbs » sim » Java Open Source

Java Open Source » Mobile » gt mobisim 
gt mobisim » edu » gatech » lbs » sim » Simulation.java
// Copyright (c) 2009, Georgia Tech Research Corporation
// Authors:
//   Peter Pesti (pesti@gatech.edu)
//
package edu.gatech.lbs.sim;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import edu.gatech.lbs.core.FileHelper;
import edu.gatech.lbs.core.logging.Logz;
import edu.gatech.lbs.core.logging.Stat;
import edu.gatech.lbs.core.logging.Varz;
import edu.gatech.lbs.core.query.LocationBasedQuery;
import edu.gatech.lbs.core.query.QueryKey;
import edu.gatech.lbs.core.vector.IVector;
import edu.gatech.lbs.core.world.IWorld;
import edu.gatech.lbs.sim.agent.SimAgent;
import edu.gatech.lbs.sim.config.IXmlConfigInterpreter;
import edu.gatech.lbs.sim.config.NullInterpreter;
import edu.gatech.lbs.sim.config.XmlAgentsConfigInterpreter;
import edu.gatech.lbs.sim.config.XmlTimesConfigInterpreter;
import edu.gatech.lbs.sim.config.XmlWorldConfigInterpreter;
import edu.gatech.lbs.sim.scheduling.SimEventQueue;
import edu.gatech.lbs.sim.scheduling.activity.ISimActivity;
import edu.gatech.lbs.sim.scheduling.event.AccelerationChangeEvent;
import edu.gatech.lbs.sim.scheduling.event.LocationChangeEvent;
import edu.gatech.lbs.sim.scheduling.event.QueryCreateEvent;
import edu.gatech.lbs.sim.scheduling.event.QueryDeleteEvent;
import edu.gatech.lbs.sim.scheduling.event.SimEvent;
import edu.gatech.lbs.sim.scheduling.event.VelocityChangeEvent;

public class Simulation {
  // event priorities from highest to lowest priority:
  public static int priorityTraceLoadEvent = 10;
  public static int priorityAccelerationChangeEvent = 20;
  public static int priorityVelocityChangeEvent = 20;
  public static int priorityLocationChangeEvent = 20;
  public static int priorityPeriodicTraceSaveEvent = 30;
  public static int priorityQueryCreateEvent = 40;
  public static int priorityQueryRemoveEvent = 40;
  public static int priorityDrawGUIEvent = 1000;

  protected long simTime; // [ms], current time in simulation
  protected long simStartTime; // [ms], absolute time when simulation starts
  protected long simEndTime; // [ms], absolute time when simulation ends
  protected long simWarmupDuration; // [ms], time period of warmup, after which logging begins

  protected IWorld world;

  protected HashMap<Integer, SimAgent> agents; // simAgentId -> agent
  protected HashMap<Integer, List<SimAgent>> agentIndex; // segmentId --> SimAgent

  protected HashMap<QueryKey, LocationBasedQuery> queries; // simQueryKey -> query

  protected SimEventQueue eventQueue; // the simulation event queue
  protected Collection<ISimActivity> simActivities;

  public Simulation() {
    simActivities = new LinkedList<ISimActivity>();
    agents = new HashMap<Integer, SimAgent>();
  }

  public void setSimTimes(long simStartTime, long simEndTime, long simWarmupDuration) {
    this.simStartTime = simStartTime;
    this.simEndTime = simEndTime;
    this.simWarmupDuration = simWarmupDuration;
  }

  public long getSimStartTime() {
    return simStartTime;
  }

  public long getSimEndTime() {
    return simEndTime;
  }

  public long getSimWarmupDuration() {
    return simWarmupDuration;
  }

  public long getTime() {
    return simTime;
  }

  public void setTime(long simTime) {
    this.simTime = simTime;
  }

  public void setWorld(IWorld world) {
    this.world = world;
  }

  public IWorld getWorld() {
    return world;
  }

  public void setAgents(Collection<SimAgent> agents) {
    this.agents.clear();
    for (SimAgent agent : agents) {
      this.agents.put(agent.getSimAgentId(), agent);
    }
  }

  public SimAgent getAgent(int simAgentId) {
    return agents.get(simAgentId);
  }

  public Collection<SimAgent> getAgents() {
    return agents.values();
  }

  public List<SimAgent> getAgentsOnSegment(int segmentId) {
    return agentIndex.get(segmentId);
  }

  public int getAgentCount() {
    return agents.size();
  }

  public void updateAgentIndex(SimAgent agent, IVector newLocation) {
    IVector oldLocation = agent.getLocation();
    int oldSegmentId = oldLocation != null ? oldLocation.toRoadnetVector().getRoadSegment().getId() : -1;
    int newSegmentId = newLocation != null ? newLocation.toRoadnetVector().getRoadSegment().getId() : -1;

    if (oldSegmentId == newSegmentId) {
      return;
    }

    if (oldSegmentId >= 0) {
      agentIndex.get(oldSegmentId).remove(agent);
    }
    if (newSegmentId >= 0) {
      List<SimAgent> agentsOnSegment = agentIndex.get(newSegmentId);
      if (agentsOnSegment == null) {
        agentsOnSegment = new LinkedList<SimAgent>();
        agentIndex.put(newSegmentId, agentsOnSegment);
      }
      agentsOnSegment.add(agent);
    }
  }

  public void simulateAddQuery(QueryKey simKey, LocationBasedQuery query) {
    SimAgent agent = agents.get(simKey.uid);
    agent.simulateAddQuery(simKey, query);
    queries.put(simKey, query);
  }

  public void simulateRemoveQuery(QueryKey simKey) {
    SimAgent agent = agents.get(simKey.uid);
    queries.remove(simKey);
    agent.simulateRemoveQuery(simKey);
  }

  public SimEventQueue getQueue() {
    return eventQueue;
  }

  public void addEvent(SimEvent event) {
    eventQueue.addEvent(event);
  }

  public void addActivity(ISimActivity activity) {
    simActivities.add(activity);
  }

  /**
   * Loads the simulation's configuration parameters from the given xml file.
   */
  public void loadConfiguration(String configFilename) {
    try {
      InputStream in = FileHelper.openFileOrUrl(configFilename);
      String contents = FileHelper.getContentsFromInputStream(in);
      in.close();

      loadConfigurationFromSpecification(contents.toString());
    } catch (IOException e) {
      Logz.println("" + e);
      System.exit(-1);
    }
  }

  /**
   * Loads the simulation's configuration parameters from the given xml text.
   */
  public void loadConfigurationFromSpecification(String configText) {
    simActivities.clear();

    try {
      Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(configText)));
      Element rootNode = doc.getDocumentElement();

      Collection<IXmlConfigInterpreter> interpreters = getConfigInterpreters();
      for (IXmlConfigInterpreter interpreter : interpreters) {
        Logz.println("Config interpreter: " + interpreter.getClass().getSimpleName());
        interpreter.initFromXmlElement(rootNode, this);
      }

    } catch (IOException e) {
      Logz.println("IOException");
      System.exit(-1);
    } catch (SAXParseException e) {
      Logz.println("Parsing error on line " + e.getLineNumber());
      Logz.println(" " + e.getMessage());
      System.exit(-1);
    } catch (SAXException e) {
      Logz.println("SAXException");
      Exception x = e.getException();
      ((x == null) ? e : x).printStackTrace();
      System.exit(-1);
    } catch (ParserConfigurationException e) {
      Logz.println("ParserConfigurationException");
      System.exit(-1);
    }
    Logz.println("Configuration loaded.\n");
  }

  /**
   * Override this method to customize what events are recognized as loadable from a trace file.
   */
  protected List<Class<?>> getLoadableTraceSimEvents() {
    List<Class<?>> loadableEvents = new LinkedList<Class<?>>();

    loadableEvents.add(LocationChangeEvent.class);
    loadableEvents.add(VelocityChangeEvent.class);
    loadableEvents.add(AccelerationChangeEvent.class);

    loadableEvents.add(QueryCreateEvent.class);
    loadableEvents.add(QueryDeleteEvent.class);

    return loadableEvents;
  }

  /**
   * Initializes the simulation.
   * This method is used to put the simulation in an initial, pre-run state, based on
   * the previously loaded configuration.
   */
  public void initSimulation() {
    eventQueue = new SimEventQueue();
    eventQueue.setLoadableSimEvents(getLoadableTraceSimEvents());

    agentIndex = new HashMap<Integer, List<SimAgent>>();
    queries = new HashMap<QueryKey, LocationBasedQuery>();

    simTime = simStartTime;

    for (ISimActivity activity : simActivities) {
      Logz.println("Scheduling activity: " + activity.getClass().getSimpleName());
      activity.scheduleOn(this);
    }
  }

  /**
   * Cleans up after the simulation.
   */
  public void endSimulation() {
    for (ISimActivity activity : simActivities) {
      activity.cleanup();
    }
  }

  /**
   * Runs the simulation from start to finish.
   */
  public void runSimulation() {
    // simulation loop:
    Logz.println("Running simulation... ");
    long wallStartTime = System.nanoTime();
    long eventsProcessed = 0;
    while ((simTime = eventQueue.getNextEventTime()) >= 0 && simTime < simEndTime) {
      eventQueue.executeNextEvent();
      eventsProcessed++;

      if (eventsProcessed % 1000000 == 1) {
        Logz.println(" Queue has " + eventQueue.size() + " events, simTime= " + Stat.round(eventQueue.getNextEventTime() / (1000 * 60.0), 1) + " min, wallTime= " + Stat.round((System.nanoTime() - wallStartTime) / (1e9 * 60.0), 1) + " min");
      }
    }
    Varz.set("eventsProcessed", eventsProcessed); // for the whole simulation, including warmup
    Varz.set("wallRunTime", (System.nanoTime() - wallStartTime) / 1e9); // [sec], for the whole simulation, including warmup
    double simToWallSpeedRatio = (simEndTime - simStartTime) / ((System.nanoTime() - wallStartTime) / 1e6);
    Logz.println(" Speed: " + Stat.round(simToWallSpeedRatio, 1) + "x realtime (" + Stat.round(simToWallSpeedRatio, 1) + " simulated minutes/wall minute)");
    Logz.println("DONE.");

    Varz.set("simRunTime", (simEndTime - simStartTime - simWarmupDuration) / 1000.0); // [sec], without warmup
    Varz.set("agentCount", agents.size());
  }

  /**
   * Special-purpose simulation runner, that executes quietly and without logging, up to the exact
   * time specified. The primary purpose is to run the mobility-models, so the agent locations are
   * available immediately after the specified point in time.
   */
  public void runSimulationTo(long simEndTime) {
    while ((simTime = eventQueue.getNextEventTime()) >= 0 && simTime <= simEndTime) {
      eventQueue.executeNextEvent();
    }
    simTime = simEndTime;
  }

  /**
   * Provides the ordered set of configuration interpreters, which can understand a simulation
   * configuration file.
   * Override this method to customize how a config xml is interpreted & how the simulation is set up.
   */
  protected Collection<IXmlConfigInterpreter> getConfigInterpreters() {
    Collection<IXmlConfigInterpreter> interpreters = new LinkedList<IXmlConfigInterpreter>();
    interpreters.add(new XmlTimesConfigInterpreter());
    interpreters.add(new XmlWorldConfigInterpreter());
    interpreters.add(new XmlAgentsConfigInterpreter());
    interpreters.add(new NullInterpreter());
    return interpreters;
  }

  /**
   * Runs the simulation with the configuration file given as first argument.
   */
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage:");
      System.out.println("  java " + Simulation.class + " config.xml");
      return;
    }

    Simulation sim = new Simulation();
    sim.loadConfiguration(args[0]);
    sim.initSimulation();
    sim.runSimulation();
    sim.endSimulation();
  }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.