/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                           */
/*                  This file is part of the program and library             */
/*         SCIP --- Solving Constraint Integer Programs                      */
/*                                                                           */
/*  Copyright (c) 2002-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 SCIP; see the file LICENSE. If not visit scipopt.org.         */
/*                                                                           */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/**@file   debug.h
 * @ingroup INTERNALAPI
 * @brief  methods for debugging
 * @author Tobias Achterberg
 */

/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/

#ifndef __SCIP_DEBUG_H__
#define __SCIP_DEBUG_H__

/** uncomment this define to activate debugging the LP interface  */
/* #define SCIP_DEBUG_LP_INTERFACE */

#include "scip/def.h"
#include "scip/type_retcode.h"
#include "scip/type_scip.h"

#ifdef WITH_DEBUG_SOLUTION
#include "blockmemshell/memory.h"
#include "scip/type_cons.h"
#include "scip/type_lp.h"
#include "scip/type_misc.h"
#include "scip/type_set.h"
#include "scip/type_sol.h"
#include "scip/type_tree.h"
#include "scip/type_var.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

/** solution data for debugging purposes */
typedef struct SCIP_DebugSolData SCIP_DEBUGSOLDATA;

#ifdef WITH_DEBUG_SOLUTION

/** creates debug solution data */
SCIP_RETCODE SCIPdebugSolDataCreate(
   SCIP_DEBUGSOLDATA**   debugsoldata        /**< pointer to debug solution data */
   );

/** frees the debug solution */
SCIP_RETCODE SCIPdebugFreeSol(
   SCIP_SET*             set
   );

/** resets the data structure after restart */
SCIP_RETCODE SCIPdebugReset(
   SCIP_SET*             set
   );

/** frees debugging data for the particular instance */
SCIP_RETCODE SCIPdebugFreeDebugData(
   SCIP_SET*             set                 /**< global SCIP settings */
   );

/** frees all debugging data */
SCIP_RETCODE SCIPdebugFree(
   SCIP_SET*             set                 /**< global SCIP settings */
   );

/** checks for validity of the debugging solution in given constraints */
SCIP_RETCODE SCIPdebugCheckConss(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_CONS**           conss,              /**< constraints to check for validity */
   int                   nconss              /**< number of given constraints */
   );

/** checks whether given row is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckRow(
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_ROW*             row                 /**< row to check for validity */
   );

/** checks whether given global lower bound is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckLbGlobal(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_VAR*             var,                /**< problem variable */
   SCIP_Real             lb                  /**< lower bound */
   );

/** checks whether given global upper bound is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckUbGlobal(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_VAR*             var,                /**< problem variable */
   SCIP_Real             ub                  /**< upper bound */
   );

/** checks whether given local bound implication is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckInference(
   BMS_BLKMEM*           blkmem,             /**< block memory */
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_NODE*            node,               /**< local node where this bound change was applied */
   SCIP_VAR*             var,                /**< problem variable */
   SCIP_Real             newbound,           /**< new value for bound */
   SCIP_BOUNDTYPE        boundtype           /**< type of bound: lower or upper bound */
   );

/** informs solution debugger, that the given node will be freed */
SCIP_RETCODE SCIPdebugRemoveNode(
   BMS_BLKMEM*           blkmem,             /**< block memory */
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_NODE*            node                /**< node that will be freed */
   );

/** checks whether global lower bound does not exceed debuging solution value */
SCIP_RETCODE SCIPdebugCheckGlobalLowerbound(
   BMS_BLKMEM*           blkmem,             /**< block memory */
   SCIP_SET*             set                 /**< global SCIP settings */
   );

/** checks whether local lower bound does not exceed debuging solution value */
SCIP_RETCODE SCIPdebugCheckLocalLowerbound(
   BMS_BLKMEM*           blkmem,             /**< block memory */
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_NODE*            node                /**< node that will be freed */
   );

/** checks whether given variable bound is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckVbound(
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_VAR*             var,                /**< problem variable x in x <= b*z + d  or  x >= b*z + d */
   SCIP_BOUNDTYPE        vbtype,             /**< type of variable bound (LOWER or UPPER) */
   SCIP_VAR*             vbvar,              /**< variable z    in x <= b*z + d  or  x >= b*z + d */
   SCIP_Real             vbcoef,             /**< coefficient b in x <= b*z + d  or  x >= b*z + d */
   SCIP_Real             vbconstant          /**< constant d    in x <= b*z + d  or  x >= b*z + d */
   );

/** checks whether given implication is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckImplic(
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_VAR*             var,                /**< problem variable */
   SCIP_Bool             varfixing,          /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
   SCIP_Real             implbound           /**< bound b    in implication y <= b or y >= b */
   );

