예제 #1
0
/**
 * 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 */
예제 #2
0
static double compute_enode(enode *p, Value *list_args) {
  
  int i;
  Value m, param;
  double res=0.0;
    
  if (!p)
    return(0.);

  value_init(m);
  value_init(param);

  if (p->type == polynomial) {
    if (p->size > 1)
                 value_assign(param,list_args[p->pos-1]);
    
    /* Compute the polynomial using Horner's rule */
    for (i=p->size-1;i>0;i--) {
      res +=compute_evalue(&p->arr[i],list_args);
      res *=VALUE_TO_DOUBLE(param);
    }
    res +=compute_evalue(&p->arr[0],list_args);
  }
  else if (p->type == periodic) {
    value_assign(m,list_args[p->pos-1]);
    
    /* Choose the right element of the periodic */
    value_set_si(param,p->size);
    value_pmodulus(m,m,param);
    res = compute_evalue(&p->arr[VALUE_TO_INT(m)],list_args);
  }
  value_clear(m);
  value_clear(param);
  return res;
} /* compute_enode */
예제 #3
0
파일: alpha.c 프로젝트: intersense/pluto-gw
/*---------------------------------------------------------------------*/
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;
}
예제 #4
0
/* 
 * Return the component of 'p' with minimum non-zero absolute value. 'index'
 * points to the component index that has the minimum value. If no such value
 * and index is found, Value 1 is returned.
 */
void Vector_Min_Not_Zero(Value *p,unsigned length,int *index,Value *min)
{
  Value aux;
  int i;
  
  
  i = First_Non_Zero(p, length);
  if (i == -1) {
    value_set_si(*min,1);
    return;
  }
  *index = i;
  value_absolute(*min, p[i]);
  value_init(aux);
  for (i = i+1; i < length; i++) {
    if (value_zero_p(p[i]))
      continue;
    value_absolute(aux, p[i]);
    if (value_lt(aux,*min)) {
      value_assign(*min,aux);
      *index = i;
    }  
  }
  value_clear(aux);
} /* Vector_Min_Not_Zero */
예제 #5
0
/* 
 * Given matrices 'Mat1' and 'Mat2', compute the matrix product and store in 
 * matrix 'Mat3' 
 */
void Matrix_Product(Matrix *Mat1,Matrix *Mat2,Matrix *Mat3) {
  
  int Size, i, j, k;
  unsigned NbRows, NbColumns;
  Value **q1, **q2, *p1, *p3,sum;
  
  NbRows    = Mat1->NbRows;
  NbColumns = Mat2->NbColumns;
  
  Size      = Mat1->NbColumns;
  if(Mat2->NbRows!=Size||Mat3->NbRows!=NbRows||Mat3->NbColumns!=NbColumns) {
    fprintf(stderr, "? Matrix_Product : incompatable matrix dimension\n");
    return;
  }     
  value_init(sum); 
  p3 = Mat3->p_Init;
  q1 = Mat1->p;
  q2 = Mat2->p;
  
  /* Mat3[i][j] = Sum(Mat1[i][k]*Mat2[k][j] where sum is over k = 1..nbrows */
  for (i=0;i<NbRows;i++) {
    for (j=0;j<NbColumns;j++) {
      p1 = *(q1+i);
      value_set_si(sum,0);
      for (k=0;k<Size;k++) {
	value_addmul(sum, *p1, *(*(q2+k)+j));
	p1++;
      }
      value_assign(*p3,sum);
      p3++;
    }
  }
  value_clear(sum); 
  return;
} /* Matrix_Product */
예제 #6
0
/** 
 * 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 */
예제 #7
0
/* 
 * Compute GCD of 'a' and 'b' 
 */
void Gcd(Value a,Value b,Value *result) {

  Value acopy, bcopy;

  value_init(acopy);
  value_init(bcopy);
  value_assign(acopy,a);
  value_assign(bcopy,b);
  while(value_notzero_p(acopy)) { 
    value_modulus(*result,bcopy,acopy);      
    value_assign(bcopy,acopy);                     
    value_assign(acopy,*result);                   
  }
  value_absolute(*result,bcopy);
  value_clear(acopy);
  value_clear(bcopy);
} /* Gcd */
예제 #8
0
/** 
 * 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 */
