source: trunk/Bonmin/experimental/Bcp/BM_pack.cpp @ 530

Last change on this file since 530 was 530, checked in by ladanyi, 13 years ago

prepare Bcp for changing some LPs into TM storage places. Serial version works, currently debugging parallel version.

  • Property svn:eol-style set to native
  • Property svn:keywords set to "Author Date Id Revision"
File size: 9.7 KB
Line 
1// (C) Copyright International Business Machines Corporation and Carnegie Mellon University 2006, 2007
2// All Rights Reserved.
3// This code is published under the Common Public License.
4//
5// Authors :
6// Laszlo Ladanyi, International Business Machines Corporation
7
8#include "BM.hpp"
9#include "BCP_lp.hpp"
10
11#include "BonAmplSetup.hpp"
12
13//#############################################################################
14
15void
16BM_lp::pack_feasible_solution(BCP_buffer& buf, const BCP_solution* sol)
17{
18    const BM_solution* bs = dynamic_cast<const BM_solution*>(sol);
19    if (!bs) {
20        throw BCP_fatal_error("Trying to pack non-BM_solution.\n");
21    }
22    buf.pack(bs->_objective);
23    buf.pack(bs->_ind);
24    buf.pack(bs->_values);
25}
26
27/****************************************************************************/
28
29BCP_solution*
30BM_tm::unpack_feasible_solution(BCP_buffer& buf)
31{
32    BM_solution* bs = new BM_solution;
33    buf.unpack(bs->_objective);
34    buf.unpack(bs->_ind);
35    buf.unpack(bs->_values);
36    return bs;
37}
38
39//#############################################################################
40
41void
42BM_tm::pack_module_data(BCP_buffer& buf, BCP_process_t ptype)
43{
44    // possible process types looked up in BCP_enum_process_t.hpp
45    switch (ptype) {
46    case BCP_ProcessType_LP:
47        par.pack(buf);
48        buf.pack(nl_file_content);
49        buf.pack(ipopt_file_content);
50        break;
51    default:
52        abort();
53    }
54}
55
56/****************************************************************************/
57
58void
59BM_lp::unpack_module_data(BCP_buffer& buf)
60{
61    using namespace Bonmin;
62
63    par.unpack(buf);
64    buf.unpack(nl_file_content);
65    buf.unpack(ipopt_file_content);
66
67    char* argv_[3];
68    char** argv = argv_;
69    argv[0] = NULL;
70    argv[1] = strdup("dont_even_try_to_open_it.nl");
71    argv[2] = NULL;
72    std::string ipopt_content(ipopt_file_content.c_str());
73    std::string nl_content(nl_file_content.c_str());
74
75    /* PIERRE create the setup for algorithm, last argument indicates that
76      continuous relaxation should not be created.*/
77    bonmin_.initializeBonmin(argv, ipopt_content, nl_content, false);
78    bonmin_.nonlinearSolver()->Set_expose_warm_start(true);
79    babSolver_.setSolver(bonmin_.nonlinearSolver());
80
81    free(argv[1]);
82    if (! get_param(BCP_lp_par::MessagePassingIsSerial) &&
83        bonmin_.getAlgorithm() == 0 /* pure B&B */ &&
84        par.entry(BM_par::WarmStartStrategy) == WarmStartFromParent) {
85        printf("\
86BM: WarmStartFromParent is not supported for pure B&B in parallel env.\n");
87        printf("\
88BM: Switching to WarmStartFromRoot.\n");
89        par.set_entry(BM_par::WarmStartStrategy, WarmStartFromRoot);
90    }
91
92    /* synchronize bonmin & BCP parameters */
93    Ipopt::SmartPtr<Ipopt::OptionsList> options = bonmin_.options();
94
95    /** update getting options directly from setup and store them in vars
96        local to the BM_lp object */
97    integerTolerance_ = bonmin_.getDoubleParameter(BabSetupBase::IntTol);
98    // cutOffDecrement_ could be negative
99    cutOffDecrement_ = bonmin_.getDoubleParameter(BabSetupBase::CutoffDecr);
100
101    BCP_lp_prob* bcp_lp = getLpProblemPointer();
102    const double bcp_intTol = bcp_lp->par.entry(BCP_lp_par::IntegerTolerance);
103    const double bcp_cutoffIncr = bcp_lp->par.entry(BCP_lp_par::Granularity);
104
105    if (fabs(integerTolerance_ - bcp_intTol) > 1e-10) {
106        printf("WARNING!\n");
107        printf("   The integrality tolerance parameters are different for\n");
108        printf("   BCP (%f) and bonmin (%f). They should be identical.\n",
109               bcp_intTol, integerTolerance_);
110        printf("   For now both will be set to that of bonmin.\n");
111    }
112    if (fabs(cutOffDecrement_ - cutOffDecrement_) > 1e-10) {
113        printf("WARNING!\n");
114        printf("   The granularity (cutoff increment) parameters are different\n");
115        printf("   BCP (%f) and bonmin (%f). They should be identical.\n",
116               bcp_cutoffIncr, cutOffDecrement_);
117        printf("   For now both will be set to that of bonmin.\n");
118    }
119    bcp_lp->par.set_entry(BCP_lp_par::IntegerTolerance, integerTolerance_);
120    bcp_lp->par.set_entry(BCP_lp_par::Granularity, cutOffDecrement_);
121
122    /* Store a few more options in vars local to the BM_lp object */
123
124    // Getting the options for the choose variable object
125    if (!options->GetEnumValue("varselect_stra",varselect_,"bonmin.")) {
126      // For Bcp, we change the default to most-fractional for now
127      varselect_ = Bonmin::OsiTMINLPInterface::MOST_FRACTIONAL;
128    }
129    options->GetIntegerValue("number_ecp_rounds", numEcpRounds_,"bonmin.");
130    options->GetIntegerValue("number_strong_branch",numberStrong_,"bonmin.");
131    options->GetIntegerValue("number_before_trust", minReliability_,"bonmin.");
132    delete chooseVar_;
133    chooseVar_ = NULL;
134
135
136    /* If pure BB is selected then a number of BCP parameters are changed */
137    if (bonmin_.getAlgorithm() == 0 /* pure B&B */) {
138        /* disable strong branching */
139        bcp_lp->par.set_entry(BCP_lp_par::MaxPresolveIter, -1);
140        /* disable a bunch of printing, all of which are meaningless, since the
141           LP relaxation is meaningless */
142        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_LpSolutionValue, false);
143        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_FinalRelaxedSolution, false);
144        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_RelaxedSolution, false);
145        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_ReportLocalCutPoolSize, false);
146        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_ReportLocalVarPoolSize, false);
147        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_GeneratedCutCount, false);
148        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_GeneratedVarCount, false);
149        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_IterationCount, false);
150        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_RowEffectivenessCount, false);
151        //  bcp_lp->par.set_entry(BCP_lp_par::LpVerb_FathomInfo, false);
152    } else {
153#if 0 // Pierre cut generators have already been initialized
154        /* for hybrid: initialize the cut generators */
155
156        /* NOTE:
157           
158           if the localSerchSolver for oaDec_ is NULL, that will force the cut
159           generator to create a clone of the solverinterface in bcp and use
160           that to solve the milp subproblem.
161
162           If localSearchSolver is set then if it is *not* the same as bcp's
163           solverinterface then bcp's si's data gets copied into
164           localsearchsolver when the milp is solvede.
165
166           Finally, if localSearchSolver is set and it is the same as bcp's
167           si, then bcp's si will be modified by the oaDec_. A big NO-NO!
168           Fortunately, this will never happen as in each search tree node bcp
169           creates a clone of the master lp.
170        */
171        OsiSolverInterface * localSearchSolver = NULL;
172        if (minlpParams_.milpSubSolver == 2) {/* try to use cplex */
173#ifdef COIN_HAS_CPX
174            localSearchSolver = new OsiCpxSolverInterface;
175            nlpSolver->extractLinearRelaxation(*localSearchSolver);
176#else
177            std::cerr << "You have set an option to use CPLEX as the milp\n"
178                      << "subsolver in oa decomposition. However, apparently\n"
179                      << "CPLEX is not configured to be used in bonmin.\n"
180                      << "See the manual for configuring CPLEX\n";
181            throw -1;
182#endif
183        }
184        Bonmin::initializeCutGenerators(minlpParams_, &nlp_,
185                                        miGGen_, probGen_,
186                                        knapsackGen_, mixedGen_,
187                                        oaGen_, ecpGen_,
188                                        oaDec_, localSearchSolver,
189                                        feasCheck_, NULL
190                                        );
191#else
192  //Check if OA decomposition is in cut generators and remove it
193    for(BabSetupBase::CuttingMethods::iterator i = bonmin_.cutGenerators().begin() ;
194        i != bonmin_.cutGenerators().end() ; i++){
195      OACutGenerator2 * oaDec = dynamic_cast<OACutGenerator2 *> (i->cgl);
196      if(oaDec)//Disable it
197      {
198        i->frequency = 0;
199      }
200    }
201#endif
202    }
203
204    /* extract the sos constraints */
205Bonmin::OsiTMINLPInterface& nlp = *bonmin_.nonlinearSolver();
206const Bonmin::TMINLP::SosInfo * sos = nlp.model()->sosConstraints();
207   
208    int i;
209    const int numCols = nlp.getNumCols();
210    const double* clb = nlp.getColLower();
211    const double* cub = nlp.getColUpper();
212
213    /* Find first the integer variables and then the SOS constraints */
214    int nObj = 0;
215    OsiObject** osiObj = new OsiObject*[numCols + sos->num];
216    for (i = 0; i < numCols; ++i) {
217        if (nlp.isInteger(i)) {
218            osiObj[nObj++] = new OsiSimpleInteger(i, clb[i], cub[i]);
219        }
220    }
221    const int* starts = sos->starts;
222    for (i = 0; i < sos->num; ++i) {
223        OsiSOS* so = new OsiSOS(NULL, /* FIXME: why does the constr need */
224                                starts[i+1] - starts[i],
225                                sos->indices + starts[i],
226                                sos->weights + starts[i],
227                                sos->types[i]);
228        // FIXME: this should go when SOS object can get a priority
229        so->setPriority(1);
230        osiObj[nObj++] = so;
231       
232    }
233    nlp.addObjects(nObj, osiObj);
234    for (i = 0; i < nObj; ++i) {
235        delete osiObj[i];
236    }
237    delete[] osiObj;
238
239    /* just to be on the safe side... always allocate */
240    primal_solution_ = new double[nlp.getNumCols()];
241
242    /* solve the initial nlp to get warmstart info in the root */
243    nlp.initialSolve();
244    ws_ = nlp.getWarmStart();
245    if (get_param(BCP_lp_par::MessagePassingIsSerial) &&
246        par.entry(BM_par::WarmStartStrategy) == WarmStartFromParent) {
247        warmStart[0] = ws_;
248        ws_ = NULL;
249    }
250}
251
252//#############################################################################
253
254void
255BM_pack::pack_user_data(const BCP_user_data* ud, BCP_buffer& buf)
256{
257    const BM_node* data = dynamic_cast<const BM_node*>(ud);
258    data->pack(buf);
259}
260
261/*---------------------------------------------------------------------------*/
262
263BCP_user_data*
264BM_pack::unpack_user_data(BCP_buffer& buf)
265{
266    return new BM_node(buf);
267}
268
269/*---------------------------------------------------------------------------*/
270
271void
272BM_pack::pack_cut_algo(const BCP_cut_algo* cut, BCP_buffer& buf)
273{
274    const BB_cut* bb_cut = dynamic_cast<const BB_cut*>(cut);
275    if (!bb_cut)
276        throw BCP_fatal_error("pack_cut_algo() : unknown cut type!\n");
277    bb_cut->pack(buf);
278}
279
280/*---------------------------------------------------------------------------*/
281BCP_cut_algo* BM_pack::unpack_cut_algo(BCP_buffer& buf)
282{
283    return new BB_cut(buf);
284}
Note: See TracBrowser for help on using the repository browser.