Home > src > softMetaConstraint.m

# softMetaConstraint

## PURPOSE

- parent class for soft meta-constraints

## SYNOPSIS

This is a script file.

## DESCRIPTION

     - parent class for soft meta-constraints

     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
- softConstraint - parent class for soft constraints
- softMetaConstraint - parent class for soft meta-constraints
- verbosePrint - master print function that regulates cmd line output based on verbosity flags

This function is called by:

- genericConstraint - parent class for constraints
- softMetaConstraint - parent class for soft meta-constraints

## SUBFUNCTIONS

- function obj = softMetaConstraint(varargin)
- function cost = initCost(obj)
- function swCost = swapCost(obj)
- function cost = minDiff(obj,x1,x2)
- function cost = minDiffCond(obj,x1,x2)
- function cost = acceptSwap(obj)
- function cost = rejectSwap(obj)

## SOURCE CODE

    0001 % - parent class for soft meta-constraints
    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 classdef softMetaConstraint < softConstraint
    0025     %% creates and supports soft meta constraints.
    0026     %
    0027     % Meta constraints are a special type of soft constraint that operate
    0028     % on the actual cost values of other constraints rather than creating
    0029     % their own cost values from the actual data being matched.  These meta
    0030     % cosntraints can help balance (or intentionally imbalance) the degree
    0031     % to which different constraints are emphasized when optimizing sets.
    0032     %
    0033     % PROPERTIES
    0034     %     const1 % the first constraint
    0035     %     const2 % the second constraint
    0036     %     const2costScale % multiplier to apply to cost from the second constraint
    0037     %     comparison % how the two cost values should be compared.
    0038     %
    0039     % METHODS:
    0040     %   obj = softMetaConstraint(varargin) % CONSTRUCTOR
    0041     %   cost = initCost(obj)  % initializes cost
    0042     %   cost = minDiff(obj,x1,x2) % calculates cost when trying to minimize difference between the two cosntraint's costs.
    0043     %   cost = minDiff(obj,x1,x2) % calculates cost when trying to minimize difference between the two cosntraint's costs.
    0044     %   cost = acceptSwap(obj) % accept the swap
    0045     %   cost = rejectSwap(obj) % reject the swap
    0046     %
    0047
    0048
    0049     %% PROPERTIES
    0050     properties
    0051         const1 % the first constraint
    0052         const2 % the second constraint
    0053         const2costScale % multiplier to apply to cost from the second constraint
    0054         comparison % how the two cost values should be compared.
    0055     end
    0056
    0057     %% METHODS
    0058     methods
    0059
    0060         function obj = softMetaConstraint(varargin)
    0061             %% Constructs a softMetaConstraint object
    0062             %
    0063             % PARAMETERS
    0064             %   sosObj - the sosObject this metacosntraint will be linked to
    0065             %   constraintType - must be 'meta'
    0066             %   fnc - match function to use ('matchCost' and matchCostNotMin are currently supported).
    0067             %
    0068             %   constraint1 - first constraint object
    0069             %   constraint2 - second constraint object
    0070             %   constraint2costScale - multiplier for constraint2 cost
    0071             %   exponent - exponent to use to scale the metaconstraint
    0072             %   weight - weight to be used to scale the metaconstraint
    0073             %   name - string label to assign to the object.
    0074
    0075             p = inputParser;
    0076
    0077             p.addParamValue('sosObj','null', ...
    0078                                  @(sosObj)strcmp(class(sosObj),'sos'));
    0079             p.addParamValue('constraintType', 'null', ...
    0080                 @(constraintType)strcmp('meta',constraintType));
    0081             p.addParamValue('fnc','null', ...
    0082                  @(fnc)any(strcmp({'matchCost','matchCostNotMin'},fnc)));
    0083             p.addParamValue('constraint1','null', ...
    0084                 @(softCost1)any(strcmp(superclasses(softCost1),...
    0085                                             'genericConstraint')));
    0086             p.addParamValue('constraint2','null', ...
    0087                 @(softCost2)any(strcmp(superclasses(softCost2),...
    0088                                             'genericConstraint')));
    0089             p.addParamValue('constraint2costScale', 1, ...
    0090                    @(constraint2costScale)isnumeric(constraint2costScale));
    0091             p.addParamValue('exponent',2,@(exponent)isnumeric(exponent));
    0092             p.addParamValue('weight',1,@(weight)isnumeric(weight));
    0093             p.addParamValue('name','noname',@(name)ischar(name));
    0094
    0095             p.parse(varargin{:});
    0096
    0097             % check additional constraints on values submitted to the
    0098             % constructor
    0099             if(p.Results.sosObj.containsConstraint(p.Results.constraint1) == 0)
    0100                 error('Constraint2 is not part of the specified sosObj');
    0101             end
    0102
    0103             if(p.Results.sosObj.containsConstraint(p.Results.constraint2) == 0)
    0104                 error('Constraint2 is not part of the specified sosObj');
    0105             end
    0106
    0107             % assign properties to the object
    0108
    0109             obj.sosObj = p.Results.sosObj;
    0110             obj.constraintType = p.Results.constraintType;
    0111             obj.fnc = p.Results.fnc;
    0112
    0113             obj.weight = p.Results.weight;
    0114             obj.exp = p.Results.exponent;
    0115
    0116             obj.const1 = p.Results.constraint1;
    0117             obj.const2 = p.Results.constraint2;
    0118             obj.const2costScale = p.Results.constraint2costScale;
    0119
    0120             if strcmp(obj.fnc,'matchCost')
    0121                 obj.comparison = @obj.minDiff;
    0122             elseif strcmp(obj.fnc,'matchCostNotMin')
    0123                 obj.comparison = @obj.minDiffCond;
    0124             else
    0125                 error(['fnc: "' obj.fnc, '" not yet supported']);
    0126             end
    0127
    0128             obj.cost = NaN;
    0129             obj.swCost = NaN;
    0130
    0131             % add the name and the label
    0132             obj.label = [obj.constraintType,'_',obj.fnc,'_[',...
    0133                     obj.const1.name,']_[',...
    0134                     obj.const2.name,']_',...
    0135                     'x',num2str(obj.const2costScale),'_w',...
    0136                     num2str(obj.weight),'_e',num2str(obj.exp)];
    0137             if any(strcmp(p.UsingDefaults,'name'))
    0138                 obj.name = obj.label;
    0139             else
    0140                  obj.name = p.Results.name;
    0141             end
    0142
    0143             verbosePrint('Soft META Constraint has been created', ...
    0144                     'softMetaConstraint_Constructor_endObjCreation');
    0145
    0146         end
    0147
    0148         %% cost = initCost(obj) METHOD
    0149         function cost = initCost(obj)
    0150             % initializes cost
    0151             cost = obj.comparison(obj.const1.cost,obj.const2.cost);
    0152             obj.cost = cost;
    0153         end
    0154
    0155         function swCost = swapCost(obj)
    0156
    0157             if isnan(obj.const1.swCost)
    0158                 cost1 = obj.const1.cost;
    0159             else
    0160                 cost1 = obj.const1.swCost;
    0161             end
    0162
    0163             if isnan(obj.const2.swCost)
    0164                 cost2 = obj.const2.cost;
    0165             else
    0166                 cost2 = obj.const2.swCost;
    0167             end
    0168
    0169             swCost = obj.comparison(cost1,cost2);
    0170             obj.swCost = swCost;
    0171         end
    0172
    0173
    0174         function cost = minDiff(obj,x1,x2)
    0175             %% calculates cost when trying to minimize difference between the two cosntraint's costs.
    0176             cost = (abs((obj.const2costScale*x2) - x1)^obj.exp)*obj.weight*100;
    0177         end
    0178
    0179
    0180         function cost = minDiffCond(obj,x1,x2)
    0181             %% calculates cost when trying to minimize difference between the two cosntraint's costs.
    0182             if x2 <= 0
    0183                 cost = ( ((abs(obj.const2costScale*x2 - x1)*x1)^0.5 )^obj.exp)*obj.weight*100;
    0184             else
    0185                  cost = 0;
    0186             end
    0187         end
    0188
    0189         function cost = acceptSwap(obj)
    0190             %% accept the swap
    0191             cost = acceptSwap@genericConstraint(obj);
    0192         end
    0193
    0194         function cost = rejectSwap(obj)
    0195             %% reject the swap
    0196             cost = rejectSwap@genericConstraint(obj);
    0197         end
    0198
    0199     end
    0200
    0201 end
    0202