Example #1
0
        /// <summary>
        /// This method will compute any possible possibilities for the next split (predictions),
        /// will make some stats on it, and then take a decision to keep the best one
        /// </summary>
        /// <param name="splitIndex">split index (starting from 0)</param>
        /// <param name="prevMostPopSof">Most Populated class SoF of the previous split</param>
        /// <returns></returns>
        private Data.PredictionOfSplits ComputeFieldPredictionsAndKeepTheBest(int splitIndex, int prevMostPopSof)
        {
            // remaining class car queues which contains cars in it
            var availableQueues = (from r in classesQueues where r.CarsCount > 0 select r).ToList();
            int remainingQueues = availableQueues.Count;

            // enum classes ids
            var availableClassesId = (from r in availableQueues select r.CarClassId).ToList();

            // Get the Truth Table of any possibile combinations for the current split (splitIndex)
            Calc.EveryCombinations combS = new EveryCombinations(availableClassesId);
            // Get anothe Truth Table of any possibile combinations for the next split (splitIndex+1)
            Calc.EveryCombinations combNS = new EveryCombinations(availableClassesId);


            // generate all possible predictions
            List <PredictionOfSplits> predictions = new List <PredictionOfSplits>();

            foreach (var cS in combS.Combinations)
            {
                foreach (var cNS in combNS.Combinations)
                {
                    if (cNS.NumberOfTrue >= remainingQueues)
                    {
                        PredictionOfSplits prediction = new PredictionOfSplits();
                        prediction.CurrentSplit = GenerateSplitFromCombination(splitIndex + 1, cS);
                        prediction.NextSplit    = GenerateSplitFromCombination(splitIndex + 2, cNS, prediction.CurrentSplit);
                        if (prediction.CurrentSplit.TotalCarsCount > 0 && prediction.NextSplit.TotalCarsCount > 0)
                        {
                            predictions.Add(prediction);
                        }
                    }
                }
            }

            // calc stats of all predictions
            List <PredictionOfSplits> predictions2 = new List <PredictionOfSplits>(); // a new list

            foreach (var prediction in predictions)                                   // for each existing prediction
            {
                prediction.CalcStats(prevMostPopSof);                                 // calc stats
                predictions2.Add(prediction);                                         // add it to a new list

                if (ParameterRatingThresholdValue > 0)                                // it the iRating split option is enabled
                {
                    // compute another prediction with cutting the split
                    var variations = prediction.CuttedVariation(ParameterRatingThresholdValue, prevMostPopSof, minCarsToHalfSplits);
                    if (variations != null && variations.Count > 0)
                    {
                        predictions2.AddRange(variations);                                             // if available, add this new predictions to the list
                    }
                }
            }


            if (predictions2.Count == 0)
            {
                return(null);
            }

            // Choose the best now prediction
            PredictionsEvaluator eval = new PredictionsEvaluator(predictions2, classesQueues,
                                                                 ParameterMaxSofDiffValue,
                                                                 ParameterMaxSofFunctStartingIRValue,
                                                                 ParameterMaxSofFunctStartingThreshold,
                                                                 ParameterMaxSofFunctExtraThresoldPerK,
                                                                 ParameterTopSplitExceptionValue,
                                                                 ParameterDebugFileValue,
                                                                 ParameterNoMiddleClassesEmptyValue);
            PredictionOfSplits bestScenario = eval.GetBest();

            return(bestScenario);
        }
Example #2
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
        }