void free_candidate(branch_obj **cand) { int i; if (*cand){ branch_obj *can = *cand; #ifdef COMPILE_FRAC_BRANCHING for (i = can->child_num-1; i >= 0; i--){ if (can->frac_num[i]){ FREE(can->frac_ind[i]); FREE(can->frac_val[i]); } } #endif free_waiting_row(&(can->row)); #ifndef MAX_CHILDREN_NUM FREE(can->sense); FREE(can->rhs); FREE(can->range); FREE(can->branch); if (can->solutions){ for (i = can->child_num-1; i >= 0; i--){ #else if (can->solutions){ for (i = MAX_CHILDREN_NUM - 1; i >= 0; i--){ #endif FREE(can->sol_inds[i]); FREE(can->solutions[i]); } } #ifdef SENSITIVITY_ANALYSIS #ifndef MAX_CHILDREN_NUM if (can->duals){ for (i = can->child_num-1; i >= 0; i--){ #else if (can->duals){ for (i = MAX_CHILDREN_NUM - 1; i >= 0; i--){ #endif FREE(can->duals[i]); } } #endif FREE(can->sol_sizes); FREE(can->sol_inds); FREE(can->solutions); #ifdef SENSITIVITY_ANALYSIS FREE(can->duals); #endif FREE(*cand); } } /*===========================================================================*/ void free_candidate_completely(branch_obj **cand) { if (*cand){ #ifndef MAX_CHILDREN_NUM branch_obj *can = *cand; #endif #ifndef MAX_CHILDREN_NUM FREE(can->objval); FREE(can->termcode); FREE(can->feasible); FREE(can->iterd); # ifdef COMPILE_FRAC_BRANCHING FREE(can->frac_num); FREE(can->frac_ind); FREE(can->frac_val); # endif #endif free_candidate(cand); } } /*===========================================================================*/ void free_waiting_row(waiting_row **wrow) { waiting_row *wr = *wrow; if (wr){ FREE(wr->matval); FREE(wr->matind); free_cut(&wr->cut); free(wr); *wrow = NULL; } } /*===========================================================================*/ void free_waiting_rows(waiting_row **rows, int row_num) { int i; if (rows) for (i=row_num-1; i>=0; i--) free_waiting_row(rows+i); } /*===========================================================================*/ void free_waiting_row_array(waiting_row ***rows, int row_num) { free_waiting_rows(*rows, row_num); FREE(*rows); } /*===========================================================================*/ void free_node_desc(node_desc **desc) { if (*desc){ node_desc *n = *desc; FREE(n->cutind.list); FREE(n->uind.list); if (n->nf_status == NF_CHECK_AFTER_LAST || n->nf_status == NF_CHECK_UNTIL_LAST) FREE(n->not_fixed.list); if (n->basis.basis_exists){ FREE(n->basis.basevars.list); FREE(n->basis.basevars.stat); FREE(n->basis.extravars.list); FREE(n->basis.extravars.stat); FREE(n->basis.baserows.list); FREE(n->basis.baserows.stat); FREE(n->basis.extrarows.list); FREE(n->basis.extrarows.stat); } if (n->desc_size > 0) FREE(n->desc); if (n->bnd_change) { FREE(n->bnd_change->index); FREE(n->bnd_change->lbub); FREE(n->bnd_change->value); FREE(n->bnd_change); } FREE(*desc); } } /*===========================================================================*/ void free_node_dependent(lp_prob *p) { LPdata *lp_data = p->lp_data; int i; free_node_desc(&p->desc); for (i = p->base.cutnum; i < lp_data->m; i++){ #ifdef COMPILE_IN_LP if (lp_data->rows[i].cut->name < 0 || lp_data->rows[i].cut->branch & CUT_BRANCHED_ON) #endif free_cut(&lp_data->rows[i].cut); #ifdef COMPILE_IN_LP else lp_data->rows[i].cut = NULL; #endif } if (p->par.branch_on_cuts && p->slack_cut_num > 0){ free_cuts(p->slack_cuts, p->slack_cut_num); p->slack_cut_num = 0; } // necessary to purge waiting rows, otherwise these may get added to the // node that is solved next time. if (p->waiting_row_num>0) { free_waiting_rows(p->waiting_rows, p->waiting_row_num); p->waiting_row_num = 0; FREE(p->waiting_rows); } unload_lp_prob(lp_data); }
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); }