mirror of
https://github.com/Interlisp/maiko.git
synced 2026-01-13 15:18:14 +00:00
Some of these didn't have include guards, some used old names for them. Now they follow the current convention.
535 lines
18 KiB
C
Executable File
535 lines
18 KiB
C
Executable File
#ifndef LPKIT_H
|
|
#define LPKIT_H 1
|
|
|
|
/* $Id: lpkit.h,v 1.2 1999/01/03 02:06:14 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved */
|
|
|
|
/*
|
|
Main header file of the LP_SOLVE toolkit.
|
|
|
|
By Jeroen Dirks, 21-2-95
|
|
|
|
include this file in your program and link with liblps.a
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#define FAIL -1
|
|
|
|
#define NULL 0
|
|
#define FALSE 0
|
|
#define TRUE 1
|
|
|
|
#define DEFNUMINV 50
|
|
|
|
/* solve status values */
|
|
#define OPTIMAL 0
|
|
#define MILP_FAIL 1
|
|
#define INFEASIBLE 2
|
|
#define UNBOUNDED 3
|
|
#define FAILURE 4
|
|
#define RUNNING 5
|
|
#define INT_SOLN 6
|
|
#define TIMEOUT 7
|
|
|
|
/* lag_solve extra status values */
|
|
#define FEAS_FOUND 6
|
|
#define NO_FEAS_FOUND 7
|
|
#define BREAK_BB 8
|
|
|
|
#define FIRST_NI 0
|
|
#define RAND_NI 1
|
|
|
|
#define LE 0
|
|
#define EQ 1
|
|
#define GE 2
|
|
#define OF 3
|
|
|
|
#define my_abs(x) ((x) < 0 ? -(x) : (x))
|
|
#define my_min(x, y) ((x) < (y) ? (x) : (y))
|
|
#define my_max(x, y) ((x) > (y) ? (x) : (y))
|
|
|
|
#define MAX_WARN_COUNT 20
|
|
|
|
#ifdef CHECK
|
|
#define my_round(val, eps) { \
|
|
REAL absv; \
|
|
absv = ((val) < 0 ? -(val) : (val)); \
|
|
if(absv < (eps)) \
|
|
val = 0; \
|
|
if(Warn_count < MAX_WARN_COUNT) \
|
|
{ \
|
|
if(absv > 0.5 * (eps) && absv < 2 * (eps)) \
|
|
{ \
|
|
Warn_count++; \
|
|
fprintf(stderr, \
|
|
"Warning Value close to epsilon V: %e E: %e\n", \
|
|
(double)absv, (double)(eps)); \
|
|
if(Warn_count == MAX_WARN_COUNT) \
|
|
{ \
|
|
fprintf(stderr, \
|
|
"*** Suppressing further rounding warnings\n"); \
|
|
} \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#else
|
|
#define my_round(val,eps) { \
|
|
if (((val) < 0 ? -(val) : (val)) < (eps)) \
|
|
val = 0; \
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
#define debug_print(x,y,z,w,e,r,t,q)
|
|
#define debug_print_bounds(x,y)
|
|
#define debug_print_solution()
|
|
|
|
|
|
|
|
#define DEF_INFINITE 1e24 /* limit for dynamic range */
|
|
#define DEF_EPSB 5.01e-7 /* for rounding RHS values to 0 determine
|
|
infeasibility basis */
|
|
#define DEF_EPSEL 1e-8 /* for rounding other values (vectors) to 0 */
|
|
#define DEF_EPSD 1e-6 /* for rounding reduced costs to zero */
|
|
#define DEF_EPSILON 1e-3 /* to determine if a float value is integer */
|
|
|
|
#define PREJ 1e-3 /* pivot reject (try others first) */
|
|
|
|
#ifndef REAL /* to allow -DREAL=<float type> while compiling */
|
|
#define REAL double
|
|
#endif
|
|
|
|
#define HASHSIZE 10007 /* prime number is better, MB */
|
|
#define ETA_START_SIZE 10000 /* start size of array Eta. Realloced if needed */
|
|
#define FNAMLEN 64
|
|
#define NAMELEN 25
|
|
#define MAXSTRL (NAMELEN-1)
|
|
#define STD_ROW_NAME_PREFIX "r_"
|
|
|
|
#define CALLOC(ptr, nr, type) \
|
|
if (!(ptr = (type *) calloc((size_t)(nr), sizeof(type)))) \
|
|
{ fprintf(stderr, "calloc failed on line %d of file %s\n", __LINE__, __FILE__); \
|
|
ERROR(ERR_NOMEM); }
|
|
|
|
#define MALLOC(ptr, nr, type) if(!(ptr = (type *) malloc((size_t)((nr) * sizeof(type))))) { fprintf(stderr, "malloc failed on line %d of file %s\n", __LINE__, __FILE__); ERROR(ERR_NOMEM); }
|
|
|
|
#define REALLOC(ptr, nr, type) if(!(ptr = (type *) realloc(ptr,(size_t)(nr)*sizeof(type)))) { fprintf(stderr, "realloc failed on line %d of file %s\n", __LINE__, __FILE__); ERROR(ERR_NOMEM); }
|
|
|
|
#define MALLOCCPY(nptr,optr,nr,type) {MALLOC(nptr, nr, type); memcpy(nptr, optr, (size_t)((nr) * sizeof(type)));}
|
|
|
|
#define MEMCPY(nptr,optr,nr,type) {memcpy(nptr,optr, (size_t)((nr) * sizeof(type)));}
|
|
|
|
typedef char nstring[NAMELEN];
|
|
|
|
typedef struct _matrec
|
|
{
|
|
int row_nr;
|
|
REAL value;
|
|
} matrec;
|
|
|
|
typedef struct _lispmr
|
|
{
|
|
int rownr;
|
|
float value;
|
|
} lispmr;
|
|
|
|
typedef struct _column
|
|
{
|
|
int row;
|
|
float value;
|
|
struct _column *next ;
|
|
} column;
|
|
|
|
typedef struct _constraint_name
|
|
{
|
|
char name[NAMELEN];
|
|
int row;
|
|
struct _constraint_name *next;
|
|
} constraint_name;
|
|
|
|
typedef struct _bound
|
|
{
|
|
REAL upbo;
|
|
REAL lowbo;
|
|
} bound;
|
|
|
|
typedef struct _tmp_store_struct
|
|
{
|
|
nstring name;
|
|
int row;
|
|
REAL value;
|
|
REAL rhs_value;
|
|
short relat;
|
|
} tmp_store_struct;
|
|
|
|
typedef struct _hashelem
|
|
{
|
|
nstring colname;
|
|
struct _hashelem *next;
|
|
struct _column *col;
|
|
struct _bound *bnd;
|
|
int must_be_int;
|
|
} hashelem;
|
|
|
|
typedef struct _rside /* contains relational operator and rhs value */
|
|
{
|
|
REAL value;
|
|
struct _rside *next;
|
|
short relat;
|
|
} rside;
|
|
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* S T A T E - S A V I N G F O R T I M E - O U T S */
|
|
/* */
|
|
/* */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
typedef struct solve_state
|
|
{
|
|
int saved; /* 0 = not used, else states below */
|
|
int notint; /* variable # of the non-integer var chosen */
|
|
int bound; /* integer lower bound for variable notint */
|
|
int res1, res2;
|
|
struct solve_state *next; /* The next state holder in the chain */
|
|
} sstate;
|
|
|
|
#define ST_LO 1 /* We got to before calling solve on the lower bound side */
|
|
#define ST_HI 2 /* We got to before calling solve on the upper bound side */
|
|
#define ST_SOLN 3 /* We got past calling solve, not to analyzing */
|
|
|
|
|
|
|
|
|
|
/* fields indicated with ## may be modified directly */
|
|
/* pointers will have there size in the comments */
|
|
|
|
typedef struct _lprec
|
|
{
|
|
nstring lp_name; /* the name of the lp */
|
|
|
|
short active; /*TRUE if the globals point to this structure*/
|
|
short verbose; /* ## Verbose flag */
|
|
short print_duals; /* ## PrintDuals flag for PrintSolution */
|
|
short print_sol; /* ## used in lp_solve */
|
|
short debug; /* ## Print B&B information */
|
|
short print_at_invert; /* ## Print information at every reinversion */
|
|
short trace; /* ## Print information on pivot selection */
|
|
short anti_degen; /* ## Do perturbations */
|
|
|
|
int rows; /* Nr of constraint rows in the problem */
|
|
int rows_alloc; /* The allocated memory for Rows sized data */
|
|
int columns; /* The number of columns (= variables) */
|
|
int columns_alloc;
|
|
int sum; /* The size of the variables + the slacks */
|
|
int sum_alloc;
|
|
|
|
short names_used; /* Flag to indicate if names for rows and
|
|
columns are used */
|
|
nstring *row_name; /* rows_alloc+1 */
|
|
nstring *col_name; /* columns_alloc+1 */
|
|
|
|
/* Row[0] of the sparse matrix is the objective function */
|
|
|
|
int non_zeros; /* The number of elements in the sparse matrix*/
|
|
int mat_alloc; /* The allocated size for matrix sized
|
|
structures */
|
|
matrec *mat; /* mat_alloc :The sparse matrix */
|
|
int *col_end; /* columns_alloc+1 :Cend[i] is the index of the
|
|
first element after column i.
|
|
column[i] is stored in elements
|
|
col_end[i-1] to col_end[i]-1 */
|
|
int *col_no; /* mat_alloc :From Row 1 on, col_no contains the
|
|
column nr. of the
|
|
nonzero elements, row by row */
|
|
short row_end_valid; /* true if row_end & col_no are valid */
|
|
int *row_end; /* rows_alloc+1 :row_end[i] is the index of the
|
|
first element in Colno after row i */
|
|
REAL *orig_rh; /* rows_alloc+1 :The RHS after scaling & sign
|
|
changing, but before `Bound transformation' */
|
|
REAL *rh; /* rows_alloc+1 :As orig_rh, but after Bound
|
|
transformation */
|
|
REAL *rhs; /* rows_alloc+1 :The RHS of the current simplex
|
|
tableau */
|
|
short *must_be_int; /* sum_alloc+1 :TRUE if variable must be
|
|
Integer */
|
|
REAL *orig_upbo; /* sum_alloc+1 :Bound before transformations */
|
|
REAL *orig_lowbo; /* " " */
|
|
REAL *upbo; /* " " :Upper bound after transformation
|
|
& B&B work*/
|
|
REAL *lowbo; /* " " :Lower bound after transformation
|
|
& B&B work */
|
|
|
|
short basis_valid; /* TRUE is the basis is still valid */
|
|
int *bas; /* rows_alloc+1 :The basis column list */
|
|
short *basis; /* sum_alloc+1 : basis[i] is TRUE if the column
|
|
is in the basis */
|
|
short *lower; /* " " :TRUE is the variable is at its
|
|
lower bound (or in the basis), it is FALSE
|
|
if the variable is at its upper bound */
|
|
|
|
short eta_valid; /* TRUE if current Eta structures are valid */
|
|
int eta_alloc; /* The allocated memory for Eta */
|
|
int eta_size; /* The number of Eta columns */
|
|
int num_inv; /* The number of real pivots */
|
|
int max_num_inv; /* ## The number of real pivots between
|
|
reinversions */
|
|
REAL *eta_value; /* eta_alloc :The Structure containing the
|
|
values of Eta */
|
|
int *eta_row_nr; /* " " :The Structure containing the Row
|
|
indexes of Eta */
|
|
int *eta_col_end; /* rows_alloc + MaxNumInv : eta_col_end[i] is
|
|
the start index of the next Eta column */
|
|
|
|
short bb_rule; /* what rule for selecting B&B variables */
|
|
|
|
short break_at_int; /* TRUE if stop at first integer better than
|
|
break_value */
|
|
REAL break_value;
|
|
|
|
REAL obj_bound; /* ## Objective function bound for speedup of
|
|
B&B */
|
|
int iter; /* The number of iterations in the simplex
|
|
solver (LP) */
|
|
int total_iter; /* The total number of iterations (B&B) (ILP)*/
|
|
int max_level; /* The Deepest B&B level of the last solution */
|
|
int total_nodes; /* total number of nodes processed in b&b */
|
|
REAL *solution; /* sum_alloc+1 :The Solution of the last LP,
|
|
0 = The Optimal Value,
|
|
1..rows The Slacks,
|
|
rows+1..sum The Variables */
|
|
REAL *best_solution; /* " " :The Best 'Integer' Solution */
|
|
REAL *duals; /* rows_alloc+1 :The dual variables of the
|
|
last LP */
|
|
|
|
short maximise; /* TRUE if the goal is to maximise the
|
|
objective function */
|
|
short floor_first; /* TRUE if B&B does floor bound first */
|
|
short *ch_sign; /* rows_alloc+1 :TRUE if the Row in the matrix
|
|
has changed sign
|
|
(a`x > b, x>=0) is translated to
|
|
s + -a`x = -b with x>=0, s>=0) */
|
|
|
|
short scaling_used; /* TRUE if scaling is used */
|
|
short columns_scaled; /* TRUE is the columns are scaled too, Only use
|
|
if all variables are non-integer */
|
|
REAL *scale; /* sum_alloc+1 :0..Rows the scaling of the Rows,
|
|
Rows+1..Sum the scaling of the columns */
|
|
|
|
int nr_lagrange; /* Nr. of Langrangian relaxation constraints */
|
|
REAL **lag_row; /* NumLagrange, columns+1:Pointer to pointer of
|
|
rows */
|
|
REAL *lag_rhs; /* NumLagrange :Pointer to pointer of Rhs */
|
|
REAL *lambda; /* NumLagrange :Lambda Values */
|
|
short *lag_con_type; /* NumLagrange :TRUE if constraint type EQ */
|
|
REAL lag_bound; /* the lagrangian lower bound */
|
|
|
|
short valid; /* Has this lp passed the 'test' */
|
|
REAL infinite; /* ## numerical stuff */
|
|
REAL epsilon; /* ## */
|
|
REAL epsb; /* ## */
|
|
REAL epsd; /* ## */
|
|
REAL epsel; /* ## */
|
|
sstate *solve_states; /* for time out */
|
|
} lprec;
|
|
|
|
|
|
|
|
/* function interface for the user */
|
|
|
|
lprec *make_lp(int rows, int columns);
|
|
/* create and initialise a lprec structure
|
|
defaults:
|
|
Empty (Rows * Columns) matrix,
|
|
Minimise the objective function
|
|
constraints all type <=
|
|
Upperbounds all Infinite
|
|
no integer variables
|
|
floor first in B&B
|
|
no scaling
|
|
default basis */
|
|
|
|
lprec *read_lp_file(FILE *input, short verbose, nstring lp_name);
|
|
/* create and read an .lp file from input (input must be open) */
|
|
|
|
void delete_lp(lprec *lp);
|
|
/* Remove problem from memory */
|
|
|
|
lprec *copy_lp(lprec *lp);
|
|
/* copy a lp structure */
|
|
|
|
void set_mat(lprec *lp, int row, int column, REAL value);
|
|
/* fill in element (Row,Column) of the matrix
|
|
Row in [0..Rows] and Column in [1..Columns] */
|
|
|
|
void set_obj_fn(lprec *lp, REAL *row);
|
|
/* set the objective function (Row 0) of the matrix */
|
|
void str_set_obj_fn(lprec *lp, char *row);
|
|
/* The same, but with string input */
|
|
|
|
void add_constraint(lprec *lp, REAL *row, short constr_type, REAL rh);
|
|
/* Add a constraint to the problem,
|
|
row is the constraint row,
|
|
rh is the right hand side,
|
|
constr_type is the type of constraint (LE (<=), GE(>=), EQ(=)) */
|
|
void str_add_constraint(lprec *lp, char *row_string ,short constr_type, REAL rh);
|
|
/* The same, but with string input */
|
|
|
|
void del_constraint(lprec *lp,int del_row);
|
|
/* Remove constrain nr del_row from the problem */
|
|
|
|
void add_lag_con(lprec *lp, REAL *row, short con_type, REAL rhs);
|
|
/* add a Lagrangian constraint of form Row' x contype Rhs */
|
|
void str_add_lag_con(lprec *lp, char *row, short con_type, REAL rhs);
|
|
/* The same, but with string input */
|
|
|
|
void add_column(lprec *lp, REAL *column);
|
|
/* Add a Column to the problem */
|
|
void str_add_column(lprec *lp, char *col_string);
|
|
/* The same, but with string input */
|
|
|
|
void del_column(lprec *lp, int column);
|
|
/* Delete a column */
|
|
|
|
void set_upbo(lprec *lp, int column, REAL value);
|
|
/* Set the upperbound of a variable */
|
|
|
|
void set_lowbo(lprec *lp, int column, REAL value);
|
|
/* Set the lowerbound of a variable */
|
|
|
|
void set_int(lprec *lp, int column, short must_be_int);
|
|
/* Set the type of variable, if must_be_int = TRUE then the variable must be integer */
|
|
|
|
void set_rh(lprec *lp, int row, REAL value);
|
|
/* Set the right hand side of a constraint row */
|
|
|
|
void set_rh_vec(lprec *lp, REAL *rh);
|
|
/* Set the right hand side vector */
|
|
void str_set_rh_vec(lprec *lp, char *rh_string);
|
|
/* The same, but with string input */
|
|
|
|
void set_maxim(lprec *lp);
|
|
/* maximise the objective function */
|
|
|
|
void set_minim(lprec *lp);
|
|
/* minimise the objective function */
|
|
|
|
void set_constr_type(lprec *lp, int row, short con_type);
|
|
/* Set the type of constraint in row Row (LE, GE, EQ) */
|
|
|
|
void set_row_name(lprec *lp, int row, nstring new_name);
|
|
/* Set the name of a constraint row, make sure that the name has < 25 characters */
|
|
|
|
void set_col_name(lprec *lp, int column, nstring new_name);
|
|
/* Set the name of a variable column, make sure that the name has < 25 characters */
|
|
|
|
void auto_scale(lprec *lp);
|
|
/* Automatic scaling of the problem */
|
|
|
|
void unscale(lprec *lp);
|
|
/* Remove all scaling from the problem */
|
|
|
|
int solve(lprec *lp);
|
|
/* Solve the problem */
|
|
|
|
short Isvalid(lprec *lp);
|
|
int milpsolve (sstate *st, REAL *upbo, REAL *lowbo, short *sbasis, short *slower, int *sbas);
|
|
|
|
int lag_solve(lprec *lp, REAL start_bound, int num_iter, short verbose);
|
|
/* Do NumIter iterations with Lagrangian relaxation constraints */
|
|
|
|
void reset_basis(lprec *lp);
|
|
/* Reset the basis of a problem, can be useful in case of degeneracy - JD */
|
|
|
|
REAL mat_elm(lprec *lp, int row, int column);
|
|
/* get a single element from the matrix */
|
|
|
|
void get_row(lprec *lp, int row_nr, REAL *row);
|
|
/* fill row with the row row_nr from the problem */
|
|
|
|
void get_column(lprec *lp, int col_nr, REAL *column);
|
|
/* fill column with the column col_nr from the problem */
|
|
|
|
void get_reduced_costs(lprec *lp, REAL *rc);
|
|
/* get the reduced costs vector */
|
|
|
|
short is_feasible(lprec *lp, REAL *values);
|
|
/* returns TRUE if the vector in values is a feasible solution to the lp */
|
|
|
|
short column_in_lp(lprec *lp, REAL *column);
|
|
/* returns TRUE if column is already present in lp. (Does not look at bounds
|
|
and types, only looks at matrix values */
|
|
|
|
lprec *read_mps(FILE *input, short verbose);
|
|
/* read a MPS file */
|
|
|
|
void write_MPS(lprec *lp, FILE *output);
|
|
/* write a MPS file to output */
|
|
|
|
void write_LP(lprec *lp, FILE *output);
|
|
/* write a LP file to output */
|
|
|
|
void print_lp(lprec *lp);
|
|
/* Print the current problem, only useful in very small (test) problems.
|
|
Shows the effect of scaling */
|
|
|
|
void print_solution(lprec *lp);
|
|
/* Print the solution to stdout */
|
|
|
|
void print_duals(lprec *lp);
|
|
/* Print the dual variables of the solution */
|
|
|
|
void print_scales(lprec *lp);
|
|
/* If scaling is used, print the scaling factors */
|
|
|
|
|
|
|
|
|
|
/* functions used internally by the lp toolkit */
|
|
void error(char *format, ...);
|
|
void inc_mat_space(lprec *lp, int max_extra);
|
|
void inc_row_space(lprec *lp);
|
|
void inc_col_space(lprec *lp);
|
|
static REAL minmax_to_scale(REAL min, REAL max);
|
|
void unscale_columns(lprec *lp);
|
|
void set_globals(lprec *lp);
|
|
void ftran(int start, int end, REAL *pcol);
|
|
void btran(REAL *row);
|
|
void invert(void);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
/* */
|
|
/* E R R O R H A N D L I N G F O R L I B R A R Y */
|
|
/* */
|
|
/* */
|
|
/* */
|
|
/* */
|
|
/* */
|
|
/*************************************************************************/
|
|
|
|
#define ERROR(x) longjmp(LP_jmpbuf,256|x)
|
|
|
|
#define ERR_NOMEM 0x10 /* Any out-of-memory problem */
|
|
#define ERR_ST 0x11 /* ran out allocating State-infos */
|
|
|
|
#define ERR_NUM 0x20 /* Any numeric stability problem */
|
|
|
|
#define ERR_BUG 0x40 /* Any lp_solve-bug exit */
|
|
#define ERR_BUG_CONDCOL 0x41 /* Condensecol out-of-bounds */
|
|
|
|
#include <setjmp.h>
|
|
extern jmp_buf LP_jmpbuf;
|
|
extern int SolveCount;
|
|
|
|
#endif
|