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

Last change on this file since 508 was 508, checked in by pbonami, 13 years ago

Make bcp-bonmin work with new setup

  • Property svn:eol-style set to native
  • Property svn:keywords set to "Author Date Id Revision"
File size: 10.4 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
9#include "BM.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 continuous relaxation
76      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
82   
83    free(argv[1]);
84    if (! get_param(BCP_lp_par::MessagePassingIsSerial) &&
85        bonmin_.getAlgorithm() == 0 /* pure B&B */ &&
86        par.entry(BM_par::WarmStartStrategy) == WarmStartFromParent) {
87        printf("\
88BM: WarmStartFromParent is not supported for pure B&B in parallel env.\n");
89        printf("\
90BM: Switching to WarmStartFromRoot.\n");
91        par.set_entry(BM_par::WarmStartStrategy, WarmStartFromRoot);
92    }
93
94    /* synchronize bonmin & BCP parameters */
95    Ipopt::SmartPtr<Ipopt::OptionsList> options = bonmin_.options();
96
97    /* PIERRE This should be already done with new code.
98    int nlpLogLevel;
99    options->GetIntegerValue("nlp_log_level", nlpLogLevel, "bonmin.");
100    nlp_.messageHandler()->setLogLevel(nlpLogLevel);
101*/
102    /** update getting options directly from setup*/
103    double bm_intTol = bonmin_.getDoubleParameter(BabSetupBase::IntTol);
104    double bm_cutoffIncr = bonmin_.getDoubleParameter(BabSetupBase::CutoffDecr); // could be negative
105//PIERRE deprecated    options->GetNumericValue("integer_tolerance",bm_intTol,"bonmin.");
106//PIERRE deprecated    options->GetNumericValue("cutoff_decr",bm_cutoffIncr,"bonmin.");
107
108    BCP_lp_prob* bcp_lp = getLpProblemPointer();
109    const double bcp_intTol = bcp_lp->par.entry(BCP_lp_par::IntegerTolerance);
110    const double bcp_cutoffIncr = bcp_lp->par.entry(BCP_lp_par::Granularity);
111
112    if (fabs(bm_intTol - bcp_intTol) > 1e-10) {
113        printf("WARNING!\n");
114        printf("   The integrality tolerance parameters are different for\n");
115        printf("   BCP (%f) and bonmin (%f). They should be identical.\n",
116               bcp_intTol, bm_intTol);
117        printf("   For now both will be set to that of bonmin.\n");
118    }
119    if (fabs(bm_cutoffIncr - bcp_cutoffIncr) > 1e-10) {
120        printf("WARNING!\n");
121        printf("   The granularity (cutoff increment) parameters are different\n");
122        printf("   BCP (%f) and bonmin (%f). They should be identical.\n",
123               bcp_cutoffIncr, bm_cutoffIncr);
124        printf("   For now both will be set to that of bonmin.\n");
125    }
126    bcp_lp->par.set_entry(BCP_lp_par::IntegerTolerance, bm_intTol);
127    bcp_lp->par.set_entry(BCP_lp_par::Granularity, bm_cutoffIncr);
128
129    /* Store a few options in local variables */
130
131    /** update getting options directly from setup*/
132    double integerTolerance_ = bonmin_.getDoubleParameter(BabSetupBase::IntTol);
133    double cutOffDecrement_ = bonmin_.getDoubleParameter(BabSetupBase::CutoffDecr); 
134   
135    //PIERRE deprecated    options->GetNumericValue("integer_tolerance",integerTolerance_,"bonmin.");
136    //PIERRE deprecated    options->GetNumericValue("cutoff_decr",cutOffDecrement_,"bonmin.");
137   
138    // Getting the options for the choose variable object
139    if (!options->GetEnumValue("varselect_stra",varselect_,"bonmin.")) {
140      // For Bcp, we change the default to most-fractional for now
141      varselect_ = Bonmin::OsiTMINLPInterface::MOST_FRACTIONAL;
142    }
143    options->GetIntegerValue("number_ecp_rounds", numEcpRounds_,"bonmin.");
144    options->GetIntegerValue("number_strong_branch",numberStrong_,"bonmin.");
145    options->GetIntegerValue("number_before_trust", minReliability_,"bonmin.");
146    delete chooseVar_;
147    chooseVar_ = NULL;
148
149
150    /* If pure BB is selected then a number of BCP parameters are changed */
151    if (bonmin_.getAlgorithm() == 0 /* pure B&B */) {
152        /* disable strong branching */
153        bcp_lp->par.set_entry(BCP_lp_par::MaxPresolveIter, -1);
154        /* disable a bunch of printing, all of which are meaningless, since the
155           LP relaxation is meaningless */
156        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_LpSolutionValue, false);
157        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_FinalRelaxedSolution, false);
158        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_RelaxedSolution, false);
159        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_ReportLocalCutPoolSize, false);
160        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_ReportLocalVarPoolSize, false);
161        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_GeneratedCutCount, false);
162        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_GeneratedVarCount, false);
163        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_IterationCount, false);
164        bcp_lp->par.set_entry(BCP_lp_par::LpVerb_RowEffectivenessCount, false);
165        //  bcp_lp->par.set_entry(BCP_lp_par::LpVerb_FathomInfo, false);
166    } else {
167#if 0 // Pierre cut generators have already been initialized
168        /* for hybrid: initialize the cut generators */
169
170        /* NOTE:
171           
172           if the localSerchSolver for oaDec_ is NULL, that will force the cut
173           generator to create a clone of the solverinterface in bcp and use
174           that to solve the milp subproblem.
175
176           If localSearchSolver is set then if it is *not* the same as bcp's
177           solverinterface then bcp's si's data gets copied into
178           localsearchsolver when the milp is solvede.
179
180           Finally, if localSearchSolver is set and it is the same as bcp's
181           si, then bcp's si will be modified by the oaDec_. A big NO-NO!
182           Fortunately, this will never happen as in each search tree node bcp
183           creates a clone of the master lp.
184        */
185        OsiSolverInterface * localSearchSolver = NULL;
186        if (minlpParams_.milpSubSolver == 2) {/* try to use cplex */
187#ifdef COIN_HAS_CPX
188            localSearchSolver = new OsiCpxSolverInterface;
189            nlpSolver->extractLinearRelaxation(*localSearchSolver);
190#else
191            std::cerr << "You have set an option to use CPLEX as the milp\n"
192                      << "subsolver in oa decomposition. However, apparently\n"
193                      << "CPLEX is not configured to be used in bonmin.\n"
194                      << "See the manual for configuring CPLEX\n";
195            throw -1;
196#endif
197        }
198        Bonmin::initializeCutGenerators(minlpParams_, &nlp_,
199                                        miGGen_, probGen_,
200                                        knapsackGen_, mixedGen_,
201                                        oaGen_, ecpGen_,
202                                        oaDec_, localSearchSolver,
203                                        feasCheck_, NULL
204                                        );
205#else
206  //Check if OA decomposition is in cut generators and remove it
207    for(BabSetupBase::CuttingMethods::iterator i = bonmin_.cutGenerators().begin() ;
208        i != bonmin_.cutGenerators().end() ; i++){
209      OACutGenerator2 * oaDec = dynamic_cast<OACutGenerator2 *> (i->cgl);
210      if(oaDec)//Disable it
211      {
212        i->frequency = 0;
213      }
214    }
215#endif
216    }
217
218    /* extract the sos constraints */
219Bonmin::OsiTMINLPInterface& nlp = *bonmin_.nonlinearSolver();
220const Bonmin::TMINLP::SosInfo * sos = nlp.model()->sosConstraints();
221   
222    int i;
223    const int numCols = nlp.getNumCols();
224    const double* clb = nlp.getColLower();
225    const double* cub = nlp.getColUpper();
226
227    /* Find first the integer variables and then the SOS constraints */
228    int nObj = 0;
229    OsiObject** osiObj = new OsiObject*[numCols + sos->num];
230    for (i = 0; i < numCols; ++i) {
231        if (nlp.isInteger(i)) {
232            osiObj[nObj++] = new OsiSimpleInteger(i, clb[i], cub[i]);
233        }
234    }
235    const int* starts = sos->starts;
236    for (i = 0; i < sos->num; ++i) {
237        OsiSOS* so = new OsiSOS(NULL, /* FIXME: why does the constr need */
238                                starts[i+1] - starts[i],
239                                sos->indices + starts[i],
240                                sos->weights + starts[i],
241                                sos->types[i]);
242        // FIXME: this should go when SOS object can get a priority
243        so->setPriority(1);
244        osiObj[nObj++] = so;
245       
246    }
247    nlp.addObjects(nObj, osiObj);
248    for (i = 0; i < nObj; ++i) {
249        delete osiObj[i];
250    }
251    delete[] osiObj;
252
253    /* just to be on the safe side... always allocate */
254    primal_solution_ = new double[nlp.getNumCols()];
255
256    /* solve the initial nlp to get warmstart info in the root */
257    nlp.initialSolve();
258    ws_ = nlp.getWarmStart();
259    if (get_param(BCP_lp_par::MessagePassingIsSerial) &&
260        par.entry(BM_par::WarmStartStrategy) == WarmStartFromParent) {
261        warmStart[0] = ws_;
262        ws_ = NULL;
263    }
264}
265
266//#############################################################################
267
268void
269BM_tm::pack_user_data(const BCP_user_data* ud, BCP_buffer& buf)
270{
271    const BM_node* data = dynamic_cast<const BM_node*>(ud);
272    data->pack(buf);
273}
274
275/*---------------------------------------------------------------------------*/
276
277BCP_user_data*
278BM_tm::unpack_user_data(BCP_buffer& buf)
279{
280    return new BM_node(buf);
281}
282
283/*****************************************************************************/
284
285void
286BM_lp::pack_user_data(const BCP_user_data* ud, BCP_buffer& buf)
287{
288    const BM_node* data = dynamic_cast<const BM_node*>(ud);
289    data->pack(buf);
290}
291
292/*---------------------------------------------------------------------------*/
293
294BCP_user_data*
295BM_lp::unpack_user_data(BCP_buffer& buf)
296{
297    BM_node* data = new BM_node(buf);
298    numNlpFailed_ = data->numNlpFailed_;
299    return data;
300}
301
302//#############################################################################
Note: See TracBrowser for help on using the repository browser.