예제 #1
0
        /// <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));
        }
예제 #2
0
        /// <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