[6956] | 1 | #region License Information
|
---|
| 2 | /* HeuristicLab
|
---|
[16077] | 3 | * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
|
---|
[6956] | 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 |
|
---|
[7311] | 22 | using System;
|
---|
[15504] | 23 | using System.Collections.Generic;
|
---|
[6956] | 24 | using System.Linq;
|
---|
[15504] | 25 | using HeuristicLab.Analysis;
|
---|
[6956] | 26 | using HeuristicLab.Common;
|
---|
| 27 | using HeuristicLab.Core;
|
---|
| 28 | using HeuristicLab.Data;
|
---|
| 29 | using HeuristicLab.Encodings.IntegerVectorEncoding;
|
---|
| 30 | using HeuristicLab.Optimization;
|
---|
[15504] | 31 | using HeuristicLab.Optimization.Operators;
|
---|
[6956] | 32 | using HeuristicLab.Parameters;
|
---|
| 33 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
| 34 | using HeuristicLab.PluginInfrastructure;
|
---|
[7443] | 35 | using HeuristicLab.Problems.Instances;
|
---|
[16712] | 36 | using HEAL.Attic;
|
---|
[6956] | 37 |
|
---|
| 38 | namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
|
---|
[15490] | 39 | [Item("Generalized Quadratic Assignment Problem (GQAP)", "The Generalized Quadratic Assignment Problem (GQAP) is a generalization of the QAP in that it allows to assign multiple facilities (here called equipment) to a single location. The problem is described in Lee, C.G., and Ma, Z. 2003. The Generalized Quadratic Assignment Problem. Technical Report M5S 3G8, University of Toronto, Canada.")]
|
---|
[16077] | 40 | [Creatable(CreatableAttribute.Categories.CombinatorialProblems)]
|
---|
[16712] | 41 | [StorableType("20DC9B2F-F667-425E-A235-B0192CCB1BF4")]
|
---|
[15504] | 42 | public sealed class GQAP : SingleObjectiveBasicProblem<IntegerVectorEncoding>,
|
---|
[7548] | 43 | IProblemInstanceConsumer<QAPData>,
|
---|
| 44 | IProblemInstanceConsumer<CTAPData>,
|
---|
| 45 | IProblemInstanceConsumer<TSPData>,
|
---|
| 46 | IProblemInstanceConsumer<ATSPData>,
|
---|
| 47 | IProblemInstanceConsumer<GQAPData> {
|
---|
[7419] | 48 |
|
---|
[15504] | 49 | public override bool Maximization { get { return false; } }
|
---|
[6956] | 50 |
|
---|
[15506] | 51 | [Storable]
|
---|
| 52 | private bool initialized; // ABE: helper variable that defines if the constructor has completed
|
---|
| 53 |
|
---|
[7419] | 54 | #region Parameter Descriptions
|
---|
[7423] | 55 | public static readonly string BestKnownQualityDescription = "The best known quality (if available).";
|
---|
| 56 | public static readonly string BestKnownSolutionDescription = "The best known solution (if available).";
|
---|
[7438] | 57 | public static readonly string BestKnownSolutionsDescription = "Contains an archive of best-known solutions regarding flow-distance quality and installation quality.";
|
---|
[15504] | 58 | public static readonly string ProblemInstanceDescription = "The problem instance that is to be solved.";
|
---|
| 59 | public static readonly string EvaluationDescription = "The evaluation result of a solution to the GQAP.";
|
---|
[7419] | 60 | #endregion
|
---|
| 61 |
|
---|
[6956] | 62 | #region Parameter Properties
|
---|
[7470] | 63 | public OptionalValueParameter<GQAPAssignment> BestKnownSolutionParameter {
|
---|
| 64 | get { return (OptionalValueParameter<GQAPAssignment>)Parameters["BestKnownSolution"]; }
|
---|
[6956] | 65 | }
|
---|
[7438] | 66 | public OptionalValueParameter<GQAPAssignmentArchive> BestKnownSolutionsParameter {
|
---|
| 67 | get { return (OptionalValueParameter<GQAPAssignmentArchive>)Parameters["BestKnownSolutions"]; }
|
---|
| 68 | }
|
---|
[15504] | 69 | public IValueParameter<GQAPInstance> ProblemInstanceParameter {
|
---|
| 70 | get { return (IValueParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
|
---|
[7415] | 71 | }
|
---|
[6956] | 72 | #endregion
|
---|
| 73 |
|
---|
| 74 | #region Properties
|
---|
[7470] | 75 | public GQAPAssignment BestKnownSolution {
|
---|
[7443] | 76 | get { return BestKnownSolutionParameter.Value; }
|
---|
| 77 | set { BestKnownSolutionParameter.Value = value; }
|
---|
| 78 | }
|
---|
[7448] | 79 | public GQAPAssignmentArchive BestKnownSolutions {
|
---|
| 80 | get { return BestKnownSolutionsParameter.Value; }
|
---|
| 81 | set { BestKnownSolutionsParameter.Value = value; }
|
---|
| 82 | }
|
---|
[15504] | 83 | public GQAPInstance ProblemInstance {
|
---|
| 84 | get { return ProblemInstanceParameter.Value; }
|
---|
| 85 | set { ProblemInstanceParameter.Value = value; }
|
---|
| 86 | }
|
---|
[6956] | 87 | #endregion
|
---|
| 88 |
|
---|
| 89 | [StorableConstructor]
|
---|
[16712] | 90 | private GQAP(StorableConstructorFlag _) : base(_) { }
|
---|
[15504] | 91 | private GQAP(GQAP original, Cloner cloner)
|
---|
[6956] | 92 | : base(original, cloner) {
|
---|
[7432] | 93 | RegisterEventHandlers();
|
---|
[15506] | 94 | initialized = original.initialized;
|
---|
[6956] | 95 | }
|
---|
[15504] | 96 | public GQAP() : base() {
|
---|
| 97 | Encoding = new IntegerVectorEncoding("Assignment");
|
---|
[7480] | 98 | Parameters.Add(new OptionalValueParameter<GQAPAssignment>("BestKnownSolution", BestKnownSolutionDescription, null, false));
|
---|
[7438] | 99 | Parameters.Add(new OptionalValueParameter<GQAPAssignmentArchive>("BestKnownSolutions", BestKnownSolutionsDescription, null, false));
|
---|
[15504] | 100 | Parameters.Add(new ValueParameter<GQAPInstance>("ProblemInstance", "The problem instance that is to be solved.", new GQAPInstance(), false));
|
---|
[6956] | 101 |
|
---|
[15504] | 102 | InitializeOperators();
|
---|
| 103 | RegisterEventHandlers();
|
---|
[15506] | 104 | initialized = true;
|
---|
| 105 | Parameterize();
|
---|
[15504] | 106 | }
|
---|
[6956] | 107 |
|
---|
[15504] | 108 | public override IDeepCloneable Clone(Cloner cloner) {
|
---|
| 109 | return new GQAP(this, cloner);
|
---|
| 110 | }
|
---|
[6956] | 111 |
|
---|
[15504] | 112 | public override double Evaluate(Individual individual, IRandom random = null) {
|
---|
| 113 | var assignment = individual.IntegerVector();
|
---|
| 114 | var evaluation = ProblemInstance.Evaluate(assignment);
|
---|
| 115 | individual["Evaluation"] = evaluation;
|
---|
| 116 | return ProblemInstance.ToSingleObjective(evaluation);
|
---|
| 117 | }
|
---|
[6956] | 118 |
|
---|
[15504] | 119 | public double Evaluate(IntegerVector assignment) {
|
---|
| 120 | var evaluation = ProblemInstance.Evaluate(assignment);
|
---|
| 121 | return ProblemInstance.ToSingleObjective(evaluation);
|
---|
| 122 | }
|
---|
[6956] | 123 |
|
---|
[15504] | 124 | public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
|
---|
| 125 | AnalyzeBestSolution(results, GetBestIndividual(individuals, qualities));
|
---|
| 126 | AnalyzeParetoArchive(results,
|
---|
| 127 | individuals.Select(i => Tuple.Create((IntegerVector)i.IntegerVector().Clone(),
|
---|
| 128 | (Evaluation)i["Evaluation"])));
|
---|
| 129 | }
|
---|
[6956] | 130 |
|
---|
[15504] | 131 | private void AnalyzeBestSolution(ResultCollection results, Tuple<Individual, double> best) {
|
---|
| 132 | var bestVector = best.Item1.IntegerVector();
|
---|
| 133 | var bestEvaluation = (Evaluation)best.Item1["Evaluation"];
|
---|
[6956] | 134 |
|
---|
[15504] | 135 | IResult bestResult;
|
---|
| 136 | if (!results.TryGetValue("Best Solution", out bestResult)) {
|
---|
| 137 | bestResult = new Result("Best Solution", typeof(GQAPAssignment));
|
---|
| 138 | results.Add(bestResult);
|
---|
| 139 | }
|
---|
| 140 | var item = bestResult.Value as GQAPAssignment;
|
---|
| 141 | if (item == null) bestResult.Value = new GQAPAssignment((IntegerVector)bestVector.Clone(), ProblemInstance, bestEvaluation);
|
---|
| 142 | else if (ProblemInstance.ToSingleObjective(bestEvaluation)
|
---|
[16077] | 143 | < ProblemInstance.ToSingleObjective(item.Solution.Evaluation)) {
|
---|
[15504] | 144 | item.ProblemInstance = ProblemInstance;
|
---|
[16077] | 145 | item.Solution = new GQAPSolution((IntegerVector)bestVector.Clone(), bestEvaluation);
|
---|
[15504] | 146 | }
|
---|
[6956] | 147 | }
|
---|
| 148 |
|
---|
[15504] | 149 | private void AnalyzeParetoArchive(ResultCollection results, IEnumerable<Tuple<IntegerVector, Evaluation>> solutions) {
|
---|
| 150 | IResult archiveResult;
|
---|
| 151 | if (!results.TryGetValue("Solution Archive", out archiveResult)) {
|
---|
| 152 | archiveResult = new Result("Solution Archive", typeof(GQAPAssignmentArchive));
|
---|
| 153 | results.Add(archiveResult);
|
---|
| 154 | }
|
---|
| 155 | var archive = archiveResult.Value as GQAPAssignmentArchive;
|
---|
[15510] | 156 | if (archive == null) {
|
---|
| 157 | archive = new GQAPAssignmentArchive(ProblemInstance);
|
---|
| 158 | archiveResult.Value = archive;
|
---|
| 159 | } else archive.ProblemInstance = ProblemInstance;
|
---|
[15504] | 160 |
|
---|
| 161 | var combinedArchive = solutions
|
---|
| 162 | .Select(x => new GQAPSolution(x.Item1, x.Item2))
|
---|
| 163 | .Concat(archive.Solutions);
|
---|
| 164 | archive.Solutions = GetFeasibleParetoFront(combinedArchive);
|
---|
| 165 |
|
---|
| 166 | if (BestKnownSolutions == null) {
|
---|
| 167 | BestKnownSolutions = archive;
|
---|
| 168 | } else {
|
---|
| 169 | var combinedArchive2 = solutions
|
---|
| 170 | .Select(x => new GQAPSolution(x.Item1, x.Item2))
|
---|
| 171 | .Concat(BestKnownSolutions.Solutions);
|
---|
| 172 | BestKnownSolutions.Solutions = GetFeasibleParetoFront(combinedArchive2);
|
---|
| 173 | }
|
---|
[6956] | 174 | }
|
---|
| 175 |
|
---|
[7548] | 176 | #region Problem Instance Loading
|
---|
| 177 | public void Load(QAPData data) {
|
---|
| 178 | Name = data.Name;
|
---|
| 179 | Description = data.Description;
|
---|
[7448] | 180 |
|
---|
[7548] | 181 | var weights = new DoubleMatrix(data.Weights);
|
---|
| 182 | var distances = new DoubleMatrix(data.Distances);
|
---|
| 183 | var installationCosts = new DoubleMatrix(weights.Rows, distances.Columns); // all zero
|
---|
| 184 | var capacities = new DoubleArray(Enumerable.Range(0, distances.Rows).Select(x => 1.0).ToArray());
|
---|
| 185 | var demands = new DoubleArray(Enumerable.Range(0, weights.Rows).Select(x => 1.0).ToArray());
|
---|
[7443] | 186 |
|
---|
[7548] | 187 | Load(demands, capacities, weights, distances, installationCosts, new DoubleValue(1));
|
---|
| 188 | EvaluateAndLoadAssignment(data.BestKnownAssignment);
|
---|
| 189 | }
|
---|
[7445] | 190 |
|
---|
[7548] | 191 | public void Load(CTAPData data) {
|
---|
| 192 | Name = data.Name;
|
---|
| 193 | Description = data.Description;
|
---|
| 194 |
|
---|
| 195 | var capacities = new DoubleArray(data.MemoryCapacities);
|
---|
| 196 | var demands = new DoubleArray(data.MemoryRequirements);
|
---|
| 197 | var weights = new DoubleMatrix(data.CommunicationCosts);
|
---|
| 198 | var installationCosts = new DoubleMatrix(data.ExecutionCosts.Transpose());
|
---|
| 199 | var distances = new DoubleMatrix(capacities.Length, capacities.Length);
|
---|
| 200 | for (int i = 0; i < capacities.Length - 1; i++)
|
---|
| 201 | for (int j = i + 1; j < capacities.Length; j++) {
|
---|
| 202 | distances[i, j] = 1;
|
---|
[7466] | 203 | }
|
---|
[7548] | 204 |
|
---|
| 205 | Load(demands, capacities, weights, distances, installationCosts, new DoubleValue(1));
|
---|
| 206 | EvaluateAndLoadAssignment(data.BestKnownAssignment);
|
---|
[7443] | 207 | }
|
---|
| 208 |
|
---|
[7548] | 209 | public void Load(TSPData data) {
|
---|
| 210 | if (data.Dimension > 1000)
|
---|
| 211 | throw new System.IO.InvalidDataException("Instances with more than 1000 cities are not supported.");
|
---|
[7448] | 212 |
|
---|
[7548] | 213 | Name = data.Name;
|
---|
| 214 | Description = data.Description;
|
---|
[7466] | 215 |
|
---|
[7548] | 216 | var capacities = new DoubleArray(data.Dimension);
|
---|
| 217 | var demands = new DoubleArray(data.Dimension);
|
---|
| 218 | for (int i = 0; i < data.Dimension; i++) {
|
---|
| 219 | capacities[i] = 1;
|
---|
| 220 | demands[i] = 1;
|
---|
| 221 | }
|
---|
| 222 | var installationCosts = new DoubleMatrix(data.Dimension, data.Dimension);
|
---|
| 223 | var weights = new DoubleMatrix(data.Dimension, data.Dimension);
|
---|
| 224 | for (int i = 0; i < data.Dimension; i++)
|
---|
| 225 | weights[i, (i + 1) % data.Dimension] = 1;
|
---|
| 226 | var distances = new DoubleMatrix(data.GetDistanceMatrix());
|
---|
[7466] | 227 |
|
---|
[7548] | 228 | Load(demands, capacities, weights, distances, installationCosts, new DoubleValue(1));
|
---|
| 229 | EvaluateAndLoadAssignment(data.BestKnownTour);
|
---|
| 230 | }
|
---|
| 231 |
|
---|
| 232 | public void Load(ATSPData data) {
|
---|
| 233 | Name = data.Name;
|
---|
| 234 | Description = data.Description;
|
---|
| 235 |
|
---|
| 236 | var capacities = new DoubleArray(data.Dimension);
|
---|
| 237 | var demands = new DoubleArray(data.Dimension);
|
---|
| 238 | for (int i = 0; i < data.Dimension; i++) {
|
---|
| 239 | capacities[i] = 1;
|
---|
| 240 | demands[i] = 1;
|
---|
[7466] | 241 | }
|
---|
[7548] | 242 | var installationCosts = new DoubleMatrix(data.Dimension, data.Dimension);
|
---|
| 243 | var weights = new DoubleMatrix(data.Dimension, data.Dimension);
|
---|
| 244 | for (int i = 0; i < data.Dimension; i++)
|
---|
| 245 | weights[i, (i + 1) % data.Dimension] = 1;
|
---|
| 246 | var distances = new DoubleMatrix(data.Distances);
|
---|
| 247 |
|
---|
| 248 | Load(demands, capacities, weights, distances, installationCosts, new DoubleValue(1));
|
---|
| 249 | EvaluateAndLoadAssignment(data.BestKnownTour);
|
---|
[7466] | 250 | }
|
---|
[7445] | 251 |
|
---|
[7548] | 252 | public void Load(GQAPData data) {
|
---|
| 253 | Name = data.Name;
|
---|
| 254 | Description = data.Description;
|
---|
[7470] | 255 |
|
---|
[7548] | 256 | var capacities = new DoubleArray(data.Capacities);
|
---|
| 257 | var demands = new DoubleArray(data.Demands);
|
---|
| 258 | var installationCosts = new DoubleMatrix(data.InstallationCosts);
|
---|
| 259 | var weights = new DoubleMatrix(data.Weights);
|
---|
| 260 | var distances = new DoubleMatrix(data.Distances);
|
---|
| 261 | var transportationCosts = new DoubleValue(data.TransportationCosts);
|
---|
[7445] | 262 |
|
---|
[7548] | 263 | Load(demands, capacities, weights, distances, installationCosts, transportationCosts);
|
---|
| 264 | EvaluateAndLoadAssignment(data.BestKnownAssignment);
|
---|
[7466] | 265 |
|
---|
[7548] | 266 | if (data.BestKnownAssignment == null && data.BestKnownQuality.HasValue) {
|
---|
[15504] | 267 | BestKnownQuality = data.BestKnownQuality.Value;
|
---|
[7445] | 268 | }
|
---|
| 269 | }
|
---|
| 270 |
|
---|
[7548] | 271 | public void Load(DoubleArray demands, DoubleArray capacities,
|
---|
| 272 | DoubleMatrix weights, DoubleMatrix distances, DoubleMatrix installationCosts,
|
---|
[7970] | 273 | DoubleValue transportationCosts) {
|
---|
[7548] | 274 | if (weights == null || weights.Rows == 0)
|
---|
| 275 | throw new System.IO.InvalidDataException(
|
---|
| 276 | @"The given instance does not contain weights!");
|
---|
| 277 | if (weights.Rows != weights.Columns)
|
---|
| 278 | throw new System.IO.InvalidDataException(
|
---|
[7970] | 279 | @"The weights matrix of the given instance contains
|
---|
| 280 | an unequal number of rows and columns.");
|
---|
[7548] | 281 | if (distances == null || distances.Rows == 0)
|
---|
| 282 | throw new System.IO.InvalidDataException(
|
---|
| 283 | @"The given instance does not contain distances!");
|
---|
| 284 | if (distances.Rows != distances.Columns)
|
---|
| 285 | throw new System.IO.InvalidDataException(
|
---|
[7970] | 286 | @"The distances matrix of the given instance contains
|
---|
| 287 | an unequal number of rows and columns.");
|
---|
[7548] | 288 | if (installationCosts == null || installationCosts.Rows == 0)
|
---|
| 289 | throw new System.IO.InvalidDataException(
|
---|
| 290 | @"The given instance does not contain installation costs!");
|
---|
| 291 | if (installationCosts.Rows != weights.Rows
|
---|
| 292 | || installationCosts.Columns != distances.Columns)
|
---|
| 293 | throw new System.IO.InvalidDataException(
|
---|
[7970] | 294 | @"The installation costs matrix of the given instance
|
---|
| 295 | contains different number of rows than given in the
|
---|
| 296 | weights matrix and a different number of columns than
|
---|
[7548] | 297 | given in the distances matrix.");
|
---|
| 298 | if (capacities == null || capacities.Length == 0)
|
---|
| 299 | throw new System.IO.InvalidDataException(
|
---|
| 300 | @"The given instance does not contain capacities!");
|
---|
| 301 | if (capacities.Length != distances.Rows)
|
---|
| 302 | throw new System.IO.InvalidDataException(
|
---|
[7970] | 303 | @"The given instance contains a different number of
|
---|
| 304 | capacities than rows given in the distances matrix.");
|
---|
[7548] | 305 | if (demands == null || demands.Length == 0)
|
---|
| 306 | throw new System.IO.InvalidDataException(
|
---|
| 307 | @"The given instance does not contain demands!");
|
---|
| 308 | if (demands.Length != weights.Rows)
|
---|
| 309 | throw new System.IO.InvalidDataException(
|
---|
[7970] | 310 | @"The given instance contains a different number of
|
---|
| 311 | demands than rows given in the weights matrix.");
|
---|
[7548] | 312 | if (transportationCosts == null)
|
---|
| 313 | throw new System.IO.InvalidDataException(
|
---|
| 314 | @"The given instance does not contain transportation costs.");
|
---|
[7523] | 315 |
|
---|
[15504] | 316 | ProblemInstance = new GQAPInstance() {
|
---|
| 317 | Weights = weights,
|
---|
| 318 | Distances = distances,
|
---|
| 319 | InstallationCosts = installationCosts,
|
---|
| 320 | Capacities = capacities,
|
---|
| 321 | Demands = demands,
|
---|
| 322 | TransportationCosts = transportationCosts.Value
|
---|
| 323 | };
|
---|
| 324 | BestKnownQualityParameter.Value = null;
|
---|
[7548] | 325 | BestKnownSolution = null;
|
---|
| 326 | BestKnownSolutions = null;
|
---|
[15504] | 327 | ProblemInstance.CalculatePenaltyLevel();
|
---|
[7523] | 328 | }
|
---|
[7445] | 329 | private void EvaluateAndLoadAssignment(int[] vector) {
|
---|
[7548] | 330 | if (vector == null || vector.Length == 0) return;
|
---|
[7471] | 331 | EvaluateAndLoadAssignment(new IntegerVector(vector));
|
---|
| 332 | }
|
---|
[7548] | 333 | public void EvaluateAndLoadAssignment(IntegerVector assignment) {
|
---|
[15504] | 334 | if (!ProblemInstance.IsValid()) {
|
---|
| 335 | BestKnownQualityParameter.Value = null;
|
---|
[7523] | 336 | BestKnownSolution = null;
|
---|
| 337 | BestKnownSolutions = null;
|
---|
[15504] | 338 | return;
|
---|
[7523] | 339 | }
|
---|
[15504] | 340 | var evaluation = ProblemInstance.Evaluate(assignment);
|
---|
| 341 | var quality = ProblemInstance.ToSingleObjective(evaluation);
|
---|
| 342 |
|
---|
| 343 | BestKnownSolution = new GQAPAssignment((IntegerVector)assignment.Clone(), ProblemInstance, evaluation);
|
---|
| 344 | BestKnownQuality = quality;
|
---|
| 345 | BestKnownSolutions = new GQAPAssignmentArchive(ProblemInstance);
|
---|
| 346 | BestKnownSolutions.Solutions.Add(new GQAPSolution((IntegerVector)assignment.Clone(), evaluation));
|
---|
[7445] | 347 | }
|
---|
[7548] | 348 | #endregion
|
---|
[7445] | 349 |
|
---|
[6956] | 350 | #region Events
|
---|
[7311] | 351 | protected override void OnOperatorsChanged() {
|
---|
| 352 | base.OnOperatorsChanged();
|
---|
[15506] | 353 | if (!initialized) return;
|
---|
[7311] | 354 | Parameterize();
|
---|
| 355 | }
|
---|
[15504] | 356 | protected override void OnEncodingChanged() {
|
---|
| 357 | base.OnEncodingChanged();
|
---|
[15506] | 358 | if (!initialized) return;
|
---|
[7311] | 359 | Parameterize();
|
---|
| 360 | }
|
---|
[6956] | 361 | #endregion
|
---|
| 362 |
|
---|
| 363 | #region Helpers
|
---|
| 364 | [StorableHook(HookType.AfterDeserialization)]
|
---|
[7412] | 365 | private void AfterDeserialization() {
|
---|
[7432] | 366 | RegisterEventHandlers();
|
---|
[6956] | 367 | }
|
---|
| 368 |
|
---|
[7432] | 369 | private void RegisterEventHandlers() {
|
---|
[15504] | 370 | ProblemInstanceParameter.ValueChanged += ProblemInstanceParameterOnValueChanged;
|
---|
| 371 | ProblemInstance.CapacitiesParameter.ValueChanged += ProblemInstanceCapacitiesParameterOnValueChanged;
|
---|
| 372 | ProblemInstance.DemandsParameter.ValueChanged += ProblemInstanceDemandsParameterOnValueChanged;
|
---|
| 373 | ProblemInstance.Capacities.Reset += ProblemInstanceCapacitiesOnReset;
|
---|
| 374 | ProblemInstance.Demands.Reset += ProblemInstanceDemandsOnReset;
|
---|
[6956] | 375 | }
|
---|
| 376 |
|
---|
[15504] | 377 | private void ProblemInstanceParameterOnValueChanged(object sender, EventArgs e) {
|
---|
| 378 | ProblemInstance.CapacitiesParameter.ValueChanged += ProblemInstanceCapacitiesParameterOnValueChanged;
|
---|
| 379 | ProblemInstance.Capacities.Reset += ProblemInstanceCapacitiesOnReset;
|
---|
| 380 | ProblemInstance.DemandsParameter.ValueChanged += ProblemInstanceDemandsParameterOnValueChanged;
|
---|
| 381 | ProblemInstance.Demands.Reset += ProblemInstanceDemandsOnReset;
|
---|
| 382 | UpdateEncoding();
|
---|
| 383 | }
|
---|
| 384 | private void ProblemInstanceCapacitiesParameterOnValueChanged(object sender, EventArgs e) {
|
---|
| 385 | ProblemInstance.Capacities.Reset += ProblemInstanceCapacitiesOnReset;
|
---|
| 386 | UpdateEncoding();
|
---|
| 387 | }
|
---|
| 388 | private void ProblemInstanceDemandsParameterOnValueChanged(object sender, EventArgs e) {
|
---|
| 389 | ProblemInstance.Demands.Reset += ProblemInstanceDemandsOnReset;
|
---|
| 390 | UpdateEncoding();
|
---|
| 391 | }
|
---|
| 392 | private void ProblemInstanceDemandsOnReset(object sender, EventArgs e) {
|
---|
| 393 | UpdateEncoding();
|
---|
| 394 | }
|
---|
| 395 | private void ProblemInstanceCapacitiesOnReset(object sender, EventArgs e) {
|
---|
| 396 | UpdateEncoding();
|
---|
| 397 | }
|
---|
| 398 |
|
---|
| 399 | private void UpdateEncoding() {
|
---|
| 400 | Encoding.Length = ProblemInstance.Demands.Length;
|
---|
| 401 | Encoding.Bounds = new IntMatrix(new int[,] { { 0, ProblemInstance.Capacities.Length } });
|
---|
| 402 | }
|
---|
| 403 |
|
---|
[6956] | 404 | private void InitializeOperators() {
|
---|
[15510] | 405 | Operators.RemoveAll(x => x is ISingleObjectiveMoveOperator);
|
---|
| 406 | Operators.RemoveAll(x => x is SingleObjectiveImprover);
|
---|
[7415] | 407 | Operators.AddRange(ApplicationManager.Manager.GetInstances<IGQAPOperator>());
|
---|
[7413] | 408 | Operators.AddRange(ApplicationManager.Manager.GetInstances<IGQAPMoveEvaluator>());
|
---|
[15506] | 409 | Operators.Add(new HammingSimilarityCalculator() { SolutionVariableName = Encoding.Name, QualityVariableName = Evaluator.QualityParameter.ActualName });
|
---|
| 410 | Operators.Add(new QualitySimilarityCalculator() { SolutionVariableName = Encoding.Name, QualityVariableName = Evaluator.QualityParameter.ActualName });
|
---|
[15504] | 411 |
|
---|
| 412 | Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
|
---|
[6956] | 413 | }
|
---|
[7311] | 414 |
|
---|
| 415 | private void Parameterize() {
|
---|
[7419] | 416 | var operators = Operators.Union(new IOperator[] { SolutionCreator, Evaluator }).ToArray();
|
---|
[15506] | 417 | Encoding.ConfigureOperators(operators.OfType<IOperator>());
|
---|
| 418 | foreach (var op in operators.OfType<IAssignmentAwareGQAPOperator>()) {
|
---|
| 419 | op.AssignmentParameter.ActualName = Encoding.Name;
|
---|
| 420 | op.AssignmentParameter.Hidden = true;
|
---|
| 421 | }
|
---|
[7419] | 422 | foreach (var op in operators.OfType<IBestKnownQualityAwareGQAPOperator>()) {
|
---|
| 423 | op.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
|
---|
[7970] | 424 | op.BestKnownQualityParameter.Hidden = true;
|
---|
[7419] | 425 | }
|
---|
| 426 | foreach (var op in operators.OfType<IBestKnownSolutionAwareGQAPOperator>()) {
|
---|
| 427 | op.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
|
---|
[7970] | 428 | op.BestKnownSolutionParameter.Hidden = true;
|
---|
[7419] | 429 | }
|
---|
[7438] | 430 | foreach (var op in operators.OfType<IBestKnownSolutionsAwareGQAPOperator>()) {
|
---|
| 431 | op.BestKnownSolutionsParameter.ActualName = BestKnownSolutionsParameter.Name;
|
---|
[7970] | 432 | op.BestKnownSolutionsParameter.Hidden = true;
|
---|
[7438] | 433 | }
|
---|
[7419] | 434 | foreach (var op in operators.OfType<IGQAPCrossover>()) {
|
---|
[15504] | 435 | op.ParentsParameter.ActualName = Encoding.Name;
|
---|
[7970] | 436 | op.ParentsParameter.Hidden = true;
|
---|
[15504] | 437 | op.ChildParameter.ActualName = Encoding.Name;
|
---|
[7970] | 438 | op.ChildParameter.Hidden = true;
|
---|
[7319] | 439 | }
|
---|
[7419] | 440 | var moveEvaluator = operators.OfType<IGQAPMoveEvaluator>().FirstOrDefault();
|
---|
| 441 | foreach (var op in operators.OfType<IGQAPMoveEvaluator>()) { // synchronize all move evaluators
|
---|
| 442 | if (moveEvaluator != null) {
|
---|
| 443 | op.MoveQualityParameter.ActualName = moveEvaluator.MoveQualityParameter.ActualName;
|
---|
[7970] | 444 | op.MoveQualityParameter.Hidden = true;
|
---|
[15504] | 445 | op.MoveEvaluationParameter.ActualName = "MoveEvaluation";
|
---|
| 446 | op.MoveEvaluationParameter.Hidden = true;
|
---|
[7419] | 447 | }
|
---|
| 448 | }
|
---|
| 449 | foreach (var op in operators.OfType<IMoveQualityAwareGQAPOperator>()) {
|
---|
| 450 | if (moveEvaluator != null) {
|
---|
| 451 | op.MoveQualityParameter.ActualName = moveEvaluator.MoveQualityParameter.ActualName;
|
---|
[7970] | 452 | op.MoveQualityParameter.Hidden = true;
|
---|
[15504] | 453 | op.MoveEvaluationParameter.ActualName = "MoveEvaluation";
|
---|
| 454 | op.MoveEvaluationParameter.Hidden = true;
|
---|
[7419] | 455 | }
|
---|
| 456 | }
|
---|
[15504] | 457 | foreach (var op in operators.OfType<IProblemInstanceAwareGQAPOperator>()) {
|
---|
| 458 | op.ProblemInstanceParameter.ActualName = ProblemInstanceParameter.Name;
|
---|
| 459 | op.ProblemInstanceParameter.Hidden = true;
|
---|
[7419] | 460 | }
|
---|
| 461 | foreach (var op in operators.OfType<IQualitiesAwareGQAPOperator>()) {
|
---|
[7412] | 462 | op.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
|
---|
[7970] | 463 | op.QualityParameter.Hidden = true;
|
---|
[15504] | 464 | op.EvaluationParameter.ActualName = "Evaluation";
|
---|
| 465 | op.EvaluationParameter.Hidden = true;
|
---|
[7407] | 466 | }
|
---|
[7419] | 467 | foreach (var op in operators.OfType<IQualityAwareGQAPOperator>()) {
|
---|
[7412] | 468 | op.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
|
---|
[7970] | 469 | op.QualityParameter.Hidden = true;
|
---|
[15504] | 470 | op.EvaluationParameter.ActualName = "Evaluation";
|
---|
| 471 | op.EvaluationParameter.Hidden = true;
|
---|
[7412] | 472 | }
|
---|
[15504] | 473 | }
|
---|
| 474 | #endregion
|
---|
[7407] | 475 |
|
---|
[15504] | 476 | public static ItemList<GQAPSolution> GetFeasibleParetoFront(IEnumerable<GQAPSolution> solutions) {
|
---|
| 477 | var front = new ItemList<GQAPSolution>(solutions.Where(x => x.Evaluation.IsFeasible));
|
---|
[7970] | 478 |
|
---|
[15504] | 479 | for (int i = 0; i < front.Count - 1; i++) {
|
---|
| 480 | for (int j = i + 1; j < front.Count; j++) {
|
---|
| 481 | if (front[i].Evaluation.FlowCosts <= front[j].Evaluation.FlowCosts
|
---|
| 482 | && front[i].Evaluation.InstallationCosts <= front[j].Evaluation.InstallationCosts) {
|
---|
| 483 | front.RemoveAt(j);
|
---|
| 484 | j--;
|
---|
| 485 | } else if (front[i].Evaluation.FlowCosts >= front[j].Evaluation.FlowCosts
|
---|
| 486 | && front[i].Evaluation.InstallationCosts >= front[j].Evaluation.InstallationCosts) {
|
---|
| 487 | front.RemoveAt(i);
|
---|
| 488 | j = i;
|
---|
| 489 | }
|
---|
| 490 | }
|
---|
[7970] | 491 | }
|
---|
[15504] | 492 | return front;
|
---|
[6956] | 493 | }
|
---|
| 494 | }
|
---|
| 495 | }
|
---|