= Quick guide: Integrate HeuristicLab into an application = This HowTo will show you how you can write a console application that reads in a file with an user-defined algorithm, parameterizes the algorithm and the problem and then executes the algorithm and displays the results. This is useful if you want to write an application that you can start from another program or you can use the code in your own .NET application if you need the functionality that HeuristicLab offers. Attached to this page you can find a zip file containing the sample HeuristicLab file, the needed assemblies as well as a Visual Studio project with the source code. We will start out by creating a new C# console application in Visual Studio. Because we want to read in a user-defined algorithm based on a Genetic Algorithm containing a Traveling Salesman Problem, we first need to reference the following assemblies: [[Image(assemblies.png)]] We will now write all the code for loading and executing the algorithm in the Program.cs generated by Visual Studio. The following snippet shows the Main method of the program: {{{#!csharp static void Main(string[] args) { string samplePath = @"..\..\User-defined-algorithm.hl"; ContentManager.Initialize(new PersistenceContentManager()); ContentManager.LoadAsync(samplePath, LoadingCompleted); Console.ReadLine(); } }}} In the first line the path to the HeuristicLab file containing the algorithm and the problem is specified. In the next step the Content and Persistence Manager is initialized so that HeuristicLab files can be loaded in the next step. We use the ContentManager to load the file and on completion, the LoadingCompleted method is called: {{{#!csharp private static void LoadingCompleted(IStorableContent content, Exception error) { if (error != null) throw error; Console.WriteLine("Loading completed!"); Console.WriteLine("Content loaded: " + content.ToString()); if (content is UserDefinedAlgorithm) { UserDefinedAlgorithm algorithm = content as UserDefinedAlgorithm; TravelingSalesmanProblem problem = algorithm.Problem as TravelingSalesmanProblem; if (problem == null) { Console.WriteLine("Unsupported problem type detected!"); return; } ParameterizeProblem(problem); ParameterizeAlgorithm(algorithm); RegisterAlgorithmEventHandlers(algorithm); algorithm.Start(); // Since HeuristicLab 3.3.15 Start() is blocking Console.WriteLine("Run is finished! Results are: "); foreach (var s in algorithm.Results) { Console.WriteLine(s.Name + ": " + s.Value); } DeregisterAlgorithmEventHandlers(algorithm); } else { Console.WriteLine("Unknown content in file: " + content.ToString()); } } }}} The LoadingCompleted method gets an object of type IStorableContent. This is the object which the ContentManager loaded from the HeuristicLab file. In this simple example we only support user-defined algorithms and the TSP. Therefore we cast the content to a user-defined algorithm and the problem to the TSP. In the next step we can then set the parameters of the problem and the algorithm. After parameterizing the algorithm we have to register event handlers for the algorithm so that we receive status updates during execution. The Parameterize* methods set parameters of the algorithm and the problem: {{{#!csharp private static void ParameterizeAlgorithm(UserDefinedAlgorithm algorithm) { //set all parameters of the algorithm, e.g. ((IntValue)algorithm.Parameters["MaximumGenerations"].ActualValue).Value = 5000; } private static void ParameterizeProblem(TravelingSalesmanProblem problem) { //set all parameters of the problem, e.g. problem.Maximization.Value = false; } }}} Algorithm parameters can be accessed through the parameters collection. In the code above the maximum generations is set from 1000 generations to 5000 generations. The problem offers some properties that can be changed. For example it is shown how to configure the problem to be a minimization or a maximization problem. Another example would be to set the problem data using the coordinates or distance matrix properties. RegisterAlgorithmEventHandlers registers some events so that the application is able to print the execution time and state changes of the algorithm during execution. {{{#!csharp private static void RegisterAlgorithmEventHandlers(EngineAlgorithm alg) { alg.ExecutionStateChanged += new EventHandler(alg_ExecutionStateChanged); alg.ExecutionTimeChanged += new EventHandler(alg_ExecutionTimeChanged); } private static void DeregisterAlgorithmEventHandlers(EngineAlgorithm alg) { alg.ExecutionStateChanged -= new EventHandler(alg_ExecutionStateChanged); alg.ExecutionTimeChanged -= new EventHandler(alg_ExecutionTimeChanged); } }}} Note that, before HeuristicLab 3.3.15 you had to additionally register the Stopped event to display the results as the Start() method was non-blocking. {{{#!csharp static void alg_ExecutionTimeChanged(object sender, EventArgs e) { EngineAlgorithm alg = sender as EngineAlgorithm; Console.WriteLine("Execution time changed: " + alg.ExecutionTime); } static void alg_ExecutionStateChanged(object sender, EventArgs e) { EngineAlgorithm alg = sender as EngineAlgorithm; Console.WriteLine("Execution state changed: " + alg.ExecutionState); } }}} And that's all! You have now created a HeuristicLab console client for a specific algorithm and problem. If you want to use different algorithms and problems, you have to reference the required assemblies and can then parameterize and execute these algorithms. == Creating an algorithm without loading it from a file == HeuristicLab algorithms and problems can of course also be used without loading them from a file. If you replace the above shown Main method with the following code, a Genetic Algorithm with standard parameterization and a traveling salesman problem with it's default problem instance is created and executed: {{{#!csharp GeneticAlgorithm ga = new GeneticAlgorithm(); SequentialEngine engine = new SequentialEngine(); TravelingSalesmanProblem problem = new TravelingSalesmanProblem(); ga.Engine = engine; ga.Problem = problem; RegisterAlgorithmEventHandlers(ga); ga.Start(); Console.ReadLine(); }}} Note that in HeuristicLab 3.3.14 and earlier the Start() method was non-blocking and you have to use a WaitHandle such as an [https://msdn.microsoft.com/en-us/library/system.threading.autoresetevent(v=vs.110).aspx AutoResetEvent] to avoid terminating the application prematurely.