예제 #9
0
/** 
 * Computes the validity lattice of a set of equalities. I.e., the lattice
 * induced on the last <tt>b</tt> variables by the equalities involving the
 * first <tt>a</tt> integer existential variables.  The submatrix of Eqs that
 * concerns only the existential variables (so the first a columns) is assumed
 * to be full-row rank.
 * @param Eqs the equalities
 * @param a the number of existential integer variables, placed as first
 * variables
 * @param vl the (returned) validity lattice, in homogeneous form. It is
 * allocated if initially set to null, or reused if already allocated.
 */
void Equalities_validityLattice(Matrix * Eqs, int a, Matrix** vl) {
  unsigned int b = Eqs->NbColumns-2-a;
  unsigned int r = Eqs->NbRows;
  Matrix * A=NULL, * B=NULL, *I = NULL, *Lb=NULL, *sol=NULL;
  Matrix *H, *U, *Q;
  unsigned int i;

  if (dbgCompParm) {
    printf("Computing validity lattice induced by the %d first variables of:"
	   ,a);
    show_matrix(Eqs);
  }
  if (b==0) {
    ensureMatrix((*vl), 1, 1);
    value_set_si((*vl)->p[0][0], 1);
    return;
  }

  /* 1- check that there is an integer solution to the equalities */
  /* OPT: could change integerSolution's profile to allocate or not*/
  Equalities_integerSolution(Eqs, &sol);
  /* if there is no integer solution, there is no validity lattice */
  if (sol==NULL) {
    if ((*vl)!=NULL) Matrix_Free(*vl);
    return;
  }
  Matrix_subMatrix(Eqs, 0, 1, r, 1+a, &A);
  Matrix_subMatrix(Eqs, 0, 1+a, r, 1+a+b, &B);
  linearInter(A, B, &I, &Lb);
  Matrix_Free(A);
  Matrix_Free(B);
  Matrix_Free(I);
  if (dbgCompParm) {
    show_matrix(Lb);
  }
  
  /* 2- The linear part of the validity lattice is the left HNF of Lb */
  left_hermite(Lb, &H, &Q, &U);
  Matrix_Free(Lb);
  Matrix_Free(Q);
  Matrix_Free(U);

  /* 3- build the validity lattice */
  ensureMatrix((*vl), b+1, b+1);
  Matrix_copySubMatrix(H, 0, 0, b, b, (*vl), 0,0);
  Matrix_Free(H);
  for (i=0; i< b; i++) {
    value_assign((*vl)->p[i][b], sol->p[0][a+i]);
  }
  Matrix_Free(sol);
  Vector_Set((*vl)->p[b],0, b);
  value_set_si((*vl)->p[b][b], 1);
  
} /* validityLattice */
예제 #10
0
static int
wrap_value_assign (char *a)
{
  struct gdb_wrapper_arguments *args = (struct gdb_wrapper_arguments *) a;
  value_ptr val1, val2;

  val1 = (value_ptr) (args)->args[0].pointer;
  val2 = (value_ptr) (args)->args[1].pointer;

  (args)->result.pointer = value_assign (val1, val2);
  return 1;
}
예제 #11
0
/* 
 * Reduce 'p' by operating binary function on its components successively 
 */
void Vector_Reduce(Value *p,unsigned length,void(*f)(Value,Value *),Value *r) {
  
  Value *cp;
  int i;
  
  cp = p;
  value_assign(*r,*cp);
  for(i=1;i<length;i++) {
    cp++;
    (*f)(*cp,r);
  }
} /* Vector_Reduce */
예제 #12
0
/* 
 * Return the maximum of the components of 'p' 
 */
void Vector_Max(Value *p,unsigned length, Value *max) {
  
  Value *cp;
  int i;

  cp=p;
  value_assign(*max,*cp);
  cp++;
  for (i=1;i<length;i++) {
    value_maximum(*max,*max,*cp);
    cp++;
  }
} /* Vector_Max */
예제 #13
0
/*
 * Copy Vector 'p1' to Vector 'p2' 
 */
void Vector_Copy(Value *p1,Value *p2,unsigned length) {

  int i;
  Value *cp1, *cp2;

  cp1 = p1;
  cp2 = p2;
  
  for(i=0;i<length;i++) 
    value_assign(*cp2++,*cp1++);
  
  return;
}
예제 #14
0
/* 
 * Return the minimum of the components of Vector 'p' 
 */
