14 | | == Preparing the Simulation Model == |
| 14 | == Preparing the Simulation Model in !AnyLogic 6 == |
| 15 | First save the model in a new location. Click "Save As..." in the File menu. For the sake of simplicity just put "Supply Chain" in the box that asks for a model name and leave everything else. That way it will save it in a folder called "Models" in your user's directory. |
| 16 | |
| 17 | Now download the [http://dev.heuristiclab.com/trac/hl/core/attachment/wiki/DevelopersOptimizingExternalApplications/HL3ExternalEvaluation.jar HL3 External Evaluation Java library] to a place that you remember (e.g. your Downloads directory; you should not download it into the model folder already). Then switch to !AnyLogic 6 again and click the model icon in the project view (should be called "Supply Chain" if you followed the model name suggestion above). In the properties window of this model in the section "Jar files and class folders required to build the model:" click the add button. Choose the file you just downloaded, make sure "Import to model folder is ticked" and click "Finish" to add the library. Save the model. |
| 18 | |
| 19 | Now we need to add a new experiment which we can run to serve as our evaluation function. The best type of experiment for this task is a "Parameters Variation" experiment, so choose this and choose a name for it, e.g. "!HeuristicLabOptimizationExperiment". Leave everything else as it is and click "Finish". Now we have created a new experiment with which we can optimize the parameters. |
| 20 | |
| 21 | In the "Properties" view of this experiment go to the "General" tab and choose "Freeform" instead of "Varied in range" and put a large number in the box asking for the "Number of runs", e.g.: 1,000,000,000. Then type in each field in the column "Expression" the same word as you see on the general property page of the //Simulation// experiment. So instead of the first number 20 you type //sLoRetailer//, then you replace the 80 with //SHiRetailer//, then the next 20 you replace with //sLoWholesaler//, then //SHiWholesaler//, then //sLoFactory//, and finally //SHiFactory//. Click save. |
| 22 | |
| 23 | Now in the upper right hand corner of this property page is a button called "Create default UI", click that now and you have some user interface elements added to this experiment. |
| 24 | |
| 25 | Next we need to go to the "Advanced" section of the properties and configure the experiment loop: perform the parameter retrieval, run the simulation, send the quality back, reset the model and continue with another attempt of retrieving parameters. |
| 26 | |
| 27 | In the "Imports:" section enter following code: |
| 28 | {{{ |
| 29 | #!java |
| 30 | import java.io.*; |
| 31 | import java.text.*; |
| 32 | import com.heuristiclab.problems.externalevaluation.*; |
| 33 | import com.heuristiclab.problems.externalevaluation.ExternalEvaluationMessages.*; |
| 34 | }}} |
| 35 | |
| 36 | In the "Additional class code:" section enter following code: |
| 37 | {{{ |
| 38 | #!java |
| 39 | int replications; |
| 40 | double quality; |
| 41 | com.heuristiclab.problems.externalevaluation.PollService commDriver; |
| 42 | SolutionMessage currentSolution = null; |
| 43 | |
| 44 | private void getMessage() { |
| 45 | currentSolution = commDriver.getSolution(); |
| 46 | if (currentSolution.getDoubleArrayVarsCount() > 0) { |
| 47 | SolutionMessage.IntegerArrayVariable vector = currentSolution.getIntegerArrayVars(0); |
| 48 | int i = 0; |
| 49 | for (Integer val : vector.getDataList()) { |
| 50 | if (i == 0) { |
| 51 | sLoRetailer = val.intValue(); |
| 52 | } else if (i == 1) { |
| 53 | SHiRetailer = val.intValue(); |
| 54 | } else if (i == 2) { |
| 55 | sLoWholesaler = val.intValue(); |
| 56 | } else if (i == 3) { |
| 57 | SHiWholesaler = val.intValue(); |
| 58 | } else if (i == 4) { |
| 59 | sLoFactory = val.intValue(); |
| 60 | } else if (i == 5) { |
| 61 | SHiFactory = val.intValue(); |
| 62 | } |
| 63 | i++; |
| 64 | } |
| 65 | } |
| 66 | } |
| 67 | }}} |
| 68 | |
| 69 | We have defined a method //getMessage()// that calls our library to get the next message from !HeuristicLab and extract the parameters. You'll notice that here I have put the same text as before in the box "Expression" which is an intentional coincidence ;-) |
| 70 | |
| 71 | Now in the section "Initial experiment setup" we need to initialize our communication driver. Paste the following code: |
| 72 | {{{ |
| 73 | #!java |
| 74 | commDriver = new com.heuristiclab.problems.externalevaluation.PollService(new ServerSocketListenerFactory(2112),1); |
| 75 | commDriver.start(); |
| 76 | }}} |
| 77 | |
| 78 | The number '''2112''' is important as it is the TCP port that our service will be listening on. This must be reachable by !HeuristicLab through a network connection (yes this means you can run !HeuristicLab on a different computer than your simulation model). You can of course choose another port (basically any number from 1 to 65535, but some numbers like 80 might be used by another application already). |
| 79 | |
| 80 | In the next section "Before each experiment run" we need to initialize our variables that store the quality and replications and we need to fetch the new parameters. Past the following code: |
| 81 | {{{ |
| 82 | #!java |
| 83 | quality = 0; |
| 84 | replications = 0; |
| 85 | |
| 86 | getMessage(); |
| 87 | }}} |
| 88 | |
| 89 | The call to //getMessage()// will block, that means the simulation will wait here, until we have received a new set of parameters. |
| 90 | |
| 91 | We can leave the next section "Before simulation run" empty, but in the section after that, called "After simulation run" we need to paste following code: |
| 92 | {{{ |
| 93 | #!java |
| 94 | double penalty = 10000 * (1 + root.histWaitingTime.max()); |
| 95 | if (root.histWaitingTime.max() < 0.01) quality += root.meanDailyCost(); |
| 96 | else quality += root.meanDailyCost() + penalty; |
| 97 | replications++; |
| 98 | }}} |
| 99 | |
| 100 | This calls the cost function in the `Main` object called //meanDailyCost()// in this case. This is the target that we want to optimize (note that we add an increasing penalty term if the customer waiting time is above a certain level). |
| 101 | |
| 102 | Finally in the section "After iteration" we calculate the mean cost among all iterations performed and send that back to !HeuristicLab: |
| 103 | {{{ |
| 104 | #!java |
| 105 | try { |
| 106 | commDriver.sendQuality(currentSolution, quality / replications); |
| 107 | } catch (IOException e) { } |
| 108 | }}} |
| 109 | |
| 110 | We are done here. Save the model. You can now start the !HeuristicLabOptimizationExperiement, although of course it won't do anything but block until it receives parameters. |
| 111 | |
| 112 | == Preparing the Optimization Problem in !HeuristicLab 3.3 == |