3 /***********************************************************************
4 * This code is part of GLPK (GNU Linear Programming Kit).
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
7 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
9 * E-mail: <mao@gnu.org>.
11 * GLPK is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * GLPK is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 * License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
23 ***********************************************************************/
29 #define dmp_create_poolx(size) dmp_create_pool()
31 /**********************************************************************/
32 /* * * GENERATING AND POSTSOLVING MODEL * * */
33 /**********************************************************************/
35 /*----------------------------------------------------------------------
36 -- alloc_content - allocate content arrays for all model objects.
38 -- This routine allocates content arrays for all existing model objects
39 -- and thereby finalizes creating model.
41 -- This routine must be called immediately after reading model section,
42 -- i.e. before reading data section or generating model. */
44 void alloc_content(MPL *mpl)
46 /* walk through all model statements */
47 for (stmt = mpl->model; stmt != NULL; stmt = stmt->next)
51 xassert(stmt->u.set->array == NULL);
52 stmt->u.set->array = create_array(mpl, A_ELEMSET,
57 xassert(stmt->u.par->array == NULL);
58 switch (stmt->u.par->type)
62 stmt->u.par->array = create_array(mpl, A_NUMERIC,
66 stmt->u.par->array = create_array(mpl, A_SYMBOLIC,
70 xassert(stmt != stmt);
75 xassert(stmt->u.var->array == NULL);
76 stmt->u.var->array = create_array(mpl, A_ELEMVAR,
80 /* model constraint/objective */
81 xassert(stmt->u.con->array == NULL);
82 stmt->u.con->array = create_array(mpl, A_ELEMCON,
85 #if 1 /* 11/II-2008 */
93 /* functional statements have no content array */
96 xassert(stmt != stmt);
102 /*----------------------------------------------------------------------
103 -- generate_model - generate model.
105 -- This routine executes the model statements which precede the solve
108 void generate_model(MPL *mpl)
110 xassert(!mpl->flag_p);
111 for (stmt = mpl->model; stmt != NULL; stmt = stmt->next)
112 { execute_statement(mpl, stmt);
113 if (mpl->stmt->type == A_SOLVE) break;
119 /*----------------------------------------------------------------------
120 -- build_problem - build problem instance.
122 -- This routine builds lists of rows and columns for problem instance,
123 -- which corresponds to the generated model. */
125 void build_problem(MPL *mpl)
132 xassert(mpl->m == 0);
133 xassert(mpl->n == 0);
134 xassert(mpl->row == NULL);
135 xassert(mpl->col == NULL);
136 /* check that all elemental variables has zero column numbers */
137 for (stmt = mpl->model; stmt != NULL; stmt = stmt->next)
138 { if (stmt->type == A_VARIABLE)
140 for (memb = v->array->head; memb != NULL; memb = memb->next)
141 xassert(memb->value.var->j == 0);
144 /* assign row numbers to elemental constraints and objectives */
145 for (stmt = mpl->model; stmt != NULL; stmt = stmt->next)
146 { if (stmt->type == A_CONSTRAINT)
148 for (memb = c->array->head; memb != NULL; memb = memb->next)
149 { xassert(memb->value.con->i == 0);
150 memb->value.con->i = ++mpl->m;
151 /* walk through linear form and mark elemental variables,
152 which are referenced at least once */
153 for (t = memb->value.con->form; t != NULL; t = t->next)
154 { xassert(t->var != NULL);
155 t->var->memb->value.var->j = -1;
160 /* assign column numbers to marked elemental variables */
161 for (stmt = mpl->model; stmt != NULL; stmt = stmt->next)
162 { if (stmt->type == A_VARIABLE)
164 for (memb = v->array->head; memb != NULL; memb = memb->next)
165 if (memb->value.var->j != 0) memb->value.var->j =
169 /* build list of rows */
170 mpl->row = xcalloc(1+mpl->m, sizeof(ELEMCON *));
171 for (i = 1; i <= mpl->m; i++) mpl->row[i] = NULL;
172 for (stmt = mpl->model; stmt != NULL; stmt = stmt->next)
173 { if (stmt->type == A_CONSTRAINT)
175 for (memb = c->array->head; memb != NULL; memb = memb->next)
176 { i = memb->value.con->i;
177 xassert(1 <= i && i <= mpl->m);
178 xassert(mpl->row[i] == NULL);
179 mpl->row[i] = memb->value.con;
183 for (i = 1; i <= mpl->m; i++) xassert(mpl->row[i] != NULL);
184 /* build list of columns */
185 mpl->col = xcalloc(1+mpl->n, sizeof(ELEMVAR *));
186 for (j = 1; j <= mpl->n; j++) mpl->col[j] = NULL;
187 for (stmt = mpl->model; stmt != NULL; stmt = stmt->next)
188 { if (stmt->type == A_VARIABLE)
190 for (memb = v->array->head; memb != NULL; memb = memb->next)
191 { j = memb->value.var->j;
192 if (j == 0) continue;
193 xassert(1 <= j && j <= mpl->n);
194 xassert(mpl->col[j] == NULL);
195 mpl->col[j] = memb->value.var;
199 for (j = 1; j <= mpl->n; j++) xassert(mpl->col[j] != NULL);
203 /*----------------------------------------------------------------------
204 -- postsolve_model - postsolve model.
206 -- This routine executes the model statements which follow the solve
209 void postsolve_model(MPL *mpl)
211 xassert(!mpl->flag_p);
213 for (stmt = mpl->stmt; stmt != NULL; stmt = stmt->next)
214 execute_statement(mpl, stmt);
219 /*----------------------------------------------------------------------
220 -- clean_model - clean model content.
222 -- This routine cleans the model content that assumes deleting all stuff
223 -- dynamically allocated on generating/postsolving phase.
225 -- Actually cleaning model content is not needed. This function is used
226 -- mainly to be sure that there were no logical errors on using dynamic
227 -- memory pools during the generation phase.
229 -- NOTE: This routine must not be called if any errors were detected on
230 -- the generation phase. */
232 void clean_model(MPL *mpl)
234 for (stmt = mpl->model; stmt != NULL; stmt = stmt->next)
235 clean_statement(mpl, stmt);
236 /* check that all atoms have been returned to their pools */
237 if (dmp_in_use(mpl->strings).lo != 0)
238 error(mpl, "internal logic error: %d string segment(s) were lo"
239 "st", dmp_in_use(mpl->strings).lo);
240 if (dmp_in_use(mpl->symbols).lo != 0)
241 error(mpl, "internal logic error: %d symbol(s) were lost",
242 dmp_in_use(mpl->symbols).lo);
243 if (dmp_in_use(mpl->tuples).lo != 0)
244 error(mpl, "internal logic error: %d n-tuple component(s) were"
245 " lost", dmp_in_use(mpl->tuples).lo);
246 if (dmp_in_use(mpl->arrays).lo != 0)
247 error(mpl, "internal logic error: %d array(s) were lost",
248 dmp_in_use(mpl->arrays).lo);
249 if (dmp_in_use(mpl->members).lo != 0)
250 error(mpl, "internal logic error: %d array member(s) were lost"
251 , dmp_in_use(mpl->members).lo);
252 if (dmp_in_use(mpl->elemvars).lo != 0)
253 error(mpl, "internal logic error: %d elemental variable(s) wer"
254 "e lost", dmp_in_use(mpl->elemvars).lo);
255 if (dmp_in_use(mpl->formulae).lo != 0)
256 error(mpl, "internal logic error: %d linear term(s) were lost",
257 dmp_in_use(mpl->formulae).lo);
258 if (dmp_in_use(mpl->elemcons).lo != 0)
259 error(mpl, "internal logic error: %d elemental constraint(s) w"
260 "ere lost", dmp_in_use(mpl->elemcons).lo);
264 /**********************************************************************/
265 /* * * INPUT/OUTPUT * * */
266 /**********************************************************************/
268 /*----------------------------------------------------------------------
269 -- open_input - open input text file.
271 -- This routine opens the input text file for scanning. */
273 void open_input(MPL *mpl, char *file)
278 mpl->image[0] = '\0';
280 mpl->b_token = T_EOF;
282 mpl->b_image[0] = '\0';
288 mpl->f_image[0] = '\0';
290 memset(mpl->context, ' ', CONTEXT_SIZE);
292 xassert(mpl->in_fp == NULL);
293 mpl->in_fp = xfopen(file, "r");
294 if (mpl->in_fp == NULL)
295 error(mpl, "unable to open %s - %s", file, xerrmsg());
297 /* scan the very first character */
299 /* scan the very first token */
304 /*----------------------------------------------------------------------
305 -- read_char - read next character from input text file.
307 -- This routine returns a next ASCII character read from the input text
308 -- file. If the end of file has been reached, EOF is returned. */
310 int read_char(MPL *mpl)
312 xassert(mpl->in_fp != NULL);
313 c = xfgetc(mpl->in_fp);
315 { if (xferror(mpl->in_fp))
316 error(mpl, "read error on %s - %s", mpl->in_file,
323 /*----------------------------------------------------------------------
324 -- close_input - close input text file.
326 -- This routine closes the input text file. */
328 void close_input(MPL *mpl)
329 { xassert(mpl->in_fp != NULL);
336 /*----------------------------------------------------------------------
337 -- open_output - open output text file.
339 -- This routine opens the output text file for writing data produced by
340 -- display and printf statements. */
342 void open_output(MPL *mpl, char *file)
343 { xassert(mpl->out_fp == NULL);
346 mpl->out_fp = (void *)stdout;
349 { mpl->out_fp = xfopen(file, "w");
350 if (mpl->out_fp == NULL)
351 error(mpl, "unable to create %s - %s", file, xerrmsg());
353 mpl->out_file = xmalloc(strlen(file)+1);
354 strcpy(mpl->out_file, file);
358 /*----------------------------------------------------------------------
359 -- write_char - write next character to output text file.
361 -- This routine writes an ASCII character to the output text file. */
363 void write_char(MPL *mpl, int c)
364 { xassert(mpl->out_fp != NULL);
365 if (mpl->out_fp == (void *)stdout)
368 xfprintf(mpl->out_fp, "%c", c);
372 /*----------------------------------------------------------------------
373 -- write_text - format and write text to output text file.
375 -- This routine formats a text using the format control string and then
376 -- writes this text to the output text file. */
378 void write_text(MPL *mpl, char *fmt, ...)
380 char buf[OUTBUF_SIZE], *c;
382 vsprintf(buf, fmt, arg);
383 xassert(strlen(buf) < sizeof(buf));
385 for (c = buf; *c != '\0'; c++) write_char(mpl, *c);
389 /*----------------------------------------------------------------------
390 -- flush_output - finalize writing data to output text file.
392 -- This routine finalizes writing data to the output text file. */
394 void flush_output(MPL *mpl)
395 { xassert(mpl->out_fp != NULL);
396 if (mpl->out_fp != (void *)stdout)
397 { xfflush(mpl->out_fp);
398 if (xferror(mpl->out_fp))
399 error(mpl, "write error on %s - %s", mpl->out_file,
405 /**********************************************************************/
406 /* * * SOLVER INTERFACE * * */
407 /**********************************************************************/
409 /*----------------------------------------------------------------------
410 -- error - print error message and terminate model processing.
412 -- This routine formats and prints an error message and then terminates
413 -- model processing. */
415 void error(MPL *mpl, char *fmt, ...)
419 vsprintf(msg, fmt, arg);
420 xassert(strlen(msg) < sizeof(msg));
425 /* translation phase */
426 xprintf("%s:%d: %s\n",
427 mpl->in_file == NULL ? "(unknown)" : mpl->in_file,
432 /* generation/postsolve phase */
433 xprintf("%s:%d: %s\n",
434 mpl->mod_file == NULL ? "(unknown)" : mpl->mod_file,
435 mpl->stmt == NULL ? 0 : mpl->stmt->line, msg);
441 longjmp(mpl->jump, 1);
445 /*----------------------------------------------------------------------
446 -- warning - print warning message and continue model processing.
448 -- This routine formats and prints a warning message and returns to the
449 -- calling program. */
451 void warning(MPL *mpl, char *fmt, ...)
455 vsprintf(msg, fmt, arg);
456 xassert(strlen(msg) < sizeof(msg));
461 /* translation phase */
462 xprintf("%s:%d: warning: %s\n",
463 mpl->in_file == NULL ? "(unknown)" : mpl->in_file,
467 /* generation/postsolve phase */
468 xprintf("%s:%d: warning: %s\n",
469 mpl->mod_file == NULL ? "(unknown)" : mpl->mod_file,
470 mpl->stmt == NULL ? 0 : mpl->stmt->line, msg);
478 /*----------------------------------------------------------------------
479 -- mpl_initialize - create and initialize translator database.
483 -- #include "glpmpl.h"
484 -- MPL *mpl_initialize(void);
488 -- The routine mpl_initialize creates and initializes the database used
489 -- by the GNU MathProg translator.
493 -- The routine returns a pointer to the database created. */
495 MPL *mpl_initialize(void)
497 mpl = xmalloc(sizeof(MPL));
498 /* scanning segment */
503 mpl->image = xcalloc(MAX_LENGTH+1, sizeof(char));
504 mpl->image[0] = '\0';
508 mpl->b_image = xcalloc(MAX_LENGTH+1, sizeof(char));
509 mpl->b_image[0] = '\0';
515 mpl->f_image = xcalloc(MAX_LENGTH+1, sizeof(char));
516 mpl->f_image[0] = '\0';
518 mpl->context = xcalloc(CONTEXT_SIZE, sizeof(char));
519 memset(mpl->context, ' ', CONTEXT_SIZE);
522 /* translating segment */
523 mpl->pool = dmp_create_poolx(0);
524 mpl->tree = avl_create_tree(avl_strcmp, NULL);
532 mpl->strings = dmp_create_poolx(sizeof(STRING));
533 mpl->symbols = dmp_create_poolx(sizeof(SYMBOL));
534 mpl->tuples = dmp_create_poolx(sizeof(TUPLE));
535 mpl->arrays = dmp_create_poolx(sizeof(ARRAY));
536 mpl->members = dmp_create_poolx(sizeof(MEMBER));
537 mpl->elemvars = dmp_create_poolx(sizeof(ELEMVAR));
538 mpl->formulae = dmp_create_poolx(sizeof(FORMULA));
539 mpl->elemcons = dmp_create_poolx(sizeof(ELEMCON));
541 mpl->sym_buf = xcalloc(255+1, sizeof(char));
542 mpl->sym_buf[0] = '\0';
543 mpl->tup_buf = xcalloc(255+1, sizeof(char));
544 mpl->tup_buf[0] = '\0';
545 /* generating/postsolving segment */
546 mpl->rand = rng_create_rand();
549 #if 1 /* 11/II-2008 */
556 /* input/output segment */
560 mpl->out_file = NULL;
562 mpl->prt_file = NULL;
563 /* solver interface segment */
564 if (setjmp(mpl->jump)) xassert(mpl != mpl);
566 mpl->mod_file = NULL;
567 mpl->mpl_buf = xcalloc(255+1, sizeof(char));
568 mpl->mpl_buf[0] = '\0';
572 /*----------------------------------------------------------------------
573 -- mpl_read_model - read model section and optional data section.
577 -- #include "glpmpl.h"
578 -- int mpl_read_model(MPL *mpl, char *file, int skip_data);
582 -- The routine mpl_read_model reads model section and optionally data
583 -- section, which may follow the model section, from the text file,
584 -- whose name is the character string file, performs translating model
585 -- statements and data blocks, and stores all the information in the
586 -- translator database.
588 -- The parameter skip_data is a flag. If the input file contains the
589 -- data section and this flag is set, the data section is not read as
590 -- if there were no data section and a warning message is issued. This
591 -- allows reading the data section from another input file.
593 -- This routine should be called once after the routine mpl_initialize
594 -- and before other API routines.
598 -- The routine mpl_read_model returns one the following codes:
600 -- 1 - translation successful. The input text file contains only model
601 -- section. In this case the calling program may call the routine
602 -- mpl_read_data to read data section from another file.
603 -- 2 - translation successful. The input text file contains both model
605 -- 4 - processing failed due to some errors. In this case the calling
606 -- program should call the routine mpl_terminate to terminate model
609 int mpl_read_model(MPL *mpl, char *file, int skip_data)
610 { if (mpl->phase != 0)
611 xfault("mpl_read_model: invalid call sequence\n");
613 xfault("mpl_read_model: no input filename specified\n");
614 /* set up error handler */
615 if (setjmp(mpl->jump)) goto done;
616 /* translate model section */
618 xprintf("Reading model section from %s...\n", file);
619 open_input(mpl, file);
621 if (mpl->model == NULL)
622 error(mpl, "empty model section not allowed");
623 /* save name of the input text file containing model section for
624 error diagnostics during the generation phase */
625 mpl->mod_file = xcalloc(strlen(file)+1, sizeof(char));
626 strcpy(mpl->mod_file, mpl->in_file);
627 /* allocate content arrays for all model objects */
629 /* optional data section may begin with the keyword 'data' */
630 if (is_keyword(mpl, "data"))
632 { warning(mpl, "data section ignored");
636 get_token(mpl /* data */);
637 if (mpl->token != T_SEMICOLON)
638 error(mpl, "semicolon missing where expected");
639 get_token(mpl /* ; */);
640 /* translate data section */
642 xprintf("Reading data section from %s...\n", file);
645 /* process end statement */
647 skip: xprintf("%d line%s were read\n",
648 mpl->line, mpl->line == 1 ? "" : "s");
650 done: /* return to the calling program */
654 /*----------------------------------------------------------------------
655 -- mpl_read_data - read data section.
659 -- #include "glpmpl.h"
660 -- int mpl_read_data(MPL *mpl, char *file);
664 -- The routine mpl_read_data reads data section from the text file,
665 -- whose name is the character string file, performs translating data
666 -- blocks, and stores the data read in the translator database.
668 -- If this routine is used, it should be called once after the routine
669 -- mpl_read_model and if the latter returned the code 1.
673 -- The routine mpl_read_data returns one of the following codes:
675 -- 2 - data section has been successfully processed.
676 -- 4 - processing failed due to some errors. In this case the calling
677 -- program should call the routine mpl_terminate to terminate model
680 int mpl_read_data(MPL *mpl, char *file)
681 #if 0 /* 02/X-2008 */
682 { if (mpl->phase != 1)
684 { if (!(mpl->phase == 1 || mpl->phase == 2))
686 xfault("mpl_read_data: invalid call sequence\n");
688 xfault("mpl_read_data: no input filename specified\n");
689 /* set up error handler */
690 if (setjmp(mpl->jump)) goto done;
691 /* process data section */
693 xprintf("Reading data section from %s...\n", file);
695 open_input(mpl, file);
696 /* in this case the keyword 'data' is optional */
697 if (is_literal(mpl, "data"))
698 { get_token(mpl /* data */);
699 if (mpl->token != T_SEMICOLON)
700 error(mpl, "semicolon missing where expected");
701 get_token(mpl /* ; */);
704 /* process end statement */
706 xprintf("%d line%s were read\n",
707 mpl->line, mpl->line == 1 ? "" : "s");
709 done: /* return to the calling program */
713 /*----------------------------------------------------------------------
714 -- mpl_generate - generate model.
718 -- #include "glpmpl.h"
719 -- int mpl_generate(MPL *mpl, char *file);
723 -- The routine mpl_generate generates the model using its description
724 -- stored in the translator database. This phase means generating all
725 -- variables, constraints, and objectives, executing check and display
726 -- statements, which precede the solve statement (if it is presented),
727 -- and building the problem instance.
729 -- The character string file specifies the name of output text file, to
730 -- which output produced by display statements should be written. It is
731 -- allowed to specify NULL, in which case the output goes to stdout via
732 -- the routine print.
734 -- This routine should be called once after the routine mpl_read_model
735 -- or mpl_read_data and if one of the latters returned the code 2.
739 -- The routine mpl_generate returns one of the following codes:
741 -- 3 - model has been successfully generated. In this case the calling
742 -- program may call other api routines to obtain components of the
743 -- problem instance from the translator database.
744 -- 4 - processing failed due to some errors. In this case the calling
745 -- program should call the routine mpl_terminate to terminate model
748 int mpl_generate(MPL *mpl, char *file)
749 { if (!(mpl->phase == 1 || mpl->phase == 2))
750 xfault("mpl_generate: invalid call sequence\n");
751 /* set up error handler */
752 if (setjmp(mpl->jump)) goto done;
755 open_output(mpl, file);
758 /* build problem instance */
760 /* generation phase has been finished */
761 xprintf("Model has been successfully generated\n");
762 done: /* return to the calling program */
766 /*----------------------------------------------------------------------
767 -- mpl_get_prob_name - obtain problem (model) name.
771 -- #include "glpmpl.h"
772 -- char *mpl_get_prob_name(MPL *mpl);
776 -- The routine mpl_get_prob_name returns a pointer to internal buffer,
777 -- which contains symbolic name of the problem (model).
781 -- Currently MathProg has no feature to assign a symbolic name to the
782 -- model. Therefore the routine mpl_get_prob_name tries to construct
783 -- such name using the name of input text file containing model section,
784 -- although this is not a good idea (due to portability problems). */
786 char *mpl_get_prob_name(MPL *mpl)
787 { char *name = mpl->mpl_buf;
788 char *file = mpl->mod_file;
791 xfault("mpl_get_prob_name: invalid call sequence\n");
793 { if (strchr(file, '/') != NULL)
794 file = strchr(file, '/') + 1;
795 else if (strchr(file, '\\') != NULL)
796 file = strchr(file, '\\') + 1;
797 else if (strchr(file, ':') != NULL)
798 file = strchr(file, ':') + 1;
803 { if (k == 255) break;
804 if (!(isalnum((unsigned char)*file) || *file == '_')) break;
808 strcpy(name, "Unknown");
811 xassert(strlen(name) <= 255);
815 /*----------------------------------------------------------------------
816 -- mpl_get_num_rows - determine number of rows.
820 -- #include "glpmpl.h"
821 -- int mpl_get_num_rows(MPL *mpl);
825 -- The routine mpl_get_num_rows returns total number of rows in the
826 -- problem, where each row is an individual constraint or objective. */
828 int mpl_get_num_rows(MPL *mpl)
829 { if (mpl->phase != 3)
830 xfault("mpl_get_num_rows: invalid call sequence\n");
834 /*----------------------------------------------------------------------
835 -- mpl_get_num_cols - determine number of columns.
839 -- #include "glpmpl.h"
840 -- int mpl_get_num_cols(MPL *mpl);
844 -- The routine mpl_get_num_cols returns total number of columns in the
845 -- problem, where each column is an individual variable. */
847 int mpl_get_num_cols(MPL *mpl)
848 { if (mpl->phase != 3)
849 xfault("mpl_get_num_cols: invalid call sequence\n");
853 /*----------------------------------------------------------------------
854 -- mpl_get_row_name - obtain row name.
858 -- #include "glpmpl.h"
859 -- char *mpl_get_row_name(MPL *mpl, int i);
863 -- The routine mpl_get_row_name returns a pointer to internal buffer,
864 -- which contains symbolic name of i-th row of the problem. */
866 char *mpl_get_row_name(MPL *mpl, int i)
867 { char *name = mpl->mpl_buf, *t;
870 xfault("mpl_get_row_name: invalid call sequence\n");
871 if (!(1 <= i && i <= mpl->m))
872 xfault("mpl_get_row_name: i = %d; row number out of range\n",
874 strcpy(name, mpl->row[i]->con->name);
877 t = format_tuple(mpl, '[', mpl->row[i]->memb->tuple);
879 { if (len == 255) break;
883 if (len == 255) strcpy(name+252, "...");
884 xassert(strlen(name) <= 255);
888 /*----------------------------------------------------------------------
889 -- mpl_get_row_kind - determine row kind.
893 -- #include "glpmpl.h"
894 -- int mpl_get_row_kind(MPL *mpl, int i);
898 -- The routine mpl_get_row_kind returns the kind of i-th row, which can
899 -- be one of the following:
901 -- MPL_ST - non-free (constraint) row;
902 -- MPL_MIN - free (objective) row to be minimized;
903 -- MPL_MAX - free (objective) row to be maximized. */
905 int mpl_get_row_kind(MPL *mpl, int i)
908 xfault("mpl_get_row_kind: invalid call sequence\n");
909 if (!(1 <= i && i <= mpl->m))
910 xfault("mpl_get_row_kind: i = %d; row number out of range\n",
912 switch (mpl->row[i]->con->type)
914 kind = MPL_ST; break;
916 kind = MPL_MIN; break;
918 kind = MPL_MAX; break;
925 /*----------------------------------------------------------------------
926 -- mpl_get_row_bnds - obtain row bounds.
930 -- #include "glpmpl.h"
931 -- int mpl_get_row_bnds(MPL *mpl, int i, double *lb, double *ub);
935 -- The routine mpl_get_row_bnds stores lower and upper bounds of i-th
936 -- row of the problem to the locations, which the parameters lb and ub
937 -- point to, respectively. Besides the routine returns the type of the
940 -- If some of the parameters lb and ub is NULL, the corresponding bound
941 -- value is not stored.
943 -- Types and bounds have the following meaning:
946 -- -----------------------------------------------------------
947 -- MPL_FR -inf < f(x) < +inf Free linear form
948 -- MPL_LO lb <= f(x) < +inf Inequality f(x) >= lb
949 -- MPL_UP -inf < f(x) <= ub Inequality f(x) <= ub
950 -- MPL_DB lb <= f(x) <= ub Inequality lb <= f(x) <= ub
951 -- MPL_FX f(x) = lb Equality f(x) = lb
953 -- where f(x) is the corresponding linear form of the i-th row.
955 -- If the row has no lower bound, *lb is set to zero; if the row has
956 -- no upper bound, *ub is set to zero; and if the row is of fixed type,
957 -- both *lb and *ub are set to the same value.
961 -- The routine returns the type of the i-th row as it is stated in the
964 int mpl_get_row_bnds(MPL *mpl, int i, double *_lb, double *_ub)
969 xfault("mpl_get_row_bnds: invalid call sequence\n");
970 if (!(1 <= i && i <= mpl->m))
971 xfault("mpl_get_row_bnds: i = %d; row number out of range\n",
974 #if 0 /* 21/VII-2006 */
975 if (con->con->lbnd == NULL && con->con->ubnd == NULL)
976 type = MPL_FR, lb = ub = 0.0;
977 else if (con->con->ubnd == NULL)
978 type = MPL_LO, lb = con->lbnd, ub = 0.0;
979 else if (con->con->lbnd == NULL)
980 type = MPL_UP, lb = 0.0, ub = con->ubnd;
981 else if (con->con->lbnd != con->con->ubnd)
982 type = MPL_DB, lb = con->lbnd, ub = con->ubnd;
984 type = MPL_FX, lb = ub = con->lbnd;
986 lb = (con->con->lbnd == NULL ? -DBL_MAX : con->lbnd);
987 ub = (con->con->ubnd == NULL ? +DBL_MAX : con->ubnd);
988 if (lb == -DBL_MAX && ub == +DBL_MAX)
989 type = MPL_FR, lb = ub = 0.0;
990 else if (ub == +DBL_MAX)
991 type = MPL_LO, ub = 0.0;
992 else if (lb == -DBL_MAX)
993 type = MPL_UP, lb = 0.0;
994 else if (con->con->lbnd != con->con->ubnd)
999 if (_lb != NULL) *_lb = lb;
1000 if (_ub != NULL) *_ub = ub;
1004 /*----------------------------------------------------------------------
1005 -- mpl_get_mat_row - obtain row of the constraint matrix.
1009 -- #include "glpmpl.h"
1010 -- int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[]);
1014 -- The routine mpl_get_mat_row stores column indices and numeric values
1015 -- of constraint coefficients for the i-th row to locations ndx[1], ...,
1016 -- ndx[len] and val[1], ..., val[len], respectively, where 0 <= len <= n
1017 -- is number of (structural) non-zero constraint coefficients, and n is
1018 -- number of columns in the problem.
1020 -- If the parameter ndx is NULL, column indices are not stored. If the
1021 -- parameter val is NULL, numeric values are not stored.
1023 -- Note that free rows may have constant terms, which are not part of
1024 -- the constraint matrix and therefore not reported by this routine. The
1025 -- constant term of a particular row can be obtained, if necessary, via
1026 -- the routine mpl_get_row_c0.
1030 -- The routine mpl_get_mat_row returns len, which is length of i-th row
1031 -- of the constraint matrix (i.e. number of non-zero coefficients). */
1033 int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[])
1036 if (mpl->phase != 3)
1037 xfault("mpl_get_mat_row: invalid call sequence\n");
1038 if (!(1 <= i && i <= mpl->m))
1039 xfault("mpl_get_mat_row: i = %d; row number out of range\n",
1041 for (term = mpl->row[i]->form; term != NULL; term = term->next)
1042 { xassert(term->var != NULL);
1044 xassert(len <= mpl->n);
1045 if (ndx != NULL) ndx[len] = term->var->j;
1046 if (val != NULL) val[len] = term->coef;
1051 /*----------------------------------------------------------------------
1052 -- mpl_get_row_c0 - obtain constant term of free row.
1056 -- #include "glpmpl.h"
1057 -- double mpl_get_row_c0(MPL *mpl, int i);
1061 -- The routine mpl_get_row_c0 returns numeric value of constant term of
1064 -- Note that only free rows may have non-zero constant terms. Therefore
1065 -- if i-th row is not free, the routine returns zero. */
1067 double mpl_get_row_c0(MPL *mpl, int i)
1070 if (mpl->phase != 3)
1071 xfault("mpl_get_row_c0: invalid call sequence\n");
1072 if (!(1 <= i && i <= mpl->m))
1073 xfault("mpl_get_row_c0: i = %d; row number out of range\n",
1076 if (con->con->lbnd == NULL && con->con->ubnd == NULL)
1083 /*----------------------------------------------------------------------
1084 -- mpl_get_col_name - obtain column name.
1088 -- #include "glpmpl.h"
1089 -- char *mpl_get_col_name(MPL *mpl, int j);
1093 -- The routine mpl_get_col_name returns a pointer to internal buffer,
1094 -- which contains symbolic name of j-th column of the problem. */
1096 char *mpl_get_col_name(MPL *mpl, int j)
1097 { char *name = mpl->mpl_buf, *t;
1099 if (mpl->phase != 3)
1100 xfault("mpl_get_col_name: invalid call sequence\n");
1101 if (!(1 <= j && j <= mpl->n))
1102 xfault("mpl_get_col_name: j = %d; column number out of range\n"
1104 strcpy(name, mpl->col[j]->var->name);
1106 xassert(len <= 255);
1107 t = format_tuple(mpl, '[', mpl->col[j]->memb->tuple);
1109 { if (len == 255) break;
1113 if (len == 255) strcpy(name+252, "...");
1114 xassert(strlen(name) <= 255);
1118 /*----------------------------------------------------------------------
1119 -- mpl_get_col_kind - determine column kind.
1123 -- #include "glpmpl.h"
1124 -- int mpl_get_col_kind(MPL *mpl, int j);
1128 -- The routine mpl_get_col_kind returns the kind of j-th column, which
1129 -- can be one of the following:
1131 -- MPL_NUM - continuous variable;
1132 -- MPL_INT - integer variable;
1133 -- MPL_BIN - binary variable.
1135 -- Note that column kinds are defined independently on type and bounds
1136 -- (reported by the routine mpl_get_col_bnds) of corresponding columns.
1137 -- This means, in particular, that bounds of an integer column may be
1138 -- fractional, or a binary column may have lower and upper bounds that
1139 -- are not 0 and 1 (or it may have no lower/upper bound at all). */
1141 int mpl_get_col_kind(MPL *mpl, int j)
1143 if (mpl->phase != 3)
1144 xfault("mpl_get_col_kind: invalid call sequence\n");
1145 if (!(1 <= j && j <= mpl->n))
1146 xfault("mpl_get_col_kind: j = %d; column number out of range\n"
1148 switch (mpl->col[j]->var->type)
1150 kind = MPL_NUM; break;
1152 kind = MPL_INT; break;
1154 kind = MPL_BIN; break;
1156 xassert(mpl != mpl);
1161 /*----------------------------------------------------------------------
1162 -- mpl_get_col_bnds - obtain column bounds.
1166 -- #include "glpmpl.h"
1167 -- int mpl_get_col_bnds(MPL *mpl, int j, double *lb, double *ub);
1171 -- The routine mpl_get_col_bnds stores lower and upper bound of j-th
1172 -- column of the problem to the locations, which the parameters lb and
1173 -- ub point to, respectively. Besides the routine returns the type of
1176 -- If some of the parameters lb and ub is NULL, the corresponding bound
1177 -- value is not stored.
1179 -- Types and bounds have the following meaning:
1182 -- ------------------------------------------------------
1183 -- MPL_FR -inf < x < +inf Free (unbounded) variable
1184 -- MPL_LO lb <= x < +inf Variable with lower bound
1185 -- MPL_UP -inf < x <= ub Variable with upper bound
1186 -- MPL_DB lb <= x <= ub Double-bounded variable
1187 -- MPL_FX x = lb Fixed variable
1189 -- where x is individual variable corresponding to the j-th column.
1191 -- If the column has no lower bound, *lb is set to zero; if the column
1192 -- has no upper bound, *ub is set to zero; and if the column is of fixed
1193 -- type, both *lb and *ub are set to the same value.
1197 -- The routine returns the type of the j-th column as it is stated in
1198 -- the table above. */
1200 int mpl_get_col_bnds(MPL *mpl, int j, double *_lb, double *_ub)
1204 if (mpl->phase != 3)
1205 xfault("mpl_get_col_bnds: invalid call sequence\n");
1206 if (!(1 <= j && j <= mpl->n))
1207 xfault("mpl_get_col_bnds: j = %d; column number out of range\n"
1210 #if 0 /* 21/VII-2006 */
1211 if (var->var->lbnd == NULL && var->var->ubnd == NULL)
1212 type = MPL_FR, lb = ub = 0.0;
1213 else if (var->var->ubnd == NULL)
1214 type = MPL_LO, lb = var->lbnd, ub = 0.0;
1215 else if (var->var->lbnd == NULL)
1216 type = MPL_UP, lb = 0.0, ub = var->ubnd;
1217 else if (var->var->lbnd != var->var->ubnd)
1218 type = MPL_DB, lb = var->lbnd, ub = var->ubnd;
1220 type = MPL_FX, lb = ub = var->lbnd;
1222 lb = (var->var->lbnd == NULL ? -DBL_MAX : var->lbnd);
1223 ub = (var->var->ubnd == NULL ? +DBL_MAX : var->ubnd);
1224 if (lb == -DBL_MAX && ub == +DBL_MAX)
1225 type = MPL_FR, lb = ub = 0.0;
1226 else if (ub == +DBL_MAX)
1227 type = MPL_LO, ub = 0.0;
1228 else if (lb == -DBL_MAX)
1229 type = MPL_UP, lb = 0.0;
1230 else if (var->var->lbnd != var->var->ubnd)
1235 if (_lb != NULL) *_lb = lb;
1236 if (_ub != NULL) *_ub = ub;
1240 /*----------------------------------------------------------------------
1241 -- mpl_has_solve_stmt - check if model has solve statement.
1245 -- #include "glpmpl.h"
1246 -- int mpl_has_solve_stmt(MPL *mpl);
1250 -- If the model has the solve statement, the routine returns non-zero,
1251 -- otherwise zero is returned. */
1253 int mpl_has_solve_stmt(MPL *mpl)
1254 { if (mpl->phase != 3)
1255 xfault("mpl_has_solve_stmt: invalid call sequence\n");
1259 #if 1 /* 15/V-2010 */
1260 void mpl_put_row_soln(MPL *mpl, int i, int stat, double prim,
1262 { /* store row (constraint/objective) solution components */
1263 xassert(mpl->phase == 3);
1264 xassert(1 <= i && i <= mpl->m);
1265 mpl->row[i]->stat = stat;
1266 mpl->row[i]->prim = prim;
1267 mpl->row[i]->dual = dual;
1272 #if 1 /* 15/V-2010 */
1273 void mpl_put_col_soln(MPL *mpl, int j, int stat, double prim,
1275 { /* store column (variable) solution components */
1276 xassert(mpl->phase == 3);
1277 xassert(1 <= j && j <= mpl->n);
1278 mpl->col[j]->stat = stat;
1279 mpl->col[j]->prim = prim;
1280 mpl->col[j]->dual = dual;
1285 #if 0 /* 15/V-2010 */
1286 /*----------------------------------------------------------------------
1287 -- mpl_put_col_value - store column value.
1291 -- #include "glpmpl.h"
1292 -- void mpl_put_col_value(MPL *mpl, int j, double val);
1296 -- The routine mpl_put_col_value stores numeric value of j-th column
1297 -- into the translator database. It is assumed that the column value is
1298 -- provided by the solver. */
1300 void mpl_put_col_value(MPL *mpl, int j, double val)
1301 { if (mpl->phase != 3)
1302 xfault("mpl_put_col_value: invalid call sequence\n");
1303 if (!(1 <= j && j <= mpl->n))
1305 "mpl_put_col_value: j = %d; column number out of range\n", j);
1306 mpl->col[j]->prim = val;
1311 /*----------------------------------------------------------------------
1312 -- mpl_postsolve - postsolve model.
1316 -- #include "glpmpl.h"
1317 -- int mpl_postsolve(MPL *mpl);
1321 -- The routine mpl_postsolve performs postsolving of the model using
1322 -- its description stored in the translator database. This phase means
1323 -- executing statements, which follow the solve statement.
1325 -- If this routine is used, it should be called once after the routine
1326 -- mpl_generate and if the latter returned the code 3.
1330 -- The routine mpl_postsolve returns one of the following codes:
1332 -- 3 - model has been successfully postsolved.
1333 -- 4 - processing failed due to some errors. In this case the calling
1334 -- program should call the routine mpl_terminate to terminate model
1337 int mpl_postsolve(MPL *mpl)
1338 { if (!(mpl->phase == 3 && !mpl->flag_p))
1339 xfault("mpl_postsolve: invalid call sequence\n");
1340 /* set up error handler */
1341 if (setjmp(mpl->jump)) goto done;
1342 /* perform postsolving */
1343 postsolve_model(mpl);
1345 /* postsolving phase has been finished */
1346 xprintf("Model has been successfully processed\n");
1347 done: /* return to the calling program */
1351 /*----------------------------------------------------------------------
1352 -- mpl_terminate - free all resources used by translator.
1356 -- #include "glpmpl.h"
1357 -- void mpl_terminate(MPL *mpl);
1361 -- The routine mpl_terminate frees all the resources used by the GNU
1362 -- MathProg translator. */
1364 void mpl_terminate(MPL *mpl)
1365 { if (setjmp(mpl->jump)) xassert(mpl != mpl);
1371 /* there were no errors; clean the model content */
1373 xassert(mpl->a_list == NULL);
1374 #if 1 /* 11/II-2008 */
1375 xassert(mpl->dca == NULL);
1379 /* model processing has been finished due to error; delete
1380 search trees, which may be created for some arrays */
1382 for (a = mpl->a_list; a != NULL; a = a->next)
1383 if (a->tree != NULL) avl_delete_tree(a->tree);
1385 #if 1 /* 11/II-2008 */
1390 xassert(mpl != mpl);
1392 /* delete the translator database */
1394 xfree(mpl->b_image);
1395 xfree(mpl->f_image);
1396 xfree(mpl->context);
1397 dmp_delete_pool(mpl->pool);
1398 avl_delete_tree(mpl->tree);
1399 dmp_delete_pool(mpl->strings);
1400 dmp_delete_pool(mpl->symbols);
1401 dmp_delete_pool(mpl->tuples);
1402 dmp_delete_pool(mpl->arrays);
1403 dmp_delete_pool(mpl->members);
1404 dmp_delete_pool(mpl->elemvars);
1405 dmp_delete_pool(mpl->formulae);
1406 dmp_delete_pool(mpl->elemcons);
1407 xfree(mpl->sym_buf);
1408 xfree(mpl->tup_buf);
1409 rng_delete_rand(mpl->rand);
1410 if (mpl->row != NULL) xfree(mpl->row);
1411 if (mpl->col != NULL) xfree(mpl->col);
1412 if (mpl->in_fp != NULL) xfclose(mpl->in_fp);
1413 if (mpl->out_fp != NULL && mpl->out_fp != (void *)stdout)
1414 xfclose(mpl->out_fp);
1415 if (mpl->out_file != NULL) xfree(mpl->out_file);
1416 if (mpl->prt_fp != NULL) xfclose(mpl->prt_fp);
1417 if (mpl->prt_file != NULL) xfree(mpl->prt_file);
1418 if (mpl->mod_file != NULL) xfree(mpl->mod_file);
1419 xfree(mpl->mpl_buf);