www.gusucode.com > mbcdata 工具箱 matlab 源码程序 > mbcdata/@cgoptim/optimwizard.m
function [objout, OK] = optimwizard(objin, pPROJ, hParent) %OPTIMWIZARD Wizard for creating a new optimization object % % [NEWOPT, OK] = OPTIMWIZARD(OPT, pPROJ, [hParent]) where OPT is a % cgoptim object, pPROJ is a pointer to a cage project and hParent is an % optional handle to a parent figure. % % See also XREGWIZARD. % Copyright 2000-2015 The MathWorks, Inc. and Ford Global Technologies, Inc. if nargin<3 hParent = []; end [OK, out] = xregwizard(hParent, 'Optimization Wizard', {@i_createCardOne, pPROJ}); if OK objout = out.optim; else objout = objin; end %------------------------------------------------------------------------ % CARD ONE FUNCTIONS BELOW %------------------------------------------------------------------------ function [layout, localData] = i_createCardOne( pPROJ, fh, iFace, localData ) % GUI Layout for card one: Select an algorithm if isa(fh, 'xregcontainer') layout = fh; layoutUD = get(layout, 'UserData'); else % Set the wizard size to be more appropriate feval(iFace.setWizardSize, [600 300]); builtin = initfrommbc(cgoptimfuncs); userfuncs = cgoptimfuncs; optimlist = [makeoptim(builtin), makeoptim(userfuncs)]; optimdata = struct( 'list', {optimlist}, 'index', -1 ); layoutUD.optimdata = xregGui.RunTimePointer( optimdata ); layoutUD.optimdata.LinkToObject(fh); listtitle = uicontrol('Parent', fh, ... 'Visible', 'off', ... 'Style', 'text', ... 'String', 'Available optimization algorithms:', ... 'Enable', 'inactive', ... 'HorizontalAlignment', 'left'); % Draw the ListView control listbox = mbcwidgets.List( 'Parent', fh,... 'Editable', false, ... 'Visible','off',... 'Grid',false,... 'SelectionChangedCallback',{@cbkSelectInput,iFace},... 'SelectionMode', 'SingleRow'); listbox.Peer.setColumnData({'Name','Free Variables','Objectives','Constraints','Operating Point Sets'}); listbox.Peer.setColumnWidths([120 85 80 80 115]); Data = cell(length(optimlist),5); for n = 1:length(optimlist) opts = getSetup(optimlist{n}); Data{n,1}= getName(opts); desc = getModeDescriptions(opts); Data(n,2:end) = desc; end listbox.Peer.setData(Data); listbox.selectRows(1); layoutUD.listbox = listbox; layoutUD.nextFcn = @i_cardOneNext; layoutUD.cancelFcn = @i_cardCancel; layout = xreggridbaglayout(fh, ... 'packstatus', 'off', ... 'dimension', [2 1], ... 'rowsizes', [15 -1], ... 'gapy', 5, ... 'elements', {listtitle, listbox}, ... 'border', [7 0 7 10]); infostr = 'Select from the list the algorithm that you want the new optimization to use.'; layout = i_maketitlearea(fh, 'Algorithm Selection', infostr, layout); globalUD.Project = pPROJ; feval( iFace.setUserData, globalUD ); end feval( iFace.setFinishButton, 'off' ); feval( iFace.setNextButton, 'on' ); set( layout, 'UserData', layoutUD ); %------------------------------------------------------------------------ function [nextCardID, localData] = i_cardOneNext( layoutUD, iFace ) optimdata = layoutUD.optimdata; % Get the selected item from the listview index = layoutUD.listbox.getSelectedRows; % set the index of the chosen optimization object in the user data for Card One optimdata.info.index = index; feval( iFace.setCardUserdata, layoutUD ); % Set the localData localData = optimdata; % Check to see if we need to go to card two obj = optimdata.info.list{index}; opts = getSetup(obj); if canAddVariable(opts) || canRemoveVariable(opts) ... || canAddObjective(opts) || canRemoveObjective(opts) ... || canAddConstraint(opts) || canRemoveConstraint(opts) ... || canAddOperatingPointSet(opts) || canRemoveOperatingPointSet(opts) nextCardID = @i_createCardTwo; else % we can skip card two nextCardID = @i_createCardThree; end %------------------------------------------------------------------------ % CARD TWO FUNCTIONS BELOW %------------------------------------------------------------------------ function layout = i_createCardTwo( fh, iFace, localData ) % GUI Layout for card two: Number of free variables, objectives, constraints % and OpPoint sets % Have we been called to create the layout or simply update? if isa( fh, 'xregcontainer' ) layout = fh; layoutUD = get( layout, 'UserData' ); else optseditor = cgoptimgui.optionsEditor('Parent', fh, ... 'Visible', 'off'); layout = xreggridbaglayout(fh,... 'dimension', [3 1],... 'rowsizes',[-1 110 -1],... 'rowratios', [1 0 2], ... 'border', [30 0 0 0],.... 'elements', {[], optseditor}); infostr = ['Algorithms may be able to use a variable number of items.', ... ' Select the number of each item that you want to use in this optimization.']; layout = i_maketitlearea(fh, 'Algorithm Options', infostr, layout); layoutUD.optseditor = optseditor; layoutUD.nextFcn = @i_cardTwoNext; layoutUD.cancelFcn = @i_cardCancel; end if nargin > 2, layoutUD.optimdata = localData; end layoutUD = i_cardTwoUpdate( layoutUD, iFace ); set( layout, 'UserData', layoutUD ); %------------------------------------------------------------------------ function layoutUD = i_cardTwoUpdate( layoutUD, iFace ) % Fills card two with information % Get the chosen optimization object obj = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; layoutUD.optseditor.OptionsObject = getSetup(obj); % Always have to go to card three feval( iFace.setFinishButton, 'Off' ); feval( iFace.setNextButton, 'On'); %------------------------------------------------------------------------ function [nextCardID, localData] = i_cardTwoNext( layoutUD, ~ ) obj = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; obj = setSetup(obj, layoutUD.optseditor.OptionsObject); layoutUD.optimdata.info.list{layoutUD.optimdata.info.index} = obj; % set up the local data localData = layoutUD.optimdata; % Card three should always be visited nextCardID = @i_createCardThree; %------------------------------------------------------------------------ % CARD THREE FUNCTIONS BELOW %------------------------------------------------------------------------ function layout = i_createCardThree(fh, iFace, localData) % GUI Layout for card three: Assign Variables % Have we been called to create the layout or simply update? if isa(fh, 'xregcontainer') layout = fh; layoutUD = get(layout, 'UserData'); else % Draw the ListView control layoutUD.List = mbcwidgets.List('Parent', fh,... 'Editable', false, ... 'Visible','off',... 'Grid',false,... 'SelectionChangedCallback',{@i_VarListCbk, iFace},... 'SelectionMode', 'SingleRow'); layoutUD.List.Peer.setColumnData({'Label','CAGE Variable'}); layoutUD.List.Peer.setColumnWidths([140 100]); % Make a title for this ListView t = uicontrol('Parent',fh,... 'Style','text',... 'Visible','off',... 'HorizontalAlignment','left',... 'String','Optimization inputs:'); t2 = uicontrol('Parent',fh,... 'Style','text',... 'Visible','off',... 'HorizontalAlignment','left',... 'String','CAGE variables:'); layoutUD.selbutton = xregGui.iconuicontrol('parent',fh,... 'imageFile', xregrespath('leftarrow.bmp'),... 'transparentColor', [255 255 0],... 'ToolTip','Select CAGE Variable',... 'visible','off',... 'callback',{@i_select,iFace}); layoutUD.namelist = cgtools.exprList('Parent', fh, ... 'visible', 'off', ... 'DisplayTypeColumn', false, ... 'DisplayHeaderRow', false); layout = xreggridbaglayout(fh, ... 'dimension', [5 3], ... 'gapx', 10, ... 'border', [7 0 7 10], ... 'rowsizes', [15 2 -1 80 -1], ... 'colsizes', [-1 80 -1], ... 'colratios', [2 0 1], ... 'mergeblock', {[3 5], [1 1]}, ... 'mergeblock', {[3 5], [3 3]}, ... 'elements', {t, [], layoutUD.List, [],[], ... [],[],[], layoutUD.selbutton, [], ... t2, [], layoutUD.namelist, [], []}); infostr = ['Match each required variable in the optimization to a ' ... 'variable from the Variable Dictionary.']; layout = i_maketitlearea(fh, 'Required Variables', infostr, layout); layoutUD.cancelFcn = @i_cardCancel; end if nargin > 2 layoutUD.optimdata = localData; end layoutUD = i_cardThreeUpdate(layoutUD, iFace); set(layout, 'UserData', layoutUD); %------------------------------------------------------------------------ function layoutUD = i_cardThreeUpdate(layoutUD, iFace) % fills the card with information optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; opts = getSetup(optim); % List of available variables globalUD = feval(iFace.getUserData); pDD = globalUD.Project.getdd; cgvarptrs = pDD.listptrs('variable'); layoutUD.namelist.Items = cgvarptrs; % List of optimization variable labels to match % Free variables and dataset required variables strVal = [getFreeVariables(opts), getOperatingPointSetVarLabels(opts)]; pVal = get(optim, 'oppointvalues'); pVal = [get(optim, 'values'), pVal{:}]; Data= cell(length(strVal),2); for n = 1:length(strVal) Data{n,1}=strVal{n}; if ~isnull(pVal(n)) % variable already matched Data{n,2}= pVal(n).getname; end end layoutUD.List.Peer.setData(Data); layoutUD.List.selectRows(1); i_VarListCbk([], [], iFace, layoutUD); layoutUD.nextFcn = @i_cardThreeNext; layoutUD.finishFcn = @i_cardSixFinish; % -------------------------------------------------- function i_VarListCbk(~, ~, iFace, layoutUD) if nargin<4 layoutUD = feval(iFace.getCardUserdata); end optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; selected = layoutUD.List.getSelectedRows; if ~isempty(selected) TableData = layoutUD.List.getData; selected = TableData{selected,1}; pVar = getItem(optim, selected, {'variable', 'operatingpointsetvariable'}); set(layoutUD.namelist, 'SelectedItems', pVar); if isempty(layoutUD.namelist.Items) % disable the select button when there are no variables to select set(layoutUD.selbutton,'Enable', 'off'); else set(layoutUD.selbutton,'Enable', 'on'); end else set(layoutUD.selbutton,'Enable', 'off'); end i_CardThreeEnableNextFinish( layoutUD, iFace ) %------------------------------------------------------------------------ function i_CardThreeEnableNextFinish( layoutUD, iFace ) % Enable/disable the 'Next' and 'Finish' buttons for card three optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; opts = getSetup(optim); pVal = get(optim, 'oppointvalues'); pVal = [get(optim, 'values'), pVal{:}]; canLeaveCard = ~any(isnull(pVal)); hasNextCard = numObjectives(opts)>0 ... || numConstraints(opts)>0 ... || numOperatingPointSets(opts)>0; if canLeaveCard feval(iFace.setFinishButton, 'on'); if hasNextCard feval(iFace.setNextButton, 'on'); else feval(iFace.setNextButton, 'off'); end else feval(iFace.setFinishButton, 'off'); feval(iFace.setNextButton, 'off'); end %------------------------------------------------------------------------ function i_select(~, ~, iFace) layoutUD = feval(iFace.getCardUserdata); % get handles TargetItem = layoutUD.List.getSelectedRows; pSelVal = layoutUD.namelist.SelectedItems; if isempty(pSelVal) return end layoutUD.List.Peer.setDataAt(pSelVal.getname,TargetItem-1,1) optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; TargetList = layoutUD.List.getData; Target = TargetList{TargetItem,1}; optim = setItem(optim, Target, pSelVal, {'variable', 'operatingpointsetvariable'}); layoutUD.optimdata.info.list{layoutUD.optimdata.info.index} = optim; % Get the current label items selection and increment to the next one N = layoutUD.List.getRowCount; newInd = mod(TargetItem,double(N))+1; layoutUD.List.selectRows(newInd); i_VarListCbk([], [], iFace, layoutUD); feval(iFace.setCardUserdata, layoutUD); %------------------------------------------------------------------------ function [nextCardID, localData] = i_cardThreeNext(layoutUD, ~) % set up the local data localData = layoutUD.optimdata; % Which card is next? optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; opts = getSetup(optim); if numObjectives(opts)>0 % number of obj funs >= 1 ==> must vist card four nextCardID = @i_createCardFour; elseif numConstraints(opts)>0 % number of constraint >= 1 ==> must vist card five nextCardID = @i_createCardFive; elseif numOperatingPointSets(opts)>0 % number of oppoint sets >= 1 ==> must vist card six nextCardID = @i_createCardSix; else % We really shouldn't end up here. If we are here it is because the 'Next' % button hasn't been disabled. To exit smoothly, we'll just goto card six. warning(message('mbc:cgoptim:InvalidState13')); nextCardID = @i_createCardSix; end %------------------------------------------------------------------------ % CARD FOUR FUNCTIONS BELOW %------------------------------------------------------------------------ function layout = i_createCardFour(fh, iFace, localData) % GUI Layout for card four: Assign objectives % Have we been called to create the layout or simply update? if isa(fh, 'xregcontainer') layout = fh; layoutUD = get(layout, 'UserData'); else % Draw the ListView control layoutUD.List = mbcwidgets.List('Parent', fh,... 'Editable', false, ... 'Grid',false,... 'Visible','off',... 'SelectionChangedCallback',{@i_ObjListCbk, iFace},... 'SelectionMode', 'SingleRow'); layoutUD.List.Peer.setColumnData({'Optimization Model','CAGE Model', 'Type'}); layoutUD.List.Peer.setColumnWidths([120 90 110]); % Make a title for this ListView t= uicontrol('Parent',fh,... 'Style','text',... 'Visible','off',... 'HorizontalAlignment','left',... 'String','Optimization objectives:'); layoutUD.selbutton= xregGui.iconuicontrol('parent',fh,... 'imageFile',xregrespath('\leftarrow.bmp'),... 'transparentColor', [255 255 0],... 'ToolTip','Select CAGE Model',... 'visible','off',... 'callback',{@i_selectObj,iFace}); t2= uicontrol('Parent',fh,... 'Style','text',... 'Visible','off',... 'HorizontalAlignment','left',... 'String','CAGE models:'); layoutUD.namelist = cgtools.exprList('Parent', fh, ... 'visible', 'off', ... 'DisplayTypeColumn', false, ... 'DisplayHeaderRow', false); layoutUD.radiobutton= xregGui.rbgroup('parent',fh,... 'nx', 3, 'ny', 1, ... 'visible','off',... 'string',{'Minimize', 'Maximize', 'Helper'},... 'callback',{@i_radio,iFace}); rbs = xregGui.labelcontrol('parent', fh, ... 'Control', layoutUD.radiobutton, ... 'string', 'Objective type:', ... 'visible', 'off', ... 'graydisable', 'off', ... 'labelsizemode', 'absolute', ... 'labelsize', 80, ... 'controlsizemode', 'relative', ... 'controlsize', 1,... 'BaselineOffsetMode', 'manual'); layout = xreggridbaglayout(fh, ... 'dimension', [7 3], ... 'gapx', 10, ... 'border', [7 0 7 10], ... 'rowsizes', [15 2 -1 80 -1 5 20], ... 'colsizes', [-1 80 -1], ... 'colratios', [2 0 1], ... 'mergeblock', {[3 5], [1 1]}, ... 'mergeblock', {[3 5], [3 3]}, ... 'elements', {t, [], layoutUD.List, [], [], [], rbs, ... [], [], [], layoutUD.selbutton, [], [], [], ... t2, [], layoutUD.namelist}); infostr = ['Objectives are quantities that the algorithm will attempt to optimize.', ... ' Select CAGE models to be used for each objective, and whether it', ... ' should be minimized, maximized or used as a helper model for the algorithm.']; layout = i_maketitlearea(fh, 'Objectives', infostr, layout); end if nargin > 2, layoutUD.optimdata = localData; end layoutUD = i_cardFourUpdate(layoutUD, iFace); set(layout, 'UserData', layoutUD); %------------------------------------------------------------------------ function layoutUD = i_cardFourUpdate(layoutUD, iFace) % fills the card with information optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; % Fill the left-hand list box OFLabels= get(optim, 'ObjectiveFuncLabels'); OFs = getObjectiveFunc(optim); Data = cell(length(OFLabels),3); for i = 1: length(OFLabels) Data{i,1} = OFLabels{i}; if isa(OFs{i}, 'cgpointobjective') || isa(OFs{i}, 'cgsumobjective') modptr = getExpression(OFs{i}); if ~isempty(modptr) && isvalid(modptr) Data{i,2} = modptr.getname; end end % Handle case where user has added an objective function. These % functions will not be given a type by default. Data{i,3} = getObjectiveType(OFs{i}); end layoutUD.List.Peer.setData(Data); layoutUD.List.selectRows(1); % Select the first item i_ObjListCbk([], [], iFace, layoutUD); layoutUD.finishFcn = @i_cardSixFinish; layoutUD.nextFcn = @i_cardFourNext; % Can always exit from this card. The user can do the wiring in the optim % node feval(iFace.setFinishButton, 'on'); nextOK = i_checkPtrsObjs(layoutUD); if nextOK feval(iFace.setNextButton, 'on'); else feval(iFace.setNextButton, 'off'); end % -------------------------------------------------- function i_SetObjectiveRBState(hRB, OF) if ~isempty(OF) minstr = getObjectiveType(OF); radiosel = find( strncmp( minstr,{ 'Minimize', 'Maximize', 'Helper' },length(minstr) ) ); if isempty(radiosel) radiosel = 1; end if ~canChangeType(OF); % enable just the chosen radio button enableArray = false(1, 3); enableArray(radiosel) = true; else % enable min/max enableArray = [true true false]; end set(hRB, ... 'selected', radiosel, ... 'enableArray', enableArray); else % No item: disable the radio buttons set( layoutUD.radiobutton, 'EnableArray', false( 1, 3 ) ); end % -------------------------------------------------- function modelptrs = i_FilterCAGEmodels(optim, objtype, pPROJ) modelptrs = pPROJ.getmodels; if any(strcmpi(objtype, {'Maximize', 'Minimize'})) % Only show models that have a free variable feeding into them pFree = get(optim, 'values'); pInpForAll = pveceval(modelptrs, @getinports); KeepIdx = false(size(modelptrs)); for n = 1:length(modelptrs) KeepIdx(n) = anymember(pFree, pInpForAll{n}); end modelptrs = modelptrs(KeepIdx); end % -------------------------------------------------- function i_ObjListCbk(~, ~, iFace, layoutUD) if nargin<4 layoutUD = feval(iFace.getCardUserdata); end optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; OFs = getObjectiveFunc(optim); selected = layoutUD.List.getSelectedRows; if ~isempty(selected) ThisOF = OFs{selected}; % Update radio buttons i_SetObjectiveRBState(layoutUD.radiobutton, ThisOF); % Refresh the right hand list, as models you can match depend on % whether the objective is min/max or helper globalUD = feval(iFace.getUserData); if isa(ThisOF, 'cgpointobjective') || isa(ThisOF, 'cgsumobjective') modelptrs = i_FilterCAGEmodels(optim, getObjectiveType(ThisOF), globalUD.Project); selmodel = getExpression(ThisOF); else modelptrs = mbcpointer(1,0); selmodel = mbcpointer; end set(layoutUD.namelist, 'Items', modelptrs, 'SelectedItems', selmodel); if isempty(modelptrs) % disable the select button when there are no models or objectives set(layoutUD.selbutton,'Enable', 'off'); else set(layoutUD.selbutton,'Enable', 'on'); end else i_SetObjectiveRBState(layoutUD.radiobutton, []); set(layoutUD.namelist, 'Items', []); set(layoutUD.selbutton,'Enable', 'off'); end % -------------------------------------------------- function i_selectObj(~, ~, iFace) % objective function selection layoutUD = feval(iFace.getCardUserdata); optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; % get handles target = layoutUD.List.getSelectedRows; curlst = layoutUD.namelist; % Model to use pNewModel = curlst.SelectedItems; if isempty(pNewModel) && ~isempty(curlst.Items) % Try to take first item in the list pNewModel = curlst.Items(1); end % Objective to change ObjLabel = layoutUD.List.getDataAt(target-1,0); if ~isempty(pNewModel) OF = getItem(optim,target,'objective'); if isa(OF, 'cgpointobjective') || isa(OF, 'cgsumobjective') OF = setExpression(OF, pNewModel); optim = setObjectiveFunc(optim, ObjLabel, OF); layoutUD.optimdata.info.list{layoutUD.optimdata.info.index} = optim; % Update the left list layoutUD.List.Peer.setDataAt(pNewModel.getname,target-1,1); end end % Update i_ObjListCbk(layoutUD.List, [], iFace); % -------------------------------------------------- function i_radio(radio, ~,iFace) layoutUD = feval(iFace.getCardUserdata); optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; % get handles selected = layoutUD.List.getSelectedRows; radiosel = get(radio, 'Selected'); switch radiosel case 1 minstr = 'min'; case 2 minstr = 'max'; case 3 minstr = 'helper'; end OF = getItem(optim,selected,'objective'); OF = setObjectiveType(OF, minstr); OFLabels= get(optim, 'ObjectiveFuncLabels'); optim = setObjectiveFunc(optim, OFLabels{selected}, OF); layoutUD.optimdata.info.list{layoutUD.optimdata.info.index} = optim; feval(iFace.setCardUserdata, layoutUD); layoutUD.List.Peer.setDataAt(getObjectiveType(OF),selected-1,2); %------------------------------------------------------------------------ function nextOK = i_checkPtrsObjs(layoutUD) % Check to see if there are any cons or oppts. If not, cannot go any % further nextOK = 1; optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; hasModelConstraints = i_optimHasModelConstraints(optim); if ~hasModelConstraints && isempty( get( optim, 'oppoints' ) ) nextOK = 0; end %------------------------------------------------------------------------ function [nextCardID, localData] = i_cardFourNext(layoutUD, ~) % set up the local data localData = layoutUD.optimdata; % Which card is next? obj = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; % Determine whether the constraints are model constraints (and so can be % edited in the wizard) or not hasModelConstraints = i_optimHasModelConstraints(obj); if hasModelConstraints % number of model constraints >= 1 ==> must vist card five nextCardID = @i_createCardFive; elseif ~isempty( get( obj, 'oppoints' ) ) % number of oppoint sets >= 1 ==> must vist card six nextCardID = @i_createCardSix; else % We really shouldn't end up here. If we are here it is because the 'Next' % button hasn't been disabled. To exit smoothly, we'll just goto card six. warning(message('mbc:cgoptim:InvalidState14')); nextCardID = @i_createCardSix; end %------------------------------------------------------------------------ function hasModelConstraints = i_optimHasModelConstraints(optim) cons = getConstraint(optim); isModelCon = mbccellarrayeval(cons, @i_isModelCon, {}, mbclogical); hasModelConstraints = ~isempty( isModelCon ) && any( isModelCon ); %------------------------------------------------------------------------ % CARD FIVE FUNCTIONS BELOW %------------------------------------------------------------------------ function layout = i_createCardFive(fh, iFace, localData) % GUI Layout for card five: assign constraints % Constraint card % Have we been called to create the layout or simply update? if isa(fh, 'xregcontainer') layout = fh; layoutUD = get(layout, 'UserData'); else SC = xregGui.SystemColorsDbl; layoutUD.List = mbcwidgets.List( 'Parent', fh,... 'Editable', false, ... 'Grid',false,... 'Visible','off',... 'SelectionChangedCallback',{@i_ConListCbk, iFace},... 'SelectionMode', 'SingleRow'); layoutUD.List.Peer.setColumnData({'Model Constraint','CAGE Model', 'Bound'}); layoutUD.List.Peer.setColumnWidths([100 100 80]); % Make a title for this ListView t= uicontrol('Parent',fh,... 'Style','text',... 'Visible','off',... 'HorizontalAlignment','left',... 'String','Optimization constraints:'); t3 = uicontrol('Parent',fh,... 'Style','text',... 'Visible','off',... 'HorizontalAlignment','left',... 'String','Constraint:'); layoutUD.boundtext = uicontrol('Parent',fh,... 'Style','text',... 'Visible','off',... 'HorizontalAlignment','right',... 'String',''); layoutUD.boundctrl = mbcgui.widget.Spinner( 'Parent', fh, ... 'Value', 0, ... 'Visible', 'Off', ... 'Max', realmax, ... 'Callback', { @i_ConstraintBound, iFace } ); layoutUD.boundtype = uicontrol('Parent',fh,... 'Visible', 'Off', ... 'Style', 'Popupmenu', ... 'String', {'<=', '>='} ,... 'BackgroundColor', SC.WINDOW_BG, ... 'Value', 1, ... 'Callback', { @i_ConstraintBoundType, iFace } ); layoutUD.selbutton = xregGui.iconuicontrol('parent',fh,... 'imageFile',xregrespath('leftarrow.bmp'),... 'transparentColor', [255 255 0],... 'ToolTip','Select CAGE Model',... 'visible','off',... 'callback',{@i_selectCon,iFace}); t2 = uicontrol('Parent',fh,... 'Style','text',... 'Visible','off',... 'HorizontalAlignment','left',... 'String','CAGE models:'); layoutUD.namelist = cgtools.exprList('Parent', fh, ... 'visible', 'off', ... 'DisplayTypeColumn', false, ... 'DisplayHeaderRow', false); layoutUD.conlyt = xreggridbaglayout(fh, ... 'dimension', [4 3], ... 'rowsizes', [1 3 15 2], ... 'colsizes', [87 40 80], ... 'gapx', 7, ... 'mergeblock', {[1 4], [2 2]}, ... 'mergeblock', {[2 4], [3 3]}, ... 'elements', {... [],[],layoutUD.boundtext, [],... layoutUD.boundtype, [],[],[],... [],layoutUD.boundctrl}); layoutUD.constradio= uicontrol('Parent',fh,... 'Style', 'radio', ... 'Visible','off',... 'Value', 1, ... 'String', '',... 'Callback',{@i_conradioConstant, iFace}); layoutUD.boundradio= uicontrol('Parent',fh,... 'Style', 'radio', ... 'Visible','off',... 'Value', 0, ... 'String', 'Boundary of model',... 'Callback',{@i_conradioBoundary, iFace}); conradlyt = xreggridbaglayout(fh, ... 'dimension', [4 3], ... 'rowsizes', [15 21 3 20], ... 'colsizes', [10 15 -1], ... 'gapx', 7, ... 'mergeblock', {[1 1], [1 3]}, ... 'mergeblock', {[4 4], [2 3]}, ... 'elements', {t3, [], [], [], ... [], layoutUD.constradio, [], layoutUD.boundradio, ... [], layoutUD.conlyt, [], [], ... }); layout = xreggridbaglayout(fh, ... 'dimension', [7, 3], ... 'rowsizes', [15 2 -1 80 -1 5 70], ... 'colsizes', [-1 80 -1], ... 'colratios', [2 0 1], ... 'gapx', 10, ... 'border', [7 0 7 10], ... 'mergeblock', {[3 5], [1 1]}, ... 'mergeblock', {[3 5], [3 3]}, ... 'elements', {t, [], layoutUD.List, [], [], [], conradlyt, ... [],[],[], layoutUD.selbutton, [],[],[], ... t2, [], layoutUD.namelist}); infostr = ['Model Constraints define regions that the free variables can vary within.', ... ' Select CAGE models to use for each constraint. ', ... 'Select whether to constrain the model by a fixed value or by ', ... 'the model''s boundary constraint.']; layout = i_maketitlearea(fh, 'Model Constraints', infostr, layout); layoutUD.CurrentRow = 1; layoutUD.cancelFcn = @i_cardCancel; end if nargin > 2, layoutUD.optimdata = localData; end layoutUD = i_cardFiveUpdate(layoutUD, iFace); set(layout, 'UserData', layoutUD); %------------------------------------------------------------------------ function layoutUD = i_cardFiveUpdate( layoutUD, iFace ) % fills the card with information % Get the optimization object we are setting up optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; % Fill left-hand list box and decide which items can be edited here. The % wizard only allows editing of model constraints that have a numeric % bound. Finding these constraint types is a bit messy, but necessary conLabels = get( optim, 'ConstraintLabels' ); conItems = getConstraint(optim); Data = cell(length( conLabels ),3); IsModCon = false(1,length( conLabels ) ); for n = 1:length( conLabels ) if i_isModelCon(conItems{n}) IsModCon(n) = true; pConExpr = getConstraintExpression(conItems{n}); Data{n,1} = conLabels{n}; conExpr = pConExpr.info; pLHS = getlhsexpr(conExpr); if isvalid(pLHS) Data{n,2} = pLHS.getname; end if strcmp(getevaluationmode(conExpr), 'constraint') Data{n,3} = 'Boundary'; else Data{n,3} = ... sprintf('%s %g', getcomparisonoperator(conExpr), getrhsvalue(conExpr)); end end end if any(IsModCon) layoutUD.List.Peer.setData(Data(IsModCon,:)); layoutUD.List.selectRows(1); end % Get candidate constraint models from the cage browser and put them in the % right-hand list globalUD = feval(iFace.getUserData); modelptrs = globalUD.Project.getmodels; layoutUD.namelist.Items = modelptrs ; % Select the current item properly i_ConListCbk(layoutUD.List, [], iFace, layoutUD); layoutUD.finishFcn = @i_cardSixFinish; layoutUD.nextFcn = @i_cardFiveNext; feval(iFace.setFinishButton, 'on'); nextOK = i_checkPtrsCons( layoutUD ); if nextOK feval(iFace.setNextButton, 'on'); else feval(iFace.setNextButton, 'off'); end %------------------------------------------------------------------------ function ret = i_isModelCon(obj) %Check whether we can edit this constraint type ret = isa(obj, 'cgpointconstraint'); if ret pConExpr = getConstraintExpression(obj); ConExpr = pConExpr.info; ret = isa(ConExpr, 'cgexprconstraint'); if ret ret = strcmp(getvaluemode(ConExpr), 'value'); end end %------------------------------------------------------------------------ function i_UpdateBoundControls(layoutUD, CF) % Update the bound value and type controls based on the object CF if isempty( CF ) % Disable constraint bound value and type controls set( layoutUD.boundctrl, 'Enable', 'off' ); set( layoutUD.boundtype, 'Enable', 'off' ); set( layoutUD.boundtext, 'String', '' ); set( layoutUD.boundradio, 'Enable', 'off' ); set( layoutUD.constradio, 'Enable', 'off' ); else % Get constraint expression ConExpr = info(getConstraintExpression(CF)); pModExpr = getlhsexpr(ConExpr); % Enable radio buttons. Disable the boundary constraint radio button if % the current model does not have any. set(layoutUD.constradio, 'Enable', 'on'); if ~isempty(pModExpr) && isvalid(pModExpr) && concheck(pModExpr.info) set(layoutUD.boundradio, 'Enable', 'on'); else set(layoutUD.boundradio, 'Enable', 'off'); end % Assign values to constraint bound value and type controls if strcmp(getevaluationmode(ConExpr), 'eval') compstr = getcomparisonoperator(ConExpr); compmode = find( strcmp( compstr,{ '<=', '>=' } ) ); set(layoutUD.boundctrl, ... 'Value', getrhsvalue(ConExpr), ... 'Enable', 'on'); set(layoutUD.boundtype, ... 'Value', compmode, ... 'Enable', 'on'); set(layoutUD.boundradio, 'Value', 0); set(layoutUD.constradio, 'Value', 1); else % Boundary constraint. Ensure bound value and type controls are % disabled. set(layoutUD.boundctrl, 'Enable', 'off'); set(layoutUD.boundtype, 'Enable', 'off'); set(layoutUD.boundradio, 'Value', 1); set(layoutUD.constradio, 'Value', 0); end % Set string of model name label if isvalid(pModExpr) set( layoutUD.boundtext, 'String', pModExpr.getname); else set( layoutUD.boundtext, 'String', '<no selection>' ); end end %------------------------------------------------------------------------ function i_UpdateModelList(iFace, layoutUD, CF) % Update the list of possible models that can be used and update the % selection % Get all models in project globalUD = feval(iFace.getUserData); modelptrs = globalUD.Project.getmodels; % Get constraint expression pConExpr = getConstraintExpression(CF); if strcmp(pConExpr.getevaluationmode, 'constraint') % Can only use models with a boundary constraint hasBoundary = pveceval(modelptrs, @concheck); hasBoundary = [hasBoundary{:}]; layoutUD.namelist.Items = modelptrs(hasBoundary); else % All project models can be used for bound constraints layoutUD.namelist.Items = modelptrs; end % Update selection selmodel = pConExpr.getlhsexpr; set(layoutUD.namelist, 'SelectedItems', selmodel); %------------------------------------------------------------------------ function i_ConListCbk(hList, evt, iFace, layoutUD) if nargin<4 layoutUD = feval(iFace.getCardUserdata); end optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; if ~isempty(evt) selected = evt.data.SelectedRows; else selected = hList.getSelectedRows; end if strcmp(get(layoutUD.boundctrl,'Visible'),'on') % might need to update the bound control i_ConstraintBound( layoutUD.boundctrl, [], iFace ) end if ~isequal(layoutUD.CurrentRow,selected) layoutUD.CurrentRow = selected; feval(iFace.setCardUserdata,layoutUD); end if ~isempty(selected) ConLabel = hList.getDataAt(selected-1,0); CF = getConstraint(optim, ConLabel); % Update selection in model list i_UpdateModelList(iFace, layoutUD, CF); % Disable the select button when there are no models or constraints if isempty(layoutUD.namelist.Items) set(layoutUD.selbutton,'Enable', 'off'); else set(layoutUD.selbutton,'Enable', 'on'); end % Update bound controls i_UpdateBoundControls(layoutUD, CF); else i_UpdateBoundControls(layoutUD, []); set(layoutUD.selbutton,'Enable', 'off'); set(layoutUD.namelist, 'SelectedItems', []); end %------------------------------------------------------------------------ function i_ConstraintBound( src, ~, iFace ) layoutUD = feval( iFace.getCardUserdata ); optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; selected = layoutUD.CurrentRow; if ~isempty(selected) value = get( src, 'Value' ); ConLabel = layoutUD.List.getDataAt(selected-1,0); CF = getConstraint(optim, ConLabel); pConExpr = getConstraintExpression(CF); pConExpr.info = pConExpr.setrhsvalue(value); % Update UI boundtext = sprintf('%s %g', pConExpr.getcomparisonoperator, value); layoutUD.List.Peer.setDataAt(boundtext,selected-1,2); end %------------------------------------------------------------------------ function i_ConstraintBoundType( src, ~, iFace ) layoutUD = feval( iFace.getCardUserdata ); optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; selected = layoutUD.List.getSelectedRows; value = get( src, 'Value' ); ConLabel = layoutUD.List.getDataAt(selected-1,0); CF = getConstraint(optim, ConLabel); pConExpr = getConstraintExpression(CF); if value==1 pConExpr.info = pConExpr.setoperator('le'); else pConExpr.info = pConExpr.setoperator('ge'); end % Update UI boundtext = sprintf('%s %g', pConExpr.getcomparisonoperator, pConExpr.getrhsvalue); layoutUD.List.Peer.setDataAt(boundtext,selected-1,2); %------------------------------------------------------------------------ function i_selectCon(~, ~,iFace) layoutUD = feval(iFace.getCardUserdata); optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; % get handles target = layoutUD.List.getSelectedRows; curlst = layoutUD.namelist; % Model to use pNewModel = curlst.SelectedItems; if isempty(pNewModel) && ~isempty(curlst.Items) % Try to take first item in the list pNewModel = curlst.Items(1); end % Objective to change ConLabel = layoutUD.List.getDataAt(target-1,0); if ~isempty(pNewModel) CF = getConstraint(optim, ConLabel); pConExpr = getConstraintExpression(CF); pConExpr.info = pConExpr.setlhsexpr(pNewModel); % Update the left list layoutUD.List.Peer.setDataAt(pNewModel.getname,target-1,1); end % Update i_ConListCbk(layoutUD.List, [], iFace); %------------------------------------------------------------------------ function nextOK = i_checkPtrsCons(layoutUD) optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; % Check to see if there are any oppts. If not, cannot go any % further nextOK = 1; if isempty( get( optim, 'oppoints' ) ) nextOK = 0; end %-------------------------------------------------------------------------- function i_conradioConstant(~, ~, iFace) % Get the user data layoutUD = feval(iFace.getCardUserdata); % Set the other button to off set(layoutUD.boundradio, 'Value', 0); % Get the selected constraint layoutUD = feval( iFace.getCardUserdata ); optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; selected = layoutUD.List.getSelectedRows; % Get constraint expression ConLabel = layoutUD.List.getDataAt(selected-1,0); CF = getConstraint(optim, ConLabel); pConExpr = getConstraintExpression(CF); pConExpr.info = pConExpr.setevaluationmode('eval'); % Update bound and operator currently in constraint value = pConExpr.getrhsvalue; op = pConExpr.getcomparisonoperator; boundtext = sprintf('%s %g', op, value); layoutUD.List.Peer.setDataAt(boundtext,selected-1,2); % Update the bound constraint layout i_UpdateBoundControls(layoutUD, CF); % Update the list of possible models i_UpdateModelList(iFace, layoutUD, CF); %------------------------------------------------------------------------ function i_conradioBoundary(~, ~, iFace) % Get the selected constraint layoutUD = feval( iFace.getCardUserdata ); optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; selected = layoutUD.List.getSelectedRows; % Get constraint expression ConLabel = layoutUD.List.getDataAt(selected-1,0); CF = getConstraint(optim, ConLabel); pConExpr = getConstraintExpression(CF); pConExpr.info = pConExpr.setevaluationmode('constraint'); % Update UI layoutUD.List.Peer.setDataAt('Boundary',selected-1,2); % Update the bound constraint layout i_UpdateBoundControls(layoutUD, CF); % Update the list of possible models i_UpdateModelList(iFace, layoutUD, CF); %------------------------------------------------------------------------ function [nextCardID, localData] = i_cardFiveNext(layoutUD, ~) % set up the local data localData = layoutUD.optimdata; % Which card is next? obj = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; if ~isempty( get( obj, 'oppoints' ) ) % number of oppoint sets >= 1 ==> must vist card six nextCardID = @i_createCardSix; else % We really shouldn't end up here. If we are here it is because the 'Next' % button hasn't been disabled. To exit smoothly, we'll just goto card six. warning(message('mbc:cgoppoint:InvalidState12')); nextCardID = @i_createCardSix; end %------------------------------------------------------------------------ % CARD SIX FUNCTIONS BELOW %------------------------------------------------------------------------ function layout = i_createCardSix(fh, iFace, localData) % GUI Layout for card six: assign data sets % Have we been called to create the layout or simply update? if isa(fh, 'xregcontainer') layout = fh; layoutUD = get(layout, 'UserData'); else layoutUD.List = mbcwidgets.List( 'Parent', fh,... 'Editable', false, ... 'Grid',false,... 'Visible','off',... 'SelectionChangedCallback',{@i_ListCbk, iFace},... 'SelectionMode', 'SingleRow'); layoutUD.List.Peer.setColumnData({'Operating Point Set','CAGE Data Set'}); layoutUD.List.Peer.setColumnWidths([110 120]); % Make a title for this ListView we will find this and get it's user data on listview callbacks t= uicontrol('Parent',fh,... 'Style','text',... 'Visible','off',... 'HorizontalAlignment','left',... 'String','Optimization operating point sets:'); layoutUD.selbutton= xregGui.iconuicontrol('parent',fh,... 'imageFile',[xregrespath,'\leftarrow.bmp'],... 'transparentColor', [255 255 0],... 'ToolTip','Select CAGE Data Set',... 'visible','off',... 'callback',{@i_selectOpp,iFace}); t2= uicontrol('Parent',fh,... 'Style','text',... 'Visible','off',... 'HorizontalAlignment','left',... 'String','CAGE data sets:'); layoutUD.namelist = cgtools.nodeList('Parent', fh, ... 'visible', 'off', ... 'DisplayTypeColumn', false, ... 'DisplayHeaderRow', false); layout = xreggridbaglayout(fh, ... 'dimension', [5 3], ... 'gapx', 10, ... 'border', [7 0 7 10], ... 'rowsizes', [15 2 -1 80 -1], ... 'colsizes', [-1 80 -1], ... 'colratios', [2 0 1], ... 'mergeblock', {[3 5], [1 1]}, ... 'mergeblock', {[3 5], [3 3]}, ... 'elements', {t, [], layoutUD.List, [],[], ... [],[],[], layoutUD.selbutton, [], ... t2, [], layoutUD.namelist, [], []}); infostr = ['Select the data sets that the algorithm will use. The data', ... ' sets contains data that is accessible by the optimization function', ... ' when it is run.']; layout = i_maketitlearea(fh, 'Operating Point Sets', infostr, layout); layoutUD.cancelFcn = @i_cardCancel; end if nargin > 2, layoutUD.optimdata = localData; end layoutUD = i_cardSixUpdate(layoutUD, iFace); set(layout, 'UserData', layoutUD); %------------------------------------------------------------------------ function layoutUD = i_cardSixUpdate(layoutUD, iFace) optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; % fills the card with information % fill the left-hand list box oppointLabels = get(optim, 'oppointLabels'); oppointPtrs = getOppointPtr(optim); Data = cell(length(oppointLabels),2); for i = 1:length(oppointLabels) Data{i,1} = oppointLabels{i}; if isvalid(oppointPtrs(i)) Data{i,2} = oppointPtrs(i).getname; end end if ~isempty(Data) layoutUD.List.Peer.setData(Data); layoutUD.List.selectRows(1); end % Map between names and nodes for all datasets in the project globalUD = feval(iFace.getUserData); proj = globalUD.Project; dsnodes = filterbytype(proj.info, cgtypes.cgdatasettype); layoutUD.DSptrs = mbcpointer(size(dsnodes)); layoutUD.oppointnames = cell(size(dsnodes)); for n = 1:numel(dsnodes) layoutUD.DSptrs(n) = address(dsnodes{n}); layoutUD.oppointnames{n} = name(dsnodes{n}); end % Filters of allowed datasets for each optim entry are cached layoutUD.IsFilterDone = false(size(oppointLabels)); layoutUD.KeepFilter = false(length(layoutUD.DSptrs), length(oppointLabels)); % Select the correct item layoutUD = i_ListCbk([], [], iFace, layoutUD); layoutUD.finishFcn = @i_cardSixFinish; % enable the finish button, disable the next button feval(iFace.setNextButton, 'off'); feval(iFace.setFinishButton, 'on'); % -------------------------------------------------- function layoutUD = i_ListCbk(~, ~, iFace, layoutUD) if nargin<4 layoutUD = feval(iFace.getCardUserdata); end optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; selected = layoutUD.List.getSelectedRows; if ~isempty(selected) % Update the list of allowed data sets pAllReqVal = get(optim, 'oppointvalues'); if ~layoutUD.IsFilterDone(selected) layoutUD.KeepFilter(:, selected) = ... i_FilterAllowedDS(layoutUD.DSptrs, pAllReqVal{selected}); layoutUD.IsFilterDone(selected) = true; end layoutUD.namelist.Items = layoutUD.DSptrs(layoutUD.KeepFilter(:, selected)); OpPointLabel = layoutUD.List.getDataAt(selected-1,0); pSelOp = getOppointPtr(optim, OpPointLabel); if isvalid(pSelOp) layoutUD.namelist.SelectedItems = ... layoutUD.DSptrs(strcmp(pSelOp.getname, layoutUD.oppointnames)); else layoutUD.namelist.SelectedItems = []; end % Check whether to enable the select button if isempty(layoutUD.namelist.Items) % disable the select button when there are no datasets set(layoutUD.selbutton,'Enable', 'off'); else set(layoutUD.selbutton,'Enable', 'on'); end else set(layoutUD.selbutton,'Enable', 'off'); layoutUD.namelist.Items = []; end if nargin<4 feval(iFace.setCardUserdata, layoutUD); end % -------------------------------------------------- function i_selectOpp(~, ~,iFace) % oppoint selection layoutUD = feval(iFace.getCardUserdata); optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; % get handles target = layoutUD.List.getSelectedRows; curlst = layoutUD.namelist; % Model to use pNewDSNode = curlst.SelectedItems; if isempty(pNewDSNode) && ~isempty(curlst.Items) % Try to take first item in the list pNewDSNode = curlst.Items(1); end % Oppoint to change OpLabel = layoutUD.List.getDataAt(target-1,0); if ~isempty(pNewDSNode) pOp = pNewDSNode.getdata; optim = setOppointPtr(optim, OpLabel, pOp); layoutUD.optimdata.info.list{layoutUD.optimdata.info.index} = optim; % Update the left list layoutUD.List.Peer.setDataAt(pOp.getname,target-1,1); end % Move the left list selection down one N = layoutUD.List.getRowCount; newInd = mod(target,double(N))+1; layoutUD.List.selectRows(newInd); % Update i_ListCbk(layoutUD.List, [], iFace); %------------------------------------------------------------------- function Keep = i_FilterAllowedDS(pNodes, reqdptrs) nodes = infoarray(pNodes); Keep = false(size(nodes)); for i = 1:numel(nodes) pOp = getdata(nodes{i}); ptrs = get(pOp.info, 'ptrlist'); Keep(i) = all(ismember(reqdptrs, ptrs)); end %------------------------------------------------------------------------ function i_cardSixFinish(layoutUD, iFace) optimindex = layoutUD.optimdata.info.index; optimlist = layoutUD.optimdata.info.list; otherindices = [ 1:optimindex-1, optimindex+1:length( optimlist ) ]; % Destroy all optim objects that are not used for n = otherindices destroyobject( optimlist{n}); end % return the new optimization object outputUD.optim = layoutUD.optimdata.info.list{layoutUD.optimdata.info.index}; % At this point, any linear constraint will not have its inputs set up. % Set the inputs for all the linear constraints pFree = getfreevalues(outputUD.optim); cons = getConstraint(outputUD.optim); for i = 1:length(cons) if isa(cons{i}, 'cgpointconstraint') pConExpr = getConstraintExpression(cons{i}); if isa(pConExpr.info, 'cgconconstraint') conobj = getconobject(pConExpr.info); if isa(conobj, 'conlinear') pConExpr.info = setinputs(pConExpr.info, pFree); end end end end feval(iFace.setOutputData, outputUD); %------------------------------------------------------------------------ function lyt = i_maketitlearea(fh, sTitle, sInfo, hCenter) % Wrap a layout handle with a pretty titled area containing more % information hInfo = mbcgui.container.InfoPane( 'Parent', fh,... 'Visible', 'off',... 'Title', sTitle,... 'InfoString', sInfo,... 'Center', hCenter ); lyt = xreglayerlayout(fh, 'elements', {hInfo}); %------------------------------------------------------------------------ function i_cardCancel(layoutUD, ~) % Need to destroy the optim objects to make sure all pointers are released alloptims = layoutUD.optimdata.info.list; for n = 1:length(alloptims) destroyobject(alloptims{n}); end function cbkSelectInput(listbox,~,iFace) Row = getSelectedRows(listbox); if isempty(Row) feval(iFace.setNextButton, 0 ); else feval(iFace.setNextButton, 1 ); end