/** 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; }
/** 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; }
/** 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; } }
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; }