Пример #1
0
/*---------------------------------------------------------------------*/
static int exist_points(int pos,Polyhedron *Pol,Value *context) {
  
  Value LB, UB, k,tmp;
  
  value_init(LB); value_init(UB); 
  value_init(k);  value_init(tmp);
  value_set_si(LB,0);
  value_set_si(UB,0);
  
  /* Problem if UB or LB is INFINITY */
  if (lower_upper_bounds(pos,Pol,context,&LB,&UB) !=0) {
    errormsg1("exist_points", "infdom", "infinite domain");
    value_clear(LB);
    value_clear(UB);
    value_clear(k);
    value_clear(tmp);
    return -1;
  }
  value_set_si(context[pos],0);
  if(value_lt(UB,LB)) {
    value_clear(LB); 
    value_clear(UB);
    value_clear(k);
    value_clear(tmp);
    return 0;
  }  
  if (!Pol->next) {
    value_subtract(tmp,UB,LB);
    value_increment(tmp,tmp);
    value_clear(UB);
    value_clear(LB);
    value_clear(k);
    return (value_pos_p(tmp));
  }
  
  for (value_assign(k,LB);value_le(k,UB);value_increment(k,k)) {
    
    /* insert k in context */
    value_assign(context[pos],k);    
    if (exist_points(pos+1,Pol->next,context) > 0 ) {
      value_clear(LB); value_clear(UB);
      value_clear(k); value_clear(tmp);
      return 1;
    }
  }   
  /* Reset context */
  value_set_si(context[pos],0);
  value_clear(UB); value_clear(LB);
  value_clear(k); value_clear(tmp);
  return 0;
}
Пример #2
0
/* 
 * Subtract two vectors 'p1' and 'p2' and store the result in 'p3' 
 */
void Vector_Sub(Value *p1,Value *p2,Value *p3,unsigned length) {

  Value *cp1, *cp2, *cp3;	
  int i;
  
  cp1=p1;
  cp2=p2;
  cp3=p3;
  for (i=0;i<length;i++) {
    
    /* *cp3++= *cp1++ - *cp2++ */
    value_subtract(*cp3,*cp1,*cp2);
    cp1++; cp2++; cp3++;
  }
} /* Vector_Sub */
Пример #3
0
/*
 * Given a rational matrix 'Mat'(k x k), compute its inverse rational matrix 
 * 'MatInv' k x k.
 * The output is 1,
 * if 'Mat' is non-singular (invertible), otherwise the output is 0. Note:: 
 * (1) Matrix 'Mat' is modified during the inverse operation.
 * (2) Matrix 'MatInv' must be preallocated before passing into this function.
 */
