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
}
Beispiel #2
0
/** solve */
STO_RTN_CODE TssBd::solve()
{
#define FREE_MEMORY    \
	FREE_PTR(tssbdsub)

	assert(model_);

	/** subproblems */
	const double * probability = NULL; /**< probability */
	TssBdSub *     tssbdsub    = NULL; /**< cut generator */
	double lowerbound = 0.0;

	BGN_TRY_CATCH

	/** solution time */
	double swtime = CoinGetTimeOfDay();

	/** time limit */
	time_remains_ = par_->wtimeLimit_;

	/** get number of scenarios */
	probability = model_->getProbability();

	/** configure Benders cut generator */
	/** This does NOT make deep copies. So, DO NOT RELEASE POINTERS. */
	tssbdsub = new TssBdSub(par_);
	for (int s = 0; s < model_->getNumScenarios(); ++s)
		tssbdsub->scenarios_.push_back(s);
	STO_RTN_CHECK_THROW(tssbdsub->loadProblem(model_, naugs_, augs_, naux_), "loadProblem", "TssBdSub");

	if (par_->logLevel_ > 0) printf("Phase 1:\n");

	/** solution time */
	double stime = clockType_ ? CoinGetTimeOfDay() : CoinCpuTime();

	/** find lower bound */
	/** TODO: replace this with TssDd */
	STO_RTN_CHECK_THROW(findLowerBound(probability, lowerbound), "findLowerBound", "TssBd");

	/** We should have a lower bound here. */
	if (par_->logLevel_ > 0) printf(" -> Found lower bound %e\n", lowerbound);

	/** construct master problem */
	STO_RTN_CHECK_THROW(constructMasterProblem(tssbdsub, lowerbound), "constructMasterProblem", "TssBd");

	if (par_->logLevel_ > 0) printf("Phase 2:\n");

	time_remains_ -= CoinGetTimeOfDay() - swtime;

	/** use L-shaped method to find lower bound */
	if (model_->getNumCoreIntegers() == 0)
	{
		/** configure LP */
		STO_RTN_CHECK_THROW(configureSLP(), "configureSLP", "TssBd");

		/** solve LP */
		STO_RTN_CHECK_THROW(solveSLP(tssbdsub), "solveSLP", "TssBd");
	}
	else
	{
		/** configure MILP */
		STO_RTN_CHECK_THROW(configureSMILP(tssbdsub), "configureSMILP", "TssBd");

		/** solve MILP */
		STO_RTN_CHECK_THROW(solveSMILP(), "solveSMILP", "TssBd");
	}

	/** solution time */
	solutionTime_ = (clockType_ ? CoinGetTimeOfDay() : CoinCpuTime()) - stime;

	/** collect solution */
	switch (status_)
	{
	case STO_STAT_OPTIMAL:
	case STO_STAT_LIM_ITERorTIME:
	case STO_STAT_STOPPED_GAP:
	case STO_STAT_STOPPED_NODE:
	case STO_STAT_STOPPED_TIME:
		{
			const double * solution = si_->getSolution();
			if (solution)
			{
				/** first-stage solution */
				assert(solution_);
				CoinCopyN(solution, model_->getNumCols(0), solution_);

				/** second-stage solution */
				double * objval_reco = new double [model_->getNumScenarios()];
				double ** solution_reco = new double * [model_->getNumScenarios()];
				for (int s = 0; s < model_->getNumScenarios(); ++s)
					solution_reco[s] = new double [model_->getNumCols(1)];

				for (int s = 0; s < naugs_; ++s)
					CoinCopyN(solution + model_->getNumCols(0) + s * model_->getNumCols(1),
							model_->getNumCols(1), solution_reco[augs_[s]]);

				/** collect solution */
				tssbdsub->solveRecourse(solution_, objval_reco, solution_reco, par_->numCores_);
				for (int s = 0; s < model_->getNumScenarios(); ++s)
				{
					if (tssbdsub->excludedScenarios_[s]) continue;
					CoinCopyN(solution_reco[s], model_->getNumCols(1),
							solution_ + model_->getNumCols(0) + model_->getNumCols(1) * s);

				}

				/** compute primal bound */
				primalBound_ = 0.0;
				for (int j = 0; j < model_->getNumCols(0); ++j)
					primalBound_ += model_->getObjCore(0)[j] * solution_[j];
				for (int s = 0; s < model_->getNumScenarios(); ++s)
				{
					primalBound_ += objval_reco[s] * model_->getProbability()[s];
				}
				//printf("primalBound %e\n", primalBound_);

				/** free memory */
				FREE_ARRAY_PTR(objval_reco);
				FREE_2D_ARRAY_PTR(model_->getNumScenarios(), solution_reco);
			}
			break;
		}
		break;
	default:
		printf("Solution status (%d).\n", status_);
		break;
	}

	END_TRY_CATCH_RTN(FREE_MEMORY,STO_RTN_ERR)

	/** free memory */
	FREE_MEMORY

	return STO_RTN_OK;

#undef FREE_MEMORY
}