/** checks whether given (multi)-aggregation is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckAggregation(
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_VAR*             var,                /**< problem variable */
   SCIP_VAR**            aggrvars,           /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
   SCIP_Real*            scalars,            /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
   SCIP_Real             constant,           /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
   int                   naggrvars           /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
   );

/** check whether given clique is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckClique(
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_VAR**            vars,               /**< binary variables in the clique: at most one can be set to the given value */
   SCIP_Bool*            values,             /**< values of the variables in the clique; NULL to use TRUE for all vars */
   int                   nvars               /**< number of variables in the clique */
   );

/** checks whether given conflict is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckConflict(
   BMS_BLKMEM*           blkmem,             /**< block memory */
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_NODE*            node,               /**< node where the conflict clause is added */
   SCIP_BDCHGINFO**      bdchginfos,         /**< bound change informations of the conflict set */
   SCIP_Real*            relaxedbds,         /**< array with relaxed bounds which are efficient to create a valid conflict */
   int                   nbdchginfos         /**< number of bound changes in the conflict set */
   );

/** checks whether given conflict graph frontier is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckConflictFrontier(
   BMS_BLKMEM*           blkmem,             /**< block memory */
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_NODE*            node,               /**< node where the conflict clause is added */
   SCIP_BDCHGINFO*       bdchginfo,          /**< bound change info which got resolved, or NULL */
   SCIP_BDCHGINFO**      bdchginfos,         /**< bound change informations of the conflict set */
   SCIP_Real*            relaxedbds,         /**< array with relaxed bounds which are efficient to create a valid conflict */
   int                   nbdchginfos,        /**< number of bound changes in the conflict set */
   SCIP_PQUEUE*          bdchgqueue,         /**< unprocessed conflict bound changes */
   SCIP_PQUEUE*          forcedbdchgqueue    /**< unprocessed conflict bound changes that must be resolved */
   );

/** creates the debugging propagator and includes it in SCIP */
SCIP_RETCODE SCIPdebugIncludeProp(
   SCIP*                 scip                /**< SCIP data structure */
   );

/** adds a solution value for a new variable in the transformed problem that has no original counterpart
 * a value can only be set if no value has been set for this variable before
 */
SCIP_EXPORT
SCIP_RETCODE SCIPdebugAddSolVal(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_VAR*             var,                /**< variable for which to add a value */
   SCIP_Real             val                 /**< solution value for variable */
   );

/** gets pointer to the debug solution */
SCIP_EXPORT
SCIP_RETCODE SCIPdebugGetSol(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_SOL**            sol                 /**< buffer to store pointer to the debug solution */
   );

/** gets value for a variable in the debug solution
 *
 * if no value is stored for the variable, gives 0.0
 */
SCIP_EXPORT
SCIP_RETCODE SCIPdebugGetSolVal(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_VAR*             var,                /**< variable for which to get the value */
   SCIP_Real*            val                 /**< buffer to store solution value */
   );

/** check whether the debugging solution is valid in the current node */
SCIP_EXPORT
SCIP_RETCODE SCIPdebugSolIsValidInSubtree(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_Bool*            isvalidinsubtree    /**< pointer to store whether the solution is valid in the current
                                              *   subtree
                                              */
   );

/** checks whether SCIP data structure is the main SCIP (the one for which debugging is enabled) */
SCIP_EXPORT
SCIP_Bool SCIPdebugIsMainscip(
   SCIP*                 scip                /**< SCIP data structure */
   );

/** enabling solution debugging mechanism */
SCIP_EXPORT
void SCIPdebugSolEnable(
   SCIP*                 scip                /**< SCIP data structure */
   );

/** disabling solution debugging mechanism */
SCIP_EXPORT
void SCIPdebugSolDisable(
   SCIP*                 scip                /**< SCIP data structure */
   );

/** check if solution debugging mechanism is enabled */
SCIP_EXPORT
SCIP_Bool SCIPdebugSolIsEnabled(
   SCIP*                 scip                /**< SCIP data structure */
   );

/** check if SCIP is compiled with WITH_DEBUG_SOLUTION */
SCIP_EXPORT
SCIP_Bool SCIPwithDebugSol(void);

#else

