#region License Information /* HeuristicLab * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Threading; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.IntegerVectorEncoding; using HeuristicLab.Optimization; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using ILOG.CPLEX; using ILOG.OPL; namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.CPLEX { [Item("CPLEX Solver (GQAP)", "Base class")] [StorableClass] public abstract class CplexSolver : ContextAlgorithm { public override bool SupportsPause { get { return false; } } public override Type ProblemType { get { return typeof(GQAP); } } public new GQAP Problem { get { return (GQAP)base.Problem; } set { base.Problem = value; } } [StorableConstructor] protected CplexSolver(bool deserializing) : base(deserializing) { } protected CplexSolver(CplexSolver original, Cloner cloner) : base(original, cloner) { } public CplexSolver() { Problem = new GQAP(); } protected override void Run(CancellationToken cancellationToken) { base.Run(cancellationToken); var factory = new OplFactory(); var cplex = factory.CreateCplex(); cplex.Use(new LogCallback(this, cancellationToken)); cplex.SetParam(Cplex.DoubleParam.TiLim, MaximumRuntime.TotalSeconds); cplex.SetParam(Cplex.IntParam.Threads, 1); var dataSource = new GQAPDataSource(factory, Problem.ProblemInstance); using (var settings = factory.CreateOplSettings(factory.CreateOplErrorHandler())) using (var opl = GetModel(factory, settings, cplex)) { opl.AddDataSource(dataSource); opl.Generate(); if (cplex.Solve()) { var obj = cplex.ObjValue; if (double.IsNaN(Context.BestQuality) || obj < Context.BestQuality) Context.BestQuality = obj; IResult result; if (Results.TryGetValue("BestQuality", out result)) ((DoubleValue)result.Value).Value = Context.BestQuality; else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality))); Context.RunOperator(Analyzer, CancellationToken.None); } cplex.End(); } Context.RunOperator(Analyzer, CancellationToken.None); } protected abstract OplModel GetModel(OplFactory factory, OplSettings settings, Cplex cplex); } public class LogCallback : Cplex.MIPInfoCallback { private CplexSolver algorithm; private CancellationToken token; private double prev; public LogCallback(CplexSolver algorithm, CancellationToken token) { this.algorithm = algorithm; this.token = token; prev = double.NaN; } protected override void Main() { if (HasIncumbent()) { var val = GetIncumbentObjValue(); if (val >= prev) return; algorithm.Context.Iterations++; algorithm.Context.BestQuality = val; IResult result; if (algorithm.Results.TryGetValue("Iterations", out result)) ((IntValue)result.Value).Value = algorithm.Context.Iterations; else algorithm.Results.Add(new Result("Iterations", new IntValue(algorithm.Context.Iterations))); if (algorithm.Results.TryGetValue("BestQuality", out result)) ((DoubleValue)result.Value).Value = algorithm.Context.BestQuality; else algorithm.Results.Add(new Result("BestQuality", new DoubleValue(algorithm.Context.BestQuality))); algorithm.Context.RunOperator(algorithm.Analyzer, CancellationToken.None); prev = val; if (val.IsAlmost(algorithm.Problem.BestKnownQuality)) Abort(); } if (token.IsCancellationRequested) Abort(); } } }