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; } } }
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; } }
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); }
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); }
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); }