1  #region License Information


2  /* HeuristicLab


3  * Copyright (C) 20022017 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.Analysis;


25  using HeuristicLab.Common;


26  using HeuristicLab.Core;


27  using HeuristicLab.Data;


28  using HeuristicLab.Encodings.IntegerVectorEncoding;


29  using HeuristicLab.Optimization;


30  using HeuristicLab.Parameters;


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


32  using ILOG.CPLEX;


33  using ILOG.OPL;


34 


35  namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.CPLEX {


36  [Item("CPLEX Solver (GQAP)", "Base class")]


37  [StorableClass]


38  public abstract class CplexSolver : ContextAlgorithm<CplexContext, IntegerVectorEncoding> {


39  public override bool SupportsPause {


40  get { return false; }


41  }


42 


43  public override Type ProblemType {


44  get { return typeof(GQAP); }


45  }


46 


47  public new GQAP Problem {


48  get { return (GQAP)base.Problem; }


49  set { base.Problem = value; }


50  }


51 


52  [Storable]


53  private ValueParameter<DateTimeValue> lastUpdateTimeParameter;


54  public IValueParameter<DateTimeValue> LastUpdateTimeParameter {


55  get { return lastUpdateTimeParameter; }


56  }


57 


58  [StorableConstructor]


59  protected CplexSolver(bool deserializing) : base(deserializing) { }


60  protected CplexSolver(CplexSolver original, Cloner cloner)


61  : base(original, cloner) {


62  lastUpdateTimeParameter = cloner.Clone(original.lastUpdateTimeParameter);


63  }


64  public CplexSolver() {


65  Problem = new GQAP();


66  Parameters.Add(lastUpdateTimeParameter = new ValueParameter<DateTimeValue>("LastUpdateTime", "") { Hidden = true });


67  var qpc = new QualityPerClockAnalyzer();


68  qpc.LastUpdateTimeParameter.ActualName = LastUpdateTimeParameter.Name;


69  ((MultiAnalyzer)Analyzer).AddOperator(qpc);


70  }


71 


72  protected override void Run(CancellationToken cancellationToken) {


73  var factory = new OplFactory();


74  var cplex = factory.CreateCplex();


75  cplex.Use(new LogCallback(this, cancellationToken));


76  cplex.SetParam(Cplex.DoubleParam.TiLim, MaximumRuntime.TotalSeconds);


77  var dataSource = new GQAPDataSource(factory, Problem.ProblemInstance);


78  using (var settings = factory.CreateOplSettings(factory.CreateOplErrorHandler()))


79  using (var opl = GetModel(factory, settings, cplex)) {


80  opl.AddDataSource(dataSource);


81  opl.Generate();


82  LastUpdateTimeParameter.Value = new DateTimeValue(DateTime.UtcNow);


83  cplex.Solve();


84  cplex.End();


85  }


86  Context.RunOperator(Analyzer, CancellationToken.None);


87  }


88 


89  protected abstract OplModel GetModel(OplFactory factory, OplSettings settings, Cplex cplex);


90  }


91 


92  public class LogCallback : Cplex.MIPInfoCallback {


93  private CplexSolver algorithm;


94  private CancellationToken token;


95  private double prev;


96 


97 


98  public LogCallback(CplexSolver algorithm, CancellationToken token) {


99  this.algorithm = algorithm;


100  this.token = token;


101  prev = double.NaN;


102  }


103 


104  protected override void Main() {


105  if (HasIncumbent()) {


106  var val = GetIncumbentObjValue();


107  if (val >= prev) return;


108  algorithm.Context.Iterations++;


109  algorithm.Context.BestQuality = val;


110  IResult result;


111  if (algorithm.Results.TryGetValue("Iterations", out result))


112  ((IntValue)result.Value).Value = algorithm.Context.Iterations;


113  else algorithm.Results.Add(new Result("Iterations", new IntValue(algorithm.Context.Iterations)));


114  if (algorithm.Results.TryGetValue("BestQuality", out result))


115  ((DoubleValue)result.Value).Value = algorithm.Context.BestQuality;


116  else algorithm.Results.Add(new Result("BestQuality", new DoubleValue(algorithm.Context.BestQuality)));


117  algorithm.Context.RunOperator(algorithm.Analyzer, CancellationToken.None);


118  prev = val;


119  if (val.IsAlmost(algorithm.Problem.BestKnownQuality))


120  Abort();


121  }


122  if (token.IsCancellationRequested) Abort();


123  }


124  }


125  }

