#region License Information /* HeuristicLab * Copyright (C) 2002-2018 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.IO; using System.Linq; using HeuristicLab.Analysis.FitnessLandscape; using HeuristicLab.Core; using HeuristicLab.Encodings.PermutationEncoding; using HeuristicLab.Problems.Instances; using HeuristicLab.Problems.Instances.QAPLIB; using HeuristicLab.Random; using ProtoBuf; namespace WalkExporter { class RandomWalk { public static (Knowledgebase training, Knowledgebase test) GetKnowledgeBases(Experiment experiment, int length) { var training = new Knowledgebase() { Problems = new List() }; var test = new Knowledgebase() { Problems = new List() }; foreach (var trial in experiment.Trials) { foreach (var desc in AnalyzeEachWalk(trial, length)) { if (training.Problems.Count == test.Problems.Count) training.Problems.Add(desc); else test.Problems.Add(desc); } } return (training, test); } private static IEnumerable AnalyzeEachWalk(Exploration trial, int length) { var instance = trial.Problem; var dim = trial.Dimension; foreach (var walk in trial.Walks) { var trail = walk.QualityTrail.Take(length).ToArray(); var clen = RuggednessCalculator.CalculateCorrelationLength(trail, out double[] acf); var ia = new InformationAnalysis(trail); var desc = new ProblemInstanceDescriptor() { Name = instance, Class = Util.GetGeneratorClass(instance), Dimension = dim, DescriptionEffort = length * 4.0 / dim, }; desc.Features = new List(); desc.Features.Add(new KeyValue { Key = "AC1", ContinuousValue = acf[1] }); desc.Features.Add(new KeyValue { Key = "CorrelationLength", DiscreteValue = clen }); foreach (var f in ia.GetFeatures()) { if (f.Item2 is double d) desc.Features.Add(new KeyValue { Key = f.Item1, ContinuousValue = d }); else if (f.Item2 is int i) desc.Features.Add(new KeyValue { Key = f.Item1, DiscreteValue = i }); } yield return desc; } } public static Experiment PerformExperiment() { var experiment = new Experiment() { Algorithm = "RandomWalk", Trials = new List() }; foreach (var dimension in new[] { 20, 30, 40 }) { var provider = new OneSizeInstanceProvider(dimension); foreach (var desc in provider.GetDataDescriptors()) { var qapData = provider.LoadData(desc); var exploration = new Exploration() { Problem = qapData.Name, Dimension = qapData.Dimension, Walks = new List() }; for (var r = 0; r < 2; r++) { var walk = RandomWalk.Run(new MersenneTwister((uint)(r + 13)), qapData).Take((int)Math.Pow(2, 18)).ToList(); exploration.Walks.Add(new Walk() { QualityTrail = walk }); } experiment.Trials.Add(exploration); } } return experiment; } public static IEnumerable Run(IRandom random, QAPData qap) { var sol = new Permutation(PermutationTypes.Absolute, qap.Dimension, random); var fit = Util.Evaluate(sol, qap); yield return fit; while (true) { var z1 = random.Next(qap.Dimension); var z2 = (z1 + random.Next(1, qap.Dimension)) % qap.Dimension; var move = Util.EvaluateSwap2Diff(sol, z1, z2, qap); fit += move; yield return fit; sol.Swap(z1, z2); } } /////////////////////////////////////////////////////////////////////////////////// /// CONFINED RANDOM WALK /// /////////////////////////////////////////////////////////////////////////////////// public static void ConfinedRandomWalkAnalysis(QAPData qapData) { Exploration exploration = null; if (File.Exists($"confinedrandwalk_{qapData.Name}.buf")) { using (var file = File.OpenRead($"confinedrandwalk_{qapData.Name}.buf")) { exploration = Serializer.Deserialize(file); } } else { exploration = PerformCondinedRandomwWalkExploration(qapData, 100); using (var file = File.Create($"confinedrandwalk_{qapData.Name}.buf")) { Serializer.Serialize(file, exploration); } } using (var writer = File.CreateText($"confinedrandwalk_{qapData.Name}.csv")) { var headers = new[] { "Run", "Algorithm Name", "Problem Name", "Dimension", "Ld(Iterations)", "Iterations", "Effort", "AC1", "CorrelationLength", "InformationContent", "DensityBasinInformation", "PartialInformationContent", "InformationStability", "Diversity", "Regularity", "TotalEntropy", "SymmetricInformationContent", "SymmetricDensityBasinInformation", "SymmetricTotalEntropy", "PeakInformationContent", "PeakDensityBasinInformation", "PeakTotalEntropy", "PeakSymmetricInformationContent", "PeakSymmetricDensityBasinInformation", "PeakSymmetricTotalEntropy" }; var order = headers.Select((v, i) => new { Index = i, Header = v }).ToDictionary(x => x.Header, x => x.Index); writer.WriteLine(string.Format(string.Join(";", Enumerable.Range(0, headers.Length).Select(x => "{" + x + "}")), headers)); foreach (var exp in Enumerable.Range(7, 18 - 6)) { var length = (int)Math.Pow(2, exp); var run = 0; foreach (var desc in AnalyzeEachWalk(exploration, length)) { var features = string.Join(";", desc.Features.OrderBy(x => order[x.Key]).Select(x => x.GetNumericValue().ToString())); writer.WriteLine(string.Format("R{0};Confined Random Walk;{5};{6};{1};{2};{3};{4}", run, exp, length, length * 4.0 / qapData.Dimension, features, qapData.Name, qapData.Dimension)); run++; } } } } private static Exploration PerformCondinedRandomwWalkExploration(QAPData qapData, int repetitions) { var exploration = new Exploration() { Problem = qapData.Name, Dimension = qapData.Dimension, Walks = new List() }; for (var r = 0; r < repetitions; r++) { var walk = RunConfined(new MersenneTwister((uint)r), qapData, qapData.Dimension / 5).Take((int)Math.Pow(2, 18)).ToList(); exploration.Walks.Add(new Walk() { QualityTrail = walk }); } return exploration; } public static IEnumerable RunConfined(IRandom random, QAPData qap, int distance) { var sol = new Permutation(PermutationTypes.Absolute, qap.Dimension, random); var anchor = (Permutation)sol.Clone(); var fit = Util.Evaluate(sol, qap); var dist = 0; yield return fit; while (true) { var (j, k, deltaDist) = MoveConfined(random, sol, anchor, dist, distance); dist += deltaDist; var move = Util.EvaluateSwap2Diff(sol, j, k, qap); fit += move; yield return fit; sol.Swap(j, k); } } private static (int j, int k, int deltaDist) MoveConfined(IRandom random, Permutation current, Permutation anchor, int dist, int maxDist) { var evalSolPerMove = 4.0 / current.Length; var orderJ = Enumerable.Range(0, current.Length).Shuffle(random); var orderK = Enumerable.Range(0, current.Length).Shuffle(random); foreach (var j in orderJ) { if (dist == maxDist && current[j] == anchor[j]) continue; foreach (var k in orderK) { if (j == k) continue; var distChange = 0; if (current[j] != anchor[j] && current[k] == anchor[j]) distChange--; if (current[k] != anchor[k] && current[j] == anchor[k]) distChange--; if (current[j] == anchor[j]) distChange++; if (current[k] == anchor[k]) distChange++; if (dist + distChange > maxDist) continue; return (j, k, distChange); } } return (-1, -1, 0); } } }