diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml new file mode 100644 index 00000000..a8d8ef78 --- /dev/null +++ b/.github/workflows/build-test.yml @@ -0,0 +1,75 @@ +name: Build test + +on: [push, pull_request] + +jobs: + test-github-cpuonly: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, ubuntu-18.04] + compiler: [gcc, clang] + fail-fast: false + + steps: + - name: Install extra libraries + run: | + if [ ${{ matrix.os }} == ubuntu-18.04 ] && [ ${{ matrix.compiler }} == gcc ] + then + sudo apt-get update -y + sudo apt-get install -y lcov + fi + - name: Set my secrets + uses: webfactory/ssh-agent@v0.4.1 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + - name: Checkout DSP + uses: actions/checkout@v2 + with: + submodules: true + - name: Checkout DSPThirdPartyLibs + run: | + mkdir -p ~/.ssh + ssh-keyscan xgitlab.cels.anl.gov >> ~/.ssh/known_hosts + git clone git@xgitlab.cels.anl.gov:kimk/DSPThirdPartyLibs.git + - name: Run cmake, build, and test + env: + MYOS: ${{ matrix.os }} + CC: ${{ matrix.compiler }} + FC: gfortran-9 + run: | + cd DSPThirdPartyLibs + ./github.sh + if [ ${{ matrix.os }} == ubuntu-18.04 ] + then + export LD_LIBRARY_PATH=$PWD/lib:$(dirname `$FC --print-file-name libgfortran.so`):$LD_LIBRARY_PATH + echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> $GITHUB_ENV + fi + if [ ${{ matrix.os }} == macos-latest ] + then + export DYLD_LIBRARY_PATH=$PWD/lib:$(dirname `$FC --print-file-name libgfortran.dylib`):$DYLD_LIBRARY_PATH + echo "DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH" >> $GITHUB_ENV + fi + cd .. + mkdir build + cd build + if [ ${{ matrix.compiler }} == gcc ]; then export CXX=g++; fi + if [ ${{ matrix.compiler }} == clang ]; then export CXX=clang++; fi + cmake .. -DUNIT_TESTING=ON -DCODE_COVERAGE=ON -DCMAKE_BUILD_TYPE=DEBUG + make -j + make install + - name: Run test + run: | + if [ ${{ matrix.os }} == ubuntu-18.04 ]; then export LD_LIBRARY_PATH=${{ env.LD_LIBRARY_PATH }}; fi + if [ ${{ matrix.os }} == macos-latest ]; then export DYLD_LIBRARY_PATH=${{ env.DYLD_LIBRARY_PATH }}; fi + cd build + ./src/test/UnitTests + ctest + if [ ${{ matrix.os }} == ubuntu-18.04 ] && [ ${{ matrix.compiler }} == gcc ] + then + lcov --capture --directory . --output-file coverage.info + lcov --remove coverage.info '/usr/*' --output-file coverage.info + fi + - uses: codecov/codecov-action@v1 + with: + file: ./build/coverage.info diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d749d991..00000000 --- a/.travis.yml +++ /dev/null @@ -1,88 +0,0 @@ -language: cpp - -cache: ccache - -matrix: - include: - - os: linux - dist: bionic - compiler: clang - addons: - ssh_known_hosts: xgitlab.cels.anl.gov - apt: - packages: - - gfortran - - libblas-dev - - liblapack-dev - - libtbb-dev - - os: linux - dist: bionic - compiler: gcc - addons: - ssh_known_hosts: xgitlab.cels.anl.gov - apt: - packages: - - gfortran - - libblas-dev - - liblapack-dev - - libtbb-dev - - lcov - after_success: - # Create lcov report - - lcov --capture --directory . --output-file coverage.info - - lcov --remove coverage.info '/usr/*' --output-file coverage.info # filter system-files - - lcov --list coverage.info # debug info - # Uploading report to CodeCov - - bash <(curl -s https://codecov.io/bash) -f coverage.info || echo "Codecov did not collect coverage reports" - - os: osx - compiler: clang - addons: - ssh_known_hosts: xgitlab.cels.anl.gov - homebrew: - packages: - - git-lfs - - tbb - - ccache - update: true - - os: osx - compiler: gcc - addons: - ssh_known_hosts: xgitlab.cels.anl.gov - homebrew: - packages: - - git-lfs - - tbb - - ccache - update: true - -before_install: - # add environment variable for ccache on osx - - if [ $TRAVIS_OS_NAME == osx ]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi - - # print cache statistics - - ccache --show-stats - - # download and compile private dependencies - - openssl aes-256-cbc -K $encrypted_db2095f63ba3_key -iv $encrypted_db2095f63ba3_iv -in deploy_rsa.enc -out /tmp/deploy_rsa -d - - eval "$(ssh-agent -s)" - - chmod 600 /tmp/deploy_rsa - - ssh-add /tmp/deploy_rsa - - if [ $TRAVIS_OS_NAME == osx ]; then git lfs install; fi - - git clone git@xgitlab.cels.anl.gov:kimk/DSPThirdPartyLibs.git - - cd DSPThirdPartyLibs - - ./travis.sh - - if [ $TRAVIS_OS_NAME == linux ]; then export LD_LIBRARY_PATH=$PWD/lib:$(dirname `gfortran --print-file-name libgfortran.so`):$LD_LIBRARY_PATH; fi - - if [ $TRAVIS_OS_NAME == osx ]; then export DYLD_LIBRARY_PATH=$PWD/scip/build/lib:$(dirname `gfortran --print-file-name libgfortran.dylib`):$DYLD_LIBRARY_PATH; fi - - cd .. - - # print final cache statistics - - ccache --show-stats - -install: - - mkdir build && cd build && cmake .. -DUNIT_TESTING=ON -DCODE_COVERAGE=ON -DCMAKE_BUILD_TYPE=DEBUG - - make -j - - make install - -script: - - ctest - - ./src/test/UnitTests diff --git a/README.md b/README.md index 837cad8a..8683937d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Release: ![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/Argon Documentation: [![Documentation Status](https://readthedocs.org/projects/dsp/badge/?version=master)](https://dsp.readthedocs.io/?badge=master) -Status: [![Build Status](https://travis-ci.org/Argonne-National-Laboratory/DSP.svg?branch=master)](https://travis-ci.org/Argonne-National-Laboratory/DSP) +Status: ![Build Status](https://github.com/Argonne-National-Laboratory/DSP/workflows/Build%20test/badge.svg) [![codecov](https://codecov.io/gh/Argonne-National-Laboratory/DSP/branch/master/graph/badge.svg)](https://codecov.io/gh/Argonne-National-Laboratory/DSP) -------- diff --git a/deploy_rsa.enc b/deploy_rsa.enc deleted file mode 100644 index d5a05dee..00000000 Binary files a/deploy_rsa.enc and /dev/null differ diff --git a/llvm-gcov.sh b/llvm-gcov.sh deleted file mode 100644 index 1e5429bc..00000000 --- a/llvm-gcov.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -exec llvm-cov gcov "$@" \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d68a5c94..11dedcef 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,6 +42,7 @@ set(DSP_SRC Solver/DualDecomp/DdWorkerCG.cpp Solver/DualDecomp/DdWorkerLB.cpp Solver/DualDecomp/DdWorkerUB.cpp + Solver/DualDecomp/DdDroWorkerUB.cpp Solver/DantzigWolfe/DwBranchInt.cpp Solver/DantzigWolfe/DwBranchNonant.cpp Solver/DantzigWolfe/DwBranchNonant2.cpp @@ -160,6 +161,7 @@ if (MPI_CXX_FOUND) Solver/DualDecomp/DdMWAsyncDyn.cpp Solver/DualDecomp/DdMWPara.cpp Solver/DualDecomp/DdMWSync.cpp + Solver/DualDecomp/DdDroWorkerUBMpi.cpp Utility/DspMpi.cpp ) if(SCIPLIB) diff --git a/src/DspConfig.h b/src/DspConfig.h index a406f4a2..5c499225 100644 --- a/src/DspConfig.h +++ b/src/DspConfig.h @@ -5,7 +5,7 @@ * So it is based on symantic versioning. */ #define DSP_VERSION_MAJOR 1 -#define DSP_VERSION_MINOR 3 +#define DSP_VERSION_MINOR 4 #define DSP_VERSION_PATCH 0 #include @@ -13,13 +13,13 @@ inline void show_copyright() { char msg[1024]; - sprintf(msg, "\n=================================================================================\n\n" + sprintf(msg, "\n=================================================================================\n" " DSP: Parallel decomposition methods for structured programming\n" " - Version %d.%d.%d\n" " - See https://github.com/Argonne-National-Laboratory/DSP\n\n" " Under the terms of Contract No. DE-AC02-06CH11357 with UChicago Argonne, LLC,\n" " the U.S. Government retains certain rights in this software.\n\n" - "=================================================================================\n\n", + "=================================================================================\n", DSP_VERSION_MAJOR, DSP_VERSION_MINOR, DSP_VERSION_PATCH); printf("%s", msg); } diff --git a/src/Model/StoModel.cpp b/src/Model/StoModel.cpp index 52ee54d4..914151ea 100644 --- a/src/Model/StoModel.cpp +++ b/src/Model/StoModel.cpp @@ -496,7 +496,6 @@ DSP_RTN_CODE StoModel::setWassersteinAmbiguitySet(double lp_norm, double eps) * TODO: Can we do in parallel? * The relevant issues need addressed first: * - https://github.com/kibaekkim/DSPopt.jl/issues/14 - * - https://github.com/Argonne-National-Laboratory/DSP/issues/50 */ for (int ss = 0; ss < nscen_; ++ss) { @@ -542,7 +541,7 @@ DSP_RTN_CODE StoModel::setWassersteinAmbiguitySet(double lp_norm, double eps) */ printf("[DRO] Set %d reference scenarios.\n", nrefs_); - printf("[DRO] Computed the Wasserstein distances with %f-norm.\n", lp_norm); + printf("[DRO] Computed the Wasserstein distances of order %f.\n", lp_norm); return DSP_RTN_OK; } diff --git a/src/Solver/DualDecomp/DdDroWorkerUB.cpp b/src/Solver/DualDecomp/DdDroWorkerUB.cpp new file mode 100644 index 00000000..bf16c892 --- /dev/null +++ b/src/Solver/DualDecomp/DdDroWorkerUB.cpp @@ -0,0 +1,280 @@ +// #define DSP_DEBUG +#include "Model/TssModel.h" +#include "Solver/DualDecomp/DdDroWorkerUB.h" +#include "SolverInterface/DspOsiCpx.h" +#include "SolverInterface/DspOsiGrb.h" +#include "SolverInterface/DspOsiScip.h" + +#ifdef DSP_HAS_SCIP +#include "Solver/DualDecomp/SCIPconshdlrBendersDd.h" +#endif + +DdDroWorkerUB::DdDroWorkerUB(const DdDroWorkerUB &rhs) : DdWorkerUB(rhs) +{ + osi_dro_ = rhs.osi_dro_->clone(); +} + +DdDroWorkerUB::~DdDroWorkerUB() +{ + FREE_PTR(osi_dro_); +} + +DSP_RTN_CODE DdDroWorkerUB::init() +{ + BGN_TRY_CATCH + status_ = DSP_STAT_MW_CONTINUE; + + /** Create the stochastic upper bounding subproblems. + * We still need to solve these subproblems, + * in addition to the DRO upper bounding problem. + */ + DSP_RTN_CHECK_THROW(DdWorkerUB::createProblem()); + + /** Create the DRO upper bounding problem. */ + DSP_RTN_CHECK_THROW(createProblem()); + + END_TRY_CATCH_RTN(;, DSP_RTN_ERR) + return DSP_RTN_OK; +} + +DSP_RTN_CODE DdDroWorkerUB::createProblem() +{ +#define FREE_MEMORY \ + FREE_ARRAY_PTR(clbd_dro) \ + FREE_ARRAY_PTR(cubd_dro) \ + FREE_ARRAY_PTR(rlbd_dro) \ + FREE_ARRAY_PTR(rubd_dro) \ + FREE_ARRAY_PTR(obj_dro) \ + FREE_ARRAY_PTR(elem_dro) \ + FREE_ARRAY_PTR(ind_dro) \ + FREE_ARRAY_PTR(bgn_dro) \ + FREE_ARRAY_PTR(len_dro) + + /** DRO UB problem */ + double *clbd_dro = NULL; + double *cubd_dro = NULL; + double *obj_dro = NULL; + double *rlbd_dro = NULL; + double *rubd_dro = NULL; + double *elem_dro = NULL; + int *ind_dro = NULL; + int *bgn_dro = NULL; + int *len_dro = NULL; + + TssModel *tss = NULL; + + BGN_TRY_CATCH + + try + { + tss = dynamic_cast(model_); + } + catch (const std::bad_cast &e) + { + printf("This is not a stochastic programming problem.\n"); + return DSP_RTN_ERR; + } + + /** create DRO upper bounding problem */ + int nsubprobs = par_->getIntPtrParamSize("ARR_PROC_IDX"); + int ncols_dro = 1 + model_->getNumReferences(); + int nrows_dro = model_->getNumReferences() * tss->getNumScenarios(); + int nzcnt_dro = nrows_dro * 2; + + /** The second-stage objective coefficients of each subproblem + * need re-sacled by the original probability. + */ + for (int s = 0; s < nsubprobs; ++s) + { + const double *obj_reco = osi_[s]->si_->getObjCoefficients(); + for (int j = 0; j < tss->getNumCols(1); ++j) + { + osi_[s]->si_->setObjCoeff(j, obj_reco[j] / tss->getProbability()[par_->getIntPtrParam("ARR_PROC_IDX")[s]]); + } + } + + /** allocate memory */ + clbd_dro = new double[ncols_dro]; + cubd_dro = new double[ncols_dro]; + obj_dro = new double[ncols_dro]; + rlbd_dro = new double[nrows_dro]; + rubd_dro = new double[nrows_dro]; + bgn_dro = new int[nrows_dro + 1]; + len_dro = new int[nrows_dro]; + ind_dro = new int[nzcnt_dro]; + elem_dro = new double[nzcnt_dro]; + + /** column bounds */ + clbd_dro[0] = 0.0; + CoinFillN(clbd_dro + 1, ncols_dro - 1, -COIN_DBL_MAX); + CoinFillN(cubd_dro, ncols_dro, COIN_DBL_MAX); + + /** row bounds */ + CoinFillN(rlbd_dro, nrows_dro, -COIN_DBL_MAX); + CoinFillN(rubd_dro, nrows_dro, COIN_DBL_MAX); + + /** objective coefficients */ + obj_dro[0] = model_->getWassersteinSize(); + for (int j = 1; j < ncols_dro; ++j) + obj_dro[j] = model_->getReferenceProbability(j - 1); + + int pos_dro = 0; + int rnum = 0; + for (int k = 0; k < tss->getNumScenarios(); ++k) + { + for (int s = 0; s < model_->getNumReferences(); ++s) + { + rnum = k * model_->getNumReferences() + s; + + bgn_dro[rnum] = pos_dro; + + // alpha + ind_dro[pos_dro] = 0; + elem_dro[pos_dro] = model_->getWassersteinDist(s, k); + pos_dro++; + + // beta_s + ind_dro[pos_dro] = 1 + s; + elem_dro[pos_dro] = 1.0; + pos_dro++; + + len_dro[rnum] = pos_dro - bgn_dro[rnum]; + } + } + bgn_dro[nrows_dro] = pos_dro; + assert(pos_dro == nzcnt_dro); + + /** constraint matrix */ + CoinPackedMatrix *mat_dro = new CoinPackedMatrix(false, ncols_dro, nrows_dro, nzcnt_dro, elem_dro, ind_dro, bgn_dro, len_dro); + DSPdebug(mat_dro->verifyMtx(4)); + + /** creating solver interface */ + osi_dro_ = createDspOsi(); + if (!osi_dro_) + throw CoinError("Failed to create DspOsi", "createProblem", "DdWorkerUB"); + + /** no display */ + osi_dro_->setLogLevel(0); + + /** load problem */ + osi_dro_->si_->loadProblem(*mat_dro, clbd_dro, cubd_dro, obj_dro, rlbd_dro, rubd_dro); + + /** free matrix */ + FREE_PTR(mat_dro); + + END_TRY_CATCH_RTN(FREE_MEMORY, DSP_RTN_ERR) + + FREE_MEMORY + + return DSP_RTN_OK; +#undef FREE_MEMORY +} + +DSP_RTN_CODE DdDroWorkerUB::solve() +{ + double cputime; + double walltime; + + BGN_TRY_CATCH + + double primobj = 0.0; + double dualobj = 0.0; + double total_cputime = 0.0; + double total_walltime = 0.0; + int nsubprobs = par_->getIntPtrParamSize("ARR_PROC_IDX"); + + for (unsigned s = 0; s < nsubprobs; ++s) + { + cputime = CoinCpuTime(); + walltime = CoinGetTimeOfDay(); + + /** set time limit */ + osi_[s]->setTimeLimit( + CoinMin(CoinMax(0.01, time_remains_), + par_->getDblParam("DD/SUB/TIME_LIM"))); + + /** solve */ + osi_[s]->solve(); + + /** check status. there might be unexpected results. */ + int status = osi_[s]->status(); + DSPdebugMessage("status = %d\n", status); + switch (status) + { + case DSP_STAT_OPTIMAL: + case DSP_STAT_LIM_ITERorTIME: + case DSP_STAT_STOPPED_GAP: + case DSP_STAT_STOPPED_NODE: + case DSP_STAT_STOPPED_TIME: + break; + default: + status_ = DSP_STAT_MW_STOP; + message_->print(10, + "Warning: subproblem %d solution status is %d\n", s, + status); + break; + } + if (status_ == DSP_STAT_MW_STOP) + { + primobj = COIN_DBL_MAX; + dualobj = -COIN_DBL_MAX; + break; + } + + CoinCopyN(osi_[s]->si_->getColSolution(), osi_[s]->si_->getNumCols(), &primsols_[s][0]); + total_cputime += CoinCpuTime() - cputime; + total_walltime += CoinGetTimeOfDay() - walltime; + + /** consume time */ + time_remains_ -= CoinGetTimeOfDay() - walltime; + } + + cputime = CoinCpuTime(); + walltime = CoinGetTimeOfDay(); + + /** solve the DRO UB problem */ + if (status_ != DSP_STAT_MW_STOP) + { + assert(nsubprobs == model_->getNumSubproblems()); + for (int k = 0; k < nsubprobs; ++k) + { + printf("rlbd[%d] = %e\n", k * model_->getNumReferences(), osi_[k]->si_->getObjValue()); + for (int s = 0; s < model_->getNumReferences(); ++s) + { + osi_dro_->si_->setRowLower(k * model_->getNumReferences() + s, osi_[k]->si_->getObjValue()); + } + } + osi_dro_->solve(); + + if (osi_dro_->si_->isProvenOptimal()) + { + primobj = osi_dro_->getPrimObjValue(); + dualobj = osi_dro_->getPrimObjValue(); + } + else + { + primobj = COIN_DBL_MAX; + dualobj = -COIN_DBL_MAX; + } + } + + /** get primal objective */ + ub_ = primobj; + DSPdebugMessage("ub_ = %e\n", ub_); + DSPdebugMessage("status_ %d\n", status_); + + total_cputime += CoinCpuTime() - cputime; + total_walltime += CoinGetTimeOfDay() - walltime; + time_remains_ -= CoinGetTimeOfDay() - walltime; + + /** update statistics */ + s_statuses_.push_back(status_); + s_primobjs_.push_back(primobj); + s_dualobjs_.push_back(dualobj); + s_cputimes_.push_back(total_cputime); + s_walltimes_.push_back(total_walltime); + + END_TRY_CATCH_RTN(;, DSP_RTN_ERR) + + return DSP_RTN_OK; +} diff --git a/src/Solver/DualDecomp/DdDroWorkerUB.h b/src/Solver/DualDecomp/DdDroWorkerUB.h new file mode 100644 index 00000000..204ee851 --- /dev/null +++ b/src/Solver/DualDecomp/DdDroWorkerUB.h @@ -0,0 +1,52 @@ +#ifndef SRC_SOLVER_DUALDECOMP_DDDROWORKERUB_H_ +#define SRC_SOLVER_DUALDECOMP_DDDROWORKERUB_H_ + +#include "Solver/DualDecomp/DdWorkerUB.h" + +/** A worker class for solving upper bounding subproblems + * for the distributionally robust optimization. + */ +class DdDroWorkerUB : public DdWorkerUB +{ + + friend class DdMWSerial; + friend class DdMWSync; + friend class DdMWAsync; + +public: + /** A default constructor. */ + DdDroWorkerUB( + DecModel *model, /**< model pointer */ + DspParams *par, /**< parameter pointer */ + DspMessage *message /**< message pointer */) + : DdWorkerUB(model, par, message), + osi_dro_(NULL) + { + } + + /** A copy constructor. */ + DdDroWorkerUB(const DdDroWorkerUB &rhs); + + /** A default destructor. */ + virtual ~DdDroWorkerUB(); + + /** A clone function */ + virtual DdDroWorkerUB *clone() const + { + return new DdDroWorkerUB(*this); + } + + /** A virtual member for initializing solver. */ + virtual DSP_RTN_CODE init(); + + /** A virtual member for solving problem. */ + virtual DSP_RTN_CODE solve(); + + /** create problem */ + virtual DSP_RTN_CODE createProblem(); + +protected: + DspOsi *osi_dro_; /**< solver interface for DRO upper bound */ +}; + +#endif /* SRC_SOLVER_DUALDECOMP_DDDROWORKERUB_H_ */ diff --git a/src/Solver/DualDecomp/DdDroWorkerUBMpi.cpp b/src/Solver/DualDecomp/DdDroWorkerUBMpi.cpp new file mode 100644 index 00000000..f3a1eff5 --- /dev/null +++ b/src/Solver/DualDecomp/DdDroWorkerUBMpi.cpp @@ -0,0 +1,242 @@ +// #define DSP_DEBUG +#include "Model/TssModel.h" +#include "Solver/DualDecomp/DdDroWorkerUBMpi.h" + +DdDroWorkerUBMpi::DdDroWorkerUBMpi( + MPI_Comm comm, /**< MPI communicator */ + DecModel *model, /**< model pointer */ + DspParams *par, /**< parameter pointer */ + DspMessage *message /**< message pointer */) + : DdDroWorkerUB(model, par, message), comm_(comm) +{ + MPI_Comm_size(comm_, &comm_size_); + MPI_Comm_rank(comm_, &comm_rank_); + DSPdebugMessage("comm_size_ %d comm_rank_ %d\n", comm_size_, comm_rank_); +} + +DSP_RTN_CODE DdDroWorkerUBMpi::init() +{ + BGN_TRY_CATCH + status_ = DSP_STAT_MW_CONTINUE; + + /** Create the stochastic upper bounding subproblems. + * We still need to solve these subproblems, + * in addition to the DRO upper bounding problem. + */ + DSP_RTN_CHECK_THROW(DdWorkerUB::createProblem()); + + /** Create the DRO upper bounding problem. + * This problem is solved by the root process only. + */ + if (comm_rank_ == 0) + { + DSP_RTN_CHECK_THROW(createProblem()); + } + else + { + TssModel *tss = NULL; + try + { + tss = dynamic_cast(model_); + } + catch (const std::bad_cast &e) + { + printf("This is not a stochastic programming problem.\n"); + return DSP_RTN_ERR; + } + for (int s = 0; s < par_->getIntPtrParamSize("ARR_PROC_IDX"); ++s) + { + const double *obj_reco = osi_[s]->si_->getObjCoefficients(); + for (int j = 0; j < tss->getNumCols(1); ++j) + { + osi_[s]->si_->setObjCoeff(j, obj_reco[j] / tss->getProbability()[par_->getIntPtrParam("ARR_PROC_IDX")[s]]); + } + } + } + + END_TRY_CATCH_RTN(;, DSP_RTN_ERR) + return DSP_RTN_OK; +} + +DSP_RTN_CODE DdDroWorkerUBMpi::solve() +{ +#define FREE_MEMORY \ + FREE_ARRAY_PTR(sendbuf) \ + FREE_ARRAY_PTR(recvbuf) \ + FREE_ARRAY_PTR(recvcounts) \ + FREE_ARRAY_PTR(displs) \ + FREE_ARRAY_PTR(subprob_ids) + + double *sendbuf = NULL; + double *recvbuf = NULL; + int *recvcounts = NULL; + int *displs = NULL; + int *subprob_ids = NULL; + + double cputime; + double walltime; + + BGN_TRY_CATCH + + double primobj = 0.0; + double dualobj = 0.0; + double total_cputime = 0.0; + double total_walltime = 0.0; + int nsubprobs = par_->getIntPtrParamSize("ARR_PROC_IDX"); + + for (unsigned s = 0; s < nsubprobs; ++s) + { + cputime = CoinCpuTime(); + walltime = CoinGetTimeOfDay(); + + /** set time limit */ + osi_[s]->setTimeLimit( + CoinMin(CoinMax(0.01, time_remains_), + par_->getDblParam("DD/SUB/TIME_LIM"))); + + /** solve */ + osi_[s]->solve(); + + /** check status. there might be unexpected results. */ + int status = osi_[s]->status(); + DSPdebugMessage("status = %d\n", status); + switch (status) + { + case DSP_STAT_OPTIMAL: + case DSP_STAT_LIM_ITERorTIME: + case DSP_STAT_STOPPED_GAP: + case DSP_STAT_STOPPED_NODE: + case DSP_STAT_STOPPED_TIME: + break; + default: + status_ = DSP_STAT_MW_STOP; + message_->print(10, + "Warning: subproblem %d solution status is %d\n", s, + status); + break; + } + if (status_ == DSP_STAT_MW_STOP) + { + primobj = COIN_DBL_MAX; + dualobj = -COIN_DBL_MAX; + break; + } + + CoinCopyN(osi_[s]->si_->getColSolution(), osi_[s]->si_->getNumCols(), &primsols_[s][0]); + total_cputime += CoinCpuTime() - cputime; + total_walltime += CoinGetTimeOfDay() - walltime; + + /** consume time */ + time_remains_ -= CoinGetTimeOfDay() - walltime; + } + + cputime = CoinCpuTime(); + walltime = CoinGetTimeOfDay(); + + /** solve the DRO UB problem */ + if (status_ != DSP_STAT_MW_STOP) + { + /** memory allocation for MPI communication */ + sendbuf = new double[nsubprobs]; + if (comm_rank_ == 0) + { + recvbuf = new double[model_->getNumSubproblems()]; + recvcounts = new int[comm_size_]; + displs = new int[comm_size_]; + subprob_ids = new int[model_->getNumSubproblems()]; + } + + /** recvcounts stores the number of subproblems for each process. */ + // DSPdebugMessage("Rank %d: nsubprobs %d\n", comm_rank_, nsubprobs); + MPI_Gather(&nsubprobs, 1, MPI_INT, recvcounts, 1, MPI_INT, 0, comm_); + if (comm_rank_ == 0) + { + for (int i = 0; i < comm_size_; ++i) + { + displs[i] = i == 0 ? 0 : displs[i - 1] + recvcounts[i - 1]; + } + DSPdebugMessage("recvcounts:\n"); + DSPdebug(message_->printArray(comm_size_, recvcounts)); + DSPdebugMessage("displs:\n"); + DSPdebug(message_->printArray(comm_size_, displs)); + } + + /** assign send buffer */ + for (int i = 0; i < nsubprobs; ++i) + sendbuf[i] = osi_[i]->si_->getObjValue(); + // DSPdebugMessage("Rank %d: sendbuf:\n", comm_rank_); + // DSPdebug(message_->printArray(nsubprobs, sendbuf)); + + /** Gather subproblem indices */ + MPI_Gatherv(par_->getIntPtrParam("ARR_PROC_IDX"), nsubprobs, MPI_INT, + subprob_ids, recvcounts, displs, MPI_INT, 0, comm_); + + /** Gather subproblem objective values */ + MPI_Gatherv(sendbuf, nsubprobs, MPI_DOUBLE, recvbuf, recvcounts, displs, MPI_DOUBLE, 0, comm_); + + if (comm_rank_ == 0) + { + // DSPdebugMessage("subproblem IDs:\n"); + // DSPdebug(message_->printArray(model_->getNumSubproblems(), subprob_ids)); + // DSPdebugMessage("subproblem objs:\n"); + // DSPdebug(message_->printArray(model_->getNumSubproblems(), recvbuf)); + + /** Set right-hand sides for the upper bounding problem */ + for (int k = 0; k < model_->getNumSubproblems(); ++k) + { + DSPdebugMessage("subprob_ids[%d] = %d, rlbd[%d] = %e\n", k, subprob_ids[k], + subprob_ids[k] * model_->getNumReferences(), + recvbuf[k]); + for (int s = 0; s < model_->getNumReferences(); ++s) + { + osi_dro_->si_->setRowLower( + subprob_ids[k] * model_->getNumReferences() + s, + recvbuf[k]); + } + } + osi_dro_->solve(); + + if (osi_dro_->si_->isProvenOptimal()) + { + primobj = osi_dro_->getPrimObjValue(); + dualobj = osi_dro_->getPrimObjValue(); + } + else + { + primobj = COIN_DBL_MAX; + dualobj = -COIN_DBL_MAX; + } + } + else + + { + primobj = 0.0; + dualobj = 0.0; + } + } + + /** get primal objective */ + ub_ = primobj; + DSPdebugMessage("ub_ = %e\n", ub_); + DSPdebugMessage("status_ %d\n", status_); + + MPI_Barrier(comm_); + + total_cputime += CoinCpuTime() - cputime; + total_walltime += CoinGetTimeOfDay() - walltime; + time_remains_ -= CoinGetTimeOfDay() - walltime; + + /** update statistics */ + s_statuses_.push_back(status_); + s_primobjs_.push_back(primobj); + s_dualobjs_.push_back(dualobj); + s_cputimes_.push_back(total_cputime); + s_walltimes_.push_back(total_walltime); + + END_TRY_CATCH_RTN(FREE_MEMORY, DSP_RTN_ERR) + + FREE_MEMORY + + return DSP_RTN_OK; +#undef FREE_MEMORY +} diff --git a/src/Solver/DualDecomp/DdDroWorkerUBMpi.h b/src/Solver/DualDecomp/DdDroWorkerUBMpi.h new file mode 100644 index 00000000..6ef00041 --- /dev/null +++ b/src/Solver/DualDecomp/DdDroWorkerUBMpi.h @@ -0,0 +1,61 @@ +#ifndef SRC_SOLVER_DUALDECOMP_DDDROWORKERUBMPI_H_ +#define SRC_SOLVER_DUALDECOMP_DDDROWORKERUBMPI_H_ + +#include "Utility/DspMpi.h" +#include "Solver/DualDecomp/DdDroWorkerUB.h" + +/** A worker class for solving upper bounding subproblems + * for the distributionally robust optimization + * in parallel. + */ +class DdDroWorkerUBMpi : public DdDroWorkerUB +{ + + friend class DdMWSerial; + friend class DdMWSync; + friend class DdMWAsync; + +public: + /** A default constructor. */ + DdDroWorkerUBMpi( + MPI_Comm comm, /**< MPI communicator */ + DecModel *model, /**< model pointer */ + DspParams *par, /**< parameter pointer */ + DspMessage *message /**< message pointer */); + + /** A copy constructor. */ + DdDroWorkerUBMpi(const DdDroWorkerUBMpi &rhs) + : DdDroWorkerUB(rhs) + { + comm_ = rhs.comm_; + comm_size_ = rhs.comm_size_; + comm_rank_ = rhs.comm_rank_; + } + + /** A default destructor. */ + virtual ~DdDroWorkerUBMpi() + { + comm_ = MPI_COMM_NULL; + comm_size_ = 0; + comm_rank_ = -1; + } + + /** A clone function */ + virtual DdDroWorkerUBMpi *clone() const + { + return new DdDroWorkerUBMpi(*this); + } + + /** A virtual member for initializing solver. */ + virtual DSP_RTN_CODE init(); + + /** A virtual member for solving problem. */ + virtual DSP_RTN_CODE solve(); + +private: + MPI_Comm comm_; + int comm_rank_; + int comm_size_; +}; + +#endif /* SRC_SOLVER_DUALDECOMP_DDDROWORKERUBMPI_H_ */ diff --git a/src/Solver/DualDecomp/DdMW.h b/src/Solver/DualDecomp/DdMW.h index 435d7c2f..6d32e664 100644 --- a/src/Solver/DualDecomp/DdMW.h +++ b/src/Solver/DualDecomp/DdMW.h @@ -13,6 +13,7 @@ #include "Solver/DualDecomp/DdWorker.h" #include "Solver/DualDecomp/DdWorkerLB.h" #include "Solver/DualDecomp/DdWorkerUB.h" +#include "Solver/DualDecomp/DdDroWorkerUB.h" #ifdef DSP_HAS_SCIP #include "Solver/DualDecomp/DdWorkerCGBd.h" diff --git a/src/Solver/DualDecomp/DdMWPara.h b/src/Solver/DualDecomp/DdMWPara.h index fd41bddf..7be19663 100644 --- a/src/Solver/DualDecomp/DdMWPara.h +++ b/src/Solver/DualDecomp/DdMWPara.h @@ -10,6 +10,7 @@ #include "Utility/DspMpi.h" #include "DdMW.h" +#include "Solver/DualDecomp/DdDroWorkerUBMpi.h" /** A master-worker class for parallel dual decomposition */ class DdMWPara: public DdMW { diff --git a/src/Solver/DualDecomp/DdMWSerial.cpp b/src/Solver/DualDecomp/DdMWSerial.cpp index 25a6471a..fc194806 100644 --- a/src/Solver/DualDecomp/DdMWSerial.cpp +++ b/src/Solver/DualDecomp/DdMWSerial.cpp @@ -73,7 +73,12 @@ DSP_RTN_CODE DdMWSerial::init() { #endif /** create UB worker */ if (parEvalUb_ >= 0) - worker_.push_back(new DdWorkerUB(model_, par_, message_)); + { + if (model_->isDro()) + worker_.push_back(new DdDroWorkerUB(model_, par_, message_)); + else + worker_.push_back(new DdWorkerUB(model_, par_, message_)); + } /** initialize workers */ for (unsigned i = 0; i < worker_.size(); ++i) worker_[i]->init(); @@ -201,6 +206,11 @@ DSP_RTN_CODE DdMWSerial::run() { DSPdebugMessage("nsubsolution[%d] = %d\n", s, nsubsolution[s]); } +#ifdef DSP_HAS_SCIP + if (model_->isDro()) + message_->print(0, "Cut procedures are not implemented for DRO.\n"); +#endif + printHeaderInfo(); /** reset iteration info */ @@ -252,9 +262,8 @@ DSP_RTN_CODE DdMWSerial::run() { if (parFeasCuts_ >= 0 || parOptCuts_ >= 0) { #ifdef DSP_HAS_SCIP - if (model_->isDro()) { - message_->print(0, "Cut procedures are not implemented for DRO.\n"); - } else { + if (model_->isDro() == false) + { DSPdebugMessage("generate Benders cuts\n"); cg_status = generateBendersCuts(workercg, coupling_solutions, cuts); /** resolve subproblems? */ diff --git a/src/Solver/DualDecomp/DdMWSync.cpp b/src/Solver/DualDecomp/DdMWSync.cpp index 6f94eaa2..6db55df7 100644 --- a/src/Solver/DualDecomp/DdMWSync.cpp +++ b/src/Solver/DualDecomp/DdMWSync.cpp @@ -82,7 +82,10 @@ DSP_RTN_CODE DdMWSync::init() if (parEvalUb_ >= 0) { DSPdebugMessage("Rank %d creates a worker for upper bounds.\n", comm_rank_); - worker_.push_back(new DdWorkerUB(model_, par_, message_)); + if (model_->isDro()) + worker_.push_back(new DdDroWorkerUBMpi(lb_comm_, model_, par_, message_)); + else + worker_.push_back(new DdWorkerUB(model_, par_, message_)); } } /** initialize workers */ @@ -217,6 +220,7 @@ DSP_RTN_CODE DdMWSync::runMaster() * [for each subproblem] * 1 theta * 2 lambda + * 3 P (probability for the subproblem) */ int size_of_sendbuf; /**< MPI_Scatterv: size of send buffer pointer */ double * sendbuf = NULL; /**< MPI_Scatterv: send buffer */ @@ -237,6 +241,7 @@ DSP_RTN_CODE DdMWSync::runMaster() const double * thetas = NULL; /**< of master problem */ double ** lambdas = NULL; /**< of master problem */ + const double *Ps = NULL; /**< of DRO master problem */ int * nsubsolution = NULL; /**< size of subproblem solution for each scenario */ @@ -244,12 +249,27 @@ DSP_RTN_CODE DdMWSync::runMaster() Solutions dummy_solutions; std::vector dummy_double_array; + TssModel *tss = NULL; + /** Benders cuts */ OsiCuts cuts, emptycuts; int cg_status = DSP_STAT_MW_CONTINUE; BGN_TRY_CATCH + if (model_->isStochastic()) + { + try + { + tss = dynamic_cast(model_); + } + catch (const std::bad_cast &e) + { + printf("Error: Model claims to be stochastic when it is not\n"); + return DSP_RTN_ERR; + } + } + /** collect timing results */ double mt_total = 0.0; /**< total time */ double mt_solve = 0.0; /**< solution time */ @@ -264,11 +284,16 @@ DSP_RTN_CODE DdMWSync::runMaster() nsubsolution = new int [model_->getNumSubproblems()]; if (model_->isDro()) { TssModel* tss = dynamic_cast(model_); - CoinFillN(nsubsolution, model_->getNumSubproblems(), tss->getNumCols(0)+tss->getNumCols(1)); + CoinFillN( + nsubsolution, + model_->getNumSubproblems(), + tss->getNumCols(0) + tss->getNumCols(1) + 1); // +1 for auxiliary variable } else { for (int s = 0; s < model_->getNumSubproblems(); ++s) nsubsolution[s] = model_->getNumSubproblemCouplingCols(s); } + // DSPdebugMessage("Master:\n"); + // DSPdebug(message_->printArray(model_->getNumSubproblems(), nsubsolution)); /** allocate memory for buffer sizes and displacements */ scounts = new int [subcomm_size_]; @@ -283,7 +308,12 @@ DSP_RTN_CODE DdMWSync::runMaster() { scounts[i] = 0; for (int j = 0; j < nsubprobs_[i]; ++j) - scounts[i] += 1 + model_->getNumSubproblemCouplingRows(subprob_indices_[subprob_displs_[i]+j]); + { + scounts[i] += 1 // theta + + model_->getNumSubproblemCouplingRows(subprob_indices_[subprob_displs_[i] + j]); // lambda + if (model_->isStochastic()) + scounts[i] += 1; // P + } sdispls[i] = i == 0 ? 0 : sdispls[i-1] + scounts[i-1]; size_of_sendbuf += scounts[i]; } @@ -345,7 +375,7 @@ DSP_RTN_CODE DdMWSync::runMaster() master->subdualobj_[sindex] = recvbuf[pos++]; CoinCopyN(recvbuf + pos, nsubsolution[s], master->subsolution_[sindex]); - pos += model_->getNumSubproblemCouplingCols(sindex); + pos += nsubsolution[sindex]; DSPdebugMessage("-> master, subprob %d primobj %+e\n", sindex, master->subprimobj_[sindex]); } } @@ -427,6 +457,17 @@ DSP_RTN_CODE DdMWSync::runMaster() lambdas[i] = master_primsol + j; j += model_->getNumSubproblemCouplingRows(i); } + if (model_->isStochastic()) + { + if (model_->isDro()) + { + Ps = master_primsol + master_->getNumCols() - tss->getNumScenarios(); + } + else + { + Ps = tss->getProbability(); + } + } master_primsol = NULL; /** create send buffer */ @@ -439,12 +480,14 @@ DSP_RTN_CODE DdMWSync::runMaster() CoinCopyN(lambdas[subprob_index], model_->getNumSubproblemCouplingRows(subprob_index), sendbuf + pos); pos += model_->getNumSubproblemCouplingRows(subprob_index); + if (model_->isStochastic()) + sendbuf[pos++] = Ps[subprob_index]; } } - DSPdebugMessage2("master send buffer:\n"); - DSPdebug2(for (int i = 0; i < subcomm_size_; ++i) { - DSPdebugMessage2(" rank %d:\n", i); + DSPdebugMessage("master send buffer:\n"); + DSPdebug(for (int i = 0; i < subcomm_size_; ++i) { + DSPdebugMessage(" rank %d (size %d):\n", i, scounts[i]); message_->printArray(scounts[i], sendbuf + sdispls[i]); }); @@ -510,13 +553,10 @@ DSP_RTN_CODE DdMWSync::runWorker() #define FREE_MEMORY \ FREE_ARRAY_PTR(sendbuf) \ FREE_ARRAY_PTR(recvbuf) \ - FREE_ARRAY_PTR(nsubsolution) \ - Ps = NULL; + FREE_ARRAY_PTR(nsubsolution) #define SIG_BREAK if (signal == DSP_STAT_MW_STOP) break; - const double * Ps = NULL; /**< of DRO master problem */ - /** MPI_Gatherv message: * [for each subproblem] * 1 subproblem index @@ -531,6 +571,7 @@ DSP_RTN_CODE DdMWSync::runWorker() * [for each subproblem] * 1 theta * 2 lambda + * 3 P (probability for the subproblem) */ double * recvbuf = NULL; /**< MPI_Scatterv: receive buffer */ int rcount = 0; /**< MPI_Scatterv: receive buffer size */ @@ -582,6 +623,8 @@ DSP_RTN_CODE DdMWSync::runWorker() for (int s = 0; s < narrprocidx; ++s) nsubsolution[s] = workerlb->subprobs_[s]->ncols_coupling_; } + // DSPdebugMessage("Worker %d:\n", comm_rank_); + // DSPdebug(message_->printArray(narrprocidx, nsubsolution)); /** calculate size of send buffer */ for (int i = 0; i < narrprocidx; ++i) @@ -590,6 +633,8 @@ DSP_RTN_CODE DdMWSync::runWorker() /** calculate size of receive buffer */ for (int i = 0; i < narrprocidx; ++i) rcount += 1 + model_->getNumSubproblemCouplingRows(arrprocidx[i]); + if (model_->isStochastic()) + rcount += narrprocidx; /** allocate memory for message buffers */ sendbuf = new double [scount]; @@ -618,10 +663,11 @@ DSP_RTN_CODE DdMWSync::runWorker() sendbuf[pos++] = workerlb->subprobs_[s]->getPrimalObjective(); sendbuf[pos++] = workerlb->subprobs_[s]->getDualObjective(); CoinCopyN(workerlb->subprobs_[s]->getSiPtr()->getColSolution(), nsubsolution[s], sendbuf + pos); - pos += model_->getNumSubproblemCouplingCols(workerlb->subprobs_[s]->sind_); - DSPdebugMessage("MW -> worker %d, subprob %d primobj %+e dualobj %+e\n", - comm_rank_, workerlb->subprobs_[s]->sind_, - workerlb->subprobs_[s]->getPrimalObjective(), workerlb->subprobs_[s]->getDualObjective()); + pos += nsubsolution[s]; + DSPdebugMessage("MW -> worker %d, subprob %d primobj %+e dualobj %+e num_coupling_cols %d\n", + comm_rank_, workerlb->subprobs_[s]->sind_, + workerlb->subprobs_[s]->getPrimalObjective(), workerlb->subprobs_[s]->getDualObjective(), + nsubsolution[s]); } #ifdef DSP_DEBUG2 for (int i = 0; i < lb_comm_size_; ++i) @@ -696,39 +742,40 @@ DSP_RTN_CODE DdMWSync::runWorker() DSPdebugMessage("Worker received message (%d):\n", rcount); DSPdebug(message_->printArray(rcount, recvbuf)); - if (model_->isStochastic()) { - if (model_->isDro()) { - /** TODO: need to implement parallel DRO */ - //Ps = master_primsol + master_->getNumCols() - tss->getNumScenarios(); - throw CoinError("DRO is not supported.", "ruwnWorker", "DdMWSync"); - } else { - Ps = tss->getProbability(); - } - } - - /** parse message */ + /** Parse recvbuf to thetas, lambdas, Ps + * `recvbuf` contains the master solution of the form + * [theta_s1, lambda_s1, P_s1, theta_s2, lambda_s2, P_s2, ...], + * where P_s1, P_s2, .. are received for stochastic model only. + */ int sindex = -1; double probability = -1.0; + double *lambda = NULL; for (int s = 0, pos = 0; s < narrprocidx; ++s) { sindex = workerlb->subprobs_[s]->sind_; workerlb->subprobs_[s]->theta_ = recvbuf[pos++]; + lambda = recvbuf + pos; + pos += model_->getNumSubproblemCouplingRows(sindex); if (model_->isStochastic()) { - probability = Ps[sindex]; + probability = recvbuf[pos++]; + assert(probability >= 0.0); + assert(probability <= 1.0); } - workerlb->subprobs_[s]->updateProblem(recvbuf + pos, probability, bestprimalobj); + workerlb->subprobs_[s]->updateProblem(lambda, probability, bestprimalobj); /** apply Benders cuts */ if (parFeasCuts_ >= 0 || parOptCuts_ >= 0) { workerlb->subprobs_[s]->pushCuts(cutsToAdd_); DSPdebugMessage("Rank %d pushed %d Benders cuts.\n", comm_rank_, cutsToAdd_->sizeCuts()); } - pos += model_->getNumSubproblemCouplingRows(workerlb->subprobs_[s]->sind_); } } } } + /** This does the post-solve processing + * in order to return the best feasible solution. + */ if (parEvalUb_ >= 0 && model_->isStochastic()) { TssModel* tss = dynamic_cast(model_); DdWorkerUB * workerub = NULL; @@ -741,7 +788,10 @@ DSP_RTN_CODE DdMWSync::runWorker() /** get WorkerUB pointer */ for (unsigned i = 0; i < worker_.size(); ++i) if (worker_[i]->getType() == DdWorker::UB) { - workerub = dynamic_cast(worker_[i]); + if (model_->isDro()) + workerub = dynamic_cast(worker_[i]); + else + workerub = dynamic_cast(worker_[i]); break; } @@ -875,7 +925,10 @@ DSP_RTN_CODE DdMWSync::calculateUpperbound( { if (worker_[i]->getType() == DdWorker::UB) { - workerub = dynamic_cast(worker_[i]); + if (model_->isDro()) + workerub = dynamic_cast(worker_[i]); + else + workerub = dynamic_cast(worker_[i]); DSPdebugMessage("Rank %d works for upper bounds.\n", comm_rank_); break; } @@ -1058,6 +1111,7 @@ DSP_RTN_CODE DdMWSync::syncUpperbound( FREE_MEMORY return DSP_RTN_OK; +#undef FREE_MEMORY } DSP_RTN_CODE DdMWSync::scatterCouplingSolutions(Solutions & solutions) { diff --git a/src/Solver/DualDecomp/DdWorkerUB.cpp b/src/Solver/DualDecomp/DdWorkerUB.cpp index d54b7d75..6312637d 100644 --- a/src/Solver/DualDecomp/DdWorkerUB.cpp +++ b/src/Solver/DualDecomp/DdWorkerUB.cpp @@ -17,17 +17,17 @@ #endif DdWorkerUB::DdWorkerUB( - DecModel * model, /**< model pointer */ - DspParams * par, /**< parameter pointer */ - DspMessage * message /**< message pointer */): -DdWorker(model, par, message), -bestub_(COIN_DBL_MAX), -mat_mp_(NULL), -rlbd_org_(NULL), -rubd_org_(NULL), -osi_(NULL), -osi_dro_(NULL), -ub_(0.0) {} + DecModel *model, /**< model pointer */ + DspParams *par, /**< parameter pointer */ + DspMessage *message /**< message pointer */) : DdWorker(model, par, message), + bestub_(COIN_DBL_MAX), + mat_mp_(NULL), + rlbd_org_(NULL), + rubd_org_(NULL), + osi_(NULL), + ub_(0.0) +{ +} DdWorkerUB::DdWorkerUB(const DdWorkerUB& rhs) : DdWorker(rhs), @@ -50,8 +50,6 @@ ub_(rhs.ub_) { CoinCopyN(rhs.rlbd_org_[s], osi_[s]->si_->getNumRows(), rlbd_org_[s]); CoinCopyN(rhs.rubd_org_[s], osi_[s]->si_->getNumRows(), rubd_org_[s]); } - if (model_->isDro()) - osi_dro_ = rhs.osi_dro_->clone(); } DdWorkerUB::~DdWorkerUB() { @@ -59,7 +57,6 @@ DdWorkerUB::~DdWorkerUB() { FREE_2D_ARRAY_PTR(par_->getIntPtrParamSize("ARR_PROC_IDX"), rlbd_org_); FREE_2D_ARRAY_PTR(par_->getIntPtrParamSize("ARR_PROC_IDX"), rubd_org_); FREE_2D_PTR(par_->getIntPtrParamSize("ARR_PROC_IDX"), osi_); - FREE_PTR(osi_dro_); } DSP_RTN_CODE DdWorkerUB::init() { @@ -78,16 +75,7 @@ DSP_RTN_CODE DdWorkerUB::createProblem() { FREE_ARRAY_PTR(clbd_reco) \ FREE_ARRAY_PTR(cubd_reco) \ FREE_ARRAY_PTR(ctype_reco) \ - FREE_ARRAY_PTR(obj_reco) \ - FREE_ARRAY_PTR(clbd_dro) \ - FREE_ARRAY_PTR(cubd_dro) \ - FREE_ARRAY_PTR(rlbd_dro) \ - FREE_ARRAY_PTR(rubd_dro) \ - FREE_ARRAY_PTR(obj_dro) \ - FREE_ARRAY_PTR(elem_dro) \ - FREE_ARRAY_PTR(ind_dro) \ - FREE_ARRAY_PTR(bgn_dro) \ - FREE_ARRAY_PTR(len_dro) + FREE_ARRAY_PTR(obj_reco) /** recourse problem data */ CoinPackedMatrix * mat_reco = NULL; @@ -96,17 +84,6 @@ DSP_RTN_CODE DdWorkerUB::createProblem() { double * obj_reco = NULL; char * ctype_reco = NULL; - /** DRO UB problem */ - double * clbd_dro = NULL; - double * cubd_dro = NULL; - double * obj_dro = NULL; - double * rlbd_dro = NULL; - double * rubd_dro = NULL; - double * elem_dro = NULL; - int * ind_dro = NULL; - int * bgn_dro = NULL; - int * len_dro = NULL; - TssModel* tss = NULL; bool has_integer = false; @@ -114,9 +91,16 @@ DSP_RTN_CODE DdWorkerUB::createProblem() { BGN_TRY_CATCH int nsubprobs = par_->getIntPtrParamSize("ARR_PROC_IDX"); - tss = dynamic_cast(model_); - if (tss == NULL) - throw "This is not a stochastic programming problem."; + + try + { + tss = dynamic_cast(model_); + } + catch (const std::bad_cast &e) + { + printf("This is not a stochastic programming problem.\n"); + return DSP_RTN_ERR; + } /** allocate memory */ mat_mp_ = new CoinPackedMatrix * [nsubprobs]; @@ -132,12 +116,6 @@ DSP_RTN_CODE DdWorkerUB::createProblem() { mat_mp_[s], mat_reco, clbd_reco, cubd_reco, ctype_reco, obj_reco, rlbd_org_[s], rubd_org_[s])); - if (model_->isDro()) { - for (int j = 0; j < tss->getNumCols(1); ++j) { - obj_reco[j] /= tss->getProbability()[par_->getIntPtrParam("ARR_PROC_IDX")[s]]; - } - } - for (int j = 0; j < mat_reco->getNumCols(); ++j) if (ctype_reco[j] != 'C') { has_integer = true; @@ -167,79 +145,6 @@ DSP_RTN_CODE DdWorkerUB::createProblem() { FREE_MEMORY } - /** create DRO upper bounding problem */ - if (model_->isDro()) { - int ncols_dro = 1 + model_->getNumReferences(); - int nrows_dro = model_->getNumReferences() * tss->getNumScenarios(); - int nzcnt_dro = nrows_dro * 2; - - /** allocate memory */ - clbd_dro = new double [ncols_dro]; - cubd_dro = new double [ncols_dro]; - obj_dro = new double [ncols_dro]; - rlbd_dro = new double [nrows_dro]; - rubd_dro = new double [nrows_dro]; - bgn_dro = new int [nrows_dro+1]; - len_dro = new int [nrows_dro]; - ind_dro = new int [nzcnt_dro]; - elem_dro = new double [nzcnt_dro]; - - /** column bounds */ - clbd_dro[0] = 0.0; - CoinFillN(clbd_dro + 1, ncols_dro - 1, -COIN_DBL_MAX); - CoinFillN(cubd_dro, ncols_dro, COIN_DBL_MAX); - - /** row bounds */ - CoinFillN(rlbd_dro, nrows_dro, -COIN_DBL_MAX); - CoinFillN(rubd_dro, nrows_dro, COIN_DBL_MAX); - - /** objective coefficients */ - obj_dro[0] = model_->getWassersteinSize(); - for (int j = 1; j < ncols_dro; ++j) - obj_dro[j] = model_->getReferenceProbability(j-1); - - int pos_dro = 0; - int rnum = 0; - for (int k = 0; k < tss->getNumScenarios(); ++k) { - for (int s = 0; s < model_->getNumReferences(); ++s) { - rnum = k * model_->getNumReferences() + s; - - bgn_dro[rnum] = pos_dro; - - // alpha - ind_dro[pos_dro] = 0; - elem_dro[pos_dro] = model_->getWassersteinDist(s,k); - pos_dro++; - - // beta_s - ind_dro[pos_dro] = 1 + s; - elem_dro[pos_dro] = 1.0; - pos_dro++; - - len_dro[rnum] = pos_dro - bgn_dro[rnum]; - } - } - bgn_dro[nrows_dro] = pos_dro; - assert(pos_dro == nzcnt_dro); - - /** constraint matrix */ - CoinPackedMatrix *mat_dro = new CoinPackedMatrix(false, ncols_dro, nrows_dro, nzcnt_dro, elem_dro, ind_dro, bgn_dro, len_dro); - DSPdebug(mat_dro->verifyMtx(4)); - - /** creating solver interface */ - osi_dro_ = createDspOsi(); - if (!osi_dro_) throw CoinError("Failed to create DspOsi", "createProblem", "DdWorkerUB"); - - /** no display */ - osi_dro_->setLogLevel(0); - - /** load problem */ - osi_dro_->si_->loadProblem(*mat_dro, clbd_dro, cubd_dro, obj_dro, rlbd_dro, rubd_dro); - - /** free matrix */ - FREE_PTR(mat_dro); - } - END_TRY_CATCH_RTN(FREE_MEMORY, DSP_RTN_ERR) FREE_MEMORY @@ -395,23 +300,6 @@ DSP_RTN_CODE DdWorkerUB::solve() { time_remains_ -= CoinGetTimeOfDay() - walltime; } - /** solve the DRO UB problem */ - if (model_->isDro() && status_ != DSP_STAT_MW_STOP) { - assert(nsubprobs == model_->getNumSubproblems()); - for (int k = 0; k < nsubprobs; ++k) { - for (int s = 0; s < model_->getNumReferences(); ++s) { - osi_dro_->si_->setRowLower(k * model_->getNumReferences() + s, osi_[k]->si_->getObjValue()); - } - } - osi_dro_->solve(); - - if (osi_dro_->si_->isProvenOptimal()) { - primobj = osi_dro_->getPrimObjValue(); - } else { - primobj = COIN_DBL_MAX; - } - } - /** get primal objective */ ub_ = primobj; DSPdebugMessage("ub_ = %e\n", ub_); diff --git a/src/Solver/DualDecomp/DdWorkerUB.h b/src/Solver/DualDecomp/DdWorkerUB.h index 329cdc56..aec106a7 100644 --- a/src/Solver/DualDecomp/DdWorkerUB.h +++ b/src/Solver/DualDecomp/DdWorkerUB.h @@ -46,11 +46,9 @@ class DdWorkerUB: public DdWorker { /** A virtual memeber for finalizing solver. */ virtual DSP_RTN_CODE finalize() {return DSP_RTN_OK;} -public: - /** evaluate solution */ - double evaluate(CoinPackedVector * solution); - double evaluate(int n, double * solution); + virtual double evaluate(CoinPackedVector *solution); + virtual double evaluate(int n, double *solution); virtual int getType() {return UB;} @@ -66,14 +64,12 @@ class DdWorkerUB: public DdWorker { double bestub_; /**< best upper bound */ std::vector > primsols_; /**< primal solution for each subproblem */ -private: - +protected: CoinPackedMatrix ** mat_mp_; double** rlbd_org_; /**< original row lower bounds for each subproblem */ double** rubd_org_; /**< original row upper bounds for each subproblem */ - DspOsi ** osi_; /**< solver interface for each subproblem */ - DspOsi * osi_dro_; /**< solver interface for DRO upper bound */ + DspOsi **osi_; /**< solver interface for each subproblem */ double ub_; /**< upper bound */ }; diff --git a/src/Utility/DspMessage.h b/src/Utility/DspMessage.h index 7f40c68f..ca95f664 100644 --- a/src/Utility/DspMessage.h +++ b/src/Utility/DspMessage.h @@ -73,7 +73,8 @@ class DspMessage { for (int i = 0, j = 0; i < n; ++i) { - if (fabs(values[i]) < 1.0e-10) continue; + if (values[i] == 0) + continue; if (j > 0 && j % 5 == 0) printf("\n"); printf(" [%6d] %+10d", i, values[i]); j++; diff --git a/src/dsp.cpp b/src/dsp.cpp index bdb29964..f193792c 100644 --- a/src/dsp.cpp +++ b/src/dsp.cpp @@ -266,7 +266,11 @@ int runDsp(char *algotype, char *smpsfile, char *mpsfile, char *decfile, char *s if (isroot) cout << "Run distributionally robust dual decomposition" << endl; +#ifdef DSP_HAS_MPI + solveDdMpi(env, MPI_COMM_WORLD); +#else solveDd(env); +#endif } else { cout << "Dual decomposition is not available for mps/dec files." << endl; issolved = false; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9b12f502..0b5191d1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,78 +1,95 @@ if(SCIPLIB) - add_test(NAME scip_farmer_de COMMAND $ENV{PWD}/src/runDsp --algo de --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) - add_test(NAME scip_farmer_dd COMMAND $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) - add_test(NAME scip_farmer_dw COMMAND $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) - add_test(NAME scip_farmer_bd COMMAND $ENV{PWD}/src/runDsp --algo bd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) - add_test(NAME scip_farmer_drbd COMMAND $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108354) - add_test(NAME scip_farmer_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108354) - add_test(NAME scip_sslp_bd COMMAND $ENV{PWD}/src/runDsp --algo bd --smps ${CMAKE_SOURCE_DIR}/examples/smps/sslp_5_25_50 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -121.6) - add_test(NAME scip_drslp_drbd COMMAND $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test 5.60247) - add_test(NAME scip_drslp_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test 5.60247) - add_test(NAME scip_sslp_BB_drbd COMMAND $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0703) - add_test(NAME scip_sslp_BB_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0703) - add_test(NAME scip_sslp_BC_drbd COMMAND $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0705) - add_test(NAME scip_sslp_BC_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0705) - # add_test(NAME scip_sslp_CC_drbd COMMAND $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -194.836) - add_test(NAME scip_sslp_CC_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -194.811) - add_test(NAME scip_noswot_de COMMAND $ENV{PWD}/src/runDsp --algo de --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -42) + add_test(NAME scip_bd_farmer COMMAND $ENV{PWD}/src/runDsp --algo bd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) + add_test(NAME scip_bd_sslp COMMAND $ENV{PWD}/src/runDsp --algo bd --smps ${CMAKE_SOURCE_DIR}/examples/smps/sslp_5_25_50 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -121.6) + add_test(NAME scip_dd_farmer COMMAND $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) + add_test(NAME scip_de_farmer COMMAND $ENV{PWD}/src/runDsp --algo de --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) + # add_test(NAME scip_de_noswot COMMAND $ENV{PWD}/src/runDsp --algo de --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -42) + add_test(NAME scip_drbd_drslp COMMAND $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test 5.60247) + add_test(NAME scip_drbd_farmer COMMAND $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108354) + add_test(NAME scip_drbd_sslp_BB COMMAND $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0703) + add_test(NAME scip_drbd_sslp_BC COMMAND $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0705) + add_test(NAME scip_drdd_drslp COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test 5.60247) + add_test(NAME scip_drdd_farmer COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108354) + add_test(NAME scip_drdd_sslp_BB COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0705) + add_test(NAME scip_drdd_sslp_BC COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0705) + # add_test(NAME scip_drbd_sslp_CC COMMAND $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -194.836) + add_test(NAME scip_drdd_sslp_CC COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -194.811) + add_test(NAME scip_dw_farmer COMMAND $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) if(MA27LIB) - add_test(NAME ooqp_farmer_dd COMMAND $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_ooqp.txt --test -108389.9994043) + add_test(NAME ooqp_dd_farmer COMMAND $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_ooqp.txt --test -108389.9994043) endif(MA27LIB) endif(SCIPLIB) if(CPLEXLIB) - add_test(NAME cpx_farmer_de COMMAND $ENV{PWD}/src/runDsp --algo de --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108389.9994043) - add_test(NAME cpx_farmer_dd COMMAND $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108389.9994043) - add_test(NAME cpx_farmer_dw COMMAND $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108389.9994043) - add_test(NAME cpx_farmer_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108354) - add_test(NAME cpx_drslp_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test 5.60247) - add_test(NAME cpx_sslp_BB_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -98.0703) - add_test(NAME cpx_sslp_BC_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -98.0705) - add_test(NAME cpx_sslp_CC_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -194.811) - add_test(NAME cpx_noswot_de COMMAND $ENV{PWD}/src/runDsp --algo de --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -42) - add_test(NAME cpx_noswot_dw COMMAND $ENV{PWD}/src/runDsp --algo dw --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -42) + add_test(NAME cpx_de_farmer COMMAND $ENV{PWD}/src/runDsp --algo de --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108389.9994043) + add_test(NAME cpx_dd_farmer COMMAND $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108389.9994043) + add_test(NAME cpx_drdd_drslp COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test 5.60247) + add_test(NAME cpx_drdd_farmer COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108354) + add_test(NAME cpx_drdd_sslp_BB COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -98.0703) + add_test(NAME cpx_drdd_sslp_BC COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -98.0705) + add_test(NAME cpx_drdd_sslp_CC COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -194.811) + add_test(NAME cpx_dw_farmer COMMAND $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108389.9994043) + # add_test(NAME cpx_de_noswot COMMAND $ENV{PWD}/src/runDsp --algo de --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -42) + # add_test(NAME cpx_dw_noswot COMMAND $ENV{PWD}/src/runDsp --algo dw --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -42) endif(CPLEXLIB) if(GUROBILIB) - add_test(NAME grb_farmer_de COMMAND $ENV{PWD}/src/runDsp --algo de --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108389.9994043) - add_test(NAME grb_farmer_dd COMMAND $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108389.9994043) - add_test(NAME grb_farmer_dw COMMAND $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108389.9994043) - add_test(NAME grb_drslp_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test 5.60247) - add_test(NAME grb_sslp_BB_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -98.0703) - add_test(NAME grb_sslp_BC_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -98.0705) - add_test(NAME grb_sslp_CC_drdd COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -194.811) - add_test(NAME grb_noswot_de COMMAND $ENV{PWD}/src/runDsp --algo de --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -42) - add_test(NAME grb_noswot_dw COMMAND $ENV{PWD}/src/runDsp --algo dw --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -42) + add_test(NAME grb_de_farmer COMMAND $ENV{PWD}/src/runDsp --algo de --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108389.9994043) + add_test(NAME grb_dd_farmer COMMAND $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108389.9994043) + add_test(NAME grb_drdd_drslp COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test 5.60247) + add_test(NAME grb_drdd_farmer COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108354) + add_test(NAME grb_drdd_sslp_BB COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -98.0703) + add_test(NAME grb_drdd_sslp_BC COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -98.0705) + add_test(NAME grb_drdd_sslp_CC COMMAND $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -194.811) + add_test(NAME grb_dw_farmer COMMAND $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108389.9994043) + # add_test(NAME grb_noswot_de COMMAND $ENV{PWD}/src/runDsp --algo de --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -42) + # add_test(NAME grb_noswot_dw COMMAND $ENV{PWD}/src/runDsp --algo dw --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -42) endif(GUROBILIB) if (MPI_CXX_FOUND) if(SCIPLIB) - add_test(NAME scip_farmer_dd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) - add_test(NAME scip_farmer_dw_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) - add_test(NAME scip_farmer_bd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo bd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) - add_test(NAME scip_farmer_drbd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108354) - add_test(NAME scip_sslp_bd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo bd --smps ${CMAKE_SOURCE_DIR}/examples/smps/sslp_5_25_50 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -121.6) - add_test(NAME scip_sslp_BB_drbd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0703) - add_test(NAME scip_sslp_BC_drbd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0705) - add_test(NAME scip_sslp_CC_drbd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -194.811) - add_test(NAME scip_drslp_drbd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test 5.60247) - # add_test(NAME scip_noswot_dw_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -42) + add_test(NAME scip_bd_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo bd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) + add_test(NAME scip_bd_mpi_sslp COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo bd --smps ${CMAKE_SOURCE_DIR}/examples/smps/sslp_5_25_50 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -121.6) + add_test(NAME scip_dd_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) + add_test(NAME scip_drbd_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108354) + add_test(NAME scip_drbd_mpi_sslp_BB COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0703) + add_test(NAME scip_drbd_mpi_sslp_BC COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0705) + add_test(NAME scip_drbd_mpi_sslp_CC COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -194.811) + add_test(NAME scip_drbd_mpi_drslp COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test 5.60247) + add_test(NAME scip_drdd_mpi_drslp COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test 5.60247) + add_test(NAME scip_drdd_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108354) + add_test(NAME scip_drdd_mpi_sslp_BB COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0705) + add_test(NAME scip_drdd_mpi_sslp_BC COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -98.0705) + # add_test(NAME scip_drbd_mpi_sslp_CC COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drbd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -194.836) + add_test(NAME scip_drdd_mpi_sslp_CC COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -194.811) + add_test(NAME scip_dw_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -108389.9994043) + # add_test(NAME scip_dw_mpi_noswot COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_scip.txt --test -42) if(MA27LIB) - add_test(NAME ooqp_farmer_dd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_ooqp.txt --test -108389.9994043) - add_test(NAME ooqp_farmer_dd_mpi_async COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_async_dd.txt --test -108389.9994043) + add_test(NAME ooqp_dd_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_ooqp.txt --test -108389.9994043) + add_test(NAME ooqp_dd_mpi_farmer_async COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_async_dd.txt --test -108389.9994043) endif(MA27LIB) endif(SCIPLIB) if(CPLEXLIB) - add_test(NAME cpx_farmer_dd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108389.9994043) - add_test(NAME cpx_farmer_dw_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108389.9994043) - add_test(NAME cpx_noswot_dw_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -42) + add_test(NAME cpx_dd_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108389.9994043) + add_test(NAME cpx_drdd_mpi_drslp COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test 5.60247) + add_test(NAME cpx_drdd_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108354) + add_test(NAME cpx_drdd_mpi_sslp_BB COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -98.0703) + add_test(NAME cpx_drdd_mpi_sslp_BC COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -98.0705) + add_test(NAME cpx_drdd_mpi_sslp_CC COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -194.811) + add_test(NAME cpx_dw_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -108389.9994043) + # add_test(NAME cpx_dw_mpi_noswot COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_cpx.txt --test -42) endif(CPLEXLIB) if(GUROBILIB) - add_test(NAME grb_farmer_dd_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108389.9994043) - add_test(NAME grb_farmer_dw_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108389.9994043) - add_test(NAME grb_noswot_dw_mpi COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -42) + add_test(NAME grb_dd_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108389.9994043) + add_test(NAME grb_drdd_mpi_drslp COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/drslp_5_5_5_5 --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test 5.60247) + add_test(NAME grb_drdd_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --wassnorm 2 --wasseps 0.1 --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108354) + add_test(NAME grb_drdd_mpi_sslp_BB COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BB --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -98.0703) + add_test(NAME grb_drdd_mpi_sslp_BC COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_BC --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -98.0705) + add_test(NAME grb_drdd_mpi_sslp_CC COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo drdd --smps ${CMAKE_SOURCE_DIR}/examples/dro/sslp_5_25_15_CC --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -194.811) + add_test(NAME grb_dw_mpi_farmer COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --smps ${CMAKE_SOURCE_DIR}/examples/smps/farmer --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -108389.9994043) + # add_test(NAME grb_dw_mpi_noswot COMMAND mpiexec -np 3 $ENV{PWD}/src/runDsp --algo dw --mps ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.mps --dec ${CMAKE_SOURCE_DIR}/examples/mps-dec/noswot.dec --param ${CMAKE_SOURCE_DIR}/test/params_grb.txt --test -42) endif(GUROBILIB) endif(MPI_CXX_FOUND) \ No newline at end of file