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:

- genericConstraint - parent class for constraints
- hardBoundConstraint - hard bound constraint object
- hardConstraint - parent class for hard constraints
- verbosePrint - master print function that regulates cmd line output based on verbosity flags

This function is called by:

- genericConstraint - parent class for constraints
- hardBoundConstraint - hard bound constraint object

## SUBFUNCTIONS

- function obj = hardBoundConstraint(varargin)
- function cost = initCost(obj)
- function swCost = swapCost(obj, targSample, targSampleIndex, feederdf, feederdfIndex)
- function cost = itemCost(obj, targSample,targSampleIndex,feederdf, feederdfIndex)
- function cost = itemCostFilling(obj, targSample,targSampleIndex,feederdf, feederdfIndex)
- function cost = acceptSwap(obj)
- function p = hardBoundConstraintInputParser()
- function p = parseConstructorArgs(varargin)

## 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