1  #region License Information


2  /* HeuristicLab


3  * Copyright (C) 20022018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)


4  *


5  * This file is part of HeuristicLab.


6  *


7  * HeuristicLab is free software: you can redistribute it and/or modify


8  * it under the terms of the GNU General Public License as published by


9  * the Free Software Foundation, either version 3 of the License, or


10  * (at your option) any later version.


11  *


12  * HeuristicLab is distributed in the hope that it will be useful,


13  * but WITHOUT ANY WARRANTY; without even the implied warranty of


14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the


15  * GNU General Public License for more details.


16  *


17  * You should have received a copy of the GNU General Public License


18  * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.


19  */


20  #endregion


21 


22  using System;


23  using System.Threading;


24  using HeuristicLab.Common;


25  using HeuristicLab.Core;


26  using HeuristicLab.Data;


27  using HeuristicLab.Parameters;


28  using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;


29 


30  namespace HeuristicLab.MathematicalOptimization.LinearProgramming.Algorithms.Solvers.Base {


31 


32  [StorableClass]


33  public class Solver : ParameterizedNamedItem, ISolver, IDisposable {


34 


35  [Storable]


36  protected IValueParameter<EnumValue<ProblemType>> problemTypeParam;


37 


38  protected LinearSolver solver;


39 


40  [Storable]


41  protected IFixedValueParameter<TextValue> solverSpecificParametersParam;


42 


43  public Solver() {


44  Parameters.Add(problemTypeParam =


45  new ValueParameter<EnumValue<ProblemType>>(nameof(ProblemType), new EnumValue<ProblemType>()));


46  Parameters.Add(solverSpecificParametersParam =


47  new FixedValueParameter<TextValue>(nameof(SolverSpecificParameters), new TextValue()));


48  }


49 


50  [StorableConstructor]


51  protected Solver(bool deserializing)


52  : base(deserializing) {


53  }


54 


55  protected Solver(Solver original, Cloner cloner)


56  : base(original, cloner) {


57  problemTypeParam = cloner.Clone(original.problemTypeParam);


58  solverSpecificParametersParam = cloner.Clone(original.solverSpecificParametersParam);


59  }


60 


61  public ProblemType ProblemType {


62  get => problemTypeParam.Value.Value;


63  set => problemTypeParam.Value.Value = value;


64  }


65 


66  public TextValue SolverSpecificParameters => solverSpecificParametersParam.Value;


67 


68  public virtual bool SupportsPause => true;


69  public virtual bool SupportsStop => true;


70  protected virtual OptimizationProblemType OptimizationProblemType { get; }


71 


72  public override IDeepCloneable Clone(Cloner cloner) => new Solver(this, cloner);


73 


74  public void Dispose() => solver?.Dispose();


75 


76  public bool InterruptSolve() => solver?.InterruptSolve() ?? false;


77 


78  public virtual void Reset() {


79  solver?.Dispose();


80  solver = null;


81  }


82 


83  public virtual void Solve(LinearProgrammingAlgorithm algorithm, CancellationToken cancellationToken) =>


84  Solve(algorithm);


85 


86  public virtual void Solve(LinearProgrammingAlgorithm algorithm) =>


87  Solve(algorithm, algorithm.TimeLimit);


88 


89  public virtual void Solve(LinearProgrammingAlgorithm algorithm, TimeSpan timeLimit) {


90  string libraryName = null;


91  if (this is IExternalSolver externalSolver)


92  libraryName = externalSolver.LibraryName;


93 


94  if (solver == null) {


95  solver = new LinearSolver(OptimizationProblemType, s => algorithm.Problem.ProblemDefinition.BuildModel(s), Name,


96  libraryName);


97  }


98 


99  solver.TimeLimit = timeLimit;


100  solver.RelativeGapTolerance = algorithm.RelativeGapTolerance;


101  solver.PrimalTolerance = algorithm.PrimalTolerance;


102  solver.DualTolerance = algorithm.DualTolerance;


103  solver.Presolve = algorithm.Presolve;


104  solver.Scaling = algorithm.Scaling;


105  solver.LpAlgorithm = algorithm.LpAlgorithm;


106  solver.Incrementality = true;


107 


108  if (!solver.SetSolverSpecificParameters(SolverSpecificParameters.Value))


109  throw new ArgumentException("Solver specific parameters could not be set.");


110 


111  solver.Solve();


112 


113  algorithm.Problem.ProblemDefinition.Analyze(solver.Solver, algorithm.Results);


114  algorithm.Results.AddOrUpdateResult(nameof(solver.ResultStatus),


115  new EnumValue<ResultStatus>(solver.ResultStatus));


116  algorithm.Results.AddOrUpdateResult($"Best{nameof(solver.ObjectiveValue)}",


117  new DoubleValue(solver.ObjectiveValue ?? double.NaN));


118 


119  if (solver.IsMip) {


120  algorithm.Results.AddOrUpdateResult($"Best{nameof(solver.ObjectiveBound)}",


121  new DoubleValue(solver.ObjectiveBound ?? double.NaN));


122  algorithm.Results.AddOrUpdateResult(nameof(solver.AbsoluteGap),


123  new DoubleValue(solver.AbsoluteGap ?? double.NaN));


124  algorithm.Results.AddOrUpdateResult(nameof(solver.RelativeGap),


125  new PercentValue(solver.RelativeGap ?? double.NaN));


126  }


127 


128  algorithm.Results.AddOrUpdateResult(nameof(solver.NumberOfConstraints), new IntValue(solver.NumberOfConstraints));


129  algorithm.Results.AddOrUpdateResult(nameof(solver.NumberOfVariables), new IntValue(solver.NumberOfVariables));


130 


131  if (solver.IsMip) {


132  algorithm.Results.AddOrUpdateResult(nameof(solver.NumberOfNodes), new DoubleValue(solver.NumberOfNodes));


133  }


134 


135  algorithm.Results.AddOrUpdateResult(nameof(solver.Iterations), new DoubleValue(solver.Iterations));


136  algorithm.Results.AddOrUpdateResult(nameof(solver.SolverVersion), new StringValue(solver.SolverVersion));


137  }


138  }


139  }

