internal GetDlpPolicyTipsResponse(EvaluationResult evalResult, OptimizationResult optimizationResult) : this(evalResult)
 {
     this.OptimizationResult = optimizationResult;
 }
Пример #2
0
 private static string ResultToString(string info, string method, OptimizationResult <double> result)
 {
     return(info + ";" + method + ";" + result.BestValue.ToString() + ";" + result.BestTime.ToString() + ";" + result.BestIteration.ToString() + ";" + result.BestFFE.ToString());
 }
Пример #3
0
        public OptimizationResult Solve(long timeLimitMilliseconds, EventHandler <ProgressReport> progress, EventHandler <string> consoleProgress)
        {
            if (timeLimitMilliseconds < ip5GurobiConfig.ClusteringTimeLimitMiliseconds + ip5GurobiConfig.SchedulingTimeLimitMiliseconds)
            {
                throw new ArgumentOutOfRangeException(nameof(timeLimitMilliseconds), timeLimitMilliseconds, "must be at least the sum of ClusteringTimeLimit and SchedulingTimeLimit");
            }

            consoleProgress?.Invoke(this, "Solving started");

            var sw = Stopwatch.StartNew();

            var clusteringSolverVariableBuilder = new ClusteringSolverVariableBuilder(input, ip5GurobiConfig.TimeSliceDuration);
            var clusteringSolverInputData       = clusteringSolverVariableBuilder.Build();
            var clusteringSolver =
                new Algorithm.Clustering.ClusteringILPSolver(clusteringSolverInputData);


#if WriteMPS && DEBUG
            System.IO.File.WriteAllText($@"C:\Temp\iRuettae\ILP\Clustering\{new Guid()}.mps", clusterinSolver.ExportMPS());
#endif
            var clusteringTimeLimitMiliseconds = ip5GurobiConfig.ClusteringTimeLimitMiliseconds;
            if (clusteringTimeLimitMiliseconds == 0)
            {
                // avoid surpassing timelimit
                clusteringTimeLimitMiliseconds = timeLimitMilliseconds;
            }

            var phase1ResultState = clusteringSolver.Solve(ip5GurobiConfig.ClusteringMIPGap, clusteringTimeLimitMiliseconds);
            if (!(new[] { ResultState.Feasible, ResultState.Optimal }).Contains(phase1ResultState))
            {
                return(new OptimizationResult()
                {
                    OptimizationInput = input,
                    Routes = new Route[] { },
                    TimeElapsed = sw.ElapsedMilliseconds / 1000,
                });
            }

            var phase1Result = clusteringSolver.GetResult();
            progress?.Invoke(this, new ProgressReport(0.5));
            consoleProgress?.Invoke(this, "Clustering done");
            consoleProgress?.Invoke(this, $"Clustering Result: {phase1Result}");


            var schedulingSovlerVariableBuilders = new List <SchedulingSolverVariableBuilder>();
            foreach (var santa in Enumerable.Range(0, phase1Result.Waypoints.GetLength(0)))
            {
                foreach (var day in Enumerable.Range(0, phase1Result.Waypoints.GetLength(1)))
                {
                    var cluster = phase1Result.Waypoints[santa, day];
                    var schedulingOptimizationInput = new OptimizationInput
                    {
                        Visits     = input.Visits.Where(v => cluster.Select(w => w.Visit - 1).Contains(v.Id)).ToArray(),
                        Santas     = new[] { input.Santas[santa] },
                        Days       = new[] { input.Days[day] },
                        RouteCosts = input.RouteCosts,
                    };

                    schedulingSovlerVariableBuilders.Add(new SchedulingSolverVariableBuilder(ip5GurobiConfig.TimeSliceDuration, schedulingOptimizationInput, cluster.OrderBy(wp => wp.StartTime).Select(wp => wp.Visit).ToArray()));
                }
            }

            var schedulingInputVariables = schedulingSovlerVariableBuilders
                                           .Where(vb => vb.Visits != null && vb.Visits.Count > 1)
                                           .Select(vb => vb.Build());


            var routeResults = schedulingInputVariables
                               .AsParallel()
                               .Select(schedulingInputVariable =>
            {
                var schedulingSolver = new SchedulingILPSolver(schedulingInputVariable);

#if WriteMPS && DEBUG
                System.IO.File.WriteAllText($@"C:\Temp\iRuettae\ILP\Scheduling\{new Guid()}.mps", schedulingSolver.ExportMPS());
#endif


                var clusteringExtraTime            = Math.Max(0, clusteringTimeLimitMiliseconds - sw.ElapsedMilliseconds);
                var schedulingTimelimitMiliseconds = ip5GurobiConfig.SchedulingTimeLimitMiliseconds + clusteringExtraTime;
                if (schedulingTimelimitMiliseconds == 0 && timeLimitMilliseconds != 0)
                {
                    // avoid surpassing timelimit
                    schedulingTimelimitMiliseconds = Math.Max(1, timeLimitMilliseconds - sw.ElapsedMilliseconds);
                }

                var schedulingResultState = schedulingSolver.Solve(ip5GurobiConfig.SchedulingMIPGap, schedulingTimelimitMiliseconds);
                if (!(new[] { ResultState.Feasible, ResultState.Optimal }).Contains(schedulingResultState))
                {
                    var realWaypointList = new List <Algorithm.Waypoint>();

                    // take presolved and return it
                    for (int i = 0; i < schedulingInputVariable.Presolved.Length; i++)
                    {
                        var i1        = i;
                        var currVisit = input.Visits.FirstOrDefault(v => v.Id == schedulingInputVariable.Presolved[i1] - 1);

                        var timeStamp = schedulingInputVariable.DayStarts[0];
                        if (i > 0)
                        {
                            var lastVisit = input.Visits.FirstOrDefault(v => v.Id == schedulingInputVariable.Presolved[i - 1] - 1);

                            timeStamp  = realWaypointList.Last().StartTime + lastVisit.Duration;
                            timeStamp += i > 1
                                    ? input.RouteCosts[lastVisit.Id, currVisit.Id]
                                    : currVisit.WayCostFromHome;
                        }

                        realWaypointList.Add(new Algorithm.Waypoint(currVisit.Equals(default(Visit)) ? Constants.VisitIdHome : currVisit.Id,
                                                                    timeStamp));
                    }
                    var absolutlyLastVisit = input.Visits.FirstOrDefault(v => v.Id == schedulingInputVariable.Presolved[schedulingInputVariable.Presolved.Length - 1] - 1);
                    realWaypointList.Add(new Algorithm.Waypoint(Constants.VisitIdHome, realWaypointList.Last().StartTime + absolutlyLastVisit.Duration + absolutlyLastVisit.WayCostToHome));

                    return(new Algorithm.Route(1, 1)
                    {
                        SantaIds = schedulingInputVariable.SantaIds,
                        Waypoints = new[, ]
                        {
                            { realWaypointList }
                        }
                    });
                }

                var route = schedulingSolver.GetResult();

                for (int i = 0; i < route.Waypoints.GetLength(0); i++)
                {
                    for (int j = 0; j < route.Waypoints.GetLength(1); j++)
                    {
                        var realWaypointList = new List <Algorithm.Waypoint>();

                        var waypointList = route.Waypoints[i, j];
                        // copy for later lambda expression
                        var jCopy = j;
                        waypointList.ForEach(wp =>
                        {
                            wp.Visit = wp.Visit == 0
                                    ? Constants.VisitIdHome
                                    : schedulingInputVariable.VisitIds[wp.Visit - 1];
                            wp.StartTime  = Math.Max(wp.StartTime, 0);
                            wp.StartTime *= ip5GurobiConfig.TimeSliceDuration;
                            wp.StartTime += schedulingInputVariable.DayStarts[jCopy];
                            realWaypointList.Add(wp);
                        });
                        route.Waypoints[i, j] = realWaypointList;
                    }
                }
                return(route);
            })
                               .ToList();

            progress?.Invoke(this, new ProgressReport(0.99));
            consoleProgress?.Invoke(this, "Scheduling done");
            consoleProgress?.Invoke(this, $"Scheduling Result:{Environment.NewLine}" +
                                    routeResults.Where(r => r != null).Select(r => r.ToString()).Aggregate((acc, c) => acc + Environment.NewLine + c));

            // construct new output elem
            var optimizationResult = new OptimizationResult()
            {
                OptimizationInput = input,
                Routes            = routeResults.Select(r => r != null ? new Route
                {
                    SantaId   = r.SantaIds[0],
                    Waypoints = r.Waypoints[0, 0].Select(origWp => new Waypoint
                    {
                        VisitId   = origWp.Visit,
                        StartTime = origWp.StartTime
                    }).ToArray(),
                } : new Route()).ToArray(),
            };

            progress?.Invoke(this, new ProgressReport(1));

            // assign total elapsed time
            sw.Stop();
            optimizationResult.TimeElapsed = sw.ElapsedMilliseconds / 1000;
            return(optimizationResult);
        }
        public OptimizationResult Solve(long timeLimitMilliseconds, EventHandler <ProgressReport> progress, EventHandler <string> consoleProgress)
        {
            this.progress        = progress;
            this.consoleProgress = consoleProgress;

            var sw = Stopwatch.StartNew();

            Log("Solving started");
            Log(new ProgressReport(0.01));

            // adjust time limit if unlimited
            if (timeLimitMilliseconds == 0)
            {
                timeLimitMilliseconds = long.MaxValue;
            }

            // init population
            var(population, mapping) = new PopulationGenerator(RandomFactory.Instance).Generate(input, config.PopulationSize, config.MaxNumberOfSantas);
            var decoder = new Decoder(input, mapping);

            // calculate costs
            var result = new OptimizationResult()
            {
                OptimizationInput = input,
            };
            var costCalculator = new CostCalculator(decoder, new SimplifiedOptimizationResult(result));

            costCalculator.RecalculateCost(population);

            // Log characteristics of initial population
            Log($"Genetic Algorithm started with following paramters:{Environment.NewLine}{config}");
            var bestCost = GetMinCost(population);

            Log($"Best solution cost in initial population is: {bestCost}");

            // evolution
            var  evolutionOperation = new EvolutionOperation(config);
            var  repairOperation    = new RepairOperation(input, mapping);
            long generation         = 0;

            for (; generation < config.MaxNumberOfGenerations && sw.ElapsedMilliseconds < timeLimitMilliseconds; generation++)
            {
                // evolve
                evolutionOperation.Evolve(population);

                // repair
                repairOperation.Repair(population);

                // recalculate costs
                costCalculator.RecalculateCost(population);

                // log current solution
                var currentBestCost = GetMinCost(population);
                if (currentBestCost < bestCost)
                {
                    bestCost = currentBestCost;
                    Log($"Found better solution in generation {generation} with cost={bestCost}");
                }
            }

            Log($"Finished at generation {generation} with cost={bestCost}");
            Log($"Current stdev is {StDev(population.Select(i => (double)i.Cost).ToList())}");
            Log(new ProgressReport(0.99));

            // build result
            var bestSolution = population.OrderBy(i => i.Cost).First();

            result.Routes      = decoder.Decode(bestSolution);
            result.ResultState = ResultState.Finished;

            Log(new ProgressReport(1));

            sw.Stop();
            result.TimeElapsed = sw.ElapsedMilliseconds / 1000;
            return(result);
        }
