/**
* @brief Test if half-planes defines a non empty volume
* @param hplanes A list of half planes
* @retval true If half-planes define a non empty volume
* @retval false If half-planes define an empty volume
* @note Searched volume is defined by intersection of positive sides of half-planes
* @ref :
 [1] Paper: Finding the intersection of n half-spaces in time O(n log n).
 Author: F.P. Preparata, D.E. Muller
 Published in: Theoretical Computer Science, Volume 8, Issue 1, Pages 45-55
 Year: 1979
 More: ISSN 0304-3975, http://dx.doi.org/10.1016/0304-3975(79)90055-0.
*/
static bool isNotEmpty( const Half_planes & hplanes )
{
  // Check if it exists a point on all positive side of the half plane thanks to a Linear Program formulation [1].
  // => If a point exists: there is a common subspace defined and so intersections.
  // The LP formulation consists in set the Half_plane as constraint and check if a point can fit the equations.

  using namespace openMVG;
  using namespace openMVG::linearProgramming;

  LP_Constraints cstraint;
  {
    cstraint.nbParams_ = 3; // {X,Y,Z}
    cstraint.vec_bounds_.resize( cstraint.nbParams_ );
    std::fill( cstraint.vec_bounds_.begin(), cstraint.vec_bounds_.end(),
               std::make_pair( ( double ) - 1e+30, ( double )1e+30 ) ); // [X,Y,Z] => -inf, +inf
    cstraint.bminimize_ = true;

    // Configure constraints
    const size_t nbConstraints = hplanes.size();
    cstraint.constraint_mat_.resize( nbConstraints, 3 );
    cstraint.vec_sign_.resize( nbConstraints );
    cstraint.constraint_objective_ = Vec( nbConstraints );

    // Fill the constrains (half-space equations)
    for ( unsigned char i = 0; i < hplanes.size(); ++i )
    {
      const Vec & half_plane_coeff = hplanes[i].coeffs();
      // add the half plane equation to the system
      cstraint.constraint_mat_.row( i ) =
        Vec3( half_plane_coeff( 0 ),
              half_plane_coeff( 1 ),
              half_plane_coeff( 2 ) );
      cstraint.vec_sign_[i] = LP_Constraints::LP_GREATER_OR_EQUAL;
      cstraint.constraint_objective_( i ) = - half_plane_coeff( 3 );
    }
  }

  // Solve in order to see if a point exists within the half spaces positive side?
  OSI_CLP_SolverWrapper solver( cstraint.nbParams_ );
  solver.setup( cstraint );
  const bool bIntersect = solver.solve(); // Status of the solver tell if there is an intersection or not
  return bIntersect;
}
Example #2
0
bool OSI_X_SolverWrapper<SOLVERINTERFACE>::setup(const LP_Constraints & cstraints) //cstraints <-> constraints
{
  bool bOk = true;
  if ( si == NULL )
  {
    return false;
  }
  assert(nbParams_ == cstraints.nbParams_);

  const unsigned int NUMVAR = cstraints.constraint_mat_.cols();
  std::vector<double> col_lb(NUMVAR);//the column lower bounds
  std::vector<double> col_ub(NUMVAR);//the column upper bounds

  this->nbParams_ = NUMVAR;

  si->setObjSense( ((cstraints.bminimize_) ? 1 : -1) );

  const Mat & A = cstraints.constraint_mat_;

  //Equality constraint will be done by two constraints due to the API limitation ( >= & <=).
  const size_t nbLine = A.rows() +
    std::count(cstraints.vec_sign_.begin(), cstraints.vec_sign_.end(), LP_Constraints::LP_EQUAL);

  std::vector<double> row_lb(nbLine);//the row lower bounds
  std::vector<double> row_ub(nbLine);//the row upper bounds

  CoinPackedMatrix * matrix = new CoinPackedMatrix(false,0,0);
  matrix->setDimensions(0, NUMVAR);

  //-- Add row-wise constraint
  size_t indexRow = 0;
  for (int i=0; i < A.rows(); ++i)
  {
    Vec temp = A.row(i);

    CoinPackedVector row;
    if ( cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL || cstraints.vec_sign_[i] == LP_Constraints::LP_LESS_OR_EQUAL )
    {
      int coef = 1;
      for ( int j = 0; j < A.cols() ; j++ )
      {
        row.insert(j, coef * temp.data()[j]);
      }
      row_lb[indexRow] = -1.0 * si->getInfinity();
      row_ub[indexRow] = coef * cstraints.constraint_objective_(i);
      matrix->appendRow(row);
      indexRow++;
    }
    if ( cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL || cstraints.vec_sign_[i] == LP_Constraints::LP_GREATER_OR_EQUAL )
    {
      int coef = -1;
      for ( int j = 0; j < A.cols() ; j++ )
      {
	      row.insert(j, coef * temp.data()[j]);
      }
      row_lb[indexRow] = -1.0 * si->getInfinity();
      row_ub[indexRow] = coef * cstraints.constraint_objective_(i);
      matrix->appendRow(row);
      indexRow++;
    }
  }

  //-- Setup bounds for all the parameters
  if (cstraints.vec_bounds_.size() == 1)
  {
    // Setup the same bound for all the parameters
    for (int i=0; i < this->nbParams_; ++i)
    {
      col_lb[i] = cstraints.vec_bounds_[0].first;
      col_ub[i] = cstraints.vec_bounds_[0].second;
    }
  }
  else // each parameter have it's own bounds
  {
    for (int i=0; i < this->nbParams_; ++i)
    {
      col_lb[i] = cstraints.vec_bounds_[i].first;
      col_ub[i] = cstraints.vec_bounds_[i].second;
    }
  }

  si->loadProblem(*matrix, &col_lb[0], &col_ub[0], cstraints.vec_cost_.empty() ? NULL : &cstraints.vec_cost_[0], &row_lb[0], &row_ub[0] );

  delete matrix;

  return bOk;
}
bool MOSEK_SolveWrapper::setup(const LP_Constraints & cstraints) //cstraints <-> constraints
{
  assert(nbParams_ == cstraints.nbParams_);

  MSK_deletetask(&task);

  int NUMVAR = cstraints.constraint_mat_.cols();
  int NUMCON = cstraints.constraint_mat_.rows();
  int NUMANZ = cstraints.constraint_mat_.cols() * cstraints.constraint_mat_.rows(); //DENSE MATRIX

  MSKrescodee r = MSK_RES_OK;
  if ( r==MSK_RES_OK )
  {
    // Create the optimization task.
    r = MSK_maketask(env,NUMCON,NUMVAR,&task);

    // Directs the log task stream to the 'printstr' function.
    if ( r==MSK_RES_OK )
      MSK_linkfunctotaskstream(task,MSK_STREAM_LOG,NULL,printstr);

    // Give MOSEK an estimate of the size of the input data.
    //This is done to increase the speed of inputting data.
    // However, it is optional.
    if (r == MSK_RES_OK)
      r = MSK_putmaxnumvar(task,NUMVAR);

    if (r == MSK_RES_OK)
      r = MSK_putmaxnumcon(task,NUMCON);

    if (r == MSK_RES_OK)
      r = MSK_putmaxnumanz(task,NUMANZ);

    // Append 'NUMCON' empty constraints. The constraints will initially have no bounds.
    if ( r == MSK_RES_OK )
      r = MSK_append(task,MSK_ACC_CON,NUMCON);

    // Append 'NUMVAR' variables. The variables will initially be fixed at zero (x=0).
    if ( r == MSK_RES_OK )
      r = MSK_append(task,MSK_ACC_VAR,NUMVAR);
  }

  this->nbParams_ = NUMVAR;

  if (cstraints.bminimize_) {
    r = MSK_putobjsense(task, MSK_OBJECTIVE_SENSE_MINIMIZE);
  }
  else  {
    r = MSK_putobjsense(task, MSK_OBJECTIVE_SENSE_MAXIMIZE);
  }

  // Optionally add a constant term to the objective.
  if ( r ==MSK_RES_OK )
    r = MSK_putcfix(task,0.0);

  // Add the objective function if any
  if (!cstraints.vec_cost_.empty())  {
    // Set objective
    for (size_t i = 0; i < cstraints.vec_cost_.size(); ++i)
      MSK_putcj(task, i, cstraints.vec_cost_[i]);
  }

  //Add constraint row by row
  const Mat & A = cstraints.constraint_mat_;

  for (int i=0; i<A.rows() && r == MSK_RES_OK; ++i)
  {
    std::vector<int> vec_colno(A.cols(), 0);
    for (int ii=0; ii<A.cols(); ++ii){
      vec_colno[ii] = ii;
    }

    // Insert a row
    Vec temp = A.row(i);
    r = MSK_putavec(task,
                    MSK_ACC_CON,       // Input row of A.
                    MSKidxt (i),       // Variable row index.
                    vec_colno.size(),  // Number of non-zeros in row(i) A.
                    &vec_colno[0],     // Pointer to row indexes of row i.
                    (double*)temp.data());    // Pointer to Values of row i.
  }

  //Add bound on variables:
  if (cstraints.vec_bounds_.size() == 1) {
    for (size_t i = 0; i < NUMVAR; ++i) {
      if (r == MSK_RES_OK)
        r = MSK_putbound(task,
                         MSK_ACC_VAR, // Put bounds on variables.
                         i,           // Index of variable.
                         convertSign(cstraints.vec_sign_[0]),      // Bound key.
                         cstraints.vec_bounds_[0].first,  // Numerical value of lower bound.
                         cstraints.vec_bounds_[0].second); // Numerical value of upper bound.
    }
  }
  else{
    for (size_t i = 0; i < NUMVAR; ++i) {
    // Set the bounds on variable j.
    //    lowerbound <= x_j <= upper bound
      if (r == MSK_RES_OK)
        r = MSK_putbound(task,
                         MSK_ACC_VAR, // Put bounds on variables.
                         i,           // Index of variable.
                         convertSign(cstraints.vec_sign_[i]),      // Bound key.
                         cstraints.vec_bounds_[i].first,  // Numerical value of lower bound.
                         cstraints.vec_bounds_[i].second); // Numerical value of upper bound.
    // in order to add sparse bounds use: MSK_putboundlist
    }
  }

  // Add bounds on constraint
  for (size_t i=0; i<NUMCON && r==MSK_RES_OK; ++i)
  {
    r = MSK_putbound(task,
                     MSK_ACC_CON, // Put bounds on constraints.
                     i,           // Index of constraint.
                     convertSign(cstraints.vec_sign_[i]),      // Bound key.
                     -MSK_INFINITY,  // Numerical value of lower bound.
                     cstraints.constraint_objective_(i)); // Numerical value of upper bound.
  }

  return r == MSK_RES_OK;
}
bool OSI_X_SolverWrapper::setup(const LP_Constraints & cstraints) //cstraints <-> constraints
{
  if ( si == nullptr )
  {
    return false;
  }
  assert(nbParams_ == cstraints.nbParams_);

  const unsigned int NUMVAR = cstraints.constraint_mat_.cols();
  std::vector<double>
    col_lb(NUMVAR), // the column lower bounds
    col_ub(NUMVAR); // the column upper bounds

  this->nbParams_ = NUMVAR;

  si->setObjSense( ((cstraints.bminimize_) ? 1 : -1) );

  const Mat & A = cstraints.constraint_mat_;

  //Equality constraint will be done by two constraints due to the API limitation ( >= & <=).
  const size_t nbLine = A.rows() +
    std::count(cstraints.vec_sign_.begin(), cstraints.vec_sign_.end(), LP_Constraints::LP_EQUAL);

  // Define default lower and upper bound to [-inf, inf]
  std::vector<double>
    row_lb(nbLine, -si->getInfinity()), // the row lower bounds
    row_ub(nbLine, si->getInfinity()); // the row upper bounds

  std::unique_ptr<CoinPackedMatrix> matrix(new CoinPackedMatrix(false,0,0));
  matrix->setDimensions(0, NUMVAR);

  //-- Add row-wise constraint
  size_t indexRow = 0;
  for (int i=0; i < A.rows(); ++i)
  {
    const Vec temp = A.row(i);
    CoinPackedVector row;

    if (cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL ||
        cstraints.vec_sign_[i] == LP_Constraints::LP_LESS_OR_EQUAL)
    {
      const int coef = 1;
      for ( int j = 0; j < A.cols(); ++j )
      {
        row.insert(j, coef * temp.data()[j]);
      }
      row_ub[indexRow] = coef * cstraints.constraint_objective_(i);
      matrix->appendRow(row);
      ++indexRow;
    }

    if (cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL ||
        cstraints.vec_sign_[i] == LP_Constraints::LP_GREATER_OR_EQUAL)
    {
      const int coef = -1;
      for ( int j = 0; j < A.cols(); ++j )
      {
        row.insert(j, coef * temp.data()[j]);
      }
      row_ub[indexRow] = coef * cstraints.constraint_objective_(i);
      matrix->appendRow(row);
      ++indexRow;
    }
  }

  //-- Setup bounds for all the parameters
  if (cstraints.vec_bounds_.size() == 1)
  {
    // Setup the same bound for all the parameters
    std::fill(col_lb.begin(), col_lb.end(), cstraints.vec_bounds_[0].first);
    std::fill(col_ub.begin(), col_ub.end(), cstraints.vec_bounds_[0].second);
  }
  else // each parameter have its own bounds
  {
    for (int i=0; i < this->nbParams_; ++i)
    {
      col_lb[i] = cstraints.vec_bounds_[i].first;
      col_ub[i] = cstraints.vec_bounds_[i].second;
    }
  }

  si->loadProblem(*matrix, &col_lb[0], &col_ub[0], cstraints.vec_cost_.empty() ? nullptr : &cstraints.vec_cost_[0], &row_lb[0], &row_ub[0] );

  return true;
}
bool OSI_X_SolverWrapper<SOLVERINTERFACE>::setup(const LP_Constraints & cstraints) //cstraints <-> constraints
{
  bool bOk = true;
  if ( si == NULL )
  {
    return false;
  }
  assert(_nbParams == cstraints._nbParams);

  
  int NUMVAR = cstraints._constraintMat.cols();
  int NUMCON = cstraints._constraintMat.rows();
  int NUMANZ = cstraints._constraintMat.cols() * cstraints._constraintMat.rows(); //DENSE MATRIX
  
  std::vector<double> col_lb(NUMVAR);//the column lower bounds
  std::vector<double> col_ub(NUMVAR);//the column upper bounds
  
  this->_nbParams = NUMVAR;

  if (cstraints._bminimize) 
  {
    si->setObjSense( 1 );
  }
  else  
  {
    si->setObjSense( -1 );
  }

  const Mat & A = cstraints._constraintMat;

  //Equality constraint will be handked by two constraintsdue to the API limitation. 
  size_t nbLine = A.rows() + std::count(cstraints._vec_sign.begin(), cstraints._vec_sign.end(), EQ);
  
  std::vector<double> row_lb(nbLine);//the row lower bounds
  std::vector<double> row_ub(nbLine);//the row upper bounds
  
  CoinPackedMatrix * matrix = new CoinPackedMatrix(false,0,0);
  matrix->setDimensions(0, NUMVAR);

  
  //-- Add row-wise constraint
  size_t indexRow = 0;
  for (int i=0; i < A.rows(); ++i) 
  {
    Vec temp = A.row(i);
    
    CoinPackedVector row;
    if ( cstraints._vec_sign[i] == EQ || cstraints._vec_sign[i] == LE )
    {
      int coef = 1;
      for ( int j = 0; j < A.cols() ; j++ )
      {
	row.insert(j, coef * temp.data()[j]);
      }
      row_lb[indexRow] = -1.0 * si->getInfinity();
      row_ub[indexRow] = coef * cstraints._Cst_objective(i);
      matrix->appendRow(row);
      indexRow++;
    }
    if ( cstraints._vec_sign[i] == EQ || cstraints._vec_sign[i] == GE )
    {
      int coef = -1;
      for ( int j = 0; j < A.cols() ; j++ )
      {
	      row.insert(j, coef * temp.data()[j]);
      }
      row_lb[indexRow] = -1.0 * si->getInfinity();
      row_ub[indexRow] = coef * cstraints._Cst_objective(i);
      matrix->appendRow(row);      
      indexRow++;
    }
  }
  
  //-- Setup bounds
  if (cstraints._vec_bounds.size() == 1) 
  {
    // Setup the same bound for all the parameter
    for (int i=0; i < this->_nbParams; ++i)
    {
      col_lb[i] = cstraints._vec_bounds[0].first;
      col_ub[i] = cstraints._vec_bounds[0].second;
    }
  }
  else  
  {

    for (int i=0; i < this->_nbParams; ++i)
    {      
      col_lb[i] = cstraints._vec_bounds[i].first;
      col_ub[i] = cstraints._vec_bounds[i].second;
    }
  }  
 
  si->loadProblem(*matrix, &col_lb[0], &col_ub[0], cstraints._vec_cost.empty() ? NULL : &cstraints._vec_cost[0], &row_lb[0], &row_ub[0] );
  
  delete matrix;
  
  return bOk;
}