00001
00007 #ifdef COIN_USE_DYLP
00008
00009 #ifdef _MSC_VER
00010
00011
00012 # pragma warning(disable:4786)
00013
00014
00015
00016
00017
00018
00019 # define assert_same
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #endif
00031
00032
00033
00034 #define ODSI OsiDylpSolverInterface
00035 #define OSI OsiSolverInterface
00036
00135 namespace {
00136 char sccsid[] = "%W% %G%" ;
00137 char cvsid[] = "$Id: OsiDylpSolverInterface.cpp,v 1.22 2003/10/27 18:55:31 jpfasano Exp $" ;
00138 }
00139
00140 #include <string>
00141 #include <cassert>
00142 #include <OsiColCut.hpp>
00143 #include <OsiRowCut.hpp>
00144 #include <OsiRowCutDebugger.hpp>
00145 #include "OsiDylpSolverInterface.hpp"
00146 #include "OsiDylpMessages.hpp"
00147 #include "OsiDylpWarmStartBasis.hpp"
00148
00149 using std::string ;
00150 using std::vector ;
00151
00152
00153 extern "C"
00154 {
00155
00156 #include "bonsai.h"
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 #define DYLP_INFINITY HUGE_VAL
00168
00169
00170 #ifndef ERRMSGDIR
00171 # define ERRMSGDIR "."
00172 #endif
00173
00174
00175 extern bool dy_mpsin(const char *filename, consys_struct **consys) ;
00176 extern void dy_initbasis(int concnt, int factor_freq, double zero_tol) ;
00177 extern void dy_freebasis() ;
00178
00179
00180
00181
00182
00183
00184
00185
00186 extern char *stralloc(const char *str) ;
00187 extern void strfree(const char *str) ;
00188
00189 }
00190
00233 ioid cmdchn = IOID_NOSTRM,
00234 logchn = IOID_NOSTRM ;
00235
00236 bool cmdecho = false,
00237 gtxecho = false ;
00238
00240
00276 int ODSI::reference_count = 0 ;
00277 bool ODSI::basis_ready = false ;
00278 ODSI *ODSI::dylp_owner = 0 ;
00279
00281
00282
00283
00295
00298 inline int ODSI::idx (int i) { return i+1 ; }
00299
00306 template<class T> inline T* ODSI::idx_vec (T* vec) { return vec-1 ; }
00307
00310 inline int ODSI::inv (int i) { return i-1 ; }
00311
00318 template<class T> inline T* ODSI::inv_vec (T* vec) { return vec+1 ; }
00319
00320
00321
00322
00323
00324
00325 #ifdef _MSC_VER
00326 # define IDX_VEC(zz_type_zz,zz_vec_zz) (zz_vec_zz-1)
00327 # define INV_VEC(zz_type_zz,zz_vec_zz) (zz_vec_zz+1)
00328 #else
00329 # define IDX_VEC(zz_type_zz,zz_vec_zz) idx_vec<zz_type_zz>(zz_vec_zz)
00330 # define INV_VEC(zz_type_zz,zz_vec_zz) inv_vec<zz_type_zz>(zz_vec_zz)
00331 #endif
00332
00342 pkvec_struct* ODSI::packed_vector (const CoinShallowPackedVector src,
00343 int dimension)
00344
00345 { int n = src.getNumElements() ;
00346 pkvec_struct* dst = pkvec_new(n) ;
00347
00348 assert(dst) ;
00349
00350 if (n == 0) return (dst) ;
00351
00352 packed_vector(src,dimension,dst) ;
00353
00354 return (dst) ; }
00355
00356
00365 void ODSI::packed_vector (const CoinShallowPackedVector src, int dimension,
00366 pkvec_struct *dst)
00367
00368 { int n = src.getNumElements() ;
00369
00370 dst->cnt = n ;
00371 dst->dim = dimension ;
00372
00373 if (n == 0) return ;
00374
00375 const int* indices = src.getIndices() ;
00376 const double* elements = src.getElements() ;
00377 pkcoeff_struct* coeffs = dst->coeffs ;
00378
00379 for (int i = 0 ; i < n ; i++)
00380 { coeffs[i].ndx = idx(indices[i]) ;
00381 coeffs[i].val = elements[i] ; }
00382
00383 return ; }
00384
00385
00387
00388
00389
00396
00397
00398
00404 template<class T> inline T* ODSI::copy (const T* src)
00405
00406 { if (!src) return 0 ;
00407 T* dst = new T ;
00408 memcpy(dst, src, sizeof(T)) ;
00409 return dst ;
00410 }
00411
00412 #ifdef _MSC_VER
00413 # define CLONE(zz_type_zz,zz_src_zz,zz_dst_zz) \
00414 if (zz_src_zz) \
00415 { zz_dst_zz = new zz_type_zz ; \
00416 memcpy(zz_dst_zz,zz_src_zz,sizeof(zz_type_zz)) ; } \
00417 else \
00418 { zz_dst_zz = NULL ; }
00419 #else
00420 # define CLONE(zz_type_zz,zz_src_zz,zz_dst_zz) \
00421 zz_dst_zz = copy<zz_type_zz>(zz_src_zz) ;
00422 #endif
00423
00424
00430 template<class T> inline void ODSI::copy (const T* src, T* dst, int n)
00431
00432 { if (!dst || !src || n == 0) return ;
00433 int size = sizeof(T) * n ;
00434 memcpy(dst,src,size) ;
00435 }
00436
00437 #ifdef _MSC_VER
00438 # define COPY_VEC(zz_type_zz,zz_src_zz,zz_dst_zz,zz_n_zz) \
00439 if (zz_dst_zz && zz_src_zz && zz_n_zz > 0 ) \
00440 std::copy(zz_src_zz,zz_src_zz+zz_n_zz,zz_dst_zz)
00441 #else
00442 # define COPY_VEC(zz_type_zz,zz_src_zz,zz_dst_zz,zz_n_zz) \
00443 copy<zz_type_zz>(zz_src_zz,zz_dst_zz,zz_n_zz)
00444 #endif
00445
00446
00452 template<class T> inline T* ODSI::copy (const T* src, int n)
00453
00454 { if (!src || n == 0) return 0 ;
00455 T* dst = new T[n] ;
00456 copy(src, dst, n) ;
00457 return dst ;
00458 }
00459
00460 #ifdef _MSC_VER
00461 # define CLONE_VEC(zz_type_zz,zz_src_zz,zz_dst_zz,zz_n_zz) \
00462 if (zz_src_zz && zz_n_zz > 0) \
00463 { zz_dst_zz = new zz_type_zz[zz_n_zz] ; \
00464 std::copy(zz_src_zz,zz_src_zz+zz_n_zz,zz_dst_zz) ; } \
00465 else \
00466 { zz_dst_zz = NULL ; }
00467 #else
00468 # define CLONE_VEC(zz_type_zz,zz_src_zz,zz_dst_zz,zz_n_zz) \
00469 zz_dst_zz = copy<zz_type_zz>(zz_src_zz,zz_n_zz)
00470 #endif
00471
00472
00473
00474
00475
00482 inline void ODSI::copy_basis (const basis_struct* src, basis_struct* dst)
00483
00484 { if (!src) return ;
00485
00486 dst->len = src->len ;
00487 if (dst->el == 0)
00488 { throw CoinError("No basis element vector",
00489 "copy_basis","OsiDylpSolverInterface") ; }
00490 memcpy(dst->el,src->el,idx(src->len)*sizeof(basisel_struct)) ;
00491
00492 # ifndef NDEBUG
00493 assert_same(*dst, *src, true) ;
00494 # endif
00495
00496 return ; }
00497
00498
00510 inline basis_struct* ODSI::copy_basis (const basis_struct* src, int dstsze)
00511
00512 { if (!src) return 0 ;
00513 basis_struct* dst = new basis_struct ;
00514 dst->el = (basisel_struct *) CALLOC(idx(dstsze),sizeof(basisel_struct)) ;
00515 copy_basis(src,dst) ;
00516 return dst ; }
00517
00518
00533 lpprob_struct* ODSI::copy_lpprob (const lpprob_struct* src)
00534
00535 { if (!src) return 0 ;
00536
00537 int col_count = idx(src->colsze) ;
00538 int row_count = idx(src->rowsze) ;
00539
00540 lpprob_struct* dst = NULL;
00541 CLONE(lpprob_struct,src,dst);
00542
00543 dst->basis = copy_basis(src->basis,row_count) ;
00544 CLONE_VEC(flags,src->status,dst->status,col_count);
00545 CLONE_VEC(double,src->x,dst->x,row_count);
00546 CLONE_VEC(double,src->y,dst->y,row_count);
00547 CLONE_VEC(bool,src->actvars,dst->actvars,col_count);
00548
00549 # ifndef NDEBUG
00550 assert_same(*dst, *src, true) ;
00551 # endif
00552
00553 return dst ; }
00554
00556
00557
00558
00559
00560
00561
00562
00563
00564
00573 inline void ODSI::destruct_col_cache ()
00574
00575 { delete [] _col_x ; _col_x = 0 ;
00576 delete [] _col_obj ; _col_obj = 0 ;
00577 delete [] _col_cbar ; _col_cbar = 0 ;
00578 }
00579
00580
00589 void ODSI::destruct_row_cache ()
00590
00591 { delete [] _row_lhs ; _row_lhs = 0 ;
00592 delete [] _row_lower ; _row_lower = 0 ;
00593 delete [] _row_price ; _row_price = 0 ;
00594 delete [] _row_range ; _row_range = 0 ;
00595 delete [] _row_rhs ; _row_rhs = 0 ;
00596 delete [] _row_sense ; _row_sense = 0 ;
00597 delete [] _row_upper ; _row_upper = 0 ;
00598 }
00599
00608 inline void ODSI::destruct_cache ()
00609
00610 { destruct_row_cache() ;
00611 destruct_col_cache() ;
00612
00613 delete _matrix_by_row ; _matrix_by_row = 0 ;
00614 delete _matrix_by_col ; _matrix_by_col = 0 ;
00615
00616 return ; }
00617
00618
00619
00620
00629
00640 inline contyp_enum ODSI::bound_to_type (double lower, double upper)
00641
00642 {
00643
00644 # include <cfloat>
00645 double inf = DBL_MAX ;
00646
00647 if (upper == lower) return contypEQ ;
00648 bool finite_low = (lower > -inf) ;
00649 bool finite_up = (upper < inf) ;
00650 if (finite_low && finite_up) return contypRNG ;
00651 if (finite_low) return contypGE ;
00652 if (finite_up) return contypLE ;
00653 return contypNB ; }
00654
00655
00658 inline contyp_enum ODSI::sense_to_type (char sense)
00659
00660 { switch (sense)
00661 { case 'E': return contypEQ ;
00662 case 'G': return contypGE ;
00663 case 'L': return contypLE ;
00664 case 'N': return contypNB ;
00665 case 'R': return contypRNG ;
00666 default: { assert(0) ; return contypINV ; } } }
00667
00668
00671 inline char ODSI::type_to_sense (contyp_enum ctypi)
00672
00673 { switch (ctypi)
00674 { case contypNB:
00675 { return 'N' ; }
00676 case contypGE:
00677 { return 'G' ; }
00678 case contypEQ:
00679 { return 'E' ; }
00680 case contypLE:
00681 { return 'L' ; }
00682 case contypRNG:
00683 { return 'R' ; }
00684 case contypINV:
00685 default:
00686 { assert(0) ;
00687 return '?' ; } } }
00688
00689
00697 inline void
00698 ODSI::gen_rowiparms (contyp_enum* ctypi, double* rhsi, double* rhslowi,
00699 char sensei, double rhsini, double rangei)
00700
00701 { *ctypi = sense_to_type(sensei) ;
00702 switch (*ctypi)
00703 { case contypEQ:
00704 { *rhslowi = 0 ;
00705 *rhsi = rhsini ;
00706 break ; }
00707 case contypLE:
00708 { *rhslowi = 0 ;
00709 *rhsi = rhsini ;
00710 break ; }
00711 case contypGE:
00712 { *rhslowi = 0 ;
00713 *rhsi = rhsini ;
00714 break ; }
00715 case contypRNG:
00716 { *rhslowi = rhsini-rangei ;
00717 *rhsi = rhsini ;
00718 break ; }
00719 case contypNB:
00720 { *rhslowi = 0 ;
00721 *rhsi = 0 ;
00722 break ; }
00723 default:
00724 { assert(false) ; } }
00725
00726 return ; }
00727
00728
00736 inline void
00737 ODSI::gen_rowiparms (contyp_enum* ctypi, double* rhsi, double* rhslowi,
00738 double rowlbi, double rowubi)
00739
00740 { *ctypi = bound_to_type(rowlbi,rowubi) ;
00741 switch (*ctypi)
00742 { case contypEQ:
00743 case contypLE:
00744 { *rhslowi = 0 ;
00745 *rhsi = rowubi ;
00746 break ; }
00747 case contypGE:
00748 { *rhslowi = 0 ;
00749 *rhsi = rowlbi ;
00750 break ; }
00751 case contypRNG:
00752 { *rhslowi = rowlbi ;
00753 *rhsi = rowubi ;
00754 break ; }
00755 case contypNB:
00756 { *rhslowi = 0 ;
00757 *rhsi = 0 ;
00758 break ; }
00759 default:
00760 { assert(false) ; } }
00761
00762 return ; }
00763
00764
00775 void ODSI::add_col (const CoinPackedVectorBase& coin_colj,
00776 vartyp_enum vtypj, double vlbj, double vubj, double objj)
00777
00778 { pkvec_struct *pk_colj = packed_vector(coin_colj,getNumRows()) ;
00779
00780
00781
00782
00783 if (!consys) construct_consys(0,0) ;
00784
00785
00786
00787 bool r = consys_addcol_pk(consys,vtypj,pk_colj,objj,vlbj,vubj) ;
00788 pkvec_free(pk_colj) ;
00789 assert(r) ;
00790
00791
00792
00793 resolveOptions->forcewarm = true ;
00794
00795 destruct_cache() ; }
00796
00797
00807 void ODSI::add_row (const CoinPackedVectorBase &coin_rowi, char clazzi,
00808 contyp_enum ctypi, double rhsi, double rhslowi)
00809
00810 { pkvec_struct *pk_rowi = packed_vector(coin_rowi,getNumCols()) ;
00811
00812
00813
00814
00815 if (!consys) construct_consys(0,0) ;
00816
00817
00818
00819 bool r = consys_addrow_pk(consys,clazzi,ctypi,pk_rowi,rhsi,rhslowi,0,0) ;
00820 pkvec_free(pk_rowi) ;
00821 assert(r) ;
00822
00823
00824
00825 resolveOptions->forcewarm = true ;
00826
00827 destruct_cache() ; }
00828
00829
00840 void ODSI::worst_case_primal ()
00841
00842 {
00843
00844
00845
00846
00847 int n = getNumCols() ;
00848 if (n == 0) return ;
00849 assert(consys && consys->obj && consys->vub && consys->vlb) ;
00850
00851 double *obj = consys->obj ;
00852 double *vlb = consys->vlb ;
00853 double *vub = consys->vub ;
00854
00855
00856
00857
00858 if (!_col_x) _col_x = new double[n] ;
00859
00860
00861
00862
00863
00864 for (int j = 1 ; j <= n ; j++)
00865 { if (obj[j] > 0)
00866 { _col_x[inv(j)] = vub[j] ; }
00867 else
00868 { _col_x[inv(j)] = vlb[j] ; } }
00869
00870 return ; }
00871
00881 void ODSI::calc_objval ()
00882
00883 { int n = getNumCols() ;
00884
00885
00886
00887
00888 if (n == 0)
00889 { _objval = 0 ;
00890 return ; }
00891
00892
00893
00894
00895 const double *obj = getObjCoefficients() ;
00896 const double *x = getColSolution() ;
00897 _objval = 0.0 ;
00898 for (int j = 0 ; j < n ; j++) _objval += x[j]*obj[j] ;
00899 setcleanzero(_objval,tolerances->cost) ;
00900
00901 return ; }
00902
00903
00904
00906
00907
00908
00909
00910
00911
00914
00921 inline void ODSI::construct_lpprob ()
00922
00923 { lpprob = new lpprob_struct ;
00924 memset(lpprob, 0, sizeof(lpprob_struct)) ;
00925 setflg(lpprob->ctlopts,lpctlNOFREE) ;
00926 lpprob->phase = dyINV ;
00927 lpprob->consys = consys ;
00928 lpprob->rowsze = consys->rowsze ;
00929 lpprob->colsze = consys->colsze ;
00930
00931 return ; }
00932
00933
00938 inline void ODSI::construct_options ()
00939
00940 {
00941
00942
00943
00944
00945 delete initialSolveOptions ;
00946 initialSolveOptions = new lpopts_struct ;
00947 delete tolerances ;
00948 tolerances = new lptols_struct ;
00949 dy_defaults(&initialSolveOptions,&tolerances) ;
00950 delete resolveOptions ;
00951 CLONE(lpopts_struct,initialSolveOptions,resolveOptions);
00952 dy_setprintopts(0,initialSolveOptions) ;
00953 dy_setprintopts(0,resolveOptions) ;
00954
00955 setIntParam(OsiMaxNumIteration,3*initialSolveOptions->iterlim) ;
00956 setIntParam(OsiMaxNumIterationHotStart,3*initialSolveOptions->iterlim) ;
00957 setDblParam(OsiDualTolerance,tolerances->dfeas_scale*tolerances->cost) ;
00958 setDblParam(OsiPrimalTolerance,tolerances->pfeas_scale*tolerances->zero) ;
00959
00960
00961
00962 initialSolveOptions->forcecold = true ;
00963 initialSolveOptions->fullsys = true ;
00964 resolveOptions->forcecold = false ;
00965 resolveOptions->fullsys = false ;
00966
00967
00968
00969 delete statistics ;
00970 statistics = new lpstats_struct ;
00971 memset(statistics,0,sizeof(lpstats_struct)) ;
00972 }
00973
00982 void ODSI::construct_consys (int cols, int rows)
00983
00984 {
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995 flags parts = CONSYS_OBJ |
00996 CONSYS_VUB | CONSYS_VLB | CONSYS_VTYP |
00997 CONSYS_RHS | CONSYS_RHSLOW | CONSYS_CTYP ;
00998 flags opts = CONSYS_WRNATT ;
00999
01000
01001
01002
01003 consys = consys_create(0,parts,opts,rows,cols) ;
01004 assert(consys) ;
01005
01006 return ; }
01007
01008
01015 void ODSI::dylp_ioinit ()
01016
01017 { if (reference_count > 1) return ;
01018
01019 std::string errfile = std::string(ERRMSGDIR)+std::string("/bonsaierrs.txt") ;
01020 # ifndef NDEBUG
01021 errinit(const_cast<char *>(errfile.c_str()),0,true) ;
01022 # else
01023 errinit(const_cast<char *>(errfile.c_str()),0,false) ;
01024 # endif
01025 bool r1 = ioinit() ;
01026 assert(r1) ;
01027 }
01028
01053 void ODSI::load_problem (const CoinMpsIO &mps)
01054
01055 { int n = mps.getNumCols() ;
01056 int m = mps.getNumRows() ;
01057
01058
01059
01060 const CoinPackedMatrix matrix = *mps.getMatrixByCol() ;
01061 const double* col_lower = mps.getColLower() ;
01062 const double* col_upper = mps.getColUpper() ;
01063 const double* obj = mps.getObjCoefficients() ;
01064 const char *sense = mps.getRowSense() ;
01065 const double* rhsin = mps.getRightHandSide() ;
01066 const double* range = mps.getRowRange() ;
01067
01068 double *rhs = new double[m] ;
01069 double *rhslow = new double[m] ;
01070 contyp_enum *ctyp = new contyp_enum[m] ;
01071
01072 gen_rowparms(m,rhs,rhslow,ctyp,sense,rhsin,range) ;
01073
01074
01075
01076
01077 destruct_problem(true) ;
01078
01079
01080
01081
01082 construct_consys(n,m) ;
01083 setStrParam(OsiProbName,mps.getProblemName()) ;
01084 if (consys->objnme) strfree(consys->objnme) ;
01085 consys->objnme = stralloc(mps.getObjectiveName()) ;
01086 setDblParam(OsiObjOffset,mps.objectiveOffset()) ;
01087
01088
01089
01090 pkvec_struct* rowi = pkvec_new(0) ;
01091 assert(rowi) ;
01092
01093 for (int i = 0 ; i < m ; i++)
01094 { rowi->nme = const_cast<char *>(mps.rowName(i)) ;
01095 bool r = consys_addrow_pk(consys,'a',ctyp[i],rowi,rhs[i],rhslow[i],0,0) ;
01096 assert(r) ; }
01097
01098 if (rowi) pkvec_free(rowi) ;
01099 delete[] rhs ;
01100 delete[] rhslow ;
01101 delete[] ctyp ;
01102
01103
01104
01105
01106
01107
01108 const char *const intvars = mps.integerColumns() ;
01109 vartyp_enum *const vtyp = new vartyp_enum[n] ;
01110 if (intvars)
01111 { for (int j = 0 ; j < n ; j++)
01112 { if (intvars[j])
01113 { if ((col_lower[j] == 0.0 || col_lower[j] == 1.0) &&
01114 (col_upper[j] == 0.0 || col_upper[j] == 1.0))
01115 { vtyp[j] = vartypBIN ; }
01116 else
01117 { vtyp[j] = vartypINT ; } }
01118 else
01119 { vtyp[j] = vartypCON ; } } }
01120 else
01121 { for (int j = 0 ; j < n ; j++) vtyp[j] = vartypCON ; }
01122
01123
01124
01125
01126
01127 const CoinPackedMatrix *matrix2 ;
01128 if (matrix.isColOrdered())
01129 { matrix2 = &matrix ; }
01130 else
01131 { _matrix_by_col = new CoinPackedMatrix ;
01132 _matrix_by_col->reverseOrderedCopyOf(matrix) ;
01133 matrix2 = _matrix_by_col ; }
01134
01135 pkvec_struct* colj = pkvec_new(n) ;
01136
01137 for (int j = 0 ; j < n ; j++)
01138 { const CoinShallowPackedVector coin_col = matrix2->getVector(j) ;
01139 packed_vector(coin_col,n,colj) ;
01140 colj->nme = const_cast<char *>(mps.columnName(j)) ;
01141 bool r = consys_addcol_pk(consys,vtyp[j],colj,obj[j],
01142 col_lower[j],col_upper[j]) ;
01143 assert(r) ; }
01144
01145 pkvec_free(colj) ;
01146 delete[] vtyp ;
01147 assert(matrix2->isEquivalent(*getMatrixByCol())) ;
01148
01149
01150
01151
01152
01153
01154 worst_case_primal() ;
01155 calc_objval() ;
01156
01157 return ; }
01158
01178 void ODSI::load_problem (const CoinPackedMatrix& matrix,
01179 const double* col_lower, const double* col_upper, const double* obj,
01180 const contyp_enum *ctyp, const double* rhs, const double* rhslow)
01181
01182 {
01183
01184
01185
01186
01187 destruct_problem(true) ;
01188
01189
01190
01191 int m = matrix.getNumCols() ;
01192 int n = matrix.getNumRows() ;
01193
01194 construct_consys(n,m) ;
01195
01196
01197
01198 pkvec_struct* rowi = pkvec_new(0) ;
01199 assert(rowi) ;
01200
01201 for (int i = 0 ; i < n ; i++)
01202 { rowi->nme = 0 ;
01203 bool r = consys_addrow_pk(consys,'a',ctyp[i],rowi,rhs[i],rhslow[i],0,0) ;
01204 assert(r) ;
01205 }
01206
01207 if (rowi) pkvec_free(rowi) ;
01208
01209
01210
01211
01212
01213 const CoinPackedMatrix *matrix2 ;
01214 if (matrix.isColOrdered())
01215 { matrix2 = &matrix ; }
01216 else
01217 { _matrix_by_col = new CoinPackedMatrix ;
01218 _matrix_by_col->reverseOrderedCopyOf(matrix) ;
01219 matrix2 = _matrix_by_col ; }
01220
01221 pkvec_struct* colj = pkvec_new(n) ;
01222
01223 for (int j = 0 ; j < m ; j++)
01224 { const CoinShallowPackedVector coin_col = matrix2->getVector(j) ;
01225 packed_vector(coin_col,n,colj) ;
01226 double objj = obj?obj[j]:0 ;
01227 double vlbj = col_lower?col_lower[j]:0 ;
01228 double vubj = col_upper?col_upper[j]:DYLP_INFINITY ;
01229 colj->nme = 0 ;
01230 bool r = consys_addcol_pk(consys,vartypCON,colj,objj,vlbj,vubj) ;
01231 assert(r) ; }
01232
01233 pkvec_free(colj) ;
01234 assert(matrix2->isEquivalent(*getMatrixByCol())) ;
01235
01236
01237
01238
01239
01240
01241 worst_case_primal() ;
01242 calc_objval() ;
01243
01244 return ; }
01245
01246
01273 void ODSI::load_problem (const int colcnt, const int rowcnt,
01274 const int *start, const int *index, const double *value,
01275 const double* col_lower, const double* col_upper, const double* obj,
01276 const contyp_enum *ctyp, const double* rhs, const double* rhslow)
01277
01278 {
01279
01280
01281
01282
01283 destruct_problem(true) ;
01284
01285
01286
01287
01288
01289 construct_consys(rowcnt,colcnt) ;
01290
01291
01292
01293 pkvec_struct* rowi = pkvec_new(0) ;
01294 assert(rowi) ;
01295
01296 for (int i = 0 ; i < rowcnt ; i++)
01297 { rowi->nme = 0 ;
01298 bool r = consys_addrow_pk(consys,'a',ctyp[i],rowi,rhs[i],rhslow[i],0,0) ;
01299 assert(r) ;
01300 }
01301
01302 if (rowi) pkvec_free(rowi) ;
01303
01304
01305
01306
01307 pkvec_struct *colj = pkvec_new(rowcnt) ;
01308 assert(colj) ;
01309 colj->dim = rowcnt ;
01310 pkcoeff_struct *coeffs = colj->coeffs ;
01311
01312 for (int j = 0 ; j < colcnt ; j++)
01313 { int startj = start[j] ;
01314 int lenj = start[j+1]-startj ;
01315
01316 for (int ndx = 0 ; ndx < lenj ; ndx++)
01317 { coeffs[ndx].ndx = idx(index[startj+ndx]) ;
01318 coeffs[ndx].val = value[startj+ndx] ; }
01319 colj->cnt = lenj ;
01320
01321 double objj = obj?obj[j]:0 ;
01322 double vlbj = col_lower?col_lower[j]:0 ;
01323 double vubj = col_upper?col_upper[j]:DYLP_INFINITY ;
01324 colj->nme = 0 ;
01325 bool r = consys_addcol_pk(consys,vartypCON,colj,objj,vlbj,vubj) ;
01326 assert(r) ;
01327 }
01328
01329 if (colj) pkvec_free(colj) ;
01330
01331
01332
01333 worst_case_primal() ;
01334 calc_objval() ;
01335
01336 return ; }
01337
01338
01339
01347 void ODSI::gen_rowparms (int rowcnt,
01348 double *rhs, double *rhslow, contyp_enum *ctyp,
01349 const double *rowlb, const double *rowub)
01350
01351 { double inf = DYLP_INFINITY ;
01352 double rowlbi,rowubi ;
01353
01354 for (int i = 0 ; i < rowcnt ; i++)
01355 { rowlbi = rowlb?rowlb[i]:-inf ;
01356 rowubi = rowub?rowub[i]:inf ;
01357 ctyp[i] = bound_to_type(rowlbi,rowubi) ;
01358
01359 switch (ctyp[i])
01360 { case contypEQ:
01361 case contypLE:
01362 { rhs[i] = rowubi ;
01363 rhslow[i] = 0 ;
01364 break ; }
01365 case contypGE:
01366 { rhs[i] = rowlbi ;
01367 rhslow[i] = 0 ;
01368 break ; }
01369 case contypRNG:
01370 { rhs[i] = rowubi ;
01371 rhslow[i] = rowlbi ;
01372 break ; }
01373 case contypNB:
01374 { rhs[i] = inf ;
01375 rhslow[i] = -inf ;
01376 break ; }
01377 default:
01378 { assert(0) ; } } }
01379
01380 return ; }
01381
01382
01390 void ODSI::gen_rowparms (int rowcnt,
01391 double *rhs, double *rhslow, contyp_enum *ctyp,
01392 const char *sense, const double *rhsin, const double *range)
01393
01394 { double rhsi,rangei ;
01395 char sensei ;
01396
01397 for (int i = 0 ; i < rowcnt ; i++)
01398 { rhsi = rhsin?rhsin[i]:0 ;
01399 rangei = range?range[i]:0 ;
01400 sensei = sense?sense[i]:'G' ;
01401
01402 switch (sensei)
01403 { case 'E':
01404 { rhs[i] = rhsi ;
01405 rhslow[i] = 0 ;
01406 ctyp[i] = contypEQ ;
01407 break ; }
01408 case 'L':
01409 { rhs[i] = rhsi ;
01410 rhslow[i] = 0 ;
01411 ctyp[i] = contypLE ;
01412 break ; }
01413 case 'G':
01414 { rhs[i] = rhsi ;
01415 rhslow[i] = 0 ;
01416 ctyp[i] = contypGE ;
01417 break ; }
01418 case 'R':
01419 { rhs[i] = rhsi ;
01420 rhslow[i] = rhsi-rangei ;
01421 ctyp[i] = contypRNG ;
01422 break ; }
01423 case 'N':
01424 { rhs[i] = 0 ;
01425 rhslow[i] = 0 ;
01426 ctyp[i] = contypNB ;
01427 break ; }
01428 default:
01429 { assert(0) ; } } }
01430
01431 return ; }
01432
01434
01435
01436
01444
01454 ODSI::OsiDylpSolverInterface ()
01455
01456 : initialSolveOptions(0),
01457 resolveOptions(0),
01458 tolerances(0),
01459 consys(0),
01460 lpprob(0),
01461 statistics(0),
01462
01463 local_logchn(IOID_NOSTRM),
01464 initial_gtxecho(false),
01465 resolve_gtxecho(false),
01466 lp_retval(lpINV),
01467 obj_sense(1.0),
01468
01469 solvername("dylp"),
01470 mps_debug(0),
01471 hotstart_fallback(0),
01472 activeBasis(0),
01473 activeIsModified(false),
01474
01475 _objval(0),
01476 _col_x(0),
01477 _col_obj(0),
01478 _col_cbar(0),
01479 _row_lhs(0),
01480 _row_lower(0),
01481 _row_price(0),
01482 _row_range(0),
01483 _row_rhs(0),
01484 _row_sense(0),
01485 _row_upper(0),
01486 _matrix_by_row(0),
01487 _matrix_by_col(0)
01488
01489 {
01490
01491
01492
01493 setOsiDylpMessages(CoinMessages::us_en) ;
01494
01495
01496
01497 for (int i = 0 ; i < OsiLastHintParam ; i++) info_[i] = 0 ;
01498
01499
01500
01501 construct_options() ;
01502
01503
01504
01505
01506 reference_count++ ;
01507
01508 if (reference_count == 1)
01509 { dylp_ioinit() ;
01510 CoinRelFltEq eq ;
01511 assert(eq(DYLP_INFINITY, DYLP_INFINITY)) ; }
01512
01513 return ; }
01514
01515
01521 ODSI::OsiDylpSolverInterface (const OsiDylpSolverInterface& src)
01522
01523 : OsiSolverInterface(src),
01524 initial_gtxecho(src.initial_gtxecho),
01525 resolve_gtxecho(src.resolve_gtxecho),
01526 lp_retval(src.lp_retval),
01527 obj_sense(src.obj_sense),
01528
01529 solvername(src.solvername),
01530 mps_debug(src.mps_debug),
01531 hotstart_fallback(0),
01532 activeBasis(0),
01533 activeIsModified(false),
01534
01535 _objval(src._objval),
01536 _matrix_by_row(0),
01537 _matrix_by_col(0)
01538
01539 { if (src.consys)
01540 { bool r = consys_dupsys(src.consys,&consys,src.consys->parts) ;
01541 assert(r) ; }
01542 else
01543 { consys = 0 ; }
01544 if (src.lpprob)
01545 { lpprob = copy_lpprob(src.lpprob) ;
01546 lpprob->consys = consys ; }
01547 else
01548 { lpprob = 0 ; }
01549
01550 CLONE(lpopts_struct,src.initialSolveOptions,initialSolveOptions) ;
01551 CLONE(lpopts_struct,src.resolveOptions,resolveOptions) ;
01552 CLONE(lpstats_struct,src.statistics,statistics) ;
01553 CLONE(lptols_struct,src.tolerances,tolerances) ;
01554
01555 if (src.local_logchn != IOID_NOSTRM)
01556 { local_logchn = openfile(idtopath(src.local_logchn),
01557 const_cast<char *>("w")) ; }
01558 else
01559 { local_logchn = IOID_NOSTRM ; }
01560 assert(local_logchn == src.local_logchn) ;
01561
01562 if (src.activeBasis)
01563 { activeBasis = src.activeBasis->clone() ;
01564 activeIsModified = src.activeIsModified ; }
01565
01566 int col_count = src.getNumCols() ;
01567 int row_count = src.getNumRows() ;
01568
01569 CLONE_VEC(double,src._col_x,_col_x,col_count) ;
01570 CLONE_VEC(double,src._col_obj,_col_obj,col_count) ;
01571 CLONE_VEC(double,src._col_cbar,_col_cbar,col_count) ;
01572 CLONE_VEC(double,src._row_lhs,_row_lhs,row_count) ;
01573 CLONE_VEC(double,src._row_lower,_row_lower,row_count) ;
01574 CLONE_VEC(double,src._row_price,_row_price,row_count) ;
01575 CLONE_VEC(double,src._row_range,_row_range,row_count) ;
01576 CLONE_VEC(double,src._row_rhs,_row_rhs,row_count) ;
01577 CLONE_VEC(char,src._row_sense,_row_sense,row_count) ;
01578 CLONE_VEC(double,src._row_upper,_row_upper,row_count) ;
01579
01580 if (src._matrix_by_row)
01581 _matrix_by_row = new CoinPackedMatrix(*src._matrix_by_row) ;
01582 if (src._matrix_by_col)
01583 _matrix_by_col = new CoinPackedMatrix(*src._matrix_by_col) ;
01584
01585 COPY_VEC(void *,&src.info_[0],&info_[0],OsiLastHintParam) ;
01586
01587 reference_count++ ;
01588
01589 # ifndef NDEBUG
01590 assert_same(*this, src, true) ;
01591 # endif
01592
01593 }
01594
01595
01600 inline OsiSolverInterface* ODSI::clone (bool copyData) const
01601
01602 { if (copyData)
01603 { return new OsiDylpSolverInterface(*this) ; }
01604 else
01605 { return new OsiDylpSolverInterface() ; }
01606 }
01607
01608
01616 OsiDylpSolverInterface &ODSI::operator= (const OsiDylpSolverInterface &rhs)
01617
01618 { if (this != &rhs)
01619 { destruct_problem(false) ;
01620
01621 OSI::operator=(rhs) ;
01622
01623 if (rhs.consys)
01624 { bool r = consys_dupsys(rhs.consys,&consys,rhs.consys->parts) ;
01625 assert(r) ; }
01626 else
01627 { consys = 0 ; }
01628 if (rhs.lpprob)
01629 { lpprob = copy_lpprob(rhs.lpprob) ;
01630 lpprob->consys = consys ; }
01631 else
01632 { lpprob = 0 ; }
01633
01634 CLONE(lpopts_struct,rhs.initialSolveOptions,initialSolveOptions) ;
01635 CLONE(lpopts_struct,rhs.resolveOptions,resolveOptions) ;
01636 CLONE(lpstats_struct,rhs.statistics,statistics) ;
01637 CLONE(lptols_struct,rhs.tolerances,tolerances) ;
01638
01639 if (rhs.local_logchn != IOID_NOSTRM)
01640 { local_logchn = openfile(idtopath(rhs.local_logchn),
01641 const_cast<char *>("w")) ; }
01642 else
01643 { local_logchn = IOID_NOSTRM ; }
01644 assert(local_logchn == rhs.local_logchn) ;
01645
01646 if (rhs.activeBasis)
01647 { activeBasis = rhs.activeBasis->clone() ;
01648 activeIsModified = rhs.activeIsModified ; }
01649
01650 int col_count = rhs.getNumCols() ;
01651 int row_count = rhs.getNumRows() ;
01652
01653 CLONE_VEC(double,rhs._col_x,_col_x,col_count) ;
01654 CLONE_VEC(double,rhs._col_obj,_col_obj,col_count) ;
01655 CLONE_VEC(double,rhs._col_cbar,_col_cbar,col_count) ;
01656 CLONE_VEC(double,rhs._row_lhs,_row_lhs,row_count) ;
01657 CLONE_VEC(double,rhs._row_lower,_row_lower,row_count) ;
01658 CLONE_VEC(double,rhs._row_price,_row_price,row_count) ;
01659 CLONE_VEC(double,rhs._row_range,_row_range,row_count) ;
01660 CLONE_VEC(double,rhs._row_rhs,_row_rhs,row_count) ;
01661 CLONE_VEC(char,rhs._row_sense,_row_sense,row_count) ;
01662 CLONE_VEC(double,rhs._row_upper,_row_upper,row_count) ;
01663
01664 if (rhs._matrix_by_row)
01665 _matrix_by_row = new CoinPackedMatrix(*rhs._matrix_by_row) ;
01666 if (rhs._matrix_by_col)
01667 _matrix_by_col = new CoinPackedMatrix(*rhs._matrix_by_col) ;
01668
01669 COPY_VEC(void *,&rhs.info_[0],&info_[0],OsiLastHintParam) ;
01670
01671 reference_count++ ;
01672
01673 # ifndef NDEBUG
01674 assert_same(*this, rhs, true) ;
01675 # endif
01676 }
01677
01678 return (*this) ; }
01679
01680
01682
01683
01684
01685
01686
01689
01709 void ODSI::destruct_problem (bool preserve_interface)
01710
01711 {
01712
01713
01714
01715
01716 assert((dylp_owner != this) || (dylp_owner == this && lpprob)) ;
01717
01718 if (dylp_owner == this) detach_dylp() ;
01719
01720 if (lpprob)
01721 { assert(lpprob->consys == consys) ;
01722 consys_free(consys) ;
01723 consys = 0 ;
01724 dy_freesoln(lpprob) ;
01725 delete lpprob ;
01726 lpprob = 0 ; }
01727 else
01728 if (consys)
01729 { consys_free(consys) ;
01730 consys = 0 ; }
01731
01732 if (hotstart_fallback)
01733 { delete hotstart_fallback ;
01734 hotstart_fallback = 0 ; }
01735 if (activeBasis)
01736 { delete activeBasis ;
01737 activeBasis = 0 ;
01738 activeIsModified = false ; }
01739
01740 destruct_cache() ;
01741
01742 if (preserve_interface == false)
01743 { if (initialSolveOptions)
01744 { delete initialSolveOptions ;
01745 initialSolveOptions = 0 ; }
01746 if (resolveOptions)
01747 { delete resolveOptions ;
01748 resolveOptions = 0 ; }
01749 if (tolerances)
01750 { delete tolerances ;
01751 tolerances = 0 ; } }
01752
01753 if (statistics)
01754 { if (preserve_interface == true)
01755 { memset(statistics,0,sizeof(lpstats_struct)) ; }
01756 else
01757 { delete statistics ;
01758 statistics = 0 ; } }
01759
01760 return ; }
01761
01762
01776 void ODSI::detach_dylp ()
01777
01778 { assert(dylp_owner == this && lpprob && lpprob->consys) ;
01779 assert(flgon(lpprob->ctlopts,lpctlDYVALID)) ;
01780 flags save_flags = getflg(lpprob->ctlopts,lpctlNOFREE|lpctlONLYFREE) ;
01781 clrflg(lpprob->ctlopts,lpctlNOFREE) ;
01782 setflg(lpprob->ctlopts,lpctlONLYFREE) ;
01783 lpprob->phase = dyDONE ;
01784
01785
01786
01787
01788 dylp(lpprob,initialSolveOptions,tolerances,statistics) ;
01789 clrflg(lpprob->ctlopts,lpctlONLYFREE) ;
01790 setflg(lpprob->ctlopts,save_flags) ;
01791 dylp_owner = 0 ; }
01792
01794
01803 ODSI::~OsiDylpSolverInterface ()
01804
01805 {
01806
01807
01808
01809
01810 destruct_problem(false) ;
01811 if (local_logchn != IOID_INV && local_logchn != IOID_NOSTRM)
01812 (void) closefile(local_logchn) ;
01813
01814 reference_count-- ;
01815 if (reference_count == 0)
01816 { if (basis_ready == true)
01817 { dy_freebasis() ;
01818 basis_ready = false ; }
01819 ioterm() ;
01820 errterm() ; }
01821
01822 return ; }
01823
01832 void ODSI::reset ()
01833
01834 {
01835
01836
01837
01838
01839 destruct_problem(false) ;
01840 if (local_logchn != IOID_INV && local_logchn != IOID_NOSTRM)
01841 { (void) closefile(local_logchn) ;
01842 local_logchn = IOID_NOSTRM ; }
01843
01844
01845
01846
01847 setInitialData() ;
01848
01849
01850
01851
01852
01853 initial_gtxecho = false ;
01854 resolve_gtxecho = false ;
01855 lp_retval = lpINV ;
01856 setObjSense(1.0) ;
01857 mps_debug = false ;
01858 construct_options() ;
01859 setOsiDylpMessages(CoinMessages::us_en) ;
01860 for (int i = 0 ; i < OsiLastHintParam ; i++) info_[i] = 0 ;
01861
01862 return ; }
01863
01864
01865
01873
01874 inline void ODSI::setContinuous (int j)
01875
01876 { if (!consys->vtyp)
01877 { bool r = consys_attach(consys,CONSYS_VTYP,sizeof(vartyp_enum),
01878 reinterpret_cast<void **>(&consys->vtyp)) ;
01879 assert(r) ; }
01880
01881 consys->vtyp[idx(j)] = vartypCON ; }
01882
01883
01884 inline void ODSI::setContinuous (const int* indices, int len)
01885
01886 { if (!consys->vtyp)
01887 { bool r = consys_attach(consys,CONSYS_VTYP,sizeof(vartyp_enum),
01888 reinterpret_cast<void **>(&consys->vtyp)) ;
01889 assert(r) ; }
01890
01891 for (int i = 0 ; i < len ; i++)
01892 consys->vtyp[idx(indices[i])] = vartypCON ; }
01893
01894
01895 inline void ODSI::setInteger (int j)
01896
01897 { if (!consys->vtyp)
01898 { bool r = consys_attach(consys,CONSYS_VTYP,sizeof(vartyp_enum),
01899 reinterpret_cast<void **>(&consys->vtyp)) ;
01900 assert(r) ; }
01901
01902 if (getColLower()[j] == 0.0 && getColUpper()[j] == 1.0)
01903 consys->vtyp[idx(j)] = vartypBIN ;
01904 else
01905 consys->vtyp[idx(j)] = vartypINT ; }
01906
01907
01908 inline void ODSI::setInteger (const int* indices, int len)
01909
01910 { if (!consys->vtyp)
01911 { bool r = consys_attach(consys,CONSYS_VTYP,sizeof(vartyp_enum),
01912 reinterpret_cast<void **>(&consys->vtyp)) ;
01913 assert(r) ; }
01914
01915 for (int i = 0 ; i < len ; i++) setInteger(indices[i]) ; }
01916
01917
01930 inline void ODSI::setColLower (int i, double val)
01931
01932 { if (!consys->vlb)
01933 { bool r = consys_attach(consys,CONSYS_VLB,sizeof(double),
01934 reinterpret_cast<void **>(&consys->vlb)) ;
01935 assert(r) ; }
01936
01937 consys->vlb[idx(i)] = val ;
01938 if (lpprob) setflg(lpprob->ctlopts,lpctlLBNDCHG) ;
01939
01940 if (isInteger(i))
01941 { if (floor(val) != val)
01942 setContinuous(i) ;
01943 else
01944 if (isBinary(i) && !(val == 0.0 || val == 1.0))
01945 setInteger(i) ; } }
01946
01951 inline void ODSI::setColUpper (int i, double val)
01952
01953 { if (!consys->vub)
01954 { bool r = consys_attach(consys,CONSYS_VUB,sizeof(double),
01955 reinterpret_cast<void **>(&consys->vub)) ;
01956 assert(r) ; }
01957
01958 consys->vub[idx(i)] = val ;
01959 if (lpprob) setflg(lpprob->ctlopts,lpctlUBNDCHG) ;
01960
01961 if (isInteger(i))
01962 { if (floor(val) != val)
01963 setContinuous(i) ;
01964 else
01965 if (isBinary(i) && !(val == 0.0 || val == 1.0))
01966 setInteger(i) ; } }
01967
01968
01973 void ODSI::setRowType (int i, char sense, double rhs, double range)
01974
01975 { int k = idx(i) ;
01976
01977 gen_rowiparms(&consys->ctyp[k],&consys->rhs[k],&consys->rhslow[k],
01978 sense,rhs,range) ;
01979 if (resolveOptions) resolveOptions->forcewarm = true ;
01980
01981 destruct_row_cache() ; }
01982
01983
01988 void ODSI::setRowUpper (int i, double val)
01989
01990 { int k = idx(i) ;
01991 double clbi ;
01992
01993 switch (consys->ctyp[k])
01994 { case contypEQ:
01995 case contypGE:
01996 { clbi = consys->rhs[k] ;
01997 break ; }
01998 case contypRNG:
01999 { clbi = consys->rhslow[k] ;
02000 break ; }
02001 case contypLE:
02002 case contypNB:
02003 { clbi = -DYLP_INFINITY ;
02004 break ; }
02005 default:
02006 { assert(false) ; } }
02007
02008 gen_rowiparms(&consys->ctyp[k],&consys->rhs[k],&consys->rhslow[k],
02009 clbi,val) ;
02010 if (lpprob) setflg(lpprob->ctlopts,lpctlRHSCHG) ;
02011
02012 destruct_row_cache() ; }
02013
02014
02019 void ODSI::setRowLower (int i, double val)
02020
02021 { int k = idx(i) ;
02022 double cubi ;
02023 contyp_enum ctypi = consys->ctyp[k] ;
02024
02025 if (ctypi == contypGE || ctypi == contypNB)
02026 cubi = DYLP_INFINITY ;
02027 else
02028 cubi = consys->rhs[k] ;
02029
02030 gen_rowiparms(&consys->ctyp[k],&consys->rhs[k],&consys->rhslow[k],
02031 val,cubi) ;
02032 if (lpprob) setflg(lpprob->ctlopts,lpctlRHSCHG) ;
02033
02034 destruct_row_cache() ; }
02035
02036
02044 inline void ODSI::addRow (const CoinPackedVectorBase &row,
02045 double rlb, double rub)
02046
02047 { contyp_enum ctypi ;
02048 double rhsi,rhslowi ;
02049
02050 gen_rowiparms(&ctypi,&rhsi,&rhslowi,rlb,rub) ;
02051 add_row(row,'a',ctypi,rhsi,rhslowi) ;
02052
02053 return ; }
02054
02055
02063 inline void ODSI::addRow (const CoinPackedVectorBase &coin_row,
02064 char sense, double rhs, double range)
02065
02066 { contyp_enum ctypi ;
02067 double rhsi,rhslowi ;
02068
02069 gen_rowiparms(&ctypi,&rhsi,&rhslowi,sense,rhs,range) ;
02070 add_row(coin_row,'a',ctypi,rhsi,rhslowi) ;
02071
02072 return ; }
02073
02074
02081 void ODSI::applyRowCut (const OsiRowCut &cut)
02082
02083 { contyp_enum ctypi ;
02084 double rhsi,rhslowi ;
02085
02086 gen_rowiparms(&ctypi,&rhsi,&rhslowi,cut.lb(),cut.ub()) ;
02087 add_row(cut.row(),'c',ctypi,rhsi,rhslowi) ;
02088
02089 return ; }
02090
02091
02104 void ODSI::deleteRows (int count, const int* rows)
02105
02106 { if (count <= 0) return ;
02107
02108
02109
02110 vector<int> lclrows = vector<int>(&rows[0],&rows[count]) ;
02111
02112 if (count > 1) std::sort(lclrows.begin(),lclrows.end()) ;
02113
02114 for (int k = count-1 ; k >= 0 ; k--)
02115 { int i = idx(lclrows[k]) ;
02116 bool r = consys_delrow_stable(consys,i) ;
02117 assert(r) ; }
02118
02119
02120
02121
02122
02123 if (activeBasis)
02124 { bool allslack = true ;
02125 OsiDylpWarmStartBasis *odwsb =
02126 dynamic_cast<OsiDylpWarmStartBasis *>(activeBasis) ;
02127 for (int k = count-1 ; k >= 0 ; k--)
02128 { int i = lclrows[k] ;
02129 if (odwsb->getArtifStatus(i) != CoinWarmStartBasis::basic)
02130 { allslack = false ;
02131 break ; } }
02132 if (allslack == true)
02133 { odwsb->deleteRows(count,rows) ;
02134 activeIsModified = true ;
02135 resolveOptions->forcewarm = true ; }
02136 else
02137 { delete activeBasis ;
02138 activeBasis = 0 ;
02139 activeIsModified = false ;
02140 resolveOptions->forcecold = true ; } }
02141
02142 destruct_cache() ; }
02143
02144
02145
02150 void ODSI::setObjCoeff (int j, double objj)
02151
02152 { if (j >= getNumCols()) return ;
02153
02154 consys->obj[idx(j)] = getObjSense()*objj ;
02155 if (_col_obj) _col_obj[j] = objj ;
02156 if (lpprob) setflg(lpprob->ctlopts,lpctlOBJCHG) ;
02157 calc_objval() ; }
02158
02159
02165 void ODSI::setObjSense (double val)
02166
02167
02168
02169
02170
02171
02172 { int n = getNumCols() ;
02173
02174 if (n > 0 && val != obj_sense)
02175 { double *tmpobj = INV_VEC(double,consys->obj) ;
02176 std::transform(tmpobj,tmpobj+n,tmpobj,std::negate<double>()) ;
02177 if (lpprob) setflg(lpprob->ctlopts,lpctlOBJCHG) ; }
02178
02179 obj_sense = val ;
02180
02181 return ; }
02182
02183
02192 inline void ODSI::addCol (const CoinPackedVectorBase& coin_col,
02193 double vlb, double vub, double obj)
02194
02195 { add_col(coin_col,vartypCON,vlb,vub,obj) ; }
02196
02197
02205 void ODSI::applyColCut (const OsiColCut &cut)
02206
02207 { const double* old_lower = getColLower() ;
02208 const double* old_upper = getColUpper() ;
02209 const CoinPackedVector& new_lower = cut.lbs() ;
02210 const CoinPackedVector& new_upper = cut.ubs() ;
02211
02212 int i ;
02213 int n1 = new_lower.getNumElements() ;
02214 int n2 = new_upper.getNumElements() ;
02215
02216 for (i = 0 ; i < n1 ; i++)
02217 { int j = new_lower.getIndices()[i] ;
02218 double x = new_lower.getElements()[i] ;
02219 if (x > old_lower[j]) setColLower(j,x) ; }
02220
02221 for (i = 0 ; i < n2 ; i++)
02222 { int j = new_upper.getIndices()[i] ;
02223 double x = new_upper.getElements()[i] ;
02224 if (x < old_upper[j]) setColUpper(j,x) ; }
02225 }
02226
02227
02240 void ODSI::deleteCols (int count, const int* cols)
02241
02242 { if (count <= 0) return ;
02243
02244
02245
02246 vector<int> lclcols = vector<int>(&cols[0],&cols[count]) ;
02247
02248 if (count > 1) std::sort(lclcols.begin(),lclcols.end()) ;
02249
02250 for (int k = 0 ; k < count ; k++)
02251 { int j = idx(lclcols[k]) ;
02252 bool r = consys_delcol(consys, j) ;
02253 assert(r) ; }
02254
02255
02256
02257
02258
02259 if (activeBasis)
02260 { bool allnonbasic = true ;
02261 OsiDylpWarmStartBasis *odwsb =
02262 dynamic_cast<OsiDylpWarmStartBasis *>(activeBasis) ;
02263 for (int k = count-1 ; k >= 0 ; k--)
02264 { int j = lclcols[k] ;
02265 if (odwsb->getStructStatus(j) == CoinWarmStartBasis::basic)
02266 { allnonbasic = false ;
02267 break ; } }
02268 if (allnonbasic == true)
02269 { odwsb->deleteColumns(count,cols) ;
02270 activeIsModified = true ;
02271 resolveOptions->forcewarm = true ; }
02272 else
02273 { delete activeBasis ;
02274 activeBasis = 0 ;
02275 activeIsModified = false ;
02276 resolveOptions->forcecold = true ; } }
02277
02278 destruct_cache() ; }
02279
02280
02290 void ODSI::setColSolution (const double* solution)
02291
02292 { int n = getNumCols() ;
02293
02294
02295
02296 if (n == 0) return ;
02297
02298 if (_col_x) delete[] _col_x ;
02299 _col_x = new double[n] ;
02300
02301 COPY_VEC(double,solution,_col_x,n) ;
02302 calc_objval() ;
02303
02304 return ; }
02305
02306
02316 void ODSI::setRowPrice (const double* price)
02317
02318 { int m = getNumRows() ;
02319
02320
02321
02322
02323 if (m == 0) return ;
02324
02325 if (_row_price) delete[] _row_price ;
02326 _row_price = new double[m] ;
02327
02328 COPY_VEC(double,price,_row_price,m) ;
02329
02330 return ; }
02331
02333
02334
02335
02336 #ifndef _MSC_VER
02337
02346
02347
02356 void ODSI::assert_same (double d1, double d2, bool exact)
02357
02358 { if (d1 == d2) return ;
02359
02360 assert(!exact && finite(d1) && finite(d2)) ;
02361
02362 static const double epsilon = 1.e-10 ;
02363 double tol = std::max(fabs(d1),fabs(d2))+1 ;
02364 double diff = fabs(d1 - d2) ;
02365
02366 assert(diff <= tol*epsilon) ; }
02367
02368
02374 template<class T>
02375 void ODSI::assert_same (const T& t1, const T& t2, bool exact)
02376
02377
02378 { if (&t1 == &t2) return ;
02379 assert(memcmp(&t1,&t2,sizeof(T)) == 0) ; }
02380
02381
02384 template<class T>
02385 void ODSI::assert_same (const T* t1, const T* t2, int n, bool exact)
02386
02387 { if (t1 == t2) return ;
02388 for (int i=0 ; i<n ; i++) assert_same(t1[i],t2[i],exact) ; }
02389
02390
02398 void ODSI::assert_same (const basis_struct& b1, const basis_struct& b2,
02399 bool exact)
02400 { assert(exact) ;
02401 if (&b1 == &b2) return ;
02402 assert(b1.len == b2.len) ;
02403
02404 int size = b1.len*sizeof(basisel_struct) ;
02405 assert(memcmp(inv_vec<basisel_struct>(b1.el),
02406 inv_vec<basisel_struct>(b2.el),size) == 0) ; }
02407
02408
02416 void ODSI::assert_same (const conbnd_struct& c1, const conbnd_struct& c2,
02417 bool exact)
02418
02419 { assert(exact) ;
02420 if (&c1 == &c2) return ;
02421
02422
02423 assert(c1.revs == c2.revs) ;
02424 assert(c1.inf == c2.inf) ;
02425 assert(c1.bnd == c2.bnd) ; }
02426
02427
02437 void ODSI::assert_same (const consys_struct& c1, const consys_struct& c2,
02438 bool exact)
02439
02440 { if (&c1 == &c2) return ;
02441
02442
02443
02444 assert(c1.parts == c2.parts) ;
02445 assert(c1.opts == c2.opts) ;
02446 assert(c1.varcnt == c2.varcnt) ;
02447 assert(c1.archvcnt == c2.archvcnt) ;
02448 assert(c1.logvcnt == c2.logvcnt) ;
02449 assert(c1.intvcnt == c2.intvcnt) ;
02450 assert(c1.binvcnt == c2.binvcnt) ;
02451 assert(c1.maxcollen == c2.maxcollen) ;
02452 assert(!exact || (c1.maxcolndx == c2.maxcolndx)) ;
02453 assert(c1.concnt == c2.concnt) ;
02454 assert(c1.archccnt == c2.archccnt) ;
02455 assert(c1.cutccnt == c2.cutccnt) ;
02456 assert(c1.maxrowlen == c2.maxrowlen) ;
02457 assert(!exact || (c1.maxrowndx == c2.maxrowndx)) ;
02458 assert(c1.objndx == c2.objndx) ;
02459 assert(c1.xzndx == c2.xzndx) ;
02460
02461
02462
02463 int var_count = ODSI::idx(c1.varcnt) ;
02464 int con_count = ODSI::idx(c1.concnt) ;
02465
02466 assert_same(c1.obj, c2.obj, var_count, exact) ;
02467 assert_same(c1.vtyp, c2.vtyp, var_count, true) ;
02468 assert_same(c1.vub, c2.vub, var_count, exact) ;
02469 assert_same(c1.vlb, c2.vlb, var_count, exact) ;
02470 assert_same(c1.colscale, c2.colscale, var_count, exact) ;
02471
02472 assert_same(c1.rhs, c2.rhs, con_count, exact) ;
02473 assert_same(c1.rhslow, c2.rhslow, con_count, exact) ;
02474 assert_same(c1.ctyp, c2.ctyp, con_count, true) ;
02475 assert_same(c1.cub, c2.cub, con_count, exact) ;
02476 assert_same(c1.clb, c2.clb, con_count, exact) ;
02477 assert_same(c1.rowscale, c2.rowscale, con_count, exact) ;
02478
02479
02480
02481
02482 if (exact)
02483 { assert(c1.nme == c2.nme) ;
02484 assert(c1.colsze == c2.colsze) ;
02485 assert(c1.rowsze == c2.rowsze) ;
02486 assert(c1.objnme == c2.objnme) ; } }
02487
02488
02496 void ODSI::assert_same (const lpprob_struct& l1, const lpprob_struct& l2,
02497 bool exact)
02498
02499 { if (&l1 == &l2) return ;
02500
02501
02502
02503
02504 assert(l1.ctlopts == l2.ctlopts) ;
02505 assert(l1.phase == l2.phase) ;
02506 assert(l1.lpret == l2.lpret) ;
02507 assert_same(l1.obj,l2.obj,exact) ;
02508 assert(l1.iters == l2.iters) ;
02509
02510
02511
02512
02513 if (exact)
02514 { assert(l1.colsze == l2.colsze) ;
02515 assert(l1.rowsze == l2.rowsze) ; }
02516
02517
02518
02519 int min_col = idx(std::min(l1.colsze, l2.colsze)) ;
02520 int min_row = idx(std::min(l1.rowsze, l2.rowsze)) ;
02521
02522 assert_same(l1.status,l2.status,min_col,exact) ;
02523 assert_same(l1.x,l2.x,min_row, exact) ;
02524 assert_same(l1.y,l2.y,min_row, exact) ;
02525
02526
02527
02528 assert_same(*l1.consys,*l2.consys,exact) ;
02529 assert_same(*l1.basis,*l2.basis,exact) ; }
02530
02531
02539 void ODSI::assert_same (const OsiDylpSolverInterface& o1,
02540 const OsiDylpSolverInterface& o2, bool exact)
02541
02542 {
02543
02544
02545
02546 if (&o1 == &o2) return ;
02547
02548
02549
02550
02551 assert(o1.reference_count == o2.reference_count) ;
02552 assert(o1.basis_ready == o2.basis_ready) ;
02553 assert(o1.dylp_owner == o2.dylp_owner) ;
02554
02555
02556
02557 assert(o1.local_logchn == o2.local_logchn) ;
02558 assert(o1.initial_gtxecho == o2.initial_gtxecho) ;
02559 assert(o1.resolve_gtxecho == o2.resolve_gtxecho) ;
02560 assert(o1.lp_retval == o2.lp_retval) ;
02561 assert(o1.obj_sense == o2.obj_sense) ;
02562 assert(o1.solvername == o2.solvername) ;
02563 assert(o1.mps_debug == o2.mps_debug) ;
02564
02565
02566
02567 assert_same(*o1.initialSolveOptions, *o2.initialSolveOptions, true) ;
02568 assert_same(*o1.resolveOptions, *o2.resolveOptions, true) ;
02569 assert_same(*o1.statistics, *o2.statistics, true) ;
02570 assert_same(*o1.tolerances, *o2.tolerances, true) ;
02571
02572
02573
02574 assert_same(o1.info_,o2.info_,OsiLastHintParam,exact) ;
02575
02576
02577
02578
02579
02580
02581 if (o1.lpprob)
02582 { assert(o2.lpprob) ;
02583 assert(o1.lpprob->consys && (o1.consys == o1.lpprob->consys)) ;
02584 assert(o2.lpprob->consys && (o2.consys == o2.lpprob->consys)) ;
02585 assert_same(*o1.lpprob,*o2.lpprob,exact) ; }
02586 else
02587 { assert(!o2.lpprob) ;
02588 assert_same(*o1.consys,*o2.consys,exact) ; }
02589
02590
02591
02592
02593 const CoinPackedMatrix* m1 = o1.getMatrixByCol() ;
02594 const CoinPackedMatrix* m2 = o2.getMatrixByCol() ;
02595 if (m1)
02596 { assert(m2 || m1->isEquivalent(*m2)) ; }
02597 else
02598 { assert(!m2) ; }
02599 }
02600
02602
02603 #endif
02604
02605
02606
02607
02608
02609
02610
02611
02621
02629 lpopts_struct* main_lpopts ;
02630 lptols_struct* main_lptols ;
02631
02633
02636
02646 std::string ODSI::make_filename (const char *filename,
02647 const char *ext1, const char *ext2)
02648
02649 { std::string basename(filename) ;
02650 std::string ext1str(ext1), ext2str(ext2) ;
02651
02652
02653
02654
02655 if (ext1 && strlen(ext1) > 0 && ext1[0] != '.')
02656 ext1str.insert(ext1str.begin(),'.') ;
02657 if (ext2 && strlen(ext2) > 0 && ext2[0] != '.')
02658 ext2str.insert(ext2str.begin(),'.') ;
02659
02660
02661
02662 if (ext1 && strlen(ext1) > 0)
02663 { string tmpname(filename) ;
02664 string::size_type ext1pos = tmpname.rfind(ext1str) ;
02665 if (ext1pos < tmpname.npos)
02666 { basename = tmpname.substr(0,ext1pos) ; } }
02667
02668
02669
02670 if (ext2 && strlen(ext2) > 0) basename += ext2str ;
02671
02672 return (basename) ; }
02673
02674
02676
02677
02678
02707
02708
02709
02723 int ODSI::readMps (const char* basename, const char* ext)
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739 { int errcnt ;
02740 CoinMpsIO mps ;
02741 CoinMessageHandler *mps_handler = mps.messageHandler() ;
02742
02743 if (mps_debug)
02744 { mps_handler->setLogLevel(handler_->logLevel()) ; }
02745 else
02746 { mps_handler->setLogLevel(0) ; }
02747
02748
02749
02750
02751 std::string filename = make_filename(basename,ext,"spc") ;
02752 dylp_controlfile(filename.c_str(),true,false) ;
02753
02754
02755
02756
02757 mps.setInfinity(DYLP_INFINITY) ;
02758 filename = make_filename(basename,ext,ext) ;
02759 errcnt = mps.readMps(filename.c_str(),0) ;
02760 handler_->message(ODSI_MPSFILEIO,messages_)
02761 << filename << "read" << errcnt << CoinMessageEol ;
02762 if (errcnt != 0) return (errcnt) ;
02763
02764
02765
02766
02767
02768 load_problem(mps) ;
02769
02770
02771
02772 return (0) ; }
02773
02774
02782 void ODSI::writeMps (const char *basename,
02783 const char *ext, double objsense) const
02784
02785 { string filename = make_filename(basename,ext,ext) ;
02786
02787 CoinMpsIO mps ;
02788 CoinMessageHandler *mps_handler = mps.messageHandler() ;
02789
02790 if (mps_debug)
02791 { mps_handler->setLogLevel(handler_->logLevel()) ; }
02792 else
02793 { mps_handler->setLogLevel(0) ; }
02794
02795 double *outputobj ;
02796 const double *const solverobj = getObjCoefficients() ;
02797
02798 int n = getNumCols(),
02799 m = getNumRows() ;
02800
02801 if (objsense == getObjSense())
02802 { outputobj = const_cast<double *>(solverobj) ; }
02803 else
02804 { outputobj = new double[n] ;
02805 std::transform(solverobj,solverobj+n,outputobj,std::negate<double>()) ; }
02806
02807 char *vartyp = new char[n] ;
02808 typedef char *charp ;
02809 char **colnames = new charp[n],
02810 **rownames = new charp[m] ;
02811 int i,j ;
02812
02813 for (j = 0 ; j < n ; j++) vartyp[j] = isInteger(j) ;
02814
02815 for (i = 0 ; i < m ; i++)
02816 rownames[i] = consys_nme(consys,'c',idx(i),false,0) ;
02817
02818 for (j = 0 ; j < n ; j++)
02819 colnames[j] = consys_nme(consys,'v',idx(j),false,0) ;
02820
02821 mps.setMpsData(*getMatrixByRow(),DYLP_INFINITY,
02822 getColLower(),getColUpper(),outputobj,vartyp,
02823 getRowLower(),getRowUpper(),colnames,rownames) ;
02824
02825
02826
02827 int errcnt = mps.writeMps(filename.c_str(),0,4,2) ;
02828 handler_->message(ODSI_MPSFILEIO,messages_)
02829 << filename << "read" << errcnt << CoinMessageEol ;
02830
02831
02832
02833 delete[] vartyp ;
02834 delete[] colnames ;
02835 delete[] rownames ;
02836 if (outputobj != solverobj) delete[] outputobj ;
02837
02838 return ; }
02839
02840
02848 inline void
02849 ODSI::assignProblem (CoinPackedMatrix*& matrix,
02850 double*& col_lower, double*& col_upper, double*& obj,
02851 double*& row_lower, double*& row_upper)
02852
02853 { loadProblem(*matrix,col_lower,col_upper,obj,row_lower,row_upper) ;
02854 delete matrix ; matrix = 0 ;
02855 delete [] col_lower ; col_lower = 0 ;
02856 delete [] col_upper ; col_upper = 0 ;
02857 delete [] obj ; obj = 0 ;
02858 delete [] row_lower ; row_lower = 0 ;
02859 delete [] row_upper ; row_upper = 0 ;
02860 }
02861
02862
02870 inline void
02871 ODSI::assignProblem (CoinPackedMatrix*& matrix,
02872 double*& lower, double*& upper, double*& obj,
02873 char*& sense, double*& rhs, double*& range)
02874
02875 { loadProblem(*matrix, lower, upper, obj, sense, rhs, range) ;
02876 delete matrix ; matrix = 0 ;
02877 delete [] lower ; lower = 0 ;
02878 delete [] upper ; upper = 0 ;
02879 delete [] obj ; obj = 0 ;
02880 delete [] sense ; sense = 0 ;
02881 delete [] rhs ; rhs = 0 ;
02882 delete [] range ; range = 0 ;
02883 }
02884
02885
02892 inline void
02893 ODSI::loadProblem (const CoinPackedMatrix& matrix,
02894 const double* col_lower, const double* col_upper,
02895 const double* obj,
02896 const double* row_lower, const double* row_upper)
02897
02898 { int rowcnt = matrix.getNumRows() ;
02899 double *rhs = new double[rowcnt] ;
02900 double *rhslow = new double[rowcnt] ;
02901 contyp_enum *ctyp = new contyp_enum[rowcnt] ;
02902
02903 gen_rowparms(rowcnt,rhs,rhslow,ctyp,row_lower,row_upper) ;
02904 load_problem(matrix,col_lower,col_upper,obj,ctyp,rhs,rhslow) ;
02905
02906 delete[] rhs ;
02907 delete[] rhslow ;
02908 delete[] ctyp ; }
02909
02910
02917 inline void
02918 ODSI::loadProblem (const CoinPackedMatrix& matrix,
02919 const double* col_lower, const double* col_upper,
02920 const double* obj,
02921 const char* sense, const double* rhsin, const double* range)
02922
02923 { int rowcnt = matrix.getNumRows() ;
02924 double *rhs = new double[rowcnt] ;
02925 double *rhslow = new double[rowcnt] ;
02926 contyp_enum *ctyp = new contyp_enum[rowcnt] ;
02927
02928 gen_rowparms(rowcnt,rhs,rhslow,ctyp,sense,rhsin,range) ;
02929 load_problem(matrix,col_lower,col_upper,obj,ctyp,rhs,rhslow) ;
02930
02931 delete[] rhs ;
02932 delete[] rhslow ;
02933 delete[] ctyp ; }
02934
02942 inline void
02943 ODSI::loadProblem (const int colcnt, const int rowcnt,
02944 const int *start, const int *index, const double *value,
02945 const double* col_lower, const double* col_upper,
02946 const double* obj,
02947 const double* row_lower, const double* row_upper)
02948
02949 { double *rhs = new double[rowcnt] ;
02950 double *rhslow = new double[rowcnt] ;
02951 contyp_enum *ctyp = new contyp_enum[rowcnt] ;
02952
02953 gen_rowparms(rowcnt,rhs,rhslow,ctyp,row_lower,row_upper) ;
02954 load_problem(colcnt,rowcnt,start,index,value,
02955 col_lower,col_upper,obj,ctyp,rhs,rhslow) ;
02956
02957 delete[] rhs ;
02958 delete[] rhslow ;
02959 delete[] ctyp ; }
02960
02961
02969 inline void
02970 ODSI::loadProblem (const int colcnt, const int rowcnt,
02971 const int *start, const int *index, const double *value,
02972 const double* col_lower, const double* col_upper,
02973 const double* obj,
02974 const char* sense, const double* rhsin, const double* range)
02975
02976 { double *rhs = new double[rowcnt] ;
02977 double *rhslow = new double[rowcnt] ;
02978 contyp_enum *ctyp = new contyp_enum[rowcnt] ;
02979
02980 gen_rowparms(rowcnt,rhs,rhslow,ctyp,sense,rhsin,range) ;
02981 load_problem(colcnt,rowcnt,start,index,value,
02982 col_lower,col_upper,obj,ctyp,rhs,rhslow) ;
02983
02984 delete[] rhs ;
02985 delete[] rhslow ;
02986 delete[] ctyp ; }
02987
02989
02990
02991
02992
02993
03052
03053 inline double ODSI::getInfinity () const { return DYLP_INFINITY ; }
03054
03055
03056 bool ODSI::setDblParam (OsiDblParam key, double value)
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074 { if (key == OsiLastDblParam) return (false) ;
03075
03076 bool retval = OSI::setDblParam(key,value) ;
03077
03078 switch (key)
03079 { case OsiDualTolerance:
03080 { tolerances->dfeas_scale = value/tolerances->cost ;
03081 break ; }
03082 case OsiPrimalTolerance:
03083 { tolerances->pfeas_scale = value/tolerances->zero ;
03084 break ; }
03085 case OsiObjOffset:
03086 { break ; }
03087 case OsiDualObjectiveLimit:
03088 case OsiPrimalObjectiveLimit:
03089 { break ; }
03090 default:
03091 { retval = false ;
03092 break ; } }
03093
03094 return (retval) ; }
03095
03096
03097 bool ODSI::getDblParam (OsiDblParam key, double& value) const
03098
03099
03100
03101
03102 { if (key == OsiLastDblParam) return (false) ;
03103
03104 bool retval ;
03105
03106 switch (key)
03107 { case OsiDualTolerance:
03108 case OsiPrimalTolerance:
03109 case OsiObjOffset:
03110 { retval = OSI::getDblParam(key,value) ;
03111 break ; }
03112 case OsiDualObjectiveLimit:
03113 case OsiPrimalObjectiveLimit:
03114 { retval = OSI::getDblParam(key,value) ;
03115 break ; }
03116 default:
03117 { OSI::getDblParam(key,value) ;
03118 retval = false ;
03119 break ; } }
03120
03121 return (retval) ; }
03122
03123
03124 bool ODSI::setIntParam (OsiIntParam key, int value)
03125
03126
03127
03128
03129
03130 { if (key == OsiLastIntParam) return (false) ;
03131
03132 bool retval = OSI::setIntParam(key,value) ;
03133
03134 switch (key)
03135 { case OsiMaxNumIteration:
03136 { initialSolveOptions->iterlim = value/3 ;
03137 resolveOptions->iterlim = initialSolveOptions->iterlim ;
03138 break ; }
03139 case OsiMaxNumIterationHotStart:
03140 { break ; }
03141 default:
03142 { retval = false ;
03143 break ; } }
03144
03145 return (retval) ; }
03146
03147
03148 inline bool ODSI::getIntParam (OsiIntParam key, int& value) const
03149
03150
03151
03152
03153 { bool retval ;
03154
03155 if (key == OsiLastIntParam) return (false) ;
03156
03157 switch (key)
03158 { case OsiMaxNumIteration:
03159 case OsiMaxNumIterationHotStart:
03160 { retval = OSI::getIntParam(key,value) ;
03161 break ; }
03162 default:
03163 { retval = false ;
03164 break ; } }
03165
03166 return (retval) ; }
03167
03168
03169 bool ODSI::setStrParam (OsiStrParam key, const std::string& value)
03170
03171
03172
03173
03174
03175
03176
03177 { if (key == OsiLastStrParam) return (false) ;
03178
03179 bool retval = OSI::setStrParam(key,value) ;
03180
03181 switch (key)
03182 { case OsiProbName:
03183 { if (consys)
03184 { if (consys->nme) strfree(consys->nme) ;
03185 consys->nme = stralloc(value.c_str()) ; }
03186 break ; }
03187 case OsiSolverName:
03188 { break ; }
03189 default:
03190 { retval = false ;
03191 break ; } }
03192
03193 return (retval) ; }
03194
03195 bool ODSI::getStrParam (OsiStrParam key, std::string& value) const
03196
03197
03198
03199
03200 { if (key == OsiLastStrParam) return (false) ;
03201
03202 bool retval = true ;
03203
03204 switch (key)
03205 { case OsiProbName:
03206 { retval = OSI::getStrParam(key,value) ;
03207 break ; }
03208 case OsiSolverName:
03209 { value = solvername ;
03210 break ; }
03211 default:
03212 { retval = false ;
03213 break ; } }
03214
03215 return (retval) ; }
03216
03217
03226 void ODSI::unimp_hint (bool dylpSense, bool hintSense,
03227 OsiHintStrength hintStrength, const char *msgString)
03228
03229 { if (dylpSense != hintSense)
03230 { std::string message("Dylp ") ;
03231 if (dylpSense == true)
03232 { message += "cannot disable " ; }
03233 else
03234 { message += "does not support " ; }
03235 message += msgString ;
03236 if (hintStrength == OsiForceDo)
03237 { handler_->message(ODSI_UNSUPFORCEDO,messages_)
03238 << message << CoinMessageEol ;
03239 throw CoinError(message,"setHintParam","OsiDylpSolverInterface") ; }
03240 else
03241 { handler_->message(ODSI_IGNORED,messages_)
03242 << message << CoinMessageEol ; } }
03243
03244 return ; }
03245
03246
03259 bool ODSI::setHintParam (OsiHintParam key, bool sense,
03260 OsiHintStrength strength, void *info)
03261
03262
03263
03264
03265
03266 { bool retval = false ;
03267
03268
03269
03270
03271
03272
03273 try
03274 { retval = OSI::setHintParam(key,sense,strength) ; }
03275 catch (CoinError)
03276 { retval = (strength == OsiForceDo) ; }
03277
03278 if (retval == false) return (false) ;
03279 info_[key] = info ;
03280
03281
03282
03283 if (strength == OsiHintIgnore) return (true) ;
03284
03285
03286
03287
03288 switch (key)
03289 {
03290
03291
03292
03293 case OsiDoPresolveInInitial:
03294 case OsiDoPresolveInResolve:
03295 { unimp_hint(false,sense,strength,"presolve") ;
03296 retval = true ;
03297 break ; }
03298
03299
03300
03301
03302
03303
03304 case OsiDoDualInInitial:
03305 case OsiDoDualInResolve:
03306 { unimp_hint(false,sense,strength,"exclusive use of dual simplex") ;
03307 retval = true ;
03308 lpopts_struct *opts =
03309 (key == OsiDoDualInInitial)?initialSolveOptions:resolveOptions ;
03310 if (sense == false)
03311 { if (strength >= OsiHintDo) opts->usedual = false ; }
03312 else
03313 { opts->usedual = true ; }
03314 break ; }
03315
03316
03317
03318 case OsiDoScale:
03319 { if (sense == false)
03320 { if (strength >= OsiHintTry) initialSolveOptions->scaling = 0 ; }
03321 else
03322 { initialSolveOptions->scaling = 2 ; }
03323 resolveOptions->scaling = initialSolveOptions->scaling ;
03324 break ; }
03325
03326
03327
03328
03329 case OsiDoCrash:
03330 { unimp_hint(true,sense,strength,"basis crash") ;
03331 retval = true ;
03332 break ; }
03333
03334
03335
03336
03337
03338
03339
03340
03341
03342
03343
03344 case OsiDoReducePrint:
03345 { int verbosity = messageHandler()->logLevel() ;
03346 mps_debug = false ;
03347 if (info)
03348 { verbosity = *reinterpret_cast<int *>(info) ;
03349 if (verbosity&0x8) mps_debug = true ; }
03350 else
03351 { if (sense == true)
03352 { verbosity -= strength ;
03353 verbosity = max(verbosity,0) ; }
03354 else
03355 { verbosity += strength ;
03356 verbosity = min(verbosity,4) ; } }
03357
03358 dy_setprintopts(0,initialSolveOptions) ;
03359 dy_setprintopts(0,resolveOptions) ;
03360 if (verbosity == 0)
03361 { initial_gtxecho = false ;
03362 resolve_gtxecho = false ; }
03363 else
03364 { initial_gtxecho = true ;
03365 resolve_gtxecho = true ; }
03366 messageHandler()->setLogLevel(verbosity) ;
03367 dy_setprintopts((verbosity&0x7),initialSolveOptions) ;
03368 dy_setprintopts((verbosity&0x7),resolveOptions) ;
03369 retval = true ;
03370 break ; }
03371
03372
03373
03374
03375
03376
03377 default:
03378 { unimp_hint(!sense,sense,strength,"unrecognized hint") ;
03379 retval = true ;
03380 break ; } }
03381
03382 return (retval) ; }
03383
03384
03385 inline bool ODSI::getHintParam (OsiHintParam key, bool &sense,
03386 OsiHintStrength &strength, void *&info) const
03387
03388
03389
03390
03391
03392 { bool retval = OSI::getHintParam(key,sense,strength) ;
03393
03394 if (retval == false) return (false) ;
03395
03396 info = info_[key] ;
03397
03398 return (true) ; }
03399
03400
03402
03403
03404
03414
03424 void ODSI::initialSolve ()
03425
03426 {
03427
03428
03429
03430
03431 assert(consys && initialSolveOptions && tolerances) ;
03432
03433
03434
03435 if (!lpprob) construct_lpprob() ;
03436
03437
03438
03439 if (basis_ready == false)
03440 { int count = static_cast<int>((1.5*getNumRows()) + 2*getNumCols()) ;
03441 dy_initbasis(count,initialSolveOptions->factor,0) ;
03442 basis_ready = true ; }
03443
03444
03445
03446 if (dylp_owner != 0 && dylp_owner != this) dylp_owner->detach_dylp() ;
03447
03448
03449
03450 lpopts_struct lclopts = *initialSolveOptions ;
03451 lptols_struct lcltols = *tolerances ;
03452 dy_checkdefaults(consys,&lclopts,&lcltols) ;
03453 if (isactive(local_logchn)) logchn = local_logchn ;
03454 gtxecho = initial_gtxecho ;
03455 lpprob->phase = dyINV ;
03456 lp_retval = dylp_dolp(lpprob,&lclopts,&lcltols,statistics) ;
03457 if (!(lp_retval == lpOPTIMAL || lp_retval == lpINFEAS ||
03458 lp_retval == lpUNBOUNDED))
03459 { throw CoinError("Call to dylp failed.",
03460 "initialSolve","OsiDylpSolverInterface") ; }
03461
03462
03463
03464
03465
03466 destruct_col_cache() ;
03467 destruct_row_cache() ;
03468
03469
03470
03471
03472
03473
03474
03475
03476
03477
03478
03479 delete activeBasis ;
03480 activeBasis = 0 ;
03481 activeIsModified = false ;
03482 if (flgon(lpprob->ctlopts,lpctlDYVALID))
03483 { dylp_owner = this ;
03484 if (lpprob->lpret == lpUNBOUNDED)
03485 { _objval = -getObjSense()*getInfinity() ; }
03486 else
03487 { _objval = getObjSense()*lpprob->obj ; }
03488 activeBasis = this->getWarmStart() ; }
03489 else
03490 { dylp_owner = 0 ; }
03491
03492 return ; }
03493
03495
03496
03497
03500
03501
03502 inline int ODSI::getIterationCount () const
03503
03504 { return ((lpprob)?lpprob->iters:0) ; }
03505
03506
03507 inline bool ODSI::isIterationLimitReached () const
03508
03509 { return (lp_retval == lpITERLIM) ; }
03510
03511
03512 inline bool ODSI::isProvenOptimal () const
03513
03514 { return (lp_retval == lpOPTIMAL) ; }
03515
03516
03517 inline bool ODSI::isProvenPrimalInfeasible () const
03518
03519 { return (lp_retval == lpINFEAS) ; }
03520
03521
03526 inline bool ODSI::isProvenDualInfeasible () const
03527
03528 { return (lp_retval == lpUNBOUNDED) ; }
03529
03530
03537 inline bool ODSI::isAbandoned () const
03538
03539 { if (lp_retval == lpACCCHK || lp_retval == lpSINGULAR ||
03540 lp_retval == lpSTALLED || lp_retval == lpNOSPACE ||
03541 lp_retval == lpLOSTFEAS || lp_retval == lpPUNT || lp_retval == lpFATAL)
03542 return (true) ;
03543 else
03544 return (false) ; }
03545
03546
03548
03549
03550
03553
03562 inline double ODSI::getObjValue () const
03563
03564
03565
03566
03567 { double objoffset ;
03568
03569 getDblParam(OsiObjOffset,objoffset) ;
03570
03571 return (_objval-objoffset) ; }
03572
03573
03574
03587 const double* ODSI::getColSolution () const
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603 { if (_col_x) return _col_x ;
03604
03605 if (lpprob)
03606 { assert(lpprob->status && lpprob->x) ;
03607
03608 int n = getNumCols() ;
03609 flags statj ;
03610 _col_x = new double[n] ;
03611
03612
03613
03614
03615
03616 for (int j = 0 ; j < n ; j++)
03617 { statj = lpprob->status[idx(j)] ;
03618 if (((int) statj) < 0)
03619 { int k = -((int) statj) ;
03620 _col_x[j] = lpprob->x[k] ; }
03621 else
03622 { switch (statj)
03623 { case vstatNBLB:
03624 case vstatNBFX:
03625 { _col_x[j] = consys->vlb[idx(j)] ;
03626 break ; }
03627 case vstatNBUB:
03628 { _col_x[j] = consys->vub[idx(j)] ;
03629 break ; }
03630 case vstatNBFR:
03631 { _col_x[j] = 0 ;
03632 break ; }
03633 case vstatSB:
03634 { _col_x[j] = -DYLP_INFINITY ;
03635 break ; } } } } }
03636
03637 return (_col_x) ; }
03638
03639
03645 const double* ODSI::getRowPrice () const
03646
03647
03648
03649
03650
03651 { if (_row_price) return (_row_price) ;
03652
03653 if (lpprob)
03654 { assert(lpprob->basis && lpprob->y) ;
03655
03656 int m = getNumRows() ;
03657 _row_price = new double[m] ;
03658 basis_struct* basis = lpprob->basis ;
03659
03660 memset(_row_price,0,m*sizeof(double)) ;
03661
03662 for (int k = 1 ; k <= basis->len ; k++)
03663 { int i = inv(basis->el[k].cndx) ;
03664 _row_price[i] = lpprob->y[k]*getObjSense() ; } }
03665
03666 return (_row_price) ; }
03667
03668
03675 const double *ODSI::getRowActivity () const
03676
03677
03678
03679
03680
03681 {
03682
03683
03684
03685 if (_row_lhs) return (_row_lhs) ;
03686
03687
03688
03689 int m = getNumRows() ;
03690 const double *x = getColSolution() ;
03691
03692 if (m > 0 && x)
03693
03694
03695
03696 { _row_lhs = new double[consys->concnt] ;
03697 memset(_row_lhs,0,m*sizeof(double)) ;
03698
03699
03700
03701
03702 pkvec_struct *aj = pkvec_new(m) ;
03703 for (int j = 0 ; j < consys->varcnt ; j++)
03704 { if (x[j] != 0)
03705 { bool r = consys_getcol_pk(consys,idx(j),&aj) ;
03706 if (!r)
03707 { delete[] _row_lhs ;
03708 if (aj) pkvec_free(aj) ;
03709 return (0) ; }
03710 for (int l = 0 ; l < aj->cnt ; l++)
03711 { int i = inv(aj->coeffs[l].ndx) ;
03712 _row_lhs[i] += x[j]*aj->coeffs[l].val ; } } }
03713 if (aj) pkvec_free(aj) ;
03714
03715
03716
03717 for (int i = 0 ; i < consys->concnt ; i++)
03718 setcleanzero(_row_lhs[i],tolerances->zero) ; }
03719
03720
03721
03722
03723 return (_row_lhs) ; }
03724
03725
03730 const double *ODSI::getReducedCost () const
03731
03732
03733
03734
03735
03736
03737
03738
03739
03740
03741
03742
03743 {
03744
03745
03746
03747 if (_col_cbar) return (_col_cbar) ;
03748
03749
03750
03751
03752 int n = getNumCols() ;
03753 if (n == 0) return (0) ;
03754 _col_cbar = new double[n] ;
03755 COPY_VEC(double,getObjCoefficients(),_col_cbar,n) ;
03756
03757
03758
03759
03760 int m = getNumRows() ;
03761 const double *y = getRowPrice() ;
03762 if (!y) return (_col_cbar) ;
03763
03764
03765
03766
03767 pkvec_struct *ai = pkvec_new(n) ;
03768 for (int i = 0 ; i < m ; i++)
03769 { if (y[i] != 0)
03770 { bool r = consys_getrow_pk(consys,idx(i),&ai) ;
03771 if (!r)
03772 { delete[] _col_cbar ;
03773 _col_cbar = 0 ;
03774 if (ai) pkvec_free(ai) ;
03775 return (0) ; }
03776 for (int l = 0 ; l < ai->cnt ; l++)
03777 { int j = inv(ai->coeffs[l].ndx) ;
03778 _col_cbar[j] -= y[i]*ai->coeffs[l].val ; } } }
03779 if (ai) pkvec_free(ai) ;
03780
03781
03782
03783 for (int j = 0 ; j < n ; j++) setcleanzero(_col_cbar[j],tolerances->cost) ;
03784
03785 return (_col_cbar) ; }
03786
03787
03789
03790
03791
03794
03800 inline bool ODSI::isBinary (int i) const
03801
03802 { if (!consys || i < 0 || i > consys->varcnt-1)
03803 return (false) ;
03804 else
03805 if (!consys->vtyp)
03806 return (false) ;
03807 else
03808 return (consys->vtyp[idx(i)] == vartypBIN) ; }
03809
03810
03816 inline bool ODSI::isIntegerNonBinary (int i) const
03817
03818 { if (!consys || i < 0 || i > consys->varcnt-1)
03819 return (false) ;
03820 else
03821 if (!consys->vtyp)
03822 return (false) ;
03823 else
03824 return (consys->vtyp[idx(i)] == vartypINT) ; }
03825
03826
03832 inline bool ODSI::isInteger (int i) const
03833
03834 { if (!consys || i < 0 || i > consys->varcnt-1)
03835 return (false) ;
03836 else
03837 if (!consys->vtyp)
03838 return (false) ;
03839 else
03840 return (consys->vtyp[idx(i)] == vartypINT ||
03841 consys->vtyp[idx(i)] == vartypBIN) ; }
03842
03843
03844
03850 inline bool ODSI::isContinuous (int i) const
03851
03852 { if (!consys || i < 0 || i > consys->varcnt-1)
03853 return (false) ;
03854 else
03855 if (!consys->vtyp)
03856 return (true) ;
03857 else
03858 return (consys->vtyp[idx(i)] == vartypCON) ; }
03859
03860
03863 inline const double* ODSI::getColLower () const
03864
03865 { if (!consys || !consys->vlb)
03866 return (0) ;
03867 else
03868 return (INV_VEC(double,consys->vlb)) ; }
03869
03870
03873 inline const double* ODSI::getColUpper () const
03874
03875 { if (!consys || !consys->vub)
03876 return (0) ;
03877 else
03878 return (INV_VEC(double,consys->vub)) ; }
03879
03880
03881 inline int ODSI::getNumCols () const
03882
03883 { if (!consys)
03884 return (0) ;
03885 else
03886 return (consys->varcnt) ; }
03887
03888
03889 inline int ODSI::getNumElements () const
03890
03891 { if (!consys)
03892 return (0) ;
03893 else
03894 return (consys->mtx.coeffcnt) ; }
03895
03896
03897 inline int ODSI::getNumRows () const
03898
03899 { if (!consys)
03900 return (0) ;
03901 else
03902 return (consys->concnt) ; }
03903
03904
03910 inline const double* ODSI::getObjCoefficients () const
03911
03912 { if (!consys || !consys->obj) return (0) ;
03913
03914 if (_col_obj) return _col_obj ;
03915
03916 int n = getNumCols() ;
03917 _col_obj = new double[n] ;
03918 double *obj_0base = INV_VEC(double,consys->obj) ;
03919
03920 if (getObjSense() < 0)
03921 { std::transform(obj_0base,obj_0base+n,_col_obj,std::negate<double>()) ; }
03922 else
03923 { COPY_VEC(double,obj_0base,_col_obj,n) ; }
03924
03925 return (_col_obj) ; }
03926
03927
03928 inline double ODSI::getObjSense () const
03929
03930 { return (obj_sense) ; }
03931
03932
03939 const CoinPackedMatrix* ODSI::getMatrixByRow () const
03940
03941 { if (!consys) return 0 ;
03942 if (_matrix_by_row) return _matrix_by_row ;
03943
03944 _matrix_by_row = new CoinPackedMatrix ;
03945 _matrix_by_row->reverseOrderedCopyOf(*getMatrixByCol()) ;
03946
03947 return _matrix_by_row ; }
03948
03949
03965 const CoinPackedMatrix* ODSI::getMatrixByCol () const
03966
03967 { if (!consys) return 0 ;
03968 if (_matrix_by_col) return _matrix_by_col ;
03969
03970
03971
03972
03973 int col_count = getNumCols() ;
03974 assert(col_count > 0) ;
03975 int coeff_count = consys->mtx.coeffcnt ;
03976 assert(coeff_count > 0) ;
03977
03978 int* start = new int[col_count+1] ;
03979 int* len = new int[col_count] ;
03980 double* values = new double[coeff_count] ;
03981 int* indices = new int[coeff_count] ;
03982 CoinPackedMatrix* matrix = new CoinPackedMatrix ;
03983
03984
03985
03986 colhdr_struct** cols = consys->mtx.cols ;
03987 int coeff_ndx = 0 ;
03988 for (int i = 0 ; i < col_count ; i++)
03989 { start[i] = coeff_ndx ;
03990 len[i] = cols[idx(i)]->len ;
03991
03992 coeff_struct* c = cols[idx(i)]->coeffs ;
03993 for (int j = 0 ; j < len[i] ; j++, c = c->colnxt, coeff_ndx++)
03994 { values[coeff_ndx] = c->val ;
03995 indices[coeff_ndx] = inv(c->rowhdr->ndx) ; }
03996 assert(c == 0) ; }
03997 assert(coeff_ndx == coeff_count) ;
03998
03999
04000
04001 start[col_count] = coeff_ndx ;
04002 int row_count = getNumRows() ;
04003 matrix->assignMatrix(true, row_count, col_count, coeff_count,
04004 values, indices, start, len) ;
04005
04006
04007
04008 _matrix_by_col = matrix ;
04009 return matrix ; }
04010
04011
04022 const double* ODSI::getRowLower () const
04023
04024 { if (!consys) return (0) ;
04025 if (_row_lower) return _row_lower ;
04026
04027 int n = getNumRows() ;
04028 double* lower = new double[n] ;
04029
04030 for (int i = 0 ; i < n ; i++)
04031 { contyp_enum ctypi = consys->ctyp[idx(i)] ;
04032 switch (ctypi)
04033 { case contypEQ:
04034 case contypGE:
04035 { lower[i] = consys->rhs[idx(i)] ;
04036 break ; }
04037 case contypRNG:
04038 { lower[i] = consys->rhslow[idx(i)] ;
04039 break ; }
04040 case contypLE:
04041 case contypNB:
04042 { lower[i] = -DYLP_INFINITY ;
04043 break ; }
04044 default:
04045 { assert(0) ; } } }
04046
04047 _row_lower = lower ;
04048 return (lower) ; }
04049
04050
04061 const double* ODSI::getRowUpper () const
04062
04063 { if (!consys) return (0) ;
04064 if (_row_upper) return _row_upper ;
04065
04066 int n = getNumRows() ;
04067 double* upper = new double[n] ;
04068
04069 for (int i = 0 ; i < n ; i++)
04070 { if (consys->ctyp[idx(i)] == contypGE || consys->ctyp[idx(i)] == contypNB)
04071 upper[i] = DYLP_INFINITY ;
04072 else
04073 upper[i] = consys->rhs[idx(i)] ; }
04074
04075 _row_upper = upper ;
04076 return upper ; }
04077
04078
04087 const char* ODSI::getRowSense () const
04088
04089 { if (!consys) return (0) ;
04090 if (_row_sense) return _row_sense ;
04091
04092 int n = getNumRows() ;
04093 char* sense = new char[n] ;
04094 const contyp_enum* ctyp = INV_VEC(contyp_enum,consys->ctyp) ;
04095
04096 std::transform(ctyp,ctyp+n,sense,type_to_sense) ;
04097
04098 _row_sense = sense ;
04099 return sense ; }
04100
04101
04112 const double* ODSI::getRowRange () const
04113
04114 { if (!consys) return (0) ;
04115 if (_row_range) return _row_range ;
04116
04117 int n = getNumRows() ;
04118 double* range = new double[n] ;
04119 const double* lower = getRowLower() ;
04120 const double* upper = getRowUpper() ;
04121 const char* sense = getRowSense() ;
04122
04123 for (int i=0 ; i<n ; i++)
04124 if (sense[i] != 'R')
04125 range[i] = 0.0 ;
04126 else
04127 range[i] = upper[i] - lower[i] ;
04128
04129 _row_range = range ;
04130 return range ; }
04131
04132
04143 const double* ODSI::getRightHandSide () const
04144
04145 { if (!consys) return (0) ;
04146 if (_row_rhs) return _row_rhs ;
04147
04148 int n = getNumRows() ;
04149 double* rhs = new double[n] ;
04150 const double* lower = getRowLower() ;
04151 const double* upper = getRowUpper() ;
04152 const char* sense = getRowSense() ;
04153
04154 for (int i = 0 ; i < n ; i++)
04155 { switch (sense[i])
04156 { case 'N':
04157 { rhs[i] = 0.0 ;
04158 break ; }
04159 case 'G':
04160 { rhs[i] = lower[i] ;
04161 break ; }
04162 case 'E':
04163 { rhs[i] = upper[i] ;
04164 break ; }
04165 case 'L':
04166 { rhs[i] = upper[i] ;
04167 break ; }
04168 case 'R':
04169 { rhs[i] = upper[i] ;
04170 break ; }
04171 default:
04172 { assert(0) ; } } }
04173
04174 _row_rhs = rhs ;
04175 return (rhs) ; }
04176
04177
04179
04180
04181
04184
04185
04196 bool ODSI::isDualObjectiveLimitReached () const
04197
04198 { double objlim ;
04199 double objval = getObjValue() ;
04200
04201 getDblParam(OsiDualObjectiveLimit,objlim) ;
04202 objlim *= getObjSense() ;
04203
04204 if (getObjSense() > 0)
04205 return (objval > objlim) ;
04206 else
04207 return (objval < objlim) ; }
04208
04209
04216 bool ODSI::isPrimalObjectiveLimitReached () const
04217
04218 { double objlim ;
04219 double objval = getObjValue() ;
04220
04221 getDblParam(OsiDualObjectiveLimit,objlim) ;
04222 objlim *= getObjSense() ;
04223
04224 if (getObjSense() > 0)
04225 return (objval < objlim) ;
04226 else
04227 return (objval > objlim) ; }
04228
04229
04235 vector<double*> ODSI::getDualRays (int) const
04236
04237 { throw CoinError("Unimplemented method.",
04238 "getDualRays","OsiDylpSolverInterface") ;
04239
04240 return (vector<double*>(0)) ; }
04241
04242
04248 vector<double*> ODSI::getPrimalRays (int) const
04249
04250 { throw CoinError("Unimplemented method.",
04251 "getPrimalRays","OsiDylpSolverInterface") ;
04252
04253 return (vector<double*>(0)) ; }
04254
04255
04260 void ODSI::branchAndBound ()
04261
04262 { throw CoinError("Unimplemented method.",
04263 "branchAndBound","OsiDylpSolverInterface") ;
04264
04265 return ; }
04266
04267
04269
04270
04271
04298
04305 CoinWarmStart *ODSI::getEmptyWarmStart () const
04306 { return (dynamic_cast<CoinWarmStart *>(new OsiDylpWarmStartBasis())) ; }
04307
04314 CoinWarmStart* ODSI::getWarmStart () const
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326 { int i,j,k ;
04327 flags statj ;
04328
04329
04330
04331
04332 if (activeBasis) { return (activeBasis->clone()) ; }
04333
04334
04335
04336
04337 OsiDylpWarmStartBasis *wsb = new OsiDylpWarmStartBasis ;
04338 assert(wsb) ;
04339 if (!lpprob) return (wsb) ;
04340
04341
04342
04343
04344 wsb->setSize(consys->varcnt,consys->concnt) ;
04345
04346 char *const strucStatus = wsb->getStructuralStatus() ;
04347 char *const artifStatus = wsb->getArtificialStatus() ;
04348 char *const conStatus = wsb->getConstraintStatus() ;
04349 basis_struct *basis = lpprob->basis ;
04350
04351 if (lpprob->lpret == lpOPTIMAL)
04352 wsb->setPhase(dyPRIMAL2) ;
04353 else
04354 wsb->setPhase(dyPRIMAL1) ;
04355
04356
04357
04358
04359 for (k = 1 ; k <= basis->len ; k++)
04360 { i = inv(basis->el[k].cndx) ;
04361 setStatus(conStatus,i,CoinWarmStartBasis::atLowerBound) ;
04362 j = basis->el[k].vndx ;
04363 if (j < 0)
04364 { j = inv(-j) ;
04365 setStatus(artifStatus,j,CoinWarmStartBasis::basic) ; }
04366 else
04367 { j = inv(j) ;
04368 setStatus(strucStatus,j,CoinWarmStartBasis::basic) ; } }
04369
04370
04371
04372
04373
04374
04375
04376 const double *y = getRowPrice() ;
04377 for (i = 0 ; i < consys->concnt ; i++)
04378 { if (getStatus(conStatus,i) == CoinWarmStartBasis::isFree)
04379 { setStatus(artifStatus,i,CoinWarmStartBasis::basic) ; }
04380 else
04381 if (getStatus(artifStatus,i) == CoinWarmStartBasis::isFree)
04382 { if (y[i] > 0)
04383 { setStatus(artifStatus,i,CoinWarmStartBasis::atUpperBound) ; }
04384 else
04385 { setStatus(artifStatus,i,CoinWarmStartBasis::atLowerBound) ; } } }
04386
04387
04388
04389
04390
04391 for (j = 1 ; j <= consys->varcnt ; j++)
04392 { statj = lpprob->status[j] ;
04393 if (((int) statj) > 0)
04394 { switch (statj)
04395 { case vstatNBLB:
04396 case vstatNBFX:
04397 { setStatus(strucStatus,inv(j), CoinWarmStartBasis::atLowerBound) ;
04398 break ; }
04399 case vstatNBUB:
04400 { setStatus(strucStatus,inv(j), CoinWarmStartBasis::atUpperBound) ;
04401 break ; }
04402 case vstatNBFR:
04403 { setStatus(strucStatus,inv(j), CoinWarmStartBasis::isFree) ;
04404 break ; }
04405 default:
04406 { delete wsb ;
04407 wsb = 0 ; } } } }
04408
04409 return (wsb) ; }
04410
04411
04420 bool ODSI::setWarmStart (const CoinWarmStart *ws)
04421
04422 { int i,j,k ;
04423 CoinWarmStartBasis::Status osi_statlogi,osi_statconi,osi_statvarj ;
04424
04425
04426
04427
04428
04429 const OsiDylpWarmStartBasis *wsb =
04430 dynamic_cast<const OsiDylpWarmStartBasis *>(ws) ;
04431 if (!wsb)
04432 { handler_->message(ODSI_NOTODWSB,messages_) ;
04433 return (false) ; }
04434 int varcnt = wsb->getNumStructural() ;
04435 int concnt = wsb->getNumArtificial() ;
04436 if (!(varcnt > 0 && concnt > 0))
04437 { handler_->message(ODSI_EMPTYODWSB,messages_) ;
04438 return (false) ; }
04439
04440
04441
04442 assert(consys && consys->vlb && consys->vub) ;
04443 if (!lpprob) construct_lpprob() ;
04444 assert(resolveOptions) ;
04445
04446
04447
04448
04449
04450
04451
04452
04453
04454
04455
04456
04457 if (!(varcnt == getNumCols() && concnt == getNumRows()))
04458 { handler_->message(ODSI_ODWSBBADSIZE,messages_) <<
04459 concnt << varcnt << getNumRows() << getNumCols() ;
04460 return (false) ; }
04461
04462 const char *const strucStatus = wsb->getStructuralStatus() ;
04463 const char *const artifStatus = wsb->getArtificialStatus() ;
04464 const char *const conStatus = wsb->getConstraintStatus() ;
04465
04466 flags *status = new flags[idx(varcnt)] ;
04467 basis_struct basis ;
04468 basis.el = new basisel_struct[idx(concnt)] ;
04469
04470
04471
04472
04473 basis.el[0].cndx = 0 ;
04474 basis.el[0].vndx = 0 ;
04475 status[0] = 0 ;
04476
04477
04478
04479 int actcons = 0 ;
04480 for (i = 1 ; i <= concnt ; i++)
04481 { osi_statconi = getStatus(conStatus,inv(i)) ;
04482 if (osi_statconi == CoinWarmStartBasis::atLowerBound)
04483 { actcons++ ;
04484 basis.el[actcons].cndx = i ;
04485 basis.el[actcons].vndx = 0 ; } }
04486 basis.len = actcons ;
04487
04488
04489
04490
04491
04492
04493 k = 0 ;
04494 for (j = 1 ; j <= varcnt ; j++)
04495 { osi_statvarj = getStatus(strucStatus,inv(j)) ;
04496 switch (osi_statvarj)
04497 { case CoinWarmStartBasis::basic:
04498 { k++ ;
04499 assert(k <= actcons) ;
04500 basis.el[k].vndx = j ;
04501 status[j] = (flags) (-k) ;
04502 break ; }
04503 case CoinWarmStartBasis::atLowerBound:
04504 { if (consys->vlb[j] == consys->vub[j])
04505 { status[j] = vstatNBFX ; }
04506 else
04507 { status[j] = vstatNBLB ; }
04508 break ; }
04509 case CoinWarmStartBasis::atUpperBound:
04510 { status[j] = vstatNBUB ;
04511 break ; }
04512 case CoinWarmStartBasis::isFree:
04513 { status[j] = vstatNBFR ;
04514 break ; } } }
04515
04516
04517
04518
04519
04520
04521
04522
04523 for (i = 1 ; i <= concnt ; i++)
04524 { osi_statlogi = getStatus(artifStatus,inv(i)) ;
04525 osi_statconi = getStatus(conStatus,inv(i)) ;
04526 if (osi_statlogi == CoinWarmStartBasis::basic &&
04527 osi_statconi == CoinWarmStartBasis::atLowerBound)
04528 { k++ ;
04529 assert(k <= actcons) ;
04530 basis.el[k].vndx = -i ; } }
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540 if (lpprob->colsze < varcnt)
04541 { if (lpprob->status)
04542 { FREE(lpprob->status) ;
04543 lpprob->status = 0 ; }
04544 if (lpprob->actvars)
04545 { lpprob->actvars =
04546 (bool *) REALLOC(lpprob->actvars,idx(varcnt)*sizeof(bool)) ; }
04547 lpprob->colsze = varcnt ; }
04548 if (!lpprob->status)
04549 { lpprob->status = (flags *) CALLOC(idx(lpprob->colsze),sizeof(flags)) ; }
04550 if (!lpprob->actvars)
04551 { lpprob->actvars = (bool *) CALLOC(idx(lpprob->colsze),sizeof(bool)) ; }
04552
04553 if (lpprob->rowsze < actcons)
04554 { if (lpprob->x)
04555 { lpprob->x =
04556 (double *) REALLOC(lpprob->x,idx(actcons)*sizeof(double)) ; }
04557 if (lpprob->y)
04558 { lpprob->y =
04559 (double *) REALLOC(lpprob->y,idx(actcons)*sizeof(double)) ; }
04560 if (lpprob->basis && lpprob->basis->el)
04561 { FREE(lpprob->basis->el) ;
04562 lpprob->basis->el = 0 ; }
04563 lpprob->rowsze = actcons ; }
04564 if (!lpprob->x)
04565 { lpprob->x = (double *) CALLOC(idx(lpprob->rowsze),sizeof(double)) ; }
04566 if (!lpprob->y)
04567 { lpprob->y = (double *) CALLOC(idx(lpprob->rowsze),sizeof(double)) ; }
04568 if (!lpprob->basis)
04569 { lpprob->basis = (basis_struct *) CALLOC(1,sizeof(basis_struct)) ; }
04570 if (!lpprob->basis->el)
04571 { lpprob->basis->el =
04572 (basisel_struct *) CALLOC(idx(lpprob->rowsze),sizeof(basisel_struct)) ; }
04573
04574
04575
04576 copy_basis(&basis,lpprob->basis) ;
04577 COPY_VEC(flags,status,lpprob->status,idx(varcnt)) ;
04578 delete[] basis.el ;
04579 delete[] status ;
04580
04581
04582
04583
04584
04585 lpprob->phase = wsb->getPhase() ;
04586 resolveOptions->forcecold = false ;
04587 resolveOptions->forcewarm = true ;
04588
04589
04590
04591
04592 if (wsb != static_cast<const CoinWarmStart *>(activeBasis) )
04593 { delete activeBasis ;
04594 activeBasis = wsb->clone() ;
04595 activeIsModified = false ; }
04596
04597 return (true) ; }
04598
04599
04600 void ODSI::resolve ()
04601
04602
04603
04604
04605
04606
04607
04608
04609
04610
04611
04612
04613
04614
04615 { assert(lpprob && lpprob->basis && lpprob->status && consys &&
04616 resolveOptions && tolerances && statistics) ;
04617
04618 if (dylp_owner != 0 && dylp_owner != this) dylp_owner->detach_dylp() ;
04619
04620
04621
04622 if (basis_ready == false)
04623 { int count = static_cast<int>((1.5*getNumRows()) + 2*getNumCols()) ;
04624 dy_initbasis(count,initialSolveOptions->factor,0) ;
04625 basis_ready = true ; }
04626
04627
04628
04629
04630
04631
04632
04633
04634
04635
04636
04637 if (activeBasis && (activeIsModified == true || dylp_owner == 0))
04638 { if (setWarmStart(activeBasis) == false)
04639 { throw CoinError("Warm start failed --- invalid active basis.",
04640 "resolve","OsiDylpSolverInterface") ; }
04641 delete activeBasis ;
04642 activeBasis = 0 ;
04643 activeIsModified = false ;
04644 resolveOptions->forcewarm = true ; }
04645
04646
04647
04648
04649 lpopts_struct lclopts = *resolveOptions ;
04650 lptols_struct lcltols = *tolerances ;
04651 dy_checkdefaults(consys,&lclopts,&lcltols) ;
04652 assert(lclopts.forcecold == false) ;
04653 if (isactive(local_logchn)) logchn = local_logchn ;
04654 gtxecho = resolve_gtxecho ;
04655 dyphase_enum phase = lpprob->phase ;
04656 if (!(phase == dyPRIMAL1 || phase == dyPRIMAL2 || phase == dyDUAL))
04657 lpprob->phase = dyINV ;
04658 lp_retval = dylp_dolp(lpprob,&lclopts,&lcltols,statistics) ;
04659 if (!(lp_retval == lpOPTIMAL || lp_retval == lpINFEAS ||
04660 lp_retval == lpUNBOUNDED))
04661 { throw CoinError("Call to dylp failed.",
04662 "resolve","OsiDylpSolverInterface") ; }
04663
04664
04665
04666
04667
04668 destruct_col_cache() ;
04669 destruct_row_cache() ;
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680
04681 delete activeBasis ;
04682 activeBasis = 0 ;
04683 activeIsModified = false ;
04684 if (flgon(lpprob->ctlopts,lpctlDYVALID))
04685 { dylp_owner = this ;
04686 if (lpprob->lpret == lpUNBOUNDED)
04687 { _objval = -getObjSense()*getInfinity() ; }
04688 else
04689 { _objval = getObjSense()*lpprob->obj ; }
04690 activeBasis = this->getWarmStart() ;
04691 resolveOptions->forcewarm = false ; }
04692 else
04693 { dylp_owner = 0 ; }
04694
04695 return ; }
04696
04698
04699
04700
04733
04741 inline void ODSI::markHotStart ()
04742 {
04743
04744
04745
04746
04747
04748 assert(dylp_owner == this) ;
04749 assert(lpprob && resolveOptions) ;
04750 assert(flgon(lpprob->ctlopts,lpctlDYVALID)) ;
04751
04752
04753
04754 resolveOptions->forcecold = false ;
04755 resolveOptions->forcewarm = false ;
04756
04757
04758
04759
04760 if (hotstart_fallback) delete hotstart_fallback ;
04761 hotstart_fallback = getWarmStart() ;
04762
04763 return ; }
04764
04772 void ODSI::solveFromHotStart ()
04773
04774 {
04775
04776
04777
04778
04779
04780
04781
04782 if (dylp_owner != this)
04783 { if (hotstart_fallback && setWarmStart(hotstart_fallback))
04784 { resolve() ; }
04785 else
04786 { throw CoinError("Hot start failed --- invalid/missing hot start object.",
04787 "solveFromHotStart","OsiDylpSolverInterface") ; } }
04788
04789
04790
04791
04792
04793
04794
04795 else
04796 { int tmp_iterlim = -1 ;
04797 int hotlim ;
04798
04799 assert(lpprob && lpprob->basis && lpprob->status && basis_ready &&
04800 consys && resolveOptions && tolerances && statistics) ;
04801
04802 if (isactive(local_logchn)) logchn = local_logchn ;
04803 gtxecho = resolve_gtxecho ;
04804
04805
04806
04807
04808
04809 lpopts_struct lclopts = *resolveOptions ;
04810 lptols_struct lcltols = *tolerances ;
04811 dy_checkdefaults(consys,&lclopts,&lcltols) ;
04812 lpprob->phase = dyPRIMAL1 ;
04813 assert(lclopts.forcecold == false) ;
04814 lclopts.forcewarm = false ;
04815 getIntParam(OsiMaxNumIterationHotStart,hotlim) ;
04816 if (hotlim > 0)
04817 { tmp_iterlim = resolveOptions->iterlim ;
04818 resolveOptions->iterlim = (hotlim/3 > 0)?hotlim/3:1 ; }
04819
04820 lp_retval = dylp_dolp(lpprob,&lclopts,&lcltols,statistics) ;
04821 if (!(lp_retval == lpOPTIMAL || lp_retval == lpINFEAS ||
04822 lp_retval == lpUNBOUNDED))
04823 { throw CoinError("Call to dylp failed.",
04824 "solveFromHotStart","OsiDylpSolverInterface") ; }
04825
04826
04827
04828
04829
04830 destruct_col_cache() ;
04831 destruct_row_cache() ;
04832
04833
04834
04835
04836
04837
04838
04839
04840
04841
04842
04843 delete activeBasis ;
04844 activeBasis = 0 ;
04845 activeIsModified = false ;
04846 if (flgon(lpprob->ctlopts,lpctlDYVALID))
04847 { if (lpprob->lpret == lpUNBOUNDED)
04848 { _objval = -getObjSense()*getInfinity() ; }
04849 else
04850 { _objval = getObjSense()*lpprob->obj ; }
04851 activeBasis = this->getWarmStart() ; }
04852 else
04853 { dylp_owner = 0 ; }
04854 if (tmp_iterlim > 0) resolveOptions->iterlim = tmp_iterlim ; }
04855
04856 return ; }
04857
04858
04859 inline void ODSI::unmarkHotStart ()
04860
04861
04862
04863
04864 { if (hotstart_fallback)
04865 { delete hotstart_fallback ;
04866 hotstart_fallback = 0 ; }
04867
04868 return ; }
04869
04871
04872
04873
04876
04897 void ODSI::activateRowCutDebugger (const char * modelName)
04898
04899 { delete rowCutDebugger_ ;
04900
04901 if (dylp_owner && dylp_owner->lpprob &&
04902 flgon(dylp_owner->lpprob->ctlopts,lpctlDYVALID))
04903 { CoinWarmStart *ws = dylp_owner->getWarmStart() ;
04904 ODSI *prev_owner = dylp_owner ;
04905 prev_owner->detach_dylp() ;
04906 rowCutDebugger_ = new OsiRowCutDebugger(*this,modelName) ;
04907 prev_owner->setWarmStart(ws) ;
04908 prev_owner->resolve() ;
04909 delete ws ; }
04910 else
04911 { rowCutDebugger_ = new OsiRowCutDebugger(*this,modelName) ; }
04912
04913 return ; }
04914
04916
04917
04918
04921
04933 void ODSI::dylp_controlfile (const char *name,
04934 const bool silent, const bool mustexist)
04935
04936 { if (name == 0 || *name == 0) return ;
04937 string mode = (mustexist)?"r":"q" ;
04938 cmdchn = openfile(const_cast<char *>(name),const_cast<char *>(mode.c_str())) ;
04939 if (!(cmdchn == IOID_INV || cmdchn == IOID_NOSTRM))
04940 { setmode (cmdchn, 'l') ;
04941 main_lpopts = initialSolveOptions ;
04942 main_lptols = tolerances ;
04943 bool r = (process_cmds(silent) != 0) ;
04944 (void) closefile(cmdchn) ;
04945 assert(r == cmdOK) ;
04946
04947
04948
04949 lpopts_struct saveOptions = *resolveOptions ;
04950 memcpy(resolveOptions,initialSolveOptions,sizeof(lpopts_struct));
04951 resolveOptions->forcecold = saveOptions.forcecold ;
04952 resolveOptions->fullsys = saveOptions.fullsys ; }
04953
04954 cmdchn = IOID_NOSTRM ;
04955
04956 return ; }
04957
04958
04966 void ODSI::dylp_logfile (const char *name, bool echo)
04967
04968 { if (name == 0 || *name == 0) return ;
04969
04970 string log = make_filename(name,".mps",".log") ;
04971 local_logchn = openfile(const_cast<char *>(log.c_str()),
04972 const_cast<char *>("w")) ;
04973 if (local_logchn == IOID_INV) local_logchn = IOID_NOSTRM ;
04974 initial_gtxecho = echo ;
04975 resolve_gtxecho = echo ; }
04976
04978
04979 #endif