void OsiSolver::printModel() { printf("########\nMODEL:\nVARS :\n"); printf("V%d(%.2lf, %.2lf)", 0, col_lb[0], col_ub[0]); for (int i = 1; i < n_cols; i++) { printf(", V%d(%.2lf,%.2lf)", i, col_lb[i], col_ub[i]); } printf("\n\nObjective : Maximise(%s): ", (_obj_coef == -1 ? "Minimise" : "Maximise")); printf("%.2lf * V%d", objective[0], 0); for (int i = 1; i < n_cols; i++) { printf(" + %.2lf * V%d", objective[i], i); } printf("\n\nMatrix:\n"); for (int i = 0; i < matrix->getNumRows(); i++) { CoinShallowPackedVector row = matrix->getVector(i); const double* elements = row.getElements(); const int* indices = row.getIndices(); int n = row.getNumElements(); if (row_lb[i] == -1.0 * si->getInfinity()) printf("-infinity <= "); else printf("%.2lf <= ", row_lb[i]); printf("%.2lf * V%d", elements[0], indices[0]); for (int j = 1; j < n; j++) printf(" + %.2lf * V%d", elements[j], indices[j]); if (row_ub[i] == si->getInfinity()) printf(" <= infinity\n"); else printf(" <= %.2lf\n", row_ub[i]); } printf("########\n"); }
void OsiSolver::build_expressions() { // build expressions*, first element is Sum() for the objective // every pair after that ((1,2),(3,4)) is a le and ge over a // common Sum const double*objCoef = si->getObjCoefficients(); const int ncols = si->getNumCols(); const int nrows = si->getNumRows(); const double* col_ubs = si->getColUpper(); const double* col_lbs = si->getColLower(); const double* row_ubs = si->getRowUpper(); const double* row_lbs = si->getRowLower(); const CoinPackedMatrix* mtx = si->getMatrixByRow(); // Build objective expression. OsiExpArray vars; OsiDoubleArray coefs; double sum = 0; for (int i = 0; i < ncols; i++) { Osi_Expression* var; if (si->isContinuous(i)) var = new Osi_DoubleVar(col_lbs[i], col_ubs[i], i); else var = new Osi_IntVar(col_lbs[i], col_ubs[i], i); var->varname = si->getColName(i, 255); vars.add(var); expressions.push_back(var); coefs.add(objCoef[i]); sum += objCoef[i]; } /* Only return an objective if there is one! (Empty objectives were not * working with some solvers */ if (sum != 0) { expressions.push_back(new Osi_Minimise(new Osi_Sum(vars, coefs, 0))); } // Build remaining expressions, expr <= upper, expr >= lower for (int i = 0; i < nrows; i++) { CoinShallowPackedVector row = mtx->getVector(i); if (row.getNumElements() > 0) { const double* elements = row.getElements(); const int* indices = row.getIndices(); OsiExpArray sumvars; OsiDoubleArray coefs; for (int j = 0; j < row.getNumElements(); j++) { sumvars.add(vars.get_item(indices[j])); coefs.add(elements[j]); } Osi_Sum* expr = new Osi_Sum(sumvars, coefs, 0); if (!(row_ubs[i] == si->getInfinity())) expressions.push_back(new Osi_le(expr, row_ubs[i])); if (!(row_lbs[i] == -1.0 * si->getInfinity())) expressions.push_back(new Osi_ge(expr, row_lbs[i])); } } }
/* * split_ranged_rows finds rows that are bounded on both sides and creates * two separate rows for each. This is added since OsiVol doesn't like * ranged rows. */ void OsiSolver::splitRangedRows() { std::vector<double> row_ubs_new; std::vector<double> row_lbs_new; CoinPackedMatrix* matrix_new = new CoinPackedMatrix(false, 0, 0); for (int i = 0; i < n_rows; i++) { double ub_coef = row_ub[i] < 0.0 ? -1.0 : 1.0; double lb_coef = row_lb[i] < -1.0e20 ? 1.0 : (row_lb[i] < 0.0 ? -1.0 : 1.0); const CoinShallowPackedVector row = matrix->getVector(i); const double* elements = row.getElements(); const int* indices = row.getIndices(); if (row_lb[i] > -1.0e20 && row_ub[i] < 1.0e20 && row_lb[i] != row_ub[i]) { CoinPackedVector row_with_ub; CoinPackedVector row_with_lb; row_ubs_new.push_back(si->getInfinity()); row_ubs_new.push_back(ub_coef * row_ub[i]); row_lbs_new.push_back(lb_coef * row_lb[i]); row_lbs_new.push_back(-1.0 * si->getInfinity()); for (int j = 0; j < row.getNumElements(); j++) { row_with_ub.insert(indices[j], ub_coef * elements[j]); row_with_lb.insert(indices[j], lb_coef * elements[j]); } matrix_new->appendRow(row_with_ub); matrix_new->appendRow(row_with_lb); } else { CoinPackedVector new_row; row_ubs_new.push_back(ub_coef * row_ub[i]); row_lbs_new.push_back(lb_coef * row_lb[i]); double row_coef = row_ub[i] < 1.0e20 ? (row_ub[i] < 0.0 ? -1.0 : 1.0) : (row_lb[i] < 0.0 ? -1.0 : 1.0); for (int j = 0; j < row.getNumElements(); j++) { new_row.insert(indices[j], row_coef * elements[j]); } matrix_new->appendRow(new_row); } } n_rows = row_ubs_new.size(); delete matrix; delete[] row_lb; delete[] row_ub; row_lb = new double[n_rows]; row_ub = new double[n_rows]; for (int i = 0; i < n_rows; i++) { row_lb[i] = row_lbs_new.at(i); row_ub[i] = row_ubs_new.at(i); } matrix = matrix_new; }
//------------------------------------------------------------------- // Copy //------------------------------------------------------------------- CoinShallowPackedVector::CoinShallowPackedVector(const CoinShallowPackedVector &x) : CoinPackedVectorBase() , indices_(x.getIndices()) , elements_(x.getElements()) , nElements_(x.getNumElements()) { CoinPackedVectorBase::copyMaxMinIndex(x); try { CoinPackedVectorBase::setTestForDuplicateIndex(x.testForDuplicateIndex()); } catch (CoinError &e) { throw CoinError("duplicate index", "copy constructor", "CoinShallowPackedVector"); } }
void CoinShallowPackedVectorUnitTest() { CoinRelFltEq eq; int i; // Test default constructor { CoinShallowPackedVector r; assert( r.indices_==NULL ); assert( r.elements_==NULL ); assert( r.nElements_==0 ); } // Test set and get methods const int ne = 4; int inx[ne] = { 1, 3, 4, 7 }; double el[ne] = { 1.2, 3.4, 5.6, 7.8 }; { CoinShallowPackedVector r; assert( r.getNumElements()==0 ); // Test setting/getting elements with int* & double* vectors r.setVector( ne, inx, el ); assert( r.getNumElements()==ne ); for ( i=0; i<ne; i++ ) { assert( r.getIndices()[i] == inx[i] ); assert( r.getElements()[i] == el[i] ); } assert ( r.getMaxIndex()==7 ); assert ( r.getMinIndex()==1 ); // try to clear it r.clear(); assert( r.indices_==NULL ); assert( r.elements_==NULL ); assert( r.nElements_==0 ); // Test setting/getting elements with indices out of order const int ne2 = 5; int inx2[ne2] = { 2, 4, 8, 14, 3 }; double el2[ne2] = { 2.2, 4.4, 6.6, 8.8, 3.3 }; r.setVector(ne2,inx2,el2); assert( r.getNumElements()==ne2 ); for (i = 0; i < ne2; ++i) { assert( r.getIndices()[i]==inx2[i] ); assert( r.getElements()[i]==el2[i] ); } assert ( r.getMaxIndex()==14 ); assert ( r.getMinIndex()==2 ); // try to call it once more assert ( r.getMaxIndex()==14 ); assert ( r.getMinIndex()==2 ); CoinShallowPackedVector r1(ne2,inx2,el2); assert( r == r1 ); // assignment operator r1.clear(); r1 = r; assert( r == r1 ); // assignment from packed vector CoinPackedVector pv1(ne2,inx2,el2); r1 = pv1; assert( r == r1 ); // construction CoinShallowPackedVector r2(r1); assert( r2 == r ); // construction from packed vector CoinShallowPackedVector r3(pv1); assert( r3 == r ); // test duplicate indices { const int ne3 = 4; int inx3[ne3] = { 2, 4, 2, 3 }; double el3[ne3] = { 2.2, 4.4, 8.8, 6.6 }; r.setVector(ne3,inx3,el3, false); assert(r.testForDuplicateIndex() == false); bool errorThrown = false; try { r.setTestForDuplicateIndex(true); } catch (CoinError& e) { errorThrown = true; } assert( errorThrown ); r.clear(); errorThrown = false; try { r.setVector(ne3,inx3,el3); } catch (CoinError& e) { errorThrown = true; } assert( errorThrown ); errorThrown = false; try { CoinShallowPackedVector r1(ne3,inx3,el3); } catch (CoinError& e) { errorThrown = true; } assert( errorThrown ); } } // Test copy constructor and assignment operator { CoinShallowPackedVector rhs; { CoinShallowPackedVector r; { CoinShallowPackedVector rC1(r); assert( 0==r.getNumElements() ); assert( 0==rC1.getNumElements() ); r.setVector( ne, inx, el ); assert( ne==r.getNumElements() ); assert( 0==rC1.getNumElements() ); } CoinShallowPackedVector rC2(r); assert( ne==r.getNumElements() ); assert( ne==rC2.getNumElements() ); for ( i=0; i<ne; i++ ) { assert( r.getIndices()[i] == rC2.getIndices()[i] ); assert( r.getElements()[i] == rC2.getElements()[i] ); } rhs=rC2; } // Test that rhs has correct values even though lhs has gone out of scope assert( rhs.getNumElements()==ne ); for ( i=0; i<ne; i++ ) { assert( inx[i] == rhs.getIndices()[i] ); assert( el[i] == rhs.getElements()[i] ); } } // Test operator== { CoinShallowPackedVector v1,v2; assert( v1==v2 ); assert( v2==v1 ); assert( v1==v1 ); assert( !(v1!=v2) ); v1.setVector( ne, inx, el ); assert ( !(v1==v2) ); assert ( v1!=v2 ); CoinShallowPackedVector v3(v1); assert( v3==v1 ); assert( v3!=v2 ); CoinShallowPackedVector v4(v2); assert( v4!=v1 ); assert( v4==v2 ); } { // Test operator[] and isExistingIndex() const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinShallowPackedVector r; assert( r[1]==0. ); r.setVector(ne,inx,el); assert( r[-1]==0. ); assert( r[ 0]==1. ); assert( r[ 1]==10.); assert( r[ 2]==50.); assert( r[ 3]==0. ); assert( r[ 4]==40.); assert( r[ 5]==0. ); assert( r.isExistingIndex(2) ); assert( !r.isExistingIndex(3) ); assert( !r.isExistingIndex(-1) ); assert( r.isExistingIndex(0) ); assert( !r.isExistingIndex(3) ); assert( r.isExistingIndex(4) ); assert( !r.isExistingIndex(5) ); assert ( r.getMaxIndex()==4 ); assert ( r.getMinIndex()==0 ); } // Test that attemping to get min/max index of a 0, // length vector { CoinShallowPackedVector nullVec; assert( nullVec.getMaxIndex() == -COIN_INT_MAX/*0*/ ); assert( nullVec.getMinIndex() == COIN_INT_MAX/*0*/ ); } { // test dense vector const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinShallowPackedVector r; r.setVector(ne,inx,el); double * dense = r.denseVector(6); assert(dense[0] == 1.); assert(dense[1] == 10.); assert(dense[2] == 50.); assert(dense[3] == 0.); assert(dense[4] == 40.); assert(dense[5] == 0.); delete[] dense; // try once more dense = r.denseVector(7); assert(dense[0] == 1.); assert(dense[1] == 10.); assert(dense[2] == 50.); assert(dense[3] == 0.); assert(dense[4] == 40.); assert(dense[5] == 0.); assert(dense[6] == 0.); delete[] dense; } #if 0 // what happens when someone sets // the number of elements to be a negative number { const int ne = 4; int inx1[ne] = { 1, 3, 4, 7 }; double el1[ne] = { 1.2, 3.4, 5.6, 7.8 }; CoinShallowPackedVector v1; v1.setVector(-ne,inx1,el1); } #endif // Test adding vectors { const int ne1 = 5; int inx1[ne1] = { 1, 3, 4, 7, 5 }; double el1[ne1] = { 1., 5., 6., 2., 9. }; const int ne2 = 4; int inx2[ne2] = { 7, 4, 2, 1 }; double el2[ne2] = { 7., 4., 2., 1. }; CoinShallowPackedVector v1; v1.setVector(ne1,inx1,el1); CoinShallowPackedVector v2; v2.setVector(ne2,inx2,el2); CoinPackedVector r = v1 + v2; const int ner = 6; int inxr[ner] = { 1, 2, 3, 4, 5, 7 }; double elr[ner] = { 1.+1., 0.+2., 5.+0., 6.+4., 9.+0., 2.+7. }; CoinPackedVector rV; rV.setVector(ner,inxr,elr); assert( rV != r ); assert( r.isEquivalent(rV) ); CoinPackedVector p1=v1+3.1415; for ( i=0; i<p1.getNumElements(); i++ ) assert( eq( p1.getElements()[i], v1.getElements()[i]+3.1415) ); CoinPackedVector p2=(-3.1415) + p1; assert( p2.isEquivalent(v1) ); } // Test subtracting vectors { const int ne1 = 5; int inx1[ne1] = { 1, 3, 4, 7, 5 }; double el1[ne1] = { 1., 5., 6., 2., 9. }; const int ne2 = 4; int inx2[ne2] = { 7, 4, 2, 1 }; double el2[ne2] = { 7., 4., 2., 1. }; CoinShallowPackedVector v1; v1.setVector(ne1,inx1,el1); CoinShallowPackedVector v2; v2.setVector(ne2,inx2,el2); CoinPackedVector r = v1 - v2; const int ner = 6; int inxr[ner] = { 1, 2, 3, 4, 5, 7 }; double elr[ner] = { 1.-1., 0.-2., 5.-0., 6.-4., 9.-0., 2.-7. }; CoinPackedVector rV; rV.setVector(ner,inxr,elr); assert( r.isEquivalent(rV) ); CoinPackedVector p1=v1-3.1415; for ( i=0; i<p1.getNumElements(); i++ ) assert( eq( p1.getElements()[i], v1.getElements()[i]-3.1415) ); } // Test multiplying vectors { const int ne1 = 5; int inx1[ne1] = { 1, 3, 4, 7, 5 }; double el1[ne1] = { 1., 5., 6., 2., 9. }; const int ne2 = 4; int inx2[ne2] = { 7, 4, 2, 1 }; double el2[ne2] = { 7., 4., 2., 1. }; CoinShallowPackedVector v1; v1.setVector(ne1,inx1,el1); CoinShallowPackedVector v2; v2.setVector(ne2,inx2,el2); CoinPackedVector r = v1 * v2; const int ner = 6; int inxr[ner] = { 1, 2, 3, 4, 5, 7 }; double elr[ner] = { 1.*1., 0.*2., 5.*0., 6.*4., 9.*0., 2.*7. }; CoinPackedVector rV; rV.setVector(ner,inxr,elr); assert( r.isEquivalent(rV) ); CoinPackedVector p1=v1*3.3; for ( i=0; i<p1.getNumElements(); i++ ) assert( eq( p1.getElements()[i], v1.getElements()[i]*3.3) ); CoinPackedVector p2=(1./3.3) * p1; assert( p2.isEquivalent(v1) ); } // Test dividing vectors { const int ne1 = 3; int inx1[ne1] = { 1, 4, 7 }; double el1[ne1] = { 1., 6., 2. }; const int ne2 = 4; int inx2[ne2] = { 7, 4, 2, 1 }; double el2[ne2] = { 7., 4., 2., 1. }; CoinShallowPackedVector v1; v1.setVector(ne1,inx1,el1); CoinShallowPackedVector v2; v2.setVector(ne2,inx2,el2); CoinPackedVector r = v1 / v2; const int ner = 4; int inxr[ner] = { 1, 2, 4, 7 }; double elr[ner] = { 1./1., 0./2., 6./4., 2./7. }; CoinPackedVector rV; rV.setVector(ner,inxr,elr); assert( r.isEquivalent(rV) ); CoinPackedVector p1=v1/3.1415; for ( i=0; i<p1.getNumElements(); i++ ) assert( eq( p1.getElements()[i], v1.getElements()[i]/3.1415) ); } // Test sum { CoinShallowPackedVector s; assert( s.sum() == 0 ); int inx = 25; double value = 45.; s.setVector(1, &inx, &value); assert(s.sum()==45.); const int ne1 = 5; int inx1[ne1] = { 10, 3, 4, 7, 5 }; double el1[ne1] = { 1., 5., 6., 2., 9. }; s.setVector(ne1,inx1,el1); assert(s.sum()==1.+5.+6.+2.+9.); } // Just another interesting test { // Create numerator vector const int ne1 = 2; int inx1[ne1] = { 1, 4 }; double el1[ne1] = { 1., 6. }; CoinShallowPackedVector v1(ne1,inx1,el1); // create denominator vector const int ne2 = 3; int inx2[ne2] = { 1, 2, 4 }; double el2[ne2] = { 1., 7., 4.}; CoinShallowPackedVector v2(ne2,inx2,el2); // Compute ratio CoinPackedVector ratio = v1 / v2; // Sort ratios ratio.sortIncrElement(); // Test that the sort really worked assert( ratio.getElements()[0] == 0.0/7.0 ); assert( ratio.getElements()[1] == 1.0/1.0 ); assert( ratio.getElements()[2] == 6.0/4.0 ); // Get numerator of of sorted ratio vector assert( v1[ ratio.getIndices()[0] ] == 0.0 ); assert( v1[ ratio.getIndices()[1] ] == 1.0 ); assert( v1[ ratio.getIndices()[2] ] == 6.0 ); // Get denominator of of sorted ratio vector assert( v2[ ratio.getIndices()[0] ] == 7.0 ); assert( v2[ ratio.getIndices()[1] ] == 1.0 ); assert( v2[ ratio.getIndices()[2] ] == 4.0 ); } { // Test that sample usage works const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinShallowPackedVector r(ne,inx,el); assert( r.getIndices()[0]== 1 ); assert( r.getElements()[0]==10. ); assert( r.getIndices()[1]== 4 ); assert( r.getElements()[1]==40. ); assert( r.getIndices()[2]== 0 ); assert( r.getElements()[2]== 1. ); assert( r.getIndices()[3]== 2 ); assert( r.getElements()[3]==50. ); assert( r[ 0]==1. ); assert( r[ 1]==10.); assert( r[ 2]==50.); assert( r[ 3]==0. ); assert( r[ 4]==40.); CoinShallowPackedVector r1; r1=r; assert( r==r1 ); CoinPackedVector add = r + r1; assert( add[0] == 1.+ 1. ); assert( add[1] == 10.+10. ); assert( add[2] == 50.+50. ); assert( add[3] == 0.+ 0. ); assert( add[4] == 40.+40. ); assert( r.sum() == 10.+40.+1.+50. ); } { // Test findIndex const int ne = 4; int inx[ne] = { 1, -4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinShallowPackedVector r(ne,inx,el); assert( r.findIndex(2) == 3 ); assert( r.findIndex(0) == 2 ); assert( r.findIndex(-4) == 1 ); assert( r.findIndex(1) == 0 ); assert( r.findIndex(3) == -1 ); } { // Test construction with testing for duplicates as false const int ne = 4; int inx[ne] = { 1, -4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinShallowPackedVector r(ne,inx,el,false); assert( r.isExistingIndex(1) ); assert( r.isExistingIndex(-4) ); assert( r.isExistingIndex(0) ); assert( r.isExistingIndex(2) ); assert( !r.isExistingIndex(3) ); assert( !r.isExistingIndex(-3) ); } }