Network Dataset - is it possible to change the cost evaluators using Python?

537
2
Jump to solution
03-08-2023 05:35 AM
ConnieSu
New Contributor III

Hello!

I've built a network dataset with roads, railways, and waterways. I'm using freight as the cost, so that the Route solver finds the route with the lowest freight cost for each O-D pair.

ConnieSu_0-1678282031327.png

ConnieSu_1-1678282265381.png

I need to use 60 different freight cost equations, one for each of the 5 products and one for each month. I'm creating a template for each month, only changing the values in the cost evaluators.

Unfortunately, the chosen multimodal routes changes with each freight cost equation, since there is an intercept (fixed cost) and an inclination (variable cost), so different parameters may lead to different most economical routes.

 

Question: is it possible to create a new template changing the cost evaluators' values through a Python script? Or is it only possible directly in ArcGIS Pro?

Thanks and regards!

0 Kudos
1 Solution

Accepted Solutions
MelindaMorang
Esri Regular Contributor

To answer your specific question: No, you cannot modify network dataset properties in Python.  We don't have an API for that.

But, I think there may be a couple of better option for you to solve this problem.

If I've understood correctly, it seems like you need to be able to vary the numerical value associated with each mode based on product and month.  For example, Ferro_Novo (Along) is calculated using [some number] * [the length of the feature].  You are looking for a way to programmatically vary those numbers.  Is this correct?

I think you may be able to solve this problem using attribute parameters.  Here is some documentation explaining what this is: https://pro.arcgis.com/en/pro-app/latest/help/analysis/networks/use-parameters-with-network-attribut...

I suggest that you create one attribute that just returns the shape length in the desired units (using a Field Script evaluator).  Then, create a second attribute for the cost you're calculating. Create attribute parameters for each of the numerical factors you need (not all 60 values you want...just one per unique factor that will serve as a variable that you will need to change).  Use a Function evaluator for each edge source that multiplies the shape attribute (the simple one I suggested you create) by the appropriate parameter to scale the value.

You can then set up a travel mode for each of your 60 combinations, or, alternatively, you can dynamically create the travel modes in a Python script for running your analysis.  You can just update the attribute parameters according to the needs of the specific analysis. Here's the documentation for the TravelMode object in Python: https://pro.arcgis.com/en/pro-app/latest/arcpy/network-analyst/travelmode-nax.htm

So, to summarize you will have something like this:

Cost attribute 1: Length

  • Evaluators use "Field Script" and are based on the [Shape] field

Cost attribute 2: MyParameterizedCost

  • Evaluators use "Function".  They are a function of [some attribute parameter] * Length
  • Create an attribute parameter for your scale factor.  Let's say you have three different ones based on modes, ScaleA, ScaleB, and ScaleC.  Create each of these parameters and give them some default value (doesn't matter what).  Let's say 1, 2, and 3
  • So, the function evaluator for Ferro_Novo (Along) might look like ScaleA * Length.

Travel mode: MyParameterizedTravelMode

  • Create a travel mode that uses MyParameterizedCost as the impedance attribute
  • Set the attribute parameter values to some specific values according to your desired scale factors for whatever this travel mode is intended to model (one of your 60 combinations)

Then, either create 59 more travel modes, or use Python to dynamically create them from the base travel mode and just vary the attribute parameter values.

think that will work.

Your other option (more what you were asking for) is to modify the network dataset XML template, but I don't recommend this, and the schema of that XML is not documented.

View solution in original post

2 Replies
MelindaMorang
Esri Regular Contributor

To answer your specific question: No, you cannot modify network dataset properties in Python.  We don't have an API for that.

But, I think there may be a couple of better option for you to solve this problem.

If I've understood correctly, it seems like you need to be able to vary the numerical value associated with each mode based on product and month.  For example, Ferro_Novo (Along) is calculated using [some number] * [the length of the feature].  You are looking for a way to programmatically vary those numbers.  Is this correct?

I think you may be able to solve this problem using attribute parameters.  Here is some documentation explaining what this is: https://pro.arcgis.com/en/pro-app/latest/help/analysis/networks/use-parameters-with-network-attribut...

I suggest that you create one attribute that just returns the shape length in the desired units (using a Field Script evaluator).  Then, create a second attribute for the cost you're calculating. Create attribute parameters for each of the numerical factors you need (not all 60 values you want...just one per unique factor that will serve as a variable that you will need to change).  Use a Function evaluator for each edge source that multiplies the shape attribute (the simple one I suggested you create) by the appropriate parameter to scale the value.

You can then set up a travel mode for each of your 60 combinations, or, alternatively, you can dynamically create the travel modes in a Python script for running your analysis.  You can just update the attribute parameters according to the needs of the specific analysis. Here's the documentation for the TravelMode object in Python: https://pro.arcgis.com/en/pro-app/latest/arcpy/network-analyst/travelmode-nax.htm

So, to summarize you will have something like this:

Cost attribute 1: Length

  • Evaluators use "Field Script" and are based on the [Shape] field

Cost attribute 2: MyParameterizedCost

  • Evaluators use "Function".  They are a function of [some attribute parameter] * Length
  • Create an attribute parameter for your scale factor.  Let's say you have three different ones based on modes, ScaleA, ScaleB, and ScaleC.  Create each of these parameters and give them some default value (doesn't matter what).  Let's say 1, 2, and 3
  • So, the function evaluator for Ferro_Novo (Along) might look like ScaleA * Length.

Travel mode: MyParameterizedTravelMode

  • Create a travel mode that uses MyParameterizedCost as the impedance attribute
  • Set the attribute parameter values to some specific values according to your desired scale factors for whatever this travel mode is intended to model (one of your 60 combinations)

Then, either create 59 more travel modes, or use Python to dynamically create them from the base travel mode and just vary the attribute parameter values.

think that will work.

Your other option (more what you were asking for) is to modify the network dataset XML template, but I don't recommend this, and the schema of that XML is not documented.

ConnieSu
New Contributor III

Thanks for your help, Melinda! It worked. 😊

0 Kudos