int Matrix_Inverse(Matrix *Mat,Matrix *MatInv ) {
  
  int i, k, j, c;
  Value x, gcd, piv;
  Value m1,m2;
  Value *den;
  
  if(Mat->NbRows != Mat->NbColumns) {
   fprintf(stderr,"Trying to invert a non-square matrix !\n");
    return 0;
  }
  
  /* Initialize all the 'Value' variables */
  value_init(x);  value_init(gcd); value_init(piv);
  value_init(m1); value_init(m2);

  k = Mat->NbRows; 

  /* Initialise MatInv */
  Vector_Set(MatInv->p[0],0,k*k);

  /* Initialize 'MatInv' to Identity matrix form. Each diagonal entry is set*/
  /* to 1. Last column of each row (denominator of each entry in a row) is  */
  /* also set to 1.                                                         */ 
  for(i=0;i<k;++i) {
    value_set_si(MatInv->p[i][i],1);	
    /* value_set_si(MatInv->p[i][k],1);	/* denum */
  }  
  /* Apply Gauss-Jordan elimination method on the two matrices 'Mat' and  */
  /* 'MatInv' in parallel.                                                */
  for(i=0;i<k;++i) {
    
    /* Check if the diagonal entry (new pivot) is non-zero or not */
    if(value_zero_p(Mat->p[i][i])) {   	
      
      /* Search for a non-zero pivot down the column(i) */
      for(j=i;j<k;++j)      
	if(value_notzero_p(Mat->p[j][i]))
	  break;
      
      /* If no non-zero pivot is found, the matrix 'Mat' is non-invertible */
      /* Return 0.                                                         */
      if(j==k) {
	
	/* Clear all the 'Value' variables */
	value_clear(x);  value_clear(gcd); value_clear(piv);
	value_clear(m1); value_clear(m2);
	return 0;
      }	
      
      /* Exchange the rows, row(i) and row(j) so that the diagonal element */
      /* Mat->p[i][i] (pivot) is non-zero. Repeat the same operations on    */
      /* matrix 'MatInv'.                                                   */
      for(c=0;c<k;++c) {

	/* Interchange rows, row(i) and row(j) of matrix 'Mat'    */
	value_assign(x,Mat->p[j][c]);
	value_assign(Mat->p[j][c],Mat->p[i][c]);
	value_assign(Mat->p[i][c],x);
	
	/* Interchange rows, row(i) and row(j) of matrix 'MatInv' */
	value_assign(x,MatInv->p[j][c]);
	value_assign(MatInv->p[j][c],MatInv->p[i][c]);
	value_assign(MatInv->p[i][c],x);
      }
    }
    
    /* Make all the entries in column(i) of matrix 'Mat' zero except the */
    /* diagonal entry. Repeat the same sequence of operations on matrix  */
    /* 'MatInv'.                                                         */
    for(j=0;j<k;++j) {
      if (j==i) continue;	         /* Skip the pivot */
      value_assign(x,Mat->p[j][i]);
      if(value_notzero_p(x)) {
	value_assign(piv,Mat->p[i][i]);
	value_gcd(gcd, x, piv);
	if (value_notone_p(gcd) ) {
	  value_divexact(x, x, gcd);
	  value_divexact(piv, piv, gcd);
	}
	for(c=((j>i)?i:0);c<k;++c) {
	  value_multiply(m1,piv,Mat->p[j][c]);
	  value_multiply(m2,x,Mat->p[i][c]);
	  value_subtract(Mat->p[j][c],m1,m2); 
	}
	for(c=0;c<k;++c) {
	  value_multiply(m1,piv,MatInv->p[j][c]);
	  value_multiply(m2,x,MatInv->p[i][c]);
	  value_subtract(MatInv->p[j][c],m1,m2);
	}
	      
	/* Simplify row(j) of the two matrices 'Mat' and 'MatInv' by */
	/* dividing the rows with the common GCD.                     */
	Vector_Gcd(&MatInv->p[j][0],k,&m1);
	Vector_Gcd(&Mat->p[j][0],k,&m2);
	value_gcd(gcd, m1, m2);
	if(value_notone_p(gcd)) {
	  for(c=0;c<k;++c) {
	    value_divexact(Mat->p[j][c], Mat->p[j][c], gcd);
	    value_divexact(MatInv->p[j][c], MatInv->p[j][c], gcd);
	  }
	}
      }
    }
  }
  
  /* Find common denom for each row */ 
   den = (Value *)malloc(k*sizeof(Value));
   value_set_si(x,1);
   for(j=0 ; j<k ; ++j) {
     value_init(den[j]);
     value_assign(den[j],Mat->p[j][j]);
     
     /* gcd is always positive */
     Vector_Gcd(&MatInv->p[j][0],k,&gcd);
     value_gcd(gcd, gcd, den[j]);
     if (value_neg_p(den[j])) 
       value_oppose(gcd,gcd); /* make denominator positive */
     if (value_notone_p(gcd)) {
       for (c=0; c<k; c++) 
	 value_divexact(MatInv->p[j][c], MatInv->p[j][c], gcd); /* normalize */
       value_divexact(den[j], den[j], gcd);
     }  
     value_gcd(gcd, x, den[j]);
     value_divexact(m1, den[j], gcd);
     value_multiply(x,x,m1);
   }
   if (value_notone_p(x)) 
     for(j=0 ; j<k ; ++j) {       
       for (c=0; c<k; c++) {
	 value_division(m1,x,den[j]);
	 value_multiply(MatInv->p[j][c],MatInv->p[j][c],m1);  /* normalize */
       }
     }

   /* Clear all the 'Value' variables */
   for(j=0 ; j<k ; ++j) {
     value_clear(den[j]);
   }  
   value_clear(x);  value_clear(gcd); value_clear(piv);
   value_clear(m1); value_clear(m2);
   free(den);
   
   return 1;
} /* Matrix_Inverse */
Пример #4
0
/* 
 * Basic hermite engine 
 */