Пример #5
0
 private void setResults(OptimizationResult oResults)
 {
     if (InvokeRequired)
     {
         Invoke(new setResultsDelegate(setResults), new object[1]
         {
             oResults
         });
     }
     else
     {
         BindData(false);
         //if (m_nLastCall == 4)
         //{
         //    foreach (DataRow dataRow in (InternalDataCollectionBase) tblOscillator.Rows)
         //        dataRow[2] = "undecided";
         //    foreach (ArrayList arrayList in oResults)
         //    {
         //        var str = (string) arrayList[0];
         //        var flag = (bool) arrayList[1];
         //        foreach (DataRow dataRow in (InternalDataCollectionBase) tblOscillator.Rows)
         //        {
         //            if ((string) dataRow[0] == str)
         //            {
         //                dataRow.BeginEdit();
         //                dataRow[2] = flag.ToString();
         //                dataRow.EndEdit();
         //            }
         //        }
         //        enableTest(true);
         //    }
         //}
         //else if (m_nLastCall == 3)
         //{
         //    foreach (
         //        DataRow dataRow in
         //            (InternalDataCollectionBase) m_oParameterDataSet.Tables["SwitchParameter"].Rows)
         //        dataRow[2] = "undecided";
         //    foreach (ArrayList arrayList in oResults)
         //    {
         //        var str = (string) arrayList[0];
         //        var flag = (bool) arrayList[1];
         //        foreach (
         //            DataRow dataRow in
         //                (InternalDataCollectionBase) m_oParameterDataSet.Tables["SwitchParameter"].Rows)
         //        {
         //            if ((string) dataRow[0] == str)
         //            {
         //                dataRow.BeginEdit();
         //                dataRow[2] = flag.ToString();
         //                dataRow.EndEdit();
         //            }
         //        }
         //        enableTest(true);
         //    }
         //}
         //else
         {
             int      num1               = oResults.Iterations;
             double   num2               = oResults.Score;
             double[] numArray           = oResults.Values.ToArray();
             double[] realEigenValues    = oResults.RealEigenValues.ToArray();
             double[] complexEigenValues = oResults.ImagEigenValues.ToArray();
             int      num3               = 0;
             for (int index = 0; index < m_oLastSelection.Count; ++index)
             {
                 m_oParameterDataSet.Tables["Parameters"].Rows[(int)m_oLastSelection[index]]["optimized value"]
                     = numArray[num3++];
             }
             m_oParameterDataSet.Tables["EigenValues"].Rows.Clear();
             for (int index = 0; index < realEigenValues.Length; ++index)
             {
                 DataRow row = m_oParameterDataSet.Tables["EigenValues"].NewRow();
                 row[0] = realEigenValues[index];
                 row[1] = complexEigenValues[index];
                 m_oParameterDataSet.Tables["EigenValues"].Rows.Add(row);
             }
             txtEigenValue.Text = "done";
             txtFitness.Text    = num2.ToString("E5");
             if (m_nLastCall == 1)
             {
                 m_dParameters = numArray;
                 tblOscillator.Rows.Clear();
                 foreach (
                     DataRow dataRow in
                     (InternalDataCollectionBase)m_oParameterDataSet.Tables["Parameters"].Rows)
                 {
                     DataRow row = tblOscillator.NewRow();
                     row[0] = dataRow[0];
                     row[1] = true;
                     row[2] = "undecided";
                     tblOscillator.Rows.Add(row);
                 }
                 enableTest(true);
             }
             else if (m_nLastCall == 2)
             {
                 m_dParameters = numArray;
                 m_oParameterDataSet.Tables["SwitchParameter"].Rows.Clear();
                 foreach (
                     DataRow dataRow in
                     (InternalDataCollectionBase)m_oParameterDataSet.Tables["Parameters"].Rows)
                 {
                     DataRow row = m_oParameterDataSet.Tables["SwitchParameter"].NewRow();
                     row[0] = dataRow[0];
                     row[1] = true;
                     row[2] = "undecided";
                     m_oParameterDataSet.Tables["SwitchParameter"].Rows.Add(row);
                 }
                 enableTest(true);
             }
             lblDisplayResult.Text = CheckResult(m_nLastCall, realEigenValues, complexEigenValues);
         }
         BindData(true);
     }
 }
 private void CheckNoAdditionalSantas(OptimizationResult actual)
 {
     Assert.AreEqual(0, actual.NumberOfAdditionalSantas());
 }
        /// <summary>
        /// Checks whether new lean compute job better than previous and run new iteration if necessary.
        /// </summary>
        /// <param name="result">Lean compute job result and corresponding parameter set</param>
        public override void PushNewResults(OptimizationResult result)
        {
            if (!Initialized)
            {
                throw new InvalidOperationException($"EulerSearchOptimizationStrategy.PushNewResults: strategy has not been initialized yet.");
            }

            lock (_locker)
            {
                if (!ReferenceEquals(result, OptimizationResult.Initial) && string.IsNullOrEmpty(result?.JsonBacktestResult))
                {
                    // one of the requested backtests failed
                    _runningParameterSet.Remove(result.ParameterSet);
                    return;
                }

                // check if the incoming result is not the initial seed
                if (result.Id > 0)
                {
                    _runningParameterSet.Remove(result.ParameterSet);
                    ProcessNewResult(result);
                }

                if (_runningParameterSet.Count > 0)
                {
                    // we wait till all backtest end during each euler step
                    return;
                }

                // Once all running backtests have ended, for the current collection of optimization parameters, for each parameter we determine if
                // we can create a new smaller/finer optimization scope
                if (Target.Current.HasValue && OptimizationParameters.OfType <OptimizationStepParameter>().Any(s => s.Step > s.MinStep))
                {
                    var boundaries   = new HashSet <OptimizationParameter>();
                    var parameterSet = Solution.ParameterSet;
                    foreach (var optimizationParameter in OptimizationParameters)
                    {
                        var optimizationStepParameter = optimizationParameter as OptimizationStepParameter;
                        if (optimizationStepParameter != null && optimizationStepParameter.Step > optimizationStepParameter.MinStep)
                        {
                            var newStep   = Math.Max(optimizationStepParameter.MinStep.Value, optimizationStepParameter.Step.Value / _segmentsAmount);
                            var fractal   = newStep * ((decimal)_segmentsAmount / 2);
                            var parameter = parameterSet.Value.First(s => s.Key == optimizationParameter.Name);
                            boundaries.Add(new OptimizationStepParameter(
                                               optimizationParameter.Name,
                                               Math.Max(optimizationStepParameter.MinValue, parameter.Value.ToDecimal() - fractal),
                                               Math.Min(optimizationStepParameter.MaxValue, parameter.Value.ToDecimal() + fractal),
                                               newStep,
                                               optimizationStepParameter.MinStep.Value));
                        }
                        else
                        {
                            boundaries.Add(optimizationParameter);
                        }
                    }

                    OptimizationParameters = boundaries;
                }
                else if (!ReferenceEquals(result, OptimizationResult.Initial))
                {
                    // we ended!
                    return;
                }

                foreach (var parameterSet in Step(OptimizationParameters))
                {
                    OnNewParameterSet(parameterSet);
                }
            }
        }
