
#ifndef __HANDLE_LOCALCUTS_H__
#define __HANDLE_LOCALCUTS_H__

#include <scip/scip.h>

#ifdef __cplusplus
extern "C" {
#endif


/**< user defined data to pass to the oracle */
typedef struct LC_Data LC_DATA;

/** local cut oracle solving status */
enum LC_Status
{
   LC_STATUS_UNKNOWN        =  0,     /**< the solving status is not yet known */
   LC_STATUS_OPTIMAL        =  1,     /**< the problem was solved to optimality (even if no solution is better than the cutoff) */
   LC_STATUS_INFEASIBLE     =  2,     /**< the problem was proven to be infeasible */
   LC_STATUS_UNBOUNDED      =  3,     /**< the problem was proven to be unbounded */
   LC_STATUS_NOTAPPLICABLE  =  4,     /**< the oracle cannot be applied to this problem */
   LC_STATUS_CUTOFF         =  5      /**< all solutions exceed the cutoff */
};
typedef enum LC_Status LC_STATUS;

/** user callback method for an optimization oracle
 *  input:
 *  - scip               SCIP pointer
 *  - dim                dimension of space
 *  - data               user data as passed to LC_generateCut
 *  - obj                (linear) objective function to be maximized
 *  - cutoff             can discard solutions value less or equal to the cutoff
 *  - maxnsols           maximal number of solutions (>= 1)
 *
 *  output:
 *  - nsols              number of solutions found (>= 1 unless an error occured)
 *  - sols               solutions found (or NULL)
 *  - objvals            objective solution values
 *  - status             status of oracle
 */
#define LC_ORACLE(x) SCIP_RETCODE x (SCIP* scip, int dim, const LC_DATA* data, \
      const SCIP_Real* obj, SCIP_Real cutoff, int maxnsols, int* nsols, SCIP_Real** sols, SCIP_Real* objvals, \
      LC_STATUS* status)



/** Generates a single local cut
 *
 *  The procedure finds a local cut most violated by the point stored in x[1, ..., dim]. The cut is
 *  added as a row to the current LP.
 *
 *  The computation uses a time limit of maxTime seconds of CPU time (if maxTime is not NULL). The
 *  total used CPU time in seconds is returned in usedTime.
 */
extern
SCIP_RETCODE LC_generateCut(
   SCIP*                 scip,               /**< SCIP pointer */
   int                   dim,                /**< dimension of subproblem */
   const SCIP_Real*      x,                  /**< point to be separated in reduced space */
   SCIP_Real*            xrelint,            /**< relative interior point (or NULL) */
   SCIP_VAR**            vars,               /**< original variables corresponding to subproblem */
   LC_ORACLE((*Oracle)),                     /**< optimization oracle callback */
   const LC_DATA*        data,               /**< data passed to oracle (or NULL) */
   int                   nsols,              /**< number of initial feasible solutions */
   const SCIP_Real**     sols,               /**< initial feasible solutions */
   const SCIP_Real*      primal,             /**< primal separation point or NULL if primal separation is turned off */
   int                   ninitialrows,       /**< number of initial rows to be added to master LP */
   SCIP_Real*            initialrowslhs,     /**< left hand sides of initial rows */
   SCIP_Real*            initialrowsrhs,     /**< right hand sides of initial rows */
   int*                  initialrowsbeg,     /**< beginning indices of initial rows */
   SCIP_Real*            initialrowsvals,    /**< values of initial rows */
   int*                  initialrowsinds,    /**< variable indices of initial rows */
   SCIP_Bool             targetcut,          /**< whether the separation is based on a target cuts (local cuts otherwise) */
   SCIP_Bool             tilting,            /**< whether inequality tilting is performed (only if localCut is set) */
   SCIP_Bool             checksols,          /**< whether the solutions should be checked for feasibility in the orginal problem */
   SCIP_Bool             nicelocalcuts,      /**< try to make a nice cut by finding a rational approximation */
   SCIP_Real*            cutcoefs,           /**< cut coefficients of (tilted) cut (or NULL) */
   SCIP_Real*            cutrhs,             /**< pointer to store the rhs of the cut (or NULL) */
   SCIP_Bool*            success,            /**< pointer to store whether cut generation was successful */
   const SCIP_Real*      maxtime,            /**< maximal time that should be used for separation (or NULL) */
   SCIP_Real*            usedtime            /**< returns the used time */
   );

#ifdef __cplusplus
}
#endif

#endif
