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; }
/// <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)); }
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 }