Exemple #1
0
/*--------------------------------------------------------------*/
int Polyhedron_Not_Empty(Polyhedron *P,Polyhedron *C,int MAXRAYS) {

  int res,i;
  Value *context;
  Polyhedron *L;
  
  POL_ENSURE_FACETS(P);
  POL_ENSURE_VERTICES(P);
  POL_ENSURE_FACETS(C);
  POL_ENSURE_VERTICES(C);

  /* Create a context vector size dim+2 and set it to all zeros */
  context = (Value *) malloc((P->Dimension+2)*sizeof(Value));
  
  /* Initialize array 'context' */
  for (i=0;i<(P->Dimension+2);i++) 
    value_init(context[i]);
  
  Vector_Set(context,0,(P->Dimension+2));
  
  /* Set context[P->Dimension+1] = 1  (the constant) */
  value_set_si(context[P->Dimension+1],1);
  
  L = Polyhedron_Scan(P,C,MAXRAYS);
  res = exist_points(1,L,context);
  Domain_Free(L);
  
  /* Clear array 'context' */
  for (i=0;i<(P->Dimension+2);i++) 
    value_clear(context[i]);
  free(context);
  return res;
}
Exemple #2
0
/*
 * Given Lattice 'Lat' and a Polyhderon 'Poly', allocate space, and return
 * the Z-polyhderon corresponding to the image of the polyhderon 'Poly' by the 
 * lattice 'Lat'. If the input lattice 'Lat' is not integeral, it integralises 
 * it, i.e. the lattice of the Z-polyhderon returned is integeral. 
 */ 
ZPolyhedron *ZPolyhedron_Alloc(Lattice *Lat, Polyhedron *Poly) {
  
  ZPolyhedron *A;
  
  POL_ENSURE_FACETS(Poly);
  POL_ENSURE_VERTICES(Poly);

  if(Lat->NbRows != Poly->Dimension+1) {
    fprintf(stderr,"\nInZPolyAlloc - The Lattice  and the Polyhedron");
    fprintf(stderr," are not compatible to form a ZPolyhedra\n");
    return NULL;
  }  
  if((!(isEmptyLattice(Lat))) && (!isfulldim (Lat))) {
    fprintf(stderr,"\nZPolAlloc: Lattice not Full Dimensional\n");
    return NULL;
  }
  A = (ZPolyhedron *)malloc(sizeof(ZPolyhedron));
  if (!A) {
    fprintf(stderr,"ZPolAlloc : Out of Memory\n");
    return NULL;
  } 
  A->next = NULL;
  A->P = Domain_Copy(Poly);
  A->Lat = Matrix_Copy(Lat);
  
  if(IsLattice(Lat) == False) {
    ZPolyhedron *Res;
    
    Res = IntegraliseLattice (A);
    ZPolyhedron_Free (A);
    return Res;
  }
  return A;
} /* ZPolyhedron_Alloc */
static enum order_sign interval_minmax(Polyhedron *I)
{
    int i;
    int min = 1;
    int max = -1;
    assert(I->Dimension == 1);
    POL_ENSURE_VERTICES(I);
    for (i = 0; i < I->NbRays; ++i) {
	if (value_pos_p(I->Ray[i][1]))
	    max = 1;
	else if (value_neg_p(I->Ray[i][1]))
	    min = -1;
	else {
	    if (max < 0)
		max = 0;
	    if (min > 0)
		min = 0;
	}
    }
    if (min > 0)
	return order_gt;
    if (max < 0)
	return order_lt;
    if (min == max)
	return order_eq;
    if (max == 0)
	return order_le;
    if (min == 0)
	return order_ge;
    return order_unknown;
}
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;
}
Exemple #5
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;
}
Exemple #6
0
/* 
 * Topologically sort 'n' polyhdera and return 0 on failure, otherwise return 
 * 1 on success. Here 'L' is a an array of pointers to polyhedra, 'n' is the 
 * number of polyhedra, 'index' is the level to consider for partial ordering
 * 'pdim' is the parameter space dimension, 'time' is an array of 'n' integers
 * to store logical time values, 'pvect', if not NULL, is an array of 'n' 
 * integers that contains a permutation specification after call and MAXRAYS is
 * the workspace size for polyhedra operations. 
 */
