#region License Information
/* HeuristicLab
* Copyright (C) 2002-2016 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.Collections.Generic;
using System.Linq;
using System.Threading;
using HeuristicLab.Algorithms.MemPR.Util;
using HeuristicLab.Core;
using HeuristicLab.Encodings.PermutationEncoding;
using HeuristicLab.Random;
namespace HeuristicLab.Algorithms.MemPR.Permutation.LocalSearch {
public static class ExhaustiveSwap2 {
public static IEnumerable>
HillClimb(IRandom random, Encodings.PermutationEncoding.Permutation perm,
double quality, bool maximization, Func eval,
CancellationToken token, bool[,] subspace = null) {
var evaluations = 0;
var current = perm;
if (double.IsNaN(quality)) {
quality = eval(current, token);
evaluations++;
}
Swap2Move lastSuccessMove = null;
var neighborhood = ExhaustiveSwap2MoveGenerator.Generate(current).Shuffle(random).ToList();
while (true) {
foreach (var swap in neighborhood) {
if (lastSuccessMove != null && swap.Index1 == lastSuccessMove.Index1 && swap.Index2 == lastSuccessMove.Index2) {
// been there, done that
lastSuccessMove = null;
break;
}
if (subspace != null && !(subspace[swap.Index1, 0] && subspace[swap.Index2, 0]))
continue;
var h = current[swap.Index1];
current[swap.Index1] = current[swap.Index2];
current[swap.Index2] = h;
var q = eval(current, token);
evaluations++;
if (FitnessComparer.IsBetter(maximization, q, quality)) {
yield return Tuple.Create(current, q, evaluations);
quality = q;
lastSuccessMove = swap;
} else {
current[swap.Index2] = current[swap.Index1];
current[swap.Index1] = h;
}
if (token.IsCancellationRequested) {
lastSuccessMove = null;
break;
}
}
if (lastSuccessMove == null) break;
}
yield return Tuple.Create(current, quality, evaluations);
}
}
}