Difference between revisions of "Coding Optimizers for use in Rave"
(→Helper Functions) |
(→Helper Functions) |
||
Line 126: | Line 126: | ||
*'''ravenonlcon''' - Calculates the current values of all constraints (the constraints selected in the list on the Objective Tab, not side constraints) and returns their values in the standard Optimization Toolbox format (two vectors, c and ceq). Note that this function takes many inputs, whereas the Optimization Toolbox requires that constraint-calculating functions take only a single input (the current point, x). Consequently, before you can use this function with an optimization toolbox algorithm, it must be wrapped with an anonymous function that takes only the first input x. (See ravefmincon.m for an example, search for the variable name "anonnonlcon".) | *'''ravenonlcon''' - Calculates the current values of all constraints (the constraints selected in the list on the Objective Tab, not side constraints) and returns their values in the standard Optimization Toolbox format (two vectors, c and ceq). Note that this function takes many inputs, whereas the Optimization Toolbox requires that constraint-calculating functions take only a single input (the current point, x). Consequently, before you can use this function with an optimization toolbox algorithm, it must be wrapped with an anonymous function that takes only the first input x. (See ravefmincon.m for an example, search for the variable name "anonnonlcon".) | ||
+ | |||
+ | *'''raveinitializeoptimizeranimation''' - A short script that checks if the user requested to save the animation to a file. If so, this also sets up the file export part of the animation. (It does not do the actual animating.) Call this near the beginning of your raveKEYWORD.m file. | ||
+ | |||
+ | *'''ravefinishoptimizeranimation''' - A short script that checks if the user requested to save the animation to a file. If so, this finishes exporting the animation. Call this near the end of your raveKEYWORD.m file. |
Revision as of 16:50, 23 November 2012
Contents
Introduction
This page contains some guidelines for how to code optimizers for use in Rave. Like other Rave plugins, optimizers require you to follow certain code structures in a few places, but for the most part you can code the actual optimization part of it however you want.
Required Files
Just like workspace objects, each optimizer has a keyword that serves as its unique identifier in Rave. Keywords appear in the name of the folder that contains the files for your optimizer, and in the filenames themselves. There is no min/max length requirement for the keyword, and it can contain letters and numbers. Keywords are case sensitive, so if you use capitalization, be sure to use it everywhere.
In this example, the optimizer described has the keyword "KEYWORD".
All files related to this optimizer must be placed in a folder named KEYWORD, which in turn must be placed in one of the three subfolders in the rave\optimizers directory. The subfolders are rave\optimizers\single, rave\optimizers\multi, and rave\optimizers\ranking. Put single objective optimizers in the single directory, multiobjective optimizers in the multi directory, and ranking functions in the ranking directory. Ranking functions are any functions that act only on the data set already loaded in Rave without requiring new function calls to generate new data. (They might, for example, select some rows in the data set based on some definition of optimality.)
The choice of which directory you place your optimizer in determines where it appears in the Algorithm menu on the Optimize tab. Also, if you place it in the single directory, Rave will only allow one objective to be selected from the Objective list on the Optimize tab. If you place it in the multi or ranking directories, the user may be allowed to select multiple objectives from the Objective list, as defined by settings.maxobjectives (described below).
Once you've made your KEYWORD directory, you must put three required files in it, plus any other helper files that your optimizer uses. The three required files are:
- optimizerinfo.txt - A two line plain text file. (Note that the file name does not contain KEYWORD). The first line of this file is the name of your optimizer as you want it to appear in Rave. The second line is a short description of the optimizer that will appear in the infobar when this optimizer is selected from the Algorithm menu.
- optimizersettingsKEYWORD.m - This is a script that defines any user-specified parameters that your optimizer needs, and a few required parameters that Rave needs.
- raveKEYWORD.m - This is the main function that actually runs your optimizer
The required files are describe in more detail below.
optimizerinfo.txt
This is a simple two+ line plain text file. It doesnt contain any code, just plain english text. The first line contains the name of the optimizer as it will appear in the Algorithm menu on the Optimize Tab. Because the menu is only 200 pixels wide, try to keep this to around 40 characters or less. The second line of the file contains a slightly longer description. This should contain critical identifying information about the optimizer, not a description of how it works. If the optimizer requires any MATLAB toolboxes (or other files that must be downloaded etc) you should note it here. You might also want to put your name here.
In the remainder of this file (lines 3+), you can put any instructions or additional information about the optimizer. Future versions of Rave will offer a method for the user to view this information from the Optimize Tab.
optimizersettingsKEYWORD.m
This file defines the parameters that will appear in the Settings table on the Optimize Tab when this optimizer is selected from the Algorithm menu, and also defines values for few parameters Rave uses to control other aspects of the Optimize Tab when this algorithm is selected from the Algorithms Menu. This file is just a list of lines (i.e. a MATLAB script, not a function) where each line defines one setting. The settings should be listed in the order that you wish them to appear in the Settings Table. The required Rave parameter settings do not appear in the Table, so you can put them wherever you want in this file. Because this is a MATLAB script, you can optionally include comments describing the settings.
The format for the required Rave parameters is:
settings.PARAMETERNAME=PARAMETERVALUE;
The required parameters must be included in this file. If these are missing, your Optimizer will not run. Each of these parameters controls only how the Optimize Tab user interface should act. It is up to you to actually code your optimizer to match whatever behavior you define using these parameters.
The required parameters are:
- settings.enforcesideconstraints = 0 or 1 or 2 This parameter identifies whether the optimizer will enforce the upper/lower bounds on each independent variable defined by handles.maxlimit and handles.minlimit. If = 0, the bounds will not be enforced. If = 1, the bounds will be enforced. If = 2, the optimizer supports both approaches and the user can specify whether or not to enforce them by checking the "Enforce side constraints" box on the optimize tab.
- The value you specify here only controls the appearance of the "Enforce side constraints" check box on the Optimize Tab. It is up to you to code the actual enforcing (or ignoring) of the side constraints in the raveKEYWORD.m file.
- Note: If you set this value = 2 in this file, then when the user runs this optimizer its settings structure will have settings.enforcesideconstraints = 0 or 1 depending on whether the user checked the box or not. Thus you use this same parameter within the raveKEYWORD.m file to determine whether to enforce the side constraints for each run.
- settings.allowconstraints = 0 or 1 This parameter identifies whether your optimizer supports general constraints that the user may define on the constrain tab and select for enforcement on the Optimize Tab. If = 0, constraints are not supported and the constraint menu on the Optimize Tab will be made inactive. If = 1, constraints are supported and the user can select them on the list in the Optimize tab.
- The value you specify here only controls the appearance of the Constraint Menu on the Optimize Tab. It is up to you to code the actual enforcing of constraints in your raveKEYWORD.m file.
- settings.numberofobjectives = a two-element vector of a positive integers or inf This paramter controls the maximum number of objectives the user is allowed to select from the Objective Menu on the Optimize Tab. This parameter is only used by multi and ranking optimizers (i.e. optimizers located in the multi or ranking subdirectories of rave\optimizers). The first element of this vector defines the minimum allowable number of objectives, and the second element defines the maximum. For example, if this = [1 inf], then the optimizer supports any number of objectives. If this = [2 4], then the optimizer only supports two, three, or four objectives. If this = [2 2] then the optimizer requires exactly two objectives. If the user selects a number of objectives from the Objective Menu outside of this range, they will see an error dialog box when the try to run the optimizer telling them that they have selected too few or too many objectives, and the optimizer will not run.
- The value you specify here only controls the limits that rave enforces before your optimizer begins running. It is up to you to actually code support for whatever number of objectives you specify here in your raveKEYWORD.m file.
- settings.isstoppable = 0 or 1 This parameter identifies whether or not Rave should display a stop button when the optimizer is running. If = 1, a stop button will be shown. If = 0, no stop button will be shown.
- The value you specify here only controls whether or not the stop button appears. It is up to you to code your optimizer to actually stop when the stop button is pressed.
In addition to these required parameters, you can include user-specified parameters that will appear in the Settings Table.
The format for user-specified parameters is:
settings.PARAMETERNAME = {'FORMATTEDNAME';'INITIALVALUE'};
Here, PARAMETERNAME is the variable name that you will use to refer to this parameter in the raveKEYWORD.m file. This is not displayed in Rave, but you will use it in your code. FORMATTEDNAME is the name as it will appear to the user. This must be a string and may contains spaces or any other formatting you like. INITIALVALUE is the initial value that will appear as the default value in the settings table. This may be either a string or a scalar number. If you enter a string here, and the user changes it in the table, whatever they enter in the table will also be treated as a string. If you enter a number here, and the user changes it in the table, whatever they enter will be converted to a number. Because all numbers can be converted to strings, but not all strings can be converted to numbers, any parameter that can take string or numerical values should be listed in this file as a string.
It is recommended that you make the PARAMETERNAME similar to the FORMATTEDNAME to make your code more readable.
Here are some examples:
settings.pop={'Population',100};
This line defines a variable named settings.pop with the initial value of 100. This will appear in the Settings Table with the label Population. Because 100 is entered as a number (ie it is not in quote), the user can only change this value to another number. If they enter, for example, "hello" in this box, it will be converted to NaN before the optimizer is run.
settings.maxtime={'Time Limit','60'};
This line defines a variable named settings.maxtime with the initial value of '60'. Because '60' is a string, the user will be allowed to enter anything in this box, and Rave will just set settings.maxtime equal to exactly the string that the enter. Then in your raveKEYWORD.m file you can parse this string and determine whether to convert it to a number etc.
Parameters Defined by the Objective Tab
The settings that the user specifies on the Objective Tab are also stored in the settings structure. You don't need to include these in your optimizersettingsKEYWORD.m file (in fact, you definitely should not include these; see the section below on reusing parameter names.)
You will use these settings in your raveKEYWORD.m file to control the optimizer, so it's important that you know what they are called and how their values are interpreted. These parameters are:
- settings.src = handles.fig. You use this as an input to guidata to load/save the handles structure
- settings.method = KEYWORD. Rave stores KEYWORD here as a record of what algorithm is being run. You can refer to this in helper functions to check what algorithm is running. For example, you might create an animation function that works for multiple optimizers, so you can check this value to customize its behavior depending on what optimizer is being run. (See e.g. raveanimatemultiobj.m for an example).
- settings.d = the index of the dataset being optimized
- settings.a = the index of the analysis being used to define independent variable ranges and any other Analysis Properties that may be needed.
- settings.x = the index (or indicies) of the objectives that are selected in the objective menu. These are the columns of the dataset that are being optimized.
- settings.funvars = the indices of the independent variables that are inputs to the functions that calculate settings.x. These are used as the independent variables in the optimization.
- settings.plotprogress = 1 if the "Animate Progress" box is checked, and =0 if it is unchecked. This value is just to let you know whether or not the user requested animation. It is still up to you to code the animation itself!
- settings.plotaxes = the handle of the graph (or graphs) on which the animation will be drawn. These are elements of handles.allgraphs.
- settings.plottype = a cell array of axes formats for the graphs in settings.plotaxes. These are the values stored in handles.graphinfo.(graphtype).axesformat. (i.e. 'single','3D','matrix', etc)
- settings.plotvars = a list of variables that must be evaluated in order to animzate the progress. THese are generally the variables that are displayed on the axes of settings.plotaxes
- settings.plotinputs = a list of the independent variables that are inputs to the functions in settings.plotvars.
- settings.animation = 0 or 1 indicating whether or not to save the animation to a file.
- settings.targets = handles.targetvalues{d}(x); The target values of the objectives (usually inf or -inf).
- settings.activeconstraints = an index into the Constraint Menu on the Optimize Tab indicating which constraints are selected to be enforced. A 0 in this list indicates the blank space at the top of the constraint menu. (You should do a setdiff to remove 0 from this array before you use its value).
- settings.startbutton - the handle of the start button on the Objective Tab. You can use this if you need to enable/disable the button in response to some condition/event.
- settings.stopbuttonpos - the position to display the stop button. Currently this is directly on top of the Start button.
- settings.updatexdials - Currently = true by default; in the future this will control an aspect of how optimizers are animated.
Reusing Paramter Names
Every parameter must have a unique name, so you cannot reuse the names of any of the standard parameters listed above. To construct the settings structure, Rave first loads these standard paramters and their values and then appends whatever is contained in your optimizersettingsKEYWORD.m file. Thus any parameters listed in your optimizersettingsKEYWORD.m will overwrite the standard parameters if their names match. You almost certainly want to avoid this, but if you wanted to somehow override Rave's default behaviors, this would be one way to do it.
The creation of the settings structure happens in the function "create_settings" in optimizetab.m.
raveKEYWORD.m
Required Function Parts
At the end of the file, your function must send certain data back to Rave. At a minimum, you must include two lines:
handles.optimizerresults(end+1).settings=settings;
This line saves the settings structure from this optimizer run. You can include this line at any point in your function, just make sure you put it after any changes to the settings structure that are made while the optimizer runs
handles.optimizerresults(end+1).results=X;
Here, X is whatever data you want your optimizer to return as its "answer." X must be an array with the same number of columns as settings.x where the value in each column is the value of the corresponding independent variable as indexed by settings.x. If the optimizer only returns a single optimal designs, X will have one row. If your optimizer returns multiple designs, X will have multiple rows. You should sort the rows of X in the order that you desired them to appear in Rave (if it matters).
You don't need to save the corresponding values of the objective functions; Rave will do that automatically.
You may also include any other relevant outputs from your optimizer as additional fields below handles.optimizerresults(end+1). Rave will not use these directly, but it will save them and export them so that you can refer to them in other programs. For example, suppose your optimizer also generates a matrix called A that you want to save. You can do this by adding the line:
handles.optimizerresults(end+1).myMatrix=A;
Helper Functions
Rave comes with some helper functions to perform common tasks related to optimization. You can call these functions from any optimizers you write so that you don't need to recreate their capabilities. Because these functions are used by many optimizers, you should NEVER alter their behavior or input/output structure/format or you will almost certainly break other optimizers. If you need to make a small tweak to their behavior, just make a copy of the file, give it a new function name, and edit that.
Unlike most rave functions, these actually have help sections at the top of their source code, so their use is not explained in detail here. If one of these sounds useful to you, view its source code to see exactly how it works.
- ravemakeminimizefunction - Makes a new .m file that contains a function in the standard MATLAB objective function format (i.e. the format required for objective functions by the Optimizer Toolbox). The function is formatted/transformed so that the goal is to minimize this function. For example, if the user specified an objective to be maximized, it will be multiplied by -1 so that now it should be minimized. The function created will also be normalized so that each independent variable ranges from 0-1. This helps some optimizers perform better, especially when the true ranges of the independent variables have different orders of magnitude.
- ravenonlcon - Calculates the current values of all constraints (the constraints selected in the list on the Objective Tab, not side constraints) and returns their values in the standard Optimization Toolbox format (two vectors, c and ceq). Note that this function takes many inputs, whereas the Optimization Toolbox requires that constraint-calculating functions take only a single input (the current point, x). Consequently, before you can use this function with an optimization toolbox algorithm, it must be wrapped with an anonymous function that takes only the first input x. (See ravefmincon.m for an example, search for the variable name "anonnonlcon".)
- raveinitializeoptimizeranimation - A short script that checks if the user requested to save the animation to a file. If so, this also sets up the file export part of the animation. (It does not do the actual animating.) Call this near the beginning of your raveKEYWORD.m file.
- ravefinishoptimizeranimation - A short script that checks if the user requested to save the animation to a file. If so, this finishes exporting the animation. Call this near the end of your raveKEYWORD.m file.