Free cookie consent management tool by TermsFeed Policy Generator
wiki:Documentation/Howto/OptimizeExternalApplications

Version 9 (modified by abeham, 14 years ago) (diff)

--

Optimizing External Applications

Sometimes it is not possible to directly write a new problem for HeuristicLab and integrate it through the plugin system. Some people already have an application of which at least a part represents a NP hard problem that they'd like to solve. This guide explains how to use the ExternalEvaluationProblem that is available in HeuristicLab 3.3 to optimize problems written in a language other than C# or written using different frameworks, to name just a few possibilities. First the architecture is described, then a more detailed look into the API is given and finally a short tutorial should give the reader an idea of how to apply this to his/her case.

The most important part in any optimization problem is the evaluation function. Without knowing about the quality of a certain solution configuration the algorithm is not able to come close to an optimal solution. In NP hard problems evaluating a solution is usually a rather simple task, whereas finding the best solution is extremely difficult. Of course there can be complex problems which require high computational effort to calculate the quality of a solution, but in many cases the evaluation of a solution is rather straight forward. So, if the problem is not a HeuristicLab plugin we assume that it is available in another kind of executable format, either in an application itself or as part of another framework for example. We thus have a situation where we need inter-process communication (IPC). There are several possibilities of how to do IPC, in the following we will explain the approach we offer in HeuristicLab 3.3.

Architecture Overview

Technology & Background

Among the many possibilities and technologies that have emerged to provide a base for performing "distributed computing" in a wide sense, one of the first technologies was Remote Procedure Call (RPC). The idea is very simple: Instead of calling a local procedure to do some kind of calculation, a procedure is called that is not defined within the same executable or one of its dependencies. The client thus is in some ways hands the parameters of the method to another program or server, waits for the computation and then reads back the return value. In such a broad sense this is how most web applications nowadays work and indeed it is not until the invention of Representational State Transfer (REST) that there was a revolutionary change from this early RPC paradigm.

Recently Google, one of the biggest players in the world wide web released parts of their core RPC technologies to the general public. The framework that they call Protocol Buffers combines a domain specific language (DSL) for describing messages with an RPC framework that is used to pass these messages among different servers. The RPC framework itself is not released, but the DSL for describing messages and translating them to objects of several supported programming languages was released under the BSD license. Google directly supports C++, Java, and Python, but many developers have programmed ports of protocol buffers to different languages such as C#, Visual Basic, Objective C, Perl, Haskell, and many more. The documentation on protocol buffers is extremely helpful in understanding the framework. A similar framework called Thrift has evolved that backs the operation of Facebook and was also released to the public. These technologies provide convenient ways to define messages, manipulate them, and serialize them to small sizes at high speeds.

In HeuristicLab using remote procedure calls seems to fit very well with what we are trying to achieve in "exporting" the problem definition. The problem, to an optimizer, is basically the evaluation function and the solution representation is their common knowledge. A client is provided in HeuristicLab as well as a framework that enables developers to write a service which exposes the evaluation function to HeuristicLab. Using this service foreign language applications and problems can effectively communicate with HeuristicLab and have their parameters optimized by HeuristicLab's powerful optimization library. Please note that while we're talking about RPC, the provided frameworks are not compatible with the RPC standard, but are rather simplified to ease application. Think of RPC as a paradigm rather than a standard.

Communication also requires a given media over which to exchange the information. So far HeuristicLab offers two choices for the underlying media:

  1. The external program can be started as a process from HeuristicLab and the communication occurs via the process' stdin and stdout. This requires that the external program can be executed under Windows. If the developer controls the standard input and output streams and does not need to write or read other data through them, this might be a simple solution.
  2. The external program is started independently from HeuristicLab and opens a TCP/IP port for communicating over a network. This is independent of the platform and a universal solution that should work in most cases.

