// Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. #include "OsiConfig.h" #include #include #include #include #include #include #include #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "CoinPackedVector.hpp" #include "CoinPackedMatrix.hpp" #include "CoinTime.hpp" #include "opbdp_solve.hpp" #include "PBCS.h" // Not threadsafe static unsigned int ** opbdp_solution=NULL; static int opbdp_number_solutions=0; static int opbdp_maximum_solutions=0; static int size_solution=0; static PBCS *save_pbcs=NULL; void opbdp_save_solution(OrdInt & sol) { if (opbdp_number_solutions==opbdp_maximum_solutions) { opbdp_maximum_solutions = opbdp_maximum_solutions*2+100; unsigned int ** temp = new unsigned int * [opbdp_maximum_solutions]; CoinMemcpyN(opbdp_solution,opbdp_number_solutions,temp); CoinZeroN(temp+opbdp_number_solutions,opbdp_maximum_solutions-opbdp_number_solutions); delete [] opbdp_solution; opbdp_solution=temp; } unsigned int * array = new unsigned int [size_solution]; CoinZeroN(array,size_solution); opbdp_solution[opbdp_number_solutions++]=array; sol.first(); while(!sol.last()) { int var = sol.next(); if (var > 0) setAtOne(var-1,array,true); } OrdInt Fixed = save_pbcs->get_fixed(); Fixed.first(); while(!Fixed.last()) { int flit = Fixed.next(); if (flit > 0) setAtOne(flit-1,array,true); } // add hidden ones due to equations save_pbcs->Eq.first(); while(!save_pbcs->Eq.last()) { int l = save_pbcs->Eq.next(); int r = save_pbcs->Eq(l); if (sol.member(r) || Fixed.member(r)) setAtOne(l-1,array,true); else if (sol.member(-r) || Fixed.member(-r)) setAtOne(l-1,array,true); // just positives are added } } //------------------------------------------------------------------- // Returns the greatest common denominator of two // positive integers, a and b, found using Euclid's algorithm //------------------------------------------------------------------- static int gcd(int a, int b) { int remainder = -1; // make sure a<=b (will always remain so) if(a > b) { // Swap a and b int temp = a; a = b; b = temp; } // if zero then gcd is nonzero (zero may occur in rhs of packed) if (!a) { if (b) { return b; } else { printf("**** gcd given two zeros!!\n"); abort(); } } while (remainder) { remainder = b % a; b = a; a = remainder; } return b; } static int solve(const OsiSolverInterface * model,PBCS & pbcs, OrdInt & sol) { int numberColumns = model->getNumCols(); size_solution = (numberColumns+31)/32; int numberRows = model->getNumRows(); bool all01=true; int i; const double * objective = model->getObjCoefficients(); double infinity = model->getInfinity(); const CoinPackedMatrix * matrix = model->getMatrixByRow(); const double * columnLower = model->getColLower(); const double * columnUpper = model->getColUpper(); const double * rowLower = model->getRowLower(); const double * rowUpper = model->getRowUpper(); for (i = 0; i < numberColumns; i++) { if (!model->isInteger(i)||columnLower[i]<0.0||columnUpper[i]>1.0) { all01=false; break; } } if (!all01) return -1; // Get scale factors to make integral const int * column = matrix->getIndices(); const int * rowLength = matrix->getVectorLengths(); const CoinBigIndex * rowStart = matrix->getVectorStarts(); const double * elementByRow = matrix->getElements(); // objective not too important double maximumObjElement = 0.0 ; for (i = 0 ; i < numberColumns ; i++) maximumObjElement = CoinMax(maximumObjElement,fabs(objective[i])) ; int objGood = 0 ; double objMultiplier = 2520.0 ; bool good=true; if (maximumObjElement) { while (10.0*objMultiplier*maximumObjElement < 1.0e9) objMultiplier *= 10.0 ; if (maximumObjElement*2520>=1.0e9) objMultiplier=1.0; double tolerance = 1.0e-9*objMultiplier; for (i = 0 ; i < numberColumns ; i++) { double value=fabs(objective[i])*objMultiplier ; if (!value) continue; int nearest = (int) floor(value+0.5) ; if (fabs(value-floor(value+0.5)) > tolerance) { // just take for now objGood = 1 ; good=false; break ; } else if (!objGood) { objGood = nearest ; } else { objGood = gcd(objGood,nearest) ; } } objMultiplier /= objGood; if (!good) { printf("Unable to scale objective correctly - maximum %g\n", maximumObjElement); objMultiplier = 1.0e7/maximumObjElement; } } else { objMultiplier=0.0; // no objective } double maximumElement=0.0; // now real stuff for (i=0;i=1.0e8) elMultiplier=1.0; double tolerance = 1.0e-8*elMultiplier; good=true; for (i=0;i tolerance) { elGood = 0 ; good=false; break ; } else if (!elGood) { elGood = nearest ; } else { elGood = gcd(elGood,nearest) ; } } } if (rowUpper[i]!=infinity) { double value=fabs(rowUpper[i])*elMultiplier ; if (value) { int nearest = (int) floor(value+0.5) ; if (fabs(value-floor(value+0.5)) > tolerance) { elGood = 0 ; good=false; break ; } else if (!elGood) { elGood = nearest ; } else { elGood = gcd(elGood,nearest) ; } } } for (CoinBigIndex j=rowStart[i];j tolerance) { elGood = 0 ; good=false; break ; } else if (!elGood) { elGood = nearest ; } else { elGood = gcd(elGood,nearest) ; } } } if (!good) return -1; // no good // multiplier elMultiplier /= elGood; double objOffset=0.0; model->getDblParam(OsiObjOffset,objOffset); int doMax= (model->getObjSense()<0.0) ? 1 : 0; printf("Objective multiplier is %g, element mutiplier %g, offset %g\n", objMultiplier,elMultiplier,objOffset); Products objf; Atoms atoms; save_pbcs = & pbcs; pbcs.set_atoms(&atoms); pbcs.set_enum_heuristic(0); for (i=0;i 1) std::cout << "Big M coefficient reduction changed " << changed << " coefficients"<0) { const double * objective = model->getObjCoefficients(); double objOffset=0.0; model->getDblParam(OsiObjOffset,objOffset); int numberColumns = model->getNumCols(); double * solution = new double [numberColumns]; CoinZeroN(solution,numberColumns); sol.first(); while(!sol.last()) { int var = sol.next(); if (var > 0) solution[var-1]=1.0; } OrdInt Fixed = pbcs.get_fixed(); Fixed.first(); while(!Fixed.last()) { int flit = Fixed.next(); if (flit > 0) solution[flit-1]=1.0; } // add hidden ones due to equations pbcs.Eq.first(); while(!pbcs.Eq.last()) { int l = pbcs.Eq.next(); int r = pbcs.Eq(l); if (sol.member(r) || Fixed.member(r)) solution[l-1]=1.0; else if (sol.member(-r) || Fixed.member(-r)) solution[l-1]=1.0; // just positives are added } numberFound=1; double objValue = - objOffset; for (int i=0;igetObjSense()>0 ? "minimum" : "maximum")<<" of "<setObjValue(objValue); model->setColSolution(solution); delete [] solution; } else if (!numberFound) { std::cout << "Constraint Set is unsatisfiable"<0||opbdp_number_solutions) { // all solutions numberFound = opbdp_number_solutions; return opbdp_solution; } else { // no solution return NULL; } }