Пример #1
0
        /// <summary>
        /// Creates the final <see cref="AdapterDataRecord{GurobiResult}"/>.
        /// </summary>
        /// <param name="timeStamp">The time stamp.</param>
        /// <param name="model">The <see cref="GRBModel"/>.</param>
        /// <param name="result">The <see cref="GurobiResult"/>.</param>
        /// <returns>The final <see cref="AdapterDataRecord{GurobiResult}"/>.</returns>
        private AdapterDataRecord <GurobiResult> CreateFinalAdapterDataRecord(DateTime timeStamp, GRBModel model, GurobiResult result)
        {
            if (this._instanceFeatures == null)
            {
                throw new ArgumentNullException(nameof(this._instanceFeatures));
            }

            var finalRuntimeFeatures  = this.GetFinalGurobiRuntimeFeatures(model, result);
            var lastRuntimeFeatures   = this._lastRuntimeFeatures ?? finalRuntimeFeatures;
            var adapterFeatures       = GurobiUtils.ComposeAdapterFeatures(finalRuntimeFeatures, lastRuntimeFeatures, this._instanceFeatures);
            var adapterFeaturesHeader = GurobiUtils.ComposeAdapterFeaturesHeader(finalRuntimeFeatures, lastRuntimeFeatures, this._instanceFeatures);

            this._lastRuntimeFeatures = finalRuntimeFeatures.Copy();

            return(new AdapterDataRecord <GurobiResult>(
                       "Gurobi901",
                       result.TargetAlgorithmStatus,
                       // The cpu time is not recordable, because all parallel Gurobi runs are started in the same process in this implementation.
                       TimeSpan.FromSeconds(0),
                       this.GetCurrentRuntime(timeStamp),
                       timeStamp,
                       adapterFeaturesHeader,
                       adapterFeatures,
                       result));
        }
Пример #2
0
 /// <summary>
 /// Updates the <see cref="CurrentRuntimeFeatures"/> in MIP phase.
 /// </summary>
 private void UpdateCurrentGurobiFeaturesInMipPhase()
 {
     this.CurrentRuntimeFeatures.BestObjective      = this.GetCallbackDouble(GRB.Callback.MIP_OBJBST, this.CurrentRuntimeFeatures.BestObjective);
     this.CurrentRuntimeFeatures.BestObjectiveBound = this.GetCallbackDouble(
         GRB.Callback.MIP_OBJBND,
         this.CurrentRuntimeFeatures.BestObjectiveBound);
     this.CurrentRuntimeFeatures.FeasibleSolutionsCount = this.GetCallbackInt(
         GRB.Callback.MIP_SOLCNT,
         this.CurrentRuntimeFeatures.FeasibleSolutionsCount);
     this.CurrentRuntimeFeatures.ExploredNodeCount = this.GetCallbackDouble(
         GRB.Callback.MIP_NODCNT,
         this.CurrentRuntimeFeatures.ExploredNodeCount);
     this.CurrentRuntimeFeatures.UnexploredNodeCount = this.GetCallbackDouble(
         GRB.Callback.MIP_NODLFT,
         this.CurrentRuntimeFeatures.UnexploredNodeCount);
     this.CurrentRuntimeFeatures.SimplexIterationsCount = this.GetCallbackDouble(
         GRB.Callback.MIP_ITRCNT,
         this.CurrentRuntimeFeatures.SimplexIterationsCount);
     this.CurrentRuntimeFeatures.CuttingPlanesCount = this.GetCallbackInt(
         GRB.Callback.MIP_CUTCNT,
         this.CurrentRuntimeFeatures.CuttingPlanesCount);
     this.CurrentRuntimeFeatures.MipGap = GurobiUtils.GetMipGap(
         this.CurrentRuntimeFeatures.BestObjective,
         this.CurrentRuntimeFeatures.BestObjectiveBound);
 }
Пример #3
0
        /// <summary>
        /// Creates the current <see cref="AdapterDataRecord{GurobiResult}"/>.
        /// </summary>
        /// <param name="timeStamp">The time stamp.</param>
        /// <returns>The current <see cref="AdapterDataRecord{GurobiResult}"/>.</returns>
        private AdapterDataRecord <GurobiResult> CreateCurrentAdapterDataRecord(DateTime timeStamp)
        {
            if (this._instanceFeatures == null)
            {
                throw new ArgumentNullException(nameof(this._instanceFeatures));
            }

            var currentRuntimeFeatures = this.GetCurrentGurobiRuntimeFeatures();
            var lastRuntimeFeatures    = this._lastRuntimeFeatures ?? currentRuntimeFeatures;
            var adapterFeatures        = GurobiUtils.ComposeAdapterFeatures(currentRuntimeFeatures, lastRuntimeFeatures, this._instanceFeatures);
            var adapterFeaturesHeader  = GurobiUtils.ComposeAdapterFeaturesHeader(currentRuntimeFeatures, lastRuntimeFeatures, this._instanceFeatures);

            this._lastRuntimeFeatures = currentRuntimeFeatures.Copy();

            return(new AdapterDataRecord <GurobiResult>(
                       "Gurobi901",
                       TargetAlgorithmStatus.Running,
                       // The cpu time is not recordable, because all parallel Gurobi runs are started in the same process in this implementation.
                       TimeSpan.FromSeconds(0),
                       this.GetCurrentRuntime(timeStamp),
                       timeStamp,
                       adapterFeaturesHeader,
                       adapterFeatures,
                       new GurobiResult(
                           currentRuntimeFeatures.MipGap,
                           this._runnerConfiguration.CpuTimeout,
                           TargetAlgorithmStatus.CancelledByGrayBox,
                           currentRuntimeFeatures.FeasibleSolutionsCount > 0)));
        }
        /// <summary>
        /// Creates the list of instances to train on using .mps files in the given directory.
        /// </summary>
        /// <param name="pathToInstanceFolder">Path to the folder containing the instance .mps files.</param>
        /// <param name="numSeedsToUse">The number of seeds.</param>
        /// <param name="rngSeed">The random number generator seed.</param>
        /// <returns>
        /// The created list.
        /// </returns>
        public static List <InstanceSeedFile> CreateInstances(string pathToInstanceFolder, int numSeedsToUse, int rngSeed)
        {
            try
            {
                // Find all .mps files in directory and set them as instances.
                var instanceDirectory        = new DirectoryInfo(pathToInstanceFolder);
                var instanceSeedCombinations = new List <string>();
                var instanceSeedFiles        = new List <InstanceSeedFile>();
                foreach (var instanceFilePath in instanceDirectory.EnumerateFiles()
                         .Where(file => file.Extension.ToLower() == ".mps"))
                {
                    var fileAndSeedCsv = instanceFilePath.FullName;
                    foreach (var seed in GurobiUtils.SeedsToUse(numSeedsToUse, rngSeed))
                    {
                        instanceSeedFiles.Add(new InstanceSeedFile(instanceFilePath.FullName, seed));
                        fileAndSeedCsv += $";{seed}";
                    }

                    instanceSeedCombinations.Add(fileAndSeedCsv);
                }

                GurobiUtils.DumpFileSeedCombinations(instanceDirectory, instanceSeedCombinations);
                return(instanceSeedFiles);
            }
            catch (Exception e)
            {
                Console.Out.WriteLine(e.Message);
                Console.Out.WriteLine("Cannot open folder.");
                throw;
            }
        }
Пример #5
0
        /// <summary>
        /// Builds an instance of the <see cref="AlgorithmTuner{TTargetAlorithm,TInstance,TResult}" /> class for tuning Gurobi.
        /// </summary>
        /// <param name="configuration">The <see cref="AlgorithmTunerConfiguration" /> to use.</param>
        /// <param name="pathToTrainingInstanceFolder">The path to the folder containing training instances.</param>
        /// <param name="pathToTestInstanceFolder">The path to test instance folder.</param>
        /// <param name="gurobiConfigBuilder">The gurobi configuration builder.</param>
        /// <returns>
        /// The built instance.
        /// </returns>
        public static AlgorithmTuner <GurobiRunner, InstanceSeedFile, GurobiResult> BuildGurobiRunner(
            AlgorithmTunerConfiguration configuration,
            string pathToTrainingInstanceFolder,
            string pathToTestInstanceFolder,
            GurobiRunnerConfiguration.GurobiRunnerConfigBuilder gurobiConfigBuilder)
        {
            var gurobiConfig = gurobiConfigBuilder.Build(configuration.CpuTimeout);

            var tuner = new AlgorithmTuner <GurobiRunner, InstanceSeedFile, GurobiResult>(
                targetAlgorithmFactory: new GurobiRunnerFactory(gurobiConfig),
                runEvaluator: new GurobiRunEvaluator(),
                trainingInstances: GurobiUtils.CreateInstances(pathToTrainingInstanceFolder, gurobiConfig.NumberOfSeeds, gurobiConfig.RngSeed),
                parameterTree: GurobiUtils.CreateParameterTree(),
                configuration: configuration);

            try
            {
                if (!string.IsNullOrWhiteSpace(pathToTestInstanceFolder))
                {
                    var testInstances = GurobiUtils.CreateInstances(pathToTestInstanceFolder, gurobiConfig.NumberOfSeeds, gurobiConfig.RngSeed);
                    tuner.SetTestInstances(testInstances);
                }
            }
            catch
            {
            }

            return(tuner);
        }
Пример #6
0
        /// <summary>
        /// Creates a <see cref="ParameterTree" /> of tuneable Gurobi parameters for MIP solving.
        /// The parameters and their connections are described in parameterTree.xml.
        /// </summary>
        /// <returns>The <see cref="ParameterTree" />.</returns>
        public static ParameterTree CreateParameterTree()
        {
            var parameterTree = ParameterTreeConverter.ConvertToParameterTree(
                Path.Combine(AppDomain.CurrentDomain.BaseDirectory ?? throw new InvalidOperationException(), @"parameterTree.xml"));

            GurobiUtils.AddAllIndicatorParameterWrappers(parameterTree);
            return(parameterTree);
        }
Пример #7
0
 /// <summary>
 /// Updates the <see cref="CurrentRuntimeFeatures"/> in MIP_SOL phase.
 /// </summary>
 private void UpdateCurrentGurobiFeaturesInMipSolPhase()
 {
     this.CurrentRuntimeFeatures.BestObjective      = this.GetCallbackDouble(GRB.Callback.MIPSOL_OBJBST, this.CurrentRuntimeFeatures.BestObjective);
     this.CurrentRuntimeFeatures.BestObjectiveBound = this.GetCallbackDouble(
         GRB.Callback.MIPSOL_OBJBND,
         this.CurrentRuntimeFeatures.BestObjectiveBound);
     this.CurrentRuntimeFeatures.FeasibleSolutionsCount = this.GetCallbackInt(
         GRB.Callback.MIPSOL_SOLCNT,
         this.CurrentRuntimeFeatures.FeasibleSolutionsCount);
     this.CurrentRuntimeFeatures.ExploredNodeCount = this.GetCallbackDouble(
         GRB.Callback.MIPSOL_NODCNT,
         this.CurrentRuntimeFeatures.ExploredNodeCount);
     this.CurrentRuntimeFeatures.MipGap = GurobiUtils.GetMipGap(
         this.CurrentRuntimeFeatures.BestObjective,
         this.CurrentRuntimeFeatures.BestObjectiveBound);
 }
Пример #8
0
        /// <summary>
        /// Builds an instance of the <see cref="AlgorithmTuner{TTargetAlorithm,TInstance,TResult}" /> class for tuning Gurobi.
        /// </summary>
        /// <param name="tunerConfig">The <see cref="AlgorithmTunerConfiguration" /> to use.</param>
        /// <param name="pathToTrainingInstanceFolder">The path to the folder containing training instances.</param>
        /// <param name="pathToTestInstanceFolder">The path to test instance folder.</param>
        /// <param name="gurobiConfigBuilder">The gurobi configuration builder.</param>
        /// <returns>
        /// The built instance.
        /// </returns>
        public static AlgorithmTuner <GurobiRunner, InstanceSeedFile, GurobiResult> BuildGurobiRunner(
            AlgorithmTunerConfiguration tunerConfig,
            string pathToTrainingInstanceFolder,
            string pathToTestInstanceFolder,
            GurobiRunnerConfiguration.GurobiRunnerConfigBuilder gurobiConfigBuilder)
        {
            var gurobiConfig = Program.BuildGurobiConfigAndCheckThreadCount(gurobiConfigBuilder, tunerConfig);

            var tuner = new AlgorithmTuner <GurobiRunner, InstanceSeedFile, GurobiResult>(
                targetAlgorithmFactory: new GurobiRunnerFactory(gurobiConfig, tunerConfig),
                runEvaluator: new GurobiRunEvaluator(tunerConfig.CpuTimeout),
                trainingInstances: InstanceSeedFile.CreateInstanceSeedFilesFromDirectory(
                    pathToTrainingInstanceFolder,
                    GurobiUtils.ListOfValidFileExtensions,
                    gurobiConfig.NumberOfSeeds,
                    gurobiConfig.RngSeed),
                parameterTree: GurobiUtils.CreateParameterTree(),
                configuration: tunerConfig,
                customGrayBoxMethods: new GurobiGrayBoxMethods());

            try
            {
                if (!string.IsNullOrWhiteSpace(pathToTestInstanceFolder))
                {
                    var testInstances = InstanceSeedFile.CreateInstanceSeedFilesFromDirectory(
                        pathToTestInstanceFolder,
                        GurobiUtils.ListOfValidFileExtensions,
                        gurobiConfig.NumberOfSeeds,
                        gurobiConfig.RngSeed);
                    tuner.SetTestInstances(testInstances);
                }
            }
            catch
            {
            }

            return(tuner);
        }
Пример #9
0
        /// <summary>
        /// Creates a task that runs Gurobi on the given instance.
        /// </summary>
        /// <param name="instance">
        /// Instance to run on.
        /// </param>
        /// <param name="cancellationToken">
        /// The cancellation token given to the task. NOTE: In this implementation, we ignore this cancellation token, since Gurobi uses its own cancellation token in the callback.
        /// </param>
        /// <returns>
        /// A task that returns the run's runtime, gap, feasibility and completion status onto return.
        /// </returns>
        public Task <GurobiResult> Run(InstanceSeedFile instance, CancellationToken cancellationToken)
        {
            // Check if the runner has already been disposed.
            if (this._hasAlreadyBeenDisposed)
            {
                throw new ObjectDisposedException("GurobiRunner", "Called Run on a disposed GurobiRunner.");
            }

            // Continue if it hasn't.
            // ReSharper disable once MethodSupportsCancellation
            var solveTask = Task.Run(
                () =>
            {
                this._recordTimer = null;
                try
                {
                    // Prepare Gurobi model: Use configured _environment and the given instance,
                    // then add a cancellation token source and the Gurobi callback for cancellation.
                    var instanceFile = new FileInfo(instance.Path);
                    if (!File.Exists(instanceFile.FullName))
                    {
                        throw new FileNotFoundException($"Instance {instanceFile.FullName} not found!");
                    }

                    LoggingHelper.WriteLine(VerbosityLevel.Debug, $"Setting MIPGap to {this._runnerConfiguration.TerminationMipGap}");
                    this._environment.MIPGap = this._runnerConfiguration.TerminationMipGap;
                    LoggingHelper.WriteLine(VerbosityLevel.Debug, $"Current Seed: {instance.Seed}");
                    this._environment.Seed      = instance.Seed;
                    this._environment.TimeLimit = this._runnerConfiguration.CpuTimeout.TotalSeconds;

                    if (!Directory.Exists("GurobiLog"))
                    {
                        Directory.CreateDirectory("GurobiLog");
                    }

                    var instanceFileNameWithoutExtension = GurobiUtils.GetFileNameWithoutGurobiExtension(instanceFile);

                    this._environment.LogFile = "GurobiLog" + Path.DirectorySeparatorChar
                                                + $"GurobiRunner_{DateTime.Now:yy-MM-dd_HH-mm-ss-ffff}_"
                                                + instanceFileNameWithoutExtension + $"_{Guid.NewGuid()}.log";

                    var model = new GRBModel(this._environment, instanceFile.FullName)
                    {
                        ModelName = instanceFileNameWithoutExtension
                    };

                    if (GurobiRunner.TryToGetMstFile(instanceFile.DirectoryName, instanceFileNameWithoutExtension, out var mstFileFullName))
                    {
                        model.Read(mstFileFullName);
                    }

                    this._startTimeStamp        = DateTime.Now;
                    this._targetAlgorithmStatus = TargetAlgorithmStatus.Running;

                    this._innerCancellationTokenSource = new CancellationTokenSource(this._runnerConfiguration.CpuTimeout);

                    this._grbCallback = new GurobiCallback(
                        this._innerCancellationTokenSource.Token,
                        this._tunerConfiguration.EnableDataRecording,
                        this._startTimeStamp);
                    model.SetCallback(this._grbCallback);

                    if (this._tunerConfiguration.EnableDataRecording)
                    {
                        this._lastRuntimeFeatures = null;
                        this.SetGurobiInstanceFeatures(model);

                        // Start record timer.
                        var autoResetEvent = new AutoResetEvent(false);
                        this._recordTimer  = new Timer(
                            (timerCallback) =>
                        {
                            var currentTimeStamp = DateTime.Now;
                            if (currentTimeStamp - this._startTimeStamp < this._runnerConfiguration.CpuTimeout)
                            {
                                // Write current line to data log.
                                var currentAdapterData = this.CreateCurrentAdapterDataRecord(currentTimeStamp);
                                this.OnNewDataRecord?.Invoke(this, currentAdapterData);
                            }
                        },
                            autoResetEvent,
                            TimeSpan.FromSeconds(0),
                            this._tunerConfiguration.DataRecordUpdateInterval);
                    }

                    // Optimize. This step may be aborted in the callback.
                    model.Optimize();

                    if (this._targetAlgorithmStatus != TargetAlgorithmStatus.CancelledByGrayBox)
                    {
                        this._recordTimer?.Dispose();
                        this._targetAlgorithmStatus = this.GetIsRunInterrupted(model)
                                                                  ? TargetAlgorithmStatus.CancelledByTimeout
                                                                  : TargetAlgorithmStatus.Finished;
                    }

                    var finalTimeStamp = DateTime.Now;
                    var result         = this.CreateGurobiResult(finalTimeStamp, model);

                    if (this._tunerConfiguration.EnableDataRecording)
                    {
                        // Write last line to data log.
                        var lastAdapterData = this.CreateFinalAdapterDataRecord(finalTimeStamp, model, result);
                        this.OnNewDataRecord?.Invoke(this, lastAdapterData);
                    }

                    // Before returning, dispose of Gurobi model.
                    model.Dispose();

                    return(result);
                }
                finally
                {
                    this._recordTimer?.Dispose();
                }
            });

            return(solveTask);
        }
