/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ /* This file is part of the program and library */ /* PaPILO --- Parallel Presolve for Integer and Linear Optimization */ /* */ /* Copyright (C) 2020-2022 Konrad-Zuse-Zentrum */ /* fuer Informationstechnik Berlin */ /* */ /* This program is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU Lesser General Public License as published */ /* by the Free Software Foundation, either version 3 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU Lesser General Public License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with this program. If not, see . */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #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 namespace papilo { template bool compareVectors( const Vec& first, const Vec& second, const Num& 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 bool compareVariableDomains( const VariableDomains& first, const VariableDomains& second, const Num& 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 bool compareColBounds( const Vec& first_values, const Vec& second_values, const Vec& first_flags, const Vec& second_flags, const Num& 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 bool compareRowBounds( const Vec& first_values, const Vec& second_values, const Vec& first_flags, const Vec& second_flags, const Num& 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; } // compare index range template bool compareIndexRanges( const Vec& first, const Vec& 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; } // compare matrix values template bool compareMatrices( const SparseStorage& first, const SparseStorage& second, const Num& num ) { if( first.getNRows() != second.getNRows() ) return false; if( first.getNCols() != second.getNCols() ) return false; if( first.getNnz() != second.getNnz() ) return false; // ranges if( !compareIndexRanges( first.getRowRangesVec(), second.getRowRangesVec() ) ) return false; // columns, values 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 bool compareMatrixToTranspose( const SparseStorage& first, const SparseStorage& second, const Num& num ) { const SparseStorage transpose = first.getTranspose(); bool result = compareMatrices( second, transpose, num ); return result; } template bool compareMatrixToTranspose( const ConstraintMatrix& constarint_matrix, const Num& num ) { const SparseStorage& matrix = constarint_matrix.getConstraintMatrix(); const SparseStorage& transpose = constarint_matrix.getMatrixTranspose(); return compareMatrixToTranspose( matrix, transpose, num ); } template bool compareProblems( const Problem& first, const Problem& second, const Num& num ) { // ncols, nrows 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; // objective const Vec& objective1 = first.getObjective().coefficients; const Vec& objective2 = second.getObjective().coefficients; bool result = compareVectors( objective1, objective2, num ); if( !result ) return false; // lhs, rhs 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; // matrix rowwise result = compareMatrices( first.getConstraintMatrix().getConstraintMatrix(), second.getConstraintMatrix().getConstraintMatrix(), num ); if( !result ) return false; // matrix colwise (transpose) result = compareMatrices( first.getConstraintMatrix().getMatrixTranspose(), second.getConstraintMatrix().getMatrixTranspose(), num ); if( !result ) return false; // matrix to its own transpose result = compareMatrixToTranspose( first.getConstraintMatrix().getConstraintMatrix(), second.getConstraintMatrix().getMatrixTranspose(), num ); // objective offset if( first.getObjective().offset != second.getObjective().offset ) return false; return true; } } // namespace papilo #endif