コード例 #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>
        /// 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)));
        }
コード例 #3
0
        public void CorrectGrayBoxFeaturesAreSelected()
        {
            var gurobiGrayBoxMethods = new GurobiGrayBoxMethods();

            var runtimeFeatures       = new GurobiRuntimeFeatures(DateTime.Now);
            var instanceFeatures      = new GurobiInstanceFeatures();
            var adapterFeatures       = GurobiUtils.ComposeAdapterFeatures(runtimeFeatures, runtimeFeatures, instanceFeatures);
            var adapterFeaturesHeader = GurobiUtils.ComposeAdapterFeaturesHeader(runtimeFeatures, runtimeFeatures, instanceFeatures);
            var result = new GurobiResult(double.NaN, TimeSpan.MaxValue, TargetAlgorithmStatus.CancelledByTimeout, false);

            var adapterDataRecord = new AdapterDataRecord <GurobiResult>(
                "Gurobi901",
                TargetAlgorithmStatus.Running,
                TimeSpan.Zero,
                TimeSpan.Zero,
                DateTime.Now,
                adapterFeaturesHeader,
                adapterFeatures,
                result);

            var tunerDataRecord = new TunerDataRecord <GurobiResult>(
                "Node",
                0,
                0,
                "Instance",
                0.5,
                new[] { "Genome" },
                (GenomeDoubleRepresentation) new[] { 0D },
                result);

            var dataRecord = new DataRecord <GurobiResult>(tunerDataRecord, adapterDataRecord);

            var featureNames = gurobiGrayBoxMethods.GetGrayBoxFeatureNamesFromDataRecord(dataRecord);

            var correctFeatureNames = new[]
            {
                "ExpendedWallClockTime",
                "RuntimeFeature_CuttingPlanesCount_Current",
                "RuntimeFeature_ExploredNodeCount_Current",
                "RuntimeFeature_FeasibleSolutionsCount_Current",
                "RuntimeFeature_MipGap_Current",
                "RuntimeFeature_SimplexIterationsCount_Current",
                "RuntimeFeature_UnexploredNodeCount_Current",
                "RuntimeFeature_CuttingPlanesCount_Last",
                "RuntimeFeature_ExploredNodeCount_Last",
                "RuntimeFeature_FeasibleSolutionsCount_Last",
                "RuntimeFeature_MipGap_Last",
                "RuntimeFeature_SimplexIterationsCount_Last",
                "RuntimeFeature_UnexploredNodeCount_Last",
                "InstanceFeature_NumberOfIntegerVariables",
                "InstanceFeature_NumberOfLinearConstraints",
                "InstanceFeature_NumberOfNonZeroCoefficients",
                "InstanceFeature_NumberOfVariables",
            };

            featureNames.SequenceEqual(correctFeatureNames).ShouldBeTrue();
        }
コード例 #4
0
 /// <summary>
 /// Composes the given adapter features to a single array.
 /// </summary>
 /// <param name="currentRuntimeFeatures">The current runtime features.</param>
 /// <param name="lastRuntimeFeatures">The last runtime features.</param>
 /// <param name="instanceFeatures">The instance features.</param>
 /// <returns>The composed array.</returns>
 public static double[] ComposeAdapterFeatures(
     GurobiRuntimeFeatures currentRuntimeFeatures,
     GurobiRuntimeFeatures lastRuntimeFeatures,
     GurobiInstanceFeatures instanceFeatures)
 {
     return(currentRuntimeFeatures.ToArray()
            .Concat(lastRuntimeFeatures.ToArray())
            .Concat(instanceFeatures.ToArray())
            .ToArray());
 }
コード例 #5
0
 /// <summary>
 /// Composes the header of the given adapter features to a single array.
 /// </summary>
 /// <param name="currentRuntimeFeatures">The current runtime features.</param>
 /// <param name="lastRuntimeFeatures">The last runtime features.</param>
 /// <param name="instanceFeatures">The instance features.</param>
 /// <returns>The composed array.</returns>
 public static string[] ComposeAdapterFeaturesHeader(
     GurobiRuntimeFeatures currentRuntimeFeatures,
     GurobiRuntimeFeatures lastRuntimeFeatures,
     GurobiInstanceFeatures instanceFeatures)
 {
     return(currentRuntimeFeatures.GetHeader("RuntimeFeature_", "_Current")
            .Concat(lastRuntimeFeatures.GetHeader("RuntimeFeature_", "_Last"))
            .Concat(instanceFeatures.GetHeader("InstanceFeature_"))
            .ToArray());
 }
コード例 #6
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);
        }