All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.agentsoz.bdimatsim.Utils Maven / Gradle / Ivy

The newest version!
package io.github.agentsoz.bdimatsim;

/*
 * #%L
 * BDI-ABM Integration Package
 * %%
 * Copyright (C) 2014 - 2017 by its authors. See AUTHORS file.
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import io.github.agentsoz.util.Location;
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.network.Node;
import org.matsim.api.core.v01.population.*;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.network.NetworkUtils;
import org.matsim.core.population.PopulationUtils;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.core.utils.geometry.GeometryUtils;

import com.vividsolutions.jts.geom.LineString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Extends the original withinday controler listener so that 
 * the updated engine can be initialised here
 * @author QingyuChen
 *
 */
public final class Utils {
	private Utils(){} // do not instantiate. kai, mar'15

	@SuppressWarnings("unused")
	private static final Logger log = LoggerFactory.getLogger(Utils.class);

    /**
     * Returns a map of agent IDs to specified attributes
     * Input should be of form given below:
     * 
{@code
     * 
     *   
     *     value
     *   
     *   
     *     ...
     *   
     * 
     * }
* * @param scenario MATSim scenario reference * @return the map or else an empty map if no BDI agent types were found */ public static Map> getAgentsFromMATSimPlansFile(Scenario scenario ) { Map> map = new LinkedHashMap<>(); for (Person person : scenario.getPopulation().getPersons().values()) { // Get all person attributes // Below seems the only ugly way to get attributes list out String args = person.getAttributes().toString(); List initArgs = new ArrayList<>(); Pattern logEntry = Pattern.compile("\\{\\s*key\\s*=\\s*(.*?)\\s*;\\s*object\\s*=\\s*(.*?)\\s*\\}"); Matcher matchPattern = logEntry.matcher(args); while(matchPattern.find()) { String key = matchPattern.group(1); String val = matchPattern.group(2); initArgs.add(new String[]{key,val}); } // Also get all activities and locations for (PlanElement element : person.getSelectedPlan().getPlanElements()) { if (element instanceof Activity) { String type = ((Activity)element).getType(); String xy = String.format("%f,%f", ((Activity)element).getCoord().getX(), ((Activity)element).getCoord().getY()); initArgs.add(new String[]{type,xy}); } element.toString(); } map.put(person.getId().toString(), initArgs); } return map; } /** * Deprecated. Use {@link #getAgentsFromMATSimPlansFile} instead. * Example usage is in {@code examples/bushfire/scenarios/mount-alexander-shire/maldon-100-with-emergency-vehicles} * @param scenario * @return */ @Deprecated public static List getBDIAgentIDs( Scenario scenario ) { // this goes through all matsim agents, ignores the stub agents, and returns as many of those agent ids as the // bdi module wants as bdi agents (the remaining agents will, I guess, remain normal matsim agents). kai, mar'15 List bDIagentIDs = new ArrayList<>(); Id stubId = Id.createPersonId("StubAgent"); for ( Id id : scenario.getPopulation().getPersons().keySet() ) { if(id.compareTo(stubId) == 0){ continue; } bDIagentIDs.add(id.toString()); } // assume in popgen you did something like // person.getAttributes().putAttribute("isBdiAgent", true/false ) ; // you could now retrieve it via // person.getAttributes().getAttribute("isBdiAgent") ; // kai, dec'17 return bDIagentIDs; } final static double[] computeBoundingBox(Collection links) { double[] boundingBox0 = {Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY,Double.NEGATIVE_INFINITY,Double.NEGATIVE_INFINITY }; for ( Link link : links ) { final double xx = link.getCoord().getX(); final double yy = link.getCoord().getY(); boundingBox0[0] = Math.min( boundingBox0[0], xx ) ; boundingBox0[1] = Math.min( boundingBox0[1], yy ) ; boundingBox0[2] = Math.max( boundingBox0[2], xx ) ; boundingBox0[3] = Math.max( boundingBox0[3], yy ) ; } return boundingBox0 ; } final static double[] generateLinkCoordsAsArray(Collection links) { double[] array = new double[links.size()*2]; int ii = -1 ; for ( Link link : links ) { ii++ ; final double xx = link.getCoord().getX(); final double yy = link.getCoord().getY(); array[ii*2] = xx ; array[ii*2+1] = yy; } return array ; } final static String[] createFlatLinkIDs(Collection> allLinkIDs) { String[] flatLinkIDList = new String[allLinkIDs.size()]; int j = 0; for(Id i :allLinkIDs){ flatLinkIDList[j] = i.toString(); j ++; } return flatLinkIDList; } public static List findIntersectingLinks(Link link, Network network) { return GeometryUtils.findIntersectingLinks(link, network) ; } public static List findIntersectingLinks(LineString lineString, Network network) { return GeometryUtils.findIntersectingLinks(lineString, network) ; } public static Link getNearestLink(Network network, Coord coord) { return NetworkUtils.getNearestLink(network, coord) ; } public static Link getNearestLinkExactly( Network network, Coord coord ) { return NetworkUtils.getNearestLinkExactly(network, coord) ; } public static Node getNearestNode(Network network, Coord coord) { return NetworkUtils.getNearestNode(network, coord) ; } public static Collection getNearestNodes(Network network, Coord coord, double distance) { return NetworkUtils.getNearestNodes(network, coord, distance) ; } public static void populationWithBDIAttributeExample() { { Config config = ConfigUtils.createConfig() ; Scenario scenario = ScenarioUtils.createScenario( config ) ; Population pop = scenario.getPopulation() ; PopulationFactory pf = pop.getFactory() ; for ( int ii=0 ; ii<10 ; ii++ ) { Person person = pf.createPerson( Id.createPersonId(ii)) ; person.getAttributes().putAttribute("isBDIAgent", true ) ; pop.addPerson(person); } PopulationUtils.writePopulation(pop, "pop.xml"); } { Config config = ConfigUtils.createConfig() ; config.plans().setInputFile("pop.xml"); Scenario scenario = ScenarioUtils.loadScenario( config ) ; for ( Person person : scenario.getPopulation().getPersons().values() ) { final String attribute = (String) person.getAttributes().getAttribute("isBDIAgent"); System.out.println( "id=" + person.getId() + "; isBdi=" + attribute ) ; } } } static void parseAdditionalArguments(String[] args, Config config) { for (int i = 1; i < args.length; i++) { switch (args[i]) { case MATSimModel.MATSIM_OUTPUT_DIRECTORY_CONFIG_INDICATOR: if (i + 1 < args.length) { i++; log.info("setting matsim output directory to " + args[i] ); config.controler().setOutputDirectory( args[i] ); } break; case MATSimModel.eGlobalStartHhMm: if (i + 1 < args.length) { i++; double secs = MATSimModel.convertTimeToSeconds(args[i].replace(":", "")); config.qsim().setStartTime( (secs) > 3600 ? secs-3600 : secs ); log.info("setting matsim start time to " + args[i]); } break; default: throw new RuntimeException("unknown config option") ; } } } static void penaltyMethod2(Geometry fire, Geometry buffer, double bufferWidth, Map, Double> penaltyFactorsOfLinks, Scenario scenario ) { // Starting thoughts: // * Could make everything very expensive in buffer + fire, they find the fastest path out. This may, however, // be through the fire. // * Could make everything very expensive in fire, and factor of 10 less expensive in buffer. Then they would // find fastest way out of fire, then fastest way out of buffer. // * Problem is that fastest way out of buffer may entail getting or remaining close to the fire. // // What about // // deltaHeight = (bufferWidth-distanceToFireToNode)^2 - (bufferWidth-distanceToFireFromNode)^2, // // e.g. fromNode close to fire = large second term, toNode close to outside = small first term, // deltaHeight negative (since we go downhill). // // This should look like the Drakensberg, i.e. // * high and flat in the fire // * steep outside the fire but close ("distance ..." small) // * increasingly more flat farther away // // (Actually, the "Drakensberg" is quite misleading, since this is the shape of the 1st derivative. The // actual slope thus is // * very high in the fire // * quickly becoming less steep outside the fire (which is to make "away and back in" cheaper than // "in and back out") // // Now use deltaHeight, when positive, as penalty factor (times travel time). This should penalize "wiggling" // close to the fire more than wiggling farther away. // // In the fire the penalty factor then is bufferWidth^2. // // Links where only one node is in the fire need to be treated as in the fire, otherwise we erode the // sharp edge. // yy in the below formulation, factor could be "zero". Hedge against that (maybe // even in utility code). // yy Am just doing inLinks. I think that that should be enough ... // yy Should be able to extract the "height" function ... for ( Node node : scenario.getNetwork().getNodes().values() ) { Point point = GeometryUtils.createGeotoolsPoint(node.getCoord()); if (fire.contains(point)) { log.debug("node {} is IN fire area ", node.getId()); // in links for (Link link : node.getInLinks().values()) { penaltyFactorsOfLinks.put( link.getId(), bufferWidth*bufferWidth) ; } } else if ( buffer.contains(point) ) { log.debug("node {} is IN buffer", node.getId()); // in links for (Link link : node.getInLinks().values()) { Point fromPoint = GeometryUtils.createGeotoolsPoint(link.getFromNode().getCoord()); if (fire.contains(fromPoint)) { // coming from fire penaltyFactorsOfLinks.put(link.getId(), bufferWidth*bufferWidth); // treat as "in fire". // (yyyy probably too drastic; will avoid long links leading out of the fire) } else if (buffer.contains(fromPoint)) { final double heightAtFromNode = Math.pow(bufferWidth-fromPoint.distance(fire),2.) ; final double heightAtToNode = Math.pow( bufferWidth - point.distance(fire),2.) ; if ( heightAtToNode>heightAtFromNode) { penaltyFactorsOfLinks.put( link.getId(), heightAtToNode-heightAtFromNode ) ; } } else { // coming from out final double heightAtToNode = Math.pow( bufferWidth - point.distance(fire),2.) ; penaltyFactorsOfLinks.put(link.getId(), heightAtToNode ) ; // (height out will always be zero, and so height in will always be larger) } } } } } static void penaltyMethod1(Geometry fire, Geometry buffer, Map, Double> penaltyFactorsOfLinks, Scenario scenario) { // risk increasing are essentially forbidden: final double buffer2fire = 1000. ; final double out2buffer = 500 ; final double out2fire = out2buffer + buffer2fire ; final double buffer2bufferGettingCloser = 500. ; // risk reducing is ok, we just want to keep them short: final double fire2buffer = 20. ; final double fire2out = 10. ; final double buffer2out = 5. ; final double buffer2bufferGettingAway = 5. ; // in fire essentially forbidden: final double fire2fire = 1000. ; for ( Node node : scenario.getNetwork().getNodes().values() ) { Point point = GeometryUtils.createGeotoolsPoint(node.getCoord()); if (fire.contains(point)) { log.debug("node {} is IN fire area " + node.getId()); // outlinks: for (Link link : node.getOutLinks().values()) { Point point2 = GeometryUtils.createGeotoolsPoint(link.getToNode().getCoord()); if (fire.contains(point2)) { penaltyFactorsOfLinks.put(link.getId(), fire2fire ); // fire --> fire } else if (buffer.contains(point2)) { penaltyFactorsOfLinks.put(link.getId(), fire2buffer ); // fire --> buffer } else { penaltyFactorsOfLinks.put(link.getId(), fire2out ); // fire --> out } } // in links for (Link link : node.getInLinks().values()) { Point point2 = GeometryUtils.createGeotoolsPoint(link.getToNode().getCoord()); if (fire.contains(point2)) { penaltyFactorsOfLinks.put(link.getId(), fire2fire ); // fire <-- fire } else if (buffer.contains(point2)) { penaltyFactorsOfLinks.put(link.getId(), buffer2fire ); // fire <-- buffer } else { penaltyFactorsOfLinks.put(link.getId(), out2fire ); // fire <-- out } } } else if ( buffer.contains(point) ) { log.debug("node {} is IN buffer", node.getId()); // outlinks: for (Link link : node.getOutLinks().values()) { Point point2 = GeometryUtils.createGeotoolsPoint(link.getToNode().getCoord()); if (fire.contains(point2)) { penaltyFactorsOfLinks.put(link.getId(), buffer2fire ); // buffer --> fire } else if (buffer.contains(point2)) {// buffer --> buffer final double distanceFromNode = point.distance(fire) ; final double distanceToNode = point2.distance(fire) ; if ( distanceToNode > distanceFromNode ) { penaltyFactorsOfLinks.put(link.getId(), buffer2bufferGettingAway); } else { penaltyFactorsOfLinks.put(link.getId(), buffer2bufferGettingCloser); } } else { penaltyFactorsOfLinks.put(link.getId(), buffer2out ); // buffer --> out } } // in links for (Link link : node.getInLinks().values()) { Point point2 = GeometryUtils.createGeotoolsPoint(link.getFromNode().getCoord()); if (fire.contains(point2)) { penaltyFactorsOfLinks.put(link.getId(), fire2buffer); // buffer <-- fire } else if (buffer.contains(point2)) { // buffer <-- buffer final double distanceToNode = point.distance(fire) ; final double distanceFromNode = point2.distance(fire) ; if ( distanceToNode > distanceFromNode ) { penaltyFactorsOfLinks.put(link.getId(), buffer2bufferGettingAway); } else { penaltyFactorsOfLinks.put(link.getId(), buffer2bufferGettingCloser); } } else { penaltyFactorsOfLinks.put(link.getId(), out2buffer); // buffer <-- out } } } } // yyyy above is start, but one will need the full "potential" approach from Gregor. Otherwise, you cut a link // in two and get a different answer. Which should not be. kai, dec'17 } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy