예제 #1
0
파일: branch_pscost.c 프로젝트: hhexiy/scip
/** checks if a given branching candidate is better than a previous one and updates the best branching candidate accordingly */
static
SCIP_RETCODE updateBestCandidate(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_BRANCHRULEDATA*  branchruledata,     /**< branching rule data */
   SCIP_VAR**            bestvar,            /**< best branching candidate */
   SCIP_Real*            bestbrpoint,        /**< branching point for best branching candidate */
   SCIP_Real*            bestscore,          /**< score of best branching candidate */
   SCIP_VAR*             cand,               /**< branching candidate to consider */
   SCIP_Real             candscoremin,       /**< minimal score of branching candidate */
   SCIP_Real             candscoremax,       /**< maximal score of branching candidate */
   SCIP_Real             candscoresum,       /**< sum of scores of branching candidate */
   SCIP_Real             candsol             /**< proposed branching point of branching candidate */          
)
{
   SCIP_Real candbrpoint;
   SCIP_Real branchscore;

   SCIP_Real deltaminus;
   SCIP_Real deltaplus;

   SCIP_Real pscostdown;
   SCIP_Real pscostup;
   
   char strategy;

   assert(scip != NULL);
   assert(branchruledata != NULL);
   assert(bestvar != NULL);
   assert(bestbrpoint != NULL);
   assert(bestscore != NULL);
   assert(cand != NULL);

   /* a branching variable candidate should either be an active problem variable or a multi-aggregated variable */
   assert(SCIPvarIsActive(SCIPvarGetProbvar(cand)) ||
      SCIPvarGetStatus(SCIPvarGetProbvar(cand)) == SCIP_VARSTATUS_MULTAGGR);
   
   if( SCIPvarGetStatus(SCIPvarGetProbvar(cand)) == SCIP_VARSTATUS_MULTAGGR )
   {
      /* for a multi-aggregated variable, we call updateBestCandidate function recursively with all variables in the multi-aggregation */
      SCIP_VAR** multvars;
      int nmultvars;
      int i;
      SCIP_Bool success;
      SCIP_Real multvarlb;
      SCIP_Real multvarub;

      cand = SCIPvarGetProbvar(cand);
      multvars = SCIPvarGetMultaggrVars(cand);
      nmultvars = SCIPvarGetMultaggrNVars(cand);

      /* if we have a candidate branching point, then first register only aggregation variables
       * for which we can compute a corresponding branching point too (see also comments below)
       * if this fails, then register all (unfixed) aggregation variables, thereby forgetting about candsol
       */
      success = FALSE;
      if( candsol != SCIP_INVALID ) /*lint !e777*/
      {
         SCIP_Real* multscalars;
         SCIP_Real minact;
         SCIP_Real maxact;
         SCIP_Real aggrvarsol;
         SCIP_Real aggrvarsol1;
         SCIP_Real aggrvarsol2;

         multscalars = SCIPvarGetMultaggrScalars(cand);

         /* for computing the branching point, we need the current bounds of the multi-aggregated variable */
         minact = SCIPcomputeVarLbLocal(scip, cand);
         maxact = SCIPcomputeVarUbLocal(scip, cand);

         for( i = 0; i < nmultvars; ++i )
         {
            /* skip fixed variables */
            multvarlb = SCIPcomputeVarLbLocal(scip, multvars[i]);
            multvarub = SCIPcomputeVarUbLocal(scip, multvars[i]);
            if( SCIPisEQ(scip, multvarlb, multvarub) )
               continue;

            assert(multscalars != NULL);
            assert(multscalars[i] != 0.0);

            /* we cannot ensure that both the upper bound in the left node and the lower bound in the right node
             * will be candsol by a clever choice for the branching point of multvars[i],
             * but we can try to ensure that at least one of them will be at candsol
             */
            if( multscalars[i] > 0.0 )
            {
               /*    cand >= candsol
                * if multvars[i] >= (candsol - (maxact - multscalars[i] * ub(multvars[i]))) / multscalars[i]
                *                 = (candsol - maxact) / multscalars[i] + ub(multvars[i])
                */
               aggrvarsol1 = (candsol - maxact) / multscalars[i] + multvarub;

               /*     cand <= candsol
                * if multvars[i] <= (candsol - (minact - multscalar[i] * lb(multvars[i]))) / multscalars[i]
                *                 = (candsol - minact) / multscalars[i] + lb(multvars[i])
                */
               aggrvarsol2 = (candsol - minact) / multscalars[i] + multvarlb;
            }
            else
            {
               /*    cand >= candsol
                * if multvars[i] <= (candsol - (maxact - multscalars[i] * lb(multvars[i]))) / multscalars[i]
                *                 = (candsol - maxact) / multscalars[i] + lb(multvars[i])
                */
               aggrvarsol2 = (candsol - maxact) / multscalars[i] + multvarlb;

               /*    cand <= candsol
                * if multvars[i] >= (candsol - (minact - multscalar[i] * ub(multvars[i]))) / multscalars[i]
                *                 = (candsol - minact) / multscalars[i] + ub(multvars[i])
                */
               aggrvarsol1 = (candsol - minact) / multscalars[i] + multvarub;
            }

            /* by the above choice, aggrvarsol1 <= ub(multvars[i]) and aggrvarsol2 >= lb(multvars[i])
             * if aggrvarsol1 <= lb(multvars[i]) or aggrvarsol2 >= ub(multvars[i]), then choose the other one
             * if both are out of bounds, then give up
             * if both are inside bounds, then choose the one closer to 0.0 (someone has better idea???)
             */
            if( SCIPisFeasLE(scip, aggrvarsol1, multvarlb) )
            {
               if( SCIPisFeasGE(scip, aggrvarsol2, multvarub) )
                  continue;
               else
                  aggrvarsol = aggrvarsol2;
            }
            else
            {
               if( SCIPisFeasGE(scip, aggrvarsol2, multvarub) )
                  aggrvarsol = aggrvarsol1;
               else
                  aggrvarsol = REALABS(aggrvarsol1) < REALABS(aggrvarsol2) ? aggrvarsol1 : aggrvarsol2;
            }
            success = TRUE;

            SCIP_CALL( updateBestCandidate(scip, branchruledata, bestvar, bestbrpoint, bestscore,
                  multvars[i], candscoremin, candscoremax, candscoresum, aggrvarsol) );
         }
      }

      if( !success )
         for( i = 0; i < nmultvars; ++i )
         {
            /* skip fixed variables */
            multvarlb = SCIPcomputeVarLbLocal(scip, multvars[i]);
            multvarub = SCIPcomputeVarUbLocal(scip, multvars[i]);
            if( SCIPisEQ(scip, multvarlb, multvarub) )
               continue;

            SCIP_CALL( updateBestCandidate(scip, branchruledata, bestvar, bestbrpoint, bestscore,
               multvars[i], candscoremin, candscoremax, candscoresum, SCIP_INVALID) );
         }

      assert(*bestvar != NULL); /* if all variables were fixed, something is strange */
      
      return SCIP_OKAY;
   }
   
   /* select branching point for this variable */
   candbrpoint = SCIPgetBranchingPoint(scip, cand, candsol);
   assert(candbrpoint >= SCIPvarGetLbLocal(cand));
   assert(candbrpoint <= SCIPvarGetUbLocal(cand));

   /* we cannot branch on a huge value for a discrete variable, because we simply cannot enumerate such huge integer values in floating point
    * arithmetics
    */
   if( SCIPvarGetType(cand) != SCIP_VARTYPE_CONTINUOUS && (SCIPisHugeValue(scip, candbrpoint) || SCIPisHugeValue(scip, -candbrpoint)) )
      return SCIP_OKAY;

   assert(SCIPvarGetType(cand) == SCIP_VARTYPE_CONTINUOUS || !SCIPisIntegral(scip, candbrpoint));

   if( SCIPvarGetType(cand) == SCIP_VARTYPE_CONTINUOUS )
      strategy = (branchruledata->strategy == 'u' ? branchruledata->updatestrategy : branchruledata->strategy);
   else
      strategy = (branchruledata->strategy == 'u' ? 'l' : branchruledata->strategy);

   switch( strategy )
   {
   case 'l':
      if( SCIPisInfinity(scip,  SCIPgetSolVal(scip, NULL, cand)) || SCIPgetSolVal(scip, NULL, cand) <= SCIPadjustedVarUb(scip, cand, candbrpoint) )
         deltaminus = 0.0;
      else
         deltaminus = SCIPgetSolVal(scip, NULL, cand) - SCIPadjustedVarUb(scip, cand, candbrpoint);
      if( SCIPisInfinity(scip, -SCIPgetSolVal(scip, NULL, cand)) || SCIPgetSolVal(scip, NULL, cand) >= SCIPadjustedVarLb(scip, cand, candbrpoint) )
         deltaplus = 0.0;
      else
         deltaplus = SCIPadjustedVarLb(scip, cand, candbrpoint) - SCIPgetSolVal(scip, NULL, cand);
      break;

   case 'd':
      if( SCIPisInfinity(scip, -SCIPvarGetLbLocal(cand)) )
         deltaminus = SCIPisInfinity(scip, candscoremax) ? SCIPinfinity(scip) : WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum);
      else
         deltaminus = SCIPadjustedVarUb(scip, cand, candbrpoint) - SCIPvarGetLbLocal(cand);

      if( SCIPisInfinity(scip,  SCIPvarGetUbLocal(cand)) )
         deltaplus = SCIPisInfinity(scip, candscoremax) ? SCIPinfinity(scip) : WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum);
      else
         deltaplus = SCIPvarGetUbLocal(cand) - SCIPadjustedVarLb(scip, cand, candbrpoint);
      break;
      
   case 's':
      if( SCIPisInfinity(scip, -SCIPvarGetLbLocal(cand)) )
         deltaplus = SCIPisInfinity(scip, candscoremax) ? SCIPinfinity(scip) : WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum);
      else
         deltaplus = SCIPadjustedVarUb(scip, cand, candbrpoint) - SCIPvarGetLbLocal(cand);

      if( SCIPisInfinity(scip,  SCIPvarGetUbLocal(cand)) )
         deltaminus = SCIPisInfinity(scip, candscoremax) ? SCIPinfinity(scip) : WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum);
      else
         deltaminus = SCIPvarGetUbLocal(cand) - SCIPadjustedVarLb(scip, cand, candbrpoint);
      break;

   case 'v':
      deltaplus = SCIPisInfinity(scip, candscoremax) ? SCIPinfinity(scip) : WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum);
      deltaminus = deltaplus;
      break;

   default :
      SCIPerrorMessage("branching strategy %c unknown\n", strategy);
      SCIPABORT();
      return SCIP_INVALIDDATA;  /*lint !e527*/
   }

   if( SCIPisInfinity(scip, deltaminus) || SCIPisInfinity(scip, deltaplus) )
   {
      branchscore = SCIPinfinity(scip);
   }
   else
   {
      pscostdown  = SCIPgetVarPseudocostVal(scip, cand, -deltaminus);
      pscostup    = SCIPgetVarPseudocostVal(scip, cand,  deltaplus);
      branchscore = SCIPgetBranchScore(scip, cand, pscostdown, pscostup);
      assert(!SCIPisNegative(scip, branchscore));
   }
   SCIPdebugMessage("branching score variable <%s>[%g,%g] = %g; wscore = %g; type=%d bestbrscore=%g\n",
      SCIPvarGetName(cand), SCIPvarGetLbLocal(cand), SCIPvarGetUbLocal(cand), branchscore, WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum),
      SCIPvarGetType(cand), *bestscore);

   if( SCIPisInfinity(scip, branchscore) )
      branchscore = 0.9*SCIPinfinity(scip);
   
   if( SCIPisSumGT(scip, branchscore, *bestscore) )
   {
      (*bestscore)   = branchscore;
      (*bestvar)     = cand;
      (*bestbrpoint) = candbrpoint;
   }
   else if( SCIPisSumEQ(scip, branchscore, *bestscore)
      && !(SCIPisInfinity(scip, -SCIPvarGetLbLocal(*bestvar)) && SCIPisInfinity(scip, SCIPvarGetUbLocal(*bestvar))) )
   {
      /* if best candidate so far is not unbounded to both sides, maybe take new candidate */
      if( (SCIPisInfinity(scip, -SCIPvarGetLbLocal(cand))     || SCIPisInfinity(scip, SCIPvarGetUbLocal(cand))) &&
          (SCIPisInfinity(scip, -SCIPvarGetLbLocal(*bestvar)) || SCIPisInfinity(scip, SCIPvarGetUbLocal(*bestvar))) )
      { 
         /* if both variables are unbounded but one of them is bounded on one side, take the one with the larger bound on this side (hope that this avoids branching on always the same variable) */
         if( SCIPvarGetUbLocal(cand) > SCIPvarGetUbLocal(*bestvar) || SCIPvarGetLbLocal(cand) < SCIPvarGetLbLocal(*bestvar) )
         {
            (*bestscore)   = branchscore;
            (*bestvar)     = cand;
            (*bestbrpoint) = candbrpoint;
         }
      }
      else if( SCIPvarGetType(*bestvar) == SCIPvarGetType(cand) )
      { 
         /* if both have the same type, take the one with larger diameter */
         if( SCIPvarGetUbLocal(*bestvar) - SCIPvarGetLbLocal(*bestvar) < SCIPvarGetUbLocal(cand) - SCIPvarGetLbLocal(cand) )
         {
            (*bestscore)   = branchscore;
            (*bestvar)     = cand;
            (*bestbrpoint) = candbrpoint;
         }
      }
      else if( SCIPvarGetType(*bestvar) > SCIPvarGetType(cand) )
      { 
         /* take the one with better type ("more discrete") */
         (*bestscore)   = branchscore;
         (*bestvar)     = cand;
         (*bestbrpoint) = candbrpoint;
      }
   }

   return SCIP_OKAY;
}
예제 #2
0
/** execution method of primal heuristic */
static
SCIP_DECL_HEUREXEC(heurExecForward)
{  /*lint --e{715}*/
	
   SCIP_PROBDATA* probdata;
	int	n;
	int	p;
	int	ndep;

	/* "_" means the matrix for blas */
	SCIP_Real*	y;				/* [n] */
	SCIP_Real*	orig_X_;		/* [n*p] */
	SCIP_Real*	orig_Q_;		/* [p*p] <- (X^t) X */
	SCIP_Real*	orig_q;		/* [p]   <- (X^t) y */
	SCIP_Real	r;

	int*	Mdep;					/* [ndep] */
	int*	groupX;				/* [ndep*p] */

	/* for forward selection */
	int	dim;
	int*	list;					/* [p] */
	SCIP_Real*	a;				/* [dim] */
	SCIP_Real*	a_old;		/* [dim-1] */
	SCIP_Real*	a_new;		/* [dim] */
	SCIP_Real	RSS;			/* residual sum of square */
	SCIP_Real	RSS_new;
	SCIP_Real	AIC;
	SCIP_Real	AIC_new;

	int	ublb;
	int	*Branchz;		/* [3*p] */

	/*
	 *	X: sub matrix of orig_X_ 
	 *	Y:	(X^t X)^-1 
	 * X_new = (X, x_i);
	 * Z: (X_new ^t X_new)^-1
	 *		= ( V   v
	 			 v^t u )
	 */

	SCIP_Real*	Xy;	/* sub vector of orig_q */ 
	SCIP_Real*	X_;	
	SCIP_Real*	Y_;	/* [(dim-1)*(dim-1)] */
	SCIP_Real*	Z_;	/* [dim*dim] */
	SCIP_Real*	W_;	/* [dim*dim] */
	SCIP_Real*	V_;	/* [(dim-1)*(dim-1)] */
	SCIP_Real*	v;		/* [dim-1] */
	SCIP_Real	u;
	
	SCIP_Real*	b;		/* [dim-1] */
	SCIP_Real*	c;		/* [dim-1] */
	SCIP_Real*	d;		/* [n] */

	/* variables */
	SCIP_VAR**	var_a;		/* [p] continuous variables */
	SCIP_VAR**	var_z;		/* [p] 01 variables */
	SCIP_VAR**	var_ep;		/* [n] continuous variables */
	SCIP_VAR*	var_rss;		/* continuous variable, residual sum of squares */
	SCIP_VAR*	var_log;		/* continuous variable, log(rss) */

	/* set solution */ 
	SCIP_Real *ep;
	
	int	nsols;
	int	store;
	SCIP_SOL**	sols;
	SCIP_Real	objval;

	SCIP_SOL*	sol;
	SCIP_Real*	solvals;
	SCIP_Bool	success;
	int			nvars	=	SCIPgetNVars(scip);
	SCIP_VAR**	vars;

	int 	i,j,t,ct;
	int	memo;

   assert(heur != NULL);
   assert(scip != NULL);
   assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
   assert(result != NULL);

#if MYPARA_LOG
	printf("forward selection!\n");
#endif

   /* get heuristic data */
	/*
   SCIP_HEURDATA* heurdata;
   heurdata = SCIPheurGetData(heur);
   assert(heurdata != NULL);
   assert(lastsolindices != NULL);
	*/

	/* get values from probdata */
   probdata = SCIPgetProbData(scip);
   assert(probdata != NULL);

	n	=	SCIPprobdataGetNdatas(probdata);
	p	=	SCIPprobdataGetNexvars(probdata);
	ndep	=	SCIPprobdataGetNdep(probdata);

	y	=	SCIPprobdataGety(probdata);
	orig_X_	=	SCIPprobdataGetX(probdata);
	orig_Q_	=	SCIPprobdataGetQ(probdata);
	orig_q	=	SCIPprobdataGetq(probdata);
	r	=	SCIPprobdataGetr(probdata);

	if( ndep ){
		Mdep		=	SCIPprobdataGetMdep(probdata);
		groupX	=	SCIPprobdataGetgroupX(probdata);
	}else{
		Mdep		=	NULL;
		groupX	=	NULL;
	}

	/* variables */
	var_a		=	SCIPprobdataGetVars_a(probdata);
	var_z		=	SCIPprobdataGetVars_z(probdata);
	var_ep	=	SCIPprobdataGetVars_ep(probdata);
	var_rss	=	SCIPprobdataGetVar_rss(probdata);
	var_log	=	SCIPprobdataGetVar_log(probdata);

	/* get branching info */
	/* alloc */
	SCIP_CALL( SCIPallocBufferArray(scip, &Branchz, 3*p));
	
	GenerateZeroVecInt( 3*p, Branchz);

	for(i=0; i<p; ++i){
		ublb					=	SCIPround(scip, SCIPcomputeVarUbLocal(scip, var_z[i]) 
								+	SCIPcomputeVarLbLocal(scip, var_z[i]));
		*(Branchz+(ublb*p)+i) 	= 	1;
	}

#if MYPARA_LOG
	for(i=0; i<3; i++){
		for(j=0; j<p; j++){
			printf("%d, ", *(Branchz+(i*p)+j));
		}
		newline();
	}
#endif

	if( ndep ){
		for(i=0; i<ndep; i++){
			memo = -1; 
			for(j=0; j<p; j++){
				if( *(groupX+(i*p)+j)==1 ){
					if( *(Branchz+j)==1 ) break;
					if( *(Branchz+p+j)==1 ) memo=j;
					if( j==Mdep[i] ){
						if( memo==-1 ){
							printf("error in heur_backward.c\n");
							stop();
						}
						*(Branchz+p+memo) = 0;
						*(Branchz+memo) = 1;
						break;
					}
				}
			}
		}
	}
	
#if MYPARA_LOG
	printf("linear dependent\n");
	if( ndep ){
		for(i=0; i<3; i++){
			for(j=0; j<p; j++){
				printf("%d, ", *(Branchz+(i*p)+j));
			}
			newline();
		}
	}
#endif
	
	/* alloc */
	SCIP_CALL( SCIPallocBufferArray(scip, &X_, n*p));
	SCIP_CALL( SCIPallocBufferArray(scip, &Xy, p));
	SCIP_CALL( SCIPallocBufferArray(scip, &d, n));
	SCIP_CALL( SCIPallocBufferArray(scip, &list, p));
	
	/* initialize from Branchz */
#if MYPARA_LOG
	printf("initialization\n");
#endif

	GenerateZeroVecInt( p, list);

	dim = 0;
	memo = -1;
	AIC = 1e+06;
	SCIP_CALL( SCIPallocBufferArray(scip, &a_old, dim+1));

	for(i=0; i<p; i++){
		
		if( Branchz[i]==1 ){ /* if z_i is fixed to 0 */
			list[i] = -1;
		}else if( Branchz[p+i]==1 ){ /* if z_i is unfixed */
			list[i] = 0;
		}else if( Branchz[2*p+i]==1 ){ /* if z_i is fixed 1 */
			dim++;
			list[i] = dim;

			if( dim == 1 ){

				a_old[0] = orig_q[i] / mat_( orig_Q_, p, i, i);
				RSS = RSSvalue( 1, a_old, &orig_q[i], r);
				AIC = AICvalue( n, dim, RSS);

				/* update X_ and Xy */
				mydcopy_( &orig_X_[n * i], &X_[n * (dim-1)], n);
				Xy[dim-1] = orig_q[i];

				/* generate Y ( dim = 1 ) */
				SCIP_CALL( SCIPallocBufferArray( scip, &Y_, dim*dim));
				Y_[0] = 1 / mat_( orig_Q_, p, i, i);
		
			}else{
				/* alloc */
				SCIPfreeBufferArray(scip, &a_old);
				SCIP_CALL( SCIPallocBufferArray( scip, &a_old, dim));
				SCIP_CALL( SCIPallocBufferArray( scip, &b, dim-1));
				SCIP_CALL( SCIPallocBufferArray( scip, &c, dim-1));
				SCIP_CALL( SCIPallocBufferArray( scip, &v, dim-1));
				SCIP_CALL( SCIPallocBufferArray( scip, &V_, (dim-1)*(dim-1)));
				SCIP_CALL( SCIPallocBufferArray( scip, &Z_, (dim)*(dim)));
				
				/* 1. b <- X^t x_i */
				dgemv_t( X_, n, dim-1, &orig_X_[n * i], b);
				//printv( dim-1, b);

				/* 2. c <- Y b */
				dgemv_2( Y_, dim-1, dim-1, b, c);
				//printv( dim-1, c);

				/* 3. d <- - X c + x_i */
				dgemv_1( X_, n, dim-1, c, &orig_X_[n * i], -1.0, 1.0, d);
				//printv( n, d);

				/* 4. u <- 1/<x_i, d> */
				u = 1.0 / myddot_( &orig_X_[n * i], d, n);
				//prints(u);
				
				/* 5. v <- - u c */
				mydscal_( c, dim-1, -u, v);
				//printv( dim-1, v);

				/* 6. V <- Y + u c c^t */
				dger_1( Y_, c, c, dim-1, dim-1, u, V_);
				//printM_( V_, dim-1, dim-1);

				/* 7. Z */
				/* V */
				for(j=0; j<(dim-1); j++){
					for(t=0; t<(dim-1); t++){
						*(Z_ + j + (t*dim) ) = mat_( V_, dim-1, j, t);
					}
				}
				/* v */
				for(j=0; j<(dim-1); j++){
					*(Z_ + dim-1 + (j*dim) )  = v[j];
					*(Z_ + j + ((dim-1)*dim)) = v[j];
				}

				/* u */
				*(Z_ + dim-1 + ((dim-1)*dim)) = u;
				//printM_( Z_, dim, dim);

				/* 8. a_old <- Z (Xy) */
				Xy[dim-1] = orig_q[i];
				dgemv_2( Z_, dim, dim, Xy, a_old);
				//printv( dim, a_old);

				RSS = RSSvalue( dim, a_old, Xy, r);
				AIC = AICvalue( n, dim, RSS);

				/* copy */
				SCIPfreeBufferArray(scip, &Y_);
				SCIP_CALL( SCIPallocBufferArray(scip, &Y_, dim*dim));
				mydcopy_( Z_, Y_, dim*dim);
	
				/* update X_ and Xy */
				mydcopy_( &orig_X_[n * i], &X_[n * (dim-1)], n);
				Xy[dim-1] = orig_q[i];

				/* free */
				SCIPfreeBufferArray(scip, &b);
				SCIPfreeBufferArray(scip, &c);
				SCIPfreeBufferArray(scip, &v);
				SCIPfreeBufferArray(scip, &V_);
				SCIPfreeBufferArray(scip, &Z_);
			}

#if MYPARA_LOG
			printf("---> %dth variable, AIC:%f\n", i, AIC);
#endif

		}else{
			printf("error:heur_forward.c\n");
			stop();
		}
	}


	if( dim == 0 ){
#if MYPARA_LOG
		printf("[dim:0]\n");
#endif
		dim++;
		RSS = 1e+06;
		for(i=0; i<p; i++){
			if( list[i] == 0 ){
				a_old[0] = orig_q[i] / mat_( orig_Q_, p, i, i);
				RSS_new = RSSvalue( 1, a_old, &orig_q[i], r);
				if( RSS_new < RSS ){
					RSS = RSS_new;
					memo = i;
				}
#if MYPARA_LOG
			printf("%d: RSS = %f\n", i, RSS_new);
#endif
			}
		}
		
		if( memo < 0 || memo >= p ){
			printf("error in heur_forward.c\n");
			stop();
		}
	
		AIC = AICvalue( n, dim, RSS);
		list[memo] = dim;
		
		/* update X_ and Xy */
		mydcopy_( &orig_X_[n * memo], &X_[n * (dim-1)], n);
		Xy[dim-1] = orig_q[memo];
	
		/* generate Y ( dim = 1 ) */
		SCIP_CALL( SCIPallocBufferArray( scip, &Y_, dim*dim));
		Y_[0] = 1 / mat_( orig_Q_, p, memo, memo);
	
#if MYPARA_LOG
		printf("---> %dth variable, AIC:%f\n", memo, AIC);
#endif
	} /* if ( dim==0 ) */

	while(1){
		dim++;
		memo = -1;
		RSS = 1e+06;
#if MYPARA_LOG
		printf("(dim=%d) ", dim);
		Longline();
#endif

		/* alloc */
		SCIP_CALL( SCIPallocBufferArray( scip, &a_new, dim));
		SCIP_CALL( SCIPallocBufferArray( scip, &a, dim));
		SCIP_CALL( SCIPallocBufferArray( scip, &b, dim-1));
		SCIP_CALL( SCIPallocBufferArray( scip, &c, dim-1));
		SCIP_CALL( SCIPallocBufferArray( scip, &v, dim-1));
		SCIP_CALL( SCIPallocBufferArray( scip, &V_, (dim-1)*(dim-1)));
		SCIP_CALL( SCIPallocBufferArray( scip, &Z_, (dim)*(dim)));
		SCIP_CALL( SCIPallocBufferArray( scip, &W_, (dim)*(dim)));
		
		for(i=0; i<p; i++){
			/*
			 * 1. b <- X^t x_i
			 * 2.	c <- Y b
			 * 3. d <- - X c + x_i
			 * 4. u <- 1 / <x_i, d> 
			 * 5. v <- - u c
			 * 6. V <- Y + u c c^t
			 * 7. Z <- ( V    v
			 	          v^t  u )
			 * 8. a_new <- Z (Xy)
			 */

			if( list[i]==0 ){

				/* 1. b <- X^t x_i */
				dgemv_t( X_, n, dim-1, &orig_X_[n * i], b);
				//printv( dim-1, b);

				/* 2. c <- Y b */
				dgemv_2( Y_, dim-1, dim-1, b, c);
				//printv( dim-1, c);

				/* 3. d <- - X c + x_i */
				dgemv_1( X_, n, dim-1, c, &orig_X_[n * i], -1.0, 1.0, d);
				//printv( n, d);

				/* 4. u <- 1/<x_i, d> */
				u = 1.0 / myddot_( &orig_X_[n * i], d, n);
				//prints(u);
				
				/* 5. v <- - u c */
				mydscal_( c, dim-1, -u, v);
				//printv( dim-1, v);

				/* 6. V <- Y + u c c^t */
				dger_1( Y_, c, c, dim-1, dim-1, u, V_);
				//printM_( V_, dim-1, dim-1);

				/* 7. Z */
				/* V */
				for(j=0; j<(dim-1); j++){
					for(t=0; t<(dim-1); t++){
						*(Z_ + j + (t*dim) ) = mat_( V_, dim-1, j, t);
					}
				}
				/* v */
				for(j=0; j<(dim-1); j++){
					*(Z_ + dim-1 + (j*dim) )  = v[j];
					*(Z_ + j + ((dim-1)*dim)) = v[j];
				}

				/* u */
				*(Z_ + dim-1 + ((dim-1)*dim)) = u;
				//printM_( Z_, dim, dim);

				/* 8. a_new <- Z (Xy) */
				Xy[dim-1] = orig_q[i];
				dgemv_2( Z_, dim, dim, Xy, a_new);
				//printv( dim, a_new);

				/* test */
				RSS_new = RSSvalue( dim, a_new, Xy, r);
				if( RSS_new < RSS ){
					RSS = RSS_new;
					memo = i;
					mydcopy_( Z_, W_, dim*dim);
					mydcopy_( a_new, a, dim);
				}

#if MYPARA_LOG
				printf("%d: RSS = %f\n", i, RSS_new);
#endif

			}
		}

		if( memo < 0 || memo >= p ){
			if( memo == -1 ){
				for(i=0; i<p; i++){
					if( list[i] == 0 ){
						memo = i;
						break;
					}
				}
				if( memo != -1 ){
					printf("error in heur_forward.c\n");
					stop();
				}
			}else{
				printf("error in heur_forward.c\n");
				stop();
			}
		}

		AIC_new = AICvalue( n, dim, RSS);
		if( AIC_new < AIC ){
			AIC = AIC_new;
			list[memo] = dim;

#if MYPARA_LOG
			printf("---> %dth variable, AIC:%f\n", memo, AIC);
#endif

			/* copy and free */
			SCIPfreeBufferArray(scip, &Y_);
			SCIP_CALL( SCIPallocBufferArray(scip, &Y_, dim*dim));
			mydcopy_( W_, Y_, dim*dim);

			SCIPfreeBufferArray(scip, &a_old);
			SCIP_CALL( SCIPallocBufferArray(scip, &a_old, dim));
			mydcopy_( a, a_old, dim);

			/* update X_ and Xy */
			mydcopy_( &orig_X_[n * memo], &X_[n * (dim-1)], n);
			Xy[dim-1] = orig_q[memo];

		}else{
			memo = -1;
			SCIPfreeBufferArray(scip, Y_);
#if MYPARA_LOG
			printf("--> no selection, (AIC:%f)\n", AIC_new);
#endif
		}

		/* free */
		SCIPfreeBufferArray(scip, &a_new);
		SCIPfreeBufferArray(scip, &a);
		SCIPfreeBufferArray(scip, &b);
		SCIPfreeBufferArray(scip, &c);
		SCIPfreeBufferArray(scip, &v);
		SCIPfreeBufferArray(scip, &V_);
		SCIPfreeBufferArray(scip, &Z_);
		SCIPfreeBufferArray(scip, &W_);

		if( memo == -1 ){
			dim--;
			break;
		}
	}

	nsols = SCIPgetNSols(scip);
	
	if( nsols < MP_NUM_SOL ){
		store = 1;
	}else{
		sols = SCIPgetSols(scip);
		objval = AIC;
		nsols = MP_NUM_SOL;

		if( objval < SCIPgetSolOrigObj(scip,sols[nsols-1]) ){
			store = 1;
		}else{
			store = 0;
		}
	}

	if( store ){
		/*  generate solution  */
		/* alloc */
		SCIP_CALL( SCIPallocBufferArray(scip, &ep, n));
		dgemv_1( X_, n, dim, a_old, y, -1.0, 1.0, ep);
		
	
		/* set solution */
		/* alloc */
		SCIP_CALL( SCIPallocBufferArray(scip, &solvals, nvars));
		SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars));
	
		ct=0;
		
		/* a */
		for(i=0; i<p; ++i){
			vars[ct] = var_a[i];
			if( list[i] > 0 ){
				solvals[ct] = a_old[list[i]-1];
			}else{
				solvals[ct] = 0.0;
			}
			ct++;
		}
	
		/* z */
		for(i=0; i<p; i++){
			vars[ct] = var_z[i];
			if( list[i] > 0 ){
				solvals[ct] = 1.0;
			}else{
				solvals[ct] = 0.0;
			}
			ct++;
		}
	
		/* ep */
		for(i=0; i<n; ++i){
			vars[ct]		=	var_ep[i];
			solvals[ct]	=	ep[i];
			ct++;
		}
	
		vars[ct]		=	var_rss;
		solvals[ct] =	myddot_( ep, ep, n);
		ct++;
	
		vars[ct]		=	var_log;
		solvals[ct]	=	log(myddot_( ep, ep, n));
		ct++;
	
		if( ct!=nvars ){
			SCIPerrorMessage("It is unexpected error in set sol,");
			printf("( ct, nvars) = ( %d, %d)", ct, nvars);
			stop();
		}
	
		SCIP_CALL( SCIPcreateSol(scip, &sol, heur));
		SCIP_CALL( SCIPsetSolVals(scip, sol, nvars, vars, solvals));
		SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, FALSE, TRUE, TRUE, &success));

		/* free */
		SCIPfreeBufferArray(scip, &ep);
		SCIPfreeBufferArray(scip, &solvals);
		SCIPfreeBufferArray(scip, &vars);
	}

	/* free */
	SCIPfreeBufferArray(scip, &d);
	SCIPfreeBufferArray(scip, &X_);
	SCIPfreeBufferArray(scip, &Xy);
	SCIPfreeBufferArray(scip, &a_old);
	SCIPfreeBufferArray(scip, &list);
	SCIPfreeBufferArray(scip, &Branchz);

	*result = SCIP_FOUNDSOL;
   return SCIP_OKAY;
}
예제 #3
0
/** compares the so far best branching candidate with a new candidate and updates best candidate, if new candidate is better */
static
void updateBestCandidate(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_VAR**            bestvar,            /**< best branching candidate */
   SCIP_Real*            bestscore,          /**< score of best branching candidate */
   SCIP_Real*            bestobj,            /**< absolute objective value of best branching candidate */
   SCIP_Real*            bestsol,            /**< proposed branching point of best branching candidate */
   SCIP_VAR*             cand,               /**< branching candidate to consider */
   SCIP_Real             candscore,          /**< scoring of branching candidate */
   SCIP_Real             candsol             /**< proposed branching point of branching candidate */
   )
{
   SCIP_Real obj;

   assert(scip != NULL);
   assert(bestvar != NULL);
   assert(bestscore != NULL);
   assert(bestobj != NULL);
   assert(*bestobj >= 0.0);
   assert(cand != NULL);

   /* a branching variable candidate should either be an active problem variable or a multi-aggregated variable */
   assert(SCIPvarIsActive(SCIPvarGetProbvar(cand)) ||
      SCIPvarGetStatus(SCIPvarGetProbvar(cand)) == SCIP_VARSTATUS_MULTAGGR);

   if( SCIPvarGetStatus(SCIPvarGetProbvar(cand)) == SCIP_VARSTATUS_MULTAGGR )
   {
      /* for a multi-aggregated variable, we call updateBestCandidate function recursively with all variables in the multi-aggregation */
      SCIP_VAR** multvars;
      int nmultvars;
      int i;
      SCIP_Bool success;
      SCIP_Real multvarlb;
      SCIP_Real multvarub;

      cand = SCIPvarGetProbvar(cand);
      multvars = SCIPvarGetMultaggrVars(cand);
      nmultvars = SCIPvarGetMultaggrNVars(cand);

      /* if we have a candidate branching point, then first register only aggregation variables
       * for which we can compute a corresponding branching point too (see also comments below)
       * if this fails, then register all (unfixed) aggregation variables, thereby forgetting about candsol
       */
      success = FALSE;
      if( candsol != SCIP_INVALID ) /*lint !e777*/
      {
         SCIP_Real* multscalars;
         SCIP_Real minact;
         SCIP_Real maxact;
         SCIP_Real aggrvarsol;
         SCIP_Real aggrvarsol1;
         SCIP_Real aggrvarsol2;

         multscalars = SCIPvarGetMultaggrScalars(cand);

         /* for computing the branching point, we need the current bounds of the multi-aggregated variable */
         minact = SCIPcomputeVarLbLocal(scip, cand);
         maxact = SCIPcomputeVarUbLocal(scip, cand);

         for( i = 0; i < nmultvars; ++i )
         {
            /* skip fixed variables */
            multvarlb = SCIPcomputeVarLbLocal(scip, multvars[i]);
            multvarub = SCIPcomputeVarUbLocal(scip, multvars[i]);
            if( SCIPisEQ(scip, multvarlb, multvarub) )
               continue;

            assert(multscalars != NULL);
            assert(multscalars[i] != 0.0);

            /* we cannot ensure that both the upper bound in the left node and the lower bound in the right node
             * will be candsol by a clever choice for the branching point of multvars[i],
             * but we can try to ensure that at least one of them will be at candsol
             */
            if( multscalars[i] > 0.0 )
            {
               /*    cand >= candsol
                * if multvars[i] >= (candsol - (maxact - multscalars[i] * ub(multvars[i]))) / multscalars[i]
                *                 = (candsol - maxact) / multscalars[i] + ub(multvars[i])
                */
               aggrvarsol1 = (candsol - maxact) / multscalars[i] + multvarub;

               /*     cand <= candsol
                * if multvars[i] <= (candsol - (minact - multscalar[i] * lb(multvars[i]))) / multscalars[i]
                *                 = (candsol - minact) / multscalars[i] + lb(multvars[i])
                */
               aggrvarsol2 = (candsol - minact) / multscalars[i] + multvarlb;
            }
            else
            {
               /*    cand >= candsol
                * if multvars[i] <= (candsol - (maxact - multscalars[i] * lb(multvars[i]))) / multscalars[i]
                *                 = (candsol - maxact) / multscalars[i] + lb(multvars[i])
                */
               aggrvarsol2 = (candsol - maxact) / multscalars[i] + multvarlb;

               /*    cand <= candsol
                * if multvars[i] >= (candsol - (minact - multscalar[i] * ub(multvars[i]))) / multscalars[i]
                *                 = (candsol - minact) / multscalars[i] + ub(multvars[i])
                */
               aggrvarsol1 = (candsol - minact) / multscalars[i] + multvarub;
            }

            /* by the above choice, aggrvarsol1 <= ub(multvars[i]) and aggrvarsol2 >= lb(multvars[i])
             * if aggrvarsol1 <= lb(multvars[i]) or aggrvarsol2 >= ub(multvars[i]), then choose the other one
             * if both are out of bounds, then give up
             * if both are inside bounds, then choose the one closer to 0.0 (someone has better idea???)
             */
            if( SCIPisFeasLE(scip, aggrvarsol1, multvarlb) )
            {
               if( SCIPisFeasGE(scip, aggrvarsol2, multvarub) )
                  continue;
               else
                  aggrvarsol = aggrvarsol2;
            }
            else
            {
               if( SCIPisFeasGE(scip, aggrvarsol2, multvarub) )
                  aggrvarsol = aggrvarsol1;
               else
                  aggrvarsol = REALABS(aggrvarsol1) < REALABS(aggrvarsol2) ? aggrvarsol1 : aggrvarsol2;
            }
            success = TRUE;

            updateBestCandidate(scip, bestvar, bestscore, bestobj, bestsol,
                  multvars[i], candscore, aggrvarsol);
         }
      }

      if( !success )
         for( i = 0; i < nmultvars; ++i )
         {
            /* skip fixed variables */
            multvarlb = SCIPcomputeVarLbLocal(scip, multvars[i]);
            multvarub = SCIPcomputeVarUbLocal(scip, multvars[i]);
            if( SCIPisEQ(scip, multvarlb, multvarub) )
               continue;

            updateBestCandidate(scip, bestvar, bestscore, bestobj, bestsol,
               multvars[i], candscore, SCIP_INVALID);
         }

      assert(*bestvar != NULL); /* if all variables were fixed, something is strange */

      return;
   }

   candscore *= SCIPvarGetBranchFactor(cand);
   obj = SCIPvarGetObj(cand);
   obj = REALABS(obj);
   if( SCIPisInfinity(scip, *bestscore)
      || (!SCIPisInfinity(scip, candscore) && 
          (SCIPisLT(scip, candscore, *bestscore) || (SCIPisLE(scip, candscore, *bestscore) && obj > *bestobj))) )
   {
      *bestvar = cand;
      *bestscore = candscore;
      *bestobj = obj;
      *bestsol = candsol;
   }
}
예제 #4
0
static
SCIP_DECL_BRANCHEXECPS(branchExecpsMyfullstrong)
{  /*lint --e{715}*/

	SCIP_PROBDATA*	probdata;
   SCIP_VAR**	cands;
   int	ncands;
	SCIP_NODE*	childnode_0;		/* z_j = 0 */
	SCIP_NODE*	childnode_1;		/* z_j = 1 */

	/* probdata */
	int	p;
	int	ndep;
	SCIP_VAR**	var_z;		/* [p] 01 variables */

	/* "_" means the matrix for blas */
	SCIP_Real*	orig_Q_;		/* [p*p] <- (X^t) X */
	SCIP_Real*	orig_q;		/* [p]   <- (X^t) y */
	SCIP_Real	r;

	int*	Mdep;					/* [ndep] */
	int*	groupX;				/* [ndep*p] */

	int	dim;
	SCIP_Real	RSS;			/* residual sum of square */
	SCIP_Real	RSS_new;
	SCIP_Real*	a;				/* [dim] */

	int	ublb;
	int	*Branchz;			/* [3*p] */
	int	*Branchz_new;		/* [3*p] */

	SCIP_Real*	Q_;	/* sub matrix of orig_Q_ */
	SCIP_Real*	Xy;	/* sub vector of orig_q */ 

	int*	list;			/* list of candidate variables */

	int	i,j,t,memo,ct;
	int	ind;
	int	dpv;

#if MYPARA_LOG
	printf("[myfullstrong brnaching]");
	Longline();
#endif

   /* get branching rule data */
	/*
   SCIP_BRANCHRULEDATA* branchruledata;
   branchruledata = SCIPbranchruleGetData(branchrule);
   assert(branchruledata != NULL);
	*/
	
	/* get problem data*/
	probdata = SCIPgetProbData(scip);
   assert(probdata != NULL);

	p	=	SCIPprobdataGetNexvars(probdata);
	ndep	=	SCIPprobdataGetNdep(probdata);

	orig_Q_	=	SCIPprobdataGetQ(probdata);
	orig_q	=	SCIPprobdataGetq(probdata);
	r	=	SCIPprobdataGetr(probdata);
	var_z		=	SCIPprobdataGetVars_z(probdata);

	if( ndep ){
		Mdep		=	SCIPprobdataGetMdep(probdata);
		groupX	=	SCIPprobdataGetgroupX(probdata);
	}else{
		Mdep		=	NULL;
		groupX	=	NULL;
	}

	/* alloc */
	SCIP_CALL( SCIPallocBufferArray(scip, &list, p));
	SCIP_CALL( SCIPallocBufferArray(scip, &Branchz, 3*p));
	SCIP_CALL( SCIPallocBufferArray(scip, &Branchz_new, 3*p));

	
	GenerateZeroVecInt( p, list);
	GenerateZeroVecInt( 3*p, Branchz);

   /* get pseudo candidates (non-fixed integer variables) */
   SCIP_CALL( SCIPgetPseudoBranchCands(scip, &cands, NULL, &ncands) );
	
	for(i=0; i<ncands; i++){
		for(j=0; j<p; j++){
			if( cands[i]==var_z[j] ){
				list[j] = 1;
				break;	
			}
		}
	}

#if MYPARA_LOG
	printf("list:");
	printintv( p, list);
#endif

	/* get branching info */
	for(i=0; i<p; ++i){
		ublb					=	SCIPround(scip, SCIPcomputeVarUbLocal(scip, var_z[i]) 
								+	SCIPcomputeVarLbLocal(scip, var_z[i]));
		*(Branchz+(ublb*p)+i) 	= 	1;
	}

#if MYPARA_LOG
	for(i=0; i<3; i++){
		for(j=0; j<p; j++){
			printf("%d, ", *(Branchz+(i*p)+j));
		}
		newline();
	}
#endif
	
	RSS = -1.0;
	ind = -1;

	for(i=0; i<p; i++){

		/* copy */
		for(j=0; j<(3*p); j++){
			Branchz_new[j] = Branchz[j];
		}

		/* 
		 * solve 
		 *   Q a = Xy
		 */

		if( list[i] == 1 ){

			Branchz_new[i] = 1;
			Branchz_new[p+i] = 0;
			
			if( ndep ){
				for(t=0; t<ndep; t++){
					memo = -1; 
					for(j=0; j<p; j++){
						if( *(groupX+(t*p)+j)==1 ){
							if( Branchz_new[j]==1 ) break;
							if( Branchz_new[p+j]==1 ) memo=j;
							if( j==Mdep[t] ){
								if( memo==-1 ){
									printf("error in branch_myfullstrong.c\n");
									stop();
								}
								*(Branchz_new+p+memo) = 0;
								*(Branchz_new+memo) = 1;
								break;
							}
						}
					}
				}
			}

			dim = p - sumint( &Branchz_new[0], p);
	
			/* alloc */
			SCIP_CALL( SCIPallocBufferArray( scip, &a, dim));
			SCIP_CALL( SCIPallocBufferArray( scip, &Q_, dim*dim));
			SCIP_CALL( SCIPallocBufferArray( scip, &Xy, dim));

			/* generate Q and Xy */
			/* Q */
			ct = 0;
			for(j=0; j<p; j++){
				if( (Branchz_new[j]==0) && (j != i) ){
					for(t=0; t<p; t++){
						if( (Branchz_new[t]==0) && (t != i ) ){
							Q_[ct++] = mat_( orig_Q_, p, j, t);
						}
					}
				}
			}

			if( ct != (dim*dim) ){
				printf("error in branch_myfullstrong.c\n");
				stop();
			}

			/* Xy */
			ct = 0;
			for(j=0; j<p; j++){
				if( (Branchz_new[j]==0) && (j != i) ){
					Xy[ct++] = orig_q[j];
				}
			}

			if( ct != dim ){
				printf("error in branch_myfullstrong.c\n");
				stop();
			}

			dpv = _dposv_( Q_, Xy, dim, a);

			if( dpv == 0 ){
				/* test */
				RSS_new = RSSvalue( dim, a, Xy, r);
				if( RSS_new > RSS ){
					RSS = RSS_new;
					ind = i;
				}
#if MYPARA_LOG
				printf("%d: RSS = %f\n", i, RSS_new);
#endif
			}

			/* free */
			SCIPfreeBufferArray(scip, &Q_);
			SCIPfreeBufferArray(scip, &Xy);
			SCIPfreeBufferArray(scip, &a);

		 }
	}

#if MYPARA_LOG
	printf("max->%dth var. \n", ind);
#endif

	if( ind == -1 ){
		/* free */
		SCIPfreeBufferArray(scip, &list);
		SCIPfreeBufferArray(scip, &Branchz);
		SCIPfreeBufferArray(scip, &Branchz_new);

   	*result = SCIP_DIDNOTRUN;
		return SCIP_OKAY;
	}

	SCIP_CALL( SCIPbranchVar( scip, var_z[ind], &childnode_0, NULL, &childnode_1));

	/* free */
	SCIPfreeBufferArray(scip, &list);
	SCIPfreeBufferArray(scip, &Branchz);
	SCIPfreeBufferArray(scip, &Branchz_new);

   *result = SCIP_BRANCHED;

   return SCIP_OKAY;
}