/* create nr item randomly created with nr_unique_item distinct items */ static void speed_test(int nr_item, int nr_unique_item) { int i; double begin, end; odb_t hash; int rc; rc = odb_open(&hash, TEST_FILENAME, ODB_RDWR, sizeof(struct opd_header)); if (rc) { fprintf(stderr, "%s", strerror(rc)); exit(EXIT_FAILURE); } begin = used_time(); for (i = 0 ; i < nr_item ; ++i) { rc = odb_insert(&hash, (random() % nr_unique_item) + 1, 1); if (rc != EXIT_SUCCESS) { fprintf(stderr, "%s", strerror(rc)); exit(EXIT_FAILURE); } } end = used_time(); odb_close(&hash); remove(TEST_FILENAME); verbprintf("nr item: %d, unique item: %d, elapsed: %f\n", nr_item, nr_unique_item, end - begin); }
void sweep(int parent, heur_prob *p) { printf("\nIn sweep....\n\n"); int mytid, info, r_bufid; int i; int vertnum; sweep_data *data; float depotx, depoty; float tempx, tempy; double t=0; mytid = pvm_mytid(); (void) used_time(&t); printf("mytid in sweep.c= %i", pvm_mytid()); /*-----------------------------------------------------------------------*\ | Receive the VRP data | \*-----------------------------------------------------------------------*/ PVM_FUNC(r_bufid, pvm_recv(-1, SWEEP_TRIALS)); PVM_FUNC(info, pvm_upkint(&(p->par.sweep_trials), 1, 1)); printf("\nCheckpoint 1\n"); /*-----------------------------------------------------------------------*/ vertnum = p->vertnum; p->cur_tour = (best_tours *)calloc(1, sizeof(best_tours)); p->cur_tour->tour = (_node *)calloc(vertnum, sizeof(_node)); printf("\nCheckpoint 2\n"); data = (sweep_data *)calloc(vertnum-1, sizeof(sweep_data)); if (p->dist.coordx && p->dist.coordy){ depotx = p->dist.coordx[0]; depoty = p->dist.coordy[0]; printf("\nCheckpoint 3\n"); /*calculate angles for sorting*/ for (i=0; i<vertnum-1; i++){ tempx = p->dist.coordx[i+1] - depotx; tempy = p->dist.coordy[i+1] - depoty; data[i].angle = (float) atan2(tempy, tempx); if (data[i].angle < 0) data[i].angle += 2*M_PI; data[i].cust=i+1; } printf("\nCheckpoint 4\n"); quicksort(data, vertnum-1); printf("\nCheckpoint 5\n"); make_tour(p, data, p->cur_tour); printf("\nCheckpoint 6\n"); /*-----------------------------------------------------------------------*\ | Transmit the tour back to the parent | \*-----------------------------------------------------------------------*/ send_tour(p->cur_tour->tour, p->cur_tour->cost, p->cur_tour->numroutes, SWEEP, used_time(&t), parent, vertnum, 0, NULL); printf("\nCheckpoint 7\n"); } if (data) free((char *) data); printf("\nCheckpoint 8\n"); free_heur_prob(p); }
void cg_initialize(cg_prob *p, int master_tid) { #ifndef COMPILE_IN_CG int bytes, msgtag; #if defined(COMPILE_IN_TM) && defined(COMPILE_IN_LP) int s_bufid, r_bufid, info; #endif #endif #if !defined(COMPILE_IN_TM) || !defined(COMPILE_IN_LP) int r_bufid, s_bufid = 0; #endif /*------------------------------------------------------------------------ * Receive the problem data *------------------------------------------------------------------------*/ #ifdef COMPILE_IN_CG p->master = master_tid; #else /* We only need to do this part if the CG is running as a separate process*/ /* Otherwise, all of this setup is done in the master in the function */ /* pack_cg_data_u()*/ /* set stdout to be line buffered */ setvbuf(stdout, (char *)NULL, _IOLBF, 0); register_process(); r_bufid = receive_msg(ANYONE, MASTER_TID_INFO); bufinfo(r_bufid, &bytes, &msgtag, &p->tree_manager); receive_int_array(&p->master, 1); receive_int_array(&p->proc_index, 1); freebuf(r_bufid); #endif #if !defined(COMPILE_IN_TM) || !defined(COMPILE_IN_LP) || \ !defined(COMPILE_IN_CG) /* This part, we only need to do if we are not running in full serial mode*/ s_bufid = init_send(DataInPlace); send_msg(p->master, REQUEST_FOR_CG_DATA); freebuf(s_bufid); receive_cg_data_u(p); #endif (void) used_time(&p->tt); }
int col_gen_before_branch(lp_prob *p, int *new_vars) { our_col_set *new_cols; int dual_feas; check_ub(p); if (! p->has_ub || (p->colgen_strategy & BEFORE_BRANCH__DO_NOT_GENERATE_COLS) || (p->lp_data->nf_status & NF_CHECK_NOTHING)) return(DO_BRANCH); PRINT(p->par.verbosity, 2, ("Generating cols before branching.\n")); p->comp_times.strong_branching += used_time(&p->tt); new_cols = price_all_vars(p); p->comp_times.pricing += used_time(&p->tt); /*price_all_vars sorts by user_ind. We need things sorted by colind */ colind_sort_extra(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); check_ub(p); if (dual_feas == NOT_TDF){ return(DO_NOT_BRANCH); }else{ if (p->ub - p->par.granularity < p->lp_data->objval || p->lp_data->termcode == LP_D_OBJLIM || p->lp_data->termcode == LP_OPT_FEASIBLE){ /* If total dual feas and high cost or feasibility ==> fathomable */ PRINT(p->par.verbosity, 1, ("Managed to fathom the node.\n")); send_node_desc(p, p->lp_data->termcode == LP_OPT_FEASIBLE ? FEASIBLE_PRUNED : OVER_UB_PRUNED); p->comp_times.communication += used_time(&p->tt); return(DO_NOT_BRANCH__FATHOMED); }else{ return(DO_BRANCH); /* if we got here, then DO_BRANCH */ } } return(DO_BRANCH); /* fake return */ }
int process_chain(lp_prob *p) { int termcode; /* Create the LP */ if ((termcode = create_subproblem_u(p)) < 0){ /* User had problems creating initial LP. Abandon node. */ return(termcode); } p->last_gap = 0.0; if (p->has_ub && p->par.set_obj_upper_lim) set_obj_upper_lim(p->lp_data, p->ub - p->par.granularity); if (p->colgen_strategy & COLGEN_REPRICING){ if (p->par.verbosity > 0){ printf("****************************************************\n"); printf("* Now repricing NODE %i LEVEL %i\n", p->bc_index, p->bc_level); printf("****************************************************\n\n"); } termcode = repricing(p); free_node_dependent(p); }else{ if (p->par.verbosity > 0){ printf("****************************************************\n"); printf("* Now processing NODE %i LEVEL %i (from TM)\n", p->bc_index, p->bc_level); printf("****************************************************\n\n"); PRINT(p->par.verbosity, 4, ("Diving set to %i\n\n", p->dive)); } termcode = fathom_branch(p); #ifdef COMPILE_IN_LP p->tm->stat.chains++; p->tm->active_node_num--; free_node_dependent(p); #else /* send_lp_is_free() calls free_node_dependent() */ send_lp_is_free(p); #endif } p->lp_data->col_set_changed = TRUE; p->comp_times.lp += used_time(&p->tt); return(termcode); }
void nearest_ins(int parent, heur_prob *p) { printf("\nIn nearest_ins....\n\n"); int numroutes, cur_route, nearnode, *starter; int mytid, info, r_bufid; int *intour; int last, cost; neighbor *nbtree; _node *tour; route_data *route_info; int start; best_tours *tours; double t=0; mytid = pvm_mytid(); (void) used_time(&t); tours = p->cur_tour = (best_tours *) calloc (1, sizeof(best_tours)); /*-----------------------------------------------------------------------*\ | Receive the VRP data | \*-----------------------------------------------------------------------*/ PVM_FUNC(r_bufid, pvm_recv(-1, ROUTE_NINS_VRP_DATA)); PVM_FUNC(info, pvm_upkbyte((char *)tours, sizeof(best_tours), 1)); tour = p->cur_tour->tour = (_node *) calloc (p->vertnum, sizeof(_node)); PVM_FUNC(info, pvm_upkbyte((char *)tour, (p->vertnum)*sizeof(_node), 1)); numroutes = p->cur_tour->numroutes; starter = (int *) calloc (numroutes, sizeof(int)); route_info = p->cur_tour->route_info = (route_data *) calloc (numroutes+1, sizeof(route_data)); PVM_FUNC(r_bufid, pvm_recv(-1, ROUTE_NINS_START_RULE)); PVM_FUNC(info, pvm_upkint(&start, 1, 1));/*receive the start rule*/ if (start != FAR_INS) srand(start); /*if the start rule is random, then*\ \*initialize the random number gen.*/ starters(p, starter, route_info, start);/*generate the route starters for*\ \*all the clusters. */ /*-----------------------------------------------------------------------*\ | Allocate arrays | \*-----------------------------------------------------------------------*/ nbtree = (neighbor *) malloc (p->vertnum * sizeof(neighbor)); intour = (int *) calloc (p->vertnum, sizeof(int)); /*-----------------------------------------------------------------------*\ | Find the nearest insertion tour from 'starters' | \*-----------------------------------------------------------------------*/ for (cur_route=1; cur_route<=numroutes; cur_route++){ /*---------------------------------------------------------------------*\ | The first part of this loop adds the starter and the nearest node to | | it into the route to initialize it. Then a function is called | | which inserts the rest of the nodes into the route in nearest | | insert order. | \*---------------------------------------------------------------------*/ if (route_info[cur_route].numcust <= 1) continue; cost = 0; last = 0; intour[0] = 0; intour[starter[cur_route-1]] = IN_TOUR; ni_insert_edges(p, starter[cur_route-1], nbtree, intour, &last, tour, cur_route); nearnode = closest(nbtree, intour, &last); intour[nearnode] = IN_TOUR; ni_insert_edges(p, nearnode, nbtree, intour, &last, tour, cur_route); tour[starter[cur_route-1]].next = nearnode; tour[nearnode].next = starter[cur_route-1]; if (starter[cur_route - 1] == 0) route_info[cur_route].first = route_info[cur_route].last = nearnode; if (nearnode == 0) route_info[cur_route].first = route_info[cur_route].last = starter[cur_route-1]; cost = 2 * ICOST(&p->dist, starter[cur_route-1], nearnode); cost = nearest_ins_from_to(p, tour, cost, 2, route_info[cur_route].numcust+1, starter[cur_route-1], nbtree, intour, &last, route_info, cur_route); route_info[cur_route].cost = cost; } tour[0].next = route_info[1].first; /*-------------------------------------------------------------------------*\ | This loop points the last node of each route to the first node of the next| | route. At the end of this procedure, the last node of each route is | | pointing at the depot, which is not what we want. | \*-------------------------------------------------------------------------*/ for (cur_route = 1; cur_route< numroutes; cur_route++) tour[route_info[cur_route].last].next = route_info[cur_route+1].first; cost = compute_tour_cost(&p->dist, tour); /*-----------------------------------------------------------------------*\ | Transmit the tour back to the parent | \*-----------------------------------------------------------------------*/ send_tour(tour, cost, numroutes, tours->algorithm, used_time(&t), parent, p->vertnum, 1, route_info); if ( nbtree ) free ((char *) nbtree); if ( intour ) free ((char *) intour); if ( starter) free ((char *) starter); free_heur_prob(p); }
void tsp_fini(int parent, heur_prob *p) { printf("\nIn tsp_fini....\n\n"); int mytid, info, r_bufid; int starter, farnode, v0, v1, cur_start; _node *tsp_tour, *tour, *opt_tour; int maxdist; int *intour; int last, cost; int i, j; neighbor *nbtree; int trials, interval; int farside, vertnum; best_tours *opt_tours, *tours; double t=0; mytid = pvm_mytid(); (void) used_time(&t); /*-----------------------------------------------------------------------*\ | Receive the VRP data | \*-----------------------------------------------------------------------*/ PVM_FUNC(r_bufid, pvm_recv(-1, TSP_FINI_TRIALS)); PVM_FUNC(info, pvm_upkint(&trials, 1, 1)); PVM_FUNC(r_bufid, pvm_recv(parent, TSP_FINI_RATIO)); PVM_FUNC(info, pvm_upkint(&farside, 1, 1)); /*-----------------------------------------------------------------------*\ | Receive the starting point | \*-----------------------------------------------------------------------*/ PVM_FUNC(r_bufid, pvm_recv(-1, TSP_START_POINT)); PVM_FUNC(info, pvm_upkint(&starter, 1, 1)); vertnum = p->vertnum; if (starter == vertnum) for (starter=v0=1, maxdist=ICOST(&p->dist, 0,1); v0<vertnum-1; v0++) for (v1=v0+1; v1<vertnum; v1++) if (maxdist < ICOST(&p->dist, v0, v1)){ maxdist = ICOST(&p->dist, v0, v1); starter = v0; } /*-----------------------------------------------------------------------*\ | Allocate arrays | \*-----------------------------------------------------------------------*/ tsp_tour = (_node *) malloc (vertnum * sizeof(_node)); nbtree = (neighbor *) malloc (vertnum * sizeof(neighbor)); intour = (int *) calloc (vertnum, sizeof(int)); tours = p->cur_tour = (best_tours *) calloc (1, sizeof(best_tours)); tour = p->cur_tour->tour = (_node *) calloc (vertnum, sizeof(_node)); opt_tours = (best_tours *) malloc (sizeof(best_tours)); opt_tour = (_node *) malloc (vertnum*sizeof(_node)); /*------------------------------------------------------------------------*\ | This heuristic is a so-called route-first, cluster-second heuristic. | | We first construct a TSP route by farnear insert and then partition it | | into feasible routes by finding a shortest cycle of a graph with edge | | costs bewtween nodes being defined to be the cost of a route from one | | endpoint of the edge to the other. | \*------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*\ | Find the first 'farside node with farthest insertion from 'starter' | \*-----------------------------------------------------------------------*/ last = 0; intour[0] = IN_TOUR; intour[starter] = IN_TOUR; tsp_fi_insert_edges(p, starter, nbtree, intour, &last); farnode = tsp_farthest(nbtree, intour, &last); intour[farnode] = IN_TOUR; tsp_fi_insert_edges(p, farnode, nbtree, intour, &last); tsp_tour[starter].next = farnode; tsp_tour[farnode].next = starter; cost = 2 * ICOST(&p->dist, starter, farnode); farside = MAX(farside, 2); cost = tsp_farthest_ins_from_to(p, tsp_tour, cost, 2, farside, starter, nbtree, intour, &last); /*------------------------------------------------------------------------*\ | Order the elements in nbtree (and fix the intour values) so after that | | nbtree is suitable to continue with nearest insertion. | \*------------------------------------------------------------------------*/ qsort((char *)(nbtree+1), last, sizeof(neighbor), compar); for (i=1; i<=last; i++) intour[nbtree[i].nbor] = i; /*-----------------------------------------------------------------------*\ | Continue with nearest insertion | \*-----------------------------------------------------------------------*/ cost = tsp_nearest_ins_from_to(p, tsp_tour, cost, farside, vertnum-1, starter, nbtree, intour, &last); /*------------------------------------------------------------------------*\ | We must arbitrarily choose a node to be the first node on the first | | route in order to start the partitioning algorithm. The trials variable | | tells us how many starting points to try. Its value is contained in | | p->par.tsp.numstarts. | \*------------------------------------------------------------------------*/ if (trials > vertnum-1) trials = vertnum-1; interval = (vertnum-1)/trials; opt_tours->cost = MAXINT; /*------------------------------------------------------------------------*\ | Try various partitionings and take the solution that has the least cost | \*------------------------------------------------------------------------*/ for (i=0, cur_start = starter; i<trials; i++){ make_routes(p, tsp_tour, cur_start, tours); if (tours->cost < opt_tours->cost){ (void) memcpy ((char *)opt_tours, (char *)tours, sizeof(best_tours)); (void) memcpy ((char *)opt_tour, (char *)tour, vertnum*sizeof(_node)); } for (j=0; j<interval; j++) cur_start = tsp_tour[cur_start].next; } /*-----------------------------------------------------------------------*\ | Transmit the tour back to the parent | \*-----------------------------------------------------------------------*/ send_tour(opt_tour, opt_tours->cost, opt_tours->numroutes, TSP_FINI, used_time(&t), parent, vertnum, 0, NULL); if ( nbtree ) free ((char *) nbtree); if ( intour ) free ((char *) intour); if ( opt_tours ) free ((char *) opt_tours); if ( opt_tour ) free ((char *) opt_tour); if ( tsp_tour ) free ((char *) tsp_tour); free_heur_prob(p); }
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 fathom(lp_prob *p, int primal_feasible) { LPdata *lp_data = p->lp_data; our_col_set *new_cols = NULL; int new_vars; int colgen = p->colgen_strategy & COLGEN__FATHOM; int termcode = p->lp_data->termcode; if (p->lp_data->nf_status == NF_CHECK_NOTHING){ PRINT(p->par.verbosity, 1, ("fathoming node (no more cols to check)\n\n")); send_node_desc(p, primal_feasible ? (termcode == LP_OPT_FEASIBLE ? FEASIBLE_PRUNED: OVER_UB_PRUNED) : INFEASIBLE_PRUNED); return(TRUE); } if (p->colgen_strategy & COLGEN_REPRICING) colgen = FATHOM__GENERATE_COLS__RESOLVE; switch (colgen){ case FATHOM__DO_NOT_GENERATE_COLS__DISCARD: PRINT(p->par.verbosity, 1, ("Pruning node\n\n")); send_node_desc(p, termcode == LP_OPT_FEASIBLE ? FEASIBLE_PRUNED : DISCARDED_NODE); return(TRUE); case FATHOM__DO_NOT_GENERATE_COLS__SEND: PRINT(p->par.verbosity, 1, ("Sending node for pricing\n\n")); send_node_desc(p, primal_feasible ? OVER_UB_HOLD_FOR_NEXT_PHASE : INFEASIBLE_HOLD_FOR_NEXT_PHASE); return(TRUE); case FATHOM__GENERATE_COLS__RESOLVE: check_ub(p); /* Note that in case of COLGEN_REPRICING we must have UB. */ if (! p->has_ub){ PRINT(p->par.verbosity, 1, ("\nCan't generate cols before sending (no UB)\n")); send_node_desc(p, primal_feasible ? OVER_UB_HOLD_FOR_NEXT_PHASE : INFEASIBLE_HOLD_FOR_NEXT_PHASE); return(TRUE); } PRINT(p->par.verbosity, 1, ("\nGenerating columns before fathoming/resolving\n")); new_cols = price_all_vars(p); p->comp_times.pricing += used_time(&p->tt); new_vars = new_cols->num_vars + new_cols->rel_ub + new_cols->rel_lb; if (new_cols->dual_feas == NOT_TDF){ /* 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)); free_col_set(&new_cols); return(FALSE); } /* Now we know that we have total dual feasibility */ if ((p->has_ub && lp_data->objval > p->ub - p->par.granularity) || termcode == LP_D_OBJLIM || termcode == LP_OPT_FEASIBLE){ /* fathomable */ if (termcode == LP_D_OBJLIM || (p->has_ub && lp_data->objval > p->ub - p->par.granularity)){ PRINT(p->par.verbosity, 1, ("Fathoming node (discovered tdf & high cost)\n\n")); }else{ PRINT(p->par.verbosity, 1, ("Fathoming node (discovered tdf & feasible)\n\n")); } send_node_desc(p, termcode == LP_OPT_FEASIBLE ? FEASIBLE_PRUNED : OVER_UB_PRUNED); free_col_set(&new_cols); return(TRUE); } /* If we ever arrive here then we must have tdf and the function * was called with a primal infeasible LP. * * Again, note that in case of COLGEN_REPRICING, since we do that * only in the root node, the lp relaxation MUST be primal feasible, * * If TDF_HAS_ALL, then whatever can be used to restore * primal feasibility is already in the matrix so don't bother * to figure out restorability, just return and resolve the problem * (if new_vars == 0 then even returning is unnecessary, the node * can be fathomed, nothing can restore feasibility). */ if (new_cols->dual_feas == TDF_HAS_ALL){ if (new_vars == 0){ PRINT(p->par.verbosity, 1, ("fathoming node (no more cols to check)\n\n")); send_node_desc(p, INFEASIBLE_PRUNED); free_col_set(&new_cols); return(TRUE); }else{ free_col_set(&new_cols); return(FALSE); } } /* Sigh. There were too many variables not fixable even though we have * proved tdf. new_cols contains a good many of the non-fixables, use * new_cols to start with in restore_lp_feasibility(). */ if (! restore_lp_feasibility(p, new_cols)){ PRINT(p->par.verbosity, 1, ("Fathoming node (discovered tdf & not restorable inf.)\n\n")); send_node_desc(p, INFEASIBLE_PRUNED); free_col_set(&new_cols); return(TRUE); } /* So primal feasibility is restorable. Exactly one column has been * added (released or a new variable) to destroy the proof of * infeasibility */ free_col_set(&new_cols); p->comp_times.pricing += used_time(&p->tt); return(FALSE); } return(TRUE); /* fake return */ }
int lp_initialize(lp_prob *p, int master_tid) { #ifndef COMPILE_IN_LP int msgtag, bytes, r_bufid; #endif #if !defined(COMPILE_IN_TM) || !defined(COMPILE_IN_LP) int s_bufid; #endif int i; row_data *rows; var_desc **vars; int termcode = 0; #ifdef COMPILE_IN_LP p->master = master_tid; #else /* set stdout to be line buffered */ setvbuf(stdout, (char *)NULL, _IOLBF, 0); register_process(); /*------------------------------------------------------------------------*\ * Receive tid info; request and receive problem specific data \*------------------------------------------------------------------------*/ r_bufid = receive_msg(ANYONE, MASTER_TID_INFO); bufinfo(r_bufid, &bytes, &msgtag, &p->tree_manager); receive_int_array(&p->master, 1); receive_int_array(&p->proc_index, 1); freebuf(r_bufid); #endif p->lp_data = (LPdata *) calloc(1, sizeof(LPdata)); p->lp_data->mip = (MIPdesc *) calloc(1, sizeof(MIPdesc)); p->lp_data->par = p->par; #pragma omp critical (lp_solver) open_lp_solver(p->lp_data); (void) used_time(&p->tt); #if !defined(COMPILE_IN_TM) || !defined(COMPILE_IN_LP) s_bufid = init_send(DataInPlace); send_msg(p->master, REQUEST_FOR_LP_DATA); freebuf(s_bufid); CALL_WRAPPER_FUNCTION( receive_lp_data_u(p) ); #endif if (p->par.tailoff_gap_backsteps > 0 || p->par.tailoff_obj_backsteps > 1){ i = MAX(p->par.tailoff_gap_backsteps, p->par.tailoff_obj_backsteps); p->obj_history = (double *) malloc((i + 1) * DSIZE); } #ifndef COMPILE_IN_LP if (p->par.use_cg){ r_bufid = receive_msg(p->tree_manager, LP__CG_TID_INFO); receive_int_array(&p->cut_gen, 1); freebuf(r_bufid); } #endif p->lp_data->rows = (row_data *) malloc((p->base.cutnum + BB_BUNCH) * sizeof(row_data)); rows = p->lp_data->rows; for (i = p->base.cutnum - 1; i >= 0; i--){ ( rows[i].cut = (cut_data *) malloc(sizeof(cut_data)) )->coef = NULL; } if (p->base.varnum > 0){ vars = p->lp_data->vars = (var_desc **) malloc(p->base.varnum * sizeof(var_desc *)); for (i = p->base.varnum - 1; i >= 0; i--){ vars[i] = (var_desc *) malloc( sizeof(var_desc) ); vars[i]->userind = p->base.userind[i]; vars[i]->colind = i; } } /* Just to make sure this array is sufficently big */ p->lp_data->not_fixed = (int *) malloc(p->par.not_fixed_storage_size*ISIZE); p->lp_data->tmp.iv = (int *) malloc(p->par.not_fixed_storage_size* 2*ISIZE); p->lp_data->tmp.iv_size = 2*p->par.not_fixed_storage_size; #ifdef COMPILE_IN_CG if (!p->cgp){ p->cgp = (cg_prob *) calloc(1, sizeof(cg_prob)); } cg_initialize(p->cgp, p->master); #endif return(FUNCTION_TERMINATED_NORMALLY); }
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); }
int main(void) { int r_bufid = 0, s_bufid = 0; cg_prob *p; int num_cuts = 0; double elapsed; struct timeval tout = {15, 0}; p = (cg_prob *) calloc(1, sizeof(cg_prob)); cg_initialize(p, 0); /*------------------------------------------------------------------------*\ * The main loop -- executes continuously until the program exits \*------------------------------------------------------------------------*/ while (TRUE){ /* Wait until a message arrives */ do{ r_bufid = treceive_msg(ANYONE, ANYTHING, &tout); if (!r_bufid){ if (pstat(p->tree_manager) != PROCESS_OK){ printf("TM has died -- CG exiting\n\n"); exit(-401); } } }while (!r_bufid); if (cg_process_message(p, r_bufid) == USER_ERROR) p->msgtag = USER_ERROR; /* If there is still something in the queue, process it */ do{ r_bufid = nreceive_msg(ANYONE, ANYTHING); if (r_bufid > 0) if (cg_process_message(p, r_bufid) == USER_ERROR) p->msgtag = USER_ERROR; }while (r_bufid != 0); /*--------------------------------------------------------------------- * Now the message queue is empty. If the last message was NOT some * kind of LP_SOLUTION then we can't generate solutions now. * Otherwise, generate solutions! *---------------------------------------------------------------------*/ if (p->msgtag == LP_SOLUTION_NONZEROS || p->msgtag == LP_SOLUTION_USER || p->msgtag == LP_SOLUTION_FRACTIONS){ if (p->par.do_findcuts) if ((termcode = find_cuts_u(p, NULL, &num_cuts)) < 0) printf("Warning: User error detected in cut generator\n\n"); /*-- send signal back to the LP that the cut generator is done -----*/ s_bufid = init_send(DataInPlace); send_int_array(&num_cuts, 1); elapsed = used_time(&p->tt); send_dbl_array(&elapsed, 1); send_int_array(&p->cur_sol.xindex, 1); send_int_array(&p->cur_sol.xiter_num, 1); send_msg(p->cur_sol.lp, NO_MORE_CUTS); freebuf(s_bufid); FREE(p->cur_sol.xind); FREE(p->cur_sol.xval); } } return(0); }
int branch(lp_prob *p, int cuts) { LPdata *lp_data = p->lp_data; branch_obj *can; char *action; int branch_var, branch_row, keep; var_desc *var; cut_data *cut; node_desc *desc; can = select_branching_object(p, &cuts); if (can == NULL){ /* We were either able to fathom the node or found violated cuts * In any case, send the qualifying cuts to the cutpool */ p->comp_times.strong_branching += used_time(&p->tt); #pragma omp critical(cut_pool) send_cuts_to_pool(p, p->par.eff_cnt_before_cutpool); p->comp_times.communication += used_time(&p->tt); return( cuts == -1 ? FATHOMED_NODE : cuts ); } /*------------------------------------------------------------------------*\ * Now we evaluate can, the best of the candidates. \*------------------------------------------------------------------------*/ action = lp_data->tmp.c; /* n (good estimate... can->child_num) */ select_child_u(p, can, action); if (p->par.verbosity > 4) print_branch_stat_u(p, can, action); for (keep = can->child_num-1; keep >= 0; keep--) if (action[keep] == KEEP_THIS_CHILD) break; /* Send the branching information to the TM and inquire whether we should dive */ p->comp_times.strong_branching += used_time(&p->tt); send_branching_info(p, can, action, &keep); p->comp_times.communication += used_time(&p->tt); /* If we don't dive then return quickly */ if (keep < 0 || p->dive == DO_NOT_DIVE){ free_candidate_completely(&can); return(FATHOMED_NODE); } desc = p->desc; switch (can->type){ case CANDIDATE_VARIABLE: var = lp_data->vars[branch_var = can->position]; switch (can->sense[keep]){ case 'E': var->lb = var->ub = can->rhs[keep]; break; case 'R': var->lb = can->rhs[keep]; var->ub = var->lb + can->range[keep]; break; case 'L': var->ub = can->rhs[keep]; break; case 'G': var->lb = can->rhs[keep]; break; } change_col(lp_data, branch_var, can->sense[keep], var->lb, var->ub); lp_data->status[branch_var] |= VARIABLE_BRANCHED_ON; break; case CANDIDATE_CUT_IN_MATRIX: branch_row = can->position; cut = lp_data->rows[branch_row].cut; /* To maintain consistency with TM we have to fix a few more things if we had a non-base, new branching cut */ if (branch_row >= p->base.cutnum && !(cut->branch & CUT_BRANCHED_ON)){ /* insert cut->name into p->desc.cutind.list, and insert SLACK_BASIC to the same position in p->desc.basis.extrarows.stat */ #ifdef DO_TESTS if (desc->cutind.size != desc->basis.extrarows.size){ printf("Oops! desc.cutind.size != desc.basis.extrarows.size! \n"); exit(-123); } #endif #ifdef COMPILE_IN_LP /* Because these cuts are shared with the treemanager, we have to make a copy before changing them if the LP is compiled in */ cut = (cut_data *) malloc(sizeof(cut_data)); memcpy((char *)cut, (char *)lp_data->rows[branch_row].cut, sizeof(cut_data)); if (cut->size){ cut->coef = malloc(cut->size); memcpy((char *)cut->coef, (char *)lp_data->rows[branch_row].cut->coef, cut->size); } lp_data->rows[branch_row].cut = cut; #endif if (desc->cutind.size == 0){ desc->cutind.size = 1; desc->cutind.list = (int *) malloc(ISIZE); desc->cutind.list[0] = cut->name; desc->basis.extrarows.size = 1; /* this must have been 0, too */ desc->basis.extrarows.stat = (int *) malloc(ISIZE); desc->basis.extrarows.stat[0] = SLACK_BASIC; }else{ int i, name = cut->name; int *list; int *stat; /* most of the time the one extra element will fit into the already allocated memory chunk, so it's worth to realloc */ desc->cutind.size++; list = desc->cutind.list = (int *) realloc(desc->cutind.list, desc->cutind.size * ISIZE); desc->basis.extrarows.size++; stat = desc->basis.extrarows.stat = (int *) realloc(desc->basis.extrarows.stat, desc->cutind.size * ISIZE); for (i = desc->cutind.size - 1; i > 0; i--){ #ifdef DO_TESTS if (name == list[i-1]){ printf("Oops! name == desc.cutind.list[i] !\n"); exit(-124); } #endif if (name < list[i-1]){ list[i] = list[i-1]; stat[i] = stat[i-1]; }else{ break; } } list[i] = name; stat[i] = SLACK_BASIC; } } cut->rhs = can->rhs[keep]; if ((cut->sense = can->sense[keep]) == 'R') cut->range = can->range[keep]; cut->branch = CUT_BRANCHED_ON | can->branch[keep]; constrain_row_set(lp_data, 1, &branch_row); lp_data->rows[branch_row].free = FALSE; break; } /* Since this is a child we dived into, we know that TM stores the stati of extra vars/rows wrt the parent */ p->desc->basis.extravars.type = WRT_PARENT; p->desc->basis.extrarows.type = WRT_PARENT; free_candidate_completely(&can); /* the new p->bc_index is received in send_branching_info() */ p->bc_level++; /*p->iter_num = 0;*/ return(NEW_NODE); }
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); }
int main(void) { lp_prob *p; int r_bufid; double time, diff; struct timeval timeout = {10, 0}; char first_node_rec = FALSE; int termcode; p = (lp_prob *) calloc(1, sizeof(lp_prob)); p->start_time = wall_clock(NULL); if ((termcode = lp_initialize(p, 0)) < 0){ printf("LP initialization failed with error code %i\n\n", termcode); lp_exit(p); } /*------------------------------------------------------------------------*\ * Continue receiving node data and fathoming branches until this * process is killed \*------------------------------------------------------------------------*/ p->phase = 0; while (TRUE){ p->lp_data->col_set_changed = TRUE; /*---------------------------------------------------------------------*\ * waits for an active node message but if there's anything left after * receiving that, those messages are processed, before going to * process_chain(). \*---------------------------------------------------------------------*/ time = wall_clock(NULL); do{ r_bufid = treceive_msg(ANYONE, ANYTHING, &timeout); }while (! process_message(p, r_bufid, NULL, NULL) ); diff = wall_clock(NULL) - time; if (first_node_rec){ p->comp_times.idle_node += diff; }else{ first_node_rec = TRUE; p->comp_times.ramp_up_lp += diff; } do{ r_bufid = nreceive_msg(ANYONE, ANYTHING); if (r_bufid) process_message(p, r_bufid, NULL, NULL); }while (r_bufid); p->comp_times.communication += used_time(&p->tt); if (process_chain(p) < 0){ printf("\nThere was an error in the LP process. Exiting now.\n\n"); /* There was an error in the LP. Abandon node. */ lp_exit(p); } } p->comp_times.wall_clock_lp = wall_clock(NULL) - p->start_time; lp_exit(p); return(0); }
float used_time(float& T) { float t = T; T = used_time(); return T-t; }