12 | | 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. |
13 | | |
14 | | Recently [http://www.google.com 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 [http://code.google.com/p/protobuf/ 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 [http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns many more]. The [http://code.google.com/apis/protocolbuffers/docs/overview.html documentation] on protocol buffers is extremely helpful in understanding the framework. A similar framework called Thrift has evolved that backs the operation of [http://www.facebook.com 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. |
15 | | |
16 | | 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. |
17 | | |
18 | | Communication also requires a given media over which to exchange the information. So far HeuristicLab offers two choices for the underlying media: |
19 | | 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. |
20 | | 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. |
21 | | |
22 | | 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. |
23 | | |
24 | | === Push Service === |
25 | | |
26 | | 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. |
27 | | |
28 | | === Poll Service === |
29 | | |
30 | | 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. |
| 12 | Recently [http://www.google.com Google], released parts of their core RPC technologies to the general public. The framework that they call [http://code.google.com/p/protobuf/ Protocol Buffers] combines a domain specific language (DSL) for describing messages within 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 [http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns many more]. The [http://code.google.com/apis/protocolbuffers/docs/overview.html documentation] on protocol buffers is extremely helpful in understanding the framework. Protocol buffers provide convenient ways to define messages, manipulate them, and serialize them to small sizes at high speeds. |
| 13 | |
| 14 | 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. |
| 15 | |
| 16 | Communication also requires a given media over which to exchange the information and the preferred choice in HeuristicLab is to communicate via the TCP/IP network: The external program is started independently from HeuristicLab and opens a TCP/IP port for communicating over a network. |
| 17 | |
| 18 | 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. Generally, the poll service is a simple to use solution that should fit most needs. The implementation of these service frameworks are attached to the end of this page and are available in Java and in C# in binary as well as source code: |
| 19 | * Download the [[attachment:HL3ExternalEvaluation.jar|Java JAR library]] (binary) |
| 20 | * Download the [[attachment:HL3ExternalEvaluationCSharp.zip|C# library]] (binary) |
| 21 | * Download the [[attachment:HeuristicLab.Problems.ExternalEvaluation (src).zip|Source code]] - useful for understanding how to use the library |
59 | | public class RandomSocketPollEvaluator { |
60 | | |
61 | | public static void main(String[] args) { |
62 | | ServerSocketListenerFactory factory = new ServerSocketListenerFactory(8842); |
63 | | PollService service = new PollService(factory, 1); |
64 | | service.start(); |
| 50 | public static void main(String[] args) { |
| 51 | ServerSocketListenerFactory factory = new ServerSocketListenerFactory(8842); |
| 52 | PollService service = new PollService(factory, 1); |
| 53 | service.start(); |
| 54 | |
| 55 | Random random = new Random(); |
| 56 | while (true) { |
| 57 | SolutionMessage msg = service.getSolution(); |
| 58 | double quality = 0; |
66 | | Random random = new Random(); |
67 | | while (true) { |
68 | | SolutionMessage msg = service.getSolution(); |
69 | | try { |
70 | | service.sendQuality(msg, random.nextDouble()); |
71 | | } catch (IOException e) { |
72 | | e.printStackTrace(); |
73 | | } |
| 60 | // replace the line below to quality the quality |
| 61 | quality = random.nextDouble(); |
| 62 | // for the simple purpose here it's just a random number |
| 63 | |
| 64 | try { |
| 65 | service.sendQuality(msg, quality); |
| 66 | } catch (IOException e) { |
| 67 | e.printStackTrace(); |
79 | | 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. |
80 | | |
81 | | {{{#!java |
82 | | public class RandomSocketPushEvaluator { |
83 | | private PushService service; |
84 | | |
85 | | public static void main(String[] args) { |
86 | | RandomSocketPushEvaluator main = new RandomSocketPushEvaluator(); |
87 | | main.run(); |
88 | | System.out.println("Service is running, terminate by pressing <Return> or <Enter>."); |
89 | | System.console().readLine(); // note: you may not always have a console |
90 | | main.terminate(); |
91 | | } |
92 | | |
93 | | private void run() { |
94 | | ServerSocketListenerFactory factory = new ServerSocketListenerFactory(8842); |
95 | | service = new PushService(factory, 1, new RandomEvaluator()); |
96 | | service.start(); |
97 | | } |
98 | | |
99 | | private void terminate() { |
100 | | service.stop(); |
101 | | } |
102 | | |
103 | | private class RandomEvaluator implements IEvaluationService { |
104 | | Random random; |
105 | | |
106 | | public RandomEvaluator() { |
107 | | random = new Random(); |
108 | | } |
109 | | |
110 | | @Override |
111 | | public double evaluate(SolutionMessage msg) { |
112 | | return random.nextDouble(); |
113 | | } |
114 | | |
115 | | } |
116 | | } |
117 | | }}} |
| 73 | This code shows a concrete example of how to use the !PollService and the ease of integrating this into an external java application. |
| 74 | |
| 75 | As of July 2012 you can also extend the quality message with own fields and transmit them back to HeuristicLab. If you provide a simple plugin with your own evaluator you may further process this information inside HeuristicLab, e.g. through an Analyzer that includes these in the results. The source code contains a simple plugin with an extended protocol buffer message that would add a repetition field to return the number of repetitions that have been performed. This is just for demo purposes, you can use add any number of extensions that you like. |