예제 #1
0
파일: res.c 프로젝트: funtoo/vzctl
/** Function called on CT start to setup resource management
 *
 */
int setup_resource_management(vps_handler *h, envid_t veid, vps_res *res)
{
	int ret;

	if ((ret = check_ub(&res->ub)))
		return ret;
	if ((ret = set_ublimit(h, veid, &res->ub)))
		return ret;
	return 0;
}
예제 #2
0
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 */
}
예제 #3
0
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);
}
예제 #4
0
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 */
}
예제 #5
0
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);
}
예제 #6
0
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);
}
예제 #7
0
파일: env.c 프로젝트: funtoo/vzctl
int vps_start_custom(vps_handler *h, envid_t veid, vps_param *param,
                     skipFlags skip, struct mod_action *mod,
                     env_create_FN fn, void *data)
{
    int wait_p[2];
    int old_wait_p[2];
    int err_p[2];
    int ret, err;
    char buf[64];
    char *dist_name;
    struct sigaction act;
    vps_res *res = &param->res;
    dist_actions actions;

    memset(&actions, 0, sizeof(actions));
    if (check_var(res->fs.root, "VE_ROOT is not set"))
        return VZ_VE_ROOT_NOTSET;
    if (vps_is_run(h, veid)) {
        logger(-1, 0, "Container is already running");
        return VZ_VE_RUNNING;
    }
    if ((ret = check_ub(&res->ub)))
        return ret;
    dist_name = get_dist_name(&res->tmpl);
    ret = read_dist_actions(dist_name, DIST_DIR, &actions);
    free(dist_name);
    if (ret)
        return ret;
    logger(0, 0, "Starting container ...");
    if (vps_is_mounted(res->fs.root)) {
        /* if CT is mounted -- umount first, to cleanup mount state */
        vps_umount(h, veid, res->fs.root, skip);
    }
    if (!vps_is_mounted(res->fs.root)) {
        /* increase quota to perform setup */
        quota_inc(&res->dq, 100);
        if ((ret = vps_mount(h, veid, &res->fs, &res->dq, skip)))
            return ret;
        quota_inc(&res->dq, -100);
    }
    /* Fedora 14/15 hacks */
    if (fix_ve_devconsole(res->fs.root) != 0)
        return VZ_FS_BAD_TMPL;
    if (fix_ve_systemd(res->fs.root) != 0)
        return VZ_FS_BAD_TMPL;

    if (pipe(wait_p) < 0) {
        logger(-1, errno, "Can not create pipe");
        return VZ_RESOURCE_ERROR;
    }
    /* old_wait_p is needed for backward compatibility with older kernels,
     * while for recent ones (that support CPT_SET_LOCKFD2) we use wait_p.
     *
     * If old_wait_p is closed without writing any data, it's "OK to go"
     * signal, and if data are received from old_wait_p it's "no go"
     * signal". Note that such thing doesn't work if vzctl segfaults,
     * because in this case the descriptor will be closed without
     * sending data.
     */
    if (pipe(old_wait_p) < 0) {
        logger(-1, errno, "Can not create pipe");
        return VZ_RESOURCE_ERROR;
    }
    if (pipe(err_p) < 0) {
        close(wait_p[0]);
        close(wait_p[1]);
        logger(-1, errno, "Can not create pipe");
        return VZ_RESOURCE_ERROR;
    }
    sigemptyset(&act.sa_mask);
    act.sa_handler = SIG_IGN;
    act.sa_flags = 0;
    sigaction(SIGPIPE, &act, NULL);
    fix_numiptent(&res->ub);
    fix_cpu(&res->cpu);

    ret = vz_env_create(h, veid, res, wait_p,
                        old_wait_p, err_p, fn, data);
    if (ret)
        goto err;

    if ((ret = vps_setup_res(h, veid, &actions, &res->fs, param,
                             STATE_STARTING, skip, mod)))
    {
        goto err;
    }
    if (!(skip & SKIP_ACTION_SCRIPT)) {
        snprintf(buf, sizeof(buf), VPS_CONF_DIR "%d.%s", veid,
                 START_PREFIX);
        if (stat_file(buf)) {
            if (vps_exec_script(h, veid, res->fs.root, NULL, NULL,
                                buf, NULL, 0))
            {
                ret = VZ_ACTIONSCRIPT_ERROR;
                goto err;
            }
        }
    }
    /* Tell the child that it's time to start /sbin/init */
    err = 0;
    if (write(wait_p[1], &err, sizeof(err)) != sizeof(err))
        logger(-1, errno, "Unable to write to waitfd to start init");
    close(wait_p[1]);
    close(old_wait_p[1]);
err:
    free_dist_actions(&actions);
    if (ret) {
        /* Kill environment */
        logger(-1, 0, "Container start failed (try to check kernel "
               "messages, e.g. \"dmesg | tail\")");
        /* Close wait fd without writing anything to it
         * to signal the child that we have failed to configure
         * the environment, so it should not start /sbin/init
         */
        close(wait_p[1]);
        write(old_wait_p[1], &err, sizeof(err));
        close(old_wait_p[1]);
    } else {
        if (!read(err_p[0], &ret, sizeof(ret))) {
            if (res->misc.wait == YES) {
                logger(0, 0, "Container start in progress"
                       ", waiting ...");
                err = vps_execFn(h, veid, res->fs.root,
                                 wait_on_fifo, NULL, 0);
                if (err) {
                    logger(0, 0, "Container wait failed%s",
                           err == VZ_EXEC_TIMEOUT ? \
                           " - timeout expired" : "");
                    ret = VZ_WAIT_FAILED;
                } else {
                    logger(0, 0, "Container started"
                           " successfully");
                }
            } else {
                logger(0, 0, "Container start in progress...");
            }
        } else {
            if (ret == VZ_FS_BAD_TMPL)
                logger(-1, 0, "Unable to start init, probably"
                       " incorrect template");
            logger(-1, 0, "Container start failed");
        }
    }
    if (ret) {
        if (vps_is_run(h, veid))
            env_stop(h, veid, res->fs.root, M_KILL);
        /* restore original quota values */
        vps_set_quota(veid, &res->dq);
        if (vps_is_mounted(res->fs.root))
            vps_umount(h, veid, res->fs.root, skip);
    }
    close(wait_p[0]);
    close(wait_p[1]);
    close(err_p[0]);
    close(err_p[1]);

    return ret;
}