vector<const Match *> OptimalConstrainedMatches::calculateSubset() { _score = -1; vector<const Match*> result; if (_matches.size() == 0) { return result; } // figure out all the pairs of matches that conflict. _calculateMatchConflicts(); // if there are no conflicts, then there is nothing to solve. if (_conflicts.size() == 0) { LOG_DEBUG("No match conflicts found."); return _matches; } // populate the solver with IntegerProgrammingSolver solver; _populateSolver(solver); if (_timeLimit > 0) { solver.setTimeLimit(_timeLimit); } LOG_INFO("Calculating optimal match conflicts with an Integer Programming solution..."); // solve the Integer Programming problem. solver.solve(); _score = solver.getObjectiveValue(); result.reserve(_matches.size()); // go through all the columns (variables) for (int i = 0; i < solver.getNumColumns(); i++) { // if the value is close to 1 (as opposed to 0) if (solver.getColumnPrimalValue(i + 1) > 0.99) { // it is a keeper result.push_back(_matches[i]); } else { LOG_TRACE("Removing match: " << _matches[i]); } } return result; }
void OptimalConstrainedMatches::_populateSolver(IntegerProgrammingSolver& solver) { // try to maximize the score. solver.setObjectiveDirection(GLP_MAX); // each match is a column (variable) in the function that we want to maximize. solver.addColumns(_matches.size()); for (size_t i = 0; i < _matches.size(); i++) { solver.setColumnKind(i + 1, GLP_BV); //solver.setColumnBounds(i + 1, GLP_DB, 0.0, 1.0); // The score of a match is the coefficient. This makes higher score matches worth // more in the function. solver.setObjectiveCoefficient(i + 1, _matches[i]->getScore() + EPSILON); } // there is one row (constraint) for each conflict. solver.addRows(_conflicts.size()); vector<int> ia(_conflicts.size() * 2 + 1); vector<int> ja(_conflicts.size() * 2 + 1); vector<double> ra(_conflicts.size() * 2 + 1); int i = 0; for (MatchConflicts::ConflictMap::const_iterator it = _conflicts.constBegin(); it != _conflicts.constEnd(); ++it) { // Set the coefficients to 1 for each of the conflicting pairs and set the max value to 1. This // will make it so only one of the values can be 1 at a time, or they can both be 0. solver.setRowBounds(i + 1, GLP_DB, 0.0, 1.0); ia[i * 2 + 1] = i + 1; ja[i * 2 + 1] = (int)it.key() + 1; ra[i * 2 + 1] = 1.0; ia[i * 2 + 2] = i + 1; ja[i * 2 + 2] = (int)it.value() + 1; ra[i * 2 + 2] = 1.0; i++; } // Populate the row coefficients. solver.loadMatrix(ia, ja, ra); }
void runTest() { double z, x1, x2, x3; IntegerProgrammingSolver solver; solver.setProblemName("sample"); solver.setObjectiveDirection(GLP_MAX); solver.addRows(2); solver.setRowName(1, "p"); solver.setRowBounds(1, GLP_DB, 0.0, 1.0); solver.setRowName(2, "q"); solver.setRowBounds(2, GLP_DB, 0.0, 1.0); solver.addColumns(3); solver.setColumnName(1, "x1"); solver.setColumnKind(1, GLP_BV); solver.setColumnBounds(1, GLP_DB, 0.0, 1.0); solver.setObjectiveCoefficient(1, 0.4); solver.setColumnName(2, "x2"); solver.setColumnKind(2, GLP_BV); solver.setColumnBounds(2, GLP_DB, 0.0, 1.0); solver.setObjectiveCoefficient(2, 0.9); solver.setColumnName(3, "x3"); solver.setColumnKind(3, GLP_BV); solver.setColumnBounds(3, GLP_DB, 0.0, 1.0); solver.setObjectiveCoefficient(3, 0.6); vector<int> ia, ja; vector<double> ar; ia.push_back(-1); ja.push_back(-1); ar.push_back(-1); ia.push_back(1); ja.push_back(1); ar.push_back(1.0); ia.push_back(1); ja.push_back(2); ar.push_back(1.0); ia.push_back(1); ja.push_back(3); ar.push_back(0.0); //ia.push_back(2); ja.push_back(1); ar.push_back(0.0); ia.push_back(2); ja.push_back(2); ar.push_back(1.0); ia.push_back(2); ja.push_back(3); ar.push_back(1.0); solver.loadMatrix(ia, ja, ar); solver.solve(); z = solver.getObjectiveValue(); x1 = solver.getColumnPrimalValue(1); x2 = solver.getColumnPrimalValue(2); x3 = solver.getColumnPrimalValue(3); //LOG_INFO("z: " << z << " x1: " << x1 << " x2: " << x2 << " x3: " << x3); CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, z, 1e-5); CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, x1, 1e-5); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, x2, 1e-5); CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, x3, 1e-5); solver.setObjectiveCoefficient(3, 0.4); solver.solve(); z = solver.getObjectiveValue(); x1 = solver.getColumnPrimalValue(1); x2 = solver.getColumnPrimalValue(2); x3 = solver.getColumnPrimalValue(3); //LOG_INFO("z: " << z << " x1: " << x1 << " x2: " << x2 << " x3: " << x3); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.9, z, 1e-5); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, x1, 1e-5); CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, x2, 1e-5); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, x3, 1e-5); }
void runTest2() { double z, x1, x2, x3; IntegerProgrammingSolver solver; solver.setProblemName("sample"); solver.setObjectiveDirection(GLP_MAX); solver.addRows(1); // 0.0 <= p <= 1.1 solver.setRowName(1, "p"); // make sure it properly solves an integer problem. solver.setRowBounds(1, GLP_DB, 0.0, 1.1); // z = x1 + 2 * x2 + x3 solver.addColumns(3); solver.setColumnName(1, "x1"); solver.setColumnKind(1, GLP_BV); solver.setColumnBounds(1, GLP_DB, 0.0, 1.0); solver.setObjectiveCoefficient(1, 1.0); solver.setColumnName(2, "x2"); solver.setColumnKind(2, GLP_BV); solver.setColumnBounds(2, GLP_DB, 0.0, 1.0); solver.setObjectiveCoefficient(2, 2.0); solver.setColumnName(3, "x3"); solver.setColumnKind(3, GLP_BV); solver.setColumnBounds(3, GLP_DB, 0.0, 1.0); solver.setObjectiveCoefficient(3, 1.0); vector<int> ia, ja; vector<double> ar; ia.push_back(-1); ja.push_back(-1); ar.push_back(-1); // subject to constraint: // p = x1 + x2 + 0 * x3 ia.push_back(1); ja.push_back(1); ar.push_back(1.0); ia.push_back(1); ja.push_back(2); ar.push_back(1.0); ia.push_back(1); ja.push_back(3); ar.push_back(0.0); solver.loadMatrix(ia, ja, ar); solver.solve(); z = solver.getObjectiveValue(); x1 = solver.getColumnPrimalValue(1); x2 = solver.getColumnPrimalValue(2); x3 = solver.getColumnPrimalValue(3); //LOG_INFO("z: " << z << " x1: " << x1 << " x2: " << x2 << " x3: " << x3); CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, z, 1e-5); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, x1, 1e-5); CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, x2, 1e-5); CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, x3, 1e-5); }