naev 0.11.5
nlua_linopt.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
4
12#include <glpk.h>
13#include <lauxlib.h>
14#include "physfs.h"
15
16#include "naev.h"
19#include "nlua_linopt.h"
20
21#include "log.h"
22#include "nstring.h"
23#include "nluadef.h"
24
25#define LINOPT_MAX_TM 1000
30typedef struct LuaLinOpt_s {
31 int ncols;
32 int nrows;
33 glp_prob *prob;
35
36/* Optim metatable methods. */
37static int linoptL_gc( lua_State *L );
38static int linoptL_eq( lua_State *L );
39static int linoptL_new( lua_State *L );
40static int linoptL_size( lua_State *L );
41static int linoptL_addcols( lua_State *L );
42static int linoptL_addrows( lua_State *L );
43static int linoptL_setcol( lua_State *L );
44static int linoptL_setrow( lua_State *L );
45static int linoptL_loadmatrix( lua_State *L );
46static int linoptL_solve( lua_State *L );
47static int linoptL_readProblem( lua_State *L );
48static int linoptL_writeProblem( lua_State *L );
49static const luaL_Reg linoptL_methods[] = {
50 { "__gc", linoptL_gc },
51 { "__eq", linoptL_eq },
52 { "new", linoptL_new },
53 { "size", linoptL_size },
54 { "add_cols", linoptL_addcols },
55 { "add_rows", linoptL_addrows },
56 { "set_col", linoptL_setcol },
57 { "set_row", linoptL_setrow },
58 { "load_matrix", linoptL_loadmatrix },
59 { "solve", linoptL_solve },
60 { "read_problem", linoptL_readProblem },
61 { "write_problem", linoptL_writeProblem },
62 {0,0}
63};
71int nlua_loadLinOpt( nlua_env env )
72{
73 nlua_register(env, LINOPT_METATABLE, linoptL_methods, 1);
74 return 0;
75}
76
89LuaLinOpt_t* lua_tolinopt( lua_State *L, int ind )
90{
91 return (LuaLinOpt_t*) lua_touserdata(L,ind);
92}
93
101LuaLinOpt_t* luaL_checklinopt( lua_State *L, int ind )
102{
103 if (lua_islinopt(L,ind))
104 return lua_tolinopt(L,ind);
105 luaL_typerror(L, ind, LINOPT_METATABLE);
106 return NULL;
107}
108
116LuaLinOpt_t* lua_pushlinopt( lua_State *L, LuaLinOpt_t linopt )
117{
118 LuaLinOpt_t *c = (LuaLinOpt_t*) lua_newuserdata(L, sizeof(LuaLinOpt_t));
119 *c = linopt;
120 luaL_getmetatable(L, LINOPT_METATABLE);
121 lua_setmetatable(L, -2);
122 return c;
123}
124
132int lua_islinopt( lua_State *L, int ind )
133{
134 int ret;
135
136 if (lua_getmetatable(L,ind)==0)
137 return 0;
138 lua_getfield(L, LUA_REGISTRYINDEX, LINOPT_METATABLE);
139
140 ret = 0;
141 if (lua_rawequal(L, -1, -2)) /* does it have the correct mt? */
142 ret = 1;
143
144 lua_pop(L, 2); /* remove both metatables */
145 return ret;
146}
147
154static int linoptL_gc( lua_State *L )
155{
156 LuaLinOpt_t *lp = luaL_checklinopt(L,1);
157 glp_delete_prob(lp->prob);
158 return 0;
159}
160
169static int linoptL_eq( lua_State *L )
170{
171 LuaLinOpt_t *lp1, *lp2;
172 lp1 = luaL_checklinopt(L,1);
173 lp2 = luaL_checklinopt(L,2);
174 lua_pushboolean( L, (memcmp( lp1, lp2, sizeof(LuaLinOpt_t))==0) );
175 return 1;
176}
177
188static int linoptL_new( lua_State *L )
189{
190 LuaLinOpt_t lp;
191 const char *name;
192 int max;
193
194 /* Input. */
195 name = luaL_optstring(L,1,NULL);
196 lp.ncols = luaL_checkinteger(L,2);
197 lp.nrows = luaL_checkinteger(L,3);
198 max = lua_toboolean(L,4);
199
200#ifdef DEBUGGING
201 if (lp.ncols <= 0)
202 return NLUA_ERROR( L, _("Number of columns in a linear optimization problem must be greater than 0!") );
203#endif /* DEBUGGING */
204
205 /* Initialize and create. */
206 lp.prob = glp_create_prob();
207 glp_set_prob_name( lp.prob, name );
208 glp_add_cols( lp.prob, lp.ncols );
209 glp_add_rows( lp.prob, lp.nrows );
210 if (max)
211 glp_set_obj_dir( lp.prob, GLP_MAX );
212
213 lua_pushlinopt( L, lp );
214 return 1;
215}
216
225static int linoptL_size( lua_State *L )
226{
227 LuaLinOpt_t *lp = luaL_checklinopt(L,1);
228 lua_pushinteger( L, glp_get_num_cols( lp->prob ) );
229 lua_pushinteger( L, glp_get_num_rows( lp->prob ) );
230 return 2;
231}
232
240static int linoptL_addcols( lua_State *L )
241{
242 LuaLinOpt_t *lp = luaL_checklinopt(L,1);
243 int toadd = luaL_checkinteger(L,2);
244 glp_add_cols( lp->prob, toadd );
245 lp->ncols += toadd;
246 return 0;
247}
248
256static int linoptL_addrows( lua_State *L )
257{
258 LuaLinOpt_t *lp = luaL_checklinopt(L,1);
259 int toadd = luaL_checkinteger(L,2);
260 glp_add_rows( lp->prob, toadd );
261 lp->nrows += toadd;
262 return 0;
263}
264
277static int linoptL_setcol( lua_State *L )
278{
279 LuaLinOpt_t *lp = luaL_checklinopt(L,1);
280 int idx = luaL_checkinteger(L,2);
281 const char *name = luaL_checkstring(L,3);
282 double coef = luaL_checknumber(L,4);
283 const char *skind = luaL_optstring(L,5,"real");
284 int haslb = !lua_isnoneornil(L,6);
285 int hasub = !lua_isnoneornil(L,7);
286 double lb = luaL_optnumber(L,6,0.0);
287 double ub = luaL_optnumber(L,7,0.0);
288 int type = GLP_FR, kind = GLP_CV;
289
290 /* glpk stuff */
291 glp_set_col_name( lp->prob, idx, name );
292 glp_set_obj_coef( lp->prob, idx, coef );
293
294 /* Determine bounds. */
295 if (haslb && hasub) {
296 if (fabs(lb-ub) < 1e-5)
297 type = GLP_FX;
298 else
299 type = GLP_DB;
300 }
301 else if (haslb)
302 type = GLP_LO;
303 else if (hasub)
304 type = GLP_UP;
305 else
306 type = GLP_FR;
307 glp_set_col_bnds( lp->prob, idx, type, lb, ub );
308
309 /* Get kind. */
310 if (strcmp(skind,"real")==0)
311 kind = GLP_CV;
312 else if (strcmp(skind,"integer")==0)
313 kind = GLP_IV;
314 else if (strcmp(skind,"binary")==0)
315 kind = GLP_BV;
316 else
317 return NLUA_ERROR(L,_("Unknown column kind '%s'!"), skind);
318 glp_set_col_kind( lp->prob, idx, kind );
319
320 return 0;
321}
322
333static int linoptL_setrow( lua_State *L )
334{
335 LuaLinOpt_t *lp = luaL_checklinopt(L,1);
336 int idx = luaL_checkinteger(L,2);
337 const char *name = luaL_checkstring(L,3);
338 int haslb, hasub, type;
339 double lb, ub;
340
341 /* glpk stuff */
342 glp_set_row_name( lp->prob, idx, name );
343
344 /* Determine bounds. */
345 haslb = !lua_isnoneornil(L,4);
346 hasub = !lua_isnoneornil(L,5);
347 lb = luaL_optnumber(L,4,0.0);
348 ub = luaL_optnumber(L,5,0.0);
349 if (haslb && hasub) {
350 if (fabs(lb-ub) < 1e-5)
351 type = GLP_FX;
352 else
353 type = GLP_DB;
354 }
355 else if (haslb)
356 type = GLP_LO;
357 else if (hasub)
358 type = GLP_UP;
359 else
360 type = GLP_FR;
361 glp_set_row_bnds( lp->prob, idx, type, lb, ub );
362
363 return 0;
364}
365
375static int linoptL_loadmatrix( lua_State *L )
376{
377 size_t n;
378 int *ia, *ja;
379 double *ar;
380 LuaLinOpt_t *lp = luaL_checklinopt(L,1);
381 luaL_checktype(L, 2, LUA_TTABLE);
382 luaL_checktype(L, 3, LUA_TTABLE);
383 luaL_checktype(L, 4, LUA_TTABLE);
384
385 /* Make sure size is ok. */
386 n = lua_objlen(L,2);
387#if DEBUGGING
388 if ((n != lua_objlen(L,3)) || (n != lua_objlen(L,4)))
389 return NLUA_ERROR(L, _("Table lengths don't match!"));
390#endif /* DEBUGGING */
391
392 /* Load everything from tables, has to be 1-index based. */
393 ia = calloc( n+1, sizeof(int) );
394 ja = calloc( n+1, sizeof(int) );
395 ar = calloc( n+1, sizeof(double) );
396 for (size_t i=1; i<=n; i++) {
397 lua_rawgeti(L, 2, i);
398 lua_rawgeti(L, 3, i);
399 lua_rawgeti(L, 4, i);
400#if DEBUGGING
401 ia[i] = luaL_checkinteger(L,-3);
402 ja[i] = luaL_checkinteger(L,-2);
403 ar[i] = luaL_checknumber(L,-1);
404#else /* DEBUGGING */
405 ia[i] = lua_tointeger(L,-3);
406 ja[i] = lua_tointeger(L,-2);
407 ar[i] = lua_tonumber(L,-1);
408#endif /* DEBUGGING */
409 lua_pop(L,3);
410 }
411
412 /* Set up the matrix. */
413 glp_load_matrix( lp->prob, n, ia, ja, ar );
414
415 /* Clean up. */
416 free(ia);
417 free(ja);
418 free(ar);
419 return 0;
420}
421
422static const char* linopt_status( int retval )
423{
424 switch (retval) {
425 case GLP_OPT:
426 return "solution is optimal";
427 case GLP_FEAS:
428 return "solution is feasible";
429 case GLP_INFEAS:
430 return "solution is infeasible";
431 case GLP_NOFEAS:
432 return "problem has no feasible solution";
433 case GLP_UNBND:
434 return "problem has unbounded solution";
435 case GLP_UNDEF:
436 return "solution is undefined";
437 default:
438 return "unknown GLPK status";
439 }
440}
441static const char* linopt_error( int retval )
442{
443 switch (retval) {
444 case 0:
445 return "No error";
446
447 /* COMMON */
448 case GLP_EFAIL:
449 return "The search was prematurely terminated due to the solver failure.";
450 case GLP_ETMLIM:
451 return "The search was prematurely terminated, because the time limit has been exceeded.";
452
453 /* SIMPLEX */
454 case GLP_EBADB:
455 return "Unable to start the search, because the initial basis specified in the problem object is invalid—the number of basic (auxiliary and structural) variables is not the same as the number of rows in the problem object.";
456 case GLP_ESING:
457 return "Unable to start the search, because the basis matrix corresponding to the initial basis is singular within the working precision.";
458 case GLP_ECOND:
459 return "Unable to start the search, because the basis matrix corresponding to the initial basis is ill-conditioned, i.e. its condition number is too large.";
460 case GLP_EBOUND:
461 return "Unable to start the search, because some double-bounded (auxiliary or structural) variables have incorrect bounds.";
462 case GLP_EOBJLL:
463 return "The search was prematurely terminated, because the objective function being maximized has reached its lower limit and continues decreasing (the dual simplex only).";
464 case GLP_EOBJUL:
465 return "The search was prematurely terminated, because the objective function being minimized has reached its upper limit and continues increasing (the dual simplex only).";
466 case GLP_EITLIM:
467 return "The search was prematurely terminated, because the simplex iteration limit has been exceeded.";
468
469 /* INTOPT */
470 case GLP_EROOT:
471 return "Unable to start the search, because optimal basis for initial LP relaxation is not provided. (This code may appear only if the presolver is disabled.)";
472 case GLP_ENOPFS:
473 return "Unable to start the search, because LP relaxation of the MIP problem instance has no primal feasible solution. (This code may appear only if the presolver is enabled.)";
474 case GLP_ENODFS:
475 return "Unable to start the search, because LP relaxation of the MIP problem instance has no dual feasible solution. In other word, this code means that if the LP relaxation has at least one primal feasible solution, its optimal solution is unbounded, so if the MIP problem has at least one integer feasible solution, its (integer) optimal solution is also unbounded. (This code may appear only if the presolver is enabled.)";
476 case GLP_EMIPGAP:
477 return "The search was prematurely terminated, because the relative mip gap tolerance has been reached.";
478 case GLP_ESTOP:
479 return "The search was prematurely terminated by application. (This code may appear only if the advanced solver interface is used.)";
480
481 default:
482 return "Unknown error.";
483 }
484}
485#if 1 /* GLPK Defaults. */
486/* SMCP */
487#define METH_DEF GLP_PRIMAL
488#define PRICING_DEF GLP_PT_PSE
489#define R_TEST_DEF GLP_RT_HAR
490#define PRESOLVE_DEF GLP_OFF
491/* IOCP */
492#define BR_TECH_DEF GLP_BR_DTH
493#define BT_TECH_DEF GLP_BT_BLB
494#define PP_TECH_DEF GLP_PP_ALL
495//#define SR_HEUR_DEF GLP_ON
496#define FP_HEUR_DEF GLP_OFF
497//#define PS_HEUR_DEF GLP_OFF
498#define GMI_CUTS_DEF GLP_OFF
499#define MIR_CUTS_DEF GLP_OFF
500#define COV_CUTS_DEF GLP_OFF
501#define CLQ_CUTS_DEF GLP_OFF
502#else
503/* Customized "optimal" defaults. */
504#define BR_TECH_DEF GLP_BR_PCH
505#define BT_TECH_DEF GLP_BT_DFS
506#define PP_TECH_DEF GLP_PP_ALL
507//#define SR_HEUR_DEF GLP_ON
508#define FP_HEUR_DEF GLP_OFF
509//#define PS_HEUR_DEF GLP_OFF
510#define GMI_CUTS_DEF GLP_ON
511#define MIR_CUTS_DEF GLP_OFF
512#define COV_CUTS_DEF GLP_ON
513#define CLQ_CUTS_DEF GLP_ON
514#endif
515#define STRCHK( val, ret ) if (strcmp(str,(val))==0) return (ret);
516static int opt_meth( const char *str, int def )
517{
518 if (str==NULL) return def;
519 STRCHK( "primal", GLP_PRIMAL );
520 STRCHK( "dual", GLP_DUAL );
521 STRCHK( "dualp", GLP_DUALP );
522 WARN("Unknown meth value '%s'", str);
523 return def;
524}
525static int opt_pricing( const char *str, int def )
526{
527 if (str==NULL) return def;
528 STRCHK( "std", GLP_PT_STD );
529 STRCHK( "pse", GLP_PT_PSE );
530 WARN("Unknown pricing value '%s'", str);
531 return def;
532}
533static int opt_r_test( const char *str, int def )
534{
535 if (str==NULL) return def;
536 STRCHK( "std", GLP_RT_STD );
537 STRCHK( "har", GLP_RT_HAR );
538 WARN("Unknown r_test value '%s'", str);
539 return def;
540}
541static int opt_br_tech( const char *str, int def )
542{
543 if (str==NULL) return def;
544 STRCHK( "ffv", GLP_BR_FFV );
545 STRCHK( "lfv", GLP_BR_LFV );
546 STRCHK( "mfv", GLP_BR_MFV );
547 STRCHK( "dth", GLP_BR_DTH );
548 STRCHK( "pch", GLP_BR_PCH );
549 WARN("Unknown br_tech value '%s'", str);
550 return def;
551}
552static int opt_bt_tech( const char *str, int def )
553{
554 if (str==NULL) return def;
555 STRCHK( "dfs", GLP_BT_DFS );
556 STRCHK( "bfs", GLP_BT_BFS );
557 STRCHK( "blb", GLP_BT_BLB );
558 STRCHK( "bph", GLP_BT_BPH );
559 WARN("Unknown bt_tech value '%s'", str);
560 return def;
561}
562static int opt_pp_tech( const char *str, int def )
563{
564 if (str==NULL) return def;
565 STRCHK( "none", GLP_PP_NONE );
566 STRCHK( "root", GLP_PP_ROOT );
567 STRCHK( "all", GLP_PP_ALL );
568 WARN("Unknown pp_tech value '%s'", str);
569 return def;
570}
571static int opt_onoff( const char *str, int def )
572{
573 if (str==NULL) return def;
574 STRCHK( "on", GLP_ON );
575 STRCHK( "off", GLP_OFF );
576 WARN("Unknown onoff value '%s'", str);
577 return def;
578}
579#undef STRCHK
580
581#define GETOPT_IOCP( name, func, def ) do {lua_getfield(L,2,#name); parm_iocp.name = func( luaL_optstring(L,-1,NULL), def ); lua_pop(L,1); } while (0)
582#define GETOPT_SMCP( name, func, def ) do {lua_getfield(L,2,#name); parm_smcp.name = func( luaL_optstring(L,-1,NULL), def ); lua_pop(L,1); } while (0)
591static int linoptL_solve( lua_State *L )
592{
593 LuaLinOpt_t *lp = luaL_checklinopt(L,1);
594 double z;
595 int ret, ismip;
596 glp_iocp parm_iocp;
597 glp_smcp parm_smcp;
598#if DEBUGGING
599 Uint64 starttime = SDL_GetTicks64();
600#endif /* DEBUGGING */
601
602 /* Parameters. */
603 ismip = (glp_get_num_int( lp->prob ) > 0);
604 glp_init_smcp(&parm_smcp);
605 parm_smcp.msg_lev = GLP_MSG_ERR;
606 parm_smcp.tm_lim = LINOPT_MAX_TM;
607 if (ismip) {
608 glp_init_iocp(&parm_iocp);
609 parm_iocp.msg_lev = GLP_MSG_ERR;
610 parm_iocp.tm_lim = LINOPT_MAX_TM;
611 }
612
613 /* Load parameters. */
614 if (!lua_isnoneornil(L,2)) {
615 GETOPT_SMCP( meth, opt_meth, METH_DEF );
616 GETOPT_SMCP( pricing, opt_pricing, PRICING_DEF );
617 GETOPT_SMCP( r_test, opt_r_test, R_TEST_DEF );
618 GETOPT_SMCP( presolve,opt_onoff, PRESOLVE_DEF );
619 if (ismip) {
620 GETOPT_IOCP( br_tech, opt_br_tech, BR_TECH_DEF );
621 GETOPT_IOCP( bt_tech, opt_bt_tech, BT_TECH_DEF );
622 GETOPT_IOCP( pp_tech, opt_pp_tech, PP_TECH_DEF );
623// GETOPT_IOCP( sr_heur, opt_onoff, SR_HEUR_DEF );
624 GETOPT_IOCP( fp_heur, opt_onoff, FP_HEUR_DEF );
625// GETOPT_IOCP( ps_heur, opt_onoff, PS_HEUR_DEF );
626 GETOPT_IOCP( gmi_cuts, opt_onoff, GMI_CUTS_DEF );
627 GETOPT_IOCP( mir_cuts, opt_onoff, MIR_CUTS_DEF );
628 GETOPT_IOCP( cov_cuts, opt_onoff, COV_CUTS_DEF );
629 GETOPT_IOCP( clq_cuts, opt_onoff, CLQ_CUTS_DEF );
630 }
631 }
632#if 0
633 else {
634 parm_smcp.meth = METH_DEF;
635 parm_smcp.pricing = PRICING_DEF;
636 parm_smcp.r_test = R_TEST_DEF;
637 parm_smcp.presolve= PRESOLVE_DEF;
638 if (ismip) {
639 parm_iocp.br_tech = BR_TECH_DEF;
640 parm_iocp.bt_tech = BT_TECH_DEF;
641 parm_iocp.pp_tech = PP_TECH_DEF;
642 parm_iocp.sr_heur = SR_HEUR_DEF;
643 parm_iocp.fp_heur = FP_HEUR_DEF;
644 parm_iocp.ps_heur = PS_HEUR_DEF;
645 parm_iocp.gmi_cuts = GMI_CUTS_DEF;
646 parm_iocp.mir_cuts = MIR_CUTS_DEF;
647 parm_iocp.cov_cuts = COV_CUTS_DEF;
648 parm_iocp.clq_cuts = CLQ_CUTS_DEF;
649 }
650 }
651#endif
652
653 /* Optimization. */
654 if (!ismip || !parm_iocp.presolve) {
655 ret = glp_simplex( lp->prob, &parm_smcp );
656 if ((ret != 0) && (ret != GLP_ETMLIM)) {
657 lua_pushnil(L);
658 lua_pushstring(L, linopt_error(ret));
659 return 2;
660 }
661 /* Check for optimality of continuous problem. */
662 ret = glp_get_status(lp->prob);
663 if ((ret != GLP_OPT) && (ret != GLP_FEAS)) {
664 lua_pushnil(L);
665 lua_pushstring(L, linopt_status(ret));
666 return 2;
667 }
668 }
669 if (ismip) {
670 ret = glp_intopt( lp->prob, &parm_iocp );
671 if ((ret != 0) && (ret != GLP_ETMLIM)) {
672 lua_pushnil(L);
673 lua_pushstring(L, linopt_error(ret));
674 return 2;
675 }
676 /* Check for optimality of discrete problem. */
677 ret = glp_mip_status(lp->prob);
678 if ((ret != GLP_OPT) && (ret != GLP_FEAS)) {
679 lua_pushnil(L);
680 lua_pushstring(L, linopt_status(ret));
681 return 2;
682 }
683 }
684 z = glp_get_obj_val( lp->prob );
685
686 /* Output function value. */
687 lua_pushnumber(L,z);
688
689 /* Go over variables and store them. */
690 lua_newtable(L); /* t */
691 for (int i=1; i<=lp->ncols; i++) {
692 if (ismip)
693 z = glp_mip_col_val( lp->prob, i );
694 else
695 z = glp_get_col_prim( lp->prob, i );
696 lua_pushnumber( L, z ); /* t, z */
697 lua_rawseti( L, -2, i ); /* t */
698 }
699
700 /* Go over constraints and store them. */
701 lua_newtable(L); /* t */
702 for (int i=1; i<=lp->nrows; i++) {
703 if (ismip)
704 z = glp_mip_row_val( lp->prob, i );
705 else
706 z = glp_get_row_prim( lp->prob, i );
707 lua_pushnumber( L, z ); /* t, z */
708 lua_rawseti( L, -2, i ); /* t */
709 }
710
711 /* Complain about time. */
712#if DEBUGGING
713 if (SDL_GetTicks64() - starttime > LINOPT_MAX_TM)
714 WARN(_("glpk: too over 1 second to optimize!"));
715#endif /* DEBUGGING */
716
717 return 3;
718}
719#undef GETOPT_IOCP
720
730static int linoptL_readProblem( lua_State *L )
731{
732 const char *fname = luaL_checkstring(L,1);
733 int glpk_format = lua_toboolean(L,2);
734 int maximize = lua_toboolean(L,3);
735 const char *dirname = PHYSFS_getRealDir( fname );
736 char *fpath;
737 int ret;
738 LuaLinOpt_t lp;
739 if (dirname == NULL)
740 return NLUA_ERROR( L, _("Failed to read LP problem \"%s\"!"), fname );
741 SDL_asprintf( &fpath, "%s/%s", dirname, fname );
742 lp.prob = glp_create_prob();
743 ret = glpk_format ? glp_read_prob( lp.prob, 0, fpath ) : glp_read_mps( lp.prob, GLP_MPS_FILE, NULL, fpath );
744 free( fpath );
745 if (ret != 0) {
746 glp_delete_prob( lp.prob );
747 return NLUA_ERROR( L, _("Failed to read LP problem \"%s\"!"), fname );
748 }
749 lp.ncols = glp_get_num_cols( lp.prob );
750 lp.nrows = glp_get_num_rows( lp.prob );
751 if (maximize)
752 glp_set_obj_dir( lp.prob, GLP_MAX );
753 lua_pushlinopt( L, lp );
754 return 1;
755}
756
765static int linoptL_writeProblem( lua_State *L )
766{
767 LuaLinOpt_t *lp = luaL_checklinopt(L,1);
768 const char *fname = luaL_checkstring(L,2);
769 int glpk_format = lua_toboolean(L,3);
770 const char *dirname = PHYSFS_getWriteDir();
771 char *fpath;
772 int ret;
773 SDL_asprintf( &fpath, "%s/%s", dirname, fname );
774 ret = glpk_format ? glp_write_prob( lp->prob, 0, fpath ) : glp_write_mps( lp->prob, GLP_MPS_FILE, NULL, fpath );
775 free( fpath );
776 lua_pushboolean( L, ret==0 );
777 return 1;
778}
Header file with generic functions and naev-specifics.
LuaLinOpt_t * luaL_checklinopt(lua_State *L, int ind)
Gets linopt at index or raises error if there is no linopt at index.
static int linoptL_loadmatrix(lua_State *L)
Loads the entire matrix for the linear program.
static const luaL_Reg linoptL_methods[]
Definition nlua_linopt.c:49
static int linoptL_setcol(lua_State *L)
Adds an optimization column.
static int linoptL_solve(lua_State *L)
Solves the linear optimization problem.
static int linoptL_gc(lua_State *L)
Frees a linopt.
LuaLinOpt_t * lua_pushlinopt(lua_State *L, LuaLinOpt_t linopt)
Pushes a linopt on the stack.
LuaLinOpt_t * lua_tolinopt(lua_State *L, int ind)
Lua bindings to interact with linopts.
Definition nlua_linopt.c:89
static int linoptL_readProblem(lua_State *L)
Reads an optimization problem from a file for debugging purposes.
static int linoptL_size(lua_State *L)
Adds columns to the linear program.
static int linoptL_addrows(lua_State *L)
Adds rows to the linear program.
static int linoptL_new(lua_State *L)
Opens a new linopt.
int lua_islinopt(lua_State *L, int ind)
Checks to see if ind is a linopt.
static int linoptL_addcols(lua_State *L)
Adds columns to the linear program.
#define LINOPT_MAX_TM
Definition nlua_linopt.c:25
static int linoptL_setrow(lua_State *L)
Adds an optimization row.
static int linoptL_eq(lua_State *L)
Compares two linopts to see if they are the same.
int nlua_loadLinOpt(nlua_env env)
Loads the linopt library.
Definition nlua_linopt.c:71
static int linoptL_writeProblem(lua_State *L)
Writes an optimization problem to a file for debugging purposes.
static const double c[]
Definition rng.c:264
Our cute little linear program wrapper.
Definition nlua_linopt.c:30
glp_prob * prob
Definition nlua_linopt.c:33