VRP With Priority Stops (orders)

6121
6
Jump to solution
07-11-2016 01:39 PM
Highlighted
Occasional Contributor

Is there any way to flag specific orders so that are always reached in a route?  I tried using the time constraints and that seems to help some, but there are still scenarios where my priorities orders (ones that now have a time window) are  not reached.  What i am saying is, can I tell it, given these orders that must be fulfilled, give me the best routes to service these orders and any other 'normal' orders that can be reached.   I know i can lock a sequence, but then i have to lock at route too.  I want the give the solver that flexibility. 

Reply
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Esri Contributor

Hello

There are two main options right now for marking something as required.  The first one you seem to know about but for completeness I'll explain incase someone else is having the same question.  Solve the problem in two steps, the first time mark all of the required stops with an assignment rule of "Override" and all of the optional ones as "Exclude."  This will put all of the required routes onto a route if it is at all possible and just ignore the additional ones.  For the second step mark all of the required orders with an assignment rule of either "Preserve Route and Relative Sequence" or "Preserve Route" and mark all of the optional orders with an assignment rule of "Override."  This tells the solver that the required stops have to stay on the route they are currently on either allowing for re-sequencing or not depending on which assignment rule you choose and then adds in as many optional orders as possible.  They can be inserted into the routes that already have required orders.  Depending on the location of the required orders this can sometimes give routes that crisscross because of the solver keeping the orders on specific routes.  The benefit of this method though is it makes sure all of the required stops are routed

The other option is to use the revenue field for the orders.  This is a harder story to line out with specifics because it really depends on the other costs that are in your problem.  But in general give the required orders a really large revenue and the optional ones a revenue of zero.  Run it and see how it does.  If it still isn't getting all of the required stops try increasing the revenue and rerunning.  This method does a better job with the routing optimization portion as it doesn't lock orders on a sub-optimal route but it does not guarantee that required orders are routed (usually with the right revenues it does pretty well through).  The reported costs for the routes are also now artificially changed because of the fake revenue values.

Hope this helps,

Heather

View solution in original post

6 Replies
Highlighted
Esri Contributor

Hello

There are two main options right now for marking something as required.  The first one you seem to know about but for completeness I'll explain incase someone else is having the same question.  Solve the problem in two steps, the first time mark all of the required stops with an assignment rule of "Override" and all of the optional ones as "Exclude."  This will put all of the required routes onto a route if it is at all possible and just ignore the additional ones.  For the second step mark all of the required orders with an assignment rule of either "Preserve Route and Relative Sequence" or "Preserve Route" and mark all of the optional orders with an assignment rule of "Override."  This tells the solver that the required stops have to stay on the route they are currently on either allowing for re-sequencing or not depending on which assignment rule you choose and then adds in as many optional orders as possible.  They can be inserted into the routes that already have required orders.  Depending on the location of the required orders this can sometimes give routes that crisscross because of the solver keeping the orders on specific routes.  The benefit of this method though is it makes sure all of the required stops are routed

The other option is to use the revenue field for the orders.  This is a harder story to line out with specifics because it really depends on the other costs that are in your problem.  But in general give the required orders a really large revenue and the optional ones a revenue of zero.  Run it and see how it does.  If it still isn't getting all of the required stops try increasing the revenue and rerunning.  This method does a better job with the routing optimization portion as it doesn't lock orders on a sub-optimal route but it does not guarantee that required orders are routed (usually with the right revenues it does pretty well through).  The reported costs for the routes are also now artificially changed because of the fake revenue values.

Hope this helps,

Heather

View solution in original post

Highlighted
Occasional Contributor

Thank you.  I made some changes to my costs variables and I think the two step process is going to work for me.  My follow up question is, what is the best way to update Assignment rules via Arcpy?   I should be able to use the code block of CalculateField_management to make the specific field changes, but to do the calculation do I need the NA sublayer to be a feature layer?  Do you happen to have a snippet that does this this assignment rule update?  NA layers and sublayers seem to behave much differently than normal layers in python outside of arcDesktop.  And help would be appreciated.

Reply
0 Kudos
Highlighted
Occasional Contributor

So I think I got it.  It wasnt as bad as i thought.  I was trying to use the arcpy.na.GetNAClassNames that I saw somewhere, but had no luck with that.  A simple listlayers worked for me.  It worked but let me know if there are potential issues.

for lyr in arcpy.mapping.ListLayers(mxd, "", df):

    if lyr.name.lower() == "orders":

        orderlayerName = lyr

        print "Found it"

    else:

        print "you're not the droid im looking for"

OrdersView = "Orders_View"

print "make tableview"

arcpy.MakeTableView_management(orderlayerName,OrdersView)

#Calculate field with python expression selection

arcpy.CalculateField_management(OrdersView,"AssignmentRule","Reclass( !AssignmentRule! )","PYTHON_9.3","def Reclass(AssignmentRule):\n    if AssignmentRule == 3:\n        return 1\n    else:\n return 3")

Reply
0 Kudos
Highlighted
Esri Contributor

This looks like it should work.  The only potential issues I can see is if within the same python script you are wanting to adjust several layers like this then it might only give you the list of layers for the first one in which case you would need to use the GetNAClassNames with a dictionary approach.  This also assumes that you are working with ArcGIS in English since you have "orders" hardcoded. 

Neither of these are likely issues for you and so making the code more complicated to handle situations you won't ever be in just isn't necessary.  So go with what you have and if you have further questions or run into a situation where it isn't working then right back.

Highlighted
Occasional Contributor

With the getclassnames, it is only getting the sub layer name right?  I think my problem was that I was trying to pass that directly into my tools, where as I probably needed to use the name to find the Layer, then pass the Layer into the tools?

Reply
0 Kudos
Highlighted
Esri Regular Contributor

That's correct.  GetNAClassNames() just returns the string names of the sublayers.  In your case, you need the layer object, which is what ListLayers gives you.  If you wanted your script to be usable in localized versions of ArcGIS where the layer names might be called something in a different language, then you would want to use GetNAClassNames() to find the sublayer name in that language and pass that value into your code rather than hard-wiring "orders".  But if you're the only one running this script, then hard-wiring "orders" should be fine.