📄 read.c
字号:
/* ============================================================================ NAME : read.c PURPOSE : translation of lp-problem and storage in sparse matrix SHORT : Subroutines for yacc program to store the input in an intermediate data-structure. The yacc and lex programs translate the input. First the problemsize is determined and the date is read into an intermediate structure, then readinput fills the sparse matrix. USAGE : call yyparse(); to start reading the input. call readinput(); to fill the sparse matrix. ============================================================================ Rows : contains the amount of rows + 1. Rows-1 is the amount of constraints (no bounds) Rows also contains the rownr 0 which is the objective function Columns : contains the amount of columns (different variable names found in the constraints) Nonnuls : contains the amount of nonnuls = sum of different entries of all columns in the constraints and in the objectfunction Hash_tab : contains all columnnames on the first level of the structure the row information is kept under each column structure in a linked list (also the objective funtion is in this structure) Bound information is also stored under under the column name First_rside : points to a linked list containing all relational operators and the righthandside values of the constraints the linked list is in reversed order with respect to the rownumbers ============================================================================ */#include "lpkit.h"#include "lpglob.h"#include <string.h>#include <limits.h>short *relat;int Verbose;constraint_name *First_constraint_name;rside *First_rside;tmp_store_struct tmp_store;short Ignore_decl;hashtable *Hash_tab;#define HASHSIZE 10007 /* prime number is better, MB *//* * errorhandeling routine for yyparse() */void yyerror(char *string){ fprintf(stderr, "PARSING ERROR: %s on line %d, quiting\n", string, yylineno); exit(EXIT_FAILURE);}void check_decl(int within_int_decl){ if(within_int_decl) { Ignore_decl = FALSE; } else { fprintf(stderr, "Unknown declaration specifier on line %d, ignored\n", yylineno); Ignore_decl = TRUE; }}void add_int_var(char *name){ hashelem *hp; if(Verbose) fprintf(stderr, "int: %s\n", name); if(!(hp = findhash(name, Hash_tab))) fprintf(stderr, "Unknown variable %s declared integer on line %d, ignored\n", name, yylineno); else if(hp->must_be_int) fprintf(stderr, "Variable %s declared integer more than once on line %d\n", name, yylineno); else hp->must_be_int = TRUE;}/* * initialisation of hashtable and globals. */void init_read(void){ Rows = 0; Non_zeros = 0; Columns = 0; CALLOC(First_rside, 1); First_rside->value = 0; /* first row (nr 0) is always the objective function */ First_rside->relat = REL_OF; Hash_tab = create_hash_table(HASHSIZE);} /* init *//* * searchs in column-list (p is pointer to first element of column-list) * for column->row = row. * getrow() returns a pointer to this column structure. * If not found a NULL-pointer is returned */static column *getrow(column *p, int row){ for(; p != NULL; p = p->next) if(p->row == row) return(p); return(p) ;} /* getrow *//* * Creates a bound record. * Set lowbo = 0 and upbo = Infinite * */static bound *create_bound_rec(void){ bound *bp; CALLOC(bp, 1); bp->upbo = DEF_INFINITE; bp->lowbo = 0; return(bp);} /* create_bound_rec *//* * clears the tmp_store variable after all information has been copied */void null_tmp_store(void){ tmp_store.value = 0; tmp_store.rhs_value = 0;}/* * variable : pointer to text array with name of variable * row : the rownumber of the constraint * value : value of matrixelement * A(row, variable). * Sign : (global) determines the sign of value. * store() : stores value in matrix * A(row, variable). If A(row, variable) already contains data, * value is added to the existing value. */static void store(char *variable, int row, REAL value) { hashelem *h_tab_p; column *col_p; if(value == 0) { fprintf(stderr, "(store) Warning, variable %s has an effective coefficient of 0 on line %d. Ignored.\n", variable, yylineno); return; } if((h_tab_p = findhash(variable, Hash_tab)) == NULL) { h_tab_p = puthash(variable, Hash_tab); Columns++; /* counter for calloc of final array */ CALLOC(h_tab_p->col, 1); Non_zeros++; /* for calloc of final arrays */ h_tab_p->col->row = row; h_tab_p->col->value = value; } else if((col_p = getrow(h_tab_p->col, row)) == NULL) { CALLOC(col_p, 1); Non_zeros++; /* for calloc of final arrays */ col_p->value = value; col_p->row = row; col_p->next = h_tab_p->col; h_tab_p->col = col_p; } else col_p->value += value;} /* store *//* * store relational operator given in yylex[0] in the rightside list. * Also checks if it constaint was a bound and if so stores it in the * boundslist */void store_re_op(void){ short tmp_relat; switch(yytext[0]) { case '=': tmp_relat = REL_EQ; break; case '>': tmp_relat = REL_GE; break; case '<': tmp_relat = REL_LE; break; default: fprintf(stderr, "Error: unknown relational operator %s on line %d\n", yytext, yylineno); exit(EXIT_FAILURE); break; } if(Lin_term_count > 1) /* it is not a bound */ First_rside->relat = tmp_relat; else /* could be a bound */ tmp_store.relat = tmp_relat;} /* save_re_op *//* * store RHS value in the rightside structure * if type = true then */void rhs_store(REAL value){ if(Lin_term_count > 1) /* not a bound */ First_rside->value += value; else /* a bound */ tmp_store.rhs_value += value;} /* RHS_store *//* * store all data in the right place * count the amount of lineair terms in a constraint * only store in data-structure if the constraint is not a bound */void var_store(char *var, int row, REAL value){ if(strlen(var) > MAXSTRL) { fprintf(stderr, "Variable name '%s' too long, at most %d characters allowed\n", var, MAXSTRL); exit(EXIT_FAILURE); } /* also in a bound the same var name can occur more than once. Check for this. Don't increment Lin_term_count */ if(Lin_term_count != 1 || strcmp(tmp_store.name, var) != 0) Lin_term_count++; /* always store objective function with rownr == 0. */ if(row == 0) { store(var, row, value); return; } if(Lin_term_count == 1) { /* don't store yet. could be a bound */ strcpy(tmp_store.name, var); tmp_store.row = row; tmp_store.value += value; return; } if(Lin_term_count == 2) { /* now you can also store the first variable */ rside *rp; /* make space for the rhs information */ CALLOC(rp, 1); rp->next = First_rside; First_rside = rp; First_rside->value = tmp_store.rhs_value; First_rside->relat = tmp_store.relat; if(tmp_store.value != 0) store(tmp_store.name, tmp_store.row, tmp_store.value); else fprintf(stderr, "Warning, variable %s has an effective coefficient of 0 on line %d. Ignored.\n", tmp_store.name, yylineno); null_tmp_store(); } store(var, row, value);} /* var_store *//* * store the information in tmp_store because it is a bound */void store_bounds(void){ if(tmp_store.value != 0) { hashelem *h_tab_p; REAL boundvalue; if((h_tab_p = findhash(tmp_store.name, Hash_tab)) == NULL) { /* a new columnname is found, create an entry in the hashlist */ h_tab_p = puthash(tmp_store.name, Hash_tab); Columns++; /* counter for calloc of final array */ /* create a place to store bounds information */ h_tab_p->bnd = create_bound_rec(); } else if(h_tab_p->bnd == NULL) /* create a place to store bounds information */ h_tab_p->bnd = create_bound_rec(); /* else bound_rec already exists */ if(tmp_store.value < 0) { /* divide by negative number, */ /* relational operator may change */ if(tmp_store.relat == REL_GE) tmp_store.relat = REL_LE; else if(tmp_store.relat == REL_LE) tmp_store.relat = REL_GE; } /* Check sanity of bound; all variables should be positive */ boundvalue = tmp_store.rhs_value / tmp_store.value; if( ((tmp_store.relat == REL_EQ) && (boundvalue < 0)) || ((tmp_store.relat == REL_LE) && (boundvalue < 0))) { /* Error */ fprintf(stderr, "Error on line %d: variables must always be non-negative\n", yylineno); exit(EXIT_FAILURE); } if((tmp_store.relat == REL_GE) && (boundvalue <= 0)) /* Warning */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -