Пример #1
0
void read_eqie( RAT **ar, int dim, int *equa, int *ineq, int *maxrows, int *line,
               char *fname, char in_line[], char *scanned_inline )
/*****************************************************************/
/*
 * Read the INEQUALITY_SECTION into the table "ar".
 * For each (in)equality, the corresponding line of "ar" contains, in this order:
 *    the "dim" coefficients of the variables x1--xn,
 *    the right-hand side,
 *    0 if it was an equation, 1 if it was an inequality.
 * All inequalities are stored as "<=" inequalities.
 * Lines as
 *   "x1 - 1 <= 3 + x2"
 * are interpreted as
 *   "x1 -x2 <= 4"
 */
{
    char *p,*in;
    int i,rs=0,index=0,j,sysrow, numberread,nonempty;
    RAT val;

    sysrow = dim+2; /* row length of array "ar" */
    do 
    {
        nonempty = get_line(fp,fname,in_line,line);
    } 
    while (!nonempty);
    for (i = 0; scan_line(&val,3,dim,*line,
                          fname,in_line,scanned_inline);
         i++) 
    {
        /* 
         * scan_line() reads an inequality into string "scanned_inline",
         * with a little formatting.
         * "val" is not used.
         */
        p = in = scanned_inline;
        rs = 0;     /* rs records the type of inequality,
                     * rs = 0 means: type not yet known. */
        
        /* scan string "scanned_inline" up to '\0' or '#' */
        while (*p != '\0' && *p != '#' ) 
        {
            
            val.den.i = 1;
            val.num = 1;
            if (*p == '-')
                val.num = -1;
        
            /* 
             * If: {+,-} has been read,
             *     or {<,=,>} followed by {x,0,1,..,9} has been read,
             *     or it is the beginning of the line. then ...
             */
            if ( *p == '-' || *p == '+'  || 
                (p == scanned_inline || 
                 (p != scanned_inline && (*(p-1)=='<' || *(p-1)=='=' || *(p-1)=='>')) 
                 && ((*p < 58 && *p > 47) || *p =='x') )     ) 
            {
                numberread = 0;
                if ( *p == '-' || *p == '+')    p++;
                in = p;
                while (*p > 47 && *p < 58)
                    p++;
                if (in != p) 
                {
                    /* in points to a number, p to the next non-number */
                    numberread = 1;
                    val.num *= atoi(in);
                    if (*p == '/') 
                    {
                        p++;
                        in = p;
                        while (*p > 47 && *p < 58) p++;
                        if (p == in)
                            msg("%s, line %i : invalid denominator",
                                fname,*line);
                        if ((val.den.i = atoi(in)) <= 0)
                            msg("%s, line %i : invalid denominator",
                                fname,*line);
                    }   
                } /* if (in != p) */

                if (*p == 'x') 
                {
                    p++;
                    in = p;
                    while (*p > 47 && *p < 58) p++;
                    if (p == in) 
                        msg("%s, line %i : invalid format",fname,*line);
                    index = atoi(in)-1;
                    if (index > dim-1 || index < 0)
                        msg("%s, line %i : only variable names x1,...,xdim allowed",
                            fname,*line);
                }
                /* 
                 * Change by M.S. 1.6.92:
                 * The following four lines of code are changed.
                 *
                 * In the case (*p in {+,-}), 
                 * something like "10 +", but not "x10 +" has been encountered.
                 * In the case (rs==0 && *p in {<,>,>} ),
                 * something like "10 <", but not "x10 <" has been encountered.
                 * In both cases, the number "10" is interpreted as part of
                 * the right-hand side.
                 * But it should be tested, 
                 * whether a number has actually been read.
                 * Otherwise
                 * "x1++x2 <= 20\n"  is interpreted as
                 * "x1+1+x2 <= 20\n".
                 */
                else if (numberread && (*p == '+' || *p == '-'  || 
                          ((rs == 0) && (*p =='<'||*p == '>'||*p == '=')))) 
                {
                    index = dim;
                }
                /* The following four lines mean:
                 * If "<=" or ">=" or "==" has already been read (i.e. rs > 0),
                 * and if p points to the end of the line,
                 * then interpret the number in val as the right hand side.
                 * to be stored in the dim-th position of the current row
                 * of table "ar".
                 */
                else if (numberread && rs && (*(p) == '\0' || *(p) == '#'))  
                {
                    index = dim;
                }
                else 
                    msg("%s, line %i : invalid format",fname,*line);
            } /* if ......... */

            else if ((p != scanned_inline) 
                     && (*p == '<' || *p == '>' || *p == '=')) 
            {
                /* 
                 * Record the type of inequality:
                 * rs = 1   if it is an equation ("=" or "==")
                 * rs = 2   if it is a "<=" inequality (may also be written "=<")
                 * rs = 3   if it is a ">=" inequality (may also be written "=>")
                 */
                if (++rs > 1) 
                    msg("%s, line %i : invalid format",fname,*line);
                if ((*p == '=') && (*(p+1) == '='))
                    p++;
                else if ((*p == '=') && (*(p+1) != '>') && (*(p+1) != '<'));
                else if ((*p == '=' && *(p+1) == '>') ||
                         (*p == '>' && *(p+1) == '=')) 
                {
                    rs++;rs++;
                    p++;
                }
                else if ((*p == '=' && *(p+1) == '<') ||
                         (*p == '<' && *(p+1) == '=')) 
                {
                    rs++; 
                    p++;
                }
                else
                    msg("%s, line %i : invalid format",fname,*line);
                p++;
                index = -1;
            } /* else if < = > */
            
            else 
                msg("%s, line %i : invalid format",fname,*line);
            
            if (index > -1)  
            { /* not "< > =" */ 
                if (index == dim) val.num *= -1;
                if (rs ) 
                    I_RAT_sub(*(*ar+i*sysrow+index),val,*ar+i*sysrow+index);
                else
                    I_RAT_add(*(*ar+i*sysrow+index),val,*ar+i*sysrow+index);
            }
            
        } /* while */
        
        /* transform ">=" into "<=" by multiplying the inequality with -1 */
        if (rs == 3 ) 
        {  /* >= */
            for (j = 0; j <= dim; j++)
                (*ar+i*sysrow+j)->num = -(*ar+i*sysrow+j)->num;
            rs -= 1;
        }
        (*ar+(i+1)*sysrow-1)->num  =  --rs; 
    
        /* 
         * Now rs = 0 if the line was an equation,
         * and rs = 1 if the line was an inequality.
         * The last line stored rs into the "dim+1"th position of ar[i].
         */
        (rs == 1) ? (*ineq)++ : (*equa)++;
        
        if ((*ineq)+(*equa)+2 > *maxrows) 
        {
            *ar = (RAT *) RATallo(*ar,(*maxrows)*(dim+2),(*maxrows+INCR_INSYS_ROW)*(dim+2));
            *maxrows += INCR_INSYS_ROW;
        }
        do 
        {
            nonempty = get_line(fp,fname,in_line,line);
        } 
        while (!nonempty);
    }  /* for i */
}
Пример #2
0
void integ_rekurs( RAT *eqsum, RAT *iesum, int lev )
{ 
    val.den.i = 1;
    
    if (reknum % 1000 == 0) 
    {
        fprintf(prt,".");
        fflush(prt);

        /* 17.01.1994: include logging on file porta.log */
        porta_log(".");
        fflush(logfile);
    }
    reknum++;
    
    if (lev == eqdim) 
    {
        for (ptr = eqar+eqdim; ptr < ubea; ptr += eqrl, eqsum++) 
        {
            I_RAT_sub(*eqsum,*ptr,&val);
            if (val.num != 0)
                return;
        }
        for (ptr = iear+iedim; ptr < ubia; ptr += ierl, iesum++) 
        {
            I_RAT_sub(*iesum,*ptr,&val);
            if (val.num > 0)
                return;
        }
        
        intnum++;
        fprintf(fp,"(%3d) ",intnum);
        for (i = 0; i < eqdim; i++) 
            fprintf(fp,"%i ",integ[i]);
        fprintf(fp,"\n");
    }
    else 
    {
        val.num = lowbds[lev];
        osump = eqsum;
        nsump = eqsum+neq;
        for (ptr = eqar+lev; ptr < ubea; ptr += eqrl,osump++,nsump++) 
        {
            I_RAT_mul(*ptr,val,nsump);
            I_RAT_add(*osump,*nsump,nsump);
        }
        osump = iesum;
        nsump = iesum+nie;
        for (ptr = iear+lev; ptr < ubia; ptr += ierl,osump++,nsump++) 
        {
            I_RAT_mul(*ptr,val,nsump);
            I_RAT_add(*osump,*nsump,nsump);
        }
        
        for (integ[lev]=lowbds[lev]; integ[lev]<upbds[lev]; integ[lev]+=1) 
        {
            integ_rekurs(eqsum+neq,iesum+nie,lev+1);
            osump = eqsum;
            nsump = eqsum+neq;
            for (ptr = eqar+lev; ptr < ubea; ptr += eqrl,nsump++)
                I_RAT_add(*nsump,*ptr,nsump);
            osump = iesum;
            nsump = iesum+nie;
            for (ptr = iear+lev; ptr < ubia; ptr += ierl,nsump++)
                I_RAT_add(*nsump,*ptr,nsump);
        }
        integ_rekurs(eqsum+neq,iesum+nie,lev+1);
    }
}
Пример #3
0
int scan_line( RAT *rat_in, int type, int d, int line, 
               char fname[], char *in_line, char scanned_inline[] )
