Home > src > hardBoundConstraint.m

hardBoundConstraint

PURPOSE ^

- hard bound constraint object

SYNOPSIS ^

This is a script file.

DESCRIPTION ^

 - hard bound constraint object

 copyright 2009-2012 Blair Armstrong, Christine Watson, David Plaut

    This file is part of SOS

    SOS is free software: you can redistribute it and/or modify
    it for academic and non-commercial purposes
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.  For commercial or for-profit
    uses, please contact the authors (sos@cnbc.cmu.edu).

    SOS is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 % - hard bound constraint object
0002 %
0003 % copyright 2009-2012 Blair Armstrong, Christine Watson, David Plaut
0004 %
0005 %    This file is part of SOS
0006 %
0007 %    SOS is free software: you can redistribute it and/or modify
0008 %    it for academic and non-commercial purposes
0009 %    under the terms of the GNU General Public License as published by
0010 %    the Free Software Foundation, either version 3 of the License, or
0011 %    (at your option) any later version.  For commercial or for-profit
0012 %    uses, please contact the authors (sos@cnbc.cmu.edu).
0013 %
0014 %    SOS is distributed in the hope that it will be useful,
0015 %    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016 %    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017 %    GNU General Public License for more details.
0018 
0019 %    You should have received a copy of the GNU General Public License
0020 %    along with SOS (see COPYING.txt).
0021 %    If not, see <http://www.gnu.org/licenses/>.
0022 
0023 
0024 
0025 classdef hardBoundConstraint < hardConstraint
0026     %% creates and supports hardBoundConstraints
0027     %
0028     % Creates constraint objects that measure the number of items which
0029     % violate a specified hard bound in a sample, and which evaluates
0030     % whether a new item which could be swapped into a sample would also
0031     % violate this same hards bound.
0032     %
0033     % Additional functionality and interface requirements are inherited
0034     % from hardConstraint
0035     %
0036     % PROPERTIES
0037     %     comparison - handle to specific comparison method to use
0038     %     bound   - the bound to evaluate an item against
0039     %     s1 - the sample
0040     %     s1Col   - the column in the sample
0041     %     s1ColName   - the name of the data stored in the column of the sample
0042     %
0043     % METHODS:
0044     %   hardBoundConstraint(varargin) - CONSTRUCTOR
0045     %   cost = initCost(obj) Calculates, saves, and returns the cost value for the current  items in the sample.
0046     %   swCost = swapCost(obj, targSample, targSampleIndex, feederdf, feederdfIndex) Calculates the new cost if items from targSample and feederdf were swapped.
0047     %   cost = itemCost(obj, targSample,targSampleIndex,feederdf, feederdfIndex) Calculates the cost of the specified item in df.
0048     %   cost = itemCostFilling(obj,  targSample,targSampleIndex,feederdf, feederdfIndex) Calculates the cost of the specified item in df to the sample.
0049     %
0050     % METHODS (Static)
0051     %   p = hardBoundConstraintInputParser() - generates input parser for constructor args
0052     %
0053     % METHODS (Static, Access = private)
0054     %    p = parseConstructorArgs(varargin) - parses the construcvtor args
0055     
0056     
0057     %% PROPERTIES
0058     properties
0059         comparison % handle to specific comparison method to use
0060         bound   % the bound to evaluate an item against
0061         s1 % the sample
0062         s1Col   % the column in the sample
0063         s1ColName   % the name of the data stored in the column of the sample
0064     end
0065     
0066     methods
0067         
0068         %% hardBoundConstraint CONSTRUCTOR
0069         function obj = hardBoundConstraint(varargin)
0070             % CONSTRUCTOR - creates a hardBoundConstraint object
0071             %
0072             % CALL:
0073             % hardBoundConstraint(varargin <defined below> )
0074             %
0075             %PARAMETERS:
0076             %
0077             %   'sosObj'/sos object - the SOS object the constraint will be linked to, and which contains the samples the constraint operates on.
0078             %   'constraintType'/'hard' - the type of contraint - must be 'hard'
0079             %   'fnc'/'floor'|'ceiling' the type of bound to create
0080             %   'sample1'/sample     - the sample to apply the constraint to
0081             %   's1ColName'/string - name of column in 1st sample
0082             %   'value'/numeric -   value of the bound
0083             %
0084             % EXAMPLE:
0085             % mySOS.addConstraint('constraintType','hard','fnc','ceiling','sample1',s1,'s1ColName','Lg10WF','value',1.5);
0086   
0087             p = hardBoundConstraint.parseConstructorArgs(varargin);
0088             
0089             
0090             %now check additional characteristics of the input parameters.
0091             
0092             if(p.Results.sosObj.containsSample(p.Results.sample1) == false)
0093                 error('Cannot create hard bound constraint: sos Object does not contain the sample1');
0094             end
0095             
0096             col = p.Results.sample1.colName2colNum(p.Results.s1ColName);
0097             
0098             if(col == -1)
0099                 error('Specified column name not found in sample1');
0100             end
0101             
0102             if(strcmp(p.Results.sample1.format{col},'%f') == 0)
0103                 error('Specified column is not of numeric (%f) format, so cannot use as hard bound');
0104             end
0105 
0106             % properties meet requirements, assign properties to new obj
0107             
0108             %give a handle to either hte less than or greater than function
0109              if (strcmp(p.Results.fnc,'floor'))
0110                 comp = @ge;
0111             elseif (strcmp(p.Results.fnc,'ceiling'))
0112                 comp = @le;
0113             else
0114                 error('Specified bound function not suported');
0115              end
0116                          
0117             %parent property
0118             obj.sosObj = p.Results.sosObj;
0119             obj.constraintType = p.Results.constraintType;
0120             obj.fnc = p.Results.fnc;
0121 
0122             obj.comparison = comp;
0123             obj.bound = p.Results.value;
0124             obj.s1 = p.Results.sample1;
0125             obj.s1Col = col;
0126             obj.s1ColName = p.Results.s1ColName;       
0127             
0128             
0129             obj.cost = NaN;
0130             obj.swCost = NaN;
0131             
0132             % add the name and the label
0133             obj.label = [obj.constraintType,'_',obj.fnc,'_',...
0134                     obj.s1.name,'_',obj.s1ColName,'_',num2str(obj.bound)];              
0135             if any(strcmp(p.UsingDefaults,'name'))                 
0136                 obj.name = obj.label;
0137             else
0138                  obj.name = p.Results.name;  
0139             end
0140              
0141             
0142             verbosePrint('Hard Bound Constraint has been created', ...
0143                     'hardBoundConstraint_Constructor_endObjCreation');
0144                       
0145         end %constructor
0146         
0147         %% cost = initCost() METHOD
0148         function cost = initCost(obj)
0149             % Calculates, saves, and returns the cost value for the current items in the sample.
0150             %
0151             %CALL:
0152             % <hardBoundConstraint>.initCost();
0153             %
0154             % Calculates the cost of the hard bound for each item in the
0155             % sample.  As hard bounds should generally not be violated, a
0156             % warning message will also be displayed if items violating
0157             % a bound are present in the set.  This should indicate that
0158             % the user has forced items into the sample (e.g., by putting
0159             % them in a file listing items to be read into the sample
0160             % object when it is created).  It should not be displayed
0161             % otherwise if SOS is operating as inteded.
0162             
0163             cost = 0;
0164             for i=1:length(obj.s1.data{obj.s1Col})
0165                 if(obj.comparison(obj.s1.data{obj.s1Col}(i),obj.bound) == 0)
0166                     
0167                     %bca: may want to make this print statement more useful...
0168                     verbosePrint(['Warning: Item ', num2str(i), ' violated the hard bound constraint!'], ...
0169                         'hardBoundConstraint_initCost');
0170                     cost = cost + 1;
0171                 end
0172             end
0173             
0174             obj.cost=cost;
0175             obj.swCost = NaN;
0176         end
0177         
0178         
0179          %%  swCost(targSample,targSampleIndex, feederdf,feederdfIndex) FUNCTION
0180         function swCost = swapCost(obj, targSample, targSampleIndex, feederdf, feederdfIndex)
0181             % Calculates the new cost if items from targSample and feederdf were swapped.
0182             %
0183             %By definition, if this method is called it means that at least
0184             % one of the two swap objects is implicated in this function
0185             %
0186             %PARAMETERS:
0187             %   targSample - the target sample (i.e., the object that will call it's swapSample() method if a swap later occurs).
0188             %   targSampleIndex - row index of item to swap
0189             %   feederdf - dataframe (sample/pop) containin the other item to swap
0190             %   feederdfIndex - row index of item to swap.
0191                         
0192             curItemCost = obj.itemCost('null','null',targSample, targSampleIndex);
0193             newItemCost = obj.itemCost('null','null',feederdf, feederdfIndex);
0194           
0195            
0196             %can swap to another item that violates the constraint if you
0197             %currently violate the constraint
0198             if curItemCost == 1 && newItemCost == 1
0199                 newSubCost = 0;
0200             elseif curItemCost == 0 && newItemCost == 1
0201                 newSubCost = 1;
0202             %must swap if current item violates constraint and new one
0203             %doesn't
0204             elseif curItemCost == 1 && newItemCost == 0
0205                 newSubCost = -1;
0206             elseif curItemCost == 0 && newItemCost == 0
0207                 newSubCost = 0;
0208             else
0209                 error('This condition should not have been met');
0210             end
0211             
0212             swCost = obj.cost + newSubCost;
0213             obj.swCost = swCost;
0214             
0215         end
0216 
0217         %% itemCost(targSample,targSampleIndex,feederdf, feederdfIndex) METHOD
0218         function cost = itemCost(obj, targSample,targSampleIndex,feederdf, feederdfIndex)
0219             %Calculates the cost of the specified item in df.
0220             %Should usually be invoked once a sample is filled with items.
0221             %
0222             %NOTE:
0223             % Other parameters are provided only for consistency, but are not
0224             % used.
0225             %
0226             %SEE swCost() doc/help for more details
0227             
0228             cost = obj.itemCostFilling(targSample,targSampleIndex,feederdf, feederdfIndex);
0229         end
0230         
0231         %% cost = itemCostFilling(targSample,targSampleIndex,feederdf, feederdfIndex) METHOD
0232         function cost = itemCostFilling(obj,  targSample,targSampleIndex,feederdf, feederdfIndex) %#ok<INUSL>
0233             %Calculates the cost of the specified item in df to the sample.
0234             % Should usually only be invoked when initially filling a
0235             % sample
0236             %
0237             %NOTE:
0238             % Other parameters are provided only for consistency, but are not
0239             % used.
0240             %
0241             %SEE swCost() doc/help for more details
0242             
0243             cost = 0;
0244             
0245             if(obj.comparison(feederdf.data{obj.s1Col}(feederdfIndex),obj.bound))
0246                 %do nothing
0247             else
0248                cost = 1;
0249             end            
0250         end
0251             
0252         function cost = acceptSwap(obj)
0253             acceptSwap@genericConstraint(obj);
0254             cost = obj.cost;
0255         end
0256         
0257     end
0258     
0259     methods(Static)
0260         %% p = hardBoundConstraintInputParser() STATIC METHOD
0261         function p = hardBoundConstraintInputParser()
0262             % generates input parser for constructor args
0263             p = inputParser;
0264 
0265             %Note: some of these 'optional' parameters are de facto
0266             %required by making the default value fail validation
0267             p.addParamValue('sosObj','null', ...
0268                 @(sosObj)strcmp(class(sosObj),'sos'));
0269             p.addParamValue('constraintType', 'null', ...
0270                 @(constraintType)any(strcmp({'hard'},constraintType)));
0271             p.addParamValue('fnc','null', ...
0272                  @(fnc)any(strcmp({'floor' 'ceiling'},fnc)));
0273             p.addParamValue('sample1','null', ...
0274             @(sample1)strcmp(class(sample1),'sample'));
0275             p.addParamValue('s1ColName','',@(s1ColName)ischar(s1ColName));
0276             p.addParamValue('value','null',@(value)isnumeric(value));
0277             p.addParamValue('name','noname',@(name)ischar(name));
0278             
0279         end % hardBoundConstraintInputParser()
0280     end
0281     
0282     methods(Static, Access = private)
0283         
0284         %% parseConstructorArgs STATIC PRIVATE FUNCTION
0285         function p = parseConstructorArgs(varargin)
0286             % parses the construcvtor args
0287             %
0288             % see construcor help/doc for more info
0289             
0290             varargin = varargin{1};            
0291             p = hardBoundConstraint.hardBoundConstraintInputParser();
0292             p.parse(varargin{:});            
0293         end
0294     end
0295     
0296 end
0297

Generated on Fri 27-Jan-2012 16:18:41 by m2html © 2005