Home > src > softMatchCorrelConstraint.m

softMatchCorrelConstraint

PURPOSE ^

- soft correlation matching constraint object

SYNOPSIS ^

This is a script file.

DESCRIPTION ^

 - soft correlation matching 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 % - soft correlation matching 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 classdef softMatchCorrelConstraint < softConstraint
0024     %% creates and supports soft matchCorrel constraints
0025     %
0026     % This class creates softMatchCorrelConstraint objects that measure the
0027     % cost (in terms of matching a correlation across two variables)
0028     % associated with the current items in a set, and subsequent to
0029     % swapping a particular item with another items.
0030     %
0031     % Additional functionality and interface requirements are inherited
0032     % from softConstraint.
0033     %
0034     % a beautiful property:
0035     % correlation == covariance / stdev(x)stdev(y)
0036     % BUT because both numerator and denominators standardize for number of
0037     % observations, this cancels each other out, so also:
0038     %   cor = SPxy / sqrt(SSx)*sqrt(SSy), where SP = sum of products
0039     % This can be reduced to a set of very computationally efficient
0040     % equations:
0041     % SSx = Sum(x^2) - (Sum(x))^2/N  --- i.e., subtract correction factor
0042     % AND: SPxy = Sum(xy) - Sum(x)*Sum(y)/N
0043     % Gotta love algebra.  Pythagoras would be all over this...
0044     %
0045     % PROPERTIES
0046     %     stat % the statistic to calculate (correlation)
0047     %     comparison % handle to specific comparison calculator
0048     %     initStats % handle to global stat initialization method
0049     %     swStats % handle to local stat update method
0050     %     acceptsw % handle to local accept swap method
0051     %     rejectsw % handle to local reject swap method
0052     %     s1 % sample1
0053     %     s2 % sample2
0054     %     s1Col %s1 column index
0055     %     s2Col %s2 column index
0056     %     s1ColName % name of column in s1
0057     %     s2ColName % name of column in s2
0058     %     targVal % target value to match for 1 sample-to-value matching
0059     %     sumx1sq % sum of squares in sample 1
0060     %     sumx1 % sum of sample 1
0061     %     n1 % number of observations in sample 1
0062     %     sumx2sq % same for sample 2
0063     %     sumx2 % same for sample 2
0064     %     n2 % same for sample 2
0065     %     sumx1x2 % sum of product of x1 and x2, across all items
0066     %     swpsumx1sq % same as above for swap set
0067     %     swpsumx2sq % same as above for swap set
0068     %     swpsumx1 % same as above for swap set
0069     %     swpsumx2 % same as above for swap set
0070     %     swpsumx1x2 % same as above for swap set
0071     %     cor % the correlation between the two sets
0072     %     swpcor % the correlation if the swap was applied.
0073     %
0074     % METHODS
0075     %   function obj = softMatchCorrelConstraint(varargin) % constructor
0076     %   cost = initCost() - Calculates, saves, and returns the cost value for the current items in the sample.
0077     %   swCost = swapCost(targSample,targSampleIndex, feederdf,feederdfIndex) % Calculates the new cost if items from targSample and feederdf were swapped.
0078     %   initCorrel() FUNCTION calculates the correlation and initializes the parameters needed for local stat updates
0079     %   swCorrel(targSample,targSampleIndex, feederdf,feederdfIndex) % calculates the correlation if the swap were applied
0080     %   matchCorrel(x1,x2) % cost function minimized by reduced differences on the statistic
0081     %   acceptSwap() % generic acceptSwap function
0082     %   cost = rejectSwap() % generic reject function
0083     %   acceptSwapCorrel() % updates variables when the proposed swap is accepted for means
0084     %   rejectSwapCorrel() % resets swap variables
0085     %   constructSoftMatchCorrelConstraint(varargin)  % creates a constraint object
0086     %
0087     % METHODS (Static)
0088     %   softMatchCorrelConstraintInputParserMatchCorrel() % generates an input parser with parameter / value pairs and validators for the constructor args
0089     %
0090     % METHODS (Static, Access = private)
0091     %   p = parseMatchCorrelConstructorArgs(varargin) % parses the constructor args
0092 
0093     %% PROPERTIES
0094     properties
0095         stat % the statistic to calculate (correlation)
0096         comparison % handle to specific comparison calculator
0097         initStats % handle to global stat initialization method
0098         swStats % handle to local stat update method
0099         acceptsw % handle to local accept swap method
0100         rejectsw % handle to local reject swap method
0101         s1 % sample1
0102         s2 % sample2
0103         s1Col %s1 column index
0104         s2Col %s2 column index
0105         s1ColName % name of column in s1
0106         s2ColName % name of column in s2
0107         targVal % target value to match for 1 sample-to-value matching
0108         sumx1sq % sum of squares in sample 1
0109         sumx1 % sum of sample 1
0110         n1 % number of observations in sample 1
0111         sumx2sq % same for sample 2
0112         sumx2 % same for sample 2
0113         n2 % same for sample 2
0114         sumx1x2 % sum of product of x1 and x2, across all items
0115         swpsumx1sq % same as above for swap set
0116         swpsumx2sq % same as above for swap set
0117         swpsumx1 % same as above for swap set
0118         swpsumx2 % same as above for swap set
0119         swpsumx1x2 % same as above for swap set
0120         cor % the correlation between the two sets
0121         swpcor % the correlation if the swap was applied.
0122         
0123     end
0124     
0125     
0126     %% METHODS
0127     methods
0128         
0129         %% softMatchCorrelConstraint CONSTRUCTOR
0130         function obj = softMatchCorrelConstraint(varargin)
0131             % Creates a soft distance constraint.  See the parse
0132             % constructor args functions for parameters.
0133             
0134             p = inputParser;
0135             p.addParamValue('fnc','null', ...
0136                 @(fnc)any(strcmp({'matchCorrel'},fnc)));
0137             p.KeepUnmatched = true;
0138             p.parse(varargin{:});
0139             
0140             if any(strcmp(p.Results.fnc,'matchCorrel'))
0141                 % can create the matchCorrel constraint
0142                 obj = constructSoftMatchCorrelConstraint(obj,varargin);
0143             else
0144                 error(['Could not create a soft constraint with <fnc>: ', ...
0145                         p.Results.fnc]); 
0146             end
0147             
0148             obj.cost = NaN;
0149             obj.swCost = NaN;
0150             
0151             
0152             verbosePrint('Soft matchCorrel Constraint has been created', ...
0153                     'softMatchCorrelConstraint_Constructor_endObjCreation');
0154                     
0155         end %constructor
0156         
0157         
0158         %% cost = initCost() METHOD
0159         function cost = initCost(obj)
0160             % Calculates, saves, and returns the cost value for the current items in the sample.
0161             %
0162             %CALL:
0163             %   <softDistanceConstraint>.initCost();
0164             %
0165             %SYNOPSIS:
0166             % Calculates the cost for the current items in the sample based
0167             % on the specified constraint.  This calculation is done on the
0168             % global dataset, rather than using the differential local
0169             % computation used when calculating swap costs.
0170             %
0171           
0172             %init the stats, then compare them.  Return the calculated cost
0173             obj = obj.initStats(); 
0174             cost = obj.comparison(obj.targVal,obj.cor); %where we match the correlation...
0175             
0176             obj.swpcor = NaN;
0177             obj.swpsumx1sq = NaN;
0178             obj.swpsumx2sq = NaN;
0179             obj.swpsumx1 = NaN;
0180             obj.swpsumx2 = NaN;
0181             obj.swpsumx1x2 = NaN;
0182             
0183             obj.cost = cost;
0184             obj.swCost = NaN;
0185         end
0186         
0187         %%  swCost(targSample,targSampleIndex, feederdf,feederdfIndex) METHOD
0188         function swCost = swapCost(obj,targSample,targSampleIndex, feederdf,feederdfIndex)
0189             % Calculates the new cost if items from targSample and feederdf were swapped.
0190             %
0191             %By definition, if this method is called it means that at least
0192             % one of the two swap objects is implicated in this function
0193             %
0194             %PARAMETERS:
0195             %   targSample - the target sample (i.e., the object that will call it's swapSample() method if a swap later occurs).
0196             %   targSampleIndex - row index of item to swap
0197             %   feederdf - dataframe (sample/pop) containin the other item to swap
0198             %   feederdfIndex - row index of item to swap.
0199                        
0200            if (obj.s1 ~= targSample && obj.s2 ~= targSample ... 
0201                    && obj.s1 ~= feederdf && obj.s2  ~= feederdf)
0202                error('swCost called, but no sample part of this cost function');
0203            end
0204 
0205            
0206            % update the stats, then calculate cost of new stats
0207            obj.swStats(targSample,targSampleIndex, feederdf,feederdfIndex);
0208  
0209 
0210             swCost = obj.comparison(obj.targVal,obj.swpcor);
0211             obj.swCost = swCost;
0212               
0213         end
0214 
0215         %% obj = initCorrel() METHOD
0216         function obj = initCorrel(obj)
0217             %  calculates the correlation and initializes the parameters
0218             %  needed for local stat updates
0219            
0220             obj.sumx1sq = sum((obj.s1.zdata{obj.s1Col}).^2);
0221             obj.sumx1 = sum((obj.s1.zdata{obj.s1Col}));
0222             obj.n1 = length(obj.s1.zdata{obj.s1Col});
0223             
0224             obj.sumx2sq = sum((obj.s2.zdata{obj.s2Col}).^2);
0225             obj.sumx2 = sum((obj.s2.zdata{obj.s2Col}));
0226             obj.n2 = length(obj.s2.zdata{obj.s2Col});
0227             
0228             obj.sumx1x2 = (obj.s1.zdata{obj.s1Col})' * (obj.s2.zdata{obj.s2Col});
0229             
0230             ssx1 = obj.sumx1sq - ((obj.sumx1)^2)/obj.n1;
0231             ssx2 = obj.sumx2sq - ((obj.sumx2)^2)/obj.n2;
0232             
0233             spx1x2 = obj.sumx1x2 - obj.sumx1*obj.sumx2/obj.n1;
0234             
0235             
0236             if(ssx1 == 0 && ssx2 == 0) % no variance in either condition, define correlation as being perfect in this case
0237                 obj.cor = 1;
0238             elseif(ssx1 == 0 || ssx2 == 0)
0239                 obj.cor = 0;
0240             else % compute correlation normally
0241                 obj.cor = spx1x2/(sqrt(ssx1)*sqrt(ssx2));
0242             end
0243                        
0244             obj.swpcor = NaN;
0245             obj.swpsumx1sq = NaN;
0246             obj.swpsumx2sq = NaN;
0247             obj.swpsumx1 = NaN;
0248             obj.swpsumx2 = NaN;
0249             obj.swpsumx1x2 = NaN;
0250         end
0251         
0252         
0253         %% swCorrel(targSample,targSampleIndex,feederdf,feederdfIndex) METHOD
0254         function swCorrel(obj,targSample,targSampleIndex, feederdf,feederdfIndex)
0255             % calculates the correlation if the swap were applied
0256             obj.swpsumx1sq = obj.sumx1sq;
0257             obj.swpsumx2sq = obj.sumx2sq;
0258             obj.swpsumx1 = obj.sumx1;
0259             obj.swpsumx2 = obj.sumx2;
0260             obj.swpsumx1x2 = obj.sumx1x2;
0261                        
0262             %NOTE: if both target and feeder are identical, swapping items
0263             %within those two samples will not change the correlation.
0264             %This could be leveraged to simplify the conditionalization.
0265             
0266              if targSample == obj.s1
0267                 %must update 2 params %first, take out the old observation, then add in thew new
0268                 obj.swpsumx1sq = obj.swpsumx1sq - (targSample.zdata{obj.s1Col}(targSampleIndex))^2;
0269                 obj.swpsumx1 = obj.swpsumx1 - (targSample.zdata{obj.s1Col}(targSampleIndex));                
0270                 obj.swpsumx1sq = obj.swpsumx1sq + (feederdf.zdata{obj.s1Col}(feederdfIndex))^2;
0271                 obj.swpsumx1 = obj.swpsumx1 + (feederdf.zdata{obj.s1Col}(feederdfIndex));
0272              end
0273              
0274              if targSample == obj.s2
0275                 obj.swpsumx2sq = obj.swpsumx2sq - (targSample.zdata{obj.s2Col}(targSampleIndex))^2;
0276                 obj.swpsumx2 = obj.swpsumx2 - (targSample.zdata{obj.s2Col}(targSampleIndex));                
0277                 obj.swpsumx2sq = obj.swpsumx2sq + (feederdf.zdata{obj.s2Col}(feederdfIndex))^2;
0278                 obj.swpsumx2 = obj.swpsumx2 + (feederdf.zdata{obj.s2Col}(feederdfIndex)); 
0279              end
0280             
0281           
0282             if feederdf == obj.s1
0283                 obj.swpsumx1sq = obj.swpsumx1sq -  (feederdf.zdata{obj.s1Col}(feederdfIndex))^2;
0284                 obj.swpsumx1 = obj.swpsumx1 - (feederdf.zdata{obj.s1Col}(feederdfIndex));                
0285                 obj.swpsumx1sq = obj.swpsumx1sq + (targSample.zdata{obj.s1Col}(targSampleIndex))^2;
0286                 obj.swpsumx1 = obj.swpsumx1 + (targSample.zdata{obj.s1Col}(targSampleIndex));                   
0287             end
0288             
0289             if feederdf == obj.s2
0290                 obj.swpsumx2sq = obj.swpsumx2sq -  (feederdf.zdata{obj.s2Col}(feederdfIndex))^2;
0291                 obj.swpsumx2 = obj.swpsumx2 - (feederdf.zdata{obj.s2Col}(feederdfIndex));                
0292                 obj.swpsumx2sq = obj.swpsumx2sq + (targSample.zdata{obj.s2Col}(targSampleIndex))^2;
0293                 obj.swpsumx2 = obj.swpsumx2 + (targSample.zdata{obj.s2Col}(targSampleIndex)); 
0294             end  
0295 
0296             % Special overrides
0297             
0298             if targSample == obj.s1 && targSample ~= obj.s2
0299                 obj.swpsumx1x2 = obj.swpsumx1x2 - (targSample.zdata{obj.s1Col}(targSampleIndex)) * obj.s2.zdata{obj.s2Col}(targSampleIndex);
0300                 obj.swpsumx1x2 = obj.swpsumx1x2 + (feederdf.zdata{obj.s1Col}(feederdfIndex))     * obj.s2.zdata{obj.s2Col}(targSampleIndex);
0301             elseif targSample == obj.s2 && targSample ~= obj.s1               
0302                 obj.swpsumx1x2 = obj.swpsumx1x2 - (targSample.zdata{obj.s2Col}(targSampleIndex)) * obj.s1.zdata{obj.s1Col}(targSampleIndex);
0303                 obj.swpsumx1x2 = obj.swpsumx1x2 + (feederdf.zdata{obj.s2Col}(feederdfIndex))     * obj.s1.zdata{obj.s1Col}(targSampleIndex);                
0304             elseif targSample == obj.s1 && targSample == obj.s2
0305                 obj.swpsumx1x2 = obj.swpsumx1x2 - (obj.s1.zdata{obj.s1Col}(targSampleIndex)) * obj.s2.zdata{obj.s2Col}(targSampleIndex);
0306                 obj.swpsumx1x2 = obj.swpsumx1x2 + (feederdf.zdata{obj.s1Col}(feederdfIndex))     * feederdf.zdata{obj.s2Col}(feederdfIndex);                
0307             end
0308             
0309             
0310              if feederdf == obj.s1 && feederdf ~= obj.s2
0311                 obj.swpsumx1x2 = obj.swpsumx1x2 - (feederdf.zdata{obj.s1Col}(feederdfIndex))     * obj.s2.zdata{obj.s2Col}(feederdfIndex);
0312                 obj.swpsumx1x2 = obj.swpsumx1x2 + (targSample.zdata{obj.s1Col}(targSampleIndex)) * obj.s2.zdata{obj.s2Col}(feederdfIndex); 
0313              elseif feederdf == obj.s2 && feederdf ~= obj.s1               
0314                 obj.swpsumx1x2 = obj.swpsumx1x2 - (feederdf.zdata{obj.s2Col}(feederdfIndex))     * obj.s1.zdata{obj.s1Col}(feederdfIndex);
0315                 obj.swpsumx1x2 = obj.swpsumx1x2 + (targSample.zdata{obj.s2Col}(targSampleIndex)) * obj.s1.zdata{obj.s1Col}(feederdfIndex); 
0316                elseif feederdf == obj.s1 && feederdf == obj.s2
0317                 obj.swpsumx1x2 = obj.swpsumx1x2 - (obj.s1.zdata{obj.s1Col}(feederdfIndex)) * obj.s2.zdata{obj.s2Col}(feederdfIndex);
0318                 obj.swpsumx1x2 = obj.swpsumx1x2 + (targSample.zdata{obj.s1Col}(targSampleIndex))     * targSample.zdata{obj.s2Col}(targSampleIndex);                
0319              end           
0320             
0321             if((targSample ~= feederdf) && ...
0322                     (targSample == obj.s1 || targSample == obj.s2) && ...
0323                     (feederdf == obj.s1 || feederdf == obj.s2) && ...
0324                     targSampleIndex == feederdfIndex  && ...
0325                     obj.s1Col == obj.s2Col)
0326                 obj.swpsumx1x2 = obj.sumx1x2;
0327             end
0328                 
0329                 
0330            if((targSample ~= feederdf) && ...
0331                     (targSample == obj.s1 || targSample == obj.s2) && ...
0332                     (feederdf == obj.s1 || feederdf == obj.s2) && ...
0333                     targSampleIndex == feederdfIndex  && ...
0334                     obj.s1Col ~= obj.s2Col)
0335                 
0336                     obj.swpsumx1x2 = obj.sumx1x2 - obj.s1.zdata{obj.s1Col}(targSampleIndex) * obj.s2.zdata{obj.s2Col}(feederdfIndex) + ...
0337                         obj.s2.zdata{obj.s1Col}(feederdfIndex) * obj.s1.zdata{obj.s2Col}(targSampleIndex);             
0338            end 
0339 
0340             
0341             swpssx1 = obj.swpsumx1sq - ((obj.swpsumx1)^2)/obj.n1;
0342             swpssx2 = obj.swpsumx2sq - ((obj.swpsumx2)^2)/obj.n2;
0343             
0344             swpspx1x2 = obj.swpsumx1x2 - obj.swpsumx1*obj.swpsumx2/obj.n1;
0345             
0346             
0347             if(swpssx1 == 0 && swpssx2 == 0) % no variance in either condition, define correlation as being perfect in this case
0348                 obj.swpcor = 1;
0349             elseif(swpssx1 == 0 || swpssx2 == 0)
0350                 obj.swpcor = 0;
0351             else % compute correlation normally
0352                 obj.swpcor = swpspx1x2/(sqrt(swpssx1)*sqrt(swpssx2));
0353             end       
0354             
0355             
0356         end
0357         
0358 
0359         
0360         %% matchCorrel() METHOD
0361         function cost = matchCorrel(obj,x1,x2)
0362             % cost function minimized by reduced differences on the statistic
0363             cost = ((abs(x2-x1)/2)^obj.exp)*obj.weight;
0364             
0365         end % matchCorrel
0366         
0367         
0368         %% cost = acceptSwap() METHOD
0369         function cost = acceptSwap(obj)        
0370             %generic acceptSwap function
0371             obj.acceptsw();
0372             cost = acceptSwap@genericConstraint(obj);
0373         end
0374         
0375         %% cost = rejectSwap()  METHOD
0376         function cost = rejectSwap(obj)
0377             %generic reject function
0378             obj.rejectsw();
0379             cost = rejectSwap@genericConstraint(obj);
0380         end
0381         
0382         %% acceptSwapCorrel() METHOD
0383         function acceptSwapCorrel(obj)
0384             % updates variables when the proposed swap is accepted for
0385             % means
0386             
0387             if(isnan(obj.swpcor))
0388                 %do nothing, this method does not need to update
0389             else
0390             obj.sumx1sq = obj.swpsumx1sq;
0391             obj.sumx2sq = obj.swpsumx2sq;
0392             obj.sumx1 = obj.swpsumx1;
0393             obj.sumx2 = obj.swpsumx2;
0394             obj.sumx1x2 = obj.swpsumx1x2;
0395             obj.cor = obj.swpcor;
0396             
0397             
0398             obj.rejectSwapCorrel();
0399             
0400             end
0401         end      
0402         
0403         %% rejectSwapCorrel() METHOD
0404         function rejectSwapCorrel(obj)
0405             %resets swap variables
0406             obj.swpcor = NaN;
0407             obj.swpsumx1sq = NaN;
0408             obj.swpsumx2sq = NaN;
0409             obj.swpsumx1 = NaN;
0410             obj.swpsumx2 = NaN;
0411             obj.swpsumx1x2 = NaN;                        
0412         end
0413         
0414         %% obj = constructSoftMatchCorrelConstraint(varargin) METHOD
0415         function obj = constructSoftMatchCorrelConstraint(obj,varargin)
0416             % creates a constraint object
0417             % CONSTRUCTOR - Creates a softDistanceConstraint object
0418             %
0419             % CALL:
0420             % softDistanceConstraint(varargin<defined below>)
0421             %
0422             % PARAMETERS:
0423             % REQUIRED:
0424             %   'sosObj'/sos object - the SOS object the constraint will be linked to, and which contains the samples the constraint operates on.
0425             %   'constraintType'/'soft' - the type of contraint - must be 'soft'
0426             %   'fnc'/'matchCorrel' the distance function to create.
0427             %   'sample1'/sample - the first sample
0428             %   'sample2'/sample - the second sample
0429             %   's1ColName'/string - name of column in 1st sample
0430             %   's2ColName'/string - name of column in 2nd sample
0431             %   'targVal'/integer [-1,1] - target correlation to match
0432 
0433             % OPTIONAL:
0434             %   'exponent'/numeric - defaults to 2 (quadratic difference)
0435             %   'weight'/numeric - defaults to 1 (equal weighting of all soft costs)
0436             %
0437             % EXAMPLE:
0438             %     c2 = mySOS.addConstraint('sosObj',mySOS,'name','matchFreqCorrelConstraint','constraintType', ...
0439             %     'soft','fnc','matchCorrel',...
0440             %     'sample1',mySample1,'s1ColName','KFfrequency', ...
0441             %     'sample2',mySample2,'s2ColName','KFfrequency','targVal',1,'exponent',2,'weight',1);
0442             
0443                         
0444             p = softMatchCorrelConstraint.parseMatchCorrelConstructorArgs(varargin{:});
0445             
0446             if(p.Results.sosObj.containsSample(p.Results.sample1) == false)
0447                 error('Cannot create soft distance constraint: sos Object does not contain the sample1');
0448             end
0449             
0450             if(p.Results.sosObj.containsSample(p.Results.sample2) == false)
0451                 error('Cannot create soft distance constraint: sos Object does not contain sample2');
0452             end
0453             
0454             
0455             col1 = p.Results.sample1.colName2colNum(p.Results.s1ColName);           
0456             if(col1 == -1)
0457                 error('Specified column name not found in sample1');
0458             end
0459             
0460             if(strcmp(p.Results.sample1.format{col1},'%f') == 0)
0461                 error('Specified column is not of numeric (%f) format, so cannot use as soft constraint');
0462             end           
0463                        
0464             col2 = p.Results.sample2.colName2colNum(p.Results.s2ColName);            
0465             if(col2 == -1)
0466                 error('Specified column name not found in sample');
0467             end
0468             
0469             if(strcmp(p.Results.sample2.format{col2},'%f') == 0)
0470                 error('Specified column is not of numeric (%f) format, so cannot use as soft constraint; 2nd sample');
0471             end           
0472             
0473             %if the lengths are not going to be identical, do not run the
0474             %correlation.  The init and swap methods will ensure
0475             %that if practically the data are NaN, the optimization will
0476             %stop.
0477 
0478             if length(p.Results.sample1.n) ~= length(p.Results.sample2.n)
0479                 error('Sample sizes must be equal if using paired matching');
0480             end
0481 
0482             % Assign the comparison function appropriate for the constraint
0483             
0484             %ASSIGN HANDLE TO STAT CALCULATION METHOD
0485 
0486             obj.initStats = @obj.initCorrel;
0487             obj.swStats = @obj.swCorrel;
0488             obj.acceptsw = @obj.acceptSwapCorrel;
0489             obj.rejectsw = @obj.rejectSwapCorrel;
0490             
0491             % ASSIGN HANDLE TO DIFFERENCE COMPARISON METHOD
0492             % Group differences:
0493             if(strcmp(p.Results.fnc,'matchCorrel'))
0494                 obj.comparison = @obj.matchCorrel;
0495             else
0496                 error('function not yet supported');
0497             end
0498             
0499             % parent properties
0500             obj.sosObj = p.Results.sosObj;
0501             obj.constraintType = p.Results.constraintType;
0502             obj.fnc = p.Results.fnc;
0503             
0504             
0505             obj.weight = p.Results.weight;
0506             obj.exp = p.Results.exponent;  
0507             
0508             if(p.Results.targVal < -1 || p.Results.targVal > 1 || isnan(p.Results.targVal))
0509                 error('Target correlation value must be a number -1 <= targ <= 1');
0510             end
0511             
0512             obj.targVal = p.Results.targVal;
0513             
0514             obj.s1 = p.Results.sample1;
0515             obj.s2 = p.Results.sample2;
0516             obj.s1Col = col1;
0517             obj.s2Col = col2;           
0518             obj.s1ColName = p.Results.s1ColName;
0519             obj.s2ColName = p.Results.s2ColName;           
0520             
0521             % add the name and the label
0522             obj.label = [obj.constraintType,'_',obj.fnc,'_',...
0523                     obj.targVal,'_',...
0524                     obj.s1.name,'_',obj.s1ColName,'_',...
0525                     obj.s2.name,'_',obj.s2ColName,'_',...
0526                     'p','1','_w',...
0527                     num2str(obj.weight),'_e',num2str(obj.exp)];              
0528             if any(strcmp(p.UsingDefaults,'name'))                 
0529                 obj.name = obj.label;
0530             else
0531                  obj.name = p.Results.name;  
0532             end               
0533         end %construct2SampleSoftDistanceConstraint
0534         
0535         
0536     end
0537     
0538     methods (Static)
0539         %% p = softMatchCorrelConstraintInputParserMatchCorrel() STATIC METHOD
0540         function p = softMatchCorrelConstraintInputParserMatchCorrel()
0541             % generates an input parser with parameter / value pairs and validators for the constructor args
0542             %
0543             % See constructor help/doc for more details
0544             
0545             p = inputParser;
0546 
0547             %NOTE: though these technically are 'optional' according to
0548             %MATLAB's definition of what an input parser does, the fact
0549             %that most of their default values will fail validation in all cases
0550             %makes them de facto required parameters.
0551             
0552             p.addParamValue('sosObj','null',@(sosObj)strcmp(class(sosObj),'sos'));
0553             p.addParamValue('constraintType', 'null', ...
0554                 @(constraintType)any(strcmp({'soft'},constraintType)));
0555             p.addParamValue('fnc','null', ...
0556                  @(fnc)any(strcmp({'matchCorrel'},fnc)));
0557             p.addParamValue('sample1','null',@(sample1)strcmp(class(sample1),'sample'));
0558             p.addParamValue('sample2','null',@(sample2)strcmp(class(sample2),'sample'));
0559             p.addParamValue('s1ColName','',@(s1ColName)ischar(s1ColName));
0560             p.addParamValue('s2ColName','',@(s2ColName)ischar(s2ColName));
0561             p.addParamValue('targVal',NaN,@(targVal)isnumeric(targVal));
0562             p.addParamValue('exponent',2,@(exponent)isnumeric(exponent));
0563             p.addParamValue('weight',1,@(weight)isnumeric(weight));
0564             p.addParamValue('name','noname',@(name)ischar(name));
0565             
0566         end
0567         
0568         
0569     end
0570     
0571     methods (Static, Access = private)
0572         
0573         %% p = parseMatchCorrelConstructorArgs(varargin) STATIC PRIVATE FUNCTION
0574         function p = parseMatchCorrelConstructorArgs(varargin)
0575             % parses the constructor args
0576             %
0577             % See constructor help/doc for more info
0578                         
0579             varargin = varargin{1};
0580             p = softMatchCorrelConstraint.softMatchCorrelConstraintInputParserMatchCorrel();
0581             p.parse(varargin{:});
0582         end
0583         
0584     end
0585     
0586     
0587 end

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