Regardless of the chosen media, the solution receiving and quality sending processes are abstracted from the developer through our service framework. For writing services, generally two types of services are supported by our framework: Push Service and Poll Service. It depends on the application which one of these is more suitable. If the developer is in charge of the control flow the push service seems plausible, if however the application flow cannot be fully controlled by the developer the poll service is the better suited option.

Push Service

As the name suggests when implementing a push service the solutions are pushed into the evaluation method. The developer has to provide a class that is able to perform the evaluation task. This class specifies a method that takes a SolutionMessage and returns a double value indicating the quality of the given solution. The method is called in a new thread whenever a new solution is received by the framework.

Poll Service

In this type the received solutions have to be polled. The service receives solutions in its own thread and puts them into a queue, waiting for the developer to process them. It provides two public methods, one that returns the next solution from the queue and blocks until a solution becomes available and another that sends the quality back to HeuristicLab.

Application Scenarios

One of the application scenarios that we had in mind when designing this interface is the field of simulation-based optimization. There, a simulation model defines a number of parameters which need to be adjusted such that a measured output of the model improves. This can be inventory sizes in a supply-chain scenario, or similarly buffer sizes in an assembly line, or training the weights in a neural network simulator. There are numerous optimization problems that are implemented as simulation models and one of the main problems is talking to them. Many different frameworks exist with which one can conveniently build, run, and test a simulation model, and most of them already have some support for optimization. However that support often is of proprietary nature and little information is available on how these methods perform. HeuristicLab aims to provide an open source alternative and the means of this interface allows simulation experts to use HeuristicLab in the optimization tasks.

Naturally, there exist several more reasons why a problem cannot be modeled in HeuristicLab, such as language or platform dependency and for these purposes this interface should provide a solution.

Architecture Details

Optimizing external applications divides into two parts:

  1. Providing an evaluation service for HeuristicLab in the external application
  2. Preparing an ExternalEvaluationProblem in HeuristicLab

These two tasks are described in this section in more detail.

Providing an evaluation service

The following class diagram displays the classes and interfaces present in the java service framework. There is an abstract base class Channel on the one hand which provides methods for sending and receiving messages and several concrete implementations and on the other hand an abstract base class Service that provides the concrete PollService and PushService. Each Channel has a corresponding factory which implements IChannelFactory.

No image "ExternalEvaluationServiceCD.png" attached to Documentation/Howto/OptimizeExternalApplications

In the source you will also find some test applications that provide very simple examples of how to use the service framework. They do not really evaluate a solution, but return a random number in the interval [0;1) for every received solution.

No image "ExternalEvaluationServiceTestCD.png" attached to Documentation/Howto/OptimizeExternalApplications

Usage examples

Here is the java code for the RandomStreamingPollEvaluator

public class RandomStreamingPollEvaluator {

  public static void main(String[] args) {
    StreamChannelFactory factory = new StreamChannelFactory(System.in, System.out);
    PollService service = new PollService(factory, 1);
    service.start();
    
    Random random = new Random();
    while (true) {
      SolutionMessage msg = service.getSolution();
      // parse the message and retrieve the variables there
      try {
        service.sendQuality(msg, random.nextDouble());
      } catch (IOException e) {
        break;
      }
    }
    
    service.stop();
  }
}

This code shows a concrete example of how to use the PollService and the ease of integrating this into an external java application. Using a PushService is slightly different as can be seen in the following example. As mentioned it depends on the application which of the two possibilities is more suited.

public class RandomSocketPushEvaluator {
  private PushService service;
  
  public static void main(String[] args) {
    RandomSocketPushEvaluator main = new RandomSocketPushEvaluator();
    main.run();
    System.out.println("Service is running, terminate by pressing <Return> or <Enter>.");
    System.console().readLine();
    main.terminate();
  }
  
  private void run() {
    ServerSocketChannelFactory factory = new ServerSocketChannelFactory(8843);
    service = new PushService(factory, 1, new RandomEvaluator());
    service.start();
  }
  
