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

Last change on this file since 11892 was 11892, checked in by abeham, 7 years ago

#2174:

  • Branched ExternalEvaluation
    • Changed to use SingleObjectiveBasicProblem
    • Increased minor version number
  • Created view for MultiEncoding
  • Created dialog to construct encodings in the GUI

Setting up an external evaluation problem in HeuristicLab has finally become simple.

File size: 5.7 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.Parameters;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33using HeuristicLab.Problems.Programmable;
34
35namespace HeuristicLab.Problems.ExternalEvaluation {
36  [Item("External Evaluation Problem", "A problem that is evaluated in a different process.")]
37  [Creatable("Problems")]
38  [StorableClass]
39  public sealed class ExternalEvaluationProblem : SingleObjectiveBasicProblem<IEncoding> {
40    private HashSet<IEvaluationServiceClient> activeClients = new HashSet<IEvaluationServiceClient>();
41    private object clientLock = new object();
42
43    public static new Image StaticItemImage {
44      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
45    }
46
47    public OptionalValueParameter<EvaluationCache> CacheParameter {
48      get { return (OptionalValueParameter<EvaluationCache>)Parameters["Cache"]; }
49    }
50    public IValueParameter<CheckedItemCollection<IEvaluationServiceClient>> ClientsParameter {
51      get { return (IValueParameter<CheckedItemCollection<IEvaluationServiceClient>>)Parameters["Clients"]; }
52    }
53    public IValueParameter<SolutionMessageBuilder> MessageBuilderParameter {
54      get { return (IValueParameter<SolutionMessageBuilder>)Parameters["MessageBuilder"]; }
55    }
56
57    public EvaluationCache Cache {
58      get { return CacheParameter.Value; }
59    }
60    public CheckedItemCollection<IEvaluationServiceClient> Clients {
61      get { return ClientsParameter.Value; }
62    }
63    public SolutionMessageBuilder MessageBuilder {
64      get { return MessageBuilderParameter.Value; }
65    }
66
67    [StorableConstructor]
68    private ExternalEvaluationProblem(bool deserializing) : base(deserializing) { }
69    private ExternalEvaluationProblem(ExternalEvaluationProblem original, Cloner cloner) : base(original, cloner) { }
70    public override IDeepCloneable Clone(Cloner cloner) {
71      return new ExternalEvaluationProblem(this, cloner);
72    }
73    public ExternalEvaluationProblem()
74      : base() {
75      Parameters.Add(new OptionalValueParameter<EvaluationCache>("Cache", "Cache of previously evaluated solutions."));
76      Parameters.Add(new ValueParameter<CheckedItemCollection<IEvaluationServiceClient>>("Clients", "The clients that are used to communicate with the external application.", new CheckedItemCollection<IEvaluationServiceClient>() { new EvaluationServiceClient() }));
77      Parameters.Add(new ValueParameter<SolutionMessageBuilder>("MessageBuilder", "The message builder that converts from HeuristicLab objects to SolutionMessage representation.", new SolutionMessageBuilder()));
78    }
79
80    public override bool Maximization {
81      get { return Parameters.ContainsKey("Maximization") && ((IValueParameter<BoolValue>)Parameters["Maximization"]).Value.Value; }
82    }
83
84    public override double Evaluate(Individual individual, IRandom random) {
85      return Cache == null ? EvaluateOnNextAvailableClient(BuildSolutionMessage(individual)).Quality
86        : Cache.GetValue(BuildSolutionMessage(individual), m => EvaluateOnNextAvailableClient(m).Quality);
87    }
88
89    private QualityMessage EvaluateOnNextAvailableClient(SolutionMessage message) {
90      IEvaluationServiceClient client = null;
91      lock (clientLock) {
92        client = Clients.CheckedItems.FirstOrDefault(c => !activeClients.Contains(c));
93        while (client == null && Clients.CheckedItems.Any()) {
94          Monitor.Wait(clientLock);
95          client = Clients.CheckedItems.FirstOrDefault(c => !activeClients.Contains(c));
96        }
97        if (client != null)
98          activeClients.Add(client);
99      }
100      try {
101        return client.Evaluate(message, GetQualityMessageExtensions());
102      } finally {
103        lock (clientLock) {
104          activeClients.Remove(client);
105          Monitor.PulseAll(clientLock);
106        }
107      }
108    }
109
110    private ExtensionRegistry GetQualityMessageExtensions() {
111      return ExtensionRegistry.CreateInstance();
112    }
113
114    private SolutionMessage BuildSolutionMessage(Individual individual) {
115      lock (clientLock) {
116        SolutionMessage.Builder protobufBuilder = SolutionMessage.CreateBuilder();
117        protobufBuilder.SolutionId = 0;
118        var scope = new Scope();
119        individual.CopyToScope(scope);
120        foreach (var variable in scope.Variables) {
121          try {
122            MessageBuilder.AddToMessage(variable.Value, variable.Name, protobufBuilder);
123          } catch (ArgumentException ex) {
124            throw new InvalidOperationException(string.Format("ERROR while building solution message: Parameter {0} cannot be added to the message", name), ex);
125          }
126        }
127        return protobufBuilder.Build();
128      }
129    }
130  }
131}
Note: See TracBrowser for help on using the repository browser.