home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / apps / math / lpsolves / read.c < prev    next >
C/C++ Source or Header  |  1992-08-07  |  14KB  |  534 lines

  1. /*
  2. ============================================================================
  3. NAME    : read.c
  4. PURPOSE : translation of lp-problem and storage in sparse matrix
  5. SHORT   : Subroutines for yacc program to store the input in an intermediate
  6.           data-structure. The yacc and lex programs translate the input.
  7.           First the problemsize is determined and the date is read into
  8.           an intermediate structure, then readinput fills the sparse matrix.
  9. USAGE   : call yyparse(); to start reading the input.
  10.           call readinput(); to fill the sparse matrix.
  11. ============================================================================
  12. Rows : contains the amount of rows + 1
  13.        Rows-1 is the amount of constraints (no bounds)
  14.        Rows   also contains the rownr 0 which is the objectfunction
  15. Columns : contains the amount of columns (different variable names
  16.           found in the constraints)
  17. Nonnuls : contains the amount of nonnuls = sum of different entries
  18.           of all columns in the constraints and in the objectfunction
  19. Hash_tab : contains all columnnames on the first level of the structure
  20.            the row information is kept under each column structure
  21.            in a linked list (also the objext funtion is in this structure)
  22.            Bound information is also stored under under the column name
  23. First_rside : points to a linked list containing all relational operators
  24.               and the righthandside values of the constraints
  25.               the linked list is in reversed order with respect to the
  26.               rownumbers
  27. ============================================================================
  28. */
  29. #include "defines.h"
  30. #include "globals.h"
  31.  
  32. /*---------------------------------------------------------------------------*/
  33.  
  34. /*
  35.  * errorhandeling routine for yyparse()
  36.  */
  37. void yyerror(char *string)
  38. {
  39.   fprintf(stderr, "PARSING ERROR: %s on line %d, quiting\n", string, yylineno);
  40.   exit(1);
  41. }
  42.  
  43. void check_decl(char *str)
  44. {
  45.   if(strcmp(str, "int"))
  46.     {
  47.       fprintf(stderr, "Unknown declaration specifier %s on line %d, ignored\n",
  48.           str, yylineno);
  49.       Ignore_decl = TRUE;
  50.     }
  51. }
  52.  
  53. void add_int_var(char *name)
  54. {
  55.   hashelem *hp;
  56.  
  57.   if(Verbose)
  58.     fprintf(stderr, "int: %s\n", name);
  59.   if(!(hp = gethash(name)))
  60.     fprintf(stderr,
  61.         "Unknown variable %s declared integer on line %d, ignored\n",
  62.         name, yylineno);
  63.   else
  64.     hp->must_be_int = 1;
  65. }
  66.  
  67.  
  68. /*
  69.  * initialisation of hashtable and globals.
  70.  */
  71. void init_read(void)
  72. {
  73.   int i;
  74.   Rows = 0;
  75.   Nonnuls = 0;
  76.   Columns = 0;
  77.   for(i = 0; i<HASH_SIZE; Hash_tab[i++] = NULL);
  78.   CALLOC(First_rside, 1, rside);
  79.   First_rside->value = 0;
  80.   First_rside->relat = OF; /* first row (nr 0) is always the objective function */
  81. } /* init */
  82.  
  83. /*---------------------------------------------------------------------------*/
  84.  
  85. /*
  86.  * Returns hashvalue of string
  87.  * hashvalue = sum ( asciivalue of character * indexnumber) mod HASHSIZE
  88.  */
  89. int hashvalue(char *string)
  90. {
  91.   int i, j;
  92.   i = j = 0;
  93.   while((int)string[j]&&j<MAXSTRL)
  94.     i += (NAMELEN-j)*(int)string[j++];
  95.   return(i % HASH_SIZE);
  96. } /* hashvalue */
  97.  
  98.  
  99.  
  100. /*
  101.  * Returns a pointer to hashelement with colname = variable
  102.  * If this hashelement does not exists, gethash() returns a NULL pointer
  103.  */
  104. hashelem *gethash(char *variable) 
  105. {
  106.   hashelem *h_tab_p;
  107.   for(h_tab_p = Hash_tab[hashvalue(variable)];
  108.       h_tab_p != NULL;
  109.       h_tab_p = h_tab_p->next)
  110.     if(strcmp(variable, h_tab_p->colname) == 0)
  111.       return(h_tab_p);
  112.   return(h_tab_p);
  113. } /* gethash */
  114.  
  115.  
  116.  
  117. /*
  118.  * searchs in column-list (p is pointer to first element of column-list)
  119.  * for column->row = row.
  120.  * getrow() returns a pointer to this column structure.
  121.  * If not found a NULL-pointer is returned
  122.  */
  123. column *getrow(column *p,
  124.            int row)
  125. {
  126.   for(; p != NULL; p = p->next)
  127.     if(p->row == row)
  128.       return(p);
  129.   return(p) ;
  130. } /* getrow */
  131.  
  132.  
  133.  
  134. /*
  135.  * Creates a bound record.
  136.  * Set lowbo = 0 and upbo = INFINITE
  137.  *
  138.  */
  139. bound *create_bound_rec(void)
  140. {
  141.   bound *bp;
  142.   CALLOC(bp, 1, bound);
  143.   bp->upbo = INFINITE;
  144.   bp->lowbo = 0;
  145.   return(bp);
  146. } /* create_bound_rec */
  147.  
  148.  
  149.  
  150. /*
  151.  * clears the tmp_store variable after all information has been copied
  152.  */
  153. void null_tmp_store(void)
  154. {
  155.   tmp_store.value = 0;
  156.   tmp_store.rhs_value = 0;
  157. }
  158.  
  159. /*---------------------------------------------------------------------------*/
  160.  
  161. /*
  162.  * variable : pointer to text array with name of variable
  163.  * row      : the rownumber of the constraint
  164.  * value    : value of matrixelement
  165.  *            A(row, variable).
  166.  * Sign     : (global)  determines the sign of value.
  167.  * store()  : stores value in matrix
  168.  *          A(row, variable). If A(row, variable) already contains data,
  169.  *          value is added to the existing value.
  170.  */
  171. void store(char *variable,
  172.        int row,
  173.        double value) 
  174.   hashelem *h_tab_p;
  175.   column *col_p;
  176.   int hv;
  177.  
  178.   if(value == (double)0)
  179.     return;
  180.   if((h_tab_p = gethash(variable)) == NULL)
  181.   {
  182.     CALLOC(h_tab_p, 1, hashelem);
  183.     Columns++; /* counter for calloc of final array */
  184.     hv = hashvalue(variable);
  185.     h_tab_p->next = Hash_tab[hv];
  186.     Hash_tab[hv] = h_tab_p;
  187.     strcpy(h_tab_p->colname, variable);
  188.     CALLOC(h_tab_p->col, 1, column);
  189.     Nonnuls++; /* for calloc of final arrays */
  190.     h_tab_p->col->row = row;
  191.     h_tab_p->col->value = value;
  192.   }
  193.   else
  194.     if((col_p = getrow(h_tab_p->col, row)) == NULL)
  195.     {
  196.       CALLOC(col_p, 1, column);
  197.       Nonnuls++; /* for calloc of final arrays */
  198.       col_p->value = value;
  199.       col_p->row = row;
  200.       col_p->next = h_tab_p->col;
  201.       h_tab_p->col = col_p;
  202.     }
  203.     else
  204.       col_p->value += value;
  205. } /* store */
  206.  
  207.  
  208.  
  209. /*---------------------------------------------------------------------------*/
  210.  
  211. /*
  212.  * store relational operator given in yylex[0] in the rightside list.
  213.  * Also checks if it constaint was a bound and if so stores it in the
  214.  * boundslist
  215.  */
  216. void store_re_op(void)
  217. {
  218.   short tmp_relat;
  219.   switch(yytext[0]) {
  220.  
  221.   case '=':
  222.     tmp_relat = EQ;
  223.     break;
  224.  
  225.   case '>':
  226.     tmp_relat=GE;
  227.     break;
  228.     
  229.   case '<':
  230.     tmp_relat=LE;
  231.     break;
  232.     
  233.   default:
  234.     break;
  235.   }
  236.   
  237.   if(Lin_term_count > 1) /* it is not a bound */
  238.     First_rside->relat = tmp_relat;
  239.   else /* could be a bound */
  240.     tmp_store.relat = tmp_relat;
  241. } /* save_re_op */
  242.  
  243.  
  244.  
  245. /*
  246.  * store RHS value in the rightside structure
  247.  * if type = true then
  248.  */
  249. void rhs_store(double value)
  250. {
  251.   if(Lin_term_count <= 1) /* could be a bound */
  252.     tmp_store.rhs_value += value;
  253.   else /* not a bound */
  254.     First_rside->value += value;
  255. } /* RHS_store */
  256.  
  257.  
  258.  
  259. /*
  260.  * store all data in the right place
  261.  * count the amount of lineair terms in a constraint
  262.  * only store in data-structure if the constraint is not a bound
  263.  */
  264. void var_store(char *var,
  265.            int row,
  266.            double value)
  267. {
  268.   if(strlen(var) > MAXSTRL)
  269.     {
  270.       fprintf(stderr, "Variable name too long, at most %d characters allowed",
  271.           MAXSTRL);
  272.       exit(1);
  273.     }
  274.   /* also in a bound the same var name can occur more than once. Check for
  275.      this. Don't increment Lin_term_count */
  276.  
  277.   if(Lin_term_count != 1 || strcmp(tmp_store.name, var) != 0)
  278.     Lin_term_count++;
  279.  
  280.   if(row == 0) /* always store objective function with rownr == 0 */
  281.     {
  282.       store(var,  row,  value);
  283.       return;
  284.     }
  285.   
  286.   if(Lin_term_count == 1) /* don't yet store. could be a bound */
  287.     {
  288.       strcpy(tmp_store.name, var);
  289.       tmp_store.row = row;
  290.       tmp_store.value += value;
  291.       return;
  292.     }
  293.   
  294.   if(Lin_term_count == 2) /* now you can also store the first variable */
  295.     {
  296.       rside *rp;
  297.       /* make space for the rhs information */
  298.       CALLOC(rp, 1, rside);
  299.       rp->next = First_rside;
  300.       First_rside = rp;
  301.       First_rside->value = tmp_store.rhs_value;
  302.       First_rside->relat = tmp_store.relat;
  303.       
  304.       if (tmp_store.value != 0)
  305.         store(tmp_store.name, tmp_store.row, tmp_store.value);
  306.  
  307.       null_tmp_store();
  308.     }
  309.  
  310.   store(var, row, value);
  311. } /* var_store */
  312.  
  313.  
  314.  
  315. /*
  316.  * store the information in tmp_store because it is a bound
  317.  */
  318. store_bounds(void)
  319. {
  320.   if (tmp_store.value != 0)
  321.     {
  322.       hashelem *h_tab_p;
  323.       int hv;
  324.  
  325.       if((h_tab_p = gethash(tmp_store.name)) == NULL)
  326.         {
  327.           /* a new columnname is found, create an entry in the hashlist */
  328.           CALLOC(h_tab_p, 1, hashelem);
  329.           Columns++; /* counter for calloc of final array */
  330.       hv            = hashvalue(tmp_store.name);
  331.       h_tab_p->next = Hash_tab[hv];
  332.           Hash_tab[hv]  = h_tab_p;
  333.           strcpy(h_tab_p->colname, tmp_store.name);
  334.           /* create a place to store bounds information */
  335.           h_tab_p->bnd = create_bound_rec();
  336.         }
  337.       else
  338.         if(h_tab_p->bnd == NULL)
  339.           /* create a place to store bounds information */
  340.           h_tab_p->bnd = create_bound_rec();
  341.       /* else bound_rec already exists */
  342.    
  343.       if(tmp_store.value < 0) /* divide by negative number, */
  344.                             /* relational operator may change */
  345.         {
  346.           if (tmp_store.relat == GE)
  347.             tmp_store.relat = LE;
  348.           else if (tmp_store.relat == LE)
  349.             tmp_store.relat = GE;
  350.         }
  351.  
  352.       if ((tmp_store.relat == GE) || (tmp_store.relat == EQ))
  353.         h_tab_p->bnd->lowbo = tmp_store.rhs_value / tmp_store.value;
  354.       if ((tmp_store.relat == LE) || (tmp_store.relat == EQ))
  355.         h_tab_p->bnd->upbo = tmp_store.rhs_value / tmp_store.value;
  356.     }
  357.   
  358.   null_tmp_store();
  359. } /* store_bounds */
  360.  
  361. /* ========================================================================= */
  362.  
  363.  
  364. /*
  365.  * reallocates eta
  366.  */
  367. void resize_eta(void)
  368. {
  369.   Cur_eta_size *= 2;
  370.   if (Verbose)
  371.     printf("Resizing Eta_value and Eta_rownr, new size is %d\n", Cur_eta_size);
  372.   if(!(Eta_value = realloc(Eta_value, Cur_eta_size * sizeof(double))))
  373.     {
  374.       fprintf(stderr, "Error: cannot realloc Eta_value to size %d (entries)\n",
  375.           Cur_eta_size);
  376.       exit(1);
  377.     }
  378.   if(!(Eta_rownr = realloc(Eta_rownr, Cur_eta_size * sizeof(int))))
  379.     {
  380.       fprintf(stderr, "Error: cannot realloc Eta_rownr to size %d (entries)\n",
  381.           Cur_eta_size);
  382.       exit(1);
  383.     }
  384. } /* resize_eta */
  385.  
  386.  
  387.  
  388.  
  389. /*
  390.  * transport the data from the intermediate structure to the sparse matrix
  391.  * and free the intermediate structure
  392.  */
  393. void readinput(int *cend,
  394.            double *rh,
  395.            short *relat,
  396.            double *lowbo,
  397.            double *upbo,
  398.            matrec *mat,
  399.            nstring *names)
  400. {
  401.   int    i, j, k, index, nn_ind;
  402.   column *cp,*tcp;    /* tcp (temporary cp) points to memory-space to free */
  403.   hashelem *hp,*thp;
  404.   bound *bp;
  405.   int   x;
  406.   rside *rp;
  407.   intrec *irp;
  408.   
  409.   /* initialize lower and upper bound arrays */
  410.   for (i = 0; i <= Sum; i++)
  411.     {
  412.       lowbo[i] = 0;
  413.       upbo[i] = INFINITE;
  414.     }
  415.   
  416.   /* fill names with the rownames */
  417.   for (i = 0; i <= Rows; i++)
  418.     {
  419.       /* the first row is row zero (the objective function)             */
  420.       sprintf(names[i], "%s%d", STD_ROW_NAME_PREFIX, i);
  421.     }
  422.   
  423.   for (i = Rows;i >= 0;i--)
  424.     {
  425.       rp = First_rside;
  426.       relat[i] = rp->relat;
  427.       rh[i] = rp->value;
  428.       First_rside = rp->next;
  429.       free(rp);  /* free memory when data has been read */
  430.     }
  431.   
  432.   /* change upperbound to zero if the relational operator is the equal sign */
  433.   for (i = 1; i <= Rows; i++)
  434.     if (relat[i] == EQ)
  435.       upbo[i] = 0;
  436.   
  437.   /* start reading the Hash_list structure */
  438.   index = 0;
  439.   nn_ind = 0;
  440.   
  441.   for (i = 0;i < HASH_SIZE;i++)
  442.     {
  443.       hp = Hash_tab[i];
  444.       while (hp != NULL)
  445.         {
  446.       /* put an index in the cend array when a new name is found */
  447.       cend[index++] = nn_ind;
  448.  
  449.       /* check if it must be an integer variable */
  450.       if(hp->must_be_int)
  451.         {
  452.           CALLOC(irp, 1, intrec);
  453.           irp->varnr = Rows + index;
  454.           irp->next  = First_int;
  455.           First_int  = irp;
  456.         }
  457.       /* check for bound */
  458.       if (hp->bnd != NULL)
  459.         {
  460.           bp = hp->bnd;
  461.               lowbo[Rows+index] = bp->lowbo;
  462.               upbo[Rows+index] = bp->upbo;
  463.               free(bp); /* free memory when data has been read*/
  464.         }
  465.       
  466.       /* copy name of column variable */
  467.       strcpy(names[Rows+index], hp->colname);
  468.  
  469.       /* put matrix values in sparse matrix */
  470.           cp = hp->col;
  471.           while (cp!=NULL)
  472.             {
  473.               mat[nn_ind].rownr = cp->row;
  474.           mat[nn_ind].value = cp->value;
  475.           nn_ind++;
  476.           tcp = cp;
  477.           cp = cp->next;
  478.           free(tcp);  /* free memory when data has been read */
  479.         }
  480.       thp = hp;
  481.       hp = hp->next;
  482.           free(thp);    /* free memory when data has been read */
  483.         }
  484.     }
  485.   cend[index] = nn_ind; 
  486.   
  487.   if (Verbose)
  488.     {
  489.       printf("\n");
  490.       printf("**********Data read**********\n");
  491.       printf("Rows    : %d\n", Rows);
  492.       printf("Columns : %d\n", Columns);
  493.       printf("Nonnuls : %d\n", Nonnuls);
  494.       printf("\nSparse Matrix\nRow right hand side\n");
  495.       printf("%4s  %8s %3s %s\n\n", "nr", "row", "rel", "Value");
  496.       for (i = 0; i <= Rows; i++)
  497.     {
  498.       printf("%4d  %8s ", i, names[i]);
  499.       if (relat[i] == LE) printf(" < ");
  500.       if (relat[i] == EQ) printf(" = ");
  501.       if (relat[i] == GE) printf(" > ");
  502.       if (relat[i] == OF) printf("ObF");
  503.       printf(" %f\n", rh[i]);
  504.     }
  505.       
  506.       printf("\nMatrix contents\n%8s  %8s  %s\n\n","colname","row","value");
  507.       j = 0;
  508.       for (i = 0; i < Nonnuls; i++)
  509.     {
  510.       if (i == cend[j])
  511.         printf("%8s  %8s  %f\n", names[Rows+ ++j], names[mat[i].rownr],
  512.            mat[i].value);
  513.       else
  514.         printf("          %8s  %e\n", names[mat[i].rownr], mat[i].value);
  515.     }
  516.       printf("\nBounds\n%8s %3s %s\n\n", "name", "rel", "value");
  517.       for (i = 0; i <= Sum; i++)
  518.     {
  519.       if (upbo[i] < (INFINITE/10000))  /* double is to small to contain
  520.                           INFINITE thus is rounded */
  521.         printf("%8s  <  %f\n", names[i], upbo[i]);
  522.       if (lowbo[i] > 0)
  523.         printf("%8s  >  %f\n", names[i], lowbo[i]);
  524.     }
  525.       
  526.       printf("\n**********End data**********\n\n");
  527.     }
  528. } /* readinput */
  529.  
  530.  
  531. /* ===================== END OF read.c ===================================== */
  532.  
  533.