diff --git a/_oasis b/_oasis
index aaf751670368ed47e2cf5bbb9a63c484043428c6..61aa0cccbe1a91db969a8b89dfb3ca3437d06063 100644
--- a/_oasis
+++ b/_oasis
@@ -26,6 +26,7 @@ Library libcool
   CCOpt: -std=c++98 -x c++
   CSources:         gmlmip_stub.c,
                     minisat_stub.c,
+                    glpk_stub.c,
                     GMLMIP-0.1/rules/sizefunctions.c,
                     GMLMIP-0.1/rules/setofconclusions.c,
                     GMLMIP-0.1/rules/PML_premise.c,
diff --git a/src/lib/glpk_stub.c b/src/lib/glpk_stub.c
index df77a01c0d54c04be9fdcaf6f8ddf776ac8f5276..82075ad5d44c21ff40425875712297daff64a6bf 100644
--- a/src/lib/glpk_stub.c
+++ b/src/lib/glpk_stub.c
@@ -1,6 +1,6 @@
 /*
  * ocaml-glpk - OCaml bindings to glpk
- * Copyright (C) 2004 Samuel Mimram
+ * Copyright (C) 2004 Samuel Mimram, 2014 Dominik Paulus
  *
  * 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
@@ -18,8 +18,6 @@
  * Boston, MA 02111-1307, USA.
  */
 
-/* $Id$ */
-
 #include <caml/alloc.h>
 #include <caml/callback.h>
 #include <caml/custom.h>
@@ -34,184 +32,187 @@
 #include <glpk.h>
 
 static void raise_on_error(int ret) {
+	/* TODO: Do we want this semantics? */
+#if 0
 	switch(ret) {
-		case LPX_E_OK:
+		case glp_prob_E_OK:
 			return;
 
-		case LPX_E_FAULT:
+		case glp_prob_E_FAULT:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_fault"));
 
-		case LPX_E_OBJLL:
+		case glp_prob_E_OBJLL:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_objll"));
 
-		case LPX_E_OBJUL:
+		case glp_prob_E_OBJUL:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_objul"));
 
-		case LPX_E_NOPFS:
+		case glp_prob_E_NOPFS:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_nopfs"));
 
-		case LPX_E_NODFS:
+		case glp_prob_E_NODFS:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_nodfs"));
 
-		case LPX_E_ITLIM:
+		case glp_prob_E_ITLIM:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_itlim"));
 
-		case LPX_E_TMLIM:
+		case glp_prob_E_TMLIM:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_tmlim"));
 
-		case LPX_E_SING:
+		case glp_prob_E_SING:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_sing"));
 
-		case LPX_E_EMPTY:
+		case glp_prob_E_EMPTY:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_empty"));
 
-		case LPX_E_BADB:
+		case glp_prob_E_BADB:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_badb"));
 
-		case LPX_E_NOCONV:
+		case glp_prob_E_NOCONV:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_noconv"));
 
 		default:
 			caml_raise_constant(*caml_named_value("ocaml_glpk_exn_unknown"));
 	}
 	assert(0); /* TODO */
+#endif
 }
 
-#define Lpx_val(v) (*((LPX**)Data_custom_val(v)))
+#define Glp_val(v) (*((glp_prob**)Data_custom_val(v)))
 
-static void finalize_lpx(value block) {
-	lpx_delete_prob(Lpx_val(block));
+static void finalize_glp(value block) {
+	glp_delete_prob(Glp_val(block));
 }
 
-static struct custom_operations lpx_ops = {
-	"ocaml_glpk_lpx",
-	finalize_lpx,
+static struct custom_operations glp_ops = {
+	(char*) "ocaml_glpk_prob",
+	finalize_glp,
 	custom_compare_default,
 	custom_hash_default,
 	custom_serialize_default,
 	custom_deserialize_default
 };
 
-static value new_blp(LPX *lp) {
-	value block = caml_alloc_custom(&lpx_ops, sizeof(LPX *), 0, 1);
-	Lpx_val(block) = lp;
+static value box_problem(glp_prob *lp) {
+	value block = caml_alloc_custom(&glp_ops, sizeof(glp_prob*), 0, 1);
+	Glp_val(block) = lp;
 	return block;
 }
 
 CAMLprim value ocaml_glpk_new_prob(value unit) {
-	LPX *lp = lpx_create_prob();
-	return new_blp(lp);
+	glp_prob *lp = glp_create_prob();
+	return box_problem(lp);
 }
 
 CAMLprim value ocaml_glpk_set_prob_name(value blp, value name) {
-	LPX *lp = Lpx_val(blp);
-	lpx_set_prob_name(lp, String_val(name));
+	glp_prob *lp = Glp_val(blp);
+	glp_set_prob_name(lp, String_val(name));
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_get_prob_name(value blp) {
 	CAMLparam1(blp);
-	LPX *lp = Lpx_val(blp);
-	CAMLreturn(caml_copy_string(lpx_get_prob_name(lp)));
+	glp_prob *lp = Glp_val(blp);
+	CAMLreturn(caml_copy_string(glp_get_prob_name(lp)));
 }
 
 CAMLprim value ocaml_glpk_set_obj_name(value blp, value name) {
-	LPX *lp = Lpx_val(blp);
-	lpx_set_obj_name(lp, String_val(name));
+	glp_prob *lp = Glp_val(blp);
+	glp_set_obj_name(lp, String_val(name));
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_get_obj_name(value blp) {
 	CAMLparam1(blp);
-	LPX *lp = Lpx_val(blp);
-	CAMLreturn(caml_copy_string(lpx_get_obj_name(lp)));
+	glp_prob *lp = Glp_val(blp);
+	CAMLreturn(caml_copy_string(glp_get_obj_name(lp)));
 }
 
-static int direction_table[] = {LPX_MIN, LPX_MAX};
+static int direction_table[] = {GLP_MIN, GLP_MAX};
 
 CAMLprim value ocaml_glpk_set_direction(value blp, value direction) {
-	LPX *lp = Lpx_val(blp);
-	lpx_set_obj_dir(lp, direction_table[Int_val(direction)]);
+	glp_prob *lp = Glp_val(blp);
+	glp_set_obj_dir(lp, direction_table[Int_val(direction)]);
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_get_direction(value blp) {
-	LPX *lp = Lpx_val(blp);
-	switch(lpx_get_obj_dir(lp)) {
-		case LPX_MIN:
-			return Val_int(0);
-
-		case LPX_MAX:
-			return Val_int(1);
-
-		default:
-			assert(0);
+	glp_prob *lp = Glp_val(blp);
+	switch(glp_get_obj_dir(lp)) {
+		case GLP_MIN: return Val_int(0);
+		case GLP_MAX: return Val_int(1);
+		default: assert(0);
 	}
 }
 
 CAMLprim value ocaml_glpk_add_rows(value blp, value n) {
-	LPX *lp = Lpx_val(blp);
-	lpx_add_rows(lp, Int_val(n));
+	glp_prob *lp = Glp_val(blp);
+	glp_add_rows(lp, Int_val(n));
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_set_row_name(value blp, value n, value name) {
-	LPX *lp = Lpx_val(blp);
-	lpx_set_row_name(lp, Int_val(n) + 1, String_val(name));
+	glp_prob *lp = Glp_val(blp);
+	glp_set_row_name(lp, Int_val(n) + 1, String_val(name));
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_get_row_name(value blp, value n) {
 	CAMLparam1(blp);
-	LPX *lp = Lpx_val(blp);
-	CAMLreturn(caml_copy_string(lpx_get_row_name(lp, Int_val(n) + 1)));
+	glp_prob *lp = Glp_val(blp);
+	CAMLreturn(caml_copy_string(glp_get_row_name(lp, Int_val(n) + 1)));
 }
 
-static int auxvartype_table[] = {LPX_FR, LPX_LO, LPX_UP, LPX_DB, LPX_FX};
+static int auxvartype_table[] = {
+	GLP_FR, /* Unbound variable */
+	GLP_LO, /* Lower bound */
+	GLP_UP, /* Upper bound */
+	GLP_DB, /* Lower and upper bound */
+	GLP_FX  /* Fixed value */ };
 
 CAMLprim value ocaml_glpk_set_row_bounds(value blp, value n, value type, value lb, value ub) {
-	LPX *lp = Lpx_val(blp);
-	lpx_set_row_bnds(lp, Int_val(n) + 1, auxvartype_table[Int_val(type)], Double_val(lb), Double_val(ub));
+	glp_prob *lp = Glp_val(blp);
+	glp_set_row_bnds(lp, Int_val(n) + 1, auxvartype_table[Int_val(type)], Double_val(lb), Double_val(ub));
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_add_cols(value blp, value n) {
-	LPX *lp = Lpx_val(blp);
-	lpx_add_cols(lp, Int_val(n));
+	glp_prob *lp = Glp_val(blp);
+	glp_add_cols(lp, Int_val(n));
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_set_col_name(value blp, value n, value name) {
-	LPX *lp = Lpx_val(blp);
-	lpx_set_col_name(lp, Int_val(n) + 1, String_val(name));
+	glp_prob *lp = Glp_val(blp);
+	glp_set_col_name(lp, Int_val(n) + 1, String_val(name));
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_get_col_name(value blp, value n) {
 	CAMLparam1(blp);
-	LPX *lp = Lpx_val(blp);
-	CAMLreturn(caml_copy_string(lpx_get_col_name(lp, Int_val(n) + 1)));
+	glp_prob *lp = Glp_val(blp);
+	CAMLreturn(caml_copy_string(glp_get_col_name(lp, Int_val(n) + 1)));
 }
 
 CAMLprim value ocaml_glpk_set_col_bounds(value blp, value n, value type, value lb, value ub) {
-	LPX *lp = Lpx_val(blp);
-	lpx_set_col_bnds(lp, Int_val(n) + 1, auxvartype_table[Int_val(type)], Double_val(lb), Double_val(ub));
+	glp_prob *lp = Glp_val(blp);
+	glp_set_col_bnds(lp, Int_val(n) + 1, auxvartype_table[Int_val(type)], Double_val(lb), Double_val(ub));
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_set_obj_coef(value blp, value n, value coef) {
-	LPX *lp = Lpx_val(blp);
-	lpx_set_obj_coef(lp, Int_val(n) + 1, Double_val(coef));
+	glp_prob *lp = Glp_val(blp);
+	glp_set_obj_coef(lp, Int_val(n) + 1, Double_val(coef));
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_load_matrix(value blp, value matrix) {
-	LPX *lp = Lpx_val(blp);
-	int i_dim = Wosize_val(matrix), j_dim;
+	glp_prob *lp = Glp_val(blp);
+	unsigned int i_dim = Wosize_val(matrix), j_dim;
 	int *ia, *ja;
 	double *ar;
 	double x;
-	int i, j, n;
+	unsigned int i, j, n;
 
 	if(i_dim <= 0)
 		return Val_unit;
@@ -236,7 +237,7 @@ CAMLprim value ocaml_glpk_load_matrix(value blp, value matrix) {
 			}
 		}
 	}
-	lpx_load_matrix(lp, n - 1, ia, ja, ar);
+	glp_load_matrix(lp, n - 1, ia, ja, ar);
 
 	free(ia);
 	free(ja);
@@ -246,7 +247,7 @@ CAMLprim value ocaml_glpk_load_matrix(value blp, value matrix) {
 }
 
 CAMLprim value ocaml_glpk_load_sparse_matrix(value blp, value matrix) {
-	LPX *lp = Lpx_val(blp);
+	glp_prob *lp = Glp_val(blp);
 	int len = Wosize_val(matrix);
 	int *ia, *ja;
 	double *ar;
@@ -263,7 +264,7 @@ CAMLprim value ocaml_glpk_load_sparse_matrix(value blp, value matrix) {
 		ja[i + 1] = Int_val(Field(Field(e, 0), 1)) + 1;
 		ar[i + 1] = Double_val(Field(e, 1));
 	}
-	lpx_load_matrix(lp, len, ia, ja, ar);
+	glp_load_matrix(lp, len, ia, ja, ar);
 
 	free(ia);
 	free(ja);
@@ -274,11 +275,11 @@ CAMLprim value ocaml_glpk_load_sparse_matrix(value blp, value matrix) {
 
 CAMLprim value ocaml_glpk_simplex(value blp) {
 	CAMLparam1(blp);
-	LPX *lp = Lpx_val(blp);
+	glp_prob *lp = Glp_val(blp);
 	int ret;
 
 	caml_enter_blocking_section();
-	ret = lpx_simplex(lp);
+	ret = glp_simplex(lp, NULL);
 	caml_leave_blocking_section();
 
 	raise_on_error(ret);
@@ -286,195 +287,125 @@ CAMLprim value ocaml_glpk_simplex(value blp) {
 }
 
 CAMLprim value ocaml_glpk_get_obj_val(value blp) {
-	LPX *lp = Lpx_val(blp);
+	glp_prob *lp = Glp_val(blp);
 	double ans;
-	if(lpx_get_class(lp) == LPX_MIP)
-		ans = lpx_mip_obj_val(lp);
-	else
-		ans = lpx_get_obj_val(lp);
+	ans = glp_get_obj_val(lp);
 	return caml_copy_double(ans);
 }
 
 CAMLprim value ocaml_glpk_get_col_prim(value blp, value n) {
-	LPX *lp = Lpx_val(blp);
+	glp_prob *lp = Glp_val(blp);
 	double ans;
-	/* TODO: is it the right thing to do? */
-	if(lpx_get_class(lp) == LPX_MIP)
-		ans = lpx_mip_col_val(lp, Int_val(n) + 1);
-	else
-		ans = lpx_get_col_prim(lp, Int_val(n) + 1);
+	ans = glp_get_col_prim(lp, Int_val(n) + 1);
 	return caml_copy_double(ans);
 }
 
 CAMLprim value ocaml_glpk_get_row_prim(value blp, value n) {
-	LPX *lp = Lpx_val(blp);
-	return caml_copy_double(lpx_get_row_prim(lp, Int_val(n) + 1));
+	glp_prob *lp = Glp_val(blp);
+	return caml_copy_double(glp_get_row_prim(lp, Int_val(n) + 1));
 }
 
 CAMLprim value ocaml_glpk_get_row_dual(value blp, value n) {
-	LPX *lp = Lpx_val(blp);
-	return caml_copy_double(lpx_get_row_dual(lp, Int_val(n) + 1));
+	glp_prob *lp = Glp_val(blp);
+	return caml_copy_double(glp_get_row_dual(lp, Int_val(n) + 1));
 }
 
 CAMLprim value ocaml_glpk_get_num_rows(value blp) {
-	LPX *lp = Lpx_val(blp);
-	return Val_int(lpx_get_num_rows(lp));
+	glp_prob *lp = Glp_val(blp);
+	return Val_int(glp_get_num_rows(lp));
 }
 
 CAMLprim value ocaml_glpk_get_num_cols(value blp) {
-	LPX *lp = Lpx_val(blp);
-	return Val_int(lpx_get_num_cols(lp));
+	glp_prob *lp = Glp_val(blp);
+	return Val_int(glp_get_num_cols(lp));
 }
 
 CAMLprim value ocaml_glpk_scale_problem(value blp) {
-	LPX *lp = Lpx_val(blp);
-	lpx_scale_prob(lp);
+	glp_prob *lp = Glp_val(blp);
+	glp_scale_prob(lp, GLP_SF_AUTO); /* TODO! */
 	return Val_unit;
 }
 
 CAMLprim value ocaml_glpk_unscale_problem(value blp) {
-	LPX *lp = Lpx_val(blp);
-	lpx_unscale_prob(lp);
+	glp_prob *lp = Glp_val(blp);
+	glp_unscale_prob(lp);
 	return Val_unit;
 }
 
-/* TODO */
-/*
-CAMLprim value ocaml_glpk_check_kkt(value blp, value scaled, value vkkt)
-{
-
-}
-*/
-
 CAMLprim value ocaml_glpk_interior(value blp) {
 	CAMLparam1(blp);
-	LPX *lp = Lpx_val(blp);
+	glp_prob *lp = Glp_val(blp);
 	int ret;
 
 	caml_enter_blocking_section();
-	ret = lpx_interior(lp);
+	ret = glp_interior(lp, NULL); /* TODO! */
 	caml_leave_blocking_section();
 
 	raise_on_error(ret);
 	CAMLreturn(Val_unit);
 }
 
-static int class_table[] = {LPX_LP, LPX_MIP};
-
-CAMLprim value ocaml_glpk_set_class(value blp, value class) {
-	LPX *lp = Lpx_val(blp);
-	lpx_set_class(lp, class_table[Int_val(class)]);
-	return Val_unit;
-}
-
-CAMLprim value ocaml_glpk_get_class(value blp) {
-	LPX *lp = Lpx_val(blp);
-	switch(lpx_get_class(lp)) {
-		case LPX_LP:
-			return Val_int(0);
-
-		case LPX_MIP:
-			return Val_int(1);
-
-		default:
-			assert(0);
-	}
-}
-
-static int kind_table[] = {LPX_CV, LPX_IV};
+static int kind_table[] = {GLP_CV, GLP_IV};
 
 CAMLprim value ocaml_glpk_set_col_kind(value blp, value n, value kind) {
-	LPX *lp = Lpx_val(blp);
-	lpx_set_col_kind(lp, Int_val(n) + 1, kind_table[Int_val(kind)]);
+	glp_prob *lp = Glp_val(blp);
+	glp_set_col_kind(lp, Int_val(n) + 1, kind_table[Int_val(kind)]);
 	return Val_unit;
 }
 
-CAMLprim value ocaml_glpk_integer(value blp) {
-	CAMLparam1(blp);
-	LPX *lp = Lpx_val(blp);
-	int ret;
-
-	caml_enter_blocking_section();
-	ret = lpx_integer(lp);
-	caml_leave_blocking_section();
-
-	raise_on_error(ret);
-	CAMLreturn(Val_unit);
-}
-
-CAMLprim value ocaml_glpk_intopt(value blp) {
-	CAMLparam1(blp);
-	LPX *lp = Lpx_val(blp);
-	int ret;
-
-	caml_enter_blocking_section();
-	ret = lpx_intopt(lp);
-	caml_leave_blocking_section();
-
-	raise_on_error(ret);
-	CAMLreturn(Val_unit);
-}
-
 CAMLprim value ocaml_glpk_warm_up(value blp) {
-	LPX *lp = Lpx_val(blp);
-	raise_on_error(lpx_warm_up(lp));
+	glp_prob *lp = Glp_val(blp);
+	raise_on_error(glp_warm_up(lp));
 	return Val_unit;
 }
 
+#if 0
+
+/* TODO! */
+
 #define BIND_INT_PARAM(name, param) \
 	CAMLprim value ocaml_glpk_get_##name(value blp) \
 	{ \
-		LPX *lp = Lpx_val(blp); \
+		glp_prob *lp = Glp_val(blp); \
 		return Val_int(lpx_get_int_parm(lp, param)); \
 	} \
 	CAMLprim value ocaml_glpk_set_##name(value blp, value n) \
 	{ \
-		LPX *lp = Lpx_val(blp); \
-		lpx_set_int_parm(lp, param, Int_val(n)); \
+		glp_prob *lp = Glp_val(blp); \
+		glp_set_int_parm(lp, param, Int_val(n)); \
 		return Val_unit; \
 	}
 
 #define BIND_REAL_PARAM(name, param) \
 	CAMLprim value ocaml_glpk_get_##name(value blp) \
 	{ \
-		LPX *lp = Lpx_val(blp); \
+		glp_prob *lp = Glp_val(blp); \
 		double ans = lpx_get_real_parm(lp, param); \
 		return caml_copy_double(ans); \
 	} \
 	CAMLprim value ocaml_glpk_set_##name(value blp, value n) \
 	{ \
-		LPX *lp = Lpx_val(blp); \
-		lpx_set_real_parm(lp, param, Double_val(n)); \
+		glp_prob *lp = Glp_val(blp); \
+		glp_set_real_parm(lp, param, Double_val(n)); \
 		return Val_unit; \
 	}
 
-BIND_INT_PARAM(message_level, LPX_K_MSGLEV);
-BIND_INT_PARAM(scaling, LPX_K_SCALE);
-BIND_INT_PARAM(use_dual_simplex, LPX_K_DUAL);
-BIND_INT_PARAM(pricing, LPX_K_PRICE);
-BIND_REAL_PARAM(relaxation, LPX_K_RELAX);
+BIND_INT_PARAM(message_level, glp_prob_K_MSGLEV);
+BIND_INT_PARAM(scaling, glp_prob_K_SCALE);
+BIND_INT_PARAM(use_dual_simplex, glp_prob_K_DUAL);
+BIND_INT_PARAM(pricing, glp_prob_K_PRICE);
+BIND_REAL_PARAM(relaxation, glp_prob_K_RELAX);
 /*
-BIND_REAL_PARAM(relative_tolerance, LPX_K_TOLBND);
-BIND_REAL_PARAM(absolute_tolerance, LPX_K_TOLDJ);
+BIND_REAL_PARAM(relative_tolerance, glp_prob_K_TOLBND);
+BIND_REAL_PARAM(absolute_tolerance, glp_prob_K_TOLDJ);
 */
-BIND_INT_PARAM(solution_rounding, LPX_K_ROUND);
-BIND_INT_PARAM(iteration_limit, LPX_K_ITLIM);
-BIND_INT_PARAM(iteration_count, LPX_K_ITCNT);
-BIND_REAL_PARAM(time_limit, LPX_K_TMLIM);
-BIND_INT_PARAM(branching_heuristic, LPX_K_BRANCH);
-BIND_INT_PARAM(backtracking_heuristic, LPX_K_BTRACK);
-BIND_INT_PARAM(use_presolver, LPX_K_PRESOL);
-
-CAMLprim value ocaml_glpk_read_cplex(value fname) {
-	LPX *lp = lpx_read_cpxlp(String_val(fname));
-	if(!lp)
-		caml_failwith("Error while reading data in CPLEX LP format.");
-	return new_blp(lp);
-}
-
-CAMLprim value ocaml_glpk_write_cplex(value blp, value fname) {
-	if(lpx_write_cpxlp(Lpx_val(blp), String_val(fname)))
-		caml_failwith("Error while writing data in CPLEX LP format.");
-	return Val_unit;
-}
+BIND_INT_PARAM(solution_rounding, glp_prob_K_ROUND);
+BIND_INT_PARAM(iteration_limit, glp_prob_K_ITLIM);
+BIND_INT_PARAM(iteration_count, glp_prob_K_ITCNT);
+BIND_REAL_PARAM(time_limit, glp_prob_K_TMLIM);
+BIND_INT_PARAM(branching_heuristic, glp_prob_K_BRANCH);
+BIND_INT_PARAM(backtracking_heuristic, glp_prob_K_BTRACK);
+BIND_INT_PARAM(use_presolver, glp_prob_K_PRESOL);
+
+#endif