  private void terminate() {
    service.stop();
  }
  
  private class RandomEvaluator implements IEvaluationService {
    Random random;
    
    public RandomEvaluator() {
      random = new Random();
    }
    
    @Override
    public double evaluate(SolutionMessage msg) {
      return random.nextDouble();
    }
    
  }
}

Preparing an ExternalEvaluationProblem

In the HeuristicLab Optimizer a number of algorithms and problems are available which can be created, viewed and parameterized. Among them is a special problem designed for the purpose of calling an external evaluation function called ExternalEvaluationProblem. The problem allows the user to define a customized solution representation, as well as customizing the operators that are available to solve the problem. The following screenshot shows the default parameters of this problem.

Parameter list of the `ExternalEvaluationProblem`

The list of parameters that are available there are briefly described:

  • BestKnownQuality - Displays the best known quality of the problem, this is updated through a special analyzer.
  • BestKnownSolution - Houses the best known solution so far, that is the scope that contains the solution representation
  • Client - The client that transmits the solution to the external application. The user configures the client by defining the appropriate channel and channel connection information.
  • Evaluator - The evaluator is an operator that collects variables from the scope and includes them in a message which will be sent to the external application. The user has to configure the evaluator such that it can find the variables to collect.
  • Maximization - Is necessary for the algorithm to know whether it should minimize or maximize the quality value.
  • Operators - Contains a list of operators that the problem provides to the algorithm. In this list any Crossover, Manipulation or other operator will be passed to the algorithm and will be made selectable there.
  • SolutionCreator - Is an operator that creates a solution. This operator can also be adjusted by the user as needed. One can use the included representation generators in the HeuristicLab.Encodings namespace, or use own generators from an own plugin.

In the tutorial section it will be shown how to configure these parameters to solve a real problem.

For completeness reasons a class diagram of the HeuristicLab.Problems.ExternalEvaluation namespace shall also be given. The interaction of the classes shall be explained and the operators described.

Class diagram of the external evaluation problem in HeuristicLab

The equivalent to the channels in the java service framework are implemented also in C# for use in HeuristicLab. There is an Interface IEvaluationChannel that defines a channel. As can be seen from the class diagram the methods that each channel has to provide are exactly the same as in the java service framework. Basically a channel can be opened and closed and there are two functions for sending and receiving. In HeuristicLab however there exists a third channel, the EvaluationProcessChannel, that provides a convenience wrapper around an EvaluationStreamChannel that is attached to the stdin and stdout streams of a process started from HeuristicLab.

Also shown in the class diagram are a number of converters that are used to convert HeuristicLab data types, such as the variables that contain the solution representation, to a SolutionMessage. The SolutionMessageBuilder is the class that contains a number of converters and allows the ExternalEvaluator to construct the message. Which converter shall be used can be configured in the GUI when creating the ExternalEvaluationProblem and the converters are naturally extensible. A user can define an own converter implementing IItemToSolutionMessageConverter and add it to the SolutionMessageBuilder in the GUI. By default the SolutionMessageBuilder is configured with all the converters that can be seen which in turn cover all the data types in the HeuristicLab.Data namespace. The solution representations in HeuristicLab.Encodings are derived from those, so the converters also cover them too. But any solution representation not derived directly from one of the objects in HeuristicLab.Data naturally requires an own converter (e.g. HeuristicLab.Encodings.SymbolicExpressionTree is such a type). Next in the class diagram is the EvaluationServiceClient which holds a Channel and allows the ExternalEvaluator to communicate with the remote process. Finally, there is a class that describes the ExternalEvaluationPRoblem itself, as well as the QualityMessage (the expected answer from the service) and the SolutionMessage. These two are automatically created by parsing the ExternalEvaluationMessages.proto file with the compiler tools of Google's protocol buffer framework.

Tutorial

Attachments (29)