Free cookie consent management tool by TermsFeed Policy Generator

source: branches/ProgrammableProblem/HeuristicLab.Problems.ExternalEvaluation/3.4/ExternalEvaluationProblem.cs @ 11893

Last change on this file since 11893 was 11893, checked in by abeham, 10 years ago

#2174:

  • Added possibility to define neighborhood and analyze function for external evaluation problems
File size: 7.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 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
22using System;
23using System.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using System.Threading;
27using Google.ProtocolBuffers;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Optimization;
32using HeuristicLab.Parameters;
33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34using HeuristicLab.Problems.Programmable;
35
36namespace HeuristicLab.Problems.ExternalEvaluation {
37  [Item("External Evaluation Problem", "A problem that is evaluated in a different process.")]
38  [Creatable("Problems")]
39  [StorableClass]
40  public sealed class ExternalEvaluationProblem : SingleObjectiveBasicProblem<IEncoding> {
41    private HashSet<IEvaluationServiceClient> activeClients = new HashSet<IEvaluationServiceClient>();
42    private object clientLock = new object();
43
44    public static new Image StaticItemImage {
45      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
46    }
47
48    public OptionalValueParameter<EvaluationCache> CacheParameter {
49      get { return (OptionalValueParameter<EvaluationCache>)Parameters["Cache"]; }
50    }
51    public IValueParameter<CheckedItemCollection<IEvaluationServiceClient>> ClientsParameter {
52      get { return (IValueParameter<CheckedItemCollection<IEvaluationServiceClient>>)Parameters["Clients"]; }
53    }
54    public IValueParameter<SolutionMessageBuilder> MessageBuilderParameter {
55      get { return (IValueParameter<SolutionMessageBuilder>)Parameters["MessageBuilder"]; }
56    }
57    public IFixedValueParameter<SingleObjectiveOptimizationSupportScript> SupportScriptParameter {
58      get { return (IFixedValueParameter<SingleObjectiveOptimizationSupportScript>)Parameters["SupportScript"]; }
59    }
60
61    public EvaluationCache Cache {
62      get { return CacheParameter.Value; }
63    }
64    public CheckedItemCollection<IEvaluationServiceClient> Clients {
65      get { return ClientsParameter.Value; }
66    }
67    public SolutionMessageBuilder MessageBuilder {
68      get { return MessageBuilderParameter.Value; }
69    }
70    public SingleObjectiveOptimizationSupportScript OptimizationSupportScript {
71      get { return SupportScriptParameter.Value; }
72    }
73    private ISingleObjectiveOptimizationSupport OptimizationSupport {
74      get { return SupportScriptParameter.Value; }
75    }
76
77    [StorableConstructor]
78    private ExternalEvaluationProblem(bool deserializing) : base(deserializing) { }
79
80    private ExternalEvaluationProblem(ExternalEvaluationProblem original, Cloner cloner)
81      : base(original, cloner) {
82      try {
83        OptimizationSupportScript.Compile();
84      } catch (SingleObjectiveOptimizationSupportException ex) {
85        PluginInfrastructure.ErrorHandling.ShowErrorDialog("Support script doesn't compile.", ex);
86      }
87    }
88    public override IDeepCloneable Clone(Cloner cloner) {
89      return new ExternalEvaluationProblem(this, cloner);
90    }
91    public ExternalEvaluationProblem()
92      : base() {
93      Parameters.Add(new OptionalValueParameter<EvaluationCache>("Cache", "Cache of previously evaluated solutions."));
94      Parameters.Add(new ValueParameter<CheckedItemCollection<IEvaluationServiceClient>>("Clients", "The clients that are used to communicate with the external application.", new CheckedItemCollection<IEvaluationServiceClient>() { new EvaluationServiceClient() }));
95      Parameters.Add(new ValueParameter<SolutionMessageBuilder>("MessageBuilder", "The message builder that converts from HeuristicLab objects to SolutionMessage representation.", new SolutionMessageBuilder()));
96      Parameters.Add(new FixedValueParameter<SingleObjectiveOptimizationSupportScript>("SupportScript", "A script that can provide neighborhood and analyze the results of the optimization.", new SingleObjectiveOptimizationSupportScript()));
97    }
98
99    [StorableHook(HookType.AfterDeserialization)]
100    private void AfterDeserialization() {
101      try {
102        OptimizationSupportScript.Compile();
103      } catch (SingleObjectiveOptimizationSupportException ex) {
104        PluginInfrastructure.ErrorHandling.ShowErrorDialog("Support script doesn't compile.", ex);
105      }
106    }
107
108    public override bool Maximization {
109      get { return Parameters.ContainsKey("Maximization") && ((IValueParameter<BoolValue>)Parameters["Maximization"]).Value.Value; }
110    }
111
112    public override double Evaluate(Individual individual, IRandom random) {
113      return Cache == null ? EvaluateOnNextAvailableClient(BuildSolutionMessage(individual)).Quality
114        : Cache.GetValue(BuildSolutionMessage(individual), m => EvaluateOnNextAvailableClient(m).Quality);
115    }
116
117    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
118      OptimizationSupport.Analyze(individuals, qualities, results, random);
119    }
120
121    public override IEnumerable<Individual> GetNeighbors(Individual individual, IRandom random) {
122      return OptimizationSupport.GetNeighbors(individual, random);
123    }
124
125    private QualityMessage EvaluateOnNextAvailableClient(SolutionMessage message) {
126      IEvaluationServiceClient client = null;
127      lock (clientLock) {
128        client = Clients.CheckedItems.FirstOrDefault(c => !activeClients.Contains(c));
129        while (client == null && Clients.CheckedItems.Any()) {
130          Monitor.Wait(clientLock);
131          client = Clients.CheckedItems.FirstOrDefault(c => !activeClients.Contains(c));
132        }
133        if (client != null)
134          activeClients.Add(client);
135      }
136      try {
137        return client.Evaluate(message, GetQualityMessageExtensions());
138      } finally {
139        lock (clientLock) {
140          activeClients.Remove(client);
141          Monitor.PulseAll(clientLock);
142        }
143      }
144    }
145
146    private ExtensionRegistry GetQualityMessageExtensions() {
147      return ExtensionRegistry.CreateInstance();
148    }
149
150    private SolutionMessage BuildSolutionMessage(Individual individual) {
151      lock (clientLock) {
152        SolutionMessage.Builder protobufBuilder = SolutionMessage.CreateBuilder();
153        protobufBuilder.SolutionId = 0;
154        var scope = new Scope();
155        individual.CopyToScope(scope);
156        foreach (var variable in scope.Variables) {
157          try {
158            MessageBuilder.AddToMessage(variable.Value, variable.Name, protobufBuilder);
159          } catch (ArgumentException ex) {
160            throw new InvalidOperationException(string.Format("ERROR while building solution message: Parameter {0} cannot be added to the message", name), ex);
161          }
162        }
163        return protobufBuilder.Build();
164      }
165    }
166  }
167}
Note: See TracBrowser for help on using the repository browser.