void Vector_Min(Value *p,unsigned length,Value *min) {
  
  Value *cp;
  int i;

  cp=p;
  value_assign(*min,*cp);
  cp++;
  for (i=1;i<length;i++) {
    value_minimum(*min,*min,*cp);
    cp++;
  }
  return;
} /* Vector_Min */
예제 #15
0
/* 
 * Given vectors 'p1', 'p2', and a pointer to a function returning 'Value type,
 * compute p3[i] = f(p1[i],p2[i]).  
 */ 
void Vector_Map(Value *p1,Value *p2,Value *p3,unsigned length,
		Value *(*f)(Value,Value))
{
  Value *cp1, *cp2, *cp3;
  int i;
  
  cp1=p1;
  cp2=p2;
  cp3=p3;
  for(i=0;i<length;i++) {
    value_assign(*cp3,*(*f)(*cp1, *cp2));
    cp1++; cp2++; cp3++;
  }
  return;
} /* Vector_Map */
예제 #16
0
/* 
 * Given Vectors 'p1' and 'p2', return Vector 'p3' = lambda * p1 + mu * p2. 
 */
void Vector_Combine(Value *p1, Value *p2, Value *p3, Value lambda, Value mu,
		    unsigned length)
{
  Value tmp;
  int i;
  
  value_init(tmp);
  for (i = 0; i < length; i++) {
    value_multiply(tmp, lambda, p1[i]);
    value_addmul(tmp, mu, p2[i]);
    value_assign(p3[i], tmp);
  }
  value_clear(tmp);
  return;
} /* Vector_Combine */
예제 #17
0
enum lp_result PL_polyhedron_opt(Polyhedron *P, Value *obj, Value denom,
				enum lp_dir dir, Value *opt)
{
    int i;
    int first = 1;
    Value val, d;
    enum lp_result res = lp_empty;

    POL_ENSURE_VERTICES(P);
    if (emptyQ(P))
	return res;

    value_init(val);
    value_init(d);
    for (i = 0; i < P->NbRays; ++ i) {
	Inner_Product(P->Ray[i]+1, obj, P->Dimension+1, &val);
	if (value_zero_p(P->Ray[i][0]) && value_notzero_p(val)) {
	    res = lp_unbounded;
	    break;
	}
	if (value_zero_p(P->Ray[i][1+P->Dimension])) {
	    if ((dir == lp_min && value_neg_p(val)) ||
		(dir == lp_max && value_pos_p(val))) {
		res = lp_unbounded;
		break;
	    }
	} else {
	    res = lp_ok;
	    value_multiply(d, denom, P->Ray[i][1+P->Dimension]);
	    if (dir == lp_min)
		mpz_cdiv_q(val, val, d);
	    else
		mpz_fdiv_q(val, val, d);
	    if (first || (dir == lp_min ? value_lt(val, *opt) :
				          value_gt(val, *opt)))
		value_assign(*opt, val);
	    first = 0;
	}
    }
    value_clear(d);
    value_clear(val);

    return res;
}
예제 #18
0
/** 
 * 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 */
예제 #19
0
int in_domain(Polyhedron *P, Value *list_args) {
  
  int col,row;
  Value v; /* value of the constraint of a row when
               parameters are instanciated*/

  if( !P )
          return( 0 );

  POL_ENSURE_INEQUALITIES(P);

  value_init(v); 
  
  /* P->Constraint constraint matrice of polyhedron P */  
  for(row=0;row<P->NbConstraints;row++) {
    value_assign(v,P->Constraint[row][P->Dimension+1]); /*constant part*/
    for(col=1;col<P->Dimension+1;col++) {
      value_addmul(v, P->Constraint[row][col], list_args[col-1]); 
    }  
    if (value_notzero_p(P->Constraint[row][0])) {
        
      /*if v is not >=0 then this constraint is not respected */
      if (value_neg_p(v)) {
        value_clear(v);
        return( in_domain(P->next, list_args) );
      }        
    }
    else {
      
      /*if v is not = 0 then this constraint is not respected */
      if (value_notzero_p(v)) {
        value_clear(v);
        return( in_domain(P->next, list_args) );
      }
    }
  }
  
  /* if not return before this point => all the constraints are respected */
  value_clear(v);
  return 1;
} /* in_domain */
void
ppl_set_coef_gmp (ppl_Linear_Expression_t e, ppl_dimension_type i, Value x)
{
  Value v0, v1;
  ppl_Coefficient_t c;

  value_init (v0);
  value_init (v1);
  ppl_new_Coefficient (&c);

  ppl_Linear_Expression_coefficient (e, i, c);
  ppl_Coefficient_to_mpz_t (c, v1);
  value_oppose (v1, v1);
  value_assign (v0, x);
  value_addto (v0, v0, v1);
  ppl_assign_Coefficient_from_mpz_t (c, v0);
  ppl_Linear_Expression_add_to_coefficient (e, i, c);

  value_clear (v0);
  value_clear (v1);
  ppl_delete_Coefficient (c);
}
void
ppl_set_inhomogeneous_gmp (ppl_Linear_Expression_t e, Value x)
{
  Value v0, v1;
  ppl_Coefficient_t c;

  value_init (v0);
  value_init (v1);
  ppl_new_Coefficient (&c);

  ppl_Linear_Expression_inhomogeneous_term (e, c);
  ppl_Coefficient_to_mpz_t (c, v1);
  value_oppose (v1, v1);
  value_assign (v0, x);
  value_addto (v0, v0, v1);
  ppl_assign_Coefficient_from_mpz_t (c, v0);
  ppl_Linear_Expression_add_to_inhomogeneous (e, c);

  value_clear (v0);
  value_clear (v1);
  ppl_delete_Coefficient (c);
}
예제 #22
0
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 */
예제 #23
0
/* 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;
}
예제 #24
0
/* 
 * 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 */ 
