decomposeMinkowskiHrep

PURPOSE ^

decompose the given polytope into Minkowski summands

SYNOPSIS ^

function summandMatrix = decomposeMinkowskiHrep(hrep, varargin)

DESCRIPTION ^

 decompose the given polytope into Minkowski summands

 Syntax: hrepList = decomposeMinkowskiHrep(hrep)

 THIS FUNCTION IS NO USER FUNCTION.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function summandMatrix = decomposeMinkowskiHrep(hrep, varargin)
0002 % decompose the given polytope into Minkowski summands
0003 %
0004 % Syntax: hrepList = decomposeMinkowskiHrep(hrep)
0005 %
0006 % THIS FUNCTION IS NO USER FUNCTION.
0007 
0008 % ..event though, this function was originally designed to be. It might be
0009 %   included in the polytope subsection in some later release. The main
0010 %   missing feature is the generation of the summands itself.
0011 
0012 % Draft documentation:
0013 %
0014 % Note that Minkowski decomposition is not unique. The result of this
0015 %   algorithm gives indecomposable polytopes in hrepList so that it holds:
0016 %       hrep = addMinkowskiPolytope(hrepList{1}, ..., hrepList{n}).
0017 %   And because every hrepVector contains the original full matrix of facet
0018 %   normals this is equivalent to:
0019 %       hrep.h = hrepList{1}.h + .. + hrepList{n}.h
0020 %
0021 % The following options can be appended:
0022 %   zerotol  - tolerance for singularities  and close to zero operations.
0023 %              Default: 1e-13
0024 %   verbose  - switch on (1) and off (0) some verbosity. Default: 0
0025 %   matrix   - instead of a lost of H-representations a matrix with the
0026 %              facet distances is returned (1). One row for each summand,
0027 %              one column for each facet in hrep.A. Default: 0
0028 %   result   - This algorithm is also the main component for the
0029 %              decomposition of the constrained h-space so that with the
0030 %              option set to 'indecomposable', all indecomposable summands
0031 %              are returned. Default: 'summand'
0032 %
0033 % See also: addMinkowskiPolytope, addMinkowskiHrep
0034 
0035 % The elk-library: convex geometry applied to crystallization modeling.
0036 %   Copyright (C) 2012 Alexander Reinhold
0037 %
0038 % This program is free software: you can redistribute it and/or modify it
0039 %   under the terms of the GNU General Public License as published by the
0040 %   Free Software Foundation, either version 3 of the License, or (at your
0041 %   option) any later version.
0042 %
0043 % This program is distributed in the hope that it will be useful, but
0044 %   WITHOUT ANY WARRANTY; without even the implied warranty of
0045 %   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0046 %   General Public License for more details.
0047 %
0048 % You should have received a copy of the GNU General Public License along
0049 %   with this program.  If not, see <http://www.gnu.org/licenses/>.
0050 
0051 %% sources
0052 % The original sketch (and proof) of the algorithm can be found in Meyer,
0053 %   1974: "Indecomposable Polytopes". It is modified and presented again in
0054 %   Mount and Silverman, 1991: "Combinatorial and Computational Aspects of
0055 %   Minkowski Decomposition". The algorithm here is adopted for constrained
0056 %   Minkowski decomposition. It also has an easy to implement approach to
0057 %   eliminate the degrees of freedom by translation. In Meyer 1974 the
0058 %   Steiner-point was used.
0059 
0060 %% Input
0061 % some numbers
0062 nDim = size(hrep.A, 2);
0063 nFacet = size(hrep.A, 1);
0064 
0065 % map options
0066 [zerotol, verbose, outputResult, outputMatrix, constraintMatrix] = mapOption(varargin, ...
0067     'zerotol', elkZerotol, ...
0068     'verbose', 0, ...
0069     'result', 'summand',...
0070     'matrix', 0, ...
0071     'constraint', zeros(1, nFacet));
0072 
0073 % check polytope vs. constraint
0074 if ~isAllZero(constraintMatrix * hrep.h, zerotol)
0075     error('elk:decomposition:inputError', ...
0076         'The input polytope must fulfill the provided constraints');
0077 end
0078 
0079 %% Fix position & Scaling
0080 % get additional constraint and move hrep
0081 [positionConstraintMatrix, mapFacetDistanceToOffset] = ...
0082     fixPosition(hrep.A, constraintMatrix, zerotol);
0083 positionFixOffset = mapFacetDistanceToOffset * hrep.h;
0084 hrepPositionFixed = moveHrep(hrep, positionFixOffset);
0085 
0086 % Scaling
0087 % normal scaling cannot be applied according to position fixing. The only
0088 %   thing that can be done is scaling the h-vector. We simply scale the
0089 %   largest facet distance to one.
0090 scaleFactor = 1/max(abs(hrepPositionFixed.h));
0091 hrepScaled = hrepPositionFixed;
0092 hrepScaled.h = hrepScaled.h * scaleFactor;
0093 
0094 % check final polytope vs. input and position constraint
0095 if ~isAllZero(constraintMatrix * hrepScaled.h, zerotol)
0096     error('elk:decomposition:wrongInput', ...
0097         'The input polytope must fulfill the given constraints');
0098 end
0099 if ~isAllZero(positionConstraintMatrix * hrepScaled.h, zerotol)
0100     error('elk:decomposition:numericalProblem', ...
0101         'The scaled polytope does not fulfill the fixed position constraint. This should not happen!');
0102 end
0103 
0104 if verbose,disp('Generating incidence matrix');end
0105 
0106 %% Generate incidence matrix
0107 % Facets, incident to a vertex are stored in an incidence matrix. Rows for
0108 % vertices, columns for facets.
0109 
0110 % extreme points and initialization
0111 vrepScaled = convertHrepToVrep(hrepScaled, zerotol);
0112 nExtreme = size(vrepScaled.V, 1);
0113 incidenceVerticesToFacets = zeros(nExtreme, nFacet, 'uint8');
0114 
0115 for iExtreme = 1:nExtreme
0116     incidenceVerticesToFacets(iExtreme, :) = isZero( ...
0117         hrepScaled.A * vrepScaled.V(iExtreme, :)' - hrepScaled.h, ...
0118         zerotol);
0119 end
0120 
0121 %% Equations and Inequalities
0122 % The following loop goes through all extreme point / facet
0123 %   combinations. While it follows three states:
0124 %    (1) finding the representative facets
0125 %    (2) adding equality constraints
0126 %    (3) adding inequality constraints
0127 % Both matrices are stored in the form that each row is a equation
0128 %   (or inequality) and each column corresponds to a facet.
0129 
0130 if verbose,disp('Extracting equations and inequalities');end
0131 
0132 % initialize equality/inequality matrices
0133 nEquation = sum(sum(incidenceVerticesToFacets, 2) - nDim);
0134 nInequality = sum(sum(~incidenceVerticesToFacets, 2));
0135 equationMatrix = zeros(nEquation, nFacet);
0136 inequalityMatrix = zeros(nInequality, nFacet);
0137 thisEquationIndex = 0;
0138 thisInequalityIndex = 0;
0139 
0140 % loop over extreme points
0141 for iExtreme = 1:nExtreme
0142 
0143     thisAdjacentFacetVector = find(incidenceVerticesToFacets(iExtreme, :));
0144     thisNonadjacentFacetVector = find(~incidenceVerticesToFacets(iExtreme, :));
0145     
0146     % find representative facets
0147     thisRank = 0;
0148     repFacetMatrix = zeros(nDim, nDim);
0149     repFacetIndexVector = zeros(1, nDim);
0150     for iFacet = thisAdjacentFacetVector
0151         repFacetMatrix(thisRank+1, :) = ...
0152             hrepScaled.A(iFacet, :);
0153         if rank(repFacetMatrix) > thisRank
0154             thisRank = thisRank + 1;
0155             repFacetIndexVector(thisRank) = iFacet;
0156             if thisRank == nDim, break;end
0157         end
0158     end
0159     
0160     % error if representatives not found
0161     if thisRank < nDim
0162         error('elk:decomposition:numericalProblem', ...
0163             'Failed to find representative facets. This should not happen!');
0164     end
0165     
0166     % the inversion of the representative facet normals
0167     % this is used together with the fourth facet normal (a4). For all
0168     %   four one can find Li that satisy (L4 = 1):
0169     %     A' * [L1, L2, L3]' = -L4*a4
0170     %   by using:
0171     %     [L1, L2, L3] = -L4 * a4' * inv(A)
0172     invertedRepresentativeNormalMatrix = inv(repFacetMatrix);
0173     
0174     % eliminating representatives from adjacency vector
0175     thisAdjacentFacetVector = eliminateRows(thisAdjacentFacetVector', ...
0176         repFacetIndexVector', eps)';
0177     
0178     % adding equations
0179     % Knowing L1, L2, L3 and L4 we gather the equation:
0180     %   [L1 L2 L3 L4] * [h1; h2; h3; h4] = 0
0181     for iFacet = thisAdjacentFacetVector
0182         thisEquationIndex = thisEquationIndex + 1;
0183         equationMatrix(thisEquationIndex, iFacet) = 1;
0184         lambdaVector = -1 * hrepScaled.A(iFacet, :) * ...
0185             invertedRepresentativeNormalMatrix;
0186         equationMatrix(thisEquationIndex, ...
0187             repFacetIndexVector) = lambdaVector;
0188     end
0189 
0190     % adding inequalities
0191     % Knowing L1, L2, L3 and L4 we gather the equation:
0192     %   -1 * [L1 L2 L3 L4] * [h1; h2; h3; h4] <= 0
0193     for iFacet = thisNonadjacentFacetVector
0194         thisInequalityIndex = thisInequalityIndex + 1;
0195         inequalityMatrix(thisInequalityIndex, iFacet) = -1;
0196         lambdaVector = 1 * hrepScaled.A(iFacet, :) * ...
0197             invertedRepresentativeNormalMatrix;
0198         inequalityMatrix(thisInequalityIndex, ...
0199             repFacetIndexVector) = lambdaVector;
0200     end
0201     
0202 end
0203 
0204 if thisEquationIndex < nEquation
0205     error('elk:decomposition:numericalProblem', ...
0206         'Failed to add all equations. This should not happen!');
0207 end
0208 if thisInequalityIndex < nInequality
0209     error('elk:decomposition:numericalProblem', ...
0210         'Failed to add all inequalities. This should not happen!');
0211 end
0212 
0213 if verbose,disp(['Generated ' num2str(nEquation) ' equations and ' ...
0214         num2str(nInequality) ' inequalities']);end
0215 
0216 if verbose,disp('Solving equations and inequalities');end
0217 
0218 %% Solve equations and inequalities
0219 summandMatrix = computeExtremePointsOfCone(...
0220     [equationMatrix; constraintMatrix; positionConstraintMatrix], ...
0221     inequalityMatrix, zerotol);
0222 nSummand = size(summandMatrix, 1);
0223 
0224 %% Output handling
0225 
0226 % generate summands or not
0227 switch lower(outputResult)
0228     case 'indecomposable'
0229         %! ToDo: there should be some scaling. But this does not seem to be
0230         %        trivial with fixed position and in hrep.
0231         %  Update: Scaling is now possible in a reasonable manner, using
0232         %    the mean width (implemented in scaleToReal)
0233         %/
0234     case 'summand'
0235         error('this option is currently switched off');
0236         % get scalar factors
0237         % For any number of summands we search a solution for:
0238         %   summandMatrix' * lam = h with lam >= 0.
0239         % We simply use an optimizer with the function to be minimized:
0240         %   (1:nSummands) * lam
0241 %         cddlibOutput = callCddLib('solve_lp', struct(...
0242 %             'A', [summandMatrix'; eye(nSummand)], ...
0243 %             'B', [hrepScaled.h; zeros(nSummand, 1)], ...
0244 %             'lin', 1:nFacet, ...
0245 %             'obj', nSummand:-1:1 ...
0246 %             ));
0247 %         scalarMultiples = cddlibOutput.xopt;
0248 
0249 %! ToDo: This part does currently not work. I could need to triangulate the
0250 %        cone to find an appropriate simplex partition for which the
0251 %        condition lam > 0 is automatically fulfilled.
0252         
0253 %         summandMatrixReduced = (projectionMatrix * summandMatrix')';
0254 %         facetDistanceVectorReduced = (projectionMatrix * hrepScaled.h)';
0255         
0256 %         triangulationIndexMatrix = computeTriangulationOfCone(summandMatrixReduced);
0257 %         for iSimplex = 1:size(triangulationIndexMatrix, 1)
0258 %             thisRayMatrix = summandMatrixReduced(triangulationIndexMatrix(iSimplex, :), :);
0259 %             thisMultipleVector = inv(thisRayMatrix') * facetDistanceVectorReduced';
0260 %             if any(thisMultipleVector < 0)
0261 %                 scalarMultipleVector = [];
0262 %                 continue
0263 %             else
0264 %                 scalarMultipleVector = zeros(size(summandMatrixReduced, 1), 1);
0265 %                 scalarMultipleVector(triangulationIndexMatrix(iSimplex, :)) = ...
0266 %                     thisMultipleVector;
0267 %                 break;
0268 %             end
0269 %         end
0270 %
0271 %         if isempty(scalarMultipleVector)
0272 %             error('elk:decomposition:numericalProblem', ...
0273 %                 'Could not determine scalar coefficients for summands. This should not happen.');
0274 %         end
0275 %
0276 %         for iSummand = 1:nSummand
0277 %             summandMatrix(iSummand, :) = summandMatrix(iSummand, :) * ...
0278 %                                          scalarMultipleVector(iSummand);
0279 %         end
0280 %
0281 %         % throw away almost zero rows
0282 %         summandMatrix(...
0283 %             prod(...
0284 %             double(isZero(summandMatrix, zerotol))...
0285 %             , 2) > 0, :) = [];
0286 %         nSummand = size(summandMatrix, 1);
0287     otherwise
0288         error('elk:decomposition:inputIssue', ...
0289             'The option ''result'' is either ''summand'' or ''indecomposable''');
0290 end
0291 
0292 % revert scaling
0293 summandMatrix = summandMatrix / scaleFactor;
0294 
0295 % revert position fix
0296 % this should only be done for the first summand and only for result type
0297 %   'summand'
0298 if strcmpi(outputResult, 'summand')
0299     summandMatrix(1,:) = (summandMatrix(1,:)' - hrep.A * positionFixOffset)';
0300 end
0301 
0302 switch outputMatrix
0303     case 1
0304         % nothing to do.
0305         
0306     case 0
0307         % convert to a cell array of h-representations
0308         hrepTemplate.A = hrep.A;
0309         hrepList = cell(nSummand, 1);
0310         for iSummand = 1:nSummand
0311             hrepList{iSummand} = hrepTemplate;
0312             hrepList{iSummand}.h = summandMatrix(iSummand, :)';
0313         end
0314         summandMatrix = hrepList;
0315         
0316     otherwise
0317         error('elk:decomposition:wrongInput', ...
0318             'The option ''matrix'' is either 1 or 0');
0319 end
0320

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