/* $Id: lpkit.c,v 1.2 1999/01/03 02:07:18 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved */ /************************************************************************/ /* */ /* (C) Copyright 1989-99 Venue. All Rights Reserved. */ /* Manufactured in the United States of America. */ /* */ /************************************************************************/ #include "version.h" #include "lpkit.h" #include "lpglob.h" #include #include #include /* Globals */ lprec *Lp = NULL; /* pointer to active problem */ int Rows; int Columns; int Sum; int Non_zeros; int Level; matrec *Mat; int *Col_no; int *Col_end; int *Row_end; REAL *Orig_rh; REAL *Rh; REAL *Rhs; short *Must_be_int; REAL *Orig_upbo; REAL *Orig_lowbo; REAL *Upbo; REAL *Lowbo; int *Bas; short *Basis; short *Lower; int Eta_alloc; int Eta_size; REAL *Eta_value; int *Eta_row_nr; int *Eta_col_end; int Num_inv; REAL *Solution; REAL *Best_solution; REAL Infinite; REAL Epsilon; REAL Epsb; REAL Epsd; REAL Epsel; REAL TREJ; REAL TINV; short Maximise; short Floor_first; REAL Extrad; int Warn_count; /* used in CHECK version of rounding macro */ #ifdef NEVER void error(char *format, ...) { va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); fputc('\n', stderr); va_end(ap); exit(FAIL); } #endif lprec *make_lp(int rows, int columns) { lprec *newlp; int i, sum; sstate *st; /* to save state in MILP runs */ sum = rows + columns; if (rows < 0 || columns < 0) error("rows < 0 or columns < 0"); CALLOC(newlp, 1, lprec); strcpy(newlp->lp_name, "unnamed"); newlp->active = FALSE; newlp->verbose = FALSE; newlp->print_duals = FALSE; newlp->print_sol = FALSE; newlp->debug = FALSE; newlp->print_at_invert = FALSE; newlp->trace = FALSE; newlp->rows = rows; newlp->columns = columns; newlp->sum = sum; newlp->rows_alloc = rows; newlp->columns_alloc = columns; newlp->sum_alloc = sum; newlp->names_used = FALSE; newlp->obj_bound = DEF_INFINITE; newlp->infinite = DEF_INFINITE; newlp->epsilon = DEF_EPSILON; newlp->epsb = DEF_EPSB; newlp->epsd = DEF_EPSD; newlp->epsel = DEF_EPSEL; newlp->non_zeros = 0; newlp->mat_alloc = 1; CALLOC(newlp->mat, newlp->mat_alloc, matrec); CALLOC(newlp->col_no, newlp->mat_alloc, int); CALLOC(newlp->col_end, columns + 1, int); CALLOC(newlp->row_end, rows + 1, int); newlp->row_end_valid = FALSE; CALLOC(newlp->orig_rh, rows + 1, REAL); CALLOC(newlp->rh, rows + 1, REAL); CALLOC(newlp->rhs, rows + 1, REAL); CALLOC(newlp->must_be_int, sum + 1, short); for (i = 0; i <= sum; i++) newlp->must_be_int[i] = FALSE; CALLOC(newlp->orig_upbo, sum + 1, REAL); for (i = 0; i <= sum; i++) newlp->orig_upbo[i] = newlp->infinite; CALLOC(newlp->upbo, sum + 1, REAL); CALLOC(newlp->orig_lowbo, sum + 1, REAL); CALLOC(newlp->lowbo, sum + 1, REAL); newlp->basis_valid = TRUE; CALLOC(newlp->bas, rows + 1, int); CALLOC(newlp->basis, sum + 1, short); CALLOC(newlp->lower, sum + 1, short); for (i = 0; i <= rows; i++) { newlp->bas[i] = i; newlp->basis[i] = TRUE; } for (i = rows + 1; i <= sum; i++) newlp->basis[i] = FALSE; for (i = 0; i <= sum; i++) newlp->lower[i] = TRUE; newlp->eta_valid = TRUE; newlp->eta_size = 0; newlp->eta_alloc = 10000; newlp->max_num_inv = DEFNUMINV; newlp->nr_lagrange = 0; CALLOC(newlp->eta_value, newlp->eta_alloc, REAL); CALLOC(newlp->eta_row_nr, newlp->eta_alloc, int); CALLOC(newlp->eta_col_end, newlp->rows_alloc + newlp->max_num_inv, int); newlp->bb_rule = FIRST_NI; newlp->break_at_int = FALSE; newlp->break_value = 0; newlp->iter = 0; newlp->total_iter = 0; CALLOC(newlp->solution, sum + 1, REAL); CALLOC(newlp->best_solution, sum + 1, REAL); CALLOC(newlp->duals, rows + 1, REAL); newlp->maximise = FALSE; newlp->floor_first = TRUE; newlp->scaling_used = FALSE; newlp->columns_scaled = FALSE; CALLOC(newlp->ch_sign, rows + 1, short); for (i = 0; i <= rows; i++) newlp->ch_sign[i] = FALSE; st = newlp->solve_states = NULL; for (i = 0; i < Sum + 2; i++) { if (st) /* There's an old state-saver to use; re-use it. */ { st->saved = 0; /* clear the in-use field */ st->notint = 0; /* And the not-integer field */ st = st->next; } else { st = (sstate *)malloc(sizeof(sstate)); if (!st) ERROR(ERR_NOMEM); /* Tell the guy there's no memory */ st->next = newlp->solve_states; st->saved = 0; st->notint = 0; /* And the not-integer field */ newlp->solve_states = st; st = (sstate *)NULL; } } newlp->valid = FALSE; return (newlp); } void delete_lp(lprec *lp) { int i; if (lp->active) Lp = NULL; if (lp->names_used) { free(lp->row_name); free(lp->col_name); } free(lp->mat); free(lp->col_no); free(lp->col_end); free(lp->row_end); free(lp->orig_rh); free(lp->rh); free(lp->rhs); free(lp->must_be_int); free(lp->orig_upbo); free(lp->orig_lowbo); free(lp->upbo); free(lp->lowbo); free(lp->bas); free(lp->basis); free(lp->lower); free(lp->eta_value); free(lp->eta_row_nr); free(lp->eta_col_end); free(lp->solution); free(lp->best_solution); free(lp->duals); free(lp->ch_sign); if (lp->scaling_used) free(lp->scale); if (lp->nr_lagrange > 0) { free(lp->lag_rhs); free(lp->lambda); free(lp->lag_con_type); for (i = 0; i < lp->nr_lagrange; i++) free(lp->lag_row[i]); free(lp->lag_row); } free(lp); lp = NULL; } lprec *copy_lp(lprec *lp) { lprec *newlp; int i, rowsplus, colsplus, sumplus; rowsplus = lp->rows_alloc + 1; colsplus = lp->columns_alloc + 1; sumplus = lp->sum_alloc + 1; MALLOCCPY(newlp, lp, 1, lprec); /* copy all non pointers */ newlp->active = FALSE; if (newlp->names_used) { MALLOCCPY(newlp->col_name, lp->col_name, colsplus, nstring); MALLOCCPY(newlp->row_name, lp->row_name, rowsplus, nstring); } MALLOCCPY(newlp->mat, lp->mat, newlp->mat_alloc, matrec); MALLOCCPY(newlp->col_end, lp->col_end, colsplus, int); MALLOCCPY(newlp->col_no, lp->col_no, newlp->mat_alloc, int); MALLOCCPY(newlp->row_end, lp->row_end, rowsplus, int); MALLOCCPY(newlp->orig_rh, lp->orig_rh, rowsplus, REAL); MALLOCCPY(newlp->rh, lp->rh, rowsplus, REAL); MALLOCCPY(newlp->rhs, lp->rhs, rowsplus, REAL); MALLOCCPY(newlp->must_be_int, lp->must_be_int, sumplus, short); MALLOCCPY(newlp->orig_upbo, lp->orig_upbo, sumplus, REAL); MALLOCCPY(newlp->orig_lowbo, lp->orig_lowbo, sumplus, REAL); MALLOCCPY(newlp->upbo, lp->upbo, sumplus, REAL); MALLOCCPY(newlp->lowbo, lp->lowbo, sumplus, REAL); MALLOCCPY(newlp->bas, lp->bas, rowsplus, int); MALLOCCPY(newlp->basis, lp->basis, sumplus, short); MALLOCCPY(newlp->lower, lp->lower, sumplus, short); MALLOCCPY(newlp->eta_value, lp->eta_value, lp->eta_alloc, REAL); MALLOCCPY(newlp->eta_row_nr, lp->eta_row_nr, lp->eta_alloc, int); MALLOCCPY(newlp->eta_col_end, lp->eta_col_end, lp->rows_alloc + lp->max_num_inv, int); MALLOCCPY(newlp->solution, lp->solution, sumplus, REAL); MALLOCCPY(newlp->best_solution, lp->best_solution, sumplus, REAL); MALLOCCPY(newlp->duals, lp->duals, rowsplus, REAL); MALLOCCPY(newlp->ch_sign, lp->ch_sign, rowsplus, short); if (newlp->scaling_used) MALLOCCPY(newlp->scale, lp->scale, sumplus, REAL); if (newlp->nr_lagrange > 0) { MALLOCCPY(newlp->lag_rhs, lp->lag_rhs, newlp->nr_lagrange, REAL); MALLOCCPY(newlp->lambda, lp->lambda, newlp->nr_lagrange, REAL); MALLOCCPY(newlp->lag_con_type, lp->lag_con_type, newlp->nr_lagrange, short); MALLOC(newlp->lag_row, newlp->nr_lagrange, REAL *); for (i = 0; i < newlp->nr_lagrange; i++) MALLOCCPY(newlp->lag_row[i], lp->lag_row[i], colsplus, REAL); } return (newlp); } void inc_mat_space(lprec *lp, int maxextra) { if (lp->non_zeros + maxextra >= lp->mat_alloc) { lp->mat_alloc = lp->non_zeros + maxextra; REALLOC(lp->mat, lp->mat_alloc, matrec); REALLOC(lp->col_no, lp->mat_alloc, int); if (lp->active) { Mat = lp->mat; Col_no = lp->col_no; } } } void inc_row_space(lprec *lp) { if (lp->rows > lp->rows_alloc) { lp->rows_alloc = lp->rows + 10; lp->sum_alloc = lp->rows_alloc + lp->columns_alloc; REALLOC(lp->orig_rh, lp->rows_alloc + 1, REAL); REALLOC(lp->rh, lp->rows_alloc + 1, REAL); REALLOC(lp->rhs, lp->rows_alloc + 1, REAL); REALLOC(lp->orig_upbo, lp->sum_alloc + 1, REAL); REALLOC(lp->upbo, lp->sum_alloc + 1, REAL); REALLOC(lp->orig_lowbo, lp->sum_alloc + 1, REAL); REALLOC(lp->lowbo, lp->sum_alloc + 1, REAL); REALLOC(lp->solution, lp->sum_alloc + 1, REAL); REALLOC(lp->best_solution, lp->sum_alloc + 1, REAL); REALLOC(lp->row_end, lp->rows_alloc + 1, int); REALLOC(lp->basis, lp->sum_alloc + 1, short); REALLOC(lp->lower, lp->sum_alloc + 1, short); REALLOC(lp->must_be_int, lp->sum_alloc + 1, short); REALLOC(lp->bas, lp->rows_alloc + 1, int); REALLOC(lp->duals, lp->rows_alloc + 1, REAL); REALLOC(lp->ch_sign, lp->rows_alloc + 1, short); REALLOC(lp->eta_col_end, lp->rows_alloc + lp->max_num_inv, int); if (lp->names_used) REALLOC(lp->row_name, lp->rows_alloc + 1, nstring); if (lp->scaling_used) REALLOC(lp->scale, lp->sum_alloc + 1, REAL); if (lp->active) set_globals(lp); } } void inc_col_space(lprec *lp) { if (lp->columns >= lp->columns_alloc) { lp->columns_alloc = lp->columns + 10; lp->sum_alloc = lp->rows_alloc + lp->columns_alloc; REALLOC(lp->must_be_int, lp->sum_alloc + 1, short); REALLOC(lp->orig_upbo, lp->sum_alloc + 1, REAL); REALLOC(lp->upbo, lp->sum_alloc + 1, REAL); REALLOC(lp->orig_lowbo, lp->sum_alloc + 1, REAL); REALLOC(lp->lowbo, lp->sum_alloc + 1, REAL); REALLOC(lp->solution, lp->sum_alloc + 1, REAL); REALLOC(lp->best_solution, lp->sum_alloc + 1, REAL); REALLOC(lp->basis, lp->sum_alloc + 1, short); REALLOC(lp->lower, lp->sum_alloc + 1, short); if (lp->names_used) REALLOC(lp->col_name, lp->columns_alloc + 1, nstring); if (lp->scaling_used) REALLOC(lp->scale, lp->sum_alloc + 1, REAL); REALLOC(lp->col_end, lp->columns_alloc + 1, int); if (lp->active) set_globals(lp); } } void set_mat(lprec *lp, int Row, int Column, REAL Value) { int elmnr, lastelm, i; if (Row > lp->rows || Row < 0) error("Row out of range"); if (Column > lp->columns || Column < 1) error("Column out of range"); if (lp->scaling_used) Value *= lp->scale[Row] * lp->scale[lp->rows + Column]; if (TRUE /*abs(Value) > lp->epsilon*/) { if (lp->basis[Column] == TRUE && Row > 0) lp->basis_valid = FALSE; lp->eta_valid = FALSE; elmnr = lp->col_end[Column - 1]; while ((elmnr < lp->col_end[Column]) ? (lp->mat[elmnr].row_nr != Row) : FALSE) elmnr++; if ((elmnr != lp->col_end[Column]) ? (lp->mat[elmnr].row_nr == Row) : FALSE) if (lp->scaling_used) { if (lp->ch_sign[Row]) lp->mat[elmnr].value = -Value * lp->scale[Row] * lp->scale[Column]; else lp->mat[elmnr].value = Value * lp->scale[Row] * lp->scale[Column]; } else { if (lp->ch_sign[Row]) lp->mat[elmnr].value = -Value; else lp->mat[elmnr].value = Value; } else { /* check if more space is needed for matrix */ inc_mat_space(lp, 1); /* Shift the matrix */ lastelm = lp->non_zeros; for (i = lastelm; i > elmnr; i--) lp->mat[i] = lp->mat[i - 1]; for (i = Column; i <= lp->columns; i++) lp->col_end[i]++; /* Set new element */ lp->mat[elmnr].row_nr = Row; if (lp->scaling_used) { if (lp->ch_sign[Row]) lp->mat[elmnr].value = -Value * lp->scale[Row] * lp->scale[Column]; else lp->mat[elmnr].value = Value * lp->scale[Row] * lp->scale[Column]; } else { if (lp->ch_sign[Row]) lp->mat[elmnr].value = -Value; else lp->mat[elmnr].value = Value; } lp->row_end_valid = FALSE; lp->non_zeros++; if (lp->active) Non_zeros = lp->non_zeros; } } } void set_obj_fn(lprec *lp, REAL *row) { int i; for (i = 1; i <= lp->columns; i++) set_mat(lp, 0, i, row[i]); } void str_set_obj_fn(lprec *lp, char *row) { int i; REAL *arow; char *p, *newp; CALLOC(arow, lp->columns + 1, REAL); p = row; for (i = 1; i <= lp->columns; i++) { arow[i] = (REAL)strtod(p, &newp); if (p == newp) error("Bad string in str_set_obj_fn"); else p = newp; } set_obj_fn(lp, arow); free(arow); } void add_constraint(lprec *lp, REAL *row, short constr_type, REAL rh) { matrec *newmat; int i, j; int elmnr; int stcol; int *addtoo; int *num, *rownum, row_nr; REAL theta; MALLOC(addtoo, lp->columns + 1, int) for (i = 1; i <= lp->columns; i++) if (row[i] != 0) { addtoo[i] = TRUE; lp->non_zeros++; } else addtoo[i] = FALSE; MALLOC(newmat, lp->non_zeros, matrec); inc_mat_space(lp, 0); lp->rows++; lp->sum++; inc_row_space(lp); if (lp->scaling_used) { /* shift scale */ for (i = lp->sum; i > lp->rows; i--) lp->scale[i] = lp->scale[i - 1]; lp->scale[lp->rows] = 1; } if (lp->names_used) sprintf(lp->row_name[lp->rows], "r_%d", lp->rows); if (lp->scaling_used && lp->columns_scaled) for (i = 1; i <= lp->columns; i++) row[i] *= lp->scale[lp->rows + i]; if (constr_type == GE) lp->ch_sign[lp->rows] = TRUE; else lp->ch_sign[lp->rows] = FALSE; elmnr = 0; stcol = 0; for (i = 1; i <= lp->columns; i++) { for (j = stcol; j < lp->col_end[i]; j++) { newmat[elmnr].row_nr = lp->mat[j].row_nr; newmat[elmnr].value = lp->mat[j].value; elmnr++; } if (addtoo[i]) { if (lp->ch_sign[lp->rows]) newmat[elmnr].value = -row[i]; else newmat[elmnr].value = row[i]; newmat[elmnr].row_nr = lp->rows; elmnr++; } stcol = lp->col_end[i]; lp->col_end[i] = elmnr; } memcpy(lp->mat, newmat, lp->non_zeros * sizeof(matrec)); free(newmat); free(addtoo); for (i = lp->sum; i > lp->rows; i--) { lp->orig_upbo[i] = lp->orig_upbo[i - 1]; lp->orig_lowbo[i] = lp->orig_lowbo[i - 1]; lp->basis[i] = lp->basis[i - 1]; lp->lower[i] = lp->lower[i - 1]; lp->must_be_int[i] = lp->must_be_int[i - 1]; } for (i = 1; i <= lp->rows; i++) if (lp->bas[i] >= lp->rows) lp->bas[i]++; if (constr_type == LE || constr_type == GE) { lp->orig_upbo[lp->rows] = lp->infinite; } else if (constr_type == EQ) { lp->orig_upbo[lp->rows] = 0; } else { fprintf(stderr, "Wrong constraint type\n"); exit(FAIL); } lp->orig_lowbo[lp->rows] = 0; if (constr_type == GE && rh != 0) lp->orig_rh[lp->rows] = -rh; else lp->orig_rh[lp->rows] = rh; lp->row_end_valid = FALSE; lp->bas[lp->rows] = lp->rows; lp->basis[lp->rows] = TRUE; lp->lower[lp->rows] = TRUE; if (lp->active) set_globals(lp); lp->eta_valid = FALSE; } void str_add_constraint(lprec *lp, char *row_string, short constr_type, REAL rh) { int i; REAL *aRow; char *p, *newp; CALLOC(aRow, lp->columns + 1, REAL); p = row_string; for (i = 1; i <= lp->columns; i++) { aRow[i] = (REAL)strtod(p, &newp); if (p == newp) error("Bad string in str_add_constr"); else p = newp; } add_constraint(lp, aRow, constr_type, rh); free(aRow); } void del_constraint(lprec *lp, int del_row) { int i, j; unsigned elmnr; int startcol; int row_nr; if (del_row < 1 || del_row > lp->rows) { fprintf(stderr, "There is no constraint nr. %d\n", del_row); exit(FAIL); } elmnr = 0; startcol = 0; for (i = 1; i <= lp->columns; i++) { for (j = startcol; j < lp->col_end[i]; j++) { if (lp->mat[j].row_nr != del_row) { lp->mat[elmnr] = lp->mat[j]; if (lp->mat[elmnr].row_nr > del_row) lp->mat[elmnr].row_nr--; elmnr++; } else lp->non_zeros--; } startcol = lp->col_end[i]; lp->col_end[i] = elmnr; } for (i = del_row; i < lp->rows; i++) { lp->orig_rh[i] = lp->orig_rh[i + 1]; lp->ch_sign[i] = lp->ch_sign[i + 1]; lp->bas[i] = lp->bas[i + 1]; if (lp->names_used) strcpy(lp->row_name[i], lp->row_name[i + 1]); } for (i = 1; i < lp->rows; i++) if (lp->bas[i] > del_row) lp->bas[i]--; for (i = del_row; i < lp->sum; i++) { lp->lower[i] = lp->lower[i + 1]; lp->basis[i] = lp->basis[i + 1]; lp->orig_upbo[i] = lp->orig_upbo[i + 1]; lp->orig_lowbo[i] = lp->orig_lowbo[i + 1]; lp->must_be_int[i] = lp->must_be_int[i + 1]; if (lp->scaling_used) lp->scale[i] = lp->scale[i + 1]; } lp->rows--; lp->sum--; lp->row_end_valid = FALSE; if (lp->active) set_globals(lp); lp->eta_valid = FALSE; lp->basis_valid = FALSE; } void add_lag_con(lprec *lp, REAL *row, short con_type, REAL rhs) { int i; REAL sign; if (con_type == LE || con_type == EQ) sign = 1; else if (con_type == GE) sign = -1; else error("con_type not implemented\n"); lp->nr_lagrange++; if (lp->nr_lagrange == 1) { CALLOC(lp->lag_row, lp->nr_lagrange, REAL *); CALLOC(lp->lag_rhs, lp->nr_lagrange, REAL); CALLOC(lp->lambda, lp->nr_lagrange, REAL); CALLOC(lp->lag_con_type, lp->nr_lagrange, short); } else { REALLOC(lp->lag_row, lp->nr_lagrange, REAL *); REALLOC(lp->lag_rhs, lp->nr_lagrange, REAL); REALLOC(lp->lambda, lp->nr_lagrange, REAL); REALLOC(lp->lag_con_type, lp->nr_lagrange, short); } CALLOC(lp->lag_row[lp->nr_lagrange - 1], lp->columns + 1, REAL); lp->lag_rhs[lp->nr_lagrange - 1] = rhs * sign; for (i = 1; i <= lp->columns; i++) lp->lag_row[lp->nr_lagrange - 1][i] = row[i] * sign; lp->lambda[lp->nr_lagrange - 1] = 0; lp->lag_con_type[lp->nr_lagrange - 1] = (con_type == EQ); } void str_add_lag_con(lprec *lp, char *row, short con_type, REAL rhs) { int i; REAL *a_row; char *p, *new_p; CALLOC(a_row, lp->columns + 1, REAL); p = row; for (i = 1; i <= lp->columns; i++) { a_row[i] = (REAL)strtod(p, &new_p); if (p == new_p) error("Bad string in str_add_lag_con"); else p = new_p; } add_lag_con(lp, a_row, con_type, rhs); free(a_row); } void add_column(lprec *lp, REAL *column) { int i, j, elmnr, row_nr, *num, *rownum; lp->columns++; lp->sum++; inc_col_space(lp); inc_mat_space(lp, lp->rows + 1); if (lp->scaling_used) { for (i = 0; i <= lp->rows; i++) column[i] *= lp->scale[i]; lp->scale[lp->sum] = 1; } elmnr = lp->col_end[lp->columns - 1]; for (i = 0; i <= lp->rows; i++) if (column[i] != 0) { lp->mat[elmnr].row_nr = i; if (lp->ch_sign[i]) lp->mat[elmnr].value = -column[i]; else lp->mat[elmnr].value = column[i]; lp->non_zeros++; elmnr++; } lp->col_end[lp->columns] = elmnr; lp->orig_lowbo[lp->sum] = 0; lp->orig_upbo[lp->sum] = lp->infinite; lp->lower[lp->sum] = TRUE; lp->basis[lp->sum] = FALSE; lp->must_be_int[lp->sum] = FALSE; if (lp->names_used) sprintf(lp->col_name[lp->columns], "var_%d", lp->columns); lp->row_end_valid = FALSE; if (lp->active) { Sum = lp->sum; Columns = lp->columns; Non_zeros = lp->non_zeros; } } void str_add_column(lprec *lp, char *col_string) { int i; REAL *aCol; char *p, *newp; CALLOC(aCol, lp->rows + 1, REAL); p = col_string; for (i = 0; i <= lp->rows; i++) { aCol[i] = (REAL)strtod(p, &newp); if (p == newp) error("Bad string in str_add_column"); else p = newp; } add_column(lp, aCol); free(aCol); } void del_column(lprec *lp, int column) { int i, j, from_elm, to_elm, elm_in_col; if (column > lp->columns || column < 1) error("Column out of range in del_column"); for (i = 1; i <= lp->rows; i++) { if (lp->bas[i] == lp->rows + column) lp->basis_valid = FALSE; else if (lp->bas[i] > lp->rows + column) lp->bas[i]--; } for (i = lp->rows + column; i < lp->sum; i++) { if (lp->names_used) strcpy(lp->col_name[i - lp->rows], lp->col_name[i - lp->rows + 1]); lp->must_be_int[i] = lp->must_be_int[i + 1]; lp->orig_upbo[i] = lp->orig_upbo[i + 1]; lp->orig_lowbo[i] = lp->orig_lowbo[i + 1]; lp->upbo[i] = lp->upbo[i + 1]; lp->lowbo[i] = lp->lowbo[i + 1]; lp->basis[i] = lp->basis[i + 1]; lp->lower[i] = lp->lower[i + 1]; if (lp->scaling_used) lp->scale[i] = lp->scale[i + 1]; } for (i = 0; i < lp->nr_lagrange; i++) for (j = column; j <= lp->columns; j++) lp->lag_row[i][j] = lp->lag_row[i][j + 1]; to_elm = lp->col_end[column - 1]; from_elm = lp->col_end[column]; elm_in_col = from_elm - to_elm; for (i = from_elm; i < lp->non_zeros; i++) { lp->mat[to_elm] = lp->mat[i]; to_elm++; } for (i = column; i < lp->columns; i++) lp->col_end[i] = lp->col_end[i + 1] - elm_in_col; lp->non_zeros -= elm_in_col; lp->row_end_valid = FALSE; lp->eta_valid = FALSE; lp->sum--; lp->columns--; if (lp->active) set_globals(lp); } void set_upbo(lprec *lp, int column, REAL value) { if (column > lp->columns || column < 1) error("Column out of range"); if (lp->scaling_used) value /= lp->scale[lp->rows + column]; if (value < lp->orig_lowbo[lp->rows + column]) error("Upperbound must be >= lowerbound"); lp->eta_valid = FALSE; lp->orig_upbo[lp->rows + column] = value; } void set_lowbo(lprec *lp, int column, REAL value) { if (column > lp->columns || column < 1) error("Column out of range"); if (lp->scaling_used) value /= lp->scale[lp->rows + column]; if (value > lp->orig_upbo[lp->rows + column]) error("Upperbound must be >= lowerbound"); lp->eta_valid = FALSE; lp->orig_lowbo[lp->rows + column] = value; } void set_int(lprec *lp, int column, short must_be_int) { if (column > lp->columns || column < 1) error("Column out of range"); lp->must_be_int[lp->rows + column] = must_be_int; if (must_be_int == TRUE) if (lp->columns_scaled) unscale_columns(lp); } void set_rh(lprec *lp, int row, REAL value) { if (row > lp->rows || row < 0) error("Row out of Range"); if (row == 0) /* setting of RHS of OF not meaningful */ { fprintf(stderr, "Warning: attempt to set RHS of objective function, ignored\n"); return; } if (lp->scaling_used) if (lp->ch_sign[row]) lp->orig_rh[row] = -value * lp->scale[row]; else lp->orig_rh[row] = value * lp->scale[row]; else if (lp->ch_sign[row]) lp->orig_rh[row] = -value; else lp->orig_rh[row] = value; lp->eta_valid = FALSE; } void set_rh_vec(lprec *lp, REAL *rh) { int i; if (lp->scaling_used) for (i = 1; i <= lp->rows; i++) if (lp->ch_sign[i]) lp->orig_rh[i] = -rh[i] * lp->scale[i]; else lp->orig_rh[i] = rh[i] * lp->scale[i]; else for (i = 1; i <= lp->rows; i++) if (lp->ch_sign[i]) lp->orig_rh[i] = -rh[i]; else lp->orig_rh[i] = rh[i]; lp->eta_valid = FALSE; } void str_set_rh_vec(lprec *lp, char *rh_string) { int i; REAL *newrh; char *p, *newp; CALLOC(newrh, lp->rows + 1, REAL); p = rh_string; for (i = 1; i <= lp->rows; i++) { newrh[i] = (REAL)strtod(p, &newp); if (p == newp) error("Bad string in str_set_rh_vec"); else p = newp; } set_rh_vec(lp, newrh); free(newrh); } void set_maxim(lprec *lp) { int i; if (lp->maximise == FALSE) { for (i = 0; i < lp->non_zeros; i++) if (lp->mat[i].row_nr == 0) lp->mat[i].value *= -1; lp->eta_valid = FALSE; } lp->maximise = TRUE; lp->ch_sign[0] = TRUE; if (lp->active) Maximise = TRUE; } void set_minim(lprec *lp) { int i; if (lp->maximise == TRUE) { for (i = 0; i < lp->non_zeros; i++) if (lp->mat[i].row_nr == 0) lp->mat[i].value = -lp->mat[i].value; lp->eta_valid = FALSE; } lp->maximise = FALSE; lp->ch_sign[0] = FALSE; if (lp->active) Maximise = FALSE; } void set_constr_type(lprec *lp, int row, short con_type) { int i; if (row > lp->rows || row < 1) error("Row out of Range"); if (con_type == EQ) { lp->orig_upbo[row] = 0; lp->basis_valid = FALSE; if (lp->ch_sign[row]) { for (i = 0; i < lp->non_zeros; i++) if (lp->mat[i].row_nr == row) lp->mat[i].value *= -1; lp->eta_valid = FALSE; lp->ch_sign[row] = FALSE; if (lp->orig_rh[row] != 0) lp->orig_rh[row] *= -1; } } else if (con_type == LE) { lp->orig_upbo[row] = lp->infinite; lp->basis_valid = FALSE; if (lp->ch_sign[row]) { for (i = 0; i < lp->non_zeros; i++) if (lp->mat[i].row_nr == row) lp->mat[i].value *= -1; lp->eta_valid = FALSE; lp->ch_sign[row] = FALSE; if (lp->orig_rh[row] != 0) lp->orig_rh[row] *= -1; } } else if (con_type == GE) { lp->orig_upbo[row] = lp->infinite; lp->basis_valid = FALSE; if (!lp->ch_sign[row]) { for (i = 0; i < lp->non_zeros; i++) if (lp->mat[i].row_nr == row) lp->mat[i].value *= -1; lp->eta_valid = FALSE; lp->ch_sign[row] = TRUE; if (lp->orig_rh[row] != 0) lp->orig_rh[row] *= -1; } } else error("Constraint type not (yet) implemented"); } REAL mat_elm(lprec *lp, int row, int column) { REAL value; int elmnr; if (row < 0 || row > lp->rows) error("Row out of range in mat_elm"); if (column < 1 || column > lp->columns) error("Column out of range in mat_elm"); value = 0; elmnr = lp->col_end[column - 1]; while (lp->mat[elmnr].row_nr != row && elmnr < lp->col_end[column]) elmnr++; if (elmnr != lp->col_end[column]) { value = lp->mat[elmnr].value; if (lp->ch_sign[row]) value = -value; if (lp->scaling_used) value /= lp->scale[row] * lp->scale[lp->rows + column]; } return (value); } void get_row(lprec *lp, int row_nr, REAL *row) { int i, j; REAL RowMult; if (row_nr < 0 || row_nr > lp->rows) error("Row nr. out of range in get_row"); for (i = 1; i <= lp->columns; i++) { row[i] = 0; for (j = lp->col_end[i - 1]; j < lp->col_end[i]; j++) if (lp->mat[j].row_nr == row_nr) row[i] = lp->mat[j].value; if (lp->scaling_used) row[i] /= lp->scale[lp->rows + i] * lp->scale[row_nr]; } if (lp->ch_sign[row_nr]) for (i = 0; i <= lp->columns; i++) if (row[i] != 0) row[i] = -row[i]; } void get_column(lprec *lp, int col_nr, REAL *column) { int i; if (col_nr < 1 || col_nr > lp->columns) error("Col. nr. out of range in get_column"); for (i = 0; i <= lp->rows; i++) column[i] = 0; for (i = lp->col_end[col_nr - 1]; i < lp->col_end[col_nr]; i++) column[lp->mat[i].row_nr] = lp->mat[i].value; for (i = 0; i <= lp->rows; i++) if (column[i] != 0) { if (lp->ch_sign[i]) column[i] *= -1; if (lp->scaling_used) column[i] /= (lp->scale[i] * lp->scale[lp->rows + col_nr]); } } void get_reduced_costs(lprec *lp, REAL *rc) { int varnr, i, j; REAL f; if (!lp->basis_valid) error("Not a valid basis in get_reduced_costs"); set_globals(lp); if (!lp->eta_valid) invert(); for (i = 1; i <= lp->sum; i++) rc[i] = 0; rc[0] = 1; btran(rc); for (i = 1; i <= lp->columns; i++) { varnr = lp->rows + i; if (!Basis[varnr]) if (Upbo[varnr] > 0) { f = 0; for (j = Col_end[i - 1]; j < Col_end[i]; j++) f += rc[Mat[j].row_nr] * Mat[j].value; rc[varnr] = f; } } for (i = 1; i <= Sum; i++) my_round(rc[i], Epsd); } short is_feasible(lprec *lp, REAL *values) { int i, elmnr; REAL *this_rhs; REAL dist; if (lp->scaling_used) { for (i = lp->rows + 1; i <= lp->sum; i++) if (values[i - lp->rows] < lp->orig_lowbo[i] * lp->scale[i] || values[i - lp->rows] > lp->orig_upbo[i] * lp->scale[i]) return (FALSE); } else { for (i = lp->rows + 1; i <= lp->sum; i++) if (values[i - lp->rows] < lp->orig_lowbo[i] || values[i - lp->rows] > lp->orig_upbo[i]) return (FALSE); } CALLOC(this_rhs, lp->rows + 1, REAL) for (i = 1; i <= lp->columns; i++) for (elmnr = lp->col_end[i - 1]; elmnr < lp->col_end[i]; elmnr++) this_rhs[lp->mat[elmnr].row_nr] += lp->mat[elmnr].value * values[i]; for (i = 1; i <= lp->rows; i++) { dist = lp->orig_rh[i] - this_rhs[i]; my_round(dist, 0.001) if ((lp->orig_upbo[i] == 0 && dist != 0) || dist < 0) { free(this_rhs); return (FALSE); } } free(this_rhs); return (TRUE); } short column_in_lp(lprec *lp, REAL *testcolumn) { int i, j; short ident; REAL value; if (lp->scaling_used) for (i = 1; i <= lp->columns; i++) { ident = TRUE; j = lp->col_end[i - 1]; while (ident && (j < lp->col_end[i])) { value = lp->mat[j].value; if (lp->ch_sign[lp->mat[j].row_nr]) value = -value; value /= lp->scale[lp->rows + i]; value /= lp->scale[lp->mat[j].row_nr]; value -= testcolumn[lp->mat[j].row_nr]; if (my_abs(value) > 0.001) /* should be some epsilon? MB */ ident = FALSE; j++; } if (ident) return (TRUE); } else for (i = 1; i <= lp->columns; i++) { ident = TRUE; j = lp->col_end[i - 1]; while (ident && j < lp->col_end[i]) { value = lp->mat[j].value; if (lp->ch_sign[lp->mat[j].row_nr]) value *= -1; value -= testcolumn[lp->mat[j].row_nr]; if (my_abs(value) > 0.001) ident = FALSE; j++; } if (ident) return (TRUE); } return (FALSE); } void print_lp(lprec *lp) { int i, j; REAL *fatmat; CALLOC(fatmat, (lp->rows + 1) * lp->columns, REAL); for (i = 1; i <= lp->columns; i++) for (j = lp->col_end[i - 1]; j < lp->col_end[i]; j++) fatmat[(i - 1) * (lp->rows + 1) + lp->mat[j].row_nr] = lp->mat[j].value; printf("problem name: %s\n", lp->lp_name); printf(" "); for (j = 1; j <= lp->columns; j++) if (lp->names_used) printf("%8s ", lp->col_name[j]); else printf("Var[%3d] ", j); if (lp->maximise) { printf("\nMaximise "); for (j = 0; j < lp->columns; j++) printf("% 8.2f ", -fatmat[j * (lp->rows + 1)]); } else { printf("\nMinimize "); for (j = 0; j < lp->columns; j++) printf("% 8.2f ", fatmat[j * (lp->rows + 1)]); } printf("\n"); for (i = 1; i <= lp->rows; i++) { if (lp->names_used) printf("%9s ", lp->row_name[i]); else printf("Row[%3d] ", i); for (j = 0; j < lp->columns; j++) if (lp->ch_sign[i] && fatmat[j * (lp->rows + 1) + i] != 0) printf("% 8.2f ", -fatmat[j * (lp->rows + 1) + i]); else printf("% 8.2f ", fatmat[j * (lp->rows + 1) + i]); if (lp->orig_upbo[i] == lp->infinite) if (lp->ch_sign[i]) printf(">= "); else printf("<= "); else printf(" = "); if (lp->ch_sign[i]) printf("% 8.2f\n", -lp->orig_rh[i]); else printf("% 8.2f\n", lp->orig_rh[i]); } printf("Type "); for (i = 1; i <= lp->columns; i++) if (lp->must_be_int[lp->rows + i] == TRUE) printf(" Int "); else printf(" Real "); printf("\nupbo "); for (i = 1; i <= lp->columns; i++) if (lp->orig_upbo[lp->rows + i] == lp->infinite) printf(" Inf "); else printf("% 8.2f ", lp->orig_upbo[lp->rows + i]); printf("\nlowbo "); for (i = 1; i <= lp->columns; i++) printf("% 8.2f ", lp->orig_lowbo[lp->rows + i]); printf("\n"); for (i = 0; i < lp->nr_lagrange; i++) { printf("lag[%3d] ", i); for (j = 1; j <= lp->columns; j++) printf("% 8.2f ", lp->lag_row[i][j]); if (lp->orig_upbo[i] == lp->infinite) if (lp->lag_con_type[i] == GE) printf(">= "); else if (lp->lag_con_type[i] == LE) printf("<= "); else if (lp->lag_con_type[i] == EQ) printf(" = "); printf("% 8.2f\n", lp->lag_rhs[i]); } free(fatmat); } void set_row_name(lprec *lp, int row, nstring new_name) { int i; if (!lp->names_used) { CALLOC(lp->row_name, lp->rows_alloc + 1, nstring); CALLOC(lp->col_name, lp->columns_alloc + 1, nstring); lp->names_used = TRUE; for (i = 0; i <= lp->rows; i++) sprintf(lp->row_name[i], "r_%d", i); for (i = 1; i <= lp->columns; i++) sprintf(lp->col_name[i], "var_%d", i); } strcpy(lp->row_name[row], new_name); } void set_col_name(lprec *lp, int column, nstring new_name) { int i; if (!lp->names_used) { CALLOC(lp->row_name, lp->rows_alloc + 1, nstring); CALLOC(lp->col_name, lp->columns_alloc + 1, nstring); lp->names_used = TRUE; for (i = 0; i <= lp->rows; i++) sprintf(lp->row_name[i], "r_%d", i); for (i = 1; i <= lp->columns; i++) sprintf(lp->col_name[i], "var_%d", i); } strcpy(lp->col_name[column], new_name); } static REAL minmax_to_scale(REAL min, REAL max) { REAL scale; /* should do something sensible when min or max is 0, MB */ if ((min == 0) || (max == 0)) return ((REAL)1); scale = 1 / pow(10, (log10(min) + log10(max)) / 2); return (scale); } void unscale_columns(lprec *lp) { int i, j; /* unscale mat */ for (j = 1; j <= lp->columns; j++) for (i = lp->col_end[j - 1]; i < lp->col_end[j]; i++) lp->mat[i].value /= lp->scale[lp->rows + j]; /* unscale bounds as well */ for (i = lp->rows + 1; i < lp->sum; i++) { if (lp->orig_lowbo[i] != 0) lp->orig_lowbo[i] *= lp->scale[i]; if (lp->orig_upbo[i] != lp->infinite) lp->orig_upbo[i] *= lp->scale[i]; } for (i = lp->rows + 1; i <= lp->sum; i++) lp->scale[i] = 1; lp->columns_scaled = FALSE; lp->eta_valid = FALSE; } void unscale(lprec *lp) { int i, j; if (lp->scaling_used) { /* unscale mat */ for (j = 1; j <= lp->columns; j++) for (i = lp->col_end[j - 1]; i < lp->col_end[j]; i++) lp->mat[i].value /= lp->scale[lp->rows + j]; /* unscale bounds */ for (i = lp->rows + 1; i < lp->sum; i++) { if (lp->orig_lowbo[i] != 0) lp->orig_lowbo[i] *= lp->scale[i]; if (lp->orig_upbo[i] != lp->infinite) lp->orig_upbo[i] *= lp->scale[i]; } /* unscale the matrix */ for (j = 1; j <= lp->columns; j++) for (i = lp->col_end[j - 1]; i < lp->col_end[j]; i++) lp->mat[i].value /= lp->scale[lp->mat[i].row_nr]; /* unscale the rhs! */ for (i = 0; i <= lp->rows; i++) lp->orig_rh[i] /= lp->scale[i]; free(lp->scale); lp->scaling_used = FALSE; lp->eta_valid = FALSE; } } void auto_scale(lprec *lp) { int i, j, row_nr, IntUsed; REAL *row_max, *row_min, *scalechange, absval; REAL col_max, col_min, col_scale; if (!lp->scaling_used) { MALLOC(lp->scale, lp->sum_alloc + 1, REAL); for (i = 0; i <= lp->sum; i++) lp->scale[i] = 1; } MALLOC(row_max, lp->rows + 1, REAL); MALLOC(row_min, lp->rows + 1, REAL); MALLOC(scalechange, lp->sum + 1, REAL); /* initialise min and max values */ for (i = 0; i <= lp->rows; i++) { row_max[i] = 0; row_min[i] = lp->infinite; } /* calculate min and max absolute values of rows */ for (j = 1; j <= lp->columns; j++) { for (i = lp->col_end[j - 1]; i < lp->col_end[j]; i++) { row_nr = lp->mat[i].row_nr; absval = my_abs(lp->mat[i].value); if (absval != 0) { row_max[row_nr] = my_max(row_max[row_nr], absval); row_min[row_nr] = my_min(row_min[row_nr], absval); } } } /* calculate scale factors for rows */ for (i = 0; i <= lp->rows; i++) { scalechange[i] = minmax_to_scale(row_min[i], row_max[i]); lp->scale[i] *= scalechange[i]; } /* now actually scale the matrix */ for (j = 1; j <= lp->columns; j++) for (i = lp->col_end[j - 1]; i < lp->col_end[j]; i++) lp->mat[i].value *= scalechange[lp->mat[i].row_nr]; /* and scale the rhs! */ for (i = 0; i <= lp->rows; i++) lp->orig_rh[i] *= scalechange[i]; free(row_max); printf("after free r_max. "); free(row_min); printf("after free rmin. "); IntUsed = FALSE; i = lp->rows + 1; while (!IntUsed && i <= lp->sum) { IntUsed = lp->must_be_int[i]; i++; } if (!IntUsed) { REAL col_max, col_min, col_scale; /* calculate scales */ for (j = 1; j <= lp->columns; j++) { col_max = 0; col_min = lp->infinite; for (i = lp->col_end[j - 1]; i < lp->col_end[j]; i++) { if (lp->mat[i].value != 0) { col_max = my_max(col_max, my_abs(lp->mat[i].value)); col_min = my_min(col_min, my_abs(lp->mat[i].value)); } } scalechange[lp->rows + j] = minmax_to_scale(col_min, col_max); lp->scale[lp->rows + j] *= scalechange[lp->rows + j]; } /* scale mat */ for (j = 1; j <= lp->columns; j++) for (i = lp->col_end[j - 1]; i < lp->col_end[j]; i++) lp->mat[i].value *= scalechange[lp->rows + j]; /* scale bounds as well */ for (i = lp->rows + 1; i < lp->sum; i++) { if (lp->orig_lowbo[i] != 0) lp->orig_lowbo[i] /= scalechange[i]; if (lp->orig_upbo[i] != lp->infinite) lp->orig_upbo[i] /= scalechange[i]; } lp->columns_scaled = TRUE; } printf("b4 free scch. "); free(scalechange); printf("after free scch. "); lp->scaling_used = TRUE; lp->eta_valid = FALSE; } void reset_basis(lprec *lp) { lp->basis_valid = FALSE; } void print_solution(lprec *lp) { int i; fprintf(stdout, "Value of objective function: %16.10g\n", (double)lp->best_solution[0]); /* print normal variables */ for (i = 1; i <= lp->columns; i++) if (lp->names_used) fprintf(stdout, "%-10s%16.5g\n", lp->col_name[i], (double)lp->best_solution[lp->rows + i]); else fprintf(stdout, "Var [%4d] %16.5g\n", i, (double)lp->best_solution[lp->rows + i]); /* print achieved constraint values */ if (lp->verbose) { fprintf(stdout, "\nActual values of the constraints:\n"); for (i = 1; i <= lp->rows; i++) if (lp->names_used) fprintf(stdout, "%-10s%16.5g\n", lp->row_name[i], (double)lp->best_solution[i]); else fprintf(stdout, "%Row [%4d] %16.5g\n", i, (double)lp->best_solution[i]); } if ((lp->verbose || lp->print_duals)) { if (lp->max_level != 1) fprintf(stdout, "These are the duals from the node that gave the optimal solution.\n"); else fprintf(stdout, "\nDual values:\n"); for (i = 1; i <= lp->rows; i++) if (lp->names_used) fprintf(stdout, "%-10s%16.5g\n", lp->row_name[i], (double)lp->duals[i]); else fprintf(stdout, "Row [%4d] %16.5g\n", i, (double)lp->duals[i]); } } /* Printsolution */ void write_LP(lprec *lp, FILE *output) { int i, j; REAL *row; nstring var_name; MALLOC(row, lp->columns + 1, REAL); if (lp->maximise) fprintf(output, "max:"); else fprintf(output, "min:"); get_row(lp, 0, row); for (i = 1; i <= lp->columns; i++) if (row[i] != 0) { if (row[i] == -1) fprintf(output, " -"); else if (row[i] == 1) fprintf(output, " +"); else fprintf(output, " %+g ", row[i]); if (lp->names_used) fprintf(output, "%s", lp->col_name[i]); else fprintf(output, "x%d", i); } fprintf(output, ";\n"); for (j = 1; j <= lp->rows; j++) { if (lp->names_used) fprintf(output, "%s:", lp->row_name[j]); get_row(lp, j, row); for (i = 1; i <= lp->columns; i++) if (row[i] != 0) { if (row[i] == -1) fprintf(output, " -"); else if (row[i] == 1) fprintf(output, " +"); else fprintf(output, " %+g ", row[i]); if (lp->names_used) fprintf(output, "%s", lp->col_name[i]); else fprintf(output, "x%d", i); } if (lp->orig_upbo[j] == 0) fprintf(output, " ="); else if (lp->ch_sign[j]) fprintf(output, " >"); else fprintf(output, " <"); if (lp->ch_sign[j]) fprintf(output, " %g;\n", -lp->orig_rh[j]); else fprintf(output, " %g;\n", lp->orig_rh[j]); } for (i = lp->rows + 1; i <= lp->sum; i++) { if (lp->orig_lowbo[i] != 0) { if (lp->names_used) fprintf(output, "%s > %g;\n", lp->col_name[i - lp->rows], lp->orig_lowbo[i]); else fprintf(output, "x%d > %g;\n", i - lp->rows, lp->orig_lowbo[i]); } if (lp->orig_upbo[i] != lp->infinite) { if (lp->names_used) fprintf(output, "%s < %g;\n", lp->col_name[i - lp->rows], lp->orig_upbo[i]); else fprintf(output, "x%d < %g;\n", i - lp->rows, lp->orig_upbo[i]); } } i = 1; while (!lp->must_be_int[lp->rows + i] && i <= lp->columns) i++; if (i <= lp->columns) { if (lp->names_used) fprintf(output, "\nint %s", lp->col_name[i]); else fprintf(output, "\nint x%d", i); i++; for (; i <= lp->columns; i++) if (lp->must_be_int[lp->rows + i]) if (lp->names_used) fprintf(output, ",%s", lp->col_name[i]); else fprintf(output, ", x%d", i); fprintf(output, ";\n"); } free(row); } void write_MPS(lprec *lp, FILE *output) { int i, j, marker; REAL *column; MALLOC(column, lp->rows + 1, REAL); marker = 0; fprintf(output, "NAME %s\n", lp->lp_name); fprintf(output, "ROWS\n"); for (i = 0; i <= lp->rows; i++) { if (i == 0) fprintf(output, " N "); else if (lp->orig_upbo[i] == lp->infinite) if (lp->ch_sign[i]) fprintf(output, " G "); else fprintf(output, " L "); else fprintf(output, " E "); if (lp->names_used) fprintf(output, "%s\n", lp->row_name[i]); else fprintf(output, "r_%d\n", i); } fprintf(output, "COLUMNS\n"); j = 0; for (i = 1; i <= lp->columns; i++) { if ((lp->must_be_int[i + lp->rows]) && (marker % 2) == 0) { fprintf(output, " MARK%04d 'MARKER' 'INTORG'\n", marker); marker++; } if ((!lp->must_be_int[i + lp->rows]) && (marker % 2) == 1) { fprintf(output, " MARK%04d 'MARKER' 'INTEND'\n", marker); marker++; } get_column(lp, i, column); j = 0; if (lp->maximise) { if (column[j] != 0) { if (lp->names_used) fprintf(output, " %-8s %-8s %g\n", lp->col_name[i], lp->row_name[j], -column[j]); else fprintf(output, " var_%-4d r_%-6d %g\n", i, j, -column[j]); } } else { if (column[j] != 0) { if (lp->names_used) fprintf(output, " %-8s %-8s %g\n", lp->col_name[i], lp->row_name[j], column[j]); else fprintf(output, " var_%-4d r_%-6d %g\n", i, j, column[j]); } } for (j = 1; j <= lp->rows; j++) if (column[j] != 0) { if (lp->names_used) fprintf(output, " %-8s %-8s %g\n", lp->col_name[i], lp->row_name[j], column[j]); else fprintf(output, " var_%-4d r_%-6d %g\n", i, j, column[j]); } } if ((marker % 2) == 1) { fprintf(output, " MARK%04d 'MARKER' 'INTEND'\n", marker); marker++; } fprintf(output, "RHS\n"); for (i = 1; i <= lp->rows; i++) { if (lp->ch_sign[i]) { if (lp->names_used) fprintf(output, " RHS %-8s %g\n", lp->row_name[i], (double)-lp->orig_rh[i]); else fprintf(output, " RHS r_%-6d %g\n", i, (double)-lp->orig_rh[i]); } else { if (lp->names_used) fprintf(output, " RHS %-8s %g\n", lp->row_name[i], (double)lp->orig_rh[i]); else fprintf(output, " RHS r_%-6d %g\n", i, (double)lp->orig_rh[i]); } } fprintf(output, "BOUNDS\n"); if (lp->names_used) for (i = lp->rows + 1; i <= lp->sum; i++) { if (lp->orig_upbo[i] < lp->infinite) fprintf(output, " UP BND %-8s %g\n", lp->col_name[i - lp->rows], (double)lp->orig_upbo[i]); if (lp->orig_lowbo[i] != 0) fprintf(output, " LO BND %-8s %g\n", lp->col_name[i - lp->rows], (double)lp->orig_lowbo[i]); } else for (i = lp->rows + 1; i <= lp->sum; i++) { if (lp->orig_upbo[i] < lp->infinite) fprintf(output, " UP BND var_%-4d %g\n", i - lp->rows, (double)lp->orig_upbo[i]); if (lp->orig_lowbo[i] != 0) fprintf(output, " LO BND var_%-4d %g\n", i - lp->rows, (double)lp->orig_lowbo[i]); } fprintf(output, "ENDATA\n"); free(column); } void print_duals(lprec *lp) { int i; for (i = 1; i <= lp->rows; i++) if (lp->names_used) fprintf(stdout, "%10s [%3d] % 10.4f\n", lp->row_name[i], i, lp->duals[i]); else fprintf(stdout, "Dual [%3d] % 10.4f\n", i, lp->duals[i]); } void print_scales(lprec *lp) { int i; if (lp->scaling_used) { for (i = 0; i <= lp->rows; i++) fprintf(stdout, "Row[%3d] scaled at % 10.6f\n", i, lp->scale[i]); for (i = 1; i <= lp->columns; i++) fprintf(stdout, "Column[%3d] scaled at % 10.6f\n", i, lp->scale[lp->rows + i]); } }