/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                           */
/*               This file is part of the program and library                */
/*    PaPILO --- Parallel Presolve for Integer and Linear Optimization       */
/*                                                                           */
/* Copyright (C) 2020-2025 Zuse Institute Berlin (ZIB)                       */
/*                                                                           */
/* Licensed under the Apache License, Version 2.0 (the "License");           */
/* you may not use this file except in compliance with the License.          */
/* You may obtain a copy of the License at                                   */
/*                                                                           */
/*     http://www.apache.org/licenses/LICENSE-2.0                            */
/*                                                                           */
/* Unless required by applicable law or agreed to in writing, software       */
/* distributed under the License is distributed on an "AS IS" BASIS,         */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  */
/* See the License for the specific language governing permissions and       */
/* limitations under the License.                                            */
/*                                                                           */
/* You should have received a copy of the Apache-2.0 license                 */
/* along with PaPILO; see the file LICENSE. If not visit scipopt.org.        */
/*                                                                           */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "papilo/misc/VectorUtils.hpp"
#include "papilo/external/catch/catch_amalgamated.hpp"

using namespace papilo;

TEST_CASE( "vector-comparisons", "[misc]" )
{
   Vec<double> vec_double{1.0, -1.0, 2.0, -2.0, 3.0, -3.0, 4.0, -4.0};

   Num<double> num;

   bool vectors_same = compareVectors( vec_double, vec_double, num );
   REQUIRE( vectors_same );

   auto vec_different = vec_double;
   vec_different[0] = 7;
   bool vectors_different = compareVectors( vec_double, vec_different, num );
   REQUIRE( !vectors_different );
}

TEST_CASE( "matrix-comparisons", "[misc]" )
{
   // build the triplets for the following matrix:
   // 1  2  0  0  0  0  0  0  0
   // 0  3  4  5  6  7  0  0  0
   // 0  8  0  0  0  0  0  0  0
   // 0  0  0  0  0  0  0  0  0
   // 9  10 11 0  0  0  0  12 13
   int nrows = 5;
   int ncols = 9;
   Vec<Triplet<double>> triplets = {
       Triplet<double>{0, 0, 1.0},  Triplet<double>{0, 1, 2.0},
       Triplet<double>{1, 1, 3.0},  Triplet<double>{1, 2, 4.0},
       Triplet<double>{1, 3, 5.0},  Triplet<double>{1, 4, 6.0},
       Triplet<double>{1, 5, 7.0},  Triplet<double>{2, 1, 8.0},
       Triplet<double>{4, 0, 9.0},  Triplet<double>{4, 1, 10.0},
       Triplet<double>{4, 2, 11.0}, Triplet<double>{4, 7, 12.0},
       Triplet<double>{4, 8, 13.0}};

   Vec<int> rowsize = {2, 5, 1, -1, 5};
   Vec<int> colsize = {2, 4, 2, 1, 1, 1, -1, 1, 1};
   SparseStorage<double> matrix{triplets, nrows, ncols, true};
   SparseStorage<double> transpose = matrix.getTranspose();

   // matrix
   Num<double> num;
   bool result = compareMatrices( matrix, matrix, num );
   REQUIRE( result );

   result = compareMatrices( matrix, transpose, num );
   REQUIRE( !result );

   result = compareMatrixToTranspose( matrix, transpose, num );
   REQUIRE( result );

   transpose.getColumns()[3] = 7;
   result = compareMatrixToTranspose( matrix, transpose, num );
   REQUIRE( !result );
}

TEST_CASE( "problem-comparisons", "[misc]" )
{
   Problem<double> problem;

   Vec<double> obj_vec{0, 1, 2, 3};
   problem.setObjective( std::move( obj_vec ) );

   Vec<double> lower_bounds{0, 0, 0, 0};
   Vec<double> upper_bounds{0, 0, 0, 0};
   ColFlags flag;
   Vec<ColFlags> col_flags( 4, flag );
   problem.setVariableDomains( lower_bounds, upper_bounds, col_flags );

   // build the triplets for the following matrix:
   // 1  2  0  0
   // 0  3  4  5
   // 0  8  0  1
   int nrows = 3;
   int ncols = 4;
   Vec<Triplet<double>> triplets = {
       Triplet<double>{0, 0, 1.0}, Triplet<double>{0, 1, 2.0},
       Triplet<double>{1, 1, 3.0}, Triplet<double>{1, 2, 4.0},
       Triplet<double>{1, 3, 5.0}, Triplet<double>{2, 1, 8.0},
       Triplet<double>{2, 3, 1.0}};

   Vec<int> rowsize = {2, 3, 2};
   Vec<int> colsize = {1, 3, 1, 2};
   SparseStorage<double> matrix{triplets, nrows, ncols, true};

   Vec<double> lhs{0, 1, 2};
   Vec<double> rhs{1, 2, 3};
   RowFlags rflag;

   Vec<RowFlags> row_flags( 3, rflag );

   problem.setConstraintMatrix( matrix, lhs, rhs, row_flags );
   //  problem.setVariableNames( std::move( parser.colnames ) );
   problem.setName( "test" );
   //  problem.setConstraintNames( std::move( parser.rownames ) );

   Num<double> num;
   bool result = compareProblems( problem, problem, num );
   REQUIRE( result );

   auto different_problem = problem;
   Vec<double> obj{0, 0, 0, 3};
   different_problem.setObjective( std::move( obj ) );
   result = compareProblems( problem, different_problem, num );
   REQUIRE( !result );
}
