static Polyhedron *partition2polyhedron(Matrix *A, struct barvinok_options *options) { int i; unsigned nvar, nparam; Matrix *M; Polyhedron *P; nvar = A->NbColumns; nparam = A->NbRows; M = Matrix_Alloc(nvar + nparam, 1 + nvar + nparam + 1); assert(M); for (i = 0; i < nparam; ++i) { Vector_Copy(A->p[i], M->p[i] + 1, nvar); value_set_si(M->p[i][1 + nvar + i], -1); } for (i = 0; i < nvar; ++i) { value_set_si(M->p[nparam + i][0], 1); value_set_si(M->p[nparam + i][1 + i], 1); } P = Constraints2Polyhedron(M, options->MaxRays); Matrix_Free(M); return P; }
/** * Eliminate the columns corresponding to a list of eliminated parameters. * @param M the constraints matrix whose columns are to be removed * @param nbVars an offset to be added to the ranks of the variables to be * removed * @param elimParms the list of ranks of the variables to be removed * @param newM (output) the matrix without the removed columns */ void Constraints_removeElimCols(Matrix * M, unsigned int nbVars, unsigned int *elimParms, Matrix ** newM) { unsigned int i, j, k; if (elimParms[0]==0) { Matrix_clone(M, newM); return; } if ((*newM)==NULL) { (*newM) = Matrix_Alloc(M->NbRows, M->NbColumns - elimParms[0]); } else { assert ((*newM)->NbColumns==M->NbColumns - elimParms[0]); } for (i=0; i< M->NbRows; i++) { value_assign((*newM)->p[i][0], M->p[i][0]); /* kind of cstr */ k=0; Vector_Copy(&(M->p[i][1]), &((*newM)->p[i][1]), nbVars); for (j=0; j< M->NbColumns-2-nbVars; j++) { if (j!=elimParms[k+1]) { value_assign((*newM)->p[i][j-k+nbVars+1], M->p[i][j+nbVars+1]); } else { k++; } } value_assign((*newM)->p[i][(*newM)->NbColumns-1], M->p[i][M->NbColumns-1]); /* cst part */ } } /* Constraints_removeElimCols */
static Matrix *Polyhedron2standard_form(Polyhedron *P, Matrix **T) { int i, j; int rows; unsigned dim = P->Dimension; Matrix *M2; Matrix *H, *U; Matrix M; assert(P->NbEq == 0); Polyhedron_Remove_Positivity_Constraint(P); for (i = 0; i < P->NbConstraints; ++i) assert(value_zero_p(P->Constraint[i][1+dim])); Polyhedron_Matrix_View(P, &M, P->NbConstraints); H = standard_constraints(&M, 0, &rows, &U); *T = homogenize(U); Matrix_Free(U); M2 = Matrix_Alloc(rows, 2+dim+rows); for (i = dim; i < H->NbRows; ++i) { Vector_Copy(H->p[i], M2->p[i-dim]+1, dim); value_set_si(M2->p[i-dim][1+i], -1); } for (i = 0, j = H->NbRows-dim; i < dim; ++i) { if (First_Non_Zero(H->p[i], i) == -1) continue; Vector_Oppose(H->p[i], M2->p[j]+1, dim); value_set_si(M2->p[j][1+j+dim], 1); ++j; } Matrix_Free(H); return M2; }
/** * Computes the overall period of the variables I for (MI) mod |d|, where M is * a matrix and |d| a vector. Produce a diagonal matrix S = (s_k) where s_k is * the overall period of i_k * @param M the set of affine functions of I (row-vectors) * @param d the column-vector representing the modulos */ Matrix * affine_periods(Matrix * M, Matrix * d) { Matrix * S; unsigned int i,j; Value tmp; Value * periods = (Value *)malloc(sizeof(Value) * M->NbColumns); value_init(tmp); for(i=0; i< M->NbColumns; i++) { value_init(periods[i]); value_set_si(periods[i], 1); } for (i=0; i<M->NbRows; i++) { for (j=0; j< M->NbColumns; j++) { value_gcd(tmp, d->p[i][0], M->p[i][j]); value_divexact(tmp, d->p[i][0], tmp); value_lcm(periods[j], periods[j], tmp); } } value_clear(tmp); /* 2- build S */ S = Matrix_Alloc(M->NbColumns, M->NbColumns); for (i=0; i< M->NbColumns; i++) for (j=0; j< M->NbColumns; j++) if (i==j) value_assign(S->p[i][j],periods[j]); else value_set_si(S->p[i][j], 0); /* 3- clean up */ for(i=0; i< M->NbColumns; i++) value_clear(periods[i]); free(periods); return S; } /* affine_periods */
/* Return * T 0 * 0 1 */ static Matrix *homogenize(Matrix *T) { int i; Matrix *H = Matrix_Alloc(T->NbRows+1, T->NbColumns+1); for (i = 0; i < T->NbRows; ++i) Vector_Copy(T->p[i], H->p[i], T->NbColumns); value_set_si(H->p[T->NbRows][T->NbColumns], 1); return H; }
static Matrix *VectorArray2Matrix(VectorArray array, unsigned cols) { int i, j; Matrix *M = Matrix_Alloc(array->Size, cols+1); for (i = 0; i < array->Size; ++i) { for (j = 0; j < cols; ++j) value_set_si(M->p[i][j], array->Data[i][j]); value_set_si(M->p[i][cols], 1); } return M; }
/** * Computes the intersection of two linear lattices, whose base vectors are * respectively represented in A and B. * If I and/or Lb is set to NULL, then the matrix is allocated. * Else, the matrix is assumed to be allocated already. * I and Lb are rk x rk, where rk is the rank of A (or B). * @param A the full-row rank matrix whose column-vectors are the basis for the * first linear lattice. * @param B the matrix whose column-vectors are the basis for the second linear * lattice. * @param Lb the matrix such that B.Lb = I, where I is the intersection. * @return their intersection. */ static void linearInter(Matrix * A, Matrix * B, Matrix ** I, Matrix **Lb) { Matrix * AB=NULL; int rk = A->NbRows; int a = A->NbColumns; int b = B->NbColumns; int i,j, z=0; Matrix * H, *U, *Q; /* ensure that the spanning vectors are in the same space */ assert(B->NbRows==rk); /* 1- build the matrix * (A 0 1) * (0 B 1) */ AB = Matrix_Alloc(2*rk, a+b+rk); Matrix_copySubMatrix(A, 0, 0, rk, a, AB, 0, 0); Matrix_copySubMatrix(B, 0, 0, rk, b, AB, rk, a); for (i=0; i< rk; i++) { value_set_si(AB->p[i][a+b+i], 1); value_set_si(AB->p[i+rk][a+b+i], 1); } if (dbgCompParm) { show_matrix(AB); } /* 2- Compute its left Hermite normal form. AB.U = [H 0] */ left_hermite(AB, &H, &Q, &U); Matrix_Free(AB); Matrix_Free(Q); /* count the number of non-zero colums in H */ for (z=H->NbColumns-1; value_zero_p(H->p[H->NbRows-1][z]); z--); z++; if (dbgCompParm) { show_matrix(H); printf("z=%d\n", z); } Matrix_Free(H); /* if you split U in 9 submatrices, you have: * A.U_13 = -U_33 * B.U_23 = -U_33, * where the nb of cols of U_{*3} equals the nb of zero-cols of H * U_33 is a (the smallest) combination of col-vectors of A and B at the same * time: their intersection. */ Matrix_subMatrix(U, a+b, z, U->NbColumns, U->NbColumns, I); Matrix_subMatrix(U, a, z, a+b, U->NbColumns, Lb); if (dbgCompParm) { show_matrix(U); } Matrix_Free(U); } /* linearInter */
Matrix *pluto_matrix_to_polylib(const PlutoMatrix *mat) { int r, c; Matrix *polymat; polymat = Matrix_Alloc(mat->nrows, mat->ncols); for (r=0; r<mat->nrows; r++) { for (c=0; c<mat->ncols; c++) { polymat->p[r][c] = mat->val[r][c]; } } return polymat; }
/** * Given a full-row-rank nxm matrix M made of m row-vectors), computes the * basis K (made of n-m column-vectors) of the integer kernel of the rows of M * so we have: M.K = 0 */ Matrix * int_ker(Matrix * M) { Matrix *U, *Q, *H, *H2, *K=NULL; int i, j, rk; if (dbgCompParm) show_matrix(M); /* eliminate redundant rows : UM = H*/ right_hermite(M, &H, &Q, &U); for (rk=H->NbRows-1; (rk>=0) && Vector_IsZero(H->p[rk], H->NbColumns); rk--); rk++; if (dbgCompParmMore) { printf("rank = %d\n", rk); } /* there is a non-null kernel if and only if the dimension m of the space spanned by the rows is inferior to the number n of variables */ if (M->NbColumns <= rk) { Matrix_Free(H); Matrix_Free(Q); Matrix_Free(U); K = Matrix_Alloc(M->NbColumns, 0); return K; } Matrix_Free(U); Matrix_Free(Q); /* fool left_hermite by giving NbRows =rank of M*/ H->NbRows=rk; /* computes MU = [H 0] */ left_hermite(H, &H2, &Q, &U); if (dbgCompParmMore) { printf("-- Int. Kernel -- \n"); show_matrix(M); printf(" = \n"); show_matrix(H2); show_matrix(U); } H->NbRows==M->NbRows; Matrix_Free(H); /* the Integer Kernel is made of the last n-rk columns of U */ Matrix_subMatrix(U, 0, rk, U->NbRows, U->NbColumns, &K); /* clean up */ Matrix_Free(H2); Matrix_Free(U); Matrix_Free(Q); return K; } /* int_ker */
/** * Given an integer matrix B with m rows and integer m-vectors C and d, * computes the basis of the integer solutions to (BN+C) mod d = 0 (1). * This is an affine lattice (G): (N 1)^T= G(N' 1)^T, forall N' in Z^b. * If there is no solution, returns NULL. * @param B B, a (m x b) matrix * @param C C, a (m x 1) integer matrix * @param d d, a (1 x m) integer matrix * @param imb the affine (b+1)x(b+1) basis of solutions, in the homogeneous * form. Allocated if initially set to NULL, reused if not. */ void Equalities_intModBasis(Matrix * B, Matrix * C, Matrix * d, Matrix ** imb) { int b = B->NbColumns; /* FIXME: treat the case d=0 as a regular equality B_kN+C_k = 0: */ /* OPT: could keep only equalities for which d>1 */ int nbEqs = B->NbRows; unsigned int i; /* 1- buid the problem DI+BN+C = 0 */ Matrix * eqs = Matrix_Alloc(nbEqs, nbEqs+b+1); for (i=0; i< nbEqs; i++) { value_assign(eqs->p[i][i], d->p[0][i]); } Matrix_copySubMatrix(B, 0, 0, nbEqs, b, eqs, 0, nbEqs); Matrix_copySubMatrix(C, 0, 0, nbEqs, 1, eqs, 0, nbEqs+b); /* 2- the solution is the validity lattice of the equalities */ Equalities_validityLattice(eqs, nbEqs, imb); Matrix_Free(eqs); } /* Equalities_intModBasis */
void count_new(Value* cb, int lanes[NLANES][L],int filaments,int noconsts){ //clock_t t1 = clock(); Polyhedron *A; int i,j; Matrix *M; //printf("inside count we have the following lanes for %d filaments and %d noconsts:\n",filaments,noconsts); //dump_lanes(lanes); M=Matrix_Alloc(noconsts,filaments+2); //lock_t t2 = clock(); int** constraints; constraints= malloc(noconsts*sizeof(int *)); //clock_t t3 = clock(); //printf("%lu\n",(filaments+2)*(noconsts)); for (i=0;i<noconsts;i++){ constraints[i]=(int*)malloc(sizeof(int)*(filaments+2)); for(j=0;j<filaments+2;j++){ constraints[i][j]=0; //printf("%d %d %d\n",i,j,constraints[i][j]); } } //clock_t t4 = clock(); //printf("from count: fils %d noconsts %d\n",filaments,noconsts); gen_constraints(constraints,lanes,filaments,noconsts); //clock_t t5 = clock(); struct barvinok_options *options = barvinok_options_new_with_defaults(); Matrix_Init(M,constraints); //clock_t t6 = clock(); A=Constraints2Polyhedron(M,options->MaxRays); //clock_t t7 = clock(); barvinok_count_with_options(A, cb, options); //clock_t t8 = clock(); //printf("timings at count: t2=%f, t3=%f, t4=%f, t5=%f, t6=%f, t7=%f, t8=%f\n",(double)(t2-t1)/CLOCKS_PER_SEC,(double)(t3-t1)/CLOCKS_PER_SEC,(double)(t4-t1)/CLOCKS_PER_SEC,(double)(t5-t1)/CLOCKS_PER_SEC,(double)(t6-t1)/CLOCKS_PER_SEC,(double)(t7-t1)/CLOCKS_PER_SEC,(double)(t8-t1)/CLOCKS_PER_SEC); Polyhedron_Free(A); barvinok_options_free(options); Matrix_Free(M); for (i=0;i<noconsts;i++){ free(constraints[i]); } free(constraints); }
/** * Eliminates certain parameters from a vector of values for parameters * @param origParms the initial vector of values of parameters * @param elimParms the list of parameters to be eliminated in the vector * @param newParms the vector of values without the eliminated ones. */ void valuesWithoutElim(Matrix * origParms, unsigned int * elimParms, Matrix ** newParms) { unsigned int i, j=0; if (*newParms==NULL) { *newParms = Matrix_Alloc(1, origParms->NbColumns-elimParms[0]); } /* else assume enough space is allocated */ if (elimParms[0] ==0) { for (i=0; i< origParms->NbColumns; i++) { value_assign((*newParms)->p[0][i], origParms->p[0][i]); } } for (i=0; i< origParms->NbColumns; i++) { if (i!=elimParms[j+1]) { value_assign((*newParms)->p[0][i-j], origParms->p[0][i]); } else { j++; } } }/* valuesWithoutElim */
PlutoMatrix *pluto_matrix_inverse(PlutoMatrix *mat) { assert(mat->nrows == mat->ncols); PlutoMatrix *inv; int dim = mat->nrows; Matrix *pinv = Matrix_Alloc(dim, dim); Matrix *pmat = pluto_matrix_to_polylib(mat); Matrix_Inverse(pmat, pinv); inv = polylib_matrix_to_pluto(pinv); Matrix_Free(pmat); Matrix_Free(pinv); return inv; }
/* * Read the contents of the matrix 'Mat' from standard input. * A '#' in the first column is a comment line */ Matrix *Matrix_Read(void) { Matrix *Mat; unsigned NbRows, NbColumns; char s[1024]; if (fgets(s, 1024, stdin) == NULL) return NULL; while ((*s=='#' || *s=='\n') || (sscanf(s, "%d %d", &NbRows, &NbColumns)<2)) { if (fgets(s, 1024, stdin) == NULL) return NULL; } Mat = Matrix_Alloc(NbRows,NbColumns); if(!Mat) { errormsg1("Matrix_Read", "outofmem", "out of memory space"); return(NULL); } Matrix_Read_Input(Mat); return Mat; } /* Matrix_Read */
/** * Given a matrix that defines a full-dimensional affine lattice, returns the * affine sub-lattice spanned in the k first dimensions. * Useful for instance when you only look for the parameters' validity lattice. * @param lat the original full-dimensional lattice * @param subLat the sublattice */ void Lattice_extractSubLattice(Matrix * lat, unsigned int k, Matrix ** subLat) { Matrix * H, *Q, *U, *linLat = NULL; unsigned int i; dbgStart(Lattice_extractSubLattice); /* if the dimension is already good, just copy the initial lattice */ if (k==lat->NbRows-1) { if (*subLat==NULL) { (*subLat) = Matrix_Copy(lat); } else { Matrix_copySubMatrix(lat, 0, 0, lat->NbRows, lat->NbColumns, (*subLat), 0, 0); } return; } assert(k<lat->NbRows-1); /* 1- Make the linear part of the lattice triangular to eliminate terms from other dimensions */ Matrix_subMatrix(lat, 0, 0, lat->NbRows, lat->NbColumns-1, &linLat); /* OPT: any integer column-vector elimination is ok indeed. */ /* OPT: could test if the lattice is already in triangular form. */ left_hermite(linLat, &H, &Q, &U); if (dbgCompParmMore) { show_matrix(H); } Matrix_Free(Q); Matrix_Free(U); Matrix_Free(linLat); /* if not allocated yet, allocate it */ if (*subLat==NULL) { (*subLat) = Matrix_Alloc(k+1, k+1); } Matrix_copySubMatrix(H, 0, 0, k, k, (*subLat), 0, 0); Matrix_Free(H); Matrix_copySubMatrix(lat, 0, lat->NbColumns-1, k, 1, (*subLat), 0, k); for (i=0; i<k; i++) { value_set_si((*subLat)->p[k][i], 0); } value_set_si((*subLat)->p[k][k], 1); dbgEnd(Lattice_extractSubLattice); } /* Lattice_extractSubLattice */
int main(int argc,char *argv[]) { Matrix *C1, *P1; Polyhedron *C, *P, *S; Polyhedron *CC, *PP; Enumeration *en; Value *p; int i,j,k; int m,M; char str[1024]; Value c; /******* Read the input *********/ P1 = Matrix_Read(); C1 = Matrix_Read(); if(C1->NbColumns < 2) { fprintf(stderr,"Not enough parameters !\n"); exit(0); } P = Constraints2Polyhedron(P1, MAXRAYS); C = Constraints2Polyhedron(C1, MAXRAYS); Matrix_Free(C1); Matrix_Free(P1); /******* Compute the true context *******/ CC = align_context(C,P->Dimension,MAXRAYS); PP = DomainIntersection(P,CC,MAXRAYS); Domain_Free(CC); C1 = Matrix_Alloc(C->Dimension+1,P->Dimension+1); for(i=0;i<C1->NbRows;i++) for(j=0;j<C1->NbColumns;j++) if(i==j-P->Dimension+C->Dimension) value_set_si(C1->p[i][j],1); else value_set_si(C1->p[i][j],0); CC = Polyhedron_Image(PP,C1,MAXRAYS); Domain_Free(C); Domain_Free(PP); Matrix_Free(C1); C = CC; /******* Initialize parameters *********/ p = (Value *)malloc(sizeof(Value) * (P->Dimension+2)); for(i=0;i<=P->Dimension;i++) { value_init(p[i]); value_set_si(p[i],0); } value_init(p[i]); value_set_si(p[i],1); /*** S = scanning list of polyhedra ***/ S = Polyhedron_Scan(P,C,MAXRAYS); value_init(c); /******* Count now *********/ FOREVER { fflush(stdin); printf("Enter %d parameters : ",C->Dimension); for(k=S->Dimension-C->Dimension+1;k<=S->Dimension;++k) { scanf(" %s", str); value_read(p[k],str); } printf("EP( "); value_print(stdout,VALUE_FMT,p[S->Dimension-C->Dimension+1]); for(k=S->Dimension-C->Dimension+2;k<=S->Dimension;++k) { printf(", "); value_print(stdout,VALUE_FMT,p[k]); } printf(" ) = "); count_points(1,S,p,&c); value_print(stdout,VALUE_FMT,c); printf("\n"); } for(i=0;i<=(P->Dimension+1);i++) value_clear(p[i]); value_clear(c); return(0); } /* main */
/** * Eliminates all the equalities in a set of constraints and returns the set of * constraints defining a full-dimensional polyhedron, such that there is a * bijection between integer points of the original polyhedron and these of the * resulting (projected) polyhedron). * If VL is set to NULL, this funciton allocates it. Else, it assumes that * (*VL) points to a matrix of the right size. * <p> The following things are done: * <ol> * <li> remove equalities involving only parameters, and remove as many * parameters as there are such equalities. From that, the list of * eliminated parameters <i>elimParms</i> is built. * <li> remove equalities that involve variables. This requires a compression * of the parameters and of the other variables that are not eliminated. * The affine compresson is represented by matrix VL (for <i>validity * lattice</i>) and is such that (N I 1)^T = VL.(N' I' 1), where N', I' * are integer (they are the parameters and variables after compression). *</ol> *</p> */ void Constraints_fullDimensionize(Matrix ** M, Matrix ** C, Matrix ** VL, Matrix ** Eqs, Matrix ** ParmEqs, unsigned int ** elimVars, unsigned int ** elimParms, int maxRays) { unsigned int i, j; Matrix * A=NULL, *B=NULL; Matrix * Ineqs=NULL; unsigned int nbVars = (*M)->NbColumns - (*C)->NbColumns; unsigned int nbParms; int nbElimVars; Matrix * fullDim = NULL; /* variables for permutations */ unsigned int * permutation; Matrix * permutedEqs=NULL, * permutedIneqs=NULL; /* 1- Eliminate the equalities involving only parameters. */ (*ParmEqs) = Constraints_removeParmEqs(M, C, 0, elimParms); /* if the polyehdron is empty, return now. */ if ((*M)->NbColumns==0) return; /* eliminate the columns corresponding to the eliminated parameters */ if (elimParms[0]!=0) { Constraints_removeElimCols(*M, nbVars, (*elimParms), &A); Matrix_Free(*M); (*M) = A; Constraints_removeElimCols(*C, 0, (*elimParms), &B); Matrix_Free(*C); (*C) = B; if (dbgCompParm) { printf("After false parameter elimination: \n"); show_matrix(*M); show_matrix(*C); } } nbParms = (*C)->NbColumns-2; /* 2- Eliminate the equalities involving variables */ /* a- extract the (remaining) equalities from the poyhedron */ split_constraints((*M), Eqs, &Ineqs); nbElimVars = (*Eqs)->NbRows; /* if the polyhedron is already full-dimensional, return */ if ((*Eqs)->NbRows==0) { Matrix_identity(nbParms+1, VL); return; } /* b- choose variables to be eliminated */ permutation = find_a_permutation((*Eqs), nbParms); if (dbgCompParm) { printf("Permuting the vars/parms this way: [ "); for (i=0; i< (*Eqs)->NbColumns-2; i++) { printf("%d ", permutation[i]); } printf("]\n"); } Constraints_permute((*Eqs), permutation, &permutedEqs); Equalities_validityLattice(permutedEqs, (*Eqs)->NbRows, VL); if (dbgCompParm) { printf("Validity lattice: "); show_matrix(*VL); } Constraints_compressLastVars(permutedEqs, (*VL)); Constraints_permute(Ineqs, permutation, &permutedIneqs); if (dbgCompParmMore) { show_matrix(permutedIneqs); show_matrix(permutedEqs); } Matrix_Free(*Eqs); Matrix_Free(Ineqs); Constraints_compressLastVars(permutedIneqs, (*VL)); if (dbgCompParm) { printf("After compression: "); show_matrix(permutedIneqs); } /* c- eliminate the first variables */ assert(Constraints_eliminateFirstVars(permutedEqs, permutedIneqs)); if (dbgCompParmMore) { printf("After elimination of the variables: "); show_matrix(permutedIneqs); } /* d- get rid of the first (zero) columns, which are now useless, and put the parameters back at the end */ fullDim = Matrix_Alloc(permutedIneqs->NbRows, permutedIneqs->NbColumns-nbElimVars); for (i=0; i< permutedIneqs->NbRows; i++) { value_set_si(fullDim->p[i][0], 1); for (j=0; j< nbParms; j++) { value_assign(fullDim->p[i][j+fullDim->NbColumns-nbParms-1], permutedIneqs->p[i][j+nbElimVars+1]); } for (j=0; j< permutedIneqs->NbColumns-nbParms-2-nbElimVars; j++) { value_assign(fullDim->p[i][j+1], permutedIneqs->p[i][nbElimVars+nbParms+j+1]); } value_assign(fullDim->p[i][fullDim->NbColumns-1], permutedIneqs->p[i][permutedIneqs->NbColumns-1]); } Matrix_Free(permutedIneqs); } /* Constraints_fullDimensionize */
/* INDEX = 1 .... Dimension */ int PolyhedronLTQ (Polyhedron *Pol1,Polyhedron *Pol2,int INDEX, int PDIM, int NbMaxConstrs) { int res, dim, i, j, k; Polyhedron *Q1, *Q2, *Q3, *Q4, *Q; Matrix *Mat; if (Pol1->next || Pol2->next) { errormsg1("PolyhedronLTQ", "compoly", "Can only compare polyhedra"); return 0; } if (Pol1->Dimension != Pol2->Dimension) { errormsg1("PolyhedronLTQ","diffdim","Polyhedra are not same dimension"); return 0; } dim = Pol1->Dimension+2; POL_ENSURE_FACETS(Pol1); POL_ENSURE_VERTICES(Pol1); POL_ENSURE_FACETS(Pol2); POL_ENSURE_VERTICES(Pol2); #ifdef DEBUG fprintf(stdout, "P1\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Pol1); fprintf(stdout, "P2\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Pol2); #endif /* Create the Line to add */ k = Pol1->Dimension-INDEX+1-PDIM; Mat = Matrix_Alloc(k,dim); Vector_Set(Mat->p_Init,0,dim*k); for(j=0,i=INDEX;j<k;i++,j++) value_set_si(Mat->p[j][i],1); Q1 = AddRays(Mat->p[0],k,Pol1,NbMaxConstrs); Q2 = AddRays(Mat->p[0],k,Pol2,NbMaxConstrs); #ifdef DEBUG fprintf(stdout, "Q1\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q1); fprintf(stdout, "Q2\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q2); #endif Matrix_Free(Mat); Q = DomainIntersection(Q1,Q2,NbMaxConstrs); #ifdef DEBUG fprintf(stdout, "Q\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q); #endif Domain_Free(Q1); Domain_Free(Q2); if (emptyQ(Q)) res = 0; /* not comparable */ else { Q1 = DomainIntersection(Pol1,Q,NbMaxConstrs); Q2 = DomainIntersection(Pol2,Q,NbMaxConstrs); #ifdef DEBUG fprintf(stdout, "Q1\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q1); fprintf(stdout, "Q2\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q2); #endif k = Q1->NbConstraints + Q2->NbConstraints; Mat = Matrix_Alloc(k, dim); Vector_Set(Mat->p_Init,0,k*dim); /* First compute surrounding polyhedron */ j=0; for (i=0; i<Q1->NbConstraints; i++) { if ((value_one_p(Q1->Constraint[i][0])) && (value_pos_p(Q1->Constraint[i][INDEX]))) { /* keep Q1's lower bounds */ for (k=0; k<dim; k++) value_assign(Mat->p[j][k],Q1->Constraint[i][k]); j++; } } for (i=0; i<Q2->NbConstraints; i++) { if ((value_one_p(Q2->Constraint[i][0])) && (value_neg_p(Q2->Constraint[i][INDEX]))) { /* and keep Q2's upper bounds */ for (k=0; k<dim; k++) value_assign(Mat->p[j][k],Q2->Constraint[i][k]); j++; } } Q4 = AddConstraints(Mat->p[0], j, Q, NbMaxConstrs); Matrix_Free(Mat); #ifdef debug fprintf(stderr, "Q4 surrounding polyhedron\n"); Polyhderon_Print(stderr,P_VALUE_FMT, Q4); #endif /* if surrounding polyhedron is empty, D1>D2 */ if (emptyQ(Q4)) { res = 1; #ifdef debug fprintf(stderr, "Surrounding polyhedron is empty\n"); #endif goto LTQdone2; } /* Test if Q1 < Q2 */ /* Build a constraint array for >= Q1 and <= Q2 */ Mat = Matrix_Alloc(2,dim); Vector_Set(Mat->p_Init,0,2*dim); /* Choose a contraint from Q1 */ for (i=0; i<Q1->NbConstraints; i++) { if (value_zero_p(Q1->Constraint[i][0])) { /* Equality */ if (value_zero_p(Q1->Constraint[i][INDEX])) { /* Ignore side constraint (they are in Q) */ continue; } else if (value_neg_p(Q1->Constraint[i][INDEX])) { /* copy -constraint to Mat */ value_set_si(Mat->p[0][0],1); for (k=1; k<dim; k++) value_oppose(Mat->p[0][k],Q1->Constraint[i][k]); } else { /* Copy constraint to Mat */ value_set_si(Mat->p[0][0],1); for (k=1; k<dim; k++) value_assign(Mat->p[0][k],Q1->Constraint[i][k]); } } else if(value_neg_p(Q1->Constraint[i][INDEX])) { /* Upper bound -- make a lower bound from it */ value_set_si(Mat->p[0][0],1); for (k=1; k<dim; k++) value_oppose(Mat->p[0][k],Q1->Constraint[i][k]); } else { /* Lower or side bound -- ignore it */ continue; } /* Choose a constraint from Q2 */ for (j=0; j<Q2->NbConstraints; j++) { if (value_zero_p(Q2->Constraint[j][0])) { /* equality */ if (value_zero_p(Q2->Constraint[j][INDEX])) { /* Ignore side constraint (they are in Q) */ continue; } else if (value_pos_p(Q2->Constraint[j][INDEX])) { /* Copy -constraint to Mat */ value_set_si(Mat->p[1][0],1); for (k=1; k<dim; k++) value_oppose(Mat->p[1][k],Q2->Constraint[j][k]); } else { /* Copy constraint to Mat */ value_set_si(Mat->p[1][0],1); for (k=1; k<dim; k++) value_assign(Mat->p[1][k],Q2->Constraint[j][k]); }; } else if (value_pos_p(Q2->Constraint[j][INDEX])) { /* Lower bound -- make an upper bound from it */ value_set_si(Mat->p[1][0],1); for(k=1;k<dim;k++) value_oppose(Mat->p[1][k],Q2->Constraint[j][k]); } else { /* Upper or side bound -- ignore it */ continue; }; #ifdef DEBUG fprintf(stdout, "i=%d j=%d M=\n", i+1, j+1); Matrix_Print(stdout,P_VALUE_FMT,Mat); #endif /* Add Mat to Q and see if anything is made */ Q3 = AddConstraints(Mat->p[0],2,Q,NbMaxConstrs); #ifdef DEBUG fprintf(stdout, "Q3\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q3); #endif if (!emptyQ(Q3)) { Domain_Free(Q3); #ifdef DEBUG fprintf(stdout, "not empty\n"); #endif res = -1; goto LTQdone; } #ifdef DEBUG fprintf(stdout,"empty\n"); #endif Domain_Free(Q3); } /* end for j */ } /* end for i */ res = 1; LTQdone: Matrix_Free(Mat); LTQdone2: Domain_Free(Q4); Domain_Free(Q1); Domain_Free(Q2); } Domain_Free(Q); #ifdef DEBUG fprintf(stdout, "res = %d\n", res); #endif return res; } /* PolyhedronLTQ */
/** * Given a system of equalities, looks if it has an integer solution in the * combined space, and if yes, returns one solution. * <p>pre-condition: the equalities are full-row rank (without the constant * part)</p> * @param Eqs the system of equations (as constraints) * @param I a feasible integer solution if it exists, else NULL. Allocated if * initially set to NULL, else reused. */ void Equalities_integerSolution(Matrix * Eqs, Matrix **I) { Matrix * Hm, *H=NULL, *U, *Q, *M=NULL, *C=NULL, *Hi; Matrix *Ip; int i; Value mod; unsigned int rk; if (Eqs==NULL){ if ((*I)!=NULL) Matrix_Free(*I); I = NULL; return; } /* we use: AI = C = (Ha 0).Q.I = (Ha 0)(I' 0)^T */ /* with I = Qinv.I' = U.I'*/ /* 1- compute I' = Hainv.(-C) */ /* HYP: the equalities are full-row rank */ rk = Eqs->NbRows; Matrix_subMatrix(Eqs, 0, 1, rk, Eqs->NbColumns-1, &M); left_hermite(M, &Hm, &Q, &U); Matrix_Free(M); Matrix_subMatrix(Hm, 0, 0, rk, rk, &H); if (dbgCompParmMore) { show_matrix(Hm); show_matrix(H); show_matrix(U); } Matrix_Free(Q); Matrix_Free(Hm); Matrix_subMatrix(Eqs, 0, Eqs->NbColumns-1, rk, Eqs->NbColumns, &C); Matrix_oppose(C); Hi = Matrix_Alloc(rk, rk+1); MatInverse(H, Hi); if (dbgCompParmMore) { show_matrix(C); show_matrix(Hi); } /* put the numerator of Hinv back into H */ Matrix_subMatrix(Hi, 0, 0, rk, rk, &H); Ip = Matrix_Alloc(Eqs->NbColumns-2, 1); /* fool Matrix_Product on the size of Ip */ Ip->NbRows = rk; Matrix_Product(H, C, Ip); Ip->NbRows = Eqs->NbColumns-2; Matrix_Free(H); Matrix_Free(C); value_init(mod); for (i=0; i< rk; i++) { /* if Hinv.C is not integer, return NULL (no solution) */ value_pmodulus(mod, Ip->p[i][0], Hi->p[i][rk]); if (value_notzero_p(mod)) { if ((*I)!=NULL) Matrix_Free(*I); value_clear(mod); Matrix_Free(U); Matrix_Free(Ip); Matrix_Free(Hi); I = NULL; return; } else { value_pdivision(Ip->p[i][0], Ip->p[i][0], Hi->p[i][rk]); } } /* fill the rest of I' with zeros */ for (i=rk; i< Eqs->NbColumns-2; i++) { value_set_si(Ip->p[i][0], 0); } value_clear(mod); Matrix_Free(Hi); /* 2 - Compute the particular solution I = U.(I' 0) */ ensureMatrix((*I), Eqs->NbColumns-2, 1); Matrix_Product(U, Ip, (*I)); Matrix_Free(U); Matrix_Free(Ip); if (dbgCompParm) { show_matrix(*I); } }
/* * Given a Z-polyhderon 'A' and a Z-domain 'Head', return a new Z-domain with * 'A' added to it. If the new Z-polyhedron 'A', is already included in the * Z-domain 'Head', it is not added in the list. Othewise, the function checks * if the new Z-polyhedron 'A' to be added to the Z-domain 'Head' has a common * lattice with some other Z-polyhderon already present in the Z-domain. If it * is so, it takes the union of the underlying polyhdera; domains and returns. * The function tries to make sure that the added Z-polyhedron 'A' is in the * canonical form. */ static ZPolyhedron *AddZPolytoZDomain(ZPolyhedron *A, ZPolyhedron *Head) { ZPolyhedron *Zpol, *temp, *temp1; Polyhedron *i; Bool Added; if ((A == NULL) || (isEmptyZPolyhedron(A))) return Head; /* For each "underlying" Pol, find the Cnf and add Zpol in Cnf*/ for(i=A->P; i!= NULL; i=i->next) { ZPolyhedron *Z, *Z1; Polyhedron *Image; Matrix *H, *U; Lattice *Lat ; Added = False; Image = Domain_Copy(i); Domain_Free(Image->next); Image->next = NULL; Z1 = ZPolyhedron_Alloc(A->Lat,Image); Domain_Free(Image); CanonicalForm(Z1,&Z,&H); ZDomain_Free(Z1); Lat = (Lattice *)Matrix_Alloc(H->NbRows,Z->Lat->NbColumns); Matrix_Product(H,Z->Lat,(Matrix *)Lat); Matrix_Free(H); AffineHermite(Lat,(Lattice **)&H,&U); Image = DomainImage(Z->P,U,MAXNOOFRAYS); ZDomain_Free(Z); Zpol=ZPolyhedron_Alloc((Lattice *)H,Image); Domain_Free(Image); Matrix_Free((Matrix *)Lat); Matrix_Free(H); Matrix_Free(U); if ((Head == NULL) || (isEmptyZPolyhedron (Head))) { Head = Zpol; continue; } temp1 = temp = Head; /* Check if the curr pol is included in the zpol or vice versa. */ for(; temp != NULL; temp = temp->next) { if (ZPolyhedronIncludes(Zpol, temp) == True) { ZPolyhedron_Free (Zpol); Added = True; break; } else if (ZPolyhedronIncludes(temp, Zpol) == True) { if (temp == Head) { Zpol->next = temp->next; Head = Zpol; ZPolyhedron_Free (temp); Added = True; break; } temp1->next = Zpol; Zpol->next = temp->next; ZPolyhedron_Free (temp); Added = True; break ; } temp1 = temp ; } if(Added == True) continue ; for(temp = Head; temp != NULL; temp = temp->next) { if(sameLattice(temp->Lat, Zpol->Lat) == True) { Polyhedron *Union; Union = DomainUnion (temp->P,Zpol->P,MAXNOOFRAYS); if (!Union) fprintf (stderr,"\n In AddZPolytoZDomain: Out of memory\n"); else { Domain_Free(temp->P); temp->P = Union; Added = True; ZPolyhedron_Free(Zpol); } break ; } temp1 = temp; } if (Added == False) temp1->next = Zpol; } return Head ; } /* AddZPolytoZDomain */
/** * Tests Constraints_fullDimensionize by comparing the Ehrhart polynomials * @param A the input set of constraints * @param B the corresponding context * @param the number of samples to generate for the test * @return 1 if the Ehrhart polynomial had the same value for the * full-dimensional and non-full-dimensional sets of constraints, for their * corresponding sample parameters values. */ int test_Constraints_fullDimensionize(Matrix * A, Matrix * B, unsigned int nbSamples) { Matrix * Eqs= NULL, *ParmEqs=NULL, *VL=NULL; unsigned int * elimVars=NULL, * elimParms=NULL; Matrix * sample, * smallerSample=NULL; Matrix * transfSample=NULL; Matrix * parmVL=NULL; unsigned int i, j, r, nbOrigParms, nbParms; Value div, mod, *origVal=NULL, *fullVal=NULL; Matrix * VLInv; Polyhedron * P, *PC; Matrix * M, *C; Enumeration * origEP, * fullEP=NULL; const char **fullNames = NULL; int isOk = 1; /* holds the result */ /* compute the origial Ehrhart polynomial */ M = Matrix_Copy(A); C = Matrix_Copy(B); P = Constraints2Polyhedron(M, maxRays); PC = Constraints2Polyhedron(C, maxRays); origEP = Polyhedron_Enumerate(P, PC, maxRays, origNames); Matrix_Free(M); Matrix_Free(C); Polyhedron_Free(P); Polyhedron_Free(PC); /* compute the full-dimensional polyhedron corresponding to A and its Ehrhart polynomial */ M = Matrix_Copy(A); C = Matrix_Copy(B); nbOrigParms = B->NbColumns-2; Constraints_fullDimensionize(&M, &C, &VL, &Eqs, &ParmEqs, &elimVars, &elimParms, maxRays); if ((Eqs->NbRows==0) && (ParmEqs->NbRows==0)) { Matrix_Free(M); Matrix_Free(C); Matrix_Free(Eqs); Matrix_Free(ParmEqs); free(elimVars); free(elimParms); return 1; } nbParms = C->NbColumns-2; P = Constraints2Polyhedron(M, maxRays); PC = Constraints2Polyhedron(C, maxRays); namesWithoutElim(origNames, nbOrigParms, elimParms, &fullNames); fullEP = Polyhedron_Enumerate(P, PC, maxRays, fullNames); Matrix_Free(M); Matrix_Free(C); Polyhedron_Free(P); Polyhedron_Free(PC); /* make a set of sample parameter values and compare the corresponding Ehrhart polnomials */ sample = Matrix_Alloc(1,nbOrigParms); transfSample = Matrix_Alloc(1, nbParms); Lattice_extractSubLattice(VL, nbParms, &parmVL); VLInv = Matrix_Alloc(parmVL->NbRows, parmVL->NbRows+1); MatInverse(parmVL, VLInv); if (dbg) { show_matrix(parmVL); show_matrix(VLInv); } srand(nbSamples); value_init(mod); value_init(div); for (i = 0; i< nbSamples; i++) { /* create a random sample */ for (j=0; j< nbOrigParms; j++) { value_set_si(sample->p[0][j], rand()%100); } /* compute the corresponding value for the full-dimensional constraints */ valuesWithoutElim(sample, elimParms, &smallerSample); /* (N' i' 1)^T = VLinv.(N i 1)^T*/ for (r = 0; r < nbParms; r++) { Inner_Product(&(VLInv->p[r][0]), smallerSample->p[0], nbParms, &(transfSample->p[0][r])); /* add the constant part */ value_addto(transfSample->p[0][r], transfSample->p[0][r], VLInv->p[r][VLInv->NbColumns-2]); value_pdivision(div, transfSample->p[0][r], VLInv->p[r][VLInv->NbColumns-1]); value_subtract(mod, transfSample->p[0][r], div); /* if the parameters value does not belong to the validity lattice, the Ehrhart polynomial is zero. */ if (!value_zero_p(mod)) { fullEP = Enumeration_zero(nbParms, maxRays); break; } } /* compare the two forms of the Ehrhart polynomial.*/ if (origEP ==NULL) break; /* NULL has loose semantics for EPs */ origVal = compute_poly(origEP, sample->p[0]); fullVal = compute_poly(fullEP, transfSample->p[0]); if (!value_eq(*origVal, *fullVal)) { isOk = 0; printf("EPs don't match. \n Original value = "); value_print(stdout, VALUE_FMT, *origVal); printf("\n Original sample = ["); for (j=0; j<sample->NbColumns; j++) { value_print(stdout, VALUE_FMT, sample->p[0][j]); printf(" "); } printf("] \n EP = "); if(origEP!=NULL) { print_evalue(stdout, &(origEP->EP), origNames); } else { printf("NULL"); } printf(" \n Full-dimensional value = "); value_print(stdout, P_VALUE_FMT, *fullVal); printf("\n full-dimensional sample = ["); for (j=0; j<sample->NbColumns; j++) { value_print(stdout, VALUE_FMT, transfSample->p[0][j]); printf(" "); } printf("] \n EP = "); if(origEP!=NULL) { print_evalue(stdout, &(origEP->EP), fullNames); } else { printf("NULL"); } } if (dbg) { printf("\nOriginal value = "); value_print(stdout, VALUE_FMT, *origVal); printf("\nFull-dimensional value = "); value_print(stdout, P_VALUE_FMT, *fullVal); printf("\n"); } value_clear(*origVal); value_clear(*fullVal); } value_clear(mod); value_clear(div); Matrix_Free(sample); Matrix_Free(smallerSample); Matrix_Free(transfSample); Enumeration_Free(origEP); Enumeration_Free(fullEP); return isOk; } /* test_Constraints_fullDimensionize */
void right_hermite(Matrix *A,Matrix **Hp,Matrix **Up,Matrix **Qp) { Matrix *H, *Q, *U; int i, j, nr, nc, rank; Value tmp; /* Computes form: A = QH , UA = H */ nc = A->NbColumns; nr = A->NbRows; /* H = A */ *Hp = H = Matrix_Alloc(nr,nc); if (!H) { errormsg1("DomRightHermite", "outofmem", "out of memory space"); return; } /* Initialize all the 'Value' variables */ value_init(tmp); Vector_Copy(A->p_Init,H->p_Init,nr*nc); /* U = I */ if (Up) { *Up = U = Matrix_Alloc(nr, nr); if (!U) { errormsg1("DomRightHermite", "outofmem", "out of memory space"); value_clear(tmp); return; } Vector_Set(U->p_Init,0,nr*nr); /* zero's */ for(i=0;i<nr;i++) /* with diagonal of 1's */ value_set_si(U->p[i][i],1); } else U = (Matrix *)0; /* Q = I */ /* Actually I compute Q transpose... its easier */ if (Qp) { *Qp = Q = Matrix_Alloc(nr,nr); if (!Q) { errormsg1("DomRightHermite", "outofmem", "out of memory space"); value_clear(tmp); return; } Vector_Set(Q->p_Init,0,nr*nr); /* zero's */ for (i=0;i<nr;i++) /* with diagonal of 1's */ value_set_si(Q->p[i][i],1); } else Q = (Matrix *)0; rank = hermite(H,U,Q); /* Q is returned transposed */ /* Transpose Q */ if (Q) { for (i=0; i<nr; i++) { for (j=i+1; j<nr; j++) { value_assign(tmp,Q->p[i][j]); value_assign(Q->p[i][j],Q->p[j][i] ); value_assign(Q->p[j][i],tmp); } } } value_clear(tmp); return; } /* right_hermite */
/** Removes the equalities that involve only parameters, by eliminating some * parameters in the polyhedron's constraints and in the context.<p> * <b>Updates M and Ctxt.</b> * @param M1 the polyhedron's constraints * @param Ctxt1 the constraints of the polyhedron's context * @param renderSpace tells if the returned equalities must be expressed in the * parameters space (renderSpace=0) or in the combined var/parms space * (renderSpace = 1) * @param elimParms the list of parameters that have been removed: an array * whose 1st element is the number of elements in the list. (returned) * @return the system of equalities that involve only parameters. */ Matrix * Constraints_Remove_parm_eqs(Matrix ** M1, Matrix ** Ctxt1, int renderSpace, unsigned int ** elimParms) { int i, j, k, nbEqsParms =0; int nbEqsM, nbEqsCtxt, allZeros, nbTautoM = 0, nbTautoCtxt = 0; Matrix * M = (*M1); Matrix * Ctxt = (*Ctxt1); int nbVars = M->NbColumns-Ctxt->NbColumns; Matrix * Eqs; Matrix * EqsMTmp; /* 1- build the equality matrix(ces) */ nbEqsM = 0; for (i=0; i< M->NbRows; i++) { k = First_Non_Zero(M->p[i], M->NbColumns); /* if it is a tautology, count it as such */ if (k==-1) { nbTautoM++; } else { /* if it only involves parameters, count it */ if (k>= nbVars+1) nbEqsM++; } } nbEqsCtxt = 0; for (i=0; i< Ctxt->NbRows; i++) { if (value_zero_p(Ctxt->p[i][0])) { if (First_Non_Zero(Ctxt->p[i], Ctxt->NbColumns)==-1) { nbTautoCtxt++; } else { nbEqsCtxt ++; } } } nbEqsParms = nbEqsM + nbEqsCtxt; /* nothing to do in this case */ if (nbEqsParms+nbTautoM+nbTautoCtxt==0) { (*elimParms) = (unsigned int*) malloc(sizeof(int)); (*elimParms)[0] = 0; if (renderSpace==0) { return Matrix_Alloc(0,Ctxt->NbColumns); } else { return Matrix_Alloc(0,M->NbColumns); } } Eqs= Matrix_Alloc(nbEqsParms, Ctxt->NbColumns); EqsMTmp= Matrix_Alloc(nbEqsParms, M->NbColumns); /* copy equalities from the context */ k = 0; for (i=0; i< Ctxt->NbRows; i++) { if (value_zero_p(Ctxt->p[i][0]) && First_Non_Zero(Ctxt->p[i], Ctxt->NbColumns)!=-1) { Vector_Copy(Ctxt->p[i], Eqs->p[k], Ctxt->NbColumns); Vector_Copy(Ctxt->p[i]+1, EqsMTmp->p[k]+nbVars+1, Ctxt->NbColumns-1); k++; } } for (i=0; i< M->NbRows; i++) { j=First_Non_Zero(M->p[i], M->NbColumns); /* copy equalities that involve only parameters from M */ if (j>=nbVars+1) { Vector_Copy(M->p[i]+nbVars+1, Eqs->p[k]+1, Ctxt->NbColumns-1); Vector_Copy(M->p[i]+nbVars+1, EqsMTmp->p[k]+nbVars+1, Ctxt->NbColumns-1); /* mark these equalities for removal */ value_set_si(M->p[i][0], 2); k++; } /* mark the all-zero equalities for removal */ if (j==-1) { value_set_si(M->p[i][0], 2); } } /* 2- eliminate parameters until all equalities are used or until we find a contradiction (overconstrained system) */ (*elimParms) = (unsigned int *) malloc((Eqs->NbRows+1) * sizeof(int)); (*elimParms)[0] = 0; allZeros = 0; for (i=0; i< Eqs->NbRows; i++) { /* find a variable that can be eliminated */ k = First_Non_Zero(Eqs->p[i], Eqs->NbColumns); if (k!=-1) { /* nothing special to do for tautologies */ /* if there is a contradiction, return empty matrices */ if (k==Eqs->NbColumns-1) { printf("Contradiction in %dth row of Eqs: ",k); show_matrix(Eqs); Matrix_Free(Eqs); Matrix_Free(EqsMTmp); (*M1) = Matrix_Alloc(0, M->NbColumns); Matrix_Free(M); (*Ctxt1) = Matrix_Alloc(0,Ctxt->NbColumns); Matrix_Free(Ctxt); free(*elimParms); (*elimParms) = (unsigned int *) malloc(sizeof(int)); (*elimParms)[0] = 0; if (renderSpace==1) { return Matrix_Alloc(0,(*M1)->NbColumns); } else { return Matrix_Alloc(0,(*Ctxt1)->NbColumns); } } /* if we have something we can eliminate, do it in 3 places: Eqs, Ctxt, and M */ else { k--; /* k is the rank of the variable, now */ (*elimParms)[0]++; (*elimParms)[(*elimParms[0])]=k; for (j=0; j< Eqs->NbRows; j++) { if (i!=j) { eliminate_var_with_constr(Eqs, i, Eqs, j, k); eliminate_var_with_constr(EqsMTmp, i, EqsMTmp, j, k+nbVars); } } for (j=0; j< Ctxt->NbRows; j++) { if (value_notzero_p(Ctxt->p[i][0])) { eliminate_var_with_constr(Eqs, i, Ctxt, j, k); } } for (j=0; j< M->NbRows; j++) { if (value_cmp_si(M->p[i][0], 2)) { eliminate_var_with_constr(EqsMTmp, i, M, j, k+nbVars); } } } } /* if (k==-1): count the tautologies in Eqs to remove them later */ else { allZeros++; } } /* elimParms may have been overallocated. Now we know how many parms have been eliminated so we can reallocate the right amount of memory. */ if (!realloc((*elimParms), ((*elimParms)[0]+1)*sizeof(int))) { fprintf(stderr, "Constraints_Remove_parm_eqs > cannot realloc()"); } Matrix_Free(EqsMTmp); /* 3- remove the "bad" equalities from the input matrices and copy the equalities involving only parameters */ EqsMTmp = Matrix_Alloc(M->NbRows-nbEqsM-nbTautoM, M->NbColumns); k=0; for (i=0; i< M->NbRows; i++) { if (value_cmp_si(M->p[i][0], 2)) { Vector_Copy(M->p[i], EqsMTmp->p[k], M->NbColumns); k++; } } Matrix_Free(M); (*M1) = EqsMTmp; EqsMTmp = Matrix_Alloc(Ctxt->NbRows-nbEqsCtxt-nbTautoCtxt, Ctxt->NbColumns); k=0; for (i=0; i< Ctxt->NbRows; i++) { if (value_notzero_p(Ctxt->p[i][0])) { Vector_Copy(Ctxt->p[i], EqsMTmp->p[k], Ctxt->NbColumns); k++; } } Matrix_Free(Ctxt); (*Ctxt1) = EqsMTmp; if (renderSpace==0) {/* renderSpace=0: equalities in the parameter space */ EqsMTmp = Matrix_Alloc(Eqs->NbRows-allZeros, Eqs->NbColumns); k=0; for (i=0; i<Eqs->NbRows; i++) { if (First_Non_Zero(Eqs->p[i], Eqs->NbColumns)!=-1) { Vector_Copy(Eqs->p[i], EqsMTmp->p[k], Eqs->NbColumns); k++; } } } else {/* renderSpace=1: equalities rendered in the combined space */ EqsMTmp = Matrix_Alloc(Eqs->NbRows-allZeros, (*M1)->NbColumns); k=0; for (i=0; i<Eqs->NbRows; i++) { if (First_Non_Zero(Eqs->p[i], Eqs->NbColumns)!=-1) { Vector_Copy(Eqs->p[i], &(EqsMTmp->p[k][nbVars]), Eqs->NbColumns); k++; } } } Matrix_Free(Eqs); Eqs = EqsMTmp; return Eqs; } /* Constraints_Remove_parm_eqs */
/* * Return the Z-polyhderon 'Zpol' in canonical form: 'Result' (for the Z-poly- * hedron in canonical form) and Basis 'Basis' (for the basis with respect to * which 'Result' is in canonical form. */ void CanonicalForm(ZPolyhedron *Zpol,ZPolyhedron **Result,Matrix **Basis) { Matrix *B1 = NULL, *B2=NULL, *T1 , *B2inv; int i, l1, l2; Value tmp; Polyhedron *Image, *ImageP; Matrix *H, *U, *temp, *Hprime, *Uprime, *T2; #ifdef DOMDEBUG FILE *fp; fp = fopen("_debug", "a"); fprintf(fp,"\nEntered CANONICALFORM\n"); fclose(fp); #endif if(isEmptyZPolyhedron (Zpol)) { Basis[0] = Identity(Zpol->Lat->NbRows); Result[0] = ZDomain_Copy (Zpol); return ; } value_init(tmp); l1 = FindHermiteBasisofDomain(Zpol->P,&B1); Image = DomainImage (Zpol->P,(Matrix *)Zpol->Lat,MAXNOOFRAYS); l2 = FindHermiteBasisofDomain(Image,&B2); if (l1 != l2) fprintf(stderr,"In CNF : Something wrong with the Input Zpolyhedra \n"); B2inv = Matrix_Alloc(B2->NbRows, B2->NbColumns); temp = Matrix_Copy(B2); Matrix_Inverse(temp,B2inv); Matrix_Free(temp); temp = Matrix_Alloc(B2inv->NbRows,Zpol->Lat->NbColumns); T1 = Matrix_Alloc(temp->NbRows,B1->NbColumns); Matrix_Product(B2inv,(Matrix *)Zpol->Lat,temp); Matrix_Product(temp,B1,T1); Matrix_Free(temp); T2 = ChangeLatticeDimension(T1,l1); temp = ChangeLatticeDimension(T2,T2->NbRows+1); /* Adding the affine part */ for(i = 0; i < l1; i ++) value_assign(temp->p[i][temp->NbColumns-1],T1->p[i][T1->NbColumns-1]); AffineHermite(temp,&H,&U); Hprime = ChangeLatticeDimension(H,Zpol->Lat->NbRows); /* Exchanging the Affine part */ for(i = 0; i < l1; i ++) { value_assign(tmp,Hprime->p[i][Hprime->NbColumns-1]); value_assign(Hprime->p[i][Hprime->NbColumns-1],Hprime->p[i][H->NbColumns-1]); value_assign(Hprime->p[i][H->NbColumns-1],tmp); } Uprime = ChangeLatticeDimension(U,Zpol->Lat->NbRows); /* Exchanging the Affine part */ for (i = 0;i < l1; i++) { value_assign(tmp,Uprime->p[i][Uprime->NbColumns-1]); value_assign(Uprime->p[i][Uprime->NbColumns-1],Uprime->p[i][U->NbColumns-1]); value_assign(Uprime->p[i][U->NbColumns-1],tmp); } Polyhedron_Free (Image); Matrix_Free (B2inv); B2inv = Matrix_Alloc(B1->NbRows, B1->NbColumns); Matrix_Inverse(B1,B2inv); ImageP = DomainImage(Zpol->P, B2inv, MAXNOOFRAYS); Matrix_Free(B2inv); Image = DomainImage(ImageP, Uprime, MAXNOOFRAYS); Domain_Free(ImageP); Result[0] = ZPolyhedron_Alloc(Hprime, Image); Basis[0] = Matrix_Copy(B2); /* Free the variables */ Polyhedron_Free (Image); Matrix_Free (B1); Matrix_Free (B2); Matrix_Free (temp); Matrix_Free (T1); Matrix_Free (T2); Matrix_Free (H); Matrix_Free (U); Matrix_Free (Hprime); Matrix_Free (Uprime); value_clear(tmp); return; } /* CanonicalForm */
int main(int argc, char **argv) { isl_ctx *ctx; int i, nbPol, nbVec, nbMat, func, j, n; Polyhedron *A, *B, *C, *D, *E, *F, *G; char s[128]; struct barvinok_options *options = barvinok_options_new_with_defaults(); argc = barvinok_options_parse(options, argc, argv, ISL_ARG_ALL); ctx = isl_ctx_alloc_with_options(&barvinok_options_args, options); nbPol = nbVec = nbMat = 0; fgets(s, 128, stdin); while ((*s=='#') || ((sscanf(s, "D %d", &nbPol) < 1) && (sscanf(s, "V %d", &nbVec) < 1) && (sscanf(s, "M %d", &nbMat) < 1))) fgets(s, 128, stdin); for (i = 0; i < nbPol; ++i) { Matrix *M = Matrix_Read(); A = Constraints2Polyhedron(M, options->MaxRays); Matrix_Free(M); fgets(s, 128, stdin); while ((*s=='#') || (sscanf(s, "F %d", &func)<1)) fgets(s, 128, stdin); switch(func) { case 0: { Value cb, ck; value_init(cb); value_init(ck); fgets(s, 128, stdin); /* workaround for apparent bug in older gmps */ *strchr(s, '\n') = '\0'; while ((*s=='#') || (value_read(ck, s) != 0)) { fgets(s, 128, stdin); /* workaround for apparent bug in older gmps */ *strchr(s, '\n') = '\0'; } barvinok_count_with_options(A, &cb, options); if (value_ne(cb, ck)) return -1; value_clear(cb); value_clear(ck); break; } case 1: Polyhedron_Print(stdout, P_VALUE_FMT, A); B = Polyhedron_Polar(A, options->MaxRays); Polyhedron_Print(stdout, P_VALUE_FMT, B); C = Polyhedron_Polar(B, options->MaxRays); Polyhedron_Print(stdout, P_VALUE_FMT, C); Polyhedron_Free(C); Polyhedron_Free(B); break; case 2: Polyhedron_Print(stdout, P_VALUE_FMT, A); for (j = 0; j < A->NbRays; ++j) { B = supporting_cone(A, j); Polyhedron_Print(stdout, P_VALUE_FMT, B); Polyhedron_Free(B); } break; case 3: Polyhedron_Print(stdout, P_VALUE_FMT, A); C = B = NULL; barvinok_decompose(A,&B,&C); puts("Pos:"); Polyhedron_Print(stdout, P_VALUE_FMT, B); puts("Neg:"); Polyhedron_Print(stdout, P_VALUE_FMT, C); Domain_Free(B); Domain_Free(C); break; case 4: { Value cm, cb; struct tms tms_before, tms_between, tms_after; value_init(cm); value_init(cb); Polyhedron_Print(stdout, P_VALUE_FMT, A); times(&tms_before); manual_count(A, &cm); times(&tms_between); barvinok_count(A, &cb, 100); times(&tms_after); printf("manual: "); value_print(stdout, P_VALUE_FMT, cm); puts(""); time_diff(&tms_before, &tms_between); printf("Barvinok: "); value_print(stdout, P_VALUE_FMT, cb); puts(""); time_diff(&tms_between, &tms_after); value_clear(cm); value_clear(cb); break; } case 5: Polyhedron_Print(stdout, P_VALUE_FMT, A); B = triangulate_cone(A, 100); Polyhedron_Print(stdout, P_VALUE_FMT, B); check_triangulization(A, B); Domain_Free(B); break; case 6: Polyhedron_Print(stdout, P_VALUE_FMT, A); B = remove_equalities(A, options->MaxRays); Polyhedron_Print(stdout, P_VALUE_FMT, B); Polyhedron_Free(B); break; case 8: { evalue *EP; Matrix *M = Matrix_Read(); const char **param_name; C = Constraints2Polyhedron(M, options->MaxRays); Matrix_Free(M); Polyhedron_Print(stdout, P_VALUE_FMT, A); Polyhedron_Print(stdout, P_VALUE_FMT, C); EP = barvinok_enumerate_with_options(A, C, options); param_name = Read_ParamNames(stdin, C->Dimension); print_evalue(stdout, EP, (const char**)param_name); evalue_free(EP); Polyhedron_Free(C); } case 9: Polyhedron_Print(stdout, P_VALUE_FMT, A); Polyhedron_Polarize(A); C = B = NULL; barvinok_decompose(A,&B,&C); for (D = B; D; D = D->next) Polyhedron_Polarize(D); for (D = C; D; D = D->next) Polyhedron_Polarize(D); puts("Pos:"); Polyhedron_Print(stdout, P_VALUE_FMT, B); puts("Neg:"); Polyhedron_Print(stdout, P_VALUE_FMT, C); Domain_Free(B); Domain_Free(C); break; case 10: { evalue *EP; Value cb, ck; value_init(cb); value_init(ck); fgets(s, 128, stdin); sscanf(s, "%d", &n); for (j = 0; j < n; ++j) { Polyhedron *P; M = Matrix_Read(); P = Constraints2Polyhedron(M, options->MaxRays); Matrix_Free(M); A = DomainConcat(P, A); } fgets(s, 128, stdin); /* workaround for apparent bug in older gmps */ *strchr(s, '\n') = '\0'; while ((*s=='#') || (value_read(ck, s) != 0)) { fgets(s, 128, stdin); /* workaround for apparent bug in older gmps */ *strchr(s, '\n') = '\0'; } C = Universe_Polyhedron(0); EP = barvinok_enumerate_union(A, C, options->MaxRays); value_set_double(cb, compute_evalue(EP, &ck)+.25); if (value_ne(cb, ck)) return -1; Domain_Free(C); value_clear(cb); value_clear(ck); evalue_free(EP); break; } case 11: { isl_space *dim; isl_basic_set *bset; isl_pw_qpolynomial *expected, *computed; unsigned nparam; expected = isl_pw_qpolynomial_read_from_file(ctx, stdin); nparam = isl_pw_qpolynomial_dim(expected, isl_dim_param); dim = isl_space_set_alloc(ctx, nparam, A->Dimension - nparam); bset = isl_basic_set_new_from_polylib(A, dim); computed = isl_basic_set_lattice_width(bset); computed = isl_pw_qpolynomial_sub(computed, expected); if (!isl_pw_qpolynomial_is_zero(computed)) return -1; isl_pw_qpolynomial_free(computed); break; } case 12: { Vector *sample; int has_sample; fgets(s, 128, stdin); sscanf(s, "%d", &has_sample); sample = Polyhedron_Sample(A, options); if (!sample && has_sample) return -1; if (sample && !has_sample) return -1; if (sample && !in_domain(A, sample->p)) return -1; Vector_Free(sample); } } Domain_Free(A); } for (i = 0; i < nbVec; ++i) { int ok; Vector *V = Vector_Read(); Matrix *M = Matrix_Alloc(V->Size, V->Size); Vector_Copy(V->p, M->p[0], V->Size); ok = unimodular_complete(M, 1); assert(ok); Matrix_Print(stdout, P_VALUE_FMT, M); Matrix_Free(M); Vector_Free(V); } for (i = 0; i < nbMat; ++i) { Matrix *U, *V, *S; Matrix *M = Matrix_Read(); Smith(M, &U, &V, &S); Matrix_Print(stdout, P_VALUE_FMT, U); Matrix_Print(stdout, P_VALUE_FMT, V); Matrix_Print(stdout, P_VALUE_FMT, S); Matrix_Free(M); Matrix_Free(U); Matrix_Free(V); Matrix_Free(S); } isl_ctx_free(ctx); return 0; }
/* Assumes C is a linear cone (i.e. with apex zero). * All equalities are removed first to speed up the computation * in zsolve. */ Matrix *Cone_Hilbert_Basis(Polyhedron *C, unsigned MaxRays) { unsigned dim; int i; Matrix *M2, *M3, *T; Matrix *CV = NULL; LinearSystem initialsystem; ZSolveMatrix matrix; ZSolveVector rhs; ZSolveContext ctx; remove_all_equalities(&C, NULL, NULL, &CV, 0, MaxRays); dim = C->Dimension; for (i = 0; i < C->NbConstraints; ++i) assert(value_zero_p(C->Constraint[i][1+dim]) || First_Non_Zero(C->Constraint[i]+1, dim) == -1); M2 = Polyhedron2standard_form(C, &T); matrix = Matrix2zsolve(M2); Matrix_Free(M2); rhs = createVector(matrix->Height); for (i = 0; i < matrix->Height; i++) rhs[i] = 0; initialsystem = createLinearSystem(); setLinearSystemMatrix(initialsystem, matrix); deleteMatrix(matrix); setLinearSystemRHS(initialsystem, rhs); deleteVector(rhs); setLinearSystemLimit(initialsystem, -1, 0, MAXINT, 0); setLinearSystemEquationType(initialsystem, -1, EQUATION_EQUAL, 0); ctx = createZSolveContextFromSystem(initialsystem, NULL, 0, 0, NULL, NULL); zsolveSystem(ctx, 0); M2 = VectorArray2Matrix(ctx->Homs, C->Dimension); deleteZSolveContext(ctx, 1); Matrix_Transposition(T); M3 = Matrix_Alloc(M2->NbRows, M2->NbColumns); Matrix_Product(M2, T, M3); Matrix_Free(M2); Matrix_Free(T); if (CV) { Matrix *T, *M; T = Transpose(CV); M = Matrix_Alloc(M3->NbRows, T->NbColumns); Matrix_Product(M3, T, M); Matrix_Free(M3); Matrix_Free(CV); Matrix_Free(T); Polyhedron_Free(C); M3 = M; } return M3; }
void left_hermite(Matrix *A,Matrix **Hp,Matrix **Qp,Matrix **Up) { Matrix *H, *HT, *Q, *U; int i, j, nc, nr, rank; Value tmp; /* Computes left form: A = HQ , AU = H , T T T T T T using right form A = Q H , U A = H */ nr = A->NbRows; nc = A->NbColumns; /* HT = A transpose */ HT = Matrix_Alloc(nc, nr); if (!HT) { errormsg1("DomLeftHermite", "outofmem", "out of memory space"); return; } value_init(tmp); for (i=0; i<nr; i++) for (j=0; j<nc; j++) value_assign(HT->p[j][i],A->p[i][j]); /* U = I */ if (Up) { *Up = U = Matrix_Alloc(nc,nc); if (!U) { errormsg1("DomLeftHermite", "outofmem", "out of memory space"); value_clear(tmp); return; } Vector_Set(U->p_Init,0,nc*nc); /* zero's */ for (i=0;i<nc;i++) /* with diagonal of 1's */ value_set_si(U->p[i][i],1); } else U=(Matrix *)0; /* Q = I */ if (Qp) { *Qp = Q = Matrix_Alloc(nc, nc); if (!Q) { errormsg1("DomLeftHermite", "outofmem", "out of memory space"); value_clear(tmp); return; } Vector_Set(Q->p_Init,0,nc*nc); /* zero's */ for (i=0;i<nc;i++) /* with diagonal of 1's */ value_set_si(Q->p[i][i],1); } else Q=(Matrix *)0; rank = hermite(HT,U,Q); /* H = HT transpose */ *Hp = H = Matrix_Alloc(nr,nc); if (!H) { errormsg1("DomLeftHermite", "outofmem", "out of memory space"); value_clear(tmp); return; } for (i=0; i<nr; i++) for (j=0;j<nc;j++) value_assign(H->p[i][j],HT->p[j][i]); Matrix_Free(HT); /* Transpose U */ if (U) { for (i=0; i<nc; i++) { for (j=i+1; j<nc; j++) { value_assign(tmp,U->p[i][j]); value_assign(U->p[i][j],U->p[j][i] ); value_assign(U->p[j][i],tmp); } } } value_clear(tmp); } /* left_hermite */
/** * Given a matrix with m parameterized equations, compress the nb_parms * parameters and n-m variables so that m variables are integer, and transform * the variable space into a n-m space by eliminating the m variables (using * the equalities) the variables to be eliminated are chosen automatically by * the function. * <b>Deprecated.</b> Try to use Constraints_fullDimensionize instead. * @param M the constraints * @param the number of parameters * @param validityLattice the the integer lattice underlying the integer * solutions. */ Matrix * full_dimensionize(Matrix const * M, int nbParms, Matrix ** validityLattice) { Matrix * Eqs, * Ineqs; Matrix * permutedEqs, * permutedIneqs; Matrix * Full_Dim; Matrix * WVL; /* The Whole Validity Lattice (vars+parms) */ unsigned int i,j; int nbElimVars; unsigned int * permutation, * permutationInv; /* 0- Split the equalities and inequalities from each other */ split_constraints(M, &Eqs, &Ineqs); /* 1- if the polyhedron is already full-dimensional, return it */ if (Eqs->NbRows==0) { Matrix_Free(Eqs); (*validityLattice) = Identity_Matrix(nbParms+1); return Ineqs; } nbElimVars = Eqs->NbRows; /* 2- put the vars to be eliminated at the first positions, and compress the other vars/parms -> [ variables to eliminate / parameters / variables to keep ] */ permutation = find_a_permutation(Eqs, nbParms); if (dbgCompParm) { printf("Permuting the vars/parms this way: [ "); for (i=0; i< Eqs->NbColumns; i++) { printf("%d ", permutation[i]); } printf("]\n"); } permutedEqs = mpolyhedron_permute(Eqs, permutation); WVL = compress_parms(permutedEqs, Eqs->NbColumns-2-Eqs->NbRows); if (dbgCompParm) { printf("Whole validity lattice: "); show_matrix(WVL); } mpolyhedron_compress_last_vars(permutedEqs, WVL); permutedIneqs = mpolyhedron_permute(Ineqs, permutation); if (dbgCompParm) { show_matrix(permutedEqs); } Matrix_Free(Eqs); Matrix_Free(Ineqs); mpolyhedron_compress_last_vars(permutedIneqs, WVL); if (dbgCompParm) { printf("After compression: "); show_matrix(permutedIneqs); } /* 3- eliminate the first variables */ if (!mpolyhedron_eliminate_first_variables(permutedEqs, permutedIneqs)) { fprintf(stderr,"full-dimensionize > variable elimination failed. \n"); return NULL; } if (dbgCompParm) { printf("After elimination of the variables: "); show_matrix(permutedIneqs); } /* 4- get rid of the first (zero) columns, which are now useless, and put the parameters back at the end */ Full_Dim = Matrix_Alloc(permutedIneqs->NbRows, permutedIneqs->NbColumns-nbElimVars); for (i=0; i< permutedIneqs->NbRows; i++) { value_set_si(Full_Dim->p[i][0], 1); for (j=0; j< nbParms; j++) value_assign(Full_Dim->p[i][j+Full_Dim->NbColumns-nbParms-1], permutedIneqs->p[i][j+nbElimVars+1]); for (j=0; j< permutedIneqs->NbColumns-nbParms-2-nbElimVars; j++) value_assign(Full_Dim->p[i][j+1], permutedIneqs->p[i][nbElimVars+nbParms+j+1]); value_assign(Full_Dim->p[i][Full_Dim->NbColumns-1], permutedIneqs->p[i][permutedIneqs->NbColumns-1]); } Matrix_Free(permutedIneqs); /* 5- Keep only the the validity lattice restricted to the parameters */ *validityLattice = Matrix_Alloc(nbParms+1, nbParms+1); for (i=0; i< nbParms; i++) { for (j=0; j< nbParms; j++) value_assign((*validityLattice)->p[i][j], WVL->p[i][j]); value_assign((*validityLattice)->p[i][nbParms], WVL->p[i][WVL->NbColumns-1]); } for (j=0; j< nbParms; j++) value_set_si((*validityLattice)->p[nbParms][j], 0); value_assign((*validityLattice)->p[nbParms][nbParms], WVL->p[WVL->NbColumns-1][WVL->NbColumns-1]); /* 6- Clean up */ Matrix_Free(WVL); return Full_Dim; } /* full_dimensionize */
/* Compute integer hull of truncated linear cone C, i.e., of C with * the origin removed. * Here, we do this by first computing the Hilbert basis of C * and then discarding elements from this basis that are rational * overconvex combinations of other elements in the basis. */ Matrix *Cone_Hilbert_Integer_Hull(Polyhedron *C, struct barvinok_options *options) { int i, j, k; Matrix *hilbert = Cone_Hilbert_Basis(C, options->MaxRays); Matrix *rays, *hull; unsigned dim = C->Dimension; Value tmp; unsigned MaxRays = options->MaxRays; /* When checking for redundant points below, we want to * check if there are any _rational_ solutions. */ POL_UNSET(options->MaxRays, POL_INTEGER); POL_ENSURE_VERTICES(C); rays = Matrix_Alloc(C->NbRays-1, C->Dimension); for (i = 0, j = 0; i < C->NbRays; ++i) { if (value_notzero_p(C->Ray[i][1+C->Dimension])) continue; Vector_Copy(C->Ray[i]+1, rays->p[j++], C->Dimension); } /* We only sort the pointers into the big Value array */ qsort(rays->p, rays->NbRows, sizeof(Value *), lex_cmp); qsort(hilbert->p, hilbert->NbRows, sizeof(Value *), lex_cmp); /* Remove rays from Hilbert basis */ for (i = 0, j = 0, k = 0; i < hilbert->NbRows && j < rays->NbRows; ++i) { if (Vector_Equal(hilbert->p[i], rays->p[j], C->Dimension)) ++j; else hilbert->p[k++] = hilbert->p[i]; } hilbert->NbRows = k; /* Now remove points that are overconvex combinations of other points */ value_init(tmp); for (i = 0; hilbert->NbRows > 1 && i < hilbert->NbRows; ++i) { Matrix *LP; Vector *obj; int nray = rays->NbRows; int npoint = hilbert->NbRows; enum lp_result result; LP = Matrix_Alloc(dim + 1 + nray + (npoint-1), 2 + nray + (npoint-1)); for (j = 0; j < dim; ++j) { for (k = 0; k < nray; ++k) value_assign(LP->p[j][k+1], rays->p[k][j]); for (k = 0; k < npoint; ++k) { if (k == i) value_oppose(LP->p[j][1+nray+npoint-1], hilbert->p[k][j]); else value_assign(LP->p[j][1+nray+k-(k>i)], hilbert->p[k][j]); } } value_set_si(LP->p[dim][0], 1); for (k = 0; k < nray+npoint-1; ++k) value_set_si(LP->p[dim][1+k], 1); value_set_si(LP->p[dim][LP->NbColumns-1], -1); for (k = 0; k < LP->NbColumns-2; ++k) { value_set_si(LP->p[dim+1+k][0], 1); value_set_si(LP->p[dim+1+k][1+k], 1); } /* Somewhat arbitrary objective function. */ obj = Vector_Alloc(LP->NbColumns-1); value_set_si(obj->p[0], 1); value_set_si(obj->p[obj->Size-1], 1); result = constraints_opt(LP, obj->p, obj->p[0], lp_min, &tmp, options); /* If the LP is not empty, the point can be discarded */ if (result != lp_empty) { hilbert->NbRows--; if (i < hilbert->NbRows) hilbert->p[i] = hilbert->p[hilbert->NbRows]; --i; } Matrix_Free(LP); Vector_Free(obj); } value_clear(tmp); hull = Matrix_Alloc(rays->NbRows + hilbert->NbRows, dim+1); for (i = 0; i < rays->NbRows; ++i) { Vector_Copy(rays->p[i], hull->p[i], dim); value_set_si(hull->p[i][dim], 1); } for (i = 0; i < hilbert->NbRows; ++i) { Vector_Copy(hilbert->p[i], hull->p[rays->NbRows+i], dim); value_set_si(hull->p[rays->NbRows+i][dim], 1); } Matrix_Free(rays); Matrix_Free(hilbert); options->MaxRays = MaxRays; return hull; }