/*****************************************************************/
/*
 * Read the string "in_line" 
 * of "d" integers or fractions into the array rat_in
 * in case of type = 0 or 1, fractions are accepted:  1/2  400/5
 * in case of type = 2, only integers are accepted: 1 2 400 5
 * Brackets starting the line are overread. 
 * The statistical part is also overread. 
 * Return with 1.
 *
 * If the type = 3
 * or in_line is not started by brackets or integers or '+' or '-',
 * scan_line2() is used to scan the string in_line.
 * Output is string scanned_inline then.
 * Return with 0 if in_line begins with a number (not counting blanks),
 * with 1 otherwise.
 *
 * Change by M.S. 1.6.92:
 * Overread also tabs.
 */

{
    char ch, *ptr;
    int j,*int_in;
    RAT val;
    
    do
    {
        ch = *(in_line++);
    }  
    while (ch == ' ' || ch == '\t');
    
    /* overread brackets () and text inside */
    if (ch == '(') 
    {
        do 
        {
            ch = *(in_line++);
            if (ch == '\n')
                msg("%s, line %i : unexpected end of line",
                    fname,line);
        }  
        while (ch != ')');
        do 
        {
            ch = *(in_line++);
        } 
        while (ch == ' ' || ch == '\t');
    }
    in_line--;
    
    if ((((ch < '0' || ch > '9') && ch != '+' && ch != '-'))
        || type == 3 ) 
    {
        /* NO POINT-LINE */
        return(scan_line2(line,fname,in_line,scanned_inline));
    }

    int_in = (int *) rat_in;
    
    /* read exactly d fractions or integers */
    for (j = 0; j < d; j++,rat_in++) 
    {
        val.num = (int) strtol(in_line,&ptr,10);
        if (ptr == in_line)
            msg("%s, line %i : invalid format of input file ",
                fname,line);
        /* position in_line after the number */
        in_line = ptr;
        /* read the denominator, if type < 2 */
        if (type < 2) 
        {
            do 
            {
                ch = *(in_line++);
            } 
            while (ch == ' ' || ch == '\t');
            if (ch  == '/') 
            {
                val.den.i = (int) strtol(in_line,&ptr,10);
                if (ptr == in_line || val.den.i <= 0)
                    msg("%s, line %i : invalid denominator",
                        fname,line);
                in_line = ptr;
            }
            else 
            {
                /* default denominator = 1 */
                in_line--;
                (val.den.i = 1);
            }
        }

        if (type == 0)
            *rat_in = val;
        else if (type == 1)
            I_RAT_add(val,*rat_in,rat_in);
        else
            *(int_in+j) = val.num;
    }

    /* 
     * change by M.S. 1.7.92:
     * the following three lines lead to the rejection of
     * "(..) 1 1  # statistical part\n"
     * As for inequality-lines, the comment sign # should also be allowed
     * for point-lines.
     *
     *  for (ch = getc(fp); ch != '\n' ; ch = getc(fp))
     *    if (ch != ' ') 
     *      msg("%sline : %i invalid format of input file ","",line);
     */
    ch = *(in_line++);
    while (ch != '\n'  && ch != '#') 
    {
        if (ch >= '0' && ch <= '9')
            msg("%s, line %i : dimension error",fname,line);
        /* too many numbers on the line */
        else if (ch != ' ' && ch != '\t') 
            msg("%s, line %i : invalid format of input file ",
                fname,line);
        ch = *(in_line++);
    }
    
    return(1);
}