Skip links

User-Defined Variables, Costs and Constraints (Transportation Optimization)

User-defined variables (UDVs) are a transformative feature in Cosmic Frog’s transportation optimization algorithm (Hopper engine) that allow users to create and track custom metrics specific to their transportation needs. Once established, these variables can be seamlessly integrated into user-defined constraints and/or user-defined costs. Several example use cases are:

  • Counting shipments, products, sites, routes, etc. E.g.:
    • Limit a route to a maximum number of countries it can make stops in.
    • Cabotage constraints like no deliveries in Germany if route starts in Poland and goes to France.
    • Track the number of products on each route.
  • Quantity, weight, volume: model compartment capacities on a truck for ambient and frozen goods.
  • Shelf-life, duration at stop, route duration: a shipment cannot be on a route for more than 6 hours from pickup to delivery.
  • Distance between pickup and delivery, route distance: last stop needs to be within certain distance from pickup location.

Before diving into Hopper’s user-defined variables, costs, and constraints, it is recommended users are familiar with the basics of building and running a Hopper model, see for example this “Getting Started with Hopper” help center article.

In this documentation, we will first describe the example model used to illustrate the UDV concepts in this help article. Next, we will cover the input and output tables available when working with user-defined variables, costs, and constraints. Finally, we will walk through the inputs and outputs of 4 UDV examples: the first two examples showcase the application of constraints to user-defined variables, while the last two examples cover how to model user-defined costs.

Overview Example Model

The characteristics of the model used to show the concepts of user-defined variables, costs, and constraints throughout this help article are as follows:

  • There are 100 customer locations, 20 customers in each of the following 5 countries: Germany, Austria, Poland, Czech Republic, and Slovakia.
  • There is 1 DC in Germany at which the routes start and end.
  • There are 3 products being modelled: Ambient, Refrigerated and Frozen.
  • Each customer requires 1 delivery of 1 unit of 1 of the 3 products.
  • The only constraint in the Baseline scenario (called Baseline_UDV) is the capacity of the Truck asset, which is 10 units, essentially limiting each route to 10 stops.
  • The only costs used in the model are a $100 fixed cost per route and $1/MI variable distance cost.

The optimized routes from the Baseline_UDV scenario are shown on this map, there are 10 routes with 10 stops each. The customers are color-coded based on the country they are in:

DOC 71 UDV 009

Filtering out the route which has stops in most countries, we find the following route which has stops on it in 4 countries Poland (1 dark blue stop), Check Republic (7 yellow stops), Slovakia (1 orange stop), and Germany (1 red stop):

DOC 71 UDV 008

User-defined Variables, Costs, and Constraints Inputs

In the Input Tables part of Cosmic Frog’s Data module, there are 3 input tables in the Constraints section that can be used to configure user-defined variables, costs, and constraints:

DOC 71 UDV 001

  1. Transportation User-Defined Variables: user-defined variables, which are either just tracked and reported in the outputs or to which costs and/or constraints are applied, can be specified in this table.
  2. User-Defined Constraints: this table can be used to apply constraints to any variables specified in the Transportation User-Defined Variables table.
  3. User-Defined Costs: this table can be used to apply costs to any variables specified in the Transportation User-Defined Variables table.

We will take a closer look at each of these input tables now, and will also see more screenshots of these in the later sections that walk through several examples.

Transportation User-Defined Variables Input Table

On this table we specify the term(s) of each variable which we wish to track or apply user-defined costs and/or constraints to. This first screenshot shows the fields which are used to define the variable, its term(s), and what the return condition is:

DOC 71 UDV 101

  1. Variable Name – this is what we call the “linking condition” as we use this name given to the variable in the user-defined constraints and user-defined costs tables to link the constraint/cost to the correct variable. If a variable consists of multiple terms, multiple records with the same variable name need to be set up in this table; each record represents 1 term of the variable.
  2. Term Name and its Coefficient – together these are the “term definition”: the name needs to be a unique name for the term and the coefficient indicates the weight of the term when calculating the value of the variable from the sum of its scaled term values.
  3. Scope and Type – together these make up the “return condition”: how the variable values are calculated is based on what these are set to. Note that in the next section these are explained in more detail using several visuals and a numbers example.
    1. Scope – the scope that the variable is iterated over. This entity is first filtered (by the Filter Condition fields shown in the next screenshot, if any are used) and then evaluated based on what Type is set to. Options for the Scope field are Route, Shipment, and Stop.
    2. Type – the behavior to be captured with the term, i.e. the type of measure the scope is evaluated on. Options for the Type field are:
      1. RouteCount, StopCount, ShipmentCount, ProductCount: counts the number of routes / stops / shipments / products within the filtered scope.
      2. Quantity, Weight, Volume, Distance, Time: returns the amount in terms of quantity, weight, distance or time of the filtered scope.
      3. Offset: offset can be used to add a constant to the variable (not yet used for Hopper models).
      4. Variable: Type needs to be set to Variable if the Term Name of the variable is set to the Variable Name of another variable.
  4. This variable is named “NumberOfProductsInRoute”. It has 1 term named “ProductFlag” and its coefficient is set to 1, meaning the variable value just be equal to the value of this 1 term. Scope is set to Route and Type to Product Count, meaning that each route is filtered for a specific product (see next screenshot) and if the product is on the route (any segment, not necessarily on all segments), the value is 1. If the product is not on the route, the value is 0.

The next 2 screenshots shows the other fields available on the Transportation User-Defined Variables input table, which are used to set the Filter Condition for the Scope. Note that several of these fields have accompanying Group Behavior fields, which are not shown in the screenshot. If a group name is used in the Asset Name, Site Name, Shipment ID, or Product Name field, the Group Behavior field specifies how the group should be interpreted: if the Group Behavior field is set to Aggregate (the default if not specified) the activity of the variable is summed over the members of the group, i.e. the variable is applied to the members of the group together. If the Group Behavior field is set to Enumerate, then an instance of the variable will be created for each member of the group individually.

DOC 71 UDV 122

DOC 71 UDV 123

  1. Asset Name and its Group Behavior field – specify the name of the asset or the group of assets for which the Scope will be filtered.
  2. Site Name and its Group Behavior field – specify the name of the location (facility or customer) or group of locations for which the Scope will be filtered.
  3. Site Type – specify the type of location for which the Scope will be filtered; options are: Pickup, Delivery, and Any.
  4. Shipment ID and its Group Behavior field – specify the shipment or group of shipments for which the Scope will be filtered.
  5. Product Name and its Group Behavior field – specify the product or group of products for which the Scope will be filtered.
  6. Min Sequence Position, Max Sequence Position, and Sequence Position Type – if filtering of the Scope needs to occur based on the position of a stop on the route, these 3 fields can be utilized:
    1. Min Sequence Position – the minimum position in the stop sequence that is included in the filter condition. The first stop is indicated with 1, etc.
    2. Max Sequence Position – the maximum position in the stop sequence that is included in the filter condition. To count from the end, use negative numbers where -1 indicates the last stop.
    3. Sequence Position Type – specifies if the Min and Max Sequence Position fields should be applied to only pickup locations (value = Pickup), only delivery locations (value = Delivery) or all stops (value = Any).

Scope and Type – Visuals & Numbers Examples

Consider a route which picks up 4 shipments, Shipment #1, #2, #3, and #4, and delivers them to 3 stops on a route as shown in the following diagram. In all 3 examples that follow, the filter condition is set to Shipment ID = Shipment #3 and Site Type = Delivery. This first example shows what will be returned for the variable when Scope = Shipment and Type = Quantity:

DOC 71 UDV 119

The whole route is filtered for Delivery of Shipment #3 and we see that it is delivered to the Delivery 2 stop. Since Scope = Shipment and Type = Quantity, the resulting variable value is the quantity of this shipment, which is what the yellow outline indicates.

In the next example, we look at the same route and same filtering condition (Shipment #3, Delivery), but now Scope has been changed to Stop (Type is still Quantity):

DOC 71 UDV 120

Again, we filter the route for Delivery of Shipment #3 and we see that it is delivered to the Delivery 2 stop. Since Scope = Stop, now the variable value is the total quantity delivered to the stop (outlined in yellow again): quantity Shipment #2 + quantity Shipment #3.

The final visual example is for when the Scope is now changed to Route, while keeping all the other settings the same:

DOC 71 UDV 121

The route is again filtered for Delivery of Shipment #3, since the delivery of this shipment is on this route, we now calculate variable value as the total quantity of the route: quantity Shipment #1 + quantity Shipment #2 + quantity Shipment #3 + quantity Shipment #4, again outlined in yellow.

Next, we will also walk through a numbers example for different combinations of Scope and Type to see how these affect the calculation of the value of a variable’s term. Consider a route with 5 stops as follows:

DOC 71 UDV 109

We will calculate the value of the following 15 variables where the Scope, Type, and Product Name to filter for are set to different values. Note that all variables have just 1 term with coefficient 1, so the variable value = scaled term value.

DOC 71 UDV 110

  1. Var1, Term1 – Scope is set to Route and Type to Route Count. We filter by Product Name, which is set to Product_Ambient here. Because the Scope is set to route, when we filter the example route for this product, all we want to know is if this product is on the route or not. And due to the Type being Route Count, the value of the variable is either 0 if the product we filter for is not on the route, or 1 if the product is delivered as part of the route. Since Product_Ambient has been delivered on this route, the value of the variable is 1. Note that for this calculation it does not matter how many stops the product was delivered to or what the quantity of these deliveries was.
  2. Var2, Term1 – Scope and Type are the same as in the previous bullet point, but now we filter for a different product, Product_Frozen. Product_Frozen was also delivered as part of our example route, so again the value is 1.
  3. Var3, Term1 – Scope and Type are still the same as in the previous 2 bullet points, but we again filter for a different product, Product_Refrigerated. This product was not delivered as part of this route, so now the variable value is 0.
  4. Var4, Term1 – Scope is still set to Route, but Type is now set to Shipment Count. We filter the route for Product_Ambient, and if the product is on this route (which it is in this case), we count the number of shipments on the entire route (not just the shipments carrying this product). The route has 5 shipments on it, so this is the value of the variable.
  5. Var 5, Term1 – same Scope and Type as in the previous bullet point (Route and Shipment Count, respectively), but now filtering for Product_Frozen. This product was also on the route, so again counting the number of shipments on the route (all, not just the ones for Product_Frozen), the value of this variable is also 5.
  6. Var6, Term1 – again, same Scope and Type as the previous 2 bullet points, but now filtering for Product_Refrigerated. This route does not contain any shipments of this product, so the variable value is 0.
  7. Var7, Term1 – Scope is still set to Route, but Type has been changed to Quantity. We filter the route for Product_Ambient, and if the product is on this route (which it is in this case), sum the quantity of the entire route. The total quantity shipped on this route is 1 + 2 + 3 + 4 + 5 = 15.
  8. Var8, Term1 – same Scope and Type as in the previous bullet point (Route and Quantity, respectively), but now filtering for Product_Frozen. Since this product is shipped on this route, we again sum the quantity of the entire route to again arrive at 15 for the variable’s value.
  9. Var9, Term1 – again, same Scope and Type as the previous 2 bullet points, but now filtering for Product_Refrigerated. This route does not contain any shipments of this product, so the variable value is 0.
  10. Var10, Term1 – Scope is now set to Shipment, and Type to Shipment Count. We are filtering the route for Product_Ambient and, because the Scope is Shipment now, we count the number of shipments this product was on. This is on 2 shipments: to Stop number 1 (Shipment_05) and to Stop number 4 (Shipment_04), therefore the variable value is 2.
  11. Var11, Term1 – same Scope and Type as in the previous bullet point (Shipment and Shipment Count, respectively), but now filtering for Product_Frozen. This product was on 3 shipments (to stops 2, 3, and 5), so the variable value is 3.
  12. Var12, Term1 – again, same Scope and Type as the previous 2 bullet points, but now filtering for Product_Refrigerated. This route does not contain any shipments of this product, so the variable value is 0.
  13. Var13, Term1 – Scope is still set to Shipment, but now the Type is set to Quantity. Product Name is back to Product_Ambient, so we filter the route for this product and then sum the total quantity of this product on the route. This is 5 (1 unit at stop1 + 4 units at stop 4).
  14. Var14, Term1 – same Scope and Type as the previous bullet point (Shipment and Quantity, respectively), but now filtering for Product_Frozen. The sum of the quantity of this product on this route is 10 (2 units at stop 2, 3 at stop 3, and 5 at stop 5).
  15. Var15, Term1 – again, same Scope and Type as the previous 2 bullet points, but now filtering for Product_Refrigerated. Since this route does not contain any shipments of this product, the sum of the quantity is 0, and that is the variable’s value.

User-Defined Constraints Input Table

If wanting to apply constraints to user-defined variables, this can be set up on the User-Defined Constraints input table:

DOC 71 UDV 103

  1. Constraint Name – a unique name for the constraint.
  2. Variable Name – the variable the constraint needs to be applied to; should match the name of a variable specified in the Transportation User-Defined Variables table.
  3. Constraint Type and Constraint Value – together these define the constraint. Options for Type are:
    1. Min when setting a lower limit in the Constraint Value field
    2. Max when setting an upper limit in the Constraint Value field
    3. Fixed when setting a specific value in the Constraint Value field that needs to be matched exactly
    4. Conditional Min: either 0 or greater than or equal to the minimum value set in the Constraint Value field
  4. This constraint is called “Max One Product In Route” and is applied to the NumberOfProductsInRoute variable (see first screenshot in previous section). The upper limit is set to 1. Also note that the Status of the constraint is set to Exclude, so running a baseline or other scenarios are not impacted by this constraint, only scenario(s) that change the Status of the constraint to Include will apply the constraint as part of the Hopper solve.

User-Defined Costs Input Table

To apply costs to a user-defined variable, this can be achieved by utilizing the User-Defined Costs input table:

DOC 71 UDV 104

  1. Cost Name – a unique name for the cost.
  2. Variable Name – the variable the cost needs to be applied to; should match the name of a variable specified in the Transportation User-Defined Variables table.
  3. Unit Cost – the cost that is applied to the variable, this can be a single number or a step cost (which needs to have been set up in the Step Costs input table).

User-defined Variables, Costs, and Constraints Outputs

There are 3 output tables related to user-defined costs and constraints:

DOC 71 UDV 002

  1. Optimization User-Defined Variable Summary: lists the value of each user-defined variable.
  2. Optimization User-Defined Variable Term Summary: lists the value of each term of each variable.
  3. Optimization User-Defined Cost Summary: lists all user-defined costs.

We will cover each of these now and will see more screenshots of them in the sections that follow where we will walk through several example use cases.

Optimization User-Defined Variable Term Summary Output Table

This table lists the values of the terms of each user-defined variable. This next screenshot shows the values of the “ProductFlag” term of the “NumberOfProductsInRoute” variable for the routes of the Baseline_UDV scenario. How this variable and its term were set up can be seen in the screenshot of the transportation user-defined variables table above (Scope = Route, Type = Product Count, Coefficient = 1).

DOC 71 UDV 105

  1. Variable Name – the name of the variable that the term is part of. Note that the name is that of the variable (as specified in the Transportation User-Defined Variables input table), combined with the route id. Based on the filter condition of the variable and the value(s) of the Group Behavior field(s) the enumeration of the variable name can also include shipments or stops for example.
  2. Term Name – the name of the term for which the value is listed in the record.
  3. Term Value – the value of the term.
  4. Scaled Term Value – the value of the term, multiplied by the coefficient set on the Transportation User-Defined Variables input table. This is the number used to calculate the variable from the term(s) it consists of by summing their scaled term values.
  5. For the first 2 routes of this scenario, the first one had 3 different products on it and the second one 2 different products. The Scaled Term Values are equal to the Term Values here as the coefficient of the term is set to 1.

When setting up the Number Of Products In Route variable like above and not applying costs or constraints to it, it functions as a tracker so that user can easily get at this data rather than having to manipulate the transportation optimization output tables to calculate the number of products per route.

If we run a scenario “MaxOneProductPerRoute” where we include the maximum 1 product per route constraint that we have seen in the screenshot in the section further above on the User-Defined Constraints input table, the outputs in this table change as follows:

DOC 71 UDV 106

  1. We are looking at the outputs of the MaxOneProductPerRoute scenario in the Optimization User-Defined Variable Term Summary output table.
  2. The constraint was applied correctly since each route in this scenario has only 1 product on it, which is what the Term Value represents.

Optimization User-Defined Variable Summary Output Table

This table is a roll up to the variable level of the Optimization User-Defined Variable Term Summary output table discussed in the previous section. All the scaled terms of each variable have been added up to arrive at the variable’s value:

DOC 71 UDV 107

  1. Variable Name – the name of the variable for which this record lists the value. Like we have seen above for the Optimization User Defined Variable Term Summary output table, note that the name is that of the variable (as specified in the Transportation User-Defined Variables input table), combined with the route id, as the variable is enumerated for each route.
  2. Variable Value – the value of the variable, which is the sum of the Scaled Term Values of all terms the variable consists of.
  3. For the 2 scenarios we looked at above in the Term Summary output table we have filtered out the “number of products in route” variable for route #5 and we see that in the Baseline_UDV scenario route #5 has 3 products on it and in the MaxOneProductPerRoute scenario it has 1 product on it.

Optimization User-Defined Cost Summary Output Table

If costs have been applied to a user-defined variable, the results of that can be seen in this output table:

DOC 71 UDV 108

  1. Cost Name – the name of the cost as specified on the User-Defined Costs input table.
  2. Variable Name – the name of the variable that the cost is applied to.
  3. Variable Value – the value of the variable, which is the sum of the Scaled Term Values of all terms the variable consists of.
  4. Cost – the calculated user-defined cost of the variable. If the cost specified is a single number unit cost, then the calculated Cost = Variable Value * Unit Cost. If the cost that is specified is a step cost, the cost is looked up based on the variable value (= throughput level).

User-defined Variables & Constraints Example 1: Limit the number of Countries per Route

In this first example, we will see how we can track and limit the number of countries per route. For this purpose, a variable with 5 terms is set up in the Transportation User-Defined Variables table. Each term counts if a route has any stops in 1 of the 5 countries used in the model, 1 variable term for each country. Then we will apply constraints to this variable that limit the number of countries on each route to either 1 or 2. Let’s start with looking at the variable and its 5 terms in the Transportation User-Defined Variables table:

DOC 71 UDV 111

  1. These 5 records together set up 1 variable, NumberOfCountriesPerRoute, which is made up of 5 terms. Each term is specific to 1 of the 5 countries the customers in the model are located in and the term name is descriptive of this. The coefficient of each term is 1, so the term values are summed as is when calculating the variable value.
  2. Scope and Type – scope is set to Route, so we use the filtering condition (the site name field) and see if it is present at all in the entire route. Since the Type is RouteCount, if the filtering condition exists in the route, then the value is 1 and if it does not exist, the value is 0.
  3. Site Name and Site Name Group Behavior (latter not shown in screenshot) – these fields are used as the filtering condition. Site Name is set to the group of customers for each country matching the term name. The Site Name Group Behavior field is set to the default of Aggregate, meaning that these groups of customers within a country are treated together as 1 entity. For example, looking at the first record, this means that if any of the customers contained in the Czechia_Customers group is on a route, the value of the CountryFlag_Czechia term is 1 for that route and 0 if none of the Czechia_Customers are on the route. This works similarly for all the terms, and after adding them all up, the value of the NumberOfCountriesPerRoute variable is exactly what its name indicates: it has counted the number of countries the route makes stops in.

Next, we can add constraints that apply to this variable to change the behavior in the model and limit the number of countries a route is allowed to make stops in on any given route. We use the User-Defined Constraints table for this:

DOC 71 UDV 112

  1. There are 2 constraints set up, named Max One Country and Max Two Countries. They are both applied to the NumberOfCountriesPerRoute variable that we have discussed in the previous section, which counts the number of countries a route makes stops in.
  2. By setting Constraint Type to Max and the constraint value to 1 and 2, respectively, these constraints will limit routes so they do not make stops in more than 1 or 2 countries.
  3. The Status of both constraints is set to Exclude, so by default they will not be applied. Scenarios changing the Status to Include can be set up to see the impact of these constraints.

After running the Baseline_UDV scenario which does not include these constraints, we can have a look at the Optimization User-Defined Variable Summary output table:

DOC 71 UDV 113

We see that 3 routes make stops in just 1 country, 5 routes in 2 countries, and 1 route (route 9) makes stops in 4 countries when leaving the number of countries a route is allowed to make stops in unconstrained.

Now we want to see the impact of applying the Max One Country and Max Two Countries constraints through 2 scenarios and again we check the Optimization User-Defined Variable Summary output table after running these scenarios:

DOC 71 UDV 007

  1. We see that in the MaxOneCountryPerRoute scenario the value for the NumberOfCountriesPerRoute variable is 1 for each route, which is what we expected.
  2. The number of countries the routes of the MaxTwoCountriesPerRoute scenario make stops in are either 1 or 2, which is again what we expected with the constraint that was applied in this scenario.

Maps are also helpful to visualize these outputs. As we saw in the introduction of the example model used throughout this documentation, these are the Baseline_UDV routes visualized on a map:

DOC 71 UDV 009

These routes change as follows in the MaxOneCountryPerRoute scenario:

DOC 71 UDV 010

Since some of these routes overlap on the map, let us filter a few out and color-code them based on the country to more easily see that indeed the routes each only make stops in 1 country:

DOC 71 UDV 011

User-defined Variables & Constraints Example 2: Limit the Truck’s Compartments Capacities

In this example we will see how user-defined variables and constraints can be used to model truck compartments and their capacities. First, we set up 3 variables that track the amount of ambient, refrigerated, and frozen product on a route:

DOC 71 UDV 114

  1. Three variables with each 1 term are set up here, 1 for each type of product and the variable and term names reflect these. Not shown in the screenshot is that the Coefficient for all these records is set to 1.
  2. With Scope set to Shipment, Type to Quantity, and filtering for an individual Product Name, we filter each shipment of a whole route and if the product matches the product filtered for, we add the quantity of the shipment to the total. So, the value of the first variable will be the total quantity of PRODUCT_Ambient on a route, etc.

Without setting up any constraints that apply to these variables, they just track how much of each product is on a route, which can be within or over the actual compartment capacity. So, to set capacity limits, we can use the User-Defined Constraints table to setup constraints on these 3 variables that represent the capacity of the ambient, refrigerated, and frozen compartments of a truck:

DOC 71 UDV 115

  1. Three constraints with descriptive names are entered into the User-Defined Constraints table, 1 for each of the variables that track the amount of ambient, refrigerated, and frozen product on a route.
  2. The constraints are all set to constraint type = Max to indicate an upper limit is being specified (a maximum capacity for a compartment), and the limit itself is set in the constraint value field: maximum of 3 units for the refrigerated compartment, maximum of 5 units for the ambient compartment, and maximum of 2 units for the frozen compartment.
  3. Like in the previous example, Status of these is set to Exclude, so they are not by default applied, their status needs to be set to Include either directly in this table or through a scenario. When setting up a scenario item to include all these 3 constraints it works like this (see also this Creating Scenarios in Cosmic Frog help article):

DOC 71 UDV 014

  1. We are in the Scenarios module of Cosmic Frog.
  2. We set up a new scenario named CompartmentCapacity, which has 1 scenario item named CompartmentConstraints.
  3. We have clicked on the CompartmentConstraints scenario item to open it.
  4. When configuring a scenario item, we first choose the table that we want to make the change to from the drop-down list, the User-Defined Constraints table in this case.
  5. Next, we specify which field on this table we want to change and what to change it to. In this case we are changing the value of the Status field to Include.
  6. In the Conditions section we can either use Named Filters (see the Named Filters in Cosmic Frog help article to learn more about these) or the Condition Builder to apply a filter to the records in the table, where the change will only be applied to the records filtered out by the condition. Here the Condition Builder is used to filter out constraints where the Constraint Name starts with Compartment. To learn more about how to write these conditions, see this Writing Syntax for Conditions help article.

After running the Baseline_UDV scenario where these constraints are not applied and another scenario, Compartment Capacity, where they are applied, we can take a look at the Optimization User-Defined Variable Summary output table to see the effect of the constraints (just showing routes 1 and 2 in the below screenshot):

DOC 71 UDV 015

  1. In the Baseline_UDV scenario the amount of product on a route is not constrained, and we see that on route 1 3 units of Product_Frozen were delivered, whereas we know that the capacity of the frozen compartment is 2 units in reality. Similarly, this route delivers 6 units of refrigerated product, but the capacity of the refrigerated compartment is 3 units. Similarly, on route 2, the amount delivered for both the frozen and refrigerated products are higher than the compartment capacities.
  2. When applying the constraints in the CompartmentCapacity scenario, we now see that none of the quantities exceed the capacities set for the compartments.

Typically, when adding constraints, we expect routes to change – more routes may be needed to adhere to the constraints, and they may become less efficient. Overall, we would expect costs, distance, and time to increase. This is exactly what we see when comparing these outputs in the Transportation Summary output table for these 2 scenarios:

DOC 71 UDV 016

User-defined Variables & Costs Example 3: Apply Cost Based on Time of Shipment in Truck

We have seen 2 examples of applying constraints to user-defined variables in the previous sections. Now, we will walk through 2 examples of applying costs to user-defined variables. The first example shows how to apply a variable cost based on how long a shipment sits on a route: we will specify a cost of $1 per hour the shipment spends on the route. First, we set up a variable that tracks how long a shipment spends on a route in the Transportation User-Defined Variables input table:

DOC 71 UDV 116

  1. The variable being set up is called ShipmentTimeInTruck and it has 1 term, TermShipmentTimeInTruck, which has a coefficient of 1 (not shown in screenshot).
  2. Scope is set to Shipment with Type of Time. Shipment ID is left blank, so the default of all shipments will be used, and Shipment ID Group Behavior is set to Enumerate, which means that we will evaluate this variable for each shipment individually. Together these fields mean that we will go through all shipment IDs and for each shipment find the route it is on. Because Type = Time, the variable value will be set to the amount of time the shipment is on the route.

Next, the User-Defined Costs table is used to specify the cost of $1 per hour:

DOC 71 UDV 117

  1. A cost named CostPerTimeInTruck is being specified to apply to the ShipmentTimeInTruck variable of which we saw the definition in the previous screenshot.
  2. The Unit Cost is set to 1, meaning this cost will be $1 per hour the shipment spends on the route.
  3. Similar to user-defined constraints, it is good practice to by default set the Status of these user-defined costs to Exclude and change this to Include through a scenario, so only in the scenarios with this change the costs are applied.

After running the CostPerShipmentTimeInTruck scenario which includes this user-defined cost, we can look at both the Transportation Shipment Summary and the Optimization User-Defined Cost Summary output tables to see this cost of $1 per hour has been applied:

DOC 71 UDV 022

  1. We are on the Transportation Shipment Summary output table and are looking at the shipments for 1 route (route #4) of the CostPerShipmentTimeInTruck scenario.
  2. The difference between the Delivery Date and Pickup Date (here all midnight on January 1st of 2023) tells us how long a shipment was on a route. For example, the first record for Shipment_95 is delivered at 6:46 on January 1st, so it has been on the route for 6.77 hours (46 minutes / 60 minutes = 0.77 hours).

Next, we open the Optimization User-Defined Cost Summary output table and filter for the same scenario and route (#4):

DOC 71 UDV 023

  1. We see that the variable name is appended with both the shipment number and the route number. These match what we filtered for in the previous screenshot of the Transportation Shipment Summary output table.
  2. The Variable Value here is the number of hours the shipment spent on the route; we see that for the first record (Shipment_95) this matches what we calculated above: 6.77 hours. Since the cost is set to $1 per hour, the calculated Cost for this shipment is $6.77.

User-defined Variables & Costs Example 4: Apply Penalty Cost to Shipments In-transit > 10h

In our final example of this documentation, we will use the same variable ShipmentTimeInTruck from the previous example to set up a different type of cost. We will use it to find any shipments that are on a route for more than 10 hours and apply a penalty cost of $100 to each. This involves using a step cost for which we will also need to utilize the Step Costs table; we will start with looking at this table:

DOC 71 UDV 019

  1. On the Step Costs table, a step cost with the name Over10h_PenaltyStepCost is specified. Here, our step cost will only have one step (over 10 hours) and only one record is needed to set this up. In cases where multiple steps are required to be set up, multiple records with the same Step Cost Name need to be entered.
  2. The Step Cost Behavior field is set to Stepwise. When wanting to apply discounts based on the amount of throughput, other possible choices here are Incremental and All Item.
  3. Throughput Level and its UOM field set from which throughput the specified cost applies. In this case we want to apply the penalty cost from 10 hours. We leave the UOM field blank as the Type of Time specified for the variable takes care of setting this to hour.
  4. In the Cost field we enter the cost we want to apply for any shipment that is on a route for over 10 hours, which is $100.

Next, we configure the penalty cost in the User-Defined Costs table:

DOC 71 UDV 118

  1. A new record is added for a cost named Over10h_PenaltyCost and the variable it is applied to is the ShipmentTimeInTruck one set up previously, which tracks how long each shipment spends on a route.
  2. The Unit Cost field is now set to the name of the step cost that was covered in the previous screenshot. Status is again set to Exclude, so this cost is not applied by default, only when switching the Status to Include through a scenario.

After running a scenario in which we include the penalty cost, we can again look at the Transportation Shipment Summary and Optimization User-Defined Cost Summary output tables to see this cost in action:

DOC 71 UDV 020

  1. While on the Transportation Shipment Summary table the scenario in which the penalty cost is applied, Over10hInTruck_PenaltyCost, and one of its routes (#7) are filtered out. Again, looking at the difference between delivery date and pickup date, we can tell how long a shipment was on the route.
  2. For stops 1-7, the shipments were on the route less than 10 hours as these are delivered before 10AM on January 1st and were picked up at midnight on that same day. Stops 8-10, which are Shipment_51, Shipment_46, and Shipment_21, were all on the route for over 10 hours and we expect each of these to have gotten a penalty cost of $100, which we can check in the Optimization User-Defined Cost Summary output table:

DOC 71 UDV 021

  1. We are on the Optimization User-Defined Cost Summary output table and are filtering it for the same scenario and route number, which results in these 3 records.
  2. The Variable Name is again appended by both the Shipment ID and Route ID. We can see the Shipment IDs match those of the ones that were on the route for over 10 hours as seen in the previous screenshot.
  3. The Variable Value represents the number of hours the shipment was on the route.
  4. These 3 shipments were on the route for over 10 hours, so each was given a penalty cost of $100.
    1. Note that it does not matter in this case how much longer than 10 hours the shipment was on the route, they all get the same penalty cost of $100. Should we want to apply even heavier penalties from for example 15 hours onwards, we would need to add another record (another “step”) to the Over10h_PenaltyStepCost in the Step Costs table where the Throughput Level is set to 15 and the Cost is set to the penalty cost to be applied for shipments that are on a route for 15 hours or longer.

Have More Questions?

Contact Support Contact Sales Visit Frogger Pond Community