int repricing(lp_prob *p) { LPdata *lp_data = p->lp_data; node_times *comp_times = &p->comp_times; int iterd, termcode; int num_errors = 0; our_col_set *new_cols = NULL; int dual_feas, new_vars, cuts, no_more_cuts_count; int cut_term = 0; check_ub(p); p->iter_num = 0; /*------------------------------------------------------------------------*\ * The main loop -- continue solving relaxations until TDF \*------------------------------------------------------------------------*/ while (TRUE){ p->iter_num++; PRINT(p->par.verbosity, 2, ("\n\n**** Starting iteration %i ****\n\n", p->iter_num)); termcode = dual_simplex(lp_data, &iterd); /* Get relevant data */ get_dj_pi(lp_data); get_slacks(lp_data); /* display the current solution */ if (p->mip->obj_sense == SYM_MAXIMIZE){ PRINT(p->par.verbosity, 2, ("The LP value is: %.3f [%i,%i]\n\n", -lp_data->objval + p->mip->obj_offset, termcode, iterd)); }else{ PRINT(p->par.verbosity, 2, ("The LP value is: %.3f [%i,%i]\n\n", lp_data->objval+ p->mip->obj_offset, termcode, iterd)); } comp_times->lp += used_time(&p->tt); switch (termcode){ case LP_D_ITLIM: /* impossible, since itlim is set to infinity */ case LP_D_INFEASIBLE: /* this is impossible (?) as of now */ case LP_ABANDONED: printf("######## Unexpected termcode: %i \n", termcode); if (p->par.try_to_recover_from_error && (++num_errors == 1)){ /* Try to resolve it from scratch */ printf("######## Trying to recover by resolving from scratch...\n", termcode); continue; }else{ char name[50] = ""; printf("######## Recovery failed. %s%s", "LP solver is having numerical difficulties :(.\n", "######## Dumping current LP to MPS file and exiting.\n\n"); sprintf(name, "matrix.%i.%i.mps", p->bc_index, p->iter_num); write_mps(lp_data, name); return(ERROR__NUMERICAL_INSTABILITY); } case LP_D_UNBOUNDED: /* the primal problem is infeasible */ case LP_D_OBJLIM: case LP_OPTIMAL: if (termcode == LP_D_UNBOUNDED){ PRINT(p->par.verbosity, 1, ("Feasibility lost -- ")); }else if ((p->has_ub && lp_data->objval > p->ub - p->par.granularity) || termcode == LP_D_OBJLIM){ PRINT(p->par.verbosity, 1, ("Terminating due to high cost -- ")); }else{ /* optimal and not too high cost */ break; } comp_times->lp += used_time(&p->tt); if (fathom(p, (termcode != LP_D_UNBOUNDED))){ comp_times->communication += used_time(&p->tt); return(FUNCTION_TERMINATED_NORMALLY); }else{ comp_times->communication += used_time(&p->tt); continue; } } /* If come to here, the termcode must have been OPTIMAL and the * cost cannot be too high. */ /* is_feasible_u() fills up lp_data->x, too!! */ if (is_feasible_u(p, FALSE) == IP_FEASIBLE){ if (p->par.verbosity > 2){ printf ("Now displaying the feasible solution ...\n"); display_lp_solution_u(p, DISP_FEAS_SOLUTION); } cuts = -1; }else{ /*------------------------------------------------------------------*\ * send the current solution to the cut generator, and also to the * cut pool if this is the 1st or cut_pool_check_freq-th iteration. \*------------------------------------------------------------------*/ no_more_cuts_count = 0; if (p->cut_pool && ((p->iter_num-1) % p->par.cut_pool_check_freq == 0) ){ no_more_cuts_count += send_lp_solution_u(p, p->cut_pool); } if (p->cut_gen){ no_more_cuts_count += send_lp_solution_u(p, p->cut_gen); } if (p->par.verbosity > 4){ printf ("Now displaying the relaxed solution ...\n"); display_lp_solution_u(p, DISP_RELAXED_SOLUTION); } comp_times->lp += used_time(&p->tt); tighten_bounds(p); comp_times->fixing += used_time(&p->tt); cuts = 0; if (p->cut_gen || p->cut_pool){ cuts = check_row_effectiveness(p); } /*------------------------------------------------------------------*\ * receive the cuts from the cut generator and the cut pool \*------------------------------------------------------------------*/ if ((cut_term = receive_cuts(p, TRUE, no_more_cuts_count)) >= 0){ cuts += cut_term; }else{ return(ERROR__USER); } } comp_times->lp += used_time(&p->tt); if (cuts < 0){ /* i.e. feasible solution is found */ if (fathom(p, TRUE)){ comp_times->communication += used_time(&p->tt); return(FUNCTION_TERMINATED_NORMALLY); }else{ comp_times->communication += used_time(&p->tt); check_ub(p); continue; } } if (cuts == 0){ PRINT(p->par.verbosity, 2, ("\nIn iteration %i ... no cuts were added.\n", p->iter_num)); }else{ /* Go back to top */ PRINT(p->par.verbosity, 2, ("\nIn iteration %i ... %i violated cuts were added.\n", p->iter_num, cuts)); continue; } comp_times->lp += used_time(&p->tt); /* So no cuts were found. Price out everything */ new_cols = price_all_vars(p); new_vars = new_cols->num_vars + new_cols->rel_ub + new_cols->rel_lb; dual_feas = new_cols->dual_feas; free_col_set(&new_cols); comp_times->pricing += used_time(&p->tt); if (dual_feas != NOT_TDF) break; /* Don't have total dual feasibility. The non-dual-feasible vars * have already been added. Go back and resolve. */ PRINT(p->par.verbosity, 2, ("%i variables added in price-out.\n", new_vars)); } /* Now we know that we have TDF, just send back the node */ comp_times->lp += used_time(&p->tt); send_node_desc(p, REPRICED_NODE); comp_times->communication += used_time(&p->tt); return(FUNCTION_TERMINATED_NORMALLY); }
int spy_dual(glp_prob *P, const glp_smcp *parm) { /* driver to dual simplex method */ struct csa csa_, *csa = &csa_; SPXLP lp; #if USE_AT SPXAT at; #else SPXNT nt; #endif SPYSE se; int ret, *map, *daeh; /* build working LP and its initial basis */ memset(csa, 0, sizeof(struct csa)); csa->lp = &lp; spx_init_lp(csa->lp, P, EXCL); spx_alloc_lp(csa->lp); map = talloc(1+P->m+P->n, int); spx_build_lp(csa->lp, P, EXCL, SHIFT, map); spx_build_basis(csa->lp, P, map); switch (P->dir) { case GLP_MIN: csa->dir = +1; break; case GLP_MAX: csa->dir = -1; break; default: xassert(P != P); } csa->b = talloc(1+csa->lp->m, double); memcpy(csa->b, csa->lp->b, (1+csa->lp->m) * sizeof(double)); csa->l = talloc(1+csa->lp->n, double); memcpy(csa->l, csa->lp->l, (1+csa->lp->n) * sizeof(double)); csa->u = talloc(1+csa->lp->n, double); memcpy(csa->u, csa->lp->u, (1+csa->lp->n) * sizeof(double)); #if USE_AT /* build matrix A in row-wise format */ csa->at = &at; csa->nt = NULL; spx_alloc_at(csa->lp, csa->at); spx_build_at(csa->lp, csa->at); #else /* build matrix N in row-wise format for initial basis */ csa->at = NULL; csa->nt = &nt; spx_alloc_nt(csa->lp, csa->nt); spx_init_nt(csa->lp, csa->nt); spx_build_nt(csa->lp, csa->nt); #endif /* allocate and initialize working components */ csa->phase = 0; csa->beta = talloc(1+csa->lp->m, double); csa->beta_st = 0; csa->d = talloc(1+csa->lp->n-csa->lp->m, double); csa->d_st = 0; switch (parm->pricing) { case GLP_PT_STD: csa->se = NULL; break; case GLP_PT_PSE: csa->se = &se; spy_alloc_se(csa->lp, csa->se); break; default: xassert(parm != parm); } csa->list = talloc(1+csa->lp->m, int); csa->trow = talloc(1+csa->lp->n-csa->lp->m, double); csa->tcol = talloc(1+csa->lp->m, double); csa->work = talloc(1+csa->lp->m, double); csa->work1 = talloc(1+csa->lp->n-csa->lp->m, double); /* initialize control parameters */ csa->msg_lev = parm->msg_lev; csa->dualp = (parm->meth == GLP_DUALP); switch (parm->r_test) { case GLP_RT_STD: csa->harris = 0; break; case GLP_RT_HAR: csa->harris = 1; break; default: xassert(parm != parm); } csa->tol_bnd = parm->tol_bnd; csa->tol_bnd1 = .001 * parm->tol_bnd; csa->tol_dj = parm->tol_dj; csa->tol_dj1 = .001 * parm->tol_dj; csa->tol_piv = parm->tol_piv; switch (P->dir) { case GLP_MIN: csa->obj_lim = + parm->obj_ul; break; case GLP_MAX: csa->obj_lim = - parm->obj_ll; break; default: xassert(parm != parm); } csa->it_lim = parm->it_lim; csa->tm_lim = parm->tm_lim; csa->out_frq = parm->out_frq; csa->out_dly = parm->out_dly; /* initialize working parameters */ csa->tm_beg = xtime(); csa->it_beg = csa->it_cnt = P->it_cnt; csa->it_dpy = -1; csa->inv_cnt = 0; /* try to solve working LP */ ret = dual_simplex(csa); /* return basis factorization back to problem object */ P->valid = csa->lp->valid; P->bfd = csa->lp->bfd; /* set solution status */ P->pbs_stat = csa->p_stat; P->dbs_stat = csa->d_stat; /* if the solver failed, do not store basis header and basic * solution components to problem object */ if (ret == GLP_EFAIL) goto skip; /* convert working LP basis to original LP basis and store it to * problem object */ daeh = talloc(1+csa->lp->n, int); spx_store_basis(csa->lp, P, map, daeh); /* compute simplex multipliers for final basic solution found by * the solver */ spx_eval_pi(csa->lp, csa->work); /* convert working LP solution to original LP solution and store * it to problem object */ spx_store_sol(csa->lp, P, SHIFT, map, daeh, csa->beta, csa->work, csa->d); tfree(daeh); /* save simplex iteration count */ P->it_cnt = csa->it_cnt; /* report auxiliary/structural variable causing unboundedness */ P->some = 0; if (csa->p_stat == GLP_NOFEAS && csa->d_stat == GLP_FEAS) { int k, kk; /* xB[p] = x[k] causes dual unboundedness */ xassert(1 <= csa->p && csa->p <= csa->lp->m); k = csa->lp->head[csa->p]; xassert(1 <= k && k <= csa->lp->n); /* convert to number of original variable */ for (kk = 1; kk <= P->m + P->n; kk++) { if (abs(map[kk]) == k) { P->some = kk; break; } } xassert(P->some != 0); } skip: /* deallocate working objects and arrays */ spx_free_lp(csa->lp); tfree(map); tfree(csa->b); tfree(csa->l); tfree(csa->u); if (csa->at != NULL) spx_free_at(csa->lp, csa->at); if (csa->nt != NULL) spx_free_nt(csa->lp, csa->nt); tfree(csa->beta); tfree(csa->d); if (csa->se != NULL) spy_free_se(csa->lp, csa->se); tfree(csa->list); tfree(csa->trow); tfree(csa->tcol); tfree(csa->work); tfree(csa->work1); /* return to calling program */ return ret >= 0 ? ret : GLP_EFAIL; }
int fathom_branch(lp_prob *p) { LPdata *lp_data = p->lp_data; node_times *comp_times = &p->comp_times; char first_in_loop = TRUE; int iterd, termcode, i; int cuts, no_more_cuts_count; int num_errors = 0; int cut_term = 0; check_ub(p); p->iter_num = p->node_iter_num = 0; /*------------------------------------------------------------------------*\ * The main loop -- continue solving relaxations until no new cuts * are found \*------------------------------------------------------------------------*/ while (TRUE){ if (p->par.branch_on_cuts && p->slack_cut_num > 0){ switch (p->par.discard_slack_cuts){ case DISCARD_SLACKS_WHEN_STARTING_NEW_NODE: if (p->iter_num != 0) break; case DISCARD_SLACKS_BEFORE_NEW_ITERATION: free_cuts(p->slack_cuts, p->slack_cut_num); p->slack_cut_num = 0; break; } } p->iter_num++; p->node_iter_num++; PRINT(p->par.verbosity, 2, ("\n\n**** Starting iteration %i ****\n\n", p->iter_num)); termcode = dual_simplex(lp_data, &iterd); /* Get relevant data */ get_dj_pi(lp_data); get_slacks(lp_data); get_x(lp_data); /* display the current solution */ if (p->mip->obj_sense == SYM_MAXIMIZE){ PRINT(p->par.verbosity, 2, ("The LP value is: %.3f [%i,%i]\n\n", -lp_data->objval + p->mip->obj_offset, termcode, iterd)); }else{ PRINT(p->par.verbosity, 2, ("The LP value is: %.3f [%i,%i]\n\n", lp_data->objval+ p->mip->obj_offset, termcode, iterd)); } switch (termcode){ case LP_D_ITLIM: /* impossible, since itlim is set to infinity */ case LP_D_INFEASIBLE: /* this is impossible (?) as of now */ case LP_ABANDONED: printf("######## Unexpected termcode: %i \n", termcode); if (p->par.try_to_recover_from_error && (++num_errors == 1)){ /* Try to resolve it from scratch */ printf("######## Trying to recover by resolving from scratch...\n", termcode); continue; }else{ char name[50] = ""; printf("######## Recovery failed. %s%s", "LP solver is having numerical difficulties :(.\n", "######## Dumping current LP to MPS file and exiting.\n\n"); sprintf(name, "matrix.%i.%i.mps", p->bc_index, p->iter_num); write_mps(lp_data, name); return(ERROR__NUMERICAL_INSTABILITY); } case LP_D_UNBOUNDED: /* the primal problem is infeasible */ case LP_D_OBJLIM: case LP_OPTIMAL: if (num_errors == 1){ printf("######## Recovery succeeded! Continuing with node...\n\n"); num_errors = 0; } if (termcode == LP_D_UNBOUNDED){ PRINT(p->par.verbosity, 1, ("Feasibility lost -- ")); #if 0 char name[50] = ""; sprintf(name, "matrix.%i.%i.mps", p->bc_index, p->iter_num); write_mps(lp_data, name); #endif }else if ((p->has_ub && lp_data->objval > p->ub - p->par.granularity) || termcode == LP_D_OBJLIM){ PRINT(p->par.verbosity, 1, ("Terminating due to high cost -- ")); }else{ /* optimal and not too high cost */ break; } comp_times->lp += used_time(&p->tt); if (fathom(p, (termcode != LP_D_UNBOUNDED))){ comp_times->communication += used_time(&p->tt); return(FUNCTION_TERMINATED_NORMALLY); }else{ first_in_loop = FALSE; comp_times->communication += used_time(&p->tt); continue; } } /* If come to here, the termcode must have been OPTIMAL and the * cost cannot be too high. */ /* is_feasible_u() fills up lp_data->x, too!! */ if (is_feasible_u(p, FALSE) == IP_FEASIBLE){ cuts = -1; }else{ /*------------------------------------------------------------------*\ * send the current solution to the cut generator, and also to the * cut pool if we are either * - at the beginning of a chain (but not in the root in the * first phase) * - or this is the cut_pool_check_freq-th iteration. \*------------------------------------------------------------------*/ cuts = 0; no_more_cuts_count = 0; if (p->cut_pool && ((first_in_loop && (p->bc_level>0 || p->phase==1)) || (p->iter_num % p->par.cut_pool_check_freq == 0)) ){ no_more_cuts_count += send_lp_solution_u(p, p->cut_pool); } if (p->cut_gen){ no_more_cuts_count += send_lp_solution_u(p, p->cut_gen); } if (p->par.verbosity > 4){ printf ("Now displaying the relaxed solution ...\n"); display_lp_solution_u(p, DISP_RELAXED_SOLUTION); } comp_times->lp += used_time(&p->tt); tighten_bounds(p); comp_times->fixing += used_time(&p->tt); if (!first_in_loop){ cuts = check_row_effectiveness(p); } /*------------------------------------------------------------------*\ * receive the cuts from the cut generator and the cut pool \*------------------------------------------------------------------*/ if ((cut_term = receive_cuts(p, first_in_loop, no_more_cuts_count)) >=0 ){ cuts += cut_term; }else{ return(ERROR__USER); } } comp_times->lp += used_time(&p->tt); if (cuts < 0){ /* i.e. feasible solution is found */ if (fathom(p, TRUE)){ return(FUNCTION_TERMINATED_NORMALLY); }else{ first_in_loop = FALSE; check_ub(p); continue; } } PRINT(p->par.verbosity, 2, ("\nIn iteration %i, before calling branch()\n", p->iter_num)); if (cuts == 0){ PRINT(p->par.verbosity, 2, ("... no cuts were added.\n")); if (p->par.verbosity > 4){ printf("Now displaying final relaxed solution...\n\n"); display_lp_solution_u(p, DISP_FINAL_RELAXED_SOLUTION); } }else{ PRINT(p->par.verbosity, 2, ("... %i violated cuts were added\n", cuts)); } comp_times->lp += used_time(&p->tt); switch (cuts = branch(p, cuts)){ case NEW_NODE: #ifndef ROOT_NODEONLY if (p->par.verbosity > 0){ printf("*************************************************\n"); printf("* Now processing NODE %i LEVEL %i\n", p->bc_index, p->bc_level); printf("*************************************************\n\n"); p->node_iter_num = 0; } break; #endif case FATHOMED_NODE: comp_times->strong_branching += used_time(&p->tt); return(FUNCTION_TERMINATED_NORMALLY); case ERROR__NO_BRANCHING_CANDIDATE: /* Something went wrong */ return(ERROR__NO_BRANCHING_CANDIDATE); default: /* the return value is the number of cuts added */ if (p->par.verbosity > 2){ printf("Continue with this node."); if (cuts > 0) printf(" %i cuts added alltogether in iteration %i", cuts, p->iter_num); printf("\n\n"); } break; } comp_times->strong_branching += used_time(&p->tt); check_ub(p); first_in_loop = FALSE; } comp_times->lp += used_time(&p->tt); return(FUNCTION_TERMINATED_NORMALLY); }
branch_obj *select_branching_object(lp_prob *p, int *cuts) { LPdata *lp_data = p->lp_data; var_desc **vars; row_data *rows; int m; #ifndef MAX_CHILDREN_NUM int maxnum; double *objval, *pobj; int *termcode, *pterm, *feasible, *pfeas, *iterd, *piter; #ifdef COMPILE_FRAC_BRANCHING int *frnum, *pfrnum, **frind, **pfrind; double **frval, **pfrval; #endif #endif int i, j, k, branch_var, branch_row; double lb, ub, oldobjval; cut_data *cut; branch_obj *can, *best_can = NULL; #ifdef COMPILE_FRAC_BRANCHING int *xind; double *xval; #endif double *pseudo_costs_zero, *pseudo_costs_one; /* These are the return values from select_candidates_u() */ int cand_num = 0, new_vars = 0; branch_obj **candidates = NULL; #ifdef STATISTICS int itlim = 0, cnum = 0; #endif #if 0 if (p->bc_level == 0){ lp_data->pseudo_costs_zero = (double *) calloc(lp_data->n, DSIZE); lp_data->pseudo_costs_one = (double *) calloc(lp_data->n, DSIZE); #if 0 memcpy((char *)pseudo_costs_one, (char *)lp_data->obj, lp_data->n*DSIZE); memcpy((char *)pseudo_costs_zero,(char *)lp_data->obj, lp_data->n*DSIZE); #endif } pseudo_costs_one = lp_data->pseudo_costs_one; pseudo_costs_zero = lp_data->pseudo_costs_zero; #endif /*------------------------------------------------------------------------*\ * First we call branch_u() to select candidates. It can * -- return with DO_BRANCH and a bunch of candidates, or * -- return with DO_NOT_BRANCH along with a bunch of violated cuts * in the matrix and/or among the slack_cuts, or * -- return with DO_NOT_BRANCH__FATHOMED, i.e., the node can be fathomed. \*------------------------------------------------------------------------*/ j = select_candidates_u(p, cuts, &new_vars, &cand_num, &candidates); switch (j){ case DO_NOT_BRANCH__FATHOMED: *cuts = -1; return(NULL); case DO_NOT_BRANCH: if (cand_num) *cuts += add_violated_slacks(p, cand_num, candidates); #ifdef DO_TESTS if (*cuts == 0 && new_vars == 0){ printf("Told not to branch, but there are no cuts!\n"); exit(-1); } #endif /* Free the candidates */ if (candidates){ for (i=0; i<cand_num; i++){ free_candidate(candidates + i); } FREE(candidates); } return(NULL); case DO_BRANCH: break; } /* OK, now we have to branch. */ /* First of all, send everything to the cutpool that hasn't been sent before and send the current node description to the TM. */ p->comp_times.strong_branching += used_time(&p->tt); #pragma omp critical(cut_pool) send_cuts_to_pool(p, -1); send_node_desc(p, NODE_BRANCHED_ON); p->comp_times.communication += used_time(&p->tt); /* Add all the branching cuts */ if (p->par.branch_on_cuts) add_slacks_to_matrix(p, cand_num, candidates); m = lp_data->m; rows = lp_data->rows; #ifndef MAX_CHILDREN_NUM /* The part below is not needed when we have MAX_CHILDREN_NUM specified */ /* Count how many objval/termcode/feasible entry we might need and allocate space for it */ for (maxnum = candidates[0]->child_num, j=0, i=1; i<cand_num; i++){ if (maxnum < candidates[i]->child_num) maxnum = candidates[i]->child_num; } objval = (double *) malloc(maxnum * DSIZE); termcode = (int *) malloc(maxnum * ISIZE); feasible = (int *) malloc(maxnum * ISIZE); iterd = (int *) malloc(maxnum * ISIZE); #ifdef COMPILE_FRAC_BRANCHING frval = (double **) malloc(maxnum * sizeof(double *)); pfrval = (double **) malloc(maxnum * sizeof(double *)); frind = (int **) malloc(maxnum * sizeof(int *)); pfrind = (int **) malloc(maxnum * sizeof(int *)); frnum = (int *) malloc(maxnum * ISIZE); pfrnum = (int *) malloc(maxnum * ISIZE); #endif pobj = (double *) malloc(maxnum * DSIZE); pterm = (int *) malloc(maxnum * ISIZE); pfeas = (int *) malloc(maxnum * ISIZE); piter = (int *) malloc(maxnum * ISIZE); #endif /* Set the iteration limit */ if (p->par.max_presolve_iter > 0) set_itlim(lp_data, p->par.max_presolve_iter); vars = lp_data->vars; /* Look at the candidates one-by-one and presolve them. */ oldobjval = lp_data->objval; for (i=0; i<cand_num; i++){ can = candidates[i]; #ifndef MAX_CHILDREN_NUM can->objval = pobj; can->termcode = pterm; can->feasible = pfeas; can->iterd = piter; #ifdef COMPILE_FRAC_BRANCHING can->frac_num = pfrnum; can->frac_ind = pfrind; can->frac_val = pfrval; #endif #endif #ifdef STATISTICS cnum += can->child_num; #endif /* Now depending on the type, adjust ub/lb or rhs/range/sense */ switch (can->type){ case CANDIDATE_VARIABLE: branch_var = can->position; if (lp_data->status[branch_var] & PERM_FIXED_TO_LB || lp_data->status[branch_var] & PERM_FIXED_TO_UB){ printf("Error -- candidate is fixed. Discarding.\n\n"); continue; } #if 0 if (pseudo_costs_one[can->position] || pseudo_costs_zero[can->position]){ can->objval[1] = oldobjval + (1 - lp_data->x[can->position]) * pseudo_costs_one[can->position]; can->objval[0] = oldobjval + lp_data->x[can->position] * pseudo_costs_zero[can->position]; break; } #endif lb = vars[branch_var]->lb; ub = vars[branch_var]->ub; for (j = 0; j < can->child_num; j++){ switch (can->sense[j]){ case 'E': change_lbub(lp_data, branch_var, can->rhs[j], can->rhs[j]); break; case 'R': change_lbub(lp_data, branch_var, can->rhs[j], can->rhs[j] + can->range[j]); break; case 'L': change_lbub(lp_data, branch_var, lb, can->rhs[j]); break; case 'G': change_lbub(lp_data, branch_var, can->rhs[j], ub); break; } check_ub(p); /* The original basis is in lp_data->lpbas */ can->termcode[j] = dual_simplex(lp_data, can->iterd+j); can->objval[j] = lp_data->objval; if (can->termcode[j] == LP_OPTIMAL){ /* is_feasible_u() fills up lp_data->x, too!! */ if (is_feasible_u(p) == IP_FEASIBLE){ can->termcode[j] = LP_OPT_FEASIBLE; /*NOTE: This is confusing but not all that citical...*/ /*The "feasible" field is only filled out for the purposes of display (in vbctool) to keep track of where in the tree the feasible solutions were found. Since this may not be the actual candidate branched on, we need to pass this info on to whatever candidate does get branched on so the that the fact that a feasible solution was found in presolve can be recorded*/ if (best_can) best_can->feasible[j] = TRUE; else can->feasible[j] = TRUE; } } #ifdef COMPILE_FRAC_BRANCHING else if (can->termcode[j] != LP_ABANDONED) get_x(lp_data); if (can->termcode[j] != LP_ABANDONED){ xind = lp_data->tmp.i1; /* n */ xval = lp_data->tmp.d; /* n */ can->frac_num[j] = collect_fractions(p, lp_data->x, xind, xval); if (can->frac_num[j] > 0){ can->frac_ind[j] = (int *) malloc(can->frac_num[j] * ISIZE); can->frac_val[j] = (double *) malloc(can->frac_num[j]*DSIZE); memcpy(can->frac_ind[j], xind, can->frac_num[j] * ISIZE); memcpy(can->frac_val[j], xval, can->frac_num[j] * DSIZE); } }else{ can->frac_num[j] = 0; } #endif #ifdef STATISTICS if (can->termcode[j] == LP_D_ITLIM) itlim++; #endif } change_lbub(lp_data, branch_var, lb, ub); #if 0 pseudo_costs_one[can->position] = (can->objval[1] - oldobjval)/lp_data->x[can->position]; pseudo_costs_zero[can->position] = (can->objval[0] - oldobjval)/lp_data->x[can->position]; #endif break; case CANDIDATE_CUT_IN_MATRIX: branch_row = can->position; for (j = 0; j < can->child_num; j++){ change_row(lp_data, branch_row, can->sense[j], can->rhs[j], can->range[j]); check_ub(p); /* The original basis is in lp_data->lpbas */ can->termcode[j] = dual_simplex(lp_data, can->iterd+j); can->objval[j] = lp_data->objval; if (can->termcode[j] == LP_OPTIMAL){ /* is_feasible_u() fills up lp_data->x, too!! */ if (is_feasible_u(p) == IP_FEASIBLE){ can->termcode[j] = LP_OPT_FEASIBLE; /*NOTE: This is confusing but not all that citical...*/ /*The "feasible" field is only filled out for the purposes of display (in vbctool) to keep track of where in the tree the feasible solutions were found. Since this may not be the actual candidate branched on, we need to pass this info on to whatever candidate does get branched on so the that the fact that a feasible solution was found in presolve can be recorded*/ if (best_can) best_can->feasible[j] = TRUE; else can->feasible[j] = TRUE; } } #ifdef COMPILE_FRAC_BRANCHING else if (can->termcode[j] != LP_ABANDONED) get_x(lp_data); if (can->termcode[j] != LP_ABANDONED){ xind = lp_data->tmp.i1; /* n */ xval = lp_data->tmp.d; /* n */ can->frac_num[j] = collect_fractions(p, lp_data->x, xind, xval); if (can->frac_num[j] > 0){ can->frac_ind[j] = (int *) malloc(can->frac_num[j] * ISIZE); can->frac_val[j] = (double *) malloc(can->frac_num[j]*DSIZE); memcpy(can->frac_ind[j], xind, can->frac_num[j] * ISIZE); memcpy(can->frac_val[j], xval, can->frac_num[j] * DSIZE); } }else{ can->frac_num[j] = 0; } #endif #ifdef STATISTICS if (can->termcode[j] == LP_D_ITLIM) itlim++; #endif } cut = rows[branch_row].cut; change_row(lp_data, branch_row, cut->sense, cut->rhs, cut->range); free_row_set(lp_data, 1, &branch_row); break; } switch ((j = compare_candidates_u(p, oldobjval, best_can, can))){ case FIRST_CANDIDATE_BETTER: case FIRST_CANDIDATE_BETTER_AND_BRANCH_ON_IT: free_candidate(candidates + i); break; case SECOND_CANDIDATE_BETTER: case SECOND_CANDIDATE_BETTER_AND_BRANCH_ON_IT: #ifndef MAX_CHILDREN_NUM if (best_can == NULL){ pobj = objval; pterm = termcode; pfeas = feasible; piter = iterd; #ifdef COMPILE_FRAC_BRANCHING pfrnum = frnum; pfrind = frind; pfrval = frval; #endif }else{ pobj = best_can->objval; pterm = best_can->termcode; pfeas = best_can->feasible; piter = best_can->iterd; #ifdef COMPILE_FRAC_BRANCHING pfrnum = best_can->frac_num; pfrind = best_can->frac_ind; pfrval = best_can->frac_val; #endif } #endif if (best_can){ for (k = can->child_num - 1; k >= 0; k--){ /* Again, this is only for tracking that there was a feasible solution discovered in presolve for display purposes */ if (best_can->feasible[k]) can->feasible[k] = TRUE; } free_candidate(&best_can); } best_can = can; candidates[i] = NULL; break; } if ((j & BRANCH_ON_IT)) break; } #ifndef MAX_CHILDREN_NUM FREE(pobj); FREE(pterm); FREE(pfeas); FREE(piter); # ifdef COMPILE_FRAC_BRANCHING FREE(pfrnum); FREE(pfrind); FREE(pfrval); # endif #endif if (p->par.max_presolve_iter > 0) set_itlim(lp_data, -1); #ifdef STATISTICS PRINT(p->par.verbosity, 5, ("Itlim reached %i times out of %i .\n\n", itlim, cnum)); #endif for (i++; i<cand_num; i++){ /* Free the remaining candidates */ free_candidate(candidates + i); } FREE(candidates); return(best_can); }