Пример #10
0
        /// <summary>
        /// Entry point to the program.
        /// </summary>
        /// <param name="args">If 'master' is included as argument, a
        /// <see cref="Master{TTargetAlgorithm,TInstance,TResult}"/> is starting using the provided arguments.
        /// Otherwise, a <see cref="Worker"/> is started with the provided arguments.</param>
        public static void Main(string[] args)
        {
            ProcessUtils.SetDefaultCultureInfo(CultureInfo.InvariantCulture);
            LoggingHelper.Configure($"parserLog_{ProcessUtils.GetCurrentProcessId()}.log");

            // Parse gurobi configuration.
            var gurobiParser = new GurobiRunnerConfigurationParser();

            if (!ArgumentParserUtils.ParseArguments(gurobiParser, args))
            {
                return;
            }

            if (gurobiParser.IsPostTuningRunner)
            {
                LoggingHelper.Configure($"consoleOutput_PostTuningRun_{ProcessUtils.GetCurrentProcessId()}.log");

                // Parse and build tuner configuration.
                var masterArgumentParser = new MasterArgumentParser();
                if (!ArgumentParserUtils.ParseArguments(masterArgumentParser, gurobiParser.AdditionalArguments.ToArray()))
                {
                    return;
                }

                var tunerConfig = masterArgumentParser.ConfigurationBuilder.Build();
                LoggingHelper.ChangeConsoleLoggingLevel(tunerConfig.Verbosity);

                // Build gurobi configuration.
                var gurobiConfig        = Program.BuildGurobiConfigAndCheckThreadCount(gurobiParser.ConfigurationBuilder, tunerConfig);
                var gurobiRunnerFactory = new GurobiRunnerFactory(gurobiConfig, tunerConfig);
                var parameterTree       = GurobiUtils.CreateParameterTree();

                // Start post tuning runner.
                var parallelPostTuningRunner =
                    new ParallelPostTuningRunner <GurobiRunner, InstanceSeedFile, GurobiResult>(
                        tunerConfig,
                        gurobiParser.PostTuningConfiguration,
                        gurobiRunnerFactory,
                        parameterTree);
                parallelPostTuningRunner.ExecutePostTuningRunsInParallel();

                return;
            }

            if (gurobiParser.IsMaster)
            {
                Master <GurobiRunner, InstanceSeedFile, GurobiResult, StandardRandomForestLearner <ReuseOldTreesStrategy>,
                        GenomePredictionForestModel <GenomePredictionTree>, ReuseOldTreesStrategy> .Run(
                    args : gurobiParser.AdditionalArguments.ToArray(),
                    algorithmTunerBuilder : (algorithmTunerConfig, pathToInstanceFolder, pathToTestInstanceFolder) =>
                    Program.BuildGurobiRunner(
                        algorithmTunerConfig,
                        pathToInstanceFolder,
                        pathToTestInstanceFolder,
                        gurobiParser.ConfigurationBuilder));
            }
            else
            {
                Worker.Run(gurobiParser.AdditionalArguments.ToArray());
            }
        }