gatherValidityConeIneq

PURPOSE ^

generate the inequality constraints for valid polytopes in h-space

SYNOPSIS ^

function result = gatherValidityConeIneq(facetNormalMatrix, zerotol, verbose)

DESCRIPTION ^

 generate the inequality constraints for valid polytopes in h-space

 THIS FUNCTION IS NO USER FUNCTION.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function result = gatherValidityConeIneq(facetNormalMatrix, zerotol, verbose)
0002 % generate the inequality constraints for valid polytopes in h-space
0003 %
0004 % THIS FUNCTION IS NO USER FUNCTION.
0005 
0006 % The elk-library: convex geometry applied to crystallization modeling.
0007 %   Copyright (C) 2012 Alexander Reinhold
0008 %
0009 % This program is free software: you can redistribute it and/or modify it
0010 %   under the terms of the GNU General Public License as published by the
0011 %   Free Software Foundation, either version 3 of the License, or (at your
0012 %   option) any later version.
0013 %
0014 % This program is distributed in the hope that it will be useful, but
0015 %   WITHOUT ANY WARRANTY; without even the implied warranty of
0016 %   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017 %   General Public License for more details.
0018 %
0019 % You should have received a copy of the GNU General Public License along
0020 %   with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 
0022 %% info
0023 % This function generates inequality constraints in form of a
0024 %   H-representation in the h-space that is associated with the provided
0025 %   matrix of facet normals. For valid solutions the polytope is not empty
0026 %   (at least contains a single point) and all support planes have a
0027 %   nonempty intersection with the given polytope. The formal condition is
0028 %   then: the polytope is valid for:
0029 %     inequalityMatrix * h <= 0
0030 % This function also returns in cone.responsibleFacetMatrix a matrix that
0031 %   stores pairs of inequality indices (first column) and positive indices
0032 %   to the facet that grows out at this boundary. Negative indices are
0033 %   entered if the dissolution of that facet triggers an empty polytope.
0034 
0035 %% Input handling
0036 % some statistical numbers
0037 nDim = size(facetNormalMatrix, 2);
0038 nFacet = size(facetNormalMatrix, 1);
0039 
0040 %% initialize matrices
0041 % generate tuples to check
0042 tupleMatrix = obtainOrderedSetMatrix(nFacet, nDim+1);
0043 % using a sparse matrix was tested, but does not pay off.
0044 inequalityMatrix = zeros(nDim, nFacet);
0045 responsibleFacetVector = nan(nDim, 1);
0046 thisInequalityIndex = 0;
0047 
0048 %% start loop for all tuples
0049 if verbose,fprintf('......');end
0050 for iTuple = 1:size(tupleMatrix, 1)
0051     if verbose && mod(iTuple, 1000) == 1
0052         fprintf('\b\b\b\b\b\b%5.1f%%', iTuple / size(tupleMatrix, 1)*100);
0053     end
0054     
0055     thisTuple = tupleMatrix(iTuple, :);
0056      
0057     % find the n-tuple where the (n+1) element is in the positive OR
0058     %   negative cone and the cone is full-dimensional. The last element is
0059     %   contained in the positive span, if:
0060     %     [a(1), .., a(n)] * lam = a(n+1)  and  lam >= 0
0061     %   and in the negative span for lam <= 0.
0062     coneType = 0; % (not found)
0063     
0064     for iFacet = thisTuple
0065         thisIndexVector = thisTuple(thisTuple ~= iFacet);
0066         [u,s,v] = svd(facetNormalMatrix(thisIndexVector, :));
0067         s = diag(s);
0068         isNotZeroVector = (s <= -zerotol) | (s >= zerotol);
0069         if all(isNotZeroVector)
0070             s(isNotZeroVector) = 1./s(isNotZeroVector);
0071             lambda = u * diag(s) * v' * facetNormalMatrix(iFacet, :)';
0072                            
0073             if all(lambda >= -zerotol)
0074                 % tuplet combination found
0075                 thisTuple = [thisIndexVector iFacet];
0076                 coneType = 1; % (positive cone)
0077                 break
0078             elseif all(lambda <= zerotol)
0079                 % tuplet combination found
0080                 thisTuple = [thisIndexVector iFacet];
0081                 coneType = -1; % (negative cone)
0082                 break
0083             end
0084         end
0085     end
0086     
0087     %! Info: There is an alternative implementation, that uses fewer lines
0088     %    of code and might be quicker to grasp, put it is not faster:
0089     
0090 %     % switch some warnings to errors to detect lower rank during mldivide
0091 %     warningStateOne = warning('error', 'MATLAB:nearlySingularMatrix');
0092 %     warningStateTwo = warning('error', 'MATLAB:singularMatrix');
0093 %
0094 %     for iFacet = thisTuple
0095 %         thisIndexVector = thisTuple(thisTuple ~= iFacet);
0096 %         % use mldivide directly and catch low rank
0097 %         try
0098 %               lambda = facetNormalMatrix(thisIndexVector, :)' \ ...
0099 %                 facetNormalMatrix(iFacet, :)';
0100 %         catch
0101 %               continue
0102 %         end
0103 %         %! Assignement as above!
0104 %     end
0105 %     % reset warning states
0106 %     warning(warningStateOne);
0107 %     warning(warningStateTwo);
0108     %/
0109     
0110     % result: we have evaluated the tuple to form a negative cone
0111     %   (coneType=-1), positve cone (coneType=1) or none of these
0112     %   (coneType=0). The array thisIndexVector also have the indces to the
0113     %   cone-forming facet normals in the first three elements (that
0114     %   defines the vertex). It contains the forth facet as the last
0115     %   element.
0116     
0117     % continue with next tuple (this tuple beeing invalid) or continue with
0118     %   checking locality
0119     if coneType == 0
0120         %disp([num2str(iTuple) ': no full dimensional positive/negative span'])
0121         %thisNormalMatrix
0122         continue
0123     else
0124         % this tuple now contains the same (n+1) normal vectors that we
0125         %   started with, but the first n generate the positive/negative
0126         %   cone where the (n+1)st element is an element of.
0127         thisNormalMatrix = facetNormalMatrix(thisTuple, :);
0128     end
0129     
0130     % the disabled code represents improvements by Karl (1995, "local
0131     %   conditions") that were found to give no significant improvement.
0132 %     % check if the n-tuple is local
0133 %     % Another facet normal is part of the positive cone, whenever we have:
0134 %     %   [a(1), .., a(n)] * lam = a(i)  and  lam >= 0
0135 %     % which can be rewritten to:
0136 %     %   inv([a(1), .., a(n)]) * a(i) >= 0
0137 %     % the same facet normal is part of the negative cone, for:
0138 %     %   -inv([a(1), .., a(n)]) * a(i) >= 0
0139 %     notInTuple = 1:nFacet;
0140 %     notInTuple(thisTuple) = [];
0141     if coneType == 1
0142         testMatrix = inv(thisNormalMatrix(1:nDim, :)');
0143     else
0144         testMatrix = inv(thisNormalMatrix(1:nDim, :)');
0145     end
0146 %     exitFlag = 0;
0147 %     for iFacet = notInTuple
0148 %         lambda = testMatrix * facetNormalMatrix(iFacet, :)';
0149 %         % as this is a "we save equations" condition, less samples should
0150 %         %   be valid to fulfill this condition.
0151 %         if all(lambda >= zerotol)
0152 %             % there is another facet in the positive/negative span. Hence,
0153 %             %   the tuple is not local.
0154 %             exitFlag = 1;
0155 %             break
0156 %         end
0157 %     end
0158 %     if exitFlag
0159 %         %disp([num2str(iTuple) ': not local positive span'])
0160 %         %thisNormalMatrix
0161 %         continue;
0162 %     else
0163 %          %disp([num2str(iTuple) ': add constraint'])
0164 %     end
0165     
0166     % now, add the condition
0167     % from Karl (1995) we have:
0168     %   a(n+1)' * inv([a(1)'; ...; a(n)']) * [h(1); ..; h(n)] >= h(n+1)
0169     % which is equal to:
0170     %   (inv([a(1), ..., a(n)]) * a(n+1))' * [h(1); ..; h(n)] >= h(n+1)
0171     % where the inverse of the second equation is the testMatrix from above
0172     % for positive cones.
0173     % if coneType == -1
0174     %     testMatrix = -1*testMatrix;
0175     % end
0176     % Further more, for negative cones the inequality sign changes so that
0177     %   we have for negative cones:
0178     %     (inv([a(1), ..., a(n)]) * a(n+1))' * [h(1); ..; h(n)] - h(n+1) <= 0
0179     %
0180     % The common H-representation of the cone uses <= instead of >= so that
0181     %   for the positive cone, we obtain:
0182     %   -1*(inv([a(1), ..., a(n)]) * a(n+1))' * [h(1); ..; h(n)] + h(n+1) <= 0
0183     
0184     thisInequalityIndex = thisInequalityIndex + 1;
0185      
0186     % the following equals inv([a(1), ..., a(n)]) * a(n+1)
0187     coefficientVector = (testMatrix * thisNormalMatrix(end, :)')';
0188     
0189     if coneType == 1
0190         inequalityMatrix(thisInequalityIndex, thisTuple(end)) = 1;
0191         inequalityMatrix(thisInequalityIndex, thisTuple(1:(end-1))) = ...
0192            -1 * coefficientVector;
0193         responsibleFacetVector(thisInequalityIndex) = thisTuple(end);
0194     elseif coneType == -1 
0195         inequalityMatrix(thisInequalityIndex, thisTuple(end)) = -1;
0196         inequalityMatrix(thisInequalityIndex, thisTuple(1:(end-1))) = ...
0197            coefficientVector;
0198         responsibleFacetVector(thisInequalityIndex) = -1*thisTuple(end);
0199     else
0200         error('elk:decomposition:numericalError', ...
0201             'cone is neither positive nor negative. This should not happen');
0202     end
0203     
0204     % reserve more space in sparce matrix, if required
0205     if thisInequalityIndex >= size(inequalityMatrix, 1)
0206         % allocate more space
0207         estimatedRowSize = thisInequalityIndex / iTuple * size(tupleMatrix, 1);
0208         % round and take some more
0209         estimatedRowSize = round(estimatedRowSize) + nDim;
0210         % enlarge matrix
0211         inequalityMatrix(estimatedRowSize, :) = 0;
0212         responsibleFacetVector((end+1):estimatedRowSize) = nan;
0213     end
0214     
0215 end
0216 if verbose, fprintf('\b\b\b\b\b\b');end
0217 
0218 %% remove the reservated rows
0219 inequalityMatrix((thisInequalityIndex+1):end, :) = [];
0220 responsibleFacetVector((thisInequalityIndex+1):end, :) = [];
0221 
0222 result.A = inequalityMatrix;
0223 result.responsibleFacetVector = responsibleFacetVector;

Generated on Sat 18-Jul-2015 16:45:31 by m2html © 2005