Austin Schuh | 405fa6c | 2015-09-06 18:13:55 -0700 | [diff] [blame] | 1 | /* cddproj.c: Polyhedral Projections in cddlib |
| 2 | written by Komei Fukuda, fukuda@cs.mcgill.ca |
| 3 | Version 0.94, Aug. 4, 2005 |
| 4 | */ |
| 5 | |
| 6 | /* cddlib : C-library of the double description method for |
| 7 | computing all vertices and extreme rays of the polyhedron |
| 8 | P= {x : b - A x >= 0}. |
| 9 | Please read COPYING (GNU General Public Licence) and |
| 10 | the manual cddlibman.tex for detail. |
| 11 | */ |
| 12 | |
| 13 | #include "setoper.h" /* set operation library header (Ver. June 1, 2000 or later) */ |
| 14 | #include "cdd.h" |
| 15 | #include <stdio.h> |
| 16 | #include <stdlib.h> |
| 17 | #include <time.h> |
| 18 | #include <math.h> |
| 19 | #include <string.h> |
| 20 | |
| 21 | dd_MatrixPtr dd_BlockElimination(dd_MatrixPtr M, dd_colset delset, dd_ErrorType *error) |
| 22 | /* Eliminate the variables (columns) delset by |
| 23 | the Block Elimination with dd_DoubleDescription algorithm. |
| 24 | |
| 25 | Given (where y is to be eliminated): |
| 26 | c1 + A1 x + B1 y >= 0 |
| 27 | c2 + A2 x + B2 y = 0 |
| 28 | |
| 29 | 1. First construct the dual system: z1^T B1 + z2^T B2 = 0, z1 >= 0. |
| 30 | 2. Compute the generators of the dual. |
| 31 | 3. Then take the linear combination of the original system with each generator. |
| 32 | 4. Remove redundant inequalies. |
| 33 | |
| 34 | */ |
| 35 | { |
| 36 | dd_MatrixPtr Mdual=NULL, Mproj=NULL, Gdual=NULL; |
| 37 | dd_rowrange i,h,m,mproj,mdual,linsize; |
| 38 | dd_colrange j,k,d,dproj,ddual,delsize; |
| 39 | dd_colindex delindex; |
| 40 | mytype temp,prod; |
| 41 | dd_PolyhedraPtr dualpoly; |
| 42 | dd_ErrorType err=dd_NoError; |
| 43 | dd_boolean localdebug=dd_FALSE; |
| 44 | |
| 45 | *error=dd_NoError; |
| 46 | m= M->rowsize; |
| 47 | d= M->colsize; |
| 48 | delindex=(long*)calloc(d+1,sizeof(long)); |
| 49 | dd_init(temp); |
| 50 | dd_init(prod); |
| 51 | |
| 52 | k=0; delsize=0; |
| 53 | for (j=1; j<=d; j++){ |
| 54 | if (set_member(j, delset)){ |
| 55 | k++; delsize++; |
| 56 | delindex[k]=j; /* stores the kth deletion column index */ |
| 57 | } |
| 58 | } |
| 59 | if (localdebug) dd_WriteMatrix(stdout, M); |
| 60 | |
| 61 | linsize=set_card(M->linset); |
| 62 | ddual=m+1; |
| 63 | mdual=delsize + m - linsize; /* #equalitions + dimension of z1 */ |
| 64 | |
| 65 | /* setup the dual matrix */ |
| 66 | Mdual=dd_CreateMatrix(mdual, ddual); |
| 67 | Mdual->representation=dd_Inequality; |
| 68 | for (i = 1; i <= delsize; i++){ |
| 69 | set_addelem(Mdual->linset,i); /* equality */ |
| 70 | for (j = 1; j <= m; j++) { |
| 71 | dd_set(Mdual->matrix[i-1][j], M->matrix[j-1][delindex[i]-1]); |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | k=0; |
| 76 | for (i = 1; i <= m; i++){ |
| 77 | if (!set_member(i, M->linset)){ |
| 78 | /* set nonnegativity for the dual variable associated with |
| 79 | each non-linearity inequality. */ |
| 80 | k++; |
| 81 | dd_set(Mdual->matrix[delsize+k-1][i], dd_one); |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | /* 2. Compute the generators of the dual system. */ |
| 86 | dualpoly=dd_DDMatrix2Poly(Mdual, &err); |
| 87 | Gdual=dd_CopyGenerators(dualpoly); |
| 88 | |
| 89 | /* 3. Take the linear combination of the original system with each generator. */ |
| 90 | dproj=d-delsize; |
| 91 | mproj=Gdual->rowsize; |
| 92 | Mproj=dd_CreateMatrix(mproj, dproj); |
| 93 | Mproj->representation=dd_Inequality; |
| 94 | set_copy(Mproj->linset, Gdual->linset); |
| 95 | |
| 96 | for (i=1; i<=mproj; i++){ |
| 97 | k=0; |
| 98 | for (j=1; j<=d; j++){ |
| 99 | if (!set_member(j, delset)){ |
| 100 | k++; /* new index of the variable x_j */ |
| 101 | dd_set(prod, dd_purezero); |
| 102 | for (h = 1; h <= m; h++){ |
| 103 | dd_mul(temp,M->matrix[h-1][j-1],Gdual->matrix[i-1][h]); |
| 104 | dd_add(prod,prod,temp); |
| 105 | } |
| 106 | dd_set(Mproj->matrix[i-1][k-1],prod); |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | if (localdebug) printf("Size of the projection system: %ld x %ld\n", mproj, dproj); |
| 111 | |
| 112 | dd_FreePolyhedra(dualpoly); |
| 113 | free(delindex); |
| 114 | dd_clear(temp); |
| 115 | dd_clear(prod); |
| 116 | dd_FreeMatrix(Mdual); |
| 117 | dd_FreeMatrix(Gdual); |
| 118 | return Mproj; |
| 119 | } |
| 120 | |
| 121 | |
| 122 | dd_MatrixPtr dd_FourierElimination(dd_MatrixPtr M,dd_ErrorType *error) |
| 123 | /* Eliminate the last variable (column) from the given H-matrix using |
| 124 | the standard Fourier Elimination. |
| 125 | */ |
| 126 | { |
| 127 | dd_MatrixPtr Mnew=NULL; |
| 128 | dd_rowrange i,inew,ip,in,iz,m,mpos=0,mneg=0,mzero=0,mnew; |
| 129 | dd_colrange j,d,dnew; |
| 130 | dd_rowindex posrowindex, negrowindex,zerorowindex; |
| 131 | mytype temp1,temp2; |
| 132 | dd_boolean localdebug=dd_FALSE; |
| 133 | |
| 134 | *error=dd_NoError; |
| 135 | m= M->rowsize; |
| 136 | d= M->colsize; |
| 137 | if (d<=1){ |
| 138 | *error=dd_ColIndexOutOfRange; |
| 139 | if (localdebug) { |
| 140 | printf("The number of column is too small: %ld for Fourier's Elimination.\n",d); |
| 141 | } |
| 142 | goto _L99; |
| 143 | } |
| 144 | |
| 145 | if (M->representation==dd_Generator){ |
| 146 | *error=dd_NotAvailForV; |
| 147 | if (localdebug) { |
| 148 | printf("Fourier's Elimination cannot be applied to a V-polyhedron.\n"); |
| 149 | } |
| 150 | goto _L99; |
| 151 | } |
| 152 | |
| 153 | if (set_card(M->linset)>0){ |
| 154 | *error=dd_CannotHandleLinearity; |
| 155 | if (localdebug) { |
| 156 | printf("The Fourier Elimination function does not handle equality in this version.\n"); |
| 157 | } |
| 158 | goto _L99; |
| 159 | } |
| 160 | |
| 161 | /* Create temporary spaces to be removed at the end of this function */ |
| 162 | posrowindex=(long*)calloc(m+1,sizeof(long)); |
| 163 | negrowindex=(long*)calloc(m+1,sizeof(long)); |
| 164 | zerorowindex=(long*)calloc(m+1,sizeof(long)); |
| 165 | dd_init(temp1); |
| 166 | dd_init(temp2); |
| 167 | |
| 168 | for (i = 1; i <= m; i++) { |
| 169 | if (dd_Positive(M->matrix[i-1][d-1])){ |
| 170 | mpos++; |
| 171 | posrowindex[mpos]=i; |
| 172 | } else if (dd_Negative(M->matrix[i-1][d-1])) { |
| 173 | mneg++; |
| 174 | negrowindex[mneg]=i; |
| 175 | } else { |
| 176 | mzero++; |
| 177 | zerorowindex[mzero]=i; |
| 178 | } |
| 179 | } /*of i*/ |
| 180 | |
| 181 | if (localdebug) { |
| 182 | dd_WriteMatrix(stdout, M); |
| 183 | printf("No of (+ - 0) rows = (%ld, %ld, %ld)\n", mpos,mneg, mzero); |
| 184 | } |
| 185 | |
| 186 | /* The present code generates so many redundant inequalities and thus |
| 187 | is quite useless, except for very small examples |
| 188 | */ |
| 189 | mnew=mzero+mpos*mneg; /* the total number of rows after elimination */ |
| 190 | dnew=d-1; |
| 191 | |
| 192 | Mnew=dd_CreateMatrix(mnew, dnew); |
| 193 | dd_CopyArow(Mnew->rowvec, M->rowvec, dnew); |
| 194 | /* set_copy(Mnew->linset,M->linset); */ |
| 195 | Mnew->numbtype=M->numbtype; |
| 196 | Mnew->representation=M->representation; |
| 197 | Mnew->objective=M->objective; |
| 198 | |
| 199 | |
| 200 | /* Copy the inequalities independent of x_d to the top of the new matrix. */ |
| 201 | for (iz = 1; iz <= mzero; iz++){ |
| 202 | for (j = 1; j <= dnew; j++) { |
| 203 | dd_set(Mnew->matrix[iz-1][j-1], M->matrix[zerorowindex[iz]-1][j-1]); |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | /* Create the new inequalities by combining x_d positive and negative ones. */ |
| 208 | inew=mzero; /* the index of the last x_d zero inequality */ |
| 209 | for (ip = 1; ip <= mpos; ip++){ |
| 210 | for (in = 1; in <= mneg; in++){ |
| 211 | inew++; |
| 212 | dd_neg(temp1, M->matrix[negrowindex[in]-1][d-1]); |
| 213 | for (j = 1; j <= dnew; j++) { |
| 214 | dd_LinearComb(temp2,M->matrix[posrowindex[ip]-1][j-1],temp1,\ |
| 215 | M->matrix[negrowindex[in]-1][j-1],\ |
| 216 | M->matrix[posrowindex[ip]-1][d-1]); |
| 217 | dd_set(Mnew->matrix[inew-1][j-1],temp2); |
| 218 | } |
| 219 | dd_Normalize(dnew,Mnew->matrix[inew-1]); |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | |
| 224 | free(posrowindex); |
| 225 | free(negrowindex); |
| 226 | free(zerorowindex); |
| 227 | dd_clear(temp1); |
| 228 | dd_clear(temp2); |
| 229 | |
| 230 | _L99: |
| 231 | return Mnew; |
| 232 | } |
| 233 | |
| 234 | |
| 235 | /* end of cddproj.c */ |