Пример #8
0
 /// <summary>
 /// Checks whether new lean compute job better than previous and run new iteration if necessary.
 /// </summary>
 /// <param name="result">Lean compute job result and corresponding parameter set</param>
 public abstract void PushNewResults(OptimizationResult result);
 public CostCalculator(Decoder decoder, OptimizationResult temporaryResult)
 {
     this.decoder = decoder;
     this.result  = temporaryResult;
 }
Пример #10
0
 private static string ResultToString <Element>(OptimizationResult <Element> result)
 {
     return(result.BestValue.ToString() + "\t" + result.BestTime.ToString() + "\t" + result.BestIteration.ToString() + "\t" + result.BestFFE.ToString());
 }
Пример #11
0
        public void TrackEstimation()
        {
            Config.Set("optimization-update-interval", 1);
            OptimizationEstimate estimate = null;
            OptimizationResult   result   = null;
            var resetEvent = new ManualResetEvent(false);
            var packet     = new OptimizationNodePacket
            {
                Criterion = new Target("Profit", new Minimization(), null),
                OptimizationParameters = new HashSet <OptimizationParameter>
                {
                    new OptimizationStepParameter("ema-slow", 1, 10, 1),
                    new OptimizationStepParameter("ema-fast", 10, 100, 3)
                },
                Constraints = new List <Constraint>
                {
                    new Constraint("Drawdown", ComparisonOperatorTypes.LessOrEqual, 0.15m)
                },
                MaximumConcurrentBacktests = 5
            };
            var optimizer = new FakeLeanOptimizer(packet);
            // keep stats up-to-date
            int totalBacktest  = optimizer.GetCurrentEstimate().TotalBacktest;
            int totalUpdates   = 0;
            int completedTests = 0;
            int failed         = 0;

            optimizer.Update += (s, e) =>
            {
                estimate = optimizer.GetCurrentEstimate();
                Assert.LessOrEqual(estimate.RunningBacktest, packet.MaximumConcurrentBacktests);
                Assert.LessOrEqual(completedTests, estimate.CompletedBacktest);
                Assert.LessOrEqual(failed, estimate.FailedBacktest);

                Assert.AreEqual(totalBacktest, estimate.TotalBacktest);

                completedTests = estimate.CompletedBacktest;
                failed         = estimate.FailedBacktest;

                if (completedTests > 0)
                {
                    Assert.Greater(estimate.AverageBacktest, TimeSpan.Zero);
                }

                totalUpdates++;
            };
            optimizer.Ended += (s, solution) =>
            {
                result   = solution;
                estimate = optimizer.GetCurrentEstimate();
                optimizer.DisposeSafely();
                resetEvent.Set();
            };

            optimizer.Start();

            resetEvent.WaitOne();

            Assert.NotZero(estimate.CompletedBacktest);
            Assert.NotZero(estimate.FailedBacktest);
            // we have 2 force updates at least, expect a few more over it.
            Assert.Greater(totalUpdates, 2);
            Assert.AreEqual(estimate.CompletedBacktest + estimate.FailedBacktest + estimate.RunningBacktest, totalBacktest);
        }
        public OptimizationResult Solve(long timelimitMiliseconds, EventHandler <ProgressReport> progress,
                                        EventHandler <string> consoleProgress)
        {
            var sw     = Stopwatch.StartNew();
            var output = new OptimizationResult
            {
                OptimizationInput = input
            };

            var timeWindowIsRelevant = !input.Visits.All(visit =>
            {
                if (visit.Desired.Length > 0)
                {
                    return(false);
                }

                return(!visit.Unavailable.Any(unavailable =>
                {
                    var(unavailableFrom, unavailableTo) = unavailable;
                    foreach (var(dayFrom, dayTo) in input.Days)
                    {
                        if (IntersectionLength(unavailableFrom, unavailableTo, dayFrom, dayTo) > 0)
                        {
                            return true;
                        }
                    }
                    return false;
                }));
            });

            // first solve vrp, take result as initial solution.
            if (!timeWindowIsRelevant)
            {
                vrpTimeLimitFactor = 1;
            }

            var vrpSolution = input.Visits.Length > 75 ? FakeVRPSolution(input.Santas.Length * input.Days.Length) : new VRPCallbackSolver(input).SolveVRP((int)(timelimitMiliseconds * vrpTimeLimitFactor));

            consoleProgress?.Invoke(this, $"vrp needed {sw.ElapsedMilliseconds}ms, remaining {timelimitMiliseconds - sw.ElapsedMilliseconds}");

            if (!timeWindowIsRelevant)
            {
                BuildResultFromVRP(output, vrpSolution);
                output.TimeElapsed = sw.ElapsedMilliseconds / 1000;
                return(output);
            }

            timelimitMiliseconds -= sw.ElapsedMilliseconds;
            using (var env = new GRBEnv($"{DateTime.Now:yy-MM-dd-HH-mm-ss}_gurobi.log"))
                using (var model = new GRBModel(env))
                {
                    #region initialize Variables
                    var numberOfRoutes = input.Santas.Length * input.Days.Length;
                    var v = new GRBVar[numberOfRoutes][]; // [santa] visits [visit]
                    var w = new GRBVar[numberOfRoutes][]; // [santa] uses [way]
                    var c = new GRBVar[numberOfRoutes][]; // [santa] visits visit at the end of [way]

                    var desiredDuration     = new GRBVar[numberOfRoutes][][];
                    var unavailableDuration = new GRBVar[numberOfRoutes][][];

                    var maxRoutes = new GRBVar[numberOfRoutes];
                    var minRoutes = new GRBVar[numberOfRoutes];

                    for (int s = 0; s < numberOfRoutes; s++)
                    {
                        v[s] = new GRBVar[visitDurations.Length];
                        c[s] = new GRBVar[visitDurations.Length];
                        desiredDuration[s]     = new GRBVar[visitDurations.Length][];
                        unavailableDuration[s] = new GRBVar[visitDurations.Length][];
                        var(dayStart, dayEnd)  = input.Days[s / input.Santas.Length];
                        var dayDuration = dayEnd - dayStart;
                        for (int i = 0; i < v[s].Length; i++)
                        {
                            v[s][i] = model.AddVar(0, 1, 0.0, GRB.BINARY, GurobiVarName($"v[{s}][{i}]"));
                            c[s][i] = model.AddVar(0, dayDuration, 0, GRB.CONTINUOUS, GurobiVarName($"c[{s}][{i}]"));

                            if (i > 0)
                            {
                                var visit = input.Visits[i - 1];
                                desiredDuration[s][i]     = new GRBVar[visit.Desired.Length];
                                unavailableDuration[s][i] = new GRBVar[visit.Unavailable.Length];

                                for (int d = 0; d < visit.Desired.Length; d++)
                                {
                                    var ub = Math.Max(0, Math.Min(visit.Duration, visit.Desired[d].to - visit.Desired[d].from));
                                    desiredDuration[s][i][d] = model.AddVar(0, ub, 0, GRB.CONTINUOUS, GurobiVarName($"desiredDuration[{s}][{i}][{d}]"));
                                }

                                for (int u = 0; u < visit.Unavailable.Length; u++)
                                {
                                    var ub = Math.Max(0, Math.Min(visit.Duration, visit.Unavailable[u].to - visit.Unavailable[u].from));
                                    unavailableDuration[s][i][u] = model.AddVar(0, ub, 0, GRB.CONTINUOUS, GurobiVarName($"unavailableDuration[{s}][{i}][{u}]"));
                                }
                            }
                        }

                        w[s]         = model.AddVars(distances.GetLength(0) * distances.GetLength(1), GRB.BINARY);
                        maxRoutes[s] = model.AddVar(0, dayEnd - dayStart, 0, GRB.CONTINUOUS, GurobiVarName($"santa{s} maxRoute"));
                        minRoutes[s] = model.AddVar(0, dayEnd - dayStart, 0, GRB.CONTINUOUS, GurobiVarName($"santa{s} minRoute"));
                    }

                    #endregion initialize Variables


                    #region add constraints
                    SelfieConstraint(model, numberOfRoutes, w);

                    // visit visited once
                    VisitVisitedOnce(model, numberOfRoutes, v);
                    // breaks
                    BreakHandling(model, numberOfRoutes, v);

                    // number of ways = number of visits + home
                    NumberOfWaysMatchForSanta(model, numberOfRoutes, v, w);

                    // incoming & outgoing constraint
                    IncomingOutgoingGlobal(model, numberOfRoutes, w);
                    IncomingOutgoingSanta(model, numberOfRoutes, v, w);

                    IncomingOutgoingSantaHome(model, numberOfRoutes, w, v);

                    IncreasingC(model, numberOfRoutes, w, c, v);

                    DesiredOverlap(model, numberOfRoutes, v, w, c, desiredDuration);

                    UnavailableOverlap(model, numberOfRoutes, v, w, c, unavailableDuration, true);

                    FillMaxRoute(model, maxRoutes, c, v);
                    FillMinRoutes(model, minRoutes, c, v);
                    MinRouteSmallerThanMaxRoute(model, minRoutes, maxRoutes);

                    // Symmetry breaking constraint if no breaks
                    if (!input.Visits.Any(visit => visit.IsBreak))
                    {
                        for (int d = 0; d < input.Days.Length; d++)
                        {
                            var dayOffset = d * input.Santas.Length;
                            for (int s = 1; s < input.Santas.Length; s++)
                            {
                                model.AddConstr(maxRoutes[dayOffset + s] - minRoutes[dayOffset + s] <= maxRoutes[dayOffset + s - 1] - minRoutes[dayOffset + s - 1], null);
                            }
                        }
                    }

                    #endregion add constraints

                    // TARGET FUNCTION
                    var totalWayTime = new GRBLinExpr(0);
                    var longestRoute = model.AddVar(0, input.Days.Max(d => d.to - d.from), 0, GRB.CONTINUOUS, "longestRoute");
                    for (int s = 0; s < numberOfRoutes; s++)
                    {
                        totalWayTime += (maxRoutes[s] - minRoutes[s]);
                        model.AddConstr(longestRoute >= maxRoutes[s] - minRoutes[s], $"longesRouteConstr{s}");
                    }

                    var desiredSum     = new GRBLinExpr(0);
                    var unavailableSum = new GRBLinExpr(0);
                    for (int s = 0; s < numberOfRoutes; s++)
                    {
                        for (int i = 1; i < visitDurations.Length; i++)
                        {
                            var visit = input.Visits[i - 1];
                            for (int d = 0; d < visit.Desired.Length; d++)
                            {
                                if (!(desiredDuration[s][i][d] is null))
                                {
                                    desiredSum += desiredDuration[s][i][d];
                                }
                            }

                            for (int u = 0; u < visit.Unavailable.Length; u++)
                            {
                                if (!(unavailableDuration[s][i][u] is null))
                                {
                                    unavailableSum += unavailableDuration[s][i][u];
                                }
                            }
                        }
                    }

                    LowerBoundTotalWaytime(model, totalWayTime);

                    model.SetObjective(
                        +(12d) * unavailableSum
                        + (4d) * totalWayTime
                        - (2d) * desiredSum
                        + (3d) * longestRoute
                        , GRB.MINIMIZE);
                    model.Parameters.TimeLimit = Math.Max(0, timelimitMiliseconds / 1000);
                    InitializeWithVRPSolution(vrpSolution, numberOfRoutes, model, v, w, c);

#if DEBUG
                    model.Write($"{name}_{visitDurations.Length}.mst");
                    model.Write($"{name}_{visitDurations.Length}.mps");
                    model.Write($"{name}_{visitDurations.Length}.lp");
#endif

                    model.Optimize();
                    output.TimeElapsed = sw.ElapsedMilliseconds / 1000;
                    try
                    {
                        if (model.SolCount == 0 && vrpSolution != null)
                        {
                            consoleProgress?.Invoke(this, "No solution found -> try with vrpsolution");
                            BuildResultFromVRP(output, vrpSolution);
                            return(output);
                        }
                        BuildResult(output, numberOfRoutes, w, c);
                        consoleProgress?.Invoke(this, $"longestRoute: {longestRoute.X}");
                        consoleProgress?.Invoke(this, $"totalWayTime: {totalWayTime.Value}");
                        consoleProgress?.Invoke(this, $"DesiredDuration: {desiredSum.Value}");
                        consoleProgress?.Invoke(this, $"UnavailableDuration: {unavailableSum.Value}");
                        for (int s = 0; s < numberOfRoutes; s++)
                        {
                            consoleProgress?.Invoke(this, $"maxRoutes[{s}]: {maxRoutes[s].X}, {minRoutes[s].X} , ->{maxRoutes[s].X - minRoutes[s].X}");
                            for (int visitIndex = 0; visitIndex < visitDurations.Length; visitIndex++)
                            {
                                consoleProgress?.Invoke(this, $"c[{s}][{visitIndex}] ({v[s][visitIndex].X}): {c[s][visitIndex].X}");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        consoleProgress?.Invoke(this, $"ERROR: {e.Message}");
                        output.Routes = new Route[0];
                    }
                }

            return(output);
        }
        private void BuildResult(OptimizationResult output, int numberOfRoutes, GRBVar[][] w, GRBVar[][] c)
        {
            var routes = new List <Route>();

            for (int s = 0; s < numberOfRoutes; s++)
            {
                Debug.WriteLine($"Santa {s} uses way");
                var route  = new Route();
                var wpList = new List <Waypoint>();
                route.SantaId = s % input.Santas.Length;
                var lastId = 0;
                var day    = s / input.Santas.Length;

                do
                {
                    var(id, startingTime) = GetNextVisit(lastId, w[s], c[s]);
                    if (id == 0)
                    {
                        // if last visit
                        var lastVisit = input.Visits[lastId - 1];
                        wpList.Add(new Waypoint {
                            StartTime = wpList.Last().StartTime + lastVisit.Duration + lastVisit.WayCostToHome, VisitId = id - 1
                        });
                    }
                    else
                    {
                        wpList.Add(new Waypoint {
                            StartTime = startingTime + input.Days[day].from, VisitId = id - 1
                        });
                    }

                    lastId = id;
                } while (lastId != 0 && lastId != -1);

                if (wpList.Count == 0 || lastId == -1)
                {
                    continue;
                }

                var firstWaypoint = wpList.First();
                var firstVisit    = input.Visits[firstWaypoint.VisitId];
                route.Waypoints = wpList
                                  .Prepend(new Waypoint
                {
                    StartTime = firstWaypoint.StartTime - firstVisit.WayCostFromHome,
                    VisitId   = Constants.VisitIdHome
                })
                                  .ToArray();

                routes.Add(route);
                for (int i = 0; i < distances.GetLength(0); i++)
                {
                    for (int j = 0; j < distances.GetLength(1); j++)
                    {
                        if (Math.Round(AccessW(w[s], i, j).X, 0) > 0)
                        {
                            Debug.WriteLine($"[{i},{j}]=\t{c[s][j].X}");
                        }
                    }
                }
            }

            output.Routes = routes.ToArray();
        }
Пример #14
0
        public void TrackEstimation()
        {
            Config.Set("optimization-update-interval", 1);
            OptimizationResult result = null;
            var resetEvent            = new ManualResetEvent(false);
            var packet = new OptimizationNodePacket
            {
                Criterion = new Target("Profit", new Minimization(), null),
                OptimizationParameters = new HashSet <OptimizationParameter>
                {
                    new OptimizationStepParameter("ema-slow", 1, 10, 1),
                    new OptimizationStepParameter("ema-fast", 10, 100, 10)
                },
                Constraints = new List <Constraint>
                {
                    new Constraint("Drawdown", ComparisonOperatorTypes.LessOrEqual, 0.15m)
                },
                MaximumConcurrentBacktests = 5
            };
            var optimizer = new FakeLeanOptimizer(packet);
            // keep stats up-to-date
            int totalBacktest  = optimizer.GetCurrentEstimate();
            int totalUpdates   = 0;
            int completedTests = 0;
            int failed         = 0;

            optimizer.Update += (s, e) =>
            {
                var runtimeStats = optimizer.GetRuntimeStatistics();
                Assert.LessOrEqual(int.Parse(runtimeStats["Running"], CultureInfo.InvariantCulture), packet.MaximumConcurrentBacktests);
                Assert.LessOrEqual(completedTests, int.Parse(runtimeStats["Completed"], CultureInfo.InvariantCulture));
                Assert.LessOrEqual(failed, int.Parse(runtimeStats["Failed"], CultureInfo.InvariantCulture));

                Assert.AreEqual(totalBacktest, optimizer.GetCurrentEstimate());

                completedTests = int.Parse(runtimeStats["Completed"], CultureInfo.InvariantCulture);
                failed         = int.Parse(runtimeStats["Failed"], CultureInfo.InvariantCulture);

                if (completedTests > 0)
                {
                    // 'ms' aren't stored so might be 0
                    Assert.GreaterOrEqual(TimeSpan.Parse(runtimeStats["Average Length"], CultureInfo.InvariantCulture), TimeSpan.Zero);
                }

                totalUpdates++;
            };
            optimizer.Ended += (s, solution) =>
            {
                result = solution;
                optimizer.DisposeSafely();
                resetEvent.Set();
            };

            optimizer.Start();

            resetEvent.WaitOne();

            var runtimeStatistics = optimizer.GetRuntimeStatistics();

            Assert.NotZero(int.Parse(runtimeStatistics["Completed"], CultureInfo.InvariantCulture));
            Assert.NotZero(int.Parse(runtimeStatistics["Failed"], CultureInfo.InvariantCulture));
            // we have 2 force updates at least, expect a few more over it.
            Assert.Greater(totalUpdates, 2);
            Assert.AreEqual(int.Parse(runtimeStatistics["Completed"], CultureInfo.InvariantCulture)
                            + int.Parse(runtimeStatistics["Failed"], CultureInfo.InvariantCulture)
                            + int.Parse(runtimeStatistics["Running"], CultureInfo.InvariantCulture), totalBacktest);
        }
 private void CheckValid(OptimizationResult actual)
 {
     Assert.IsTrue(actual.IsValid(), actual.Validate());
 }
		//	This will be the value that the optimization process optimizes.
		//	It will search for the set of parameters that gives the highest result for this number.
		public virtual double EvaluateResults(OptimizationResult result)
		{
			//	By default, just use the APR.
			return result.FinalStatistic.APR;
		}
 private void CheckAllVisited(OptimizationResult actual)
 {
     Assert.AreEqual(0, actual.NumberOfNotVisitedFamilies());
 }
 public static void DrawResult(string path, OptimizationResult result, (int x, int y)[] coordinates)
        private static void EvaluateAlgorithm(string[] args)
        {
            BigHr();
            Console.WriteLine("Program written to evaluate the different optimisation algorithms.");
            Console.WriteLine();

            var algorithmSelection = args.Length == 0 ? QueryAlgorithmSelection() : (Algorithms)Enum.Parse(typeof(Algorithms), args[0]);

            SmallHr();
            Console.WriteLine();

            var datasetSelection = args.Length == 0 ? QueryDatasetSelection() : GetDatasetSelection(int.Parse(args[1]));

            SmallHr();
            Console.WriteLine();

            var runs = args.Length == 0 ? QueryNumberOfRuns() : int.Parse(args[2]);

            SmallHr();
            Console.WriteLine();
            Console.WriteLine("Starting the algorithm now");
            BigHr();


            for (int i = 0; i < runs; i++)
            {
                foreach (var dataset in datasetSelection)
                {
                    try
                    {
                        var(input, coordinates, timelimit) = GetDataset(dataset);
                        string  savepath   = $"{DateTime.Now:yy-MM-dd-HH-mm-ss}_DataSet_{dataset}";
                        ISolver solver     = null;
                        var     fastFactor = 60;
                        switch (algorithmSelection)
                        {
                        case Algorithms.ILPFast:
                            timelimit /= fastFactor;
                            goto case Algorithms.ILP;

                        case Algorithms.ILP:
                            solver = new ILPSolver(input, new ILPConfig
                            {
                                ClusteringMIPGap = 0,
                                SchedulingMIPGap = 0,

                                ClusteringTimeLimitMiliseconds = (long)(0.7 * timelimit),
                                SchedulingTimeLimitMiliseconds = (long)(0.3 * timelimit),
                                TimeSliceDuration = 120
                            });
                            savepath += "_ILP";
                            break;

                        case Algorithms.LocalSolverFast:
                            timelimit /= fastFactor;
                            goto case Algorithms.LocalSolver;

                        case Algorithms.LocalSolver:
                            solver = new Solver(input, new LocalSolverConfig
                            {
                                VrpTimeLimitFactor          = 0.1,
                                VrptwTimeLimitFactor        = 0.8,
                                MaxNumberOfAdditionalSantas = 0,
                            });
                            savepath += "_LocalSolver";
                            break;

                        case Algorithms.GA:
                            solver    = new GenAlgSolver(input, new GenAlgConfig(input));
                            savepath += "_GA";
                            break;

                        case Algorithms.GAFast:
                            timelimit /= fastFactor;
                            solver     = new GenAlgSolver(input, new GenAlgConfig(input));
                            savepath  += "_GAFast";
                            break;

                        case Algorithms.ILP2Fast:
                            timelimit /= fastFactor;
                            goto case Algorithms.ILP2;

                        case Algorithms.ILP2:
                            solver    = new IRuettae.Core.ILP2.Solver(input, 0.1, dataset.ToString());
                            savepath += "_ILP2";
                            break;

                        case Algorithms.ILPIP5GurobiFast:
                            timelimit /= fastFactor;
                            goto case Algorithms.ILPIP5Gurobi;

                        case Algorithms.ILPIP5Gurobi:
                            solver = new ILPIp5GurobiSolver(input, new ILPIp5GurobiConfig
                            {
                                ClusteringMIPGap = 0,
                                SchedulingMIPGap = 0,

                                ClusteringTimeLimitMiliseconds = (long)(0.7 * timelimit),
                                SchedulingTimeLimitMiliseconds = (long)(0.3 * timelimit),
                                TimeSliceDuration = 120
                            });
                            savepath += "_ILPIp5Gurobi";
                            break;

                        case Algorithms.GoogleRoutingFast:
                            timelimit /= fastFactor;
                            solver     = new GoogleRoutingSolver(input, GoogleRoutingConfig.GetDefault(input));
                            savepath  += "_GoogleRoutingFast";
                            break;

                        case Algorithms.GoogleRouting:
                            solver    = new GoogleRoutingSolver(input, GoogleRoutingConfig.GetDefault(input));
                            savepath += "_GoogleRouting";
                            break;
                        }

                        AddUnavailableBetweenDays(input);

                        OptimizationResult result = null;

                        void WriteConsoleInfo(object sender, string s)
                        {
                            Console.WriteLine($"Info ({DateTime.Now:HH-mm-ss}): {s}");
                        }

                        void WriteConsoleProgress(object sender, ProgressReport report)
                        {
                            Console.WriteLine($"Progress: {report}");
                        }
#if DEBUG
                        using (var sw = new StreamWriter(savepath + "-log.txt", true))
                        {
                            result = solver.Solve(timelimit, WriteConsoleProgress,
                                                  (sender, s) =>
                            {
                                WriteConsoleInfo(sender, s);
                                sw.WriteLine(s);
                            });
                        }
#else
                        result = solver.Solve(timelimit, WriteConsoleProgress, WriteConsoleInfo);
#endif

                        BigHr();

                        File.WriteAllText(savepath + ".json", JsonConvert.SerializeObject(result));

                        var summary = new StringBuilder();
                        summary.AppendLine($"Solver: {AlgorithmsDictionary[algorithmSelection]}");
                        summary.AppendLine($"Dataset{dataset}: {DatasetDictionary[dataset]}");
                        summary.AppendLine($"TimeElapsed [s]: {result.TimeElapsed}");
                        try
                        {
                            if (!result.IsValid())
                            {
                                summary.AppendLine(
                                    $"IMPORTANT: This result seems to be invalid. The reason is \"{result.Validate()}\"");
                            }
                        }
                        catch
                        {
                            summary.AppendLine("error while checking invalidity");
                        }

                        summary.AppendLine($"Cost: {result.Cost()}");
                        summary.AppendLine($"NumberOfNotVisitedFamilies: {result.NumberOfNotVisitedFamilies()}");
                        summary.AppendLine($"NumberOfMissingBreaks: {result.NumberOfMissingBreaks()}");
                        summary.AppendLine($"NumberOfAdditionalSantas: {result.NumberOfAdditionalSantas()}");
                        summary.AppendLine($"AdditionalSantaWorkTime: {result.AdditionalSantaWorkTime()}");
                        summary.AppendLine($"VisitTimeInUnavailable: {result.VisitTimeInUnavailable()}");
                        summary.AppendLine($"WayTimeOutsideBusinessHours: {result.WayTimeOutsideBusinessHours()}");
                        summary.AppendLine($"VisitTimeInDesired: {result.VisitTimeInDesired()}");
                        summary.AppendLine($"SantaWorkTime: {result.SantaWorkTime()}");
                        summary.AppendLine($"LongestDay: {result.LongestDay()}");
                        summary.AppendLine($"NumberOfRoutes: {result.NumberOfRoutes()}");

                        File.WriteAllText(savepath + ".txt", summary.ToString());
                        Console.WriteLine();
                        Console.WriteLine("Done solving");
                        Console.WriteLine(summary.ToString());
                        ResultDrawer.DrawResult(savepath, result, coordinates);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"An exception occured: {e.Message}");
                    }
                }
            }
        }