예제 #25
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 */
예제 #26
0
/**
 * 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 */
예제 #27
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 */ 
예제 #28
0
/*
 * Given (m x n) integer matrix 'X' and n x (k+1) rational matrix 'P', compute
 * the rational m x (k+1) rational matrix  'S'. The last column in each row of
 * the rational matrices is used to store the common denominator of elements
 * in a row.                              
 */
void rat_prodmat(Matrix *S,Matrix *X,Matrix *P) {
  
  int i,j,k;
  int last_column_index = P->NbColumns - 1;
  Value lcm, old_lcm,gcd,last_column_entry,s1;
  Value m1,m2;
  
  /* Initialize all the 'Value' variables */
  value_init(lcm); value_init(old_lcm); value_init(gcd);
  value_init(last_column_entry); value_init(s1); 
  value_init(m1); value_init(m2);

  /* Compute the LCM of last column entries (denominators) of rows */
  value_assign(lcm,P->p[0][last_column_index]);	
  for(k=1;k<P->NbRows;++k) {
    value_assign(old_lcm,lcm);
    value_assign(last_column_entry,P->p[k][last_column_index]);
    value_gcd(gcd, lcm, last_column_entry);
    value_divexact(m1, last_column_entry, gcd);
    value_multiply(lcm,lcm,m1);
  }
  
  /* S[i][j] = Sum(X[i][k] * P[k][j] where Sum is extended over k = 1..nbrows*/
  for(i=0;i<X->NbRows;++i)
    for(j=0;j<P->NbColumns-1;++j) {
      
      /* Initialize s1 to zero. */
      value_set_si(s1,0);
      for(k=0;k<P->NbRows;++k) {
	
	/* If the LCM of last column entries is one, simply add the products */
	if(value_one_p(lcm)) {
	  value_addmul(s1, X->p[i][k], P->p[k][j]);
	}  
	
	/* Numerator (num) and denominator (denom) of S[i][j] is given by :- */
	/* numerator  = Sum(X[i][k]*P[k][j]*lcm/P[k][last_column_index]) and */
	/* denominator= lcm where Sum is extended over k = 1..nbrows.        */
	else {
	  value_multiply(m1,X->p[i][k],P->p[k][j]);
	  value_division(m2,lcm,P->p[k][last_column_index]);
	  value_addmul(s1, m1, m2);
	}
      }	
      value_assign(S->p[i][j],s1);
    }
  
  for(i=0;i<S->NbRows;++i) {
    value_assign(S->p[i][last_column_index],lcm);

    /* Normalize the rows so that last element >=0 */
    Vector_Normalize_Positive(&S->p[i][0],S->NbColumns,S->NbColumns-1);
  }
  
  /* Clear all the 'Value' variables */
  value_clear(lcm); value_clear(old_lcm); value_clear(gcd);
  value_clear(last_column_entry); value_clear(s1); 
  value_clear(m1); value_clear(m2);
 
  return;
} /* rat_prodmat */
예제 #29
0
/**
 * 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 */
예제 #30
0
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 */