Difference between revisions of "Dispatch"

 
(14 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 
[[Category:Transforming functions]]
 
[[Category:Transforming functions]]
''New to Analytica 4.3''
+
[[Category:Financial Functions]]
  
= Dispatch( demand, capacity, Resource'', active, minimum, increment'') =
+
{{ReleaseBar}}
  
Allocates capacity from a set of resources to satisfy a demand, consuming capacity from the first resources in the order they appear in the «Resources» index«Demand» is the amount of demand that is to be filled . «Capacity» is an array indexed by the «Resource» index, with the amount of capacity provided by each resource. The optional «active» flag, if specified, is also indexed by «Resource» and is true when the indicated «Resource» can be used to fill the demand, false if it cannot be applied to the demand.
+
== Dispatch(demand, capacity, resources'', active, minimum, increment, method{{Release|6.0||, rollover, demandRollsOver, capacityRollsOver}}'') ==
 +
Given the maximum «capacity» for each of a list of «resources», it allocates «capacity» from each «resources» in sequence so that the total allocated meets the «demand». Dispatch is useful for a variety of allocation problems, including dispatching power from a set of power plants «resources» each with a specified  «capacity» to meet  total power «demand», and allocating a limited budget («demand») among competing projects each with a specified cost  («capacity»).  For example, given the generating capacity in MW of a set of power plants «resources», it dispatches them so that the sum of the amount capacity dispatched for all plants matches the «demand» in MW. It works along the list of plants («resources») allocating its generation up to its maximum capacity, until it reaches the demandIf you order the plants in «resources» by increasing marginal cost ($/MWh), it performs "economic dispatch" -- i.e. it dispatches lower-cost plants first to minimize total cost of generation. It returns an array of allocated capacity, each with a value between 0 and «capacity», indexed by «resources».  Usually, the first n-1 elements of  «resources» are allocated at full  «capacity»; the nth «resources» may be allocated partially; and the remaining «resources» are allocated at zero. If the «demand» is greater than sum of «capacity» over «resources», all elements will be equal to their full «capacity», but the result will not meet the demand.
  
The result is an array indexed by «Resource», containing for each resource the amount of the available capacity consumed in order to fulfill the demand.  The sum of the elements in the result will equal «demand» provided that there is sufficient capacity to fulfill the demand.  All the non-zero elements in the result, except for the final non-zero element, will equal the corresponding value in «capacity».  The last non-zero element in the result will usually be less than the available capacity, since only the amount of that last resource required to fill the last part of the demand is consumed, leaving the remaining part available.
+
[[Null]] values in capacity are passed through as [[Null]] values in the result.
  
The optional «minimum» or «increment» parameters, which may also be indexed by «Resource», specify that the given resources must be dispatched in fixed increments, with at least «minimum» capacity dispatched.  When «increment» is specified, partial increments are not allowed.  When the same value is passed to «capacity» and «increment» (or «minimum»), then Resources must be allocated fully or not at all[[Null]] or zero values in «increment» (or «minimum») for specific projects specify that no increment (or minimum) applies.  Preceding resources take precedence, so the amount of remaining demand carried forward is only the demand that could not be allocated to the previous resource, either because there wasn't enough to meet the «minimum», was more than «capacity», or wasn't enough to complete an «increment». Even if «minimum» is not a multiple of «increment», the result will always be a multiple of «increment».
+
The optional «active» flag, also indexed by «resource», is <code>True</code> (1) or <code>False</code> (0) to indicate whether each «Resource» can be used to fill the demandThis is useful if some elements are unavailable, or if you want to dispatch over a number of regions, in which resources in each region may only supply the demand in that region. (See the Electric power example below.)
  
= Example Uses =
+
You may specify a «minimum» level for each resource, so that, if dispatched at all, it must be at least «minimum» capacity. And an «increment» to specify that a resource must be dispatched with an integral number of increments of capacity. You may index parameters  «minimum» and «increment» by «resources» to specify different values for each resource.  If «minimum» or «increment» has the same value as «capacity», it means that that resource must be allocated fully or not at all.  A [[Null]] or zero values for «increment» or «minimum»  specifies that there is no minimum increment (or the minimum is zero).  Even if «minimum» is not a multiple of «increment», the result will always be a multiple of «increment» and less than «capacity».
  
== Electrical power dispatch ==
+
=== Method ===  
  
A certain region has a set of electrical power plants (the ''Resources'')Each power plant has a maximum amount of power that it can supply (its ''capacity''), and supplies its power at a given marginal cost per KWh. The region must satisfy a certain known electric power ''demand'', dispatching first from those plants with the lowest marginal cost.  Plants have already been sorted by ascending marginal cost, then [[Dispatch]] is used to compute how much power to utilize from each plant.
+
If you specify a nonzero «minimum» and/or «increment», it is possible that the allocation cannot match the «demand» exactly. The value of «method»  specifies how to handled this situation:
 +
* <code>0</code> = never exceed «demand» (default)
 +
* <code>1</code> = meet or exceed demand, if possible.
 +
* <code>2</code> = meet of exceed demand, if possible, and strictly maximize allocation of earlier resources.
  
Dispatch( Demand, Plant_Capacity, Plants )
+
If you are using Dispatch() to allocate resources within a limited budget, you'll want to use <code>method: 0</code>. If you are allocating generation capacity to meet demand, you'll want to use <code>method: 1</code>, or possibly <code>method: 2</code> if your generators have a strict priority ordering.
  
In a variation on this problem, the region is divided into counties. Each county has its own demand (so ''Demand_by_county'' is indexed by ''County''), and each county can only consume power from plants located in that county.  ''Plant_county'' is indexed by Plant and evaluates to the county that the Plant is located in.
+
Method 2 ensures that the first resource always provides as much as possible, up to a maximum point of just meeting demand. Then resource 2 allocates as much as possible up to the point of just meeting demand. And so on. This method gives each resource a strict precedence over all preceding resources, but may over-allocate. It also results in the first n-1 resources allocated at full capacity, followed by the nth resource at partial capacity up to the point where «demand» is met. In contrast, Method 2 still gives priority to earlier resources, but may elect to operate earlier resources at less that full capacity when the later resources are required no matter what. The [[#Method differences|Method differences example]] below illustrates the difference.
  
Dispatch( Demand_by_county, Plant_Capacity, Plants, active: Plant_County=County )
+
The «method» parameter is irrelevant if all resources can be allocated continuously -- i.e. they have «increment» and «minimum» of zero (the defaults).
  
== Investment Allocation ==
+
=== Rollover ===
 +
''New to [[Analytica 6.0]]''
  
 +
You can rollover unmet demand or unused capacity to the next time period by specifying the optional «rollover» index, which serves as a time-like index. If the «rollover» index is not specified, neither rolls over. When demand or capacity is rolled over, it is added to the «demand» or «capacity» specified for that time period.
 +
 +
You can specify whether demand or capacity, or both, rolls over by setting the optional parameters «demandRollsOver» and «capacityRollsOver» to true or false. These default to <code>demandRollsOver:True</code> and <code>capacityRollsOver:false</code>.
 +
 +
All parameters can vary along the «rollover» index.  When «demandRollsOver» or «capacityRollsOver» varies by «rollover», then the value at <code>Rollover=t</code> determines whether the unmet demand after the assignment for time <code>t</code> rolls over to <code>t+1</code>.
 +
 +
In accordance with Analytica's standard rules for arrays, if you pass in a «demand» that is not indexed by the «rollover» index, this is equivalent to specifying that the same demand (before rollover) applies to every time period. If you want to start with a total demand that gets depleted at each time period, you'll need to zero out «demand» for all but the first slice along «rollover», e.g.,
 +
:<code>[[Dispatch]]( demand * (@Time=1), capacity, Resource, rollover:Time )</code>
 +
The same applies to capacity, e.g.,
 +
:<code>[[Dispatch]]( demand , capacity* (@Time=1), Resource, rollover:Time, demandRollsOver:false, capacityRollsOver:true)</code>
 +
 +
If you set «method» to 1 or 2, then the allocation may exceed demand. In this case, no unmet demand is rolled over, and specifically, it does not roll over a negative unmet demand.
 +
 +
== History ==
 +
 +
Parameter Method was introduced in  [[Analytica 4.6]]. Earlier releases use method 1.
 +
 +
The ability to rollover unmet demand or unused capacity is new to [[Analytica 6.0]].
 +
 +
== Examples ==
 +
=== Electrical power dispatch ===
 +
 +
An island has a set of electrical power plants (the ''Resources''), each with a maximum power ''capacity'' in Megawatts (MW), to meet the ''demand'' in MW.  Each plant has a marginal cost of generation in $/KWh as ''Marginal_cost''. We dispatch the plants stored in order of increasing marginal cost to minimize the total generation cost:
 +
:<code>Index Plants_ordered := SortIndex(Marginal_cost, Plants)</code>
 +
:<code>Dispatch(Demand, Plant_Capacity[Plants = Plants_ordered], Plants_ordered)</code>
 +
 +
In a variation of this problem, the island is divided into regions, each with its own demand -- <code>Demand_by_region</code> is indexed by <code>Region</code>. Since this island has no long-range transmission lines, each region can consume power only from local plants in that region.  <code>Region_by_plant</code> gives the region in which each <code>Plant</code> is located. We use the optional parameter active to control which plants are available for allocation in each <code>Region</code>:
 +
 +
:<code>Index Plants_ordered := SortIndex(Marginal_cost, Plants)</code>
 +
:<code>Dispatch(Demand_by_region, Capacity[Plants = Plants_ordered], Plants_ordered, Active: Region_by_plant[Plants = Plants_ordered] = Region)</code>
 +
 +
=== Investment Allocation ===
 
An investor creates a model that ranks possible investment by quality (perhaps [[MIrr]], for example).  He has a fixed budget to invest, and has limits on the maximum amount that can be allocated to any given investment (the maximum varies by investment).  He's already sorted his investments by ascending quality.  He uses [[Dispatch]] to determine how much money to place in each investment.
 
An investor creates a model that ranks possible investment by quality (perhaps [[MIrr]], for example).  He has a fixed budget to invest, and has limits on the maximum amount that can be allocated to any given investment (the maximum varies by investment).  He's already sorted his investments by ascending quality.  He uses [[Dispatch]] to determine how much money to place in each investment.
  
Dispatch( investment_amount, allocation_maximum, Investments )
+
:<code>Dispatch(investment_amount, allocation_maximum, Investments)</code>
 +
 
 +
=== Project Budgeting ===
 +
A company has a set of potential projects, sorted by expected ROI.  They have a fixed budget to invest.  Each project undertaken must be funded at a minimum level, or not at all.  However, once funded, a project with a better ROI should receive as much funding as possible, up to the full project_cost.
 +
 
 +
:<code>Dispatch(Budget, Project_cost, Project, minimum:Project_minimum)</code>
 +
 
 +
=== Method differences ===
 +
This example illustrates the difference between the «method»s that can be utilized when some of the resources have a «minimum» or «increment». The presence of a non-continuous resource may mean that you can't match your «demand» precisely. When allocating within a budget, you want to ensure the allocation never exceeds the «demand» (the «demand» parameter here serves as the budget). When dispatching generation capacity you want to meet of exceed «demand»; however, however there are at least two variants on this, reflected by methods 1 and 2.
  
== Project Budgeting ==
+
:<code>Demand = 12</code>
 +
:{|class="wikitable"
 +
! rowspan="2" | Resource
 +
! rowspan="2" | Capacity
 +
! rowspan="2" | Increment
 +
! colspan="3" | Allocation
 +
|-
 +
! Method 0 !! Method 1 !! Method 2
 +
|-
 +
| 1 || 8 || 0 || 8 || 2 || 8
 +
|-
 +
| 2 || 20 || 10 || 0 || 10 || 10
 +
|-
 +
| colspan="3" align="right" | '''Total:'''
 +
| 8 || 12 || 18
 +
|}
  
A company has a set of potential projects, sorted by expected ROIThey have a fixed budget to investEach project undertaken must be funded at a minimum level, or not at all. However, once funded, a project with a better ROI should receive as much funding as possible, up to the full project_cost.
+
Notice that both of methods 1 and 2 meet or exceed the demand of 12. Method 2 operates the first resource at full capacity, and as a result overshoots the demand since it has needs some of resource 2 but can only allocate in increments of 10. Since you will need use 10 units of the second resource no matter what, Method 2 reduces the allocation from the first resource, and hence avoids overshooting the demand.
 +
 
 +
== Dispatching in reverse ==
 +
In some cases, you may want to dispatch from the end of the «Resource» index first, just because of how you defined your indexFor example, you want to may dispatch the oldest along an Age index, where index Age is in increasing orderThis is facilitated by creating a reverse index mapping.
 +
 
 +
:<code>Variable ReverseAge := <code>Slice(Age, size(Age) + 1 - @Age)</code>
 +
 
 +
Each parameter that uses an array indexed by «Resource» is then reversed, and the final result of [[Dispatch]] is reversed.
  
Dispatch( Budget, Project_cost, Project, minimum:Project_minimum )
+
:<code>Dispatch(Consumption, Inventory[Age = ReverseAge], ReverseAge, isActive[Age = ReverseAge])[ReverseAge = Age]</code>
  
= See Also =
+
Notice that you have to reverse the «capacity», «active», «minimum» and «increment» parameter.
  
* [[Cumulate]], [[Uncumulate]]
+
== See Also ==
 +
* [[Cumulate]]
 +
* [[Uncumulate]]
 +
* [[Financial functions]]

Latest revision as of 00:33, 14 January 2021




Release:

4.6  •  5.0  •  5.1  •  5.2  •  5.3  •  5.4  •  6.0  •  6.1  •  6.2  •  6.3  •  6.4  •  6.5  •  6.6


Dispatch(demand, capacity, resources, active, minimum, increment, method, rollover, demandRollsOver, capacityRollsOver)

Given the maximum «capacity» for each of a list of «resources», it allocates «capacity» from each «resources» in sequence so that the total allocated meets the «demand». Dispatch is useful for a variety of allocation problems, including dispatching power from a set of power plants «resources» each with a specified «capacity» to meet total power «demand», and allocating a limited budget («demand») among competing projects each with a specified cost («capacity»). For example, given the generating capacity in MW of a set of power plants «resources», it dispatches them so that the sum of the amount capacity dispatched for all plants matches the «demand» in MW. It works along the list of plants («resources») allocating its generation up to its maximum capacity, until it reaches the demand. If you order the plants in «resources» by increasing marginal cost ($/MWh), it performs "economic dispatch" -- i.e. it dispatches lower-cost plants first to minimize total cost of generation. It returns an array of allocated capacity, each with a value between 0 and «capacity», indexed by «resources». Usually, the first n-1 elements of «resources» are allocated at full «capacity»; the nth «resources» may be allocated partially; and the remaining «resources» are allocated at zero. If the «demand» is greater than sum of «capacity» over «resources», all elements will be equal to their full «capacity», but the result will not meet the demand.

Null values in capacity are passed through as Null values in the result.

The optional «active» flag, also indexed by «resource», is True (1) or False (0) to indicate whether each «Resource» can be used to fill the demand. This is useful if some elements are unavailable, or if you want to dispatch over a number of regions, in which resources in each region may only supply the demand in that region. (See the Electric power example below.)

You may specify a «minimum» level for each resource, so that, if dispatched at all, it must be at least «minimum» capacity. And an «increment» to specify that a resource must be dispatched with an integral number of increments of capacity. You may index parameters «minimum» and «increment» by «resources» to specify different values for each resource. If «minimum» or «increment» has the same value as «capacity», it means that that resource must be allocated fully or not at all. A Null or zero values for «increment» or «minimum» specifies that there is no minimum increment (or the minimum is zero). Even if «minimum» is not a multiple of «increment», the result will always be a multiple of «increment» and less than «capacity».

Method

If you specify a nonzero «minimum» and/or «increment», it is possible that the allocation cannot match the «demand» exactly. The value of «method» specifies how to handled this situation:

  • 0 = never exceed «demand» (default)
  • 1 = meet or exceed demand, if possible.
  • 2 = meet of exceed demand, if possible, and strictly maximize allocation of earlier resources.

If you are using Dispatch() to allocate resources within a limited budget, you'll want to use method: 0. If you are allocating generation capacity to meet demand, you'll want to use method: 1, or possibly method: 2 if your generators have a strict priority ordering.

Method 2 ensures that the first resource always provides as much as possible, up to a maximum point of just meeting demand. Then resource 2 allocates as much as possible up to the point of just meeting demand. And so on. This method gives each resource a strict precedence over all preceding resources, but may over-allocate. It also results in the first n-1 resources allocated at full capacity, followed by the nth resource at partial capacity up to the point where «demand» is met. In contrast, Method 2 still gives priority to earlier resources, but may elect to operate earlier resources at less that full capacity when the later resources are required no matter what. The Method differences example below illustrates the difference.

The «method» parameter is irrelevant if all resources can be allocated continuously -- i.e. they have «increment» and «minimum» of zero (the defaults).

Rollover

New to Analytica 6.0

You can rollover unmet demand or unused capacity to the next time period by specifying the optional «rollover» index, which serves as a time-like index. If the «rollover» index is not specified, neither rolls over. When demand or capacity is rolled over, it is added to the «demand» or «capacity» specified for that time period.

You can specify whether demand or capacity, or both, rolls over by setting the optional parameters «demandRollsOver» and «capacityRollsOver» to true or false. These default to demandRollsOver:True and capacityRollsOver:false.

All parameters can vary along the «rollover» index. When «demandRollsOver» or «capacityRollsOver» varies by «rollover», then the value at Rollover=t determines whether the unmet demand after the assignment for time t rolls over to t+1.

In accordance with Analytica's standard rules for arrays, if you pass in a «demand» that is not indexed by the «rollover» index, this is equivalent to specifying that the same demand (before rollover) applies to every time period. If you want to start with a total demand that gets depleted at each time period, you'll need to zero out «demand» for all but the first slice along «rollover», e.g.,

Dispatch( demand * (@Time=1), capacity, Resource, rollover:Time )

The same applies to capacity, e.g.,

Dispatch( demand , capacity* (@Time=1), Resource, rollover:Time, demandRollsOver:false, capacityRollsOver:true)

If you set «method» to 1 or 2, then the allocation may exceed demand. In this case, no unmet demand is rolled over, and specifically, it does not roll over a negative unmet demand.

History

Parameter Method was introduced in Analytica 4.6. Earlier releases use method 1.

The ability to rollover unmet demand or unused capacity is new to Analytica 6.0.

Examples

Electrical power dispatch

An island has a set of electrical power plants (the Resources), each with a maximum power capacity in Megawatts (MW), to meet the demand in MW. Each plant has a marginal cost of generation in $/KWh as Marginal_cost. We dispatch the plants stored in order of increasing marginal cost to minimize the total generation cost:

Index Plants_ordered := SortIndex(Marginal_cost, Plants)
Dispatch(Demand, Plant_Capacity[Plants = Plants_ordered], Plants_ordered)

In a variation of this problem, the island is divided into regions, each with its own demand -- Demand_by_region is indexed by Region. Since this island has no long-range transmission lines, each region can consume power only from local plants in that region. Region_by_plant gives the region in which each Plant is located. We use the optional parameter active to control which plants are available for allocation in each Region:

Index Plants_ordered := SortIndex(Marginal_cost, Plants)
Dispatch(Demand_by_region, Capacity[Plants = Plants_ordered], Plants_ordered, Active: Region_by_plant[Plants = Plants_ordered] = Region)

Investment Allocation

An investor creates a model that ranks possible investment by quality (perhaps MIrr, for example). He has a fixed budget to invest, and has limits on the maximum amount that can be allocated to any given investment (the maximum varies by investment). He's already sorted his investments by ascending quality. He uses Dispatch to determine how much money to place in each investment.

Dispatch(investment_amount, allocation_maximum, Investments)

Project Budgeting

A company has a set of potential projects, sorted by expected ROI. They have a fixed budget to invest. Each project undertaken must be funded at a minimum level, or not at all. However, once funded, a project with a better ROI should receive as much funding as possible, up to the full project_cost.

Dispatch(Budget, Project_cost, Project, minimum:Project_minimum)

Method differences

This example illustrates the difference between the «method»s that can be utilized when some of the resources have a «minimum» or «increment». The presence of a non-continuous resource may mean that you can't match your «demand» precisely. When allocating within a budget, you want to ensure the allocation never exceeds the «demand» (the «demand» parameter here serves as the budget). When dispatching generation capacity you want to meet of exceed «demand»; however, however there are at least two variants on this, reflected by methods 1 and 2.

Demand = 12
Resource Capacity Increment Allocation
Method 0 Method 1 Method 2
1 8 0 8 2 8
2 20 10 0 10 10
Total: 8 12 18

Notice that both of methods 1 and 2 meet or exceed the demand of 12. Method 2 operates the first resource at full capacity, and as a result overshoots the demand since it has needs some of resource 2 but can only allocate in increments of 10. Since you will need use 10 units of the second resource no matter what, Method 2 reduces the allocation from the first resource, and hence avoids overshooting the demand.

Dispatching in reverse

In some cases, you may want to dispatch from the end of the «Resource» index first, just because of how you defined your index. For example, you want to may dispatch the oldest along an Age index, where index Age is in increasing order. This is facilitated by creating a reverse index mapping.

Variable ReverseAge := Slice(Age, size(Age) + 1 - @Age)

Each parameter that uses an array indexed by «Resource» is then reversed, and the final result of Dispatch is reversed.

Dispatch(Consumption, Inventory[Age = ReverseAge], ReverseAge, isActive[Age = ReverseAge])[ReverseAge = Age]

Notice that you have to reverse the «capacity», «active», «minimum» and «increment» parameter.

See Also

Comments


You are not allowed to post comments.