#ifndef _PAPILO_CORE_STORED_HPP_
#define _PAPILO_CORE_STORED_HPP_
#include "papilo/misc/Num.hpp"
#include "papilo/core/Problem.hpp"
namespace papilo
{
template <typename REAL>
class BoundStorage
{
private:
Num<REAL> num;
Vec<REAL> col_cost;
Vec<REAL> row_lhs;
Vec<REAL> row_rhs;
Vec<int> row_infinity_lhs;
Vec<int> row_infinity_rhs;
public:
Vec<int> col_infinity_lower;
Vec<int> col_infinity_upper;
Vec<REAL> col_lower;
Vec<REAL> col_upper;
public:
BoundStorage( const Num<REAL>& n, int cols, int rows, bool is_primal_dual )
{
if( ! is_primal_dual )
return;
num = n;
col_cost.assign( cols, 0 );
col_lower.assign( cols, 0 );
col_upper.assign( cols, 0 );
row_lhs.assign( rows, 0 );
row_rhs.assign( rows, 0 );
col_infinity_upper.assign( cols, 1 );
col_infinity_lower.assign( cols, 1 );
row_infinity_rhs.assign( rows, 1 );
row_infinity_lhs.assign( rows, 1 );
}
void
set_bounds_of_variable( int col, bool lb_inf, bool ub_inf, REAL lb, REAL ub )
{
assert( lb_inf || ub_inf || lb <= ub );
col_lower[col] = lb;
col_upper[col] = ub;
col_infinity_lower[col] = lb_inf;
col_infinity_upper[col] = ub_inf;
}
void
set_bound_of_variable( int col, bool is_lower, bool inf, REAL value )
{
if( is_lower )
{
col_lower[col] = value;
col_infinity_lower[col] = inf;
}
else
{
col_upper[col] = value;
col_infinity_upper[col] = inf;
}
}
bool
is_lower_and_upper_bound_infinity( int col )
{
return col_infinity_lower[col] && col_infinity_upper[col];
}
void
set_bounds_of_row( int row, bool lhs_inf, bool rhs_inf, REAL lhs, REAL rhs )
{
assert( rhs_inf || lhs_inf || lhs <= rhs );
row_lhs[row] = lhs;
row_rhs[row] = rhs;
row_infinity_lhs[row] = rhs_inf;
row_infinity_rhs[row] = lhs_inf;
}
bool
is_on_upper_bound( int col, REAL value )
{
return ! col_infinity_upper[col] && num.isEq( value, col_upper[col] );
}
bool
is_on_lower_bound( int col, REAL value )
{
return ! col_infinity_lower[col] && num.isEq( value, col_lower[col] );
}
bool
check_bounds( const Problem<REAL>& problem )
{
const Vec<ColFlags>& colFlags = problem.getColFlags();
const Vec<REAL>& lowerBounds = problem.getLowerBounds();
const Vec<REAL>& upperBounds = problem.getUpperBounds();
for( int i = 0; i < problem.getNCols(); i++ )
{
if( colFlags[i].test( ColFlag::kInactive ) )
continue;
if( col_infinity_lower[i] != colFlags[i].test( ColFlag::kLbInf ) )
return false;
if( col_infinity_upper[i] != colFlags[i].test( ColFlag::kUbInf ) )
return false;
if( !num.isEq( col_upper[i], upperBounds[i] ) &&
!colFlags[i].test( ColFlag::kUbInf ) )
return false;
if( !num.isEq( col_lower[i], lowerBounds[i] ) &&
!colFlags[i].test( ColFlag::kLbInf ) )
return false;
}
return true;
}
};
}
#endif