예제 #1
0
void bbArraySort( BBArray *arr,int ascending ){
	int n;
	void *p;
	n=arr->scales[0]-1;
	if( n<=0 ) return;
	p=BBARRAYDATA(arr,arr->dims);
	if( ascending ){
		switch( arr->type[0] ){
		case 'b':_qsort_b( (unsigned char*)p,(unsigned char*)p+n );break;
		case 's':_qsort_s( (unsigned short*)p,(unsigned short*)p+n );break;
		case 'i':qsort_i( (int*)p,(int*)p+n );break;
		case 'l':qsort_l( (BBInt64*)p,(BBInt64*)p+n );break;
		case 'f':qsort_f( (float*)p,(float*)p+n );break;
		case 'd':qsort_d( (double*)p,(double*)p+n );break;
		case '$':case ':':qsort_obj( (BBObject**)p,(BBObject**)p+n );break;
		}
	}else{
		switch( arr->type[0] ){
		case 'b':qsort_b_d( (unsigned char*)p,(unsigned char*)p+n );break;
		case 's':qsort_s_d( (unsigned short*)p,(unsigned short*)p+n );break;
		case 'i':qsort_i_d( (int*)p,(int*)p+n );break;
		case 'l':qsort_l_d( (BBInt64*)p,(BBInt64*)p+n );break;
		case 'f':qsort_f_d( (float*)p,(float*)p+n );break;
		case 'd':qsort_d_d( (double*)p,(double*)p+n );break;
		case '$':case ':':qsort_obj_d( (BBObject**)p,(BBObject**)p+n );break;
		}
	}
}
예제 #2
0
파일: spp_cg.c 프로젝트: e2bsq/Symphony
void extend_clique_on_fgraph(spp_cg_problem *spp, cut_data *new_cut,
			     double *pviolation)
{
   int old_coef_num, coef_num, i, j, k;
   double lhs = 1 + *pviolation;
   fnode *nodes = spp->fgraph->nodes;
   int nodenum = spp->fgraph->nodenum;
   int *indices = spp->tmp->itmp_8nodenum + 7 * nodenum;
   /* same tmp array is used in parent fn, but only after this fn returns */
   int userind;
   

   old_coef_num = coef_num = new_cut->size/ISIZE;
   memcpy(indices, new_cut->coef, coef_num * ISIZE);

   /* i runs thru nodes in fgraph, j runs thru nodes in the clique.
      note that the clique is a subgraph of fgraph */
   for ( i = j = 0; i < nodenum && j < old_coef_num; i++ ) {
      userind = nodes[i].ind;
      if ( userind < indices[j] ) {
	 /* check if the node can be added to the clique */
	 for ( k = 0; k < coef_num; k++ )
	    if (spp_is_orthogonal(spp->cmatrix, userind, indices[k]))
	       break;
	 if ( k == coef_num ) {
	    /* node can be added ... */
	    indices[coef_num++] = userind;
	    lhs += nodes[i].val;
	 }
      } else {
	 /* node is in the clique */
	 j++;
      }
   }
   for ( ; i < nodenum; i++ ) {
      userind = nodes[i].ind;
      /* check if the node can be added to the clique */
      for ( k = 0; k < coef_num; k++ )
	 if (spp_is_orthogonal(spp->cmatrix, userind, indices[k]))
	    break;
      if ( k == coef_num ) {
	 /* node can be added ... */
	 indices[coef_num++] = userind;
	 lhs += nodes[i].val;
      }
   }
      
   /* if some nodes were added to the clique ... */
   if (old_coef_num < coef_num) {
      new_cut->size = coef_num * ISIZE;
      qsort_i(indices, coef_num);
      memcpy(new_cut->coef, indices, new_cut->size);
      *pviolation = lhs - 1;
   }
}
예제 #3
0
파일: spp_cg.c 프로젝트: e2bsq/Symphony
void translate_cut_to_indices(spp_cg_problem *spp, cut_data *cut)
{
   int *colnames = spp->cmatrix->colnames;
   int colnum = spp->cmatrix->colnum;
   int nodenum = spp->fgraph->nodenum;
   int i, j, name, coef_num;
   int *names = spp->tmp->itmp_8nodenum;
   int *itmp = spp->tmp->itmp_8nodenum + nodenum;

   switch (cut->type) {
    case CLIQUE:
    case ODD_HOLE:
    case ODD_ANTIHOLE:
      coef_num = cut->size/ISIZE;
      break;

    case ORTHOCUT:
    case OTHER_CUT:
      coef_num = cut->size/(ISIZE + DSIZE);
      break;
   }

   memcpy(names, cut->coef, coef_num * ISIZE);
   for (i = 0; i < coef_num; i++) {
      name = names[i];
      for (j = colnum-1; j >=0; j--)
	 if (colnames[j] == name)
	    break;
      if (j >= 0)
	 names[i] = j;
      else
	 printf("ERROR: Variable with name %i is not found\n", name);
   }

   switch (cut->type) {
    case CLIQUE:
    case ORTHOCUT:
    case OTHER_CUT:
      qsort_i(names, coef_num);
      break;

    case ODD_HOLE:
    case ODD_ANTIHOLE:
      /* find smallest indexed node and rotate cycle to have that first */
      rotate_odd_hole(coef_num, names, itmp);
      break;
   }
   
   memcpy(cut->coef, names, coef_num * ISIZE);
}
예제 #4
0
int initialize_root_node_u(sym_environment *env)
{
   int i, user_res;

   base_desc *base = env->base = (base_desc *) calloc(1, sizeof(base_desc));
   node_desc *root = env->rootdesc = (node_desc *) calloc(1,sizeof(node_desc));
   

#ifdef USE_SYM_APPLICATION
   user_res = user_initialize_root_node(env->user, &base->varnum,
					&base->userind,
					&base->cutnum, &root->uind.size,
					&root->uind.list, &env->mip->obj_sense,
					&env->mip->obj_offset, 
					&env->mip->colname,
					env->par.tm_par.colgen_strat);
#else
   user_res = USER_DEFAULT;
#endif

   switch (user_res){ 
      
    case USER_ERROR:
      
      printf("\n\n*********User error detected -- aborting***********\n\n");
      return(ERROR__USER);

    case USER_SUCCESS:
    case USER_NO_PP:
    case USER_AND_PP:  
      if (base->varnum)
	 qsort_i(base->userind, base->varnum);
      if (root->uind.size && !env->par.warm_start)
	 qsort_i(root->uind.list, root->uind.size);
      env->mip->n = base->varnum + root->uind.size;
      env->mip->m = base->cutnum;
#if 0
      /* FIXME: We'd like to create the user's problem description here,
	 but we can't because we don't have access to the user's LP
	 data structures. Right now, this means that we cannot answer
	 queries through the OSI interface. */
      
      userind = (int *) malloc((base->varnum + root->uind.size) * ISIZE);
      
      memcpy((char *)userind, (char *)base->userind, base->varnum * ISIZE);
      memcpy((char *)(userind + base->varnum), (char *)root->uind.list,
	     root->uind.size * ISIZE); 
      
      user_create_subproblem(env->user, userind, env->mip, &maxn, &maxm,
			    &maxnz);
#endif
      break;
      
    case USER_DEFAULT: 

       root->uind.size = env->mip->n;
       base->cutnum = env->mip->m;

#if 0
      if (env->mip->n && env->mip->m){
	 root->uind.size = env->mip->n;
	 base->cutnum = env->mip->m;
      }else if (!root->uind.size){
	 printf("Error setting up the root node.\n");
	 printf("User did not specify number of variables. Exiting.\n\n");
	 return(FUNCTION_TERMINATED_ABNORMALLY);
      }else if (!base->varnum){
	 printf("Error setting up the root node.\n");
	 printf("User did not specify number of base constraints.",
		"Exiting.\n\n");
	 return(FUNCTION_TERMINATED_ABNORMALLY);
      }
#endif
      if(root->uind.size){
	 root->uind.list = (int *) malloc(root->uind.size * ISIZE);
	 for (i = 0; i < root->uind.size; i++){
	    root->uind.list[i] = i;
	 }
      }

      base->varnum = 0;
      base->userind = NULL;

#if 0
      if (base->varnum){
	 qsort_i(base->userind, base->varnum);
      }
      if (root->uind.size && !env->par.warm_start){
	 qsort_i(root->uind.list, root->uind.size);
      }
#endif
      
      break;

    default:
      break;
   }

   if (env->par.warm_start){
      root->uind.size = 0;
      FREE(root->uind.list);
      return(FUNCTION_TERMINATED_NORMALLY);
   }
   
   root->uind.type = EXPLICIT_LIST;
   root->cutind.type = EXPLICIT_LIST;
   root->not_fixed.type = EXPLICIT_LIST;
   root->basis.basis_exists = FALSE;
   root->nf_status = NF_CHECK_NOTHING;
   root->nf_status = (env->par.tm_par.colgen_strat[0] & COLGEN__FATHOM) ?
                      NF_CHECK_ALL : NF_CHECK_NOTHING;

   return(FUNCTION_TERMINATED_NORMALLY);
}
예제 #5
0
char lift_clique(spp_lp_problem *spp, int n, var_desc **vars, double *dj,
		 double dj_threshold, cut_data *cut, cut_data *new_cut,
		 int strategy)
{
   int i, j, k, length, cl_length, ind, pos_cl, pos_ind;
   int *cl_indices = spp->tmp->itmp_2n;
   int *indices = spp->tmp->itmp_2n + spp->cmatrix->colnum;

   printf("\nLifting the following clique:\n");
   display_cut_in_lp(spp, cut, -1);
   
   cl_length = cut->size/ISIZE;
   memcpy(cl_indices, cut->coef, cl_length * ISIZE);

   /* extract user indices of variables with small enough reduced costs
      and fill them into indices */
   for (i = n - 1, length = 0; i >= 0; i--)
      if (dj[i] < dj_threshold)
	 indices[length++] = vars[i]->userind;
   if (length == 0) {
      printf("... no vars with small enough reduced cost (threshold: %f)\n",
	     dj_threshold);
      return(FALSE);
   }

   /* order indices */
   qsort_i(indices, length);

   if (strategy == MAY_CHANGE_CUT) {
      for (i = 0, j = 0, pos_ind = 0, pos_cl = 0; i<length && j<cl_length; )
	 if (indices[i] < cl_indices[j]) {
	    indices[pos_ind++] = indices[i];
	    i++;
	 } else if (indices[i] == cl_indices[j]) {
	    i++; j++;
	 } else {
	    cl_indices[pos_cl++] = cl_indices[j];
	    j++;
	 }
      for ( ; i < length; i++)
	 indices[pos_ind++] = indices[i];
      /* if sg is left in cl_indices, it is thrown away: do nothing */
      length = pos_ind; cl_length = pos_cl;
	    
   } else if (strategy == DONT_CHANGE_CUT) {
      for (i = 0, j = 0, pos_ind = 0; i < length && j < cl_length; )
	 if (indices[i] < cl_indices[j]) {
	    indices[pos_ind++] = indices[i];
	    i++;
	 } else if (indices[i] == cl_indices[j]) {
	    i++; j++;
	 } else {
	    j++;
	 }
      for ( ; i < length; i++)
	 indices[pos_ind++] = indices[i];
      length = pos_ind;
      
   } else {
      printf("Bogus strategy in lift_clique, %i", strategy);
      return(FALSE);
   }
   
   if (length == 0) {
      printf("... no vars with small enough reduced cost (threshold: %f)\n",
	     dj_threshold);
      return(FALSE);
   } else {
      printf("... %i vars with small enough reduced cost (threshold: %f)\n",
	     length, dj_threshold);
   }
   
   /* generate a random permutation of the indices */
   for (i = 0; i < length - 1; i++) {
      k = RANDOM() % (length - i);
      ind = indices[i];
      indices[i] = indices[i + k];
      indices[i + k] = ind;
   }

   /* shuffle those vars that extend the clique to the beginning of
      indices */
   length = extend_clique_greedily(spp->cmatrix, cl_length, cl_indices,
				   length, indices);

   /* if no variables extend the clique: return */
   if (length == 0) {
      printf("... no vars can extend the clique\n");
      return(FALSE);
   }

   /* fill out new_cut */
   memcpy(indices + length, cl_indices, cl_length * ISIZE);
   length += cl_length;
   qsort_i(indices, length);

   new_cut->type = CLIQUE_LIFTED;
   new_cut->size = length * ISIZE;
   memcpy(new_cut->coef, indices, length * ISIZE);
   new_cut->rhs = 1;
   new_cut->range = 0;
   new_cut->sense = 'L';
   new_cut->branch = TRUE;   /* ? */
   new_cut->name = CUT__SEND_TO_CP;   /* the cut is globally valid */

   printf("... the lifted clique is:\n");
   display_cut_in_lp(spp, new_cut, -1);

   return(TRUE);
}