📄 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 = 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 = EQ;
break;
case '>':
tmp_relat=GE;
break;
case '<':
tmp_relat=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 == GE)
tmp_store.relat = LE;
else if(tmp_store.relat == LE)
tmp_store.relat = GE;
}
/* Check sanity of bound; all variables should be positive */
boundvalue = tmp_store.rhs_value / tmp_store.value;
if( ((tmp_store.relat == EQ) && (boundvalue < 0))
|| ((tmp_store.relat == 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 == GE) && (boundvalue <= 0)) /* Warning */
fprintf(stderr,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -