-
Notifications
You must be signed in to change notification settings - Fork 1
Function discrete alloc
- discrete_alloc(TypeNames, LandUnitDomain, SuitabilityMaps, Partitionings, PartitioningNames, AtomicRegions, AtomicRegionMap, MinClaims, MaxClaims, Threshold, FeasibleSolution)
The last argument (FeasibleSolution) may be omitted. Variants for a single or no regional partitioning (discrete_alloc_sp, discrete_alloc_np) and for large sets of land-use types (discrete_alloc_16) are listed on the Allocation functions page.
The discrete_alloc function is used to let the GeoDms perform discrete allocation: it assigns to each land unit the land use type with the highest suitability, under the constraint of regional minimum and maximum claims per land use type.
| # | argument | description | type | value type |
|---|---|---|---|---|
| 1 | TypeNames | This attribute contains the land-use type names. Its domain unit defines the set of land-use types. For each name, the SuitabilityMaps, MinClaims and MaxClaims containers must contain a subitem with exactly that name. | attribute | string |
| 2 | LandUnitDomain | This domain unit defines the set of land units. It can be of any value type, as long as the total number of land units fits in a uint32; it usually defines a grid domain or a subset thereof. | unit | uint32 or point |
| 3 | SuitabilityMaps | A container that contains an attribute (domain: LandUnitDomain) for each land-use type that provides suitability for that land-use type for each land unit. All suitability maps must have the same values unit. | container | int32 |
| 4 | Partitionings | maps each land-use type to the id of the partitioning that defines its claim regions | attribute | uint8 |
| 5 | PartitioningNames | maps each partitioning to a partitioning name, such as "Province" or "Municipality". For each name, the AtomicRegions unit must contain an attribute with exactly that name that maps each atomic region to its region in that partitioning. | attribute | string |
| 6 | AtomicRegions | Unit that defines the set of atomic regions: the smallest common refinement of the regions of all partitionings, i.e. each atomic region is an intersection of one region from each partitioning. It is usually derived with the overlay function, see AtomicRegions. | unit | uint8, uint16 or uint32 |
| 7 | AtomicRegionMap | attribute that defines to which atomic region each land unit belongs. | attribute | value type of AtomicRegions |
| 8 | MinClaims | container with for each land-use type an attribute (domain: the partitioning of that type) with the minimum number of land units that should be allocated within each region to that land-use type | container | uint32 |
| 9 | MaxClaims | container with for each land-use type an attribute (domain: the partitioning of that type) with the maximum number of land units that may be allocated within each region to that land-use type | container | uint32 |
| 10 | Threshold | minimum suitability value that a land use type must have on a land unit to be allocatable there. Land units for which all suitabilities are below the threshold remain unallocated (null). A higher threshold reduces the set of allocation alternatives, which can result in violated claims even when the FeasibilityTest succeeded. A value of null allows any suitability. | parameter | int32 |
| 11 | FeasibleSolution | arbitrary container, reserved as a feasibility certificate for possible future use. It is never evaluated and may be omitted. | container | (empty) |
The result of the discrete_alloc function is a container with:
- attribute landuse (domain): an attribute that gives per land unit the resulting land use type. Land units for which all suitabilities are below the Threshold get the null value.
- parameter statusFlag: a boolean value indicating if the allocation was feasible
- parameter status: a text value that explains the value of
statusFlag - container shadow_prices: a container with for each LandUseType an
attribute<Price> %Lut.Name%(%Lut.ClaimRegions%)with the resulting shadow price per claim region. - container total_allocated: a container with for each LandUseType an
attribute<UInt32> %Lut.Name%(%Lut.ClaimRegions%). - attribute bid_price (domain): an attribute that indicates the augmented suitability of the highest bidder per each land unit, i.e.
$S_{ij} + \lambda_j$ for the land use type$j$ that the land unit$i$ was allocated to; null for unallocated land units.
If the FeasibilityTest fails, no allocation is attempted: landuse, bid_price, shadow_prices and total_allocated are all filled with null values and only status and statusFlag are informative. If the allocation itself completes with violated claims (statusFlag false), landuse and bid_price still contain the best allocation found, but shadow_prices and total_allocated are filled with null values.
Examples of possible resulting status texts are:
DiscrAlloc completed with a total magnified suitability of 48317397677 over 715179 land units = 67559.866379 per land unit, which is optimal
This text means that an optimal allocation has been generated with an average magnified suitability of 67559.866379. Assuming a magnification factor of 100000, this represents an average suitability (aka transition potential) of 0.67559866379
DiscrAlloc.FeasibilityTest failed: total of the minimum claims is 800000 while there are only 715179 allocatable cells, total minimum claims should be decreased with at least 84821 cells;
This text means that no allocation was attempted because the claims themselves cannot be met, see FeasibilityTest.
ClaimRange(type 0 (Urban), Nuts2 3 (ITC3: Liguria)) = [min 25883, max 26057]; 26062 allocated for price {0, 0};
This indicates that five more land units were allocated than the max claim because no alternatives could be found for allocating urban land use without violating other restrictions.
The statusFlag indicates whether a feasible allocation has been generated: it is true if and only if the FeasibilityTest succeeded and the resulting allocation satisfies all minimum and maximum claims. Land units that remain unallocated due to the Threshold do not violate any restriction themselves, but they can cause minimum claims to remain unmet.
The total_allocated container presents a count of the allocation results per land use type per corresponding claim region.
This is similar to what can be produced with reg_count (Landuse, typeNames, RegionContainer, RegionRefs).
where
RegionContainer is a container with names partitionNames and values equal to the corresponding AtomicRegions/AR[atomicRegionMap] and RegionRefs is defined as partitionNames[partitioning].
In future versions of the GeoDMS, the total_allocated sub-container could be removed or made optional, thus the usage of this part of the results is deprecated since they can easily be obtained by using reg_count explicitly.
container Disc_alloc :=
discrete_alloc(
LandUsePreparation/CBSKlasse/name // 1 string attribute
, Input/Compacted/ADomain // 2 uint32 unit
, Input/Compacted/Suitability // 3 int32 container
, const(0[Partitioning], LandUsePreparation/CBSKlasse) // 4 uint8 attribute
, Partitioning/name // 5 string attribute
, Input/AggRegio // 6 uint16 unit
, Input/Compacted/AtomicRegionMap // 7 uint16 attribute
, Input/Claims/minclaims // 8 uint32 container
, Input/Claims/maxclaims // 9 uint32 container
, threshold // 10 int32 parameter
, FeasibleSolution // 11 (empty) container
);
Value 255 (a.k.a. null-value) out of range of valid Atomic Regions-
Value 65535 (a.k.a. null-value) out of range of valid Atomic Regions- cause: the AtomicRegionMap contains values that are no element of the AtomicRegions unit; most often these are null values (255 for uint8, 65535 for uint16) for land units that are not covered by any region. There might be gaps between regions, which will become null with poly2grid.
- solution: check for null values in the AtomicRegionMap.
-
Claim attribute should contain UInt32 values- solution: configure all MinClaims and MaxClaims attributes with value type uint32.
-
Land Unit set had N elements, but total nr of elements in tiles is M. Use a land unit set with a completely covering tiling- solution: the tiling of the LandUnitDomain must cover the domain completely.
Assuming that there is one solution to the optimization problem, knowing the shadow prices that result from the allocation means that the allocation can be regenerated by simply taking, for each land unit
The
Therefore, within the context of the discrete_alloc function, the shadow prices are also known as a splitter.
For an elaborate description of the splitter perspective, the sampling and scaling, and the complexity analysis, see Tokuyama, T. and Nakano, J. (1995) Efficient algorithms for the Hitchcock transportation problem. SIAM Journal on Computing 24(3): 563-578; the implementation (DiscrAlloc.cpp) documents an expected time complexity of
Degenerate cases are cases where different allocations have the same total suitability, which means that there is a continuum of solutions to the optimization problem when
The discrete_alloc uses virtual perturbation, also known as (Simulation of simplicity: a technique to cope with degenerate cases in geometric algorithms, Edelsbrunner et al.) to decide on degenerate cases. Within the discrete_alloc function, each suitability
Also, the shadow prices internally have an explicit
The discrete_alloc function uses a scaling method to find estimates for the shadow_prices before all data is processed. The land units are processed in the order of a systematic sample: with step size
The shadow prices are initially set to 0. At each pass, each claim is scaled to the sample processed so far: the original claim is multiplied by the sampled fraction of the land units of its claim region (counted per atomic region), where scaled minimum claims are rounded down and scaled maximum claims are rounded up. Scaled claims never decrease from one pass to the next and never exceed the original claims, which are restored exactly at the final pass. All visited land units are allocated to the land use type with the highest augmented suitability, which initially equals the original unaugmented suitability.
Once an allocation of land use type
After processing all land units of a pass while maintaining the feasibility of the maximum claim restrictions, a mirrored procedure called UpdateSplitterUp is called repeatedly to get sufficient land allocated to meet the (scaled) minimum claims.
The usage of RAM or Virtual Address Space by the discrete_alloc function for allocating
- administration of land use types, partitionings and claim region names: insignificant
- administration of claims (with their shadow prices) and facets: proportional to the number of claims resp. facets (bounded by
$K*(K-1)$ per atomic region); normally insignificant compared to the$N$ -sized arrays below. - suitabilityMaps:
$K$ page-files of$N*sizeof(Int32)$ are mapped into memory. - atomicRegionMap: 1 page-file of
$N*sizeof(UInt16)$ is mapped into memory. - resulting landuse: 1 page-file of
$N*sizeof(UInt8)$ is mapped into memory. - resulting bid_price: 1 page-file of
$N*sizeof(Int32)$ , mapped for writing before the allocation starts and filled when it completes. - ordered heaps with reallocation options: used part bounded by $(K-1)Nsizeof(UInt32)$, but up to a double amount can be taken from the dynamic memory pool.
This totals
Historical note: in a Win32 process, where approximately 1.5 GiB was available as heap addresses, the discrete_allocation without selective threshold was safe as long as $(4K+3)N + 2(4K-4)*N = (12K-5)*N < 1.5$ GiB. With
For each claim j that has an overlapping region with claim
The number of reallocation alternatives that are stored in these heaps is bounded by
The growth strategy of the ordered heaps is that when the required size overflows the reserved memory, a memory reallocation with double this size is requested from the dynamic memory pool. This can result in double the amount of memory reserved for the heaps that have been in use during any step of the discrete_alloc algorithm. Furthermore, the dynamic aspect of moving land unit indices from one facet to the other due to reallocations has not been thoroughly analyzed.
A strict threshold will reduce the amount of (re)allocation options and, therefore, the sizes of these ordered heaps.
The domain of the suitability maps and the atomicRegionMap may be tiled (also known as segmented), provided that the tiling covers the domain completely. The current implementation reads the data of all tiles and solves the allocation for the entire domain in one run; the systematic sample of the scaling method spans all tiles.
Previous (GeoDMS 7) versions processed a tiled domain tile by tile, keeping only the data of one tile at a time in memory, with claims scaled per tile and the allocations of earlier tiles frozen: the Tile By Tile Heuristic. An unfortunate permutation of the domain could then result in choices in the first tile(s) that are not optimal or even result in an Infeasible Solution when taking the alternatives of later tiles into account. This heuristic is no longer applied (at least since GeoDMS 8.035); some status texts still refer to (numbers of) tiles.
- concept overview: Discrete Allocation
- overview of Allocation functions
- configuration example: Discrete Allocation Example
- AtomicRegions
- AtomicRegionMap
- FeasibilityTest
GeoDMS ©Object Vision BV. Source code distributed under GNU GPL-3. Documentation distributed under CC BY-SA 4.0.