Getting Started
The Java API of PLANit is very versatile and highly configurable. It allows you to setup a project which in turn can run one or more traffic assignments based on different networks, zonings, and demands.
If you are not interested in conducting traffic assignment, but are looking on how to perform (network) data format conversions, please have a look at the related examples section
Each traffic assignment can be configured separately, including the outputs it should generate.
In this getting started we will take you through the process of setting up an input file and constructing your first PLANit assignment run.
Prerequisites
Make sure you have access to the PLANit-Java sources and/or compiled classes via the PLANitXXXX.jar
, as per
the Installation guide
My first Application!
Let’s create our very first PLANit-Java traffic assignment application.
Creating inputs
PLANit requires a network, demands, and zoning structure as inputs to be able to construct a valid transport network.
Let’s provide all three in the same XML file. Our XML file is based on the Default PLANit Data Format.
Copy the contents of the XML snippet below and save them somewhere on disk, e.g., for Windows "c:\Users\Public\planit_test\"
,
as - for example - "planit_input.xml"
.
<PLANit xmlns:gml="http://www.opengis.net/gml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- Demand component -->
<macroscopicdemand>
<id>d1</id>
<demandconfiguration>
<timeperiods>
<timeperiod id="0">
<duration>3600</duration>
</timeperiod>
</timeperiods>
</demandconfiguration>
<oddemands>
<odcellbycellmatrix timeperiodref="0">
<o ref="1">
<d ref="2">1000</d>
</o>
</odcellbycellmatrix>
</oddemands>
</macroscopicdemand>
<!-- Physical network component -->
<macroscopicnetwork>
<id>n1</id>
<infrastructurelayers>
<layer id="road">
<nodes>
<node id="1" />
<node id="2" />
</nodes>
<links>
<link id="1" nodearef="1" nodebref="2">
<linksegment id="1" dir="a_b" />
<linksegment id="2" dir="b_a" />
<length>10</length>
</link>
</links>
</layer>
</infrastructurelayers>
</macroscopicnetwork>
<!-- zoning structure component -->
<macroscopiczoning>
<id>z1</id>
<zones>
<zone id="1">
<centroid>
<name>Zone 1 centroid</name>
</centroid>
<connectoids>
<connectoid id="1" noderef="1" />
</connectoids>
</zone>
<zone id="2">
<centroid>
<name>Zone 2 centroid</name>
</centroid>
<connectoids>
<connectoid id="2" noderef="2" />
</connectoids>
</zone>
</zones>
</macroscopiczoning>
</PLANit>
Demands
The travel demand is provided in matrix format in veh/h. In this case for the default mode (we did not specify a mode explicitly) and set to a value of 1000:
Origin/Destination | 1 | 2 |
---|---|---|
1 | - | 1000 |
2 | - | - |
Also note that the inputs define a single time period that has a duration of exactly 1 hour, i.e., 3600 seconds.
Network and zoning structure
As you can see, the demands, zoning, and network all have their own section in the XML. Here, the network comprises:
- 1 link (segment)
- 2 nodes (at upstream and downstream of link),
- 2 zones,
- 2 centroids, one per zone,
- two connectoids, one per zone
Each zone represents a geographical area. It has a centroid from which travel demand can depart/arrive. To access the physical road network, each zone has one or more connectoids, i.e., nodes marked as eligible points for ingress/egress. PLANit will construct virtual links, connecting each connectoid node to the centroid. In this case, both nodes are marked as connectoids for one of the two zones.
PLANit model configuration
Let us now configure our traffic assignment run using the above inputs.
Create a new executable Java file in your favourite IDE, e.g. Eclipse, or something else and name it PLANitMain.java
. if you are unfamiliar with programming in Java, just copy the below snippet in this file. It will create a class called PLANitMain
and when you run it it will execute the main(...)
method
public class PlanItMain {
public static void main(final String[] args) {
}
Now Copy the below Java snippet into the main
method (in between the two accolades and save). We’ll go through the snippet line by line to explain what is going on
...
try {
// PROJECT INSTANCE
final PlanItSimpleProject project = new PlanItSimpleProject("c:\\Users\\Public\\planit_test\\");
// ASSIGNMENT INSTANCE
TraditionalStaticAssignmentConfigurator assignment =
(TraditionalStaticAssignmentConfigurator) project.createAndRegisterTrafficAssignment(TrafficAssignment.TRADITIONAL_STATIC_ASSIGNMENT);
// COMPONENTS
BPRConfigurator bprCost = (BPRConfigurator) assignment.createAndRegisterPhysicalCost(PhysicalCost.BPR);
assignment.createAndRegisterVirtualCost(VirtualCost.FIXED);
assignment.createAndRegisterSmoothing(Smoothing.MSA);
// CONFIGURE COST COMPONENT
// BPR
double alpha = 0.9;
double beta = 4.5;
bprCost.setDefaultParameters(alpha, beta);
// CONFIGURE OUTPUT
assignment.getOutputConfiguration().setPersistOnlyFinalIteration(false);
// EXECUTE ASSIGNMENT
project.executeAllTrafficAssignments();
} catch (final Exception e) {
// do something
}
Make sure you imported all the suggested classes. If you are not using an IDE, you will have to look up the correct imports from the PLANitxxxx.jar or the JavaDoc.
Ok, let’s see what we just did. First, an instance of a PLANitSimpleProject
is created, named project
, via
final PlanItSimpleProject project = new PlanItSimpleProject("c:\\Users\\Public\\planit_test\\");
There are more advanced project implementations available, e.g.,
PlanItProject
orCustomPlanItProject
, that allow you to change more things but come at the cost of a more complex configuration, see the project example section for more information.
You can give the instance any name you want, it is not tied to
project
. It could also bei_love_assignment
, orp
, orwhat_now
. Do note that a descriptive name is usually the best choice.
The project
instance takes one argument here, the project path. PLANit will attempt to parse all the inputs from
this directory. So make sure that the XML file with the inputs is available in this directory. If you saved it somewhere
else, change the path that you pass in to the project to this directory.
The project
instance allows you access to the parsed inputs. Further, it is used to create and register traffic
assignments on it. So, a project can have a bunch of inputs and traffic assignments. The traffic assignment then uses
these inputs to conduct its simulation run. In case of a PlanItSimpleProject
, the project allows only a single assignment
on the project and it automatically provides the inputs to this one assignment without the user having to explicitly do this. Neat!
Let’s move on to the next line. Here we decide what traffic assignment component we are using. Here, we opt for a traditional static traffic assignment model. It is activated by creating and registering it on the project via :
TraditionalStaticAssignmentConfigurator assignment =
(TraditionalStaticAssignmentConfigurator) project.createAndRegisterTrafficAssignment(TrafficAssignment.TRADITIONAL_STATIC_ASSIGNMENT);
Like all components that the user can choose, you either provide the full Java class name or - if it is an implementation known to PLANit - a shorthand reference as is used here via TrafficAssignment.TRADITIONAL_STATIC_ASSIGNMENT
. The return type is an implementation of a TrafficAssignmentConfigurator
for the assignment at hand, in this case a TraditionalStaticAssignmentConfigurator
. It allows you to configure the underlying components relevant to the chosen assignment.
Each traffic assignment comes with a number of default components that will be activated automatically. For the sake of this example, we explicitly activate the defaults (BPR, FIXED, MSA) to show you how you do this manually via:
BPRConfigurator bprCost = (BPRConfigurator) assignment.createAndRegisterPhysicalCost(PhysicalCost.BPR);
assignment.createAndRegisterVirtualCost(VirtualCost.FIXED);
assignment.createAndRegisterSmoothing(Smoothing.MSA);
Once you have completed this example, you can try running it again, but now with the above three lines removed. You will see they yield the same result, i.e., these components are activated by default.
As you can see, each line calls a .createAndRegisterXXX()
method on the assignment
instance. As a result
these choices are attached to this particular assignment only.
Physical cost
Here, we choose to set the physical cost, which represents the cost structure imposed on the physical road network.
It is set to PhysicalCost.BPR
resulting in the activation of a BPRLinkTravelTimeCost
implementation.
Each of these methods returns the created instance, so you can configure the component directly.
Alternatively you can collect it afterwards via a getter, e.g. assignment.getXXXX()
.
Virtual cost
In PLANit, you separately configure the costs for the virtual part of the network that connects the travel demand
from the zones to the physical network (via virtual links between connectoids and centroids). Here, we choose that
cost to be fixed via VirtualCost.FIXED
. Since we do not change its configuration, it adopts the default fixed cost value.
We refer the reader to the JavaDoc for specifics on the defaults for each of the components.
Smoothing
Traditional static assignment is a so-called within-day equilibrium method based on Wardrop’s first principle, meaning
that it seeks to finds a solution where all travellers find their optimal path having the smallest cost given the choices
of all other travellers (who do the same). This is achieved by adopting an iterative procedure. During this iteration process,
so called smoothing is applied. This ensures that changes between iterations result in a smooth transition towards the
equilibrium solution. there exist many ways to apply smoothing. Here, simple MSA smoothing is used because of its
simplicity and computational attractiveness. It is activated via Smoothing.MSA
.
Configuration of components
Let us now look at how to configure options on one of our components; the BPR cost function:
double alpha = 0.9;
double beta = 4.5;
bprCost.setDefaultParameters(alpha, beta);
We can configure the BPR specific options by utilising the BPRLinkTravelTimeCost bprCost
returned by the assignment
when we registered it.
The BPR function has two parameters (alpha and beta) that you can configure in various ways. Here, we will just
change the defaults for all link segments, modes, and link segment types simultaneously. We do so .setDefaultParameters(alpha, beta)
.
Before we start the simulation run, we also explicitly make sure that we store results of all iterations, instead of only the final iteration (which is the default). To make this happen we call
assignment.getOutputConfiguration().setPersistOnlyFinalIteration(false);
Everything related to general choices regarding outputs is configured via the OutputConfiguration
instance obtained
via assignment.getOutputConfiguration()
. Dedicated configuration for link, od, and path outputs also exist (when activated).
Examples can be found under Output Examples.
Running the application
Before running the application make sure it ends with the line:
project.executeAllTrafficAssignments();
This will trigger the simulation to start. Make sure all configuration is conducted before calling this method, because
otherwise it has no impact on the simulation. Note that in project types other than PlanItSimpleProject
multiple
assignments can be configured to be run sequentially. This is why the method is named executeAllTrafficAssignments
even though in this basic example we only configured a single assignment.
Now run the main method from you IDE, or otherwise compile and run it from the command line (we assume you know how to do this, otherwise, Google is your friend!).
If all went well the application should run and all outputs are persisted in the same directory as where you placed your inputs. Go to the directory where your inputs are located. You should see that PLANit generated two files, an XML file, and a CSV file. The former contains meta-data about the latter. The CSV file contains the actual link based results of your run.
Result files
The Default Output Formatter generates meta-data for each run as well as CSV files that contain the actual data. Let’s take a quick look.
XML meta-data
The XML meta-data file you generally only use when you’re still unfamiliar with the column information in the CSV, or to get some information about the run when you forgot how it was generated, otherwise you are likely to skip it and only concern yourself with the CSV results
Your XML meta-data file contains information about the simulation run, but most importantly provides information on the column information in the CSV. Each column is listed with information on:
- name, related to the column heading in the CSV
- type, type of the values, e.g., integer, string, double, etc.
- unit, unit of the values, e.g., km, h, m, veh/h, etc.
Below you’ll find the XML meta-data for this run (you should have something very similar)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<metadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="<path_to_xsd>/metadata.xsd">
<timestamp>2020-06-01T15:29:18.480+10:00</timestamp>
<version>X.Y.Z</version>
<description>A_DESCRIPTION</description>
<outputconfiguration>
<assignment>TraditionalStaticAssignment</assignment>
<physicalcost>BPRLinkTravelTimeCost</physicalcost>
<virtualcost>FixedConnectoidTravelTimeCost</virtualcost>
<smoothing>MSASmoothing</smoothing>
<gapfunction>LinkBasedRelativeDualityGapFunction</gapfunction>
<stopcriterion>StopCriterion</stopcriterion>
<timeperiod>
<id>0</id>
<name></name>
</timeperiod>
</outputconfiguration>
<simulation>
<iteration>
<nr>2</nr>
<csvdata type="Link">LINK_TO_CSV_RESULT_FILE</csvdata>
</iteration>
</simulation>
<columns>
<column>
<name>Downstream Node XML Id</name>
<units>none</units>
<type>string</type>
</column>
<column>
<name>Link Segment XML Id</name>
<units>none</units>
<type>string</type>
</column>
<column>
<name>Mode XML Id</name>
<units>none</units>
<type>string</type>
</column>
<column>
<name>Time Period XML Id</name>
<units>none</units>
<type>string</type>
</column>
<column>
<name>Time Period Id</name>
<units>none</units>
<type>integer</type>
</column>
<column>
<name>Upstream Node XML Id</name>
<units>none</units>
<type>string</type>
</column>
<column>
<name>Capacity per Lane</name>
<units>veh/h</units>
<type>double</type>
</column>
<column>
<name>Downstream Node Location</name>
<units>srs</units>
<type>srsname</type>
</column>
<column>
<name>Length</name>
<units>km</units>
<type>double</type>
</column>
<column>
<name>Maximum Speed</name>
<units>km/h</units>
<type>double</type>
</column>
<column>
<name>Number of Lanes</name>
<units>none</units>
<type>integer</type>
</column>
<column>
<name>Upstream Node Location</name>
<units>srs</units>
<type>srsname</type>
</column>
<column>
<name>Calculated Speed</name>
<units>km/h</units>
<type>double</type>
</column>
<column>
<name>Cost</name>
<units>h</units>
<type>double</type>
</column>
<column>
<name>Density</name>
<units>veh/km</units>
<type>double</type>
</column>
<column>
<name>Flow</name>
<units>veh/h</units>
<type>double</type>
</column>
</columns>
</metadata>
CSV Results
The CSV result file - with default settings - has a heading row with the column names (corresponding to the columns in the XML meta-data file). The other rows contain the result values, separated by a comma. In this very simple example we only have a single result row for the one link. The result should look something like the following:
Downstream Node XML Id,Link Segment XML Id,Mode XML Id,Time Period XML Id,Time Period Id,Upstream Node XML Id,Capacity per Lane,Downstream Node Location,Length,Maximum Speed,Number of Lanes,Upstream Node Location,Calculated Speed,Cost,Flow
2,1,1,0,0,1,1800.0000000,Not Specified,10.0000000,80.0000000,1,Not Specified,75.1948772,0.1329878,180.0000000,1000.0000000
As you can see, we find that the flow is indeed 1000 veh/h as stated in our input. The speed is somewhat reduced compared to free flow resulting in a slightly increased travel time (cost)
Some of these columns you are likely not interested in for most applications. You can add and remove columns very easily. More information on this can be found under the Link Configuration section of the manual.