DSP_RTN_CODE BlkModel::updateBlocks() {
#define FREE_MEMORY \
	FREE_ARRAY_PTR(ncols_coupled);

	int* ncols_coupled = NULL;

	BGN_TRY_CATCH

	std::vector<int> blockids;
	for (Blocks::iterator it = blocks_.begin(); it != blocks_.end(); ++it)
		blockids.push_back(it->first);

	double stime = CoinGetTimeOfDay();
	/** number of blocks */
	if (blockids.size() > 0) {
		/** coupling columns and rows */
		std::vector<int> master_coupling_cols;

		/** retrieve master information */
		DetBlock* master = block(blockids[0]);
		if (master == NULL)
			return DSP_RTN_ERR;
		const CoinPackedMatrix* master_mat = master->getConstraintMatrix();

		/** get number of columns, rows and integers */
		ncols_full_ = master->getNumCols();
		nrows_full_ = master->getNumRows();
		nints_full_ = master->getNumIntegers();

		/** to count how many subproblems are coupled with each column of the master. */
		ncols_coupled = new int [master->getNumCols()];
		CoinZeroN(ncols_coupled, master->getNumCols());

		for (unsigned i = 1; i < blockids.size(); ++i) {
			/** coupling columns and rows */
			std::vector<int> sub_coupling_cols;
			std::vector<int> sub_coupling_rows;

			/** retrieve subproblem */
			int id = blockids[i];
			DetBlock* sub = block(id);
			if (sub == NULL)
				return DSP_RTN_ERR;

			/** mark it is a dual block angular matrix */
			if (sub->getNumCols() > master->getNumCols())
				dual_block_angular_ = true;

			/** retrieve subproblem column indices */
			const CoinPackedMatrix* sub_mat = sub->getConstraintMatrix();
			int sub_num_col_indices = sub_mat->isColOrdered() ?
					sub_mat->getNumCols() : sub_mat->getNumElements();
			int* sub_col_indices = new int [sub_num_col_indices];
			if (sub_mat->isColOrdered())
				CoinCopyN(sub_mat->getVectorStarts(), sub_num_col_indices, sub_col_indices);
			else
				CoinCopyN(sub_mat->getIndices(), sub_num_col_indices, sub_col_indices);

			/** add number of columns, rows and integers */
			ncols_full_ += sub->getNumCols() - master->getNumCols();
			nrows_full_ += sub->getNumRows() - master->getNumRows();
			nints_full_ += sub->getNumIntegers() - master->getNumIntegers();

			/** sort indices to speed up the search */
			std::sort(sub_col_indices, sub_col_indices + sub_num_col_indices);

			/** find coupling columns and rows */
			for (int j = 0; j < sub_num_col_indices; ++j) {
				if (j > 0 && sub_col_indices[j-1] == sub_col_indices[j])
					continue;
				if (sub_col_indices[j] < master_mat->getNumCols()) {
					master_coupling_cols.push_back(sub_col_indices[j]);
					sub_coupling_cols.push_back(sub_col_indices[j]);
					/** find all the coupling rows */
					for (int row = 0; row < master->getNumRows(); ++row) {
						if (fabs(master_mat->getCoefficient(row, sub_col_indices[j])) > 1.0e-8)
							sub_coupling_rows.push_back(row);
					}
				}
			}

			/** erase duplicates */
			std::sort(sub_coupling_cols.begin(), sub_coupling_cols.end());
			sub_coupling_cols.erase(
					std::unique(sub_coupling_cols.begin(), sub_coupling_cols.end()),
					sub_coupling_cols.end());
			std::sort(sub_coupling_rows.begin(), sub_coupling_rows.end());
			sub_coupling_rows.erase(
					std::unique(sub_coupling_rows.begin(), sub_coupling_rows.end()),
					sub_coupling_rows.end());

			/** set coupling columns and rows */
			sub->setCouplingCols(sub_coupling_cols.size(), &sub_coupling_cols[0]);
			sub->setCouplingRows(sub_coupling_rows.size(), &sub_coupling_rows[0]);
			DSPdebugMessage("Coupling columns of block %d:\n", id);
			DSPdebug(DspMessage::printArray(sub->getNumCouplingCols(), sub->getCouplingCols()));
			DSPdebugMessage("Coupling rows of block %d:\n", id);
			DSPdebug(DspMessage::printArray(sub->getNumCouplingRows(), sub->getCouplingRows()));

			/** count the master columns coupled */
			for (unsigned j = 0; j < sub_coupling_cols.size(); ++j)
				ncols_coupled[sub_coupling_cols[j]]++;
		}

		/** erase duplicates */
		std::sort(master_coupling_cols.begin(), master_coupling_cols.end());
		master_coupling_cols.erase(
				std::unique(master_coupling_cols.begin(), master_coupling_cols.end()),
				master_coupling_cols.end());

		/** set coupling columns */
		master->setCouplingCols(master_coupling_cols.size(), &master_coupling_cols[0]);
		/** set coupling rows */
		int* master_coupling_rows = new int [master->getNumRows()];
		for (int i = 0; i < master->getNumRows(); ++i)
			master_coupling_rows[i] = i;
		master->setCouplingRows(master->getNumRows(), master_coupling_rows);
		FREE_ARRAY_PTR(master_coupling_rows);
#if 0
		/** check if the full matrix is of a primal block angular form. */
		primal_block_angular_ = true;
		for (int j = 0; j < master->getNumCols(); ++j)
			if (ncols_coupled[j] > 1)
				primal_block_angular_ = false;

		if (primal_block_angular_ == true)
			printf("The constraint matrix is of a primal block angular.\n");
		if (dual_block_angular_ == true)
			printf("The constraint matrix is of a dual block angular.\n");
#endif
	}
	DSPdebugMessage("Update block time: %.4f\n", CoinGetTimeOfDay() - stime);

	END_TRY_CATCH_RTN(FREE_MEMORY,DSP_RTN_ERR)

	FREE_MEMORY

	return DSP_RTN_OK;
#undef FREE_MEMORY
}
DSP_RTN_CODE DdMWSync::init()
{
	BGN_TRY_CATCH

	/** This should be before DdMwPara::init(); */
	sync_ = true;

	/** initialize MPI communication settings */
	DdMWPara::init();

	if (comm_rank_ == 0)
	{
		/** create master */
		switch (par_->getIntParam("DD/MASTER_ALGO"))
		{
		case Simplex:
		case IPM:
		case IPM_Feasible:
			master_ = new DdMasterTr(par_, model_, message_);
			break;
#ifndef NO_OOQP
		case DSBM:
			master_ = new DdMasterDsb(par_, model_, message_);
			break;
#endif
		case Subgradient:
			master_ = new DdMasterSubgrad(par_, model_, message_);
			break;
		}
		/** initialize master */
		master_->init();
	}
	else
	{
		/** clear time log */
		time_lb_.clear();

		/** create workers */
		if (lb_comm_rank_ >= 0)
		{
			/** create LB worker */
			DSPdebugMessage("Rank %d creates a worker for lower bounds.\n", comm_rank_);
			worker_.push_back(new DdWorkerLB(par_, model_, message_));
			/** create CG worker */
			if (parFeasCuts_ >= 0 || parOptCuts_ >= 0)
			{
#ifndef NO_SCIP
				DSPdebugMessage("Rank %d creates a worker for Benders cut generation.\n", comm_rank_);
				worker_.push_back(new DdWorkerCGBd(par_, model_, message_));
#endif
			}
			/** create UB worker */
			if (parEvalUb_ >= 0)
			{
				DSPdebugMessage("Rank %d creates a worker for upper bounds.\n", comm_rank_);
				worker_.push_back(new DdWorkerUB(par_, model_, message_));
			}
		}
		/** initialize workers */
		for (unsigned i = 0; i < worker_.size(); ++i)
			worker_[i]->init();
	}

        /** reset iteration info */
        itercnt_   = 0;
        iterstime_ = CoinGetTimeOfDay();

	END_TRY_CATCH_RTN(;,DSP_RTN_ERR)
Beispiel #3
0
SCIP_RETCODE SCIPconshdlrBenders::sepaBenders(
		SCIP * scip,
		SCIP_CONSHDLR * conshdlr,
		SCIP_SOL * sol,
		whereFrom where,
		SCIP_RESULT * result)
{
	OsiCuts cs; /**< Benders cut placeholder */
	SCIP_Real * vals = NULL; /**< current solution */

#if 1
	if (scip_checkpriority_ < 0)
	{
		/** consider incumbent solutions only */
		double primObj = SCIPgetPrimalbound(scip);
		double currObj = SCIPgetSolOrigObj(scip, sol);
		if (SCIPisLT(scip, primObj, currObj))
		{
			DSPdebugMessage(" -> primObj %e currObj %e\n", primObj, currObj);
			return SCIP_OKAY;
		}
	}
#endif

	/** allocate memory */
	SCIP_CALL(SCIPallocMemoryArray(scip, &vals, nvars_));

	/** get current solution */
	SCIP_CALL(SCIPgetSolVals(scip, sol, nvars_, vars_, vals));

	/** TODO The following filter does not work, meaning that it provides suboptimal solution.
	 * I do not know the reason. */
#if 0
	double maxviol = 1.e-10;
	for (int j = 0; j < nvars_ - naux_; ++j)
	{
		SCIP_VARTYPE vartype = SCIPvarGetType(vars_[j]);
		if (vartype == SCIP_VARTYPE_CONTINUOUS) continue;

		double viol = 0.5 - fabs(vals[j] - floor(vals[j]) - 0.5);
		if (viol > maxviol)
			maxviol = viol;
	}
	DSPdebugMessage("maximum violation %e\n", maxviol);

	if (where != from_scip_check &&
		where != from_scip_enfolp &&
		where != from_scip_enfops &&
		maxviol > 1.e-7)
	{
		printf("where %d maxviol %e\n", where, maxviol);
		/** free memory */
		SCIPfreeMemoryArray(scip, &vals);
		return SCIP_OKAY;
	}
#endif

#ifdef DSP_DEBUG2
	double minvals = COIN_DBL_MAX;
	double maxvals = -COIN_DBL_MAX;
	double sumvals = 0.;
	double ssvals  = 0.;
	//printf("nvars_ %d naux_ %d nAuxvars_ %d\n", nvars_, naux_, tss_->nAuxvars_);
	for (int j = 0; j < nvars_ - naux_; ++j)
	{
//		if (vals[j] < 0 || vals[j] > 1)
//			printf("solution %d has value %e.\n", j, vals[j]);
		sumvals += vals[j];
		ssvals  += vals[j] * vals[j];
		minvals = minvals > vals[j] ? vals[j] : minvals;
		maxvals = maxvals < vals[j] ? vals[j] : maxvals;
	}
	DSPdebugMessage("solution: min %e max %e avg %e sum %e two-norm %e\n",
			minvals, maxvals, sumvals / nvars_, sumvals, sqrt(ssvals));
#endif

#define SCAN_GLOBAL_CUT_POOL
#ifdef SCAN_GLOBAL_CUT_POOL
	if (SCIPgetStage(scip) == SCIP_STAGE_SOLVING ||
		SCIPgetStage(scip) == SCIP_STAGE_SOLVED ||
		SCIPgetStage(scip) == SCIP_STAGE_EXITSOLVE)
	{
		bool addedPoolCut = false;
		int numPoolCuts = SCIPgetNPoolCuts(scip);
		int numCutsToScan = 100;
		SCIP_CUT ** poolcuts = SCIPgetPoolCuts(scip);
		for (int i = numPoolCuts - 1; i >= 0; --i)
		{
			if (i < 0) break;
			if (numCutsToScan == 0) break;

			/** retrieve row */
			SCIP_ROW * poolcutrow = SCIPcutGetRow(poolcuts[i]);

			/** benders? */
			if (strcmp(SCIProwGetName(poolcutrow), "benders") != 0)
				continue;

			/** counter */
			numCutsToScan--;

			if (SCIPgetCutEfficacy(scip, sol, poolcutrow) > 1.e-6)
			{
				if (where == from_scip_sepalp ||
					where == from_scip_sepasol ||
					where == from_scip_enfolp)
				{
					/** add cut */
					SCIP_Bool infeasible;
					SCIP_CALL(SCIPaddCut(scip, sol, poolcutrow,
							FALSE, /**< force cut */
							&infeasible));

					if (infeasible)
						*result = SCIP_CUTOFF;
					else //if (*result != SCIP_CUTOFF)
						*result = SCIP_SEPARATED;
				}
				else
					*result = SCIP_INFEASIBLE;
				addedPoolCut = true;
				break;
			}
		}
		if (addedPoolCut)
		{
			DSPdebugMessage("Added pool cut\n");
			/** free memory */
			SCIPfreeMemoryArray(scip, &vals);
			return SCIP_OKAY;
		}
	}
#endif

	/** generate Benders cuts */
	assert(tss_);
	tss_->generateCuts(nvars_, vals, &cs);

	/** If found Benders cuts */
	for (int i = 0; i < cs.sizeCuts(); ++i)
	{
		/** get cut pointer */
		OsiRowCut * rc = cs.rowCutPtr(i);
		if (!rc) continue;

		const CoinPackedVector cutrow = rc->row();
		if (cutrow.getNumElements() == 0) continue;

		/** is optimality cut? */
		bool isOptimalityCut = false;
		for (int j = nvars_ - naux_; j < nvars_; ++j)
		{
			if (cutrow.getMaxIndex() == j)
			{
				isOptimalityCut = true;
				break;
			}
		}

		double efficacy = rc->violated(vals) / cutrow.twoNorm();
		SCIP_Bool isEfficacious = efficacy > 1.e-6;

#define KK_TEST
#ifdef KK_TEST
		if (SCIPgetStage(scip) == SCIP_STAGE_INITSOLVE ||
			SCIPgetStage(scip) == SCIP_STAGE_SOLVING)
		{
			/** create empty row */
			SCIP_ROW * row = NULL;
			SCIP_CALL(SCIPcreateEmptyRowCons(scip, &row, conshdlr, "benders", rc->lb(), SCIPinfinity(scip),
					FALSE, /**< is row local? */
					FALSE, /**< is row modifiable? */
					FALSE  /**< is row removable? can this be TRUE? */));

			/** cache the row extension and only flush them if the cut gets added */
			SCIP_CALL(SCIPcacheRowExtensions(scip, row));

			/** collect all non-zero coefficients */
			for (int j = 0; j < cutrow.getNumElements(); ++j)
				SCIP_CALL(SCIPaddVarToRow(scip, row, vars_[cutrow.getIndices()[j]], cutrow.getElements()[j]));

			DSPdebugMessage("found Benders (%s) cut: act=%f, lhs=%f, norm=%f, eff=%f, min=%f, max=%f (range=%f)\n",
				isOptimalityCut ? "opti" : "feas",
				SCIPgetRowLPActivity(scip, row), SCIProwGetLhs(row), SCIProwGetNorm(row),
				SCIPgetCutEfficacy(scip, sol, row),
				SCIPgetRowMinCoef(scip, row), SCIPgetRowMaxCoef(scip, row),
				SCIPgetRowMaxCoef(scip, row)/SCIPgetRowMinCoef(scip, row));

			/** flush all changes before adding cut */
			SCIP_CALL(SCIPflushRowExtensions(scip, row));

			DSPdebugMessage("efficacy %e isEfficatious %d\n", efficacy, isEfficacious);

			if (isEfficacious)
			{
				if (where == from_scip_sepalp ||
					where == from_scip_sepasol ||
					where == from_scip_enfolp)
				{
					/** add cut */
					SCIP_Bool infeasible;
					SCIP_CALL(SCIPaddCut(scip, sol, row,
							FALSE, /**< force cut */
							&infeasible));

					if (infeasible)
						*result = SCIP_CUTOFF;
					else //if (*result != SCIP_CUTOFF)
						*result = SCIP_SEPARATED;
				}
				else
					*result = SCIP_INFEASIBLE;
			}

			/** add cut to global pool */
			SCIP_CALL(SCIPaddPoolCut(scip, row));
			DSPdebugMessage("number of cuts in global cut pool: %d\n", SCIPgetNPoolCuts(scip));

			/** release the row */
			SCIP_CALL(SCIPreleaseRow(scip, &row));
		}
		else if (isEfficacious &&
					where != from_scip_sepalp &&
					where != from_scip_sepasol &&
					where != from_scip_enfolp)
			*result = SCIP_INFEASIBLE;
#else
		if (where == from_scip_sepalp ||
			where == from_scip_sepasol ||
			where == from_scip_enfolp)
		{
			/** create empty row */
			SCIP_ROW * row = NULL;
			SCIP_CALL(SCIPcreateEmptyRowCons(scip, &row, conshdlr, "benders", rc->lb(), SCIPinfinity(scip),
					FALSE, /**< is row local? */
					FALSE, /**< is row modifiable? */
					FALSE  /**< is row removable? can this be TRUE? */));

			/** cache the row extension and only flush them if the cut gets added */
			SCIP_CALL(SCIPcacheRowExtensions(scip, row));

			/** collect all non-zero coefficients */
			for (int j = 0; j < cutrow.getNumElements(); ++j)
				SCIP_CALL(SCIPaddVarToRow(scip, row, vars_[cutrow.getIndices()[j]], cutrow.getElements()[j]));

			DSPdebugMessage("found Benders (%s) cut: act=%f, lhs=%f, norm=%f, eff=%f, min=%f, max=%f (range=%f)\n",
				isOptimalityCut ? "opti" : "feas",
				SCIPgetRowLPActivity(scip, row), SCIProwGetLhs(row), SCIProwGetNorm(row),
				SCIPgetCutEfficacy(scip, NULL, row),
				SCIPgetRowMinCoef(scip, row), SCIPgetRowMaxCoef(scip, row),
				SCIPgetRowMaxCoef(scip, row)/SCIPgetRowMinCoef(scip, row));

			/** flush all changes before adding cut */
			SCIP_CALL(SCIPflushRowExtensions(scip, row));

			/** is cut efficacious? */
			if (isOptimalityCut)
			{
				efficacy = SCIPgetCutEfficacy(scip, sol, row);
				isEfficacious = SCIPisCutEfficacious(scip, sol, row);
			}
			else
			{
				efficacy = rc->violated(vals);
				isEfficacious = efficacy > 1.e-6;
			}

			if (isEfficacious)
			{
				/** add cut */
				SCIP_Bool infeasible;
				SCIP_CALL(SCIPaddCut(scip, sol, row,
						FALSE, /**< force cut */
						&infeasible));

				if (infeasible)
					*result = SCIP_CUTOFF;
				else if (*result != SCIP_CUTOFF)
					*result = SCIP_SEPARATED;
			}

			/** add cut to global pool */
			SCIP_CALL(SCIPaddPoolCut(scip, row));

			/** release the row */
			SCIP_CALL(SCIPreleaseRow(scip, &row));
		}
		else
		{
			if (isOptimalityCut)
			{
				efficacy = rc->violated(vals) / cutrow.twoNorm();
				isEfficacious = efficacy > 0.05;
			}
			else
			{
				efficacy = rc->violated(vals);
				isEfficacious = efficacy > 1.e-6;
			}
			DSPdebugMessage("%s efficacy %e\n", isOptimalityCut ? "Opti" : "Feas", efficacy);

			if (isEfficacious == TRUE)
				*result = SCIP_INFEASIBLE;
		}
#endif
	}

	/** free memory */
	SCIPfreeMemoryArray(scip, &vals);

	return SCIP_OKAY;
}