/// <summary> /// Initializes a new instance of the <see cref="ResultBase{TResultType}"/> class. /// </summary> /// <param name="runtime"> /// The observed runtime. /// </param> /// <param name="targetAlgorithmStatus"> /// The target algorithm status. /// </param> protected ResultBase(TimeSpan runtime, TargetAlgorithmStatus targetAlgorithmStatus) { if (targetAlgorithmStatus == TargetAlgorithmStatus.Running) { throw new ArgumentOutOfRangeException( nameof(targetAlgorithmStatus), "While creating a result, the target algorithm status should not be running."); } this.Runtime = runtime; this.TargetAlgorithmStatus = targetAlgorithmStatus; }
/// <summary> /// Initializes a new instance of the <see cref="GurobiResult" /> class. /// </summary> /// <param name="gap">The MIP gap at the end of the run.</param> /// <param name="runtime">The runtime in milliseconds.</param> /// <param name="targetAlgorithmStatus">The target algorithm status.</param> /// <param name="hasValidSolution">Whether a valid solution was found.</param> public GurobiResult(double gap, TimeSpan runtime, TargetAlgorithmStatus targetAlgorithmStatus, bool hasValidSolution) : base(runtime, targetAlgorithmStatus) { // Check some parameters. if (gap < 0) { throw new ArgumentOutOfRangeException($"Gap has to be nonnegative, but is {gap}."); } // Set them. this.Gap = gap; this.Runtime = runtime; this.HasValidSolution = hasValidSolution; }
/// <summary> /// Creates a <see cref="ResultBase{TResultType}"/> that represents a cancelled run. /// </summary> /// <param name="runtime"> /// Run's duration before cancellation. /// </param> /// <param name="targetAlgorithmStatus">The final <see cref="TargetAlgorithmStatus"/>. Default is TargetAlgorithmStatus.CancelledByTimeout.</param> /// <returns> /// A <see cref="ResultBase{TResultType}"/> representing a cancelled run. /// </returns> public static TResultType CreateCancelledResult( TimeSpan runtime, TargetAlgorithmStatus targetAlgorithmStatus = TargetAlgorithmStatus.CancelledByTimeout) { if (targetAlgorithmStatus == TargetAlgorithmStatus.Running || targetAlgorithmStatus == TargetAlgorithmStatus.Finished) { throw new ArgumentOutOfRangeException( nameof(targetAlgorithmStatus), "While creating a cancelled result, the target algorithm status should not be running or finished."); } return(new TResultType() { TargetAlgorithmStatus = targetAlgorithmStatus, Runtime = runtime }); }
/// <summary> /// Initializes a new instance of the <see cref="AdapterDataRecord{TResult}"/> class. /// </summary> /// <param name="targetAlgorithmName">The target algorithm name.</param> /// <param name="targetAlgorithmStatus">The target algorithm status.</param> /// <param name="expendedCpuTime">The expended cpu time.</param> /// <param name="expendedWallClockTime">The expended wall clock time.</param> /// <param name="timeStamp">The time stamp.</param> /// <param name="adapterFeaturesHeader">The adapter features header.</param> /// <param name="adapterFeatures">The adapter features.</param> /// <param name="currentGrayBoxResult">The current gray box result.</param> public AdapterDataRecord( string targetAlgorithmName, TargetAlgorithmStatus targetAlgorithmStatus, TimeSpan expendedCpuTime, TimeSpan expendedWallClockTime, DateTime timeStamp, string[] adapterFeaturesHeader, double[] adapterFeatures, TResult currentGrayBoxResult) { this.TargetAlgorithmName = targetAlgorithmName; this.TargetAlgorithmStatus = targetAlgorithmStatus; this.ExpendedCpuTime = expendedCpuTime; this.ExpendedWallClockTime = expendedWallClockTime; this.TimeStamp = timeStamp; this.AdapterFeaturesHeader = adapterFeaturesHeader; this.AdapterFeatures = adapterFeatures; this.CurrentGrayBoxResult = currentGrayBoxResult; }
/// <summary> /// Initializes a new instance of the <see cref="ContinuousResult" /> class. /// </summary> /// <param name="value">The value it should hold.</param> /// <param name="runtime">The runtime.</param> /// <param name="targetAlgorithmStatus">The <see cref="TargetAlgorithmStatus"/>.</param> public ContinuousResult(double value, TimeSpan runtime, TargetAlgorithmStatus targetAlgorithmStatus = TargetAlgorithmStatus.Finished) : base(runtime, targetAlgorithmStatus) { this.Value = value; }
public void CreateCancelledResultThrowsIfTargetAlgorithmStatusIsRunningOrFinished(TargetAlgorithmStatus targetAlgorithmStatus) { Assert.Throws <ArgumentOutOfRangeException>( () => { ResultBase <TestResult> .CreateCancelledResult(TimeSpan.FromSeconds(30), targetAlgorithmStatus); }); }
/// <inheritdoc/> public void CancelByGrayBox() { this._targetAlgorithmStatus = TargetAlgorithmStatus.CancelledByGrayBox; this._recordTimer?.Dispose(); this._innerCancellationTokenSource.Cancel(); }
/// <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); }
/// <summary> /// Initializes a new instance of the <see cref="RuntimeResult"/> class. /// </summary> /// <param name="runtime">The runtime.</param> /// <param name="targetAlgorithmStatus">The <see cref="TargetAlgorithmStatus"/>.</param> public RuntimeResult(TimeSpan runtime, TargetAlgorithmStatus targetAlgorithmStatus = TargetAlgorithmStatus.Finished) : base(runtime, targetAlgorithmStatus) { }
/// <summary> /// Returns the data log file name, which matches the <see cref="DataLogFileNameRegex"/>. /// </summary> /// <param name="generationId">The generation id.</param> /// <param name="processId">The process id.</param> /// <param name="actorId">The actor id.</param> /// <param name="targetAlgorithmStatus">The target algorithm status.</param> /// <returns>The data log file name.</returns> public static string GetDataLogFileName(int generationId, int processId, int actorId, TargetAlgorithmStatus targetAlgorithmStatus) { return($"dataLog_generation_{generationId}_process_{processId}_id_{actorId}_{targetAlgorithmStatus}.csv"); }