static int hermite(Matrix *H,Matrix *U,Matrix *Q) {
  
  int nc, nr, i, j, k, rank, reduced, pivotrow;
  Value pivot,x,aux;
  Value *temp1, *temp2;
  
  /*                     T                     -1   T */
  /* Computes form: A = Q H  and U A = H  and U  = Q  */
  
  if (!H) { 
    errormsg1("Domlib", "nullH", "hermite: ? Null H");
    return -1;
  }
  nc = H->NbColumns;
  nr = H->NbRows;
  temp1 = (Value *) malloc(nc * sizeof(Value));
  temp2 = (Value *) malloc(nr * sizeof(Value));
  if (!temp1 ||!temp2) {
    errormsg1("Domlib", "outofmem", "out of memory space");
    return -1;
  }
  
  /* Initialize all the 'Value' variables */
  value_init(pivot); value_init(x); 
  value_init(aux);   
  for(i=0;i<nc;i++)
    value_init(temp1[i]);
  for(i=0;i<nr;i++)
    value_init(temp2[i]);
  
#ifdef DEBUG
  fprintf(stderr,"Start  -----------\n");
  Matrix_Print(stderr,0,H);
#endif
  for (k=0, rank=0; k<nc && rank<nr; k=k+1) {
    reduced = 1;	/* go through loop the first time */
#ifdef DEBUG
    fprintf(stderr, "Working on col %d.  Rank=%d ----------\n", k+1, rank+1);
#endif
    while (reduced) {
      reduced=0;
      
      /* 1. find pivot row */
      value_absolute(pivot,H->p[rank][k]);
      
      /* the kth-diagonal element */
      pivotrow = rank;
      
      /* find the row i>rank with smallest nonzero element in col k */
      for (i=rank+1; i<nr; i++) {
	value_absolute(x,H->p[i][k]);
	if (value_notzero_p(x) &&
	    (value_lt(x,pivot) || value_zero_p(pivot))) {
	  value_assign(pivot,x);
	  pivotrow = i;
	}
      }
      
      /* 2. Bring pivot to diagonal (exchange rows pivotrow and rank) */
      if (pivotrow != rank) {
	Vector_Exchange(H->p[pivotrow],H->p[rank],nc);
	if (U)
	  Vector_Exchange(U->p[pivotrow],U->p[rank],nr);
	if (Q)
	  Vector_Exchange(Q->p[pivotrow],Q->p[rank],nr);

#ifdef DEBUG
	fprintf(stderr,"Exchange rows %d and %d  -----------\n", rank+1, pivotrow+1);
	Matrix_Print(stderr,0,H);
#endif
      }
      value_assign(pivot,H->p[rank][k]);	/* actual ( no abs() ) pivot */
      
      /* 3. Invert the row 'rank' if pivot is negative */
      if (value_neg_p(pivot)) {
	value_oppose(pivot,pivot); /* pivot = -pivot */
	for (j=0; j<nc; j++)
	  value_oppose(H->p[rank][j],H->p[rank][j]);
	
	/* H->p[rank][j] = -(H->p[rank][j]); */
	if (U)
	  for (j=0; j<nr; j++)
	    value_oppose(U->p[rank][j],U->p[rank][j]);
	
	/* U->p[rank][j] = -(U->p[rank][j]); */
	if (Q)
	  for (j=0; j<nr; j++)
	    value_oppose(Q->p[rank][j],Q->p[rank][j]);
	
	/* Q->p[rank][j] = -(Q->p[rank][j]); */
#ifdef DEBUG
	fprintf(stderr,"Negate row %d  -----------\n", rank+1);
	Matrix_Print(stderr,0,H);
#endif

      }      
      if (value_notzero_p(pivot)) {
	
	/* 4. Reduce the column modulo the pivot */
	/*    This eventually zeros out everything below the */
	/*    diagonal and produces an upper triangular matrix */
	
	for (i=rank+1;i<nr;i++) {
	  value_assign(x,H->p[i][k]);
	  if (value_notzero_p(x)) {	    
	    value_modulus(aux,x,pivot);
	    
	    /* floor[integer division] (corrected for neg x) */
	    if (value_neg_p(x) && value_notzero_p(aux)) {
	      
	      /* x=(x/pivot)-1; */
	      value_division(x,x,pivot);
	      value_decrement(x,x);
	    }	
	    else 
	      value_division(x,x,pivot);
	    for (j=0; j<nc; j++) {
	      value_multiply(aux,x,H->p[rank][j]);
	      value_subtract(H->p[i][j],H->p[i][j],aux);
	    }
	    
	    /* U->p[i][j] -= (x * U->p[rank][j]); */
	    if (U)
	      for (j=0; j<nr; j++) {
		value_multiply(aux,x,U->p[rank][j]);
		value_subtract(U->p[i][j],U->p[i][j],aux);
	      }
	    
	    /* Q->p[rank][j] += (x * Q->p[i][j]); */
	    if (Q)
	      for(j=0;j<nr;j++) {
		value_addmul(Q->p[rank][j], x, Q->p[i][j]);
	      }
	    reduced = 1;

#ifdef DEBUG
	    fprintf(stderr,
		    "row %d = row %d - %d row %d -----------\n", i+1, i+1, x, rank+1);
	    Matrix_Print(stderr,0,H);
#endif
	
	  } /* if (x) */
	} /* for (i) */
      } /* if (pivot != 0) */
    } /* while (reduced) */
    
    /* Last finish up this column */
    /* 5. Make pivot column positive (above pivot row) */
    /*    x should be zero for i>k */
    
    if (value_notzero_p(pivot)) {
      for (i=0; i<rank; i++) {
	value_assign(x,H->p[i][k]);
	if (value_notzero_p(x)) { 	  
	  value_modulus(aux,x,pivot);
	  
	  /* floor[integer division] (corrected for neg x) */
	  if (value_neg_p(x) && value_notzero_p(aux)) {
	    value_division(x,x,pivot);
	    value_decrement(x,x);
	    
	    /* x=(x/pivot)-1; */
	  }
	  else
	    value_division(x,x,pivot);
	  
	  /* H->p[i][j] -= x * H->p[rank][j]; */
	  for (j=0; j<nc; j++) {
	    value_multiply(aux,x,H->p[rank][j]);
	    value_subtract(H->p[i][j],H->p[i][j],aux);
	  }
	  
	  /* U->p[i][j] -= x * U->p[rank][j]; */
	  if (U)
	    for (j=0; j<nr; j++) {
	      value_multiply(aux,x,U->p[rank][j]);
	      value_subtract(U->p[i][j],U->p[i][j],aux);
	    }
	  
	  /* Q->p[rank][j] += x * Q->p[i][j]; */
	  if (Q)
	    for (j=0; j<nr; j++) {
	      value_addmul(Q->p[rank][j], x, Q->p[i][j]);
	    }  
#ifdef DEBUG
	  fprintf(stderr,
		  "row %d = row %d - %d row %d -----------\n", i+1, i+1, x, rank+1);
	  Matrix_Print(stderr,0,H);
#endif
	} /* if (x) */
      } /* for (i) */
      rank++;
    } /* if (pivot!=0) */
  } /* for (k) */
  
  /* Clear all the 'Value' variables */
  value_clear(pivot); value_clear(x); 
  value_clear(aux); 
  for(i=0;i<nc;i++)
    value_clear(temp1[i]);
  for(i=0;i<nr;i++)
    value_clear(temp2[i]);
  free(temp2);
  free(temp1);
  return rank;
} /* Hermite */ 
Пример #5
0
/**
 * 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 */