#ifndef _PAPILO_MISC_VECTOR_UTILS_HPP_
#define _PAPILO_MISC_VECTOR_UTILS_HPP_
#include "papilo/core/Problem.hpp"
#include "papilo/core/RowFlags.hpp"
#include "papilo/core/Solution.hpp"
#include "papilo/core/SparseStorage.hpp"
#include "papilo/io/Message.hpp"
#include "papilo/misc/Num.hpp"
#include "papilo/misc/Vec.hpp"
#include "papilo/misc/fmt.hpp"
#include <cassert>
namespace papilo
{
template <typename REAL>
bool
compareVectors( const Vec<REAL>& first, const Vec<REAL>& second,
const Num<REAL>& num )
{
bool result = std::equal( first.begin(), first.end(), second.begin(),
[&num]( const REAL& left, const REAL& right ) {
return num.isEq( left, right );
} );
return result;
}
template <typename REAL>
bool
compareVariableDomains( const VariableDomains<REAL>& first,
const VariableDomains<REAL>& second,
const Num<REAL>& num )
{
bool result = std::equal( first.begin(), first.end(), second.begin(),
[&num]( const REAL& left, const REAL& right ) {
return num.isEq( left, right );
} );
return result;
}
template <typename REAL>
bool
compareColBounds( const Vec<REAL>& first_values, const Vec<REAL>& second_values,
const Vec<ColFlags>& first_flags,
const Vec<ColFlags>& second_flags, const Num<REAL>& num )
{
int size = (int) first_values.size();
if( size != (int) first_flags.size() )
return false;
if( size != (int) second_values.size() )
return false;
if( size != (int) second_flags.size() )
return false;
for( int i = 0; i < size; i++ )
{
if( ( first_flags[i].test( ColFlag::kLbInf ) !=
second_flags[i].test( ColFlag::kLbInf ) ) ||
( first_flags[i].test( ColFlag::kUbInf ) !=
second_flags[i].test( ColFlag::kUbInf ) ) )
return false;
if( !num.isEq( first_values[i], second_values[i] ) )
return false;
}
return true;
}
template <typename REAL>
bool
compareRowBounds( const Vec<REAL>& first_values, const Vec<REAL>& second_values,
const Vec<RowFlags>& first_flags,
const Vec<RowFlags>& second_flags, const Num<REAL>& num )
{
int size = (int) first_values.size();
if( size != (int) first_flags.size() )
return false;
if( size != (int) second_values.size() )
return false;
if( size != (int) second_flags.size() )
return false;
for( int i = 0; i < size; i++ )
{
if( ( first_flags[i].test( RowFlag::kLhsInf ) !=
second_flags[i].test( RowFlag::kLhsInf ) ) ||
( first_flags[i].test( RowFlag::kRhsInf ) !=
second_flags[i].test( RowFlag::kRhsInf ) ) )
return false;
if( !num.isEq( first_values[i], second_values[i] ) )
return false;
}
return true;
}
template <typename IndexRange>
bool
compareIndexRanges( const Vec<IndexRange>& first,
const Vec<IndexRange>& second )
{
bool result = std::equal(
first.begin(), first.end(), second.begin(),
[]( const IndexRange& left, const IndexRange& right ) {
return ( left.start == right.start && left.end == right.end );
} );
return result;
}
template <typename REAL>
bool
compareMatrices( const SparseStorage<REAL>& first,
const SparseStorage<REAL>& second, const Num<REAL>& num )
{
if( first.getNRows() != second.getNRows() )
return false;
if( first.getNCols() != second.getNCols() )
return false;
if( first.getNnz() != second.getNnz() )
return false;
if( !compareIndexRanges( first.getRowRangesVec(),
second.getRowRangesVec() ) )
return false;
if( !std::equal( first.getColumnsVec().begin(), first.getColumnsVec().end(),
second.getColumnsVec().begin() ) )
return false;
if( !compareVectors( first.getValuesVec(), second.getValuesVec(), num ) )
return false;
return true;
}
template <typename REAL>
bool
compareMatrixToTranspose( const SparseStorage<REAL>& first,
const SparseStorage<REAL>& second,
const Num<REAL>& num )
{
const SparseStorage<REAL> transpose = first.getTranspose();
bool result = compareMatrices( second, transpose, num );
return result;
}
template <typename REAL>
bool
compareMatrixToTranspose( const ConstraintMatrix<REAL>& constarint_matrix,
const Num<REAL>& num )
{
const SparseStorage<REAL>& matrix = constarint_matrix.getConstraintMatrix();
const SparseStorage<REAL>& transpose =
constarint_matrix.getMatrixTranspose();
return compareMatrixToTranspose( matrix, transpose, num );
}
template <typename REAL>
bool
compareProblems( const Problem<REAL>& first, const Problem<REAL>& second,
const Num<REAL>& num )
{
int nRows1 = first.getNRows();
int nRows2 = second.getNRows();
const int nCols1 = first.getNCols();
const int nCols2 = second.getNCols();
if( nRows1 != nRows2 )
return false;
if( nCols1 != nCols2 )
return false;
const Vec<REAL>& objective1 = first.getObjective().coefficients;
const Vec<REAL>& objective2 = second.getObjective().coefficients;
bool result = compareVectors( objective1, objective2, num );
if( !result )
return false;
result = compareColBounds( first.getLowerBounds(), second.getLowerBounds(),
first.getColFlags(), second.getColFlags(), num );
if( !result )
return false;
result = compareColBounds( first.getUpperBounds(), second.getUpperBounds(),
first.getColFlags(), second.getColFlags(), num );
if( !result )
return false;
result = compareRowBounds( first.getConstraintMatrix().getLeftHandSides(),
second.getConstraintMatrix().getLeftHandSides(),
first.getConstraintMatrix().getRowFlags(),
second.getConstraintMatrix().getRowFlags(), num );
if( !result )
return false;
result = compareMatrices( first.getConstraintMatrix().getConstraintMatrix(),
second.getConstraintMatrix().getConstraintMatrix(),
num );
if( !result )
return false;
result = compareMatrices( first.getConstraintMatrix().getMatrixTranspose(),
second.getConstraintMatrix().getMatrixTranspose(),
num );
if( !result )
return false;
result = compareMatrixToTranspose(
first.getConstraintMatrix().getConstraintMatrix(),
second.getConstraintMatrix().getMatrixTranspose(), num );
if( first.getObjective().offset != second.getObjective().offset )
return false;
return true;
}
}
#endif