#define SCIPdebugSolDataCreate(debugsoldata) SCIP_OKAY
#define SCIPdebugFreeSol(set) SCIP_OKAY
#define SCIPdebugReset(set) SCIP_OKAY
#define SCIPdebugFreeDebugData(set) SCIP_OKAY
#define SCIPdebugFree(set) SCIP_OKAY
#define SCIPdebugCheckConss(scip,conss,nconss) SCIP_OKAY
#define SCIPdebugCheckRow(set,row) SCIP_OKAY
#define SCIPdebugCheckLbGlobal(scip,var,lb) SCIP_OKAY
#define SCIPdebugCheckUbGlobal(scip,var,ub) SCIP_OKAY
#define SCIPdebugCheckInference(blkmem,set,node,var,newbound,boundtype) SCIP_OKAY
#define SCIPdebugRemoveNode(blkmem,set,node) SCIP_OKAY
#define SCIPdebugCheckGlobalLowerbound(blkmem,set) SCIP_OKAY
#define SCIPdebugCheckLocalLowerbound(blkmem,set,node) SCIP_OKAY
#define SCIPdebugCheckVbound(set,var,vbtype,vbvar,vbcoef,vbconstant) SCIP_OKAY
#define SCIPdebugCheckImplic(set,var,varfixing,implvar,impltype,implbound) SCIP_OKAY
#define SCIPdebugCheckAggregation(set,var,aggrvars,scalars,constant,naggrvars) SCIP_OKAY
#define SCIPdebugCheckClique(set,vars,values,nvars) SCIP_OKAY
#define SCIPdebugCheckConflict(blkmem,set,node,bdchginfos,relaxedbds,nliterals) SCIP_OKAY
#define SCIPdebugCheckConflictFrontier(blkmem,set,node,bdchginfo,bdchginfos,relaxedbds,nliterals,bdchgqueue,forcedbdchgqueue) SCIP_OKAY
#define SCIPdebugIncludeProp(scip) SCIP_OKAY
#define SCIPdebugAddSolVal(scip,var,val) SCIP_OKAY
#define SCIPdebugGetSolVal(scip,var,val) SCIP_OKAY
#define SCIPdebugSolIsValidInSubtree(scip,isvalidinsubtree) SCIP_OKAY
#define SCIPdebugSolEnable(scip) /**/
#define SCIPdebugSolDisable(scip) /**/
#define SCIPdebugSolIsEnabled(scip) FALSE
#define SCIPwithDebugSol(void) FALSE

#endif


/* 
 * debug method for LP interface, to check if the LP interface works correct 
 */
#ifdef SCIP_DEBUG_LP_INTERFACE 

/* check if the coef is the r-th line of the inverse matrix B^-1; this is
 * the case if (coef * B) is the r-th unit vector */
SCIP_RETCODE SCIPdebugCheckBInvRow(
   SCIP*                 scip,               /**< SCIP data structure */
   int                   r,                  /**< row number */
   SCIP_Real*            coef                /**< pointer to store the coefficients of the row */
   );

#else

#define SCIPdebugCheckBInvRow(scip,r,coef) SCIP_OKAY

#endif

/** checks, if SCIP is in one of the feasible stages */
#ifndef NDEBUG

SCIP_RETCODE SCIPcheckStage(
   SCIP*                 scip,               /**< SCIP data structure */
   const char*           method,             /**< method that was called */
   SCIP_Bool             init,               /**< may method be called in the INIT stage? */
   SCIP_Bool             problem,            /**< may method be called in the PROBLEM stage? */
   SCIP_Bool             transforming,       /**< may method be called in the TRANSFORMING stage? */
   SCIP_Bool             transformed,        /**< may method be called in the TRANSFORMED stage? */
   SCIP_Bool             initpresolve,       /**< may method be called in the INITPRESOLVE stage? */
   SCIP_Bool             presolving,         /**< may method be called in the PRESOLVING stage? */
   SCIP_Bool             exitpresolve,       /**< may method be called in the EXITPRESOLE stage? */
   SCIP_Bool             presolved,          /**< may method be called in the PRESOLVED stage? */
   SCIP_Bool             initsolve,          /**< may method be called in the INITSOLVE stage? */
   SCIP_Bool             solving,            /**< may method be called in the SOLVING stage? */
   SCIP_Bool             solved,             /**< may method be called in the SOLVED stage? */
   SCIP_Bool             exitsolve,          /**< may method be called in the EXITSOLVE stage? */
   SCIP_Bool             freetrans,          /**< may method be called in the FREETRANS stage? */
   SCIP_Bool             freescip            /**< may method be called in the FREE stage? */
   );
#else

#define SCIPcheckStage(scip,method,init,problem,transforming,transformed,initpresolve,presolving,exitpresolve,presolved, \
   initsolve,solving,solved,exitsolve,freetrans,freescip) SCIP_OKAY

#endif

#ifdef __cplusplus
}
#endif

#endif
