miércoles, 28 de abril de 2010

Compilar aplicaciones con glpk en Debian y windows7

Para los desarrolladores y usuarios que estan interesados en Programacion lineal, y software libre se tiene la opcion glpk para linux y glpk para windows

La idea del presente blog es explicar como consegui compilar mi primera aplicacion incluyendo la libreria glpk tanto en debian lenny como en Windows7.

para lenny la instalacion de glpk es sencilla, basta con usar Synaptic e instalar todo lo que tenga que ver con glpk (incluyendo libglpk-dev)

en windows se tiene que bajar el setup de gplk.

Ahora viene lo interesante con los programas compiladores y enlazadores, en mi caso usare Qdevelop tanto para windows como para linux.
antes de todo se debe instalar Qt4 en ambos sistemas, de eso nos ocuparemos en otro blog. Solo comentare que Qdevelop en linux se direcciona automaticamente al la instalacion de Qt realizada, mientras que en windows hay que compilar Qt y luego direccionar a las carpetas Qt creadas.

Si tenemos el mismo codigo siguiente para Lenny y Win

#include "stdio.h"
#include "stdlib.h"
#include "glpk.h"

int main(void)
{     glp_prob *lp;
int ia[1+1000], ja[1+1000];
double ar[1+1000], z, x1, x2, x3;
s1:   lp = glp_create_prob();
s2:   glp_set_prob_name(lp, "sample");
s3:   glp_set_obj_dir(lp, GLP_MAX);
s4:   glp_add_rows(lp, 3);
s5:   glp_set_row_name(lp, 1, "p");
s6:   glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 100.0);
s7:   glp_set_row_name(lp, 2, "q");
s8:   glp_set_row_bnds(lp, 2, GLP_UP, 0.0, 600.0);
s9:   glp_set_row_name(lp, 3, "r");
s10: glp_set_row_bnds(lp, 3, GLP_UP, 0.0, 300.0);
s11: glp_add_cols(lp, 3);
s12: glp_set_col_name(lp, 1, "x1");
s13: glp_set_col_bnds(lp, 1, GLP_LO, 0.0, 0.0);
s14: glp_set_obj_coef(lp, 1, 10.0);
s15: glp_set_col_name(lp, 2, "x2");
s16: glp_set_col_bnds(lp, 2, GLP_LO, 0.0, 0.0);
s17: glp_set_obj_coef(lp, 2, 6.0);
s18: glp_set_col_name(lp, 3, "x3");
s19: glp_set_col_bnds(lp, 3, GLP_LO, 0.0, 0.0);
s20: glp_set_obj_coef(lp, 3, 4.0);
s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1]  = 1 */
s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2]  = 1 */
s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3]  = 1 */
s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */
s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1]  = 2 */
s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2]  = 4 */
s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2]  = 2 */
s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3]  = 5 */
s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3]  = 6 */
s30: glp_load_matrix(lp, 9, ia, ja, ar);
s31:  glp_simplex(lp, NULL);
s32:  z = glp_get_obj_val(lp);
s33:  x1 = glp_get_col_prim(lp, 1);
s34:  x2 = glp_get_col_prim(lp, 2);
s35:  x3 = glp_get_col_prim(lp, 3);
s36:  printf("\nz = %g; x1 = %g; x2 = %g; x3 = %g\n", z, x1, x2, x3);
s37:  glp_delete_prob(lp);
return 0;
}/* eof */


En ambos sistemas (Debian y Win) solo nos queda crear un nuevo proyecto vacio en Qdevelop, luego incluir un archivo sample.cpp con el codigo lineas arriba, glpk.h deberia ser llamado automaticamente, en ambos sistemas si esta instalado correctamente glpk, en todo caso se detalla la direccion donde esta instalado en propiedades del proyecto (en en otras palabras en el archivo Makefile en la seccion INCPATH = -I/C:\Program Files\GnuWin32\include).

luego para enlazar la libreria de manera implicita (esta manera pedira los *.dlls requeridos o los *.so en linux para correr la aplicacion, los cuales deben ir junto con el programa) en linux tuve que añadir en las propiedades del proyecto la libreria glpk entonces eso en Makefile.

LIBS          = $(SUBLIBS)  -L/usr/lib -lglpk -lm -lQtGui -lQtCore -lpthread



y en windows se tuvo que añadir la libreria se añade de igual manera solo que ahora se le dice glpk.lib, si no la encuentra poner la libreria en la direccion del codigo (Makefile-Release).

LIBS        =        -L"d:\Qt\4.3.2\lib" glpk.lib -lQtGui4 -lQtCore4


Luego de compilar y correr sin errrores se obtiene lo siguiente en la ventana de Depuracion o Salida.

Depurando...

(gdb) (gdb) (gdb) (gdb) (gdb) Starting program: /home/eangelino/glpkxxx/glpkxxx
[Thread debugging using libthread_db enabled]
* 0: objval = 0.000000000e+00 infeas = 0.000000000e+00 (0)
* 2: objval = 7.333333333e+02 infeas = 0.000000000e+00 (0)


OPTIMAL SOLUTION FOUND

z = 733.333; x1 = 33.3333; x2 = 66.6667; x3 = 0

Program exited normally.



Actualizacion: En windows luego de instalar el glkp solo ejecutables se debe incluir en el Qt, en propiedades del proyecto:

INCLUDEPATH : "C:\Program Files\GnuWin32\include"
LIB : "C:\Program Files\GnuWin32\lib\glpk.lib"