int PolyhedronTSort (Polyhedron **L,unsigned int n,unsigned int index,unsigned int pdim,int *time,int *pvect,unsigned int MAXRAYS) {
 
  unsigned int const nbcells = ((n*(n-1))>>1);    /* Number of memory cells 
						     to allocate, see below */
  int *dag;  /* The upper triangular matrix */
  int **p;   /* Array of matrix row addresses */
  unsigned int i, j, k;
  unsigned int t, nb, isroot;

  if (n<2) return 0;

  /* we need an upper triangular matrix (example with n=4):

     . o o o
     . . o o     . are unuseful cells, o are useful cells
     . . . o
     . . . .
     
     so we need to allocate (n)(n-1)/2 cells
     - dag will point to this memory.
     - p[i] will point to row i of the matrix
     p[0] = dag - 1 (such that p[0][1] == dag[0])
     p[1] = dag - 1 + (n-1)
     p[2] = dag - 1 + (n-1) + (n-2)
     ...
     p[i] = p[i-1] + (n-1-i)
  */

  /* malloc n(n-1)/2 for dag and n-1 for p (node n does not have any row) */
  dag = (int *) malloc(nbcells*sizeof(int));
  if (!dag) return 0;
  p = (int **) malloc ((n-1) * sizeof(int *));
  if (!p) { 
    free(dag); return 0; 
  }

  /* Initialize 'p' and 'dag' */
  p[0] = dag-1;
  for (i=1; i<n-1; i++)
    p[i] = p[i-1] + (n-1)-i;
  for (i=0; i<nbcells; i++)
    dag[i] = -2;      /* -2 means 'not computed yet' */
  for (i=0; i<n; i++) time[i] = -1;

  /* Compute the dag using transitivity to reduce the number of */
  /*   PolyhedronLTQ calls.                                     */
  for (i=0; i<n-1; i++) {
    POL_ENSURE_FACETS(L[i]);
    POL_ENSURE_VERTICES(L[i]);
    for (j=i+1; j<n; j++) {
      if (p[i][j] == -2) /* not computed yes */
	p[i][j] = PolyhedronLTQ(L[i], L[j], index, pdim, MAXRAYS);
      if (p[i][j] != 0) {
	
	/* if p[i][j] is 1 or -1, look for -p[i][j] on the same row:
	   p[i][j] == -p[i][k] ==> p[j][k] = p[i][k] (transitivity)
	   note: p[r][c] == -p[c][r], use this to avoid reading or writing
	   under the matrix diagonal
	*/  
	   
	/* first, k<i so look for p[i][j] == p[k][i] (i.e. -p[i][k]) */
	for (k=0; k<i; k++)
	  if (p[k][i] == p[i][j]) p[k][j] = p[k][i];
	
	/* then, i<k<j so look for p[i][j] == -p[i][k] */
	for (k=i+1; k<j; k++)
	  if (p[i][k] == -p[i][j]) p[k][j] = -p[i][k];
	
	/* last, k>j same search but */
	for (k=j+1; k<n; k++)
	  if (p[i][k] == -p[i][j]) p[j][k] = p[i][k];
      }
    }
  }
  
  /* walk thru the dag to compute the partial order (and optionally
     the permutation)
     Note: this is not the fastest way to do it but it takes
     negligible time compared to a single call of PolyhedronLTQ !
     Each macro-step (while loop) gives the same logical time to all
     found roots and optionally add these nodes in the permutation vector
  */ 
  
  t = 0; /* current logical time, assigned to current roots and
	    increased by 1 at the end of each step */
  nb = 0; /* number of processed nodes (have been given a time) */
  while (nb<n) {
    for (i=0; i<n; i++) { /* search for roots */
      /* for any node, if it's not already been given a logical time
	 then walk thru the node row; if we find a 1 at some column j,
	 it means that node j preceeds the current node, so it is not
	 a root */
      if (time[i]<0) {
	isroot = 1; /* assume that it is until it is definitely not */
	/* first search on a column */
	for (j=0; j<i; j++) {
	  if (p[j][i]==-1) { /* found a node lower than it */
	    isroot = 0; break;
	  }
	}
	if /*still*/ (isroot)
	  for (j=i+1; j<n; j++) {
	    if (p[i][j]==1) { /* greater than this node */
	      isroot = 0; break;
	    }
	  }
	if (isroot) { /* then it definitely is */
	  time[i] = t; /* this node gets current logical time */
	  if (pvect)
	    pvect[nb] = i+1; /* nodes will be numbered from 1 to n */
	  nb++; /* one more node processed */
	}
      }
    }
    /* now make roots become neutral, i.e. non comparable with all other nodes */
    for (i=0; i<n; i++) {
      if (time[i]==t) {
	for (j=0; j<i; j++)
	  p[j][i] = 0;
	for (j=i+1; j<n; j++)
	  p[i][j] = 0;
      }
    }
    t++; /* ready for next set of root nodes */
  }
  
  free (p);   /* let's be clean, collect the garbage */
  free (dag);
  return 1;
} /* PolyhedronTSort */
Exemple #7
0
/* 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 */