/// <summary> /// Allocate the resource using a fair distribution, /// i.e. all stocks are spread evenly across all demands /// across the list of cells on a pro-rata basis of the demands. /// If a cell is asking for X % of the total demand, /// it will allocated with X % of what's available. /// This code supports several distribution models: /// - spread: all stocks of the maps are spread evenly /// - local: only stocks up to some distance of demands can be used /// - attenuation: stocks availability decreases linearly with distance /// Return the Allocation for this Resource /// </summary> /// <param name="currentTime">Current simulation Time</param> /// <param name="resource"></param> /// <param name="cells">List of Cells</param> /// <returns>Allocation</returns> public static Allocation AllocateAsSolomon(Time currentTime, Resource resource, IEnumerable cells) { //-- Build the list of Stocks and Demands AllocationContext context = new AllocationContext(); context.Build(resource, cells); //-- Step 1: build the Clusters table float[,] cluster = new float[context.DemandCells.Count, context.Stocks.Count]; for (int i = 0; i < context.DemandCells.Count; i++) { for (int j = 0; j < context.Stocks.Count; j++) { cluster[i, j] = resource.ResourceToDemandConnection(context.StockCells[j], context.DemandCells[i]); } } //-- Steps 2, 3, 4 and 5: float[,] allocationTable = SolomonSpread(cluster, context.StockValues, context.DemandValues); //-- Done: we now know for each demand how much of each stock we'll allocate return(new Allocation(resource.Id, context.DemandCells, context.Stocks, allocationTable)); }
/// <summary> /// Allocates stocks using a first algorithm, i.e. a Demand tries to get /// as much as possible from the closest stock, and move further only if /// still not satisfied. /// </summary> /// <param name="currentTime">Current simulation Time</param> /// <param name="resource"></param> /// <param name="cells">List of Cells</param> /// <param name="dmax">Maximum distance for this list of Cells</param> /// <param name="distribution">Distribution mode</param> /// <returns>Allocation</returns> public static Allocation AllocateAsHarpagon(Time currentTime, Resource resource, IEnumerable cells, int dmax, string distribution) { float allocatedDemand = 0.0f; AllocationContext context = new AllocationContext(); context.Build(resource, cells); float[,] allocationTable = new float[context.DemandCells.Count, context.Stocks.Count]; int[] demandDistances; if (distribution == "nearest") { demandDistances = new int[context.DemandCells.Count]; } else { demandDistances = new int[] { }; } //-- For each distance from 0 to dmax, and as long as there are unsatisfied Demands for (int distance = 0; (distance < dmax) && (allocatedDemand < context.TotalDemand); distance++) { //-- Build a filtered list of demands and stocks, deducting what was already allocated float[] demands = new float[context.DemandValues.Length]; for (int i = 0; i < demands.Length; i++) { demands[i] = Math.Max(0.0f, context.DemandValues[i] - AlreadyAllocatedDemand(i, allocationTable)); } float[] stocks = new float[context.StockValues.Length]; for (int j = 0; j < context.StockValues.Length; j++) { stocks[j] = Math.Max(0.0f, context.StockValues[j] - AlreadyAllocatedStock(j, allocationTable)); } //-- Extract a filtered cluster float[,] cluster = new float[context.DemandCells.Count, context.StockCells.Count]; for (int i = 0; i < context.DemandCells.Count; i++) { int filterDistance; if (distribution == "nearest") { filterDistance = NearestDistance(demandDistances[i], dmax, context.DemandCells[i], context.StockCells); demandDistances[i] = filterDistance; // Keep a copy for each Demand } else { filterDistance = distance; } if (filterDistance >= 0) { for (int j = 0; j < context.StockCells.Count; j++) { if ((context.DemandCells[i].DistanceTo(context.StockCells[j]) == filterDistance) && (demands[i] > 0.0f) && (stocks[j] > 0.0f)) { cluster[i, j] = 1.0f; } } } if (distribution == "nearest") { demandDistances[i]++; } } //-- Perform a Solomon spread on this (filtered) cluster of (filtered) demands and stocks float[,] allocation = SolomonSpread(cluster, stocks, demands); //-- Now add it to the global allocation for (int i = 0; i < context.DemandCells.Count; i++) { for (int j = 0; j < context.Stocks.Count; j++) { allocationTable[i, j] += allocation[i, j]; allocatedDemand += allocation[i, j]; } } } //-- Done: we now know for each demand how much of each stock we'll allocate return(new Allocation(resource.Id, context.DemandCells, context.Stocks, allocationTable)); } //AllocateAsHarpagon