Пример #1
0
 public SplitsRepartitionOptimizer(List <Data.Split> splits,
                                   int fieldSize,
                                   List <int> carClassesIds, List <ClassCarsQueue> carclasses,
                                   ClassicAffineDistribution algo)
 {
     this.Splits        = splits;
     this.fieldSize     = fieldSize;
     this.carClassesIds = carClassesIds;
     this.carclasses    = carclasses;
     this.algo          = algo;
 }
Пример #2
0
        /// <summary>
        /// Helper to calc Cars to get
        /// </summary>
        /// <param name="split">the split</param>
        /// <param name="classId">the class id you want to fill</param>
        /// <param name="exceptionClassId">the class ids which are not (or not allowed) in this split</param>
        /// <param name="fieldSizeOrLimit">the available slots count to fill (with every splits)</param>
        /// <returns>the number of cars to get, which is the part of 'fieldSizeOrLimit' corresponding the the classId</returns>
        internal virtual int TakeCars(List <Split> splits, Split split, int classId, List <int> exceptionClassId, int fieldSizeOrLimit)
        {
            if (exceptionClassId == null)
            {
                exceptionClassId = new List <int>();
            }

            List <int>            classesToSelect  = new List <int>();
            Dictionary <int, int> classesRemaining = new Dictionary <int, int>();

            foreach (int id in carClassesIds)
            {
                if (!exceptionClassId.Contains(id))
                {
                    classesToSelect.Add(id);
                    classesRemaining.Add(id, 1);
                }
            }
            ClassicAffineDistribution algo = baseAlgorithm as ClassicAffineDistribution;

            return(algo.TakeClassCars(fieldSizeOrLimit, classesToSelect.Count, classesRemaining, classId, null, split.Number));
        }
Пример #3
0
        public void Compute(List <Line> data, int fieldSize)
        {
            if (ParameterDebugFileValue == 1)
            {
                PredictionsEvaluator.CleanOldDebugFiles();
            }

            minCarsToHalfSplits = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(ParameterMinCarsValue) / 2d));

            // Calc number of splits required
            // And try to reduce fieldSize, if possible, for the same number of splits
            numberOfSplits = Tools.DivideAndCeil(data.Count, fieldSize);
            int betterFieldSize = Tools.DivideAndCeil(data.Count, numberOfSplits);

            this.fieldSize = Math.Min(fieldSize, betterFieldSize);

            // create classes queues
            classesQueues = Tools.SplitCarsPerClass(data);
            classesIds    = (from r in classesQueues select r.CarClassId).ToList();

            // instanciate an ClassicAffineDistributio algorithm to use its car distribution system
            affineDistributor = new ClassicAffineDistribution();
            affineDistributor.ParameterMinCarsValue = this.ParameterMinCarsValue;
            affineDistributor.SetFieldSize(fieldSize);
            affineDistributor.InitData(classesIds, data);

            if (classesQueues.Count == 1)
            {
                // if only one class, the affinedistributor will do the job
                affineDistributor.Compute(data, fieldSize);
                Splits = affineDistributor.Splits;
                return;
            }



            // Starting the process
            Splits = new List <Split>();

            // this variable will contain the SoF Max of the 'Most Populated Class' of the last split
            // it will be given to the next one to help evaluating possible situations
            int prevMaxPopSof = -1;


            // for each split required
            for (int i = 0; i < numberOfSplits; i++)
            {
                // call the prediction algorithm, and get the best situation
                var prediction = ComputeFieldPredictionsAndKeepTheBest(i, prevMaxPopSof);

                // if something is possible
                if (prediction != null)
                {
                    // Create the split, for true.
                    Implement(prediction);

                    // remember the Max SoF of the 'Most Populated Class'
                    prevMaxPopSof = prediction.CurrentSplit.GetMaxClassSof();
                }
            }


            // create the last split ...
            var lastsplit = Splits.Last();

            // by checking any class queues
            for (int i = 0; i < classesQueues.Count; i++)
            {
                // if any cars are still in the queue
                var cars = classesQueues[i].PickCars(classesQueues[i].CarsCount);
                if (cars.Count > 0)
                {
                    // put them in this last split
                    if (lastsplit.GetClassId(i) == 0)
                    {
                        lastsplit.SetClass(i, classesIds[i]);
                    }
                    lastsplit.AppendClassCars(i, cars);
                }
            }


            // call the optimizer process (second pass algorithm) for
            // rounding cars number between splits, or fix some issue
            // if some splits exceed the fieldsize
            classesQueues = Tools.SplitCarsPerClass(data);
            SplitsRepartitionOptimizer optimizer = new SplitsRepartitionOptimizer(Splits,
                                                                                  fieldSize,
                                                                                  classesIds,
                                                                                  classesQueues,
                                                                                  affineDistributor);

            Splits = optimizer.OptimizeAndSolveDifferences(); // now we have the final result
        }