blob: 2ef7e7ad9fbd7685795c97e82e0f2d854c866ce8 [file] [log] [blame]
Austin Schuh405fa6c2015-09-06 18:13:55 -07001/* 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
21dd_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
122dd_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 */