/*
 * milp.h -- a small mixed-integer linear programming solver in C99.
 *
 * Approach: two-phase revised simplex for the LP relaxation,
 * recursive branch-and-bound on integer variables.
 *
 * Problem form:
 *
 *     min  or  max   c^T x
 *     subject to     a_i^T x  {<=, ==, >=}  b_i      for each row i
 *                    lo_j <= x_j <= hi_j              for each variable j
 *                    x_j in {Z, {0,1}}                if declared integer/binary
 *
 * The solver is intentionally compact (~700 LOC, no dependencies beyond
 * libc and libm). It is meant to read in an afternoon, not to compete
 * with HiGHS. See examples/ for the four problems that motivate it.
 */
#ifndef MILP_H
#define MILP_H

#ifdef __cplusplus
extern "C" {
#endif

/* Optimisation sense */
#define MILP_MIN 0
#define MILP_MAX 1

/* Constraint sense */
#define MILP_LE  0   /* <= */
#define MILP_EQ  1   /* == */
#define MILP_GE  2   /* >= */

/* Variable type */
#define MILP_CONTINUOUS 0
#define MILP_INTEGER    1
#define MILP_BINARY     2

/* Status returned by the solver */
#define MILP_OPTIMAL     0
#define MILP_INFEASIBLE  1
#define MILP_UNBOUNDED   2
#define MILP_NODE_LIMIT  3
#define MILP_ERROR       4

typedef struct MilpModel MilpModel;

/* Construct an empty model. Must call milp_set_* below to populate. */
MilpModel *milp_new(int n_vars, int n_constraints);
void       milp_free(MilpModel *m);

void milp_set_objective (MilpModel *m, int sense, const double *c);
void milp_set_row       (MilpModel *m, int row, const double *a,
                         int op, double rhs);
void milp_set_var_type  (MilpModel *m, int var, int type);
void milp_set_var_bounds(MilpModel *m, int var, double lo, double hi);

/* Solve the LP relaxation only (treat all variables as continuous).
 * Returns MILP_OPTIMAL / INFEASIBLE / UNBOUNDED. */
int milp_solve_lp(MilpModel *m, double *x_out, double *obj_out);

/* Solve the full MILP. */
int milp_solve(MilpModel *m, double *x_out, double *obj_out);

/* Statistics from the most recent milp_solve() call. */
int    milp_nodes_explored (const MilpModel *m);
int    milp_lps_solved     (const MilpModel *m);
double milp_lp_relaxation  (const MilpModel *m); /* value of the root LP */

/* Configurable verbosity: 0=silent, 1=tree summary, 2=every node. */
void milp_set_verbose(MilpModel *m, int level);

/* Configurable node limit (default: 1<<20). */
void milp_set_node_limit(MilpModel *m, int limit);

#ifdef __cplusplus
}
#endif
#endif /* MILP_H */
