;;
;; Chicken interface to the GLPK API.
;;
;; Copyright 2008-2010 Ivan Raikov and the Okinawa Institute of
;; Science and Technology.
;;
;; This program is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; A full copy of the GPL license can be found at
;; .
;;
(module glpk
(lpx? lpx:empty-problem lpx:make-problem
lpx:set-problem-name lpx:get-problem-name
lpx:set-direction lpx:get-direction lpx:set-class lpx:get-class
lpx:add-rows lpx:add-columns lpx:set-row-name lpx:set-column-name
lpx:get-column-name lpx:get-row-name lpx:get-num-rows lpx:get-num-columns
lpx:set-row-bounds lpx:set-column-bounds
lpx:set-objective-coefficient
lpx:set-column-kind lpx:load-constraint-matrix
lpx:get-column-primals lpx:get-objective-value
lpx:message_level lpx:scaling lpx:use_dual_simplex
lpx:pricing lpx:solution_rounding lpx:iteration_limit
lpx:iteration_count lpx:branching_heuristic
lpx:backtracking_heuristic lpx:use_presolver
lpx:relaxation lpx:time_limit
LPX_E_OK LPX_E_EMPTY LPX_E_BADB LPX_E_INFEAS
LPX_E_FAULT LPX_E_OBJLL LPX_E_OBJUL LPX_E_ITLIM
LPX_E_TMLIM LPX_E_NOFEAS LPX_E_INSTAB LPX_E_SING
LPX_E_NOCONV LPX_E_NOPFS LPX_E_NODFS
lpx:scale-problem lpx:simplex lpx:integer
)
(import scheme chicken foreign srfi-1 srfi-4 )
#>
#include
#include
#define ERR_INVALID_LPX 1
#define ERR_INVALID_LPX_DIR 2
#define ERR_INVALID_LPX_CLASS 3
#define ERR_NEG_IND 4
#define ERR_INVALID_COL_KIND 5
#define ERR_INVALID_MAT_ORD 6
static C_word LPX_p(C_word obj)
{
if (C_immediatep(obj)) {
return C_SCHEME_FALSE;
} else if (C_block_header(obj) == LPX_TAG)
{
return C_SCHEME_TRUE;
} else {
return C_SCHEME_FALSE;
}
}
static void chicken_Panic (C_char *) C_noret;
static void chicken_Panic (C_char *msg)
{
C_word *a = C_alloc (C_SIZEOF_STRING (strlen (msg)));
C_word scmmsg = C_string2 (&a, msg);
C_halt (scmmsg);
exit (5); /* should never get here */
}
static void chicken_ThrowException(C_word value) C_noret;
static void chicken_ThrowException(C_word value)
{
char *aborthook = C_text("\003sysabort");
C_word *a = C_alloc(C_SIZEOF_STRING(strlen(aborthook)));
C_word abort = C_intern2(&a, aborthook);
abort = C_block_item(abort, 0);
if (C_immediatep(abort))
chicken_Panic(C_text("`##sys#abort' is not defined"));
C_save(value);
C_do_apply(1, abort, C_SCHEME_UNDEFINED);
}
void chicken_LPX_exception (int code, int msglen, const char *msg)
{
C_word *a;
C_word scmmsg;
C_word list;
a = C_alloc (C_SIZEOF_STRING (msglen) + C_SIZEOF_LIST(2));
scmmsg = C_string2 (&a, (char *) msg);
list = C_list(&a, 2, C_fix(code), scmmsg);
chicken_ThrowException(list);
}
static C_word check_LPX (C_word obj)
{
if (C_immediatep(obj))
{
chicken_LPX_exception (ERR_INVALID_LPX, 18, "invalid LPX object");
} else if (C_block_header(obj) == LPX_TAG)
{
return C_SCHEME_UNDEFINED;
} else {
chicken_LPX_exception (ERR_INVALID_LPX, 18, "invalid LPX object");
}
}
<#
(define lpx? (foreign-lambda scheme-object "LPX_p" scheme-object))
(define lpx:empty-problem
(foreign-primitive scheme-object ()
#< 0))
{
chicken_LPX_exception (ERR_NEG_IND, 22, "nrows must be positive");
}
lp = LPX_val(lpx);
lpx_add_rows (lp, nrows);
C_return(lpx);
END
))
(define lpx:get-num-rows
(foreign-lambda* int ((scheme-object lpx))
#< 0))
{
chicken_LPX_exception (ERR_NEG_IND, 22, "ncols must be positive");
}
lp = LPX_val(lpx);
lpx_add_cols (lp, ncols);
C_return(lpx);
END
))
(define lpx:get-num-columns
(foreign-lambda* int ((scheme-object lpx))
#<= 0))
{
chicken_LPX_exception (ERR_NEG_IND, 34, "row index must be zero or positive");
}
lp = LPX_val(lpx);
lpx_set_row_name (lp, i, name);
C_return(lpx);
END
))
(define lpx:set-column-name
(foreign-lambda* scheme-object ((scheme-object lpx)
(int j)
(c-string name))
#<= 0))
{
chicken_LPX_exception (ERR_NEG_IND, 37, "column index must be zero or positive");
}
lp = LPX_val(lpx);
lpx_set_col_name (lp, j, name);
C_return(lpx);
END
))
(define lpx:get-row-name
(foreign-lambda* c-string ((scheme-object lpx)
(int i))
#<= 0))
{
chicken_LPX_exception (ERR_NEG_IND, 34, "row index must be zero or positive");
}
lp = LPX_val(lpx);
result = lpx_get_row_name (lp, i);
C_return(result);
END
))
(define lpx:get-column-name
(foreign-lambda* c-string ((scheme-object lpx)
(int i))
#<= 0))
{
chicken_LPX_exception (ERR_NEG_IND, 37, "column index must be zero or positive");
}
lp = LPX_val(lpx);
result = lpx_get_col_name (lp, i);
C_return(result);
END
))
(define LPX_LO (foreign-value "LPX_LO" int))
(define LPX_UP (foreign-value "LPX_UP" int))
(define LPX_DB (foreign-value "LPX_DB" int))
(define LPX_FX (foreign-value "LPX_FX" int))
(define LPX_FR (foreign-value "LPX_FR" int))
(define lpx_set_row_bounds
(foreign-lambda* scheme-object ((scheme-object lpx)
(int i)
(int typx)
(double lb) (double ub)
)
#<= 0))
{
chicken_LPX_exception (ERR_NEG_IND, 34, "row index must be zero or positive");
}
lp = LPX_val(lpx);
lpx_set_row_bnds (lp, i, typx, lb, ub);
C_return(lpx);
END
))
(define lpx_set_col_bounds
(foreign-lambda* scheme-object ((scheme-object lpx)
(int j)
(int typx)
(double lb) (double ub)
)
#<= 0))
{
chicken_LPX_exception (ERR_NEG_IND, 37, "column index must be zero or positive");
}
lp = LPX_val(lpx);
lpx_set_col_bnds (lp, j, typx, lb, ub);
C_return(lpx);
END
))
(define (lpx_set_bounds label f_set_bounds)
(lambda (lpx i typx . rest)
(let-optionals rest ((b1 #f) (b2 #f))
(case typx
((free unbounded) (f_set_bounds lpx i LPX_FR 0 0))
((lower-bound lower lo lb)
(if (integer? b1)
(f_set_bounds lpx i LPX_LO b1 0)
(error label "lower bound argument must be an integer")))
((upper-bound upper up ub)
(if (integer? b1)
(f_set_bounds lpx i LPX_UP 0 b1)
(error label "upper bound argument must be an integer")))
((double-bounded double db)
(if (and (integer? b1) (integer? b2))
(f_set_bounds lpx i LPX_DB b1 b2)
(error label "lower and upper bound arguments must be integers")))
((fixed fx)
(if (and (integer? b1) (integer? b2))
(f_set_bounds lpx i LPX_FX b1 b2)
(error label "lower and upper bound arguments must be integers")))
(else (error label "invalid bound type" typx))))))
(define lpx:set-row-bounds (lpx_set_bounds 'lpx:set-row-bounds lpx_set_row_bounds))
(define lpx:set-column-bounds (lpx_set_bounds 'lpx:set-column-bounds lpx_set_col_bounds))
(define lpx_get_column_primals
(foreign-lambda* void ((scheme-object lpx)
(int n)
(f64vector v)
)
#<= 0))
{
chicken_LPX_exception (ERR_NEG_IND, 37, "column index must be zero or positive");
}
lp = LPX_val(lpx);
lpx_set_obj_coef (lp, j, coef);
C_return(lpx);
END
))
(define LPX_CV (foreign-value "LPX_CV" int))
(define LPX_IV (foreign-value "LPX_IV" int))
(define lpx_set_column_kind
(foreign-lambda* scheme-object ((scheme-object lpx)
(int j)
(int kind)
)
#<= 0))
{
chicken_LPX_exception (ERR_NEG_IND, 37, "column index must be zero or positive");
}
if (!((kind == LPX_CV) || (kind == LPX_IV)))
{
chicken_LPX_exception (ERR_INVALID_COL_KIND, 23, "invalid LPX column kind");
}
lp = LPX_val(lpx);
lpx_set_col_kind (lp, j, kind);
C_return(lpx);
END
))
(define (lpx:set-column-kind lpx j kind)
(case kind
((integer int iv) (lpx_set_column_kind lpx j LPX_IV))
((continuous cont cv) (lpx_set_column_kind lpx j LPX_CV))
(else (error 'lpx:set-column-kind "invalid column kind" kind))))
(define lpx_load_constraint_matrix
(foreign-lambda* scheme-object ((scheme-object lpx)
(int nrows)
(int ncols)
(char order)
(f64vector m)
(s32vector ia)
(s32vector ja)
(f64vector ar)
)
#<