--- a +++ b/feasible_joint_stiffness/lrslib-062/lrslib.c @@ -0,0 +1,5701 @@ +/* lrslib.c library code for lrs */ + +/* modified by Gary Roumanis for multithread plrs compatability */ +/* truncate needs mod to supress last pivot */ +/* need to add a test for non-degenerate pivot step in reverse I guess */ +/* Copyright: David Avis 2005,2011 avis@cs.mcgill.ca */ + +/* This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. + */ + + + +#include <stdio.h> +#include <string.h> +#include "lrslib.h" + +/* Globals; these need to be here, rather than lrslib.h, so they are + not multiply defined. */ + +FILE *lrs_cfp; /* output file for checkpoint information */ +FILE *lrs_ifp; /* input file pointer */ +FILE *lrs_ofp; /* output file pointer */ + + +static unsigned long dict_count, dict_limit, cache_tries, cache_misses; + +/* Variables and functions global to this file only */ +static long lrs_checkpoint_seconds = 0; + +static long lrs_global_count = 0; /* Track how many lrs_dat records are + allocated */ + +static lrs_dat_p *lrs_global_list[MAX_LRS_GLOBALS + 1]; + +static lrs_dic *new_lrs_dic (long m, long d, long m_A); + + +static void cache_dict (lrs_dic ** D_p, lrs_dat * global, long i, long j); +static long check_cache (lrs_dic ** D_p, lrs_dat * global, long *i_p, long *j_p); +static void save_basis (lrs_dic * D, lrs_dat * Q); + +static void lrs_dump_state (); + +static void pushQ (lrs_dat * global, long m, long d, long m_A); + +#ifdef TIMES +static void ptimes (); +static double get_time(); +#endif + + +/*******************************/ +/* signals handling */ +/*******************************/ +#ifdef SIGNALS +static void checkpoint (); +static void die_gracefully (); +static void setup_signals (); +static void timecheck (); +#endif + +/*******************************/ +/* functions for external use */ +/*******************************/ + +/*******************************************************/ +/* lrs_main is driver for lrs.c does H/V enumeration */ +/* showing function calls intended for public use */ +/*******************************************************/ +long +lrs_main (int argc, char *argv[]) + +{ + + lrs_dic *P; /* structure for holding current dictionary and indices */ + lrs_dat *Q; /* structure for holding static problem data */ + + lrs_mp_vector output; /* holds one line of output; ray,vertex,facet,linearity */ + lrs_mp_matrix Lin; /* holds input linearities if any are found */ + long col; /* output column index for dictionary */ + long startcol = 0; + long prune = FALSE; /* if TRUE, getnextbasis will prune tree and backtrack */ + +/* global variables lrs_ifp and lrs_ofp are file pointers for input and output */ +/* they default to stdin and stdout, but may be overidden by command line parms. */ + + +/*************************************************** + Step 0: + Do some global initialization that should only be done once, + no matter how many lrs_dat records are allocated. db + +***************************************************/ + +#ifdef PLRS + if (!lrs_mp_init (ZERO, stdin, stdout)) /* initialize arithmetic */ + exit(1); +#else + if ( !lrs_init ("\n*lrs:")) + return 1; + printf("\n%s",AUTHOR); +#endif + +/*********************************************************************************/ +/* Step 1: Allocate lrs_dat, lrs_dic and set up the problem */ +/*********************************************************************************/ +#ifdef PLRS +Q = lrs_alloc_dat (""); /* allocate and init structure for static problem data */ + + std::ifstream input_file; + input_file.open(argv[0]); /* Open input file */ + plrs_read_dat(Q, input_file); /* read first part of problem data to get dimensions and problem type: H- or V- input representation */ + + P = lrs_alloc_dic (Q); /* allocate and initialize lrs_dic */ + if (P == NULL) + return 1; + plrs_read_dic (P, Q, input_file); /* read remainder of input to setup P and Q */ +#else + Q = lrs_alloc_dat ("LRS globals"); /* allocate and init structure for static problem data */ + + if (Q == NULL) + return 1; + + if (!lrs_read_dat (Q, argc, argv)) /* read first part of problem data to get dimensions */ + return 1; /* and problem type: H- or V- input representation */ + + P = lrs_alloc_dic (Q); /* allocate and initialize lrs_dic */ + if (P == NULL) + return 1; + + if (!lrs_read_dic (P, Q)) /* read remainder of input to setup P and Q */ + return 1; +#endif + + output = lrs_alloc_mp_vector (Q->n); /* output holds one line of output from dictionary */ + + +/*********************************************************************************/ +/* Step 2: Find a starting cobasis from default of specified order */ +/* P is created to hold active dictionary data and may be cached */ +/* Lin is created if necessary to hold linearity space */ +/* Print linearity space if any, and retrieve output from first dict. */ +/*********************************************************************************/ + + if (!lrs_getfirstbasis (&P, Q, &Lin, FALSE)) + return 1; + + /* Pivot to a starting dictionary */ + /* There may have been column redundancy */ + /* If so the linearity space is obtained and redundant */ + /* columns are removed. User can access linearity space */ + /* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ + + + + if (Q->homogeneous && Q->hull) + startcol++; /* col zero not treated as redundant */ + + if(!Q->restart) + for (col = startcol; col < Q->nredundcol; col++) /* print linearity space */ + lrs_printoutput (Q, Lin[col]); /* Array Lin[][] holds the coeffs. */ + + + +/*********************************************************************************/ +/* Step 3: Terminate if lponly option set, otherwise initiate a reverse */ +/* search from the starting dictionary. Get output for each new dict. */ +/*********************************************************************************/ + + + + /* We initiate reverse search from this dictionary */ + /* getting new dictionaries until the search is complete */ + /* User can access each output line from output which is */ + /* vertex/ray/facet from the lrs_mp_vector output */ + /* prune is TRUE if tree should be pruned at current node */ + prune=lrs_checkbound(P,Q); + do + { + +//2015.6.5 after maxcobases reached, generate subtrees that have not been enumerated + + if ((Q->maxcobases > 0) && (Q->count[2] >=Q->maxcobases)) + { + if(!lrs_leaf(P,Q)) + /* do not return cobases of a leaf */ + lrs_printcobasis(P,Q,ZERO); + + prune=TRUE; + + } // if Q-> maxcobases... + + for (col = 0; col <= P->d; col++) /* print output vertex/ray if any */ + if (lrs_getsolution (P, Q, output, col)) + lrs_printoutput (Q, output); + + }while (!Q->lponly && lrs_getnextbasis (&P, Q, prune)); // do ... + + if (Q->lponly) + lrs_lpoutput(P,Q,output); + else + lrs_printtotals (P, Q); /* print final totals, including estimates */ + + lrs_clear_mp_vector(output, Q->n); + +/* 2015.9.16 fix memory leaks on Gcd Lcm Lin */ + if(Q->nredundcol > 0) + lrs_clear_mp_matrix(Lin,Q->nredundcol,Q->n); + if(Q->runs > 0) + { + free(Q->isave); + free(Q->jsave); + } + long savem=P->m; /* need this to clear Q*/ + lrs_free_dic (P,Q); /* deallocate lrs_dic */ + Q->m=savem; + + lrs_free_dat (Q); /* deallocate lrs_dat */ + +#ifndef PLRS + lrs_close ("lrs:"); +#endif + + return 0; +} +/*********************************************/ +/* end of model test program for lrs library */ +/*********************************************/ + + + + +/***********************************/ +/* PLRS */ +/***********************************/ + +#ifdef PLRS + +void plrs_read_dat (lrs_dat * Q, std::ifstream &input_file) +{ + + string line; + bool begin = false; + + if(input_file.is_open()){ + while(input_file.good()){ + getline(input_file, line); + + if(line.find("*") == 0){ + //Ignore lines starting with * + }else if (line.find("H-representation") != string::npos){ + Q->hull = FALSE; + }else if(line.find("hull")!= string::npos || line.find("V-representation")!= string::npos){ + Q->hull = TRUE; + Q->polytope = TRUE; + }else if(line.find("digits")!= string::npos){ + long dec_digits; + istringstream ss(line); + if(!(ss>>dec_digits) && !lrs_set_digits(dec_digits)){ + printf("\nError reading digits data!\n"); + exit(1); + } + }else if(line.find("nonnegative")!= string::npos){ + Q->nonnegative = TRUE; + }else if(line.find("linearity") != string::npos){ + //Remove the following characters + char chars[] = "linearity"; + for(unsigned int i = 0; i < sizeof(chars); ++i){ + line.erase(remove(line.begin(), line.end(), chars[i]), line.end()); + } + + plrs_readlinearity (Q, line); + }else if(line.find("begin")!= string::npos){ + begin = true; + break; + + + }else{ + //Q->name = line.c_str(); + } + } + + if(Q->hull) + Q->getvolume=TRUE; + + if(!begin){ + printf("\nNo begin line!\n"); + fprintf(lrs_ofp,"\nNo begin line!\n"); + exit(1); + } + + + getline(input_file, line); + istringstream ss(line); + string type; + + + if(!(ss >> Q->m >> Q->n >> type)){ + printf("\nNo data in file!\n"); + exit(1); + } + + if(!type.find("integer") && !type.find("rational")){ + printf("\nData type must be integer or rational!\n"); + exit(1); + } + + }else{ + printf("\nError reading input file!\n"); + exit(1); + } + + + if (Q->m == 0) + { + printf("\nNo input given!\n"); + exit(1); + } + /* inputd may be reduced in preprocessing of linearities and redund cols */ +} + +/* read constraint matrix and set up problem and dictionary */ +void plrs_read_dic (lrs_dic * P, lrs_dat * Q, std::ifstream &input_file) +{ + + lrs_mp Temp, mpone; + lrs_mp_vector oD; /* Denom for objective function */ + + long i, j; + string line; + + + /* assign local variables to structures */ + + lrs_mp_matrix A; + lrs_mp_vector Gcd, Lcm; + long hull = Q->hull; + long m, d; + + lrs_alloc_mp(Temp); lrs_alloc_mp(mpone); + A = P->A; + m = Q->m; + d = Q->inputd; + + Gcd = Q->Gcd; + Lcm = Q->Lcm; + + oD = lrs_alloc_mp_vector (d); + + + itomp (ONE, mpone); + itomp (ONE, A[0][0]); + itomp (ONE, Lcm[0]); + itomp (ONE, Gcd[0]); + + + + for (i = 1; i <= m; i++) /* read in input matrix row by row */ + { + + itomp (ONE, Lcm[i]); /* Lcm of denominators */ + itomp (ZERO, Gcd[i]); /* Gcd of numerators */ + + if(!input_file.good()){ + printf("\nInput data incorrectly formatted\n"); + exit(1); + } + +/* allow embedded CRs in multiline input for matrix rows */ +/* there must be an easier way .... but this seems to work */ + j=hull; + while (j <= d) /* hull data copied to cols 1..d */ + { + if(!input_file.good()){ + printf("\nInput incorrectly formatted\n"); + exit(1); + } + + getline(input_file, line); + istringstream ss(line); + const char* ptr1; + int string_length; + string_length=1; + while ((j<=d) && (string_length !=0)) + { + string rat; + ss>>rat; + ptr1=rat.c_str(); + string_length=strlen(ptr1); + if (string_length!=0) + { + if (plrs_readrat (A[i][j], A[0][j], ptr1)) + lcm (Lcm[i], A[0][j]); /* update lcm of denominators */ + copy (Temp, A[i][j]); + gcd (Gcd[i], Temp); /* update gcd of numerators */ + j++; + } + } + ss.clear(); + } + + + + if (hull) + { + itomp (ZERO, A[i][0]); /*for hull, we have to append an extra column of zeroes */ + if (!one (A[i][1]) || !one (A[0][1])) /* all rows must have a one in column one */ + Q->polytope = FALSE; + } + + if (!zero (A[i][hull])) /* for H-rep, are zero in column 0 */ + Q->homogeneous = FALSE; /* for V-rep, all zero in column 1 */ + + + storesign (Gcd[i], POS); + storesign (Lcm[i], POS); + + if (mp_greater (Gcd[i], mpone) || mp_greater (Lcm[i], mpone)) + for (j = 0; j <= d; j++) + { + divint (A[i][j], Gcd[i], Temp); /*reduce numerators by Gcd */ + mulint (Lcm[i], Temp, Temp); /*remove denominators */ + divint (Temp, A[0][j], A[i][j]); /*reduce by former denominator */ + } + } + + + + /* 2010.4.26 patch */ + if(Q->nonnegative) /* set up Gcd and Lcm for nonexistent nongative inequalities */ + for (i=m+1;i<=m+d;i++) + { + itomp (ONE, Lcm[i]); + itomp (ONE, Gcd[i]); + } + + + //Make new output node for nonfatal option errors + //Make stream to collect prat / pmp data + stringstream out_stream; + + if (Q->homogeneous && Q->verbose) + { + out_stream<<"*Input is homogeneous, column 1 not treated as redundant"<<endl; + } + + + while(input_file.good()){ + getline(input_file, line); + if(line.find("*") == 0){ + //Ignore lines starting with * + + }else if(line.find("startingcobasis") != string::npos){ + if(Q->nonnegative){ + out_stream<<"*Starting cobasis incompatible with nonegative option:skipped"<<endl; + }else{ + + Q->givenstart = TRUE; + istringstream ss(line); + //Trim first word + string str; + ss >>str; + //make string out of facts + stringstream facets; + facets << ss.rdbuf(); + + //Readfacets + plrs_readfacets(Q, Q->inequality,facets.str()); + + } + + }else if(line.find("restart") != string::npos){ + + Q->restart = TRUE; + istringstream ss(line); + //Trim first word + string str; + ss >>str; + //Pipe restart data from string stream + if(Q->voronoi){ + if(!(ss>>Q->count[1]>>Q->count[0]>>Q->count[2]>>P->depth)){ + printf("\nError reading restart data!\n"); + exit(1); + } + + }else if(hull){ + if(!(ss>>Q->count[0]>>Q->count[2]>>P->depth)){ + printf("\nError reading restart data!\n"); + exit(1); + } + }else{ + if(!(ss>>Q->count[1]>>Q->count[0]>>Q->count[2]>>P->depth)){ + printf("\nError reading restart data!\n"); + exit(1); + } + } + //Store starting counts to calculate totals + for (int i = 0; i<5; i++){ + Q->startcount[i] = Q->count[i]; + } + + //Make string out of facets + stringstream facets; + facets << ss.rdbuf(); + plrs_readfacets(Q,Q->facet,facets.str()); + + }else if(line.find("geometric") != string::npos){ + if(hull && !Q->voronoi) + out_stream<<"*Geometric option for H-representation or voronoi only, skipped"<<endl; + else + Q->geometric = TRUE; + + }else if(line.find("allbases") != string::npos){ + Q->allbases = TRUE; + + }else if(line.find("countonly") != string::npos){ + Q->countonly = TRUE; + + }else if(line.find("incidence") != string::npos){ + Q->incidence = TRUE; + + }else if(line.find("#incidence") != string::npos){ + Q->printcobasis = TRUE; + + }else if(line.find("printcobasis") != string::npos){ + istringstream ss(line); + //Trim first word + string str; + ss >>str; + if(!(ss>>Q->frequency)) + Q->frequency = 0; + Q->printcobasis = TRUE; + + }else if(line.find("printslack") != string::npos){ + Q->printslack = TRUE; + + }else if(line.find("maxdepth") != string::npos){ + istringstream ss(line); + //Trim first word + string str; + ss >>str; + if(!(ss>>Q->maxdepth)){ + Q->maxdepth = 1; + } + + + }else if(line.find("maxoutput") != string::npos){ + istringstream ss(line); + //Trim first word + string str; + ss >>str; + if(!(ss>>Q->maxoutput)){ + Q->maxoutput = 100; + } + + }else if(line.find("maxcobases") != string::npos){ + istringstream ss(line); + //Trim first word + string str; + ss >>str; + if(!(ss>>Q->maxcobases)){ + Q->maxcobases = 1000; + } + + }else if(line.find("lponly")!= string::npos){ + printf("\nError: lponly option not supported - use lrs!\n"); + exit(1); + + }else if(line.find("mindepth") != string::npos){ + istringstream ss(line); + //Trim first word + string str; + ss >>str; + if(!(ss>>Q->mindepth)){ + Q->mindepth = 0; + } + + }else if(line.find("estimates") != string::npos){ + istringstream ss(line); + //Trim first word + string str; + ss >>str; + if (!(ss>>Q->runs)){ + Q->runs=1; + } + + }else if(line.find("subtreesize") != string::npos){ + istringstream ss(line); + //Trim first word + string str; + ss >>str; + if (!(ss>>Q->subtreesize)){ + Q->subtreesize=MAXD; + } + + + }else if(line.find("truncate") != string::npos){ + if(!hull) + Q->truncate = TRUE; + else + out_stream<<"*Truncate option for H-representation only, skipped"<<endl; + + }else if(line.find("verbose") != string::npos){ + Q->verbose = TRUE; + + }else if(line.find("bound") != string::npos){ + istringstream ss(line); + //Trim first word + string str; + ss>>str; + //get rational number + ss>>str; + plrs_readrat(Q->boundn, Q->boundd, str.c_str()); + Q->bound = TRUE; + + }else if(line.find("nonnegative") != string::npos){ + out_stream<<"*Nonnegative option must come before begin line, skipped"<<endl; + }else if(line.find("seed") != string::npos){ + istringstream ss(line); + if(!(ss>>Q->seed)){ + Q->seed = 3142; + } + + + }else if(line.find("voronoi") != string::npos || line.find("Voronoi") != string::npos){ + if(!hull) + out_stream<<"*voronoi requires V-representation - option skipped"<<endl; + else{ + Q->voronoi = TRUE; + Q->polytope = FALSE; + } + } + } + + if (Q->restart && Q->maxcobases > 0) //2015.4.3 adjust for restart + Q->maxcobases = Q->maxcobases + Q->count[2]; + + if (Q->incidence) + { + Q->printcobasis = TRUE; + /* 2010.5.7 No need to reset this, as it may have been set by printcobasis */ + /* Q->frequency = ZERO; */ + } + + lrs_clear_mp(Temp); lrs_clear_mp(mpone); + lrs_clear_mp_vector (oD,d); + + //post output in a nonblocking manner (a consumer thread will manage output) + post_output("options warning", out_stream.str().c_str()); + +} + + +/* read and check facet list for obvious errors during start/restart */ +/* this must be done after linearity option is processed!! */ +void plrs_readfacets (lrs_dat * Q, long facet[], string facets) +{ + long i, j; + /* assign local variables to structures */ + long m, d; + long *linearity = Q->linearity; + m = Q->m; + d = Q->inputd; + + istringstream ss(facets); + for (j = Q->nlinearity; j < d; j++) /* note we place these after the linearity indices */ + { + if(!(ss>>facet[j])) + { + return; + } + + + //fprintf (lrs_ofp, " %ld", facet[j]); + /* 2010.4.26 nonnegative option needs larger range of indices */ + if(Q->nonnegative) + if (facet[j] < 1 || facet[j] > m+d) + { + printf("\nStart/Restart cobasic indices must be in range 1 .. %ld \n",m+d); + exit(1); + } + if(!Q->nonnegative) + if (facet[j] < 1 || facet[j] > m) + { + printf("\nStart/Restart cobasic indices must be in range 1 .. %ld \n",m); + exit(1); + } + for (i = 0; i < Q->nlinearity; i++) + if (linearity[i] == facet[j]) + { + printf("\nStart/Restart cobasic indices should not include linearities\n");; + exit(1); + } + /* bug fix 2011.8.1 reported by Steven Wu*/ + for (i = Q->nlinearity; i < j; i++) + /* end bug fix 2011.8.1 */ + + if (facet[i] == facet[j]) + { + printf("\nStart/Restart cobasic indices must be distinct\n"); + exit(1); + } + } +} /* end of readfacets */ + +extern int PLRS_DEBUG; +#endif + + + + + +/*******************************************************/ +/* redund_main is driver for redund.c, removes all */ +/* redundant rows from an H or V-representation */ +/* showing function calls intended for public use */ +/*******************************************************/ +long +redund_main (int argc, char *argv[]) + +{ + lrs_mp_matrix Ain; /* holds a copy of the input matrix to output at the end */ + + long *redineq; /* redineq[i]=0 if ineq i non-red,1 if red,2 linearity */ + long ineq; /* input inequality number of current index */ + + lrs_dic *P; /* structure for holding current dictionary and indices */ + lrs_dat *Q; /* structure for holding static problem data */ + + lrs_mp_matrix Lin; /* holds input linearities if any are found */ + + long i, j, d, m; + long nlinearity; /* number of linearities in input file */ + long nredund; /* number of redundant rows in input file */ + long lastdv; + long debug; + long index; /* basic index for redundancy test */ + +/* global variables lrs_ifp and lrs_ofp are file pointers for input and output */ +/* they default to stdin and stdout, but may be overidden by command line parms. */ +/* Lin is global 2-d array for linearity space if it is found (redund columns) */ + + lrs_ifp = stdin; + lrs_ofp = stdout; +/*************************************************** + Step 0: + Do some global initialization that should only be done once, + no matter how many lrs_dat records are allocated. db + +***************************************************/ + + if ( !lrs_init ("\n*redund:")) + return 1; + + printf ("\n"); + printf (AUTHOR); + +/*********************************************************************************/ +/* Step 1: Allocate lrs_dat, lrs_dic and set up the problem */ +/*********************************************************************************/ + + Q = lrs_alloc_dat ("LRS globals"); /* allocate and init structure for static problem data */ + + if (Q == NULL) + return 1; + + if (!lrs_read_dat (Q, argc, argv)) /* read first part of problem data to get dimensions */ + return 1; /* and problem type: H- or V- input representation */ + + P = lrs_alloc_dic (Q); /* allocate and initialize lrs_dic */ + if (P == NULL) + return 1; + + if (!lrs_read_dic (P, Q)) /* read remainder of input to setup P and Q */ + return 1; + +/* if non-negative flag is set, non-negative constraints are not input */ +/* explicitly, and are not checked for redundancy */ + + m = P->m_A; /* number of rows of A matrix */ + d = P->d; + debug = Q->debug; + + redineq = (long *) calloc ((m + 1), sizeof (long)); + Ain = lrs_alloc_mp_matrix (m, d); /* make a copy of A matrix for output later */ + + for (i = 1; i <= m; i++) + { + for (j = 0; j <= d; j++) + copy (Ain[i][j], P->A[i][j]); + + if (debug) + lrs_printrow ("*", Q, Ain[i], d); + } + +/*********************************************************************************/ +/* Step 2: Find a starting cobasis from default of specified order */ +/* Lin is created if necessary to hold linearity space */ +/*********************************************************************************/ + + if (!lrs_getfirstbasis (&P, Q, &Lin, TRUE)) + return 1; + + /* Pivot to a starting dictionary */ + /* There may have been column redundancy */ + /* If so the linearity space is obtained and redundant */ + /* columns are removed. User can access linearity space */ + /* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ + + +/*********************************************************************************/ +/* Step 3: Test each row of the dictionary to see if it is redundant */ +/*********************************************************************************/ + +/* note some of these may have been changed in getting initial dictionary */ + m = P->m_A; + d = P->d; + nlinearity = Q->nlinearity; + lastdv = Q->lastdv; + if (debug) + fprintf (lrs_ofp, "\ncheckindex m=%ld, n=%ld, nlinearity=%ld lastdv=%ld", m,d,nlinearity,lastdv); + +/* linearities are not considered for redundancy */ + + for (i = 0; i < nlinearity; i++) + redineq[Q->linearity[i]] = 2L; + +/* rows 0..lastdv are cost, decision variables, or linearities */ +/* other rows need to be tested */ + + for (index = lastdv + 1; index <= m + d; index++) + { + ineq = Q->inequality[index - lastdv]; /* the input inequality number corr. to this index */ + + redineq[ineq] = checkindex (P, Q, index); + if (debug) + fprintf (lrs_ofp, "\ncheck index=%ld, inequality=%ld, redineq=%ld", index, ineq, redineq[ineq]); + if (redineq[ineq] == ONE) + { + fprintf (lrs_ofp, "\n*row %ld was redundant and removed", ineq); + fflush (lrs_ofp); + } + + } /* end for index ..... */ + + if (debug) + { + fprintf (lrs_ofp, "\n*redineq:"); + for (i = 1; i <= m; i++) + fprintf (lrs_ofp, " %ld", redineq[i]); + } + + if (!Q->hull) + fprintf (lrs_ofp, "\nH-representation"); + else + fprintf (lrs_ofp, "\nV-representation"); + +/* linearities will be printed first in output */ + + if (nlinearity > 0) + { + fprintf (lrs_ofp, "\nlinearity %ld", nlinearity); + for (i = 1; i <= nlinearity; i++) + fprintf (lrs_ofp, " %ld", i); + + } + nredund = nlinearity; /* count number of non-redundant inequalities */ + for (i = 1; i <= m; i++) + if (redineq[i] == 0) + nredund++; + fprintf (lrs_ofp, "\nbegin"); + fprintf (lrs_ofp, "\n%ld %ld rational", nredund, Q->n); + +/* print the linearities first */ + + for (i = 0; i < nlinearity; i++) + lrs_printrow ("", Q, Ain[Q->linearity[i]], Q->inputd); + + for (i = 1; i <= m; i++) + if (redineq[i] == 0) + lrs_printrow ("", Q, Ain[i], Q->inputd); + fprintf (lrs_ofp, "\nend"); + fprintf (lrs_ofp, "\n*Input had %ld rows and %ld columns", m, Q->n); + fprintf (lrs_ofp, ": %ld row(s) redundant", m - nredund); + +/* 2015.9.9 fix memory leak on Gcd Lcm */ + long savem=P->m; /* need this to clear Q*/ + lrs_free_dic (P,Q); /* deallocate lrs_dic */ + Q->m=savem; + + lrs_free_dat (Q); /* deallocate lrs_dat */ + + + lrs_close ("redund:"); + + return 0; +} +/*********************************************/ +/* end of redund.c */ +/*********************************************/ +/*******************/ +/* lrs_printoutput */ +/*******************/ +void +lrs_printoutput (lrs_dat * Q, lrs_mp_vector output) +{ + +if (Q->countonly) + return; + +#ifdef PLRS + //Make new output node + char *type=NULL; + + //Make stream to collect prat / pmp data + stringstream ss; + + + if (Q->hull || zero (output[0])){ + /*non vertex */ + type = "ray"; + for (int i = 0; i < Q->n; i++) + ss<<pmp ("", output[i]); + }else{ + type = "vertex"; + /* vertex */ + ss<<" 1 "; + for (int i = 1; i < Q->n; i++) + ss<<prat ("", output[i], output[0]); + } + //post output in a nonblocking manner (a consumer thread will manage output) + post_output(type, ss.str().c_str()); +#else + long i; + + fprintf (lrs_ofp, "\n"); + + if (Q->hull || zero (output[0])) /*non vertex */ + { + for (i = 0; i < Q->n; i++) + pmp ("", output[i]); + + } + else + { /* vertex */ + fprintf (lrs_ofp, " 1 "); + for (i = 1; i < Q->n; i++) + prat ("", output[i], output[0]); + } + fflush(lrs_ofp); +#endif + +} +/**************************/ +/* end of lrs_printoutput */ +/**************************/ + +/****************/ +/* lrs_lpoutput */ +/****************/ +void lrs_lpoutput(lrs_dic * P,lrs_dat * Q, lrs_mp_vector output) +{ + + +#ifndef LRS_QUIET + lrs_mp Temp1, Temp2; + long i; + + lrs_alloc_mp (Temp1); + lrs_alloc_mp (Temp2); + + fprintf (lrs_ofp, "\n*LP solution only requested"); + prat ("\n\n*Objective function has value ", P->objnum, P->objden); + + fprintf (lrs_ofp, "\n\n*Primal: "); + for (i = 1; i < Q->n; i++) + { + fprintf(lrs_ofp,"x_%ld=",i); + prat ("", output[i], output[0]); + } + + if(Q->nlinearity > 0) + fprintf (lrs_ofp, "\n\n*Linearities in input file - partial dual solution only"); + fprintf (lrs_ofp, "\n\n*Dual: "); + + for (i = 0; i < P->d; i++) + { + fprintf(lrs_ofp,"y_%ld=",Q->inequality[P->C[i]-Q->lastdv]); + changesign(P->A[0][P->Col[i]]); + mulint(Q->Lcm[P->Col[i]],P->A[0][P->Col[i]],Temp1); + mulint(Q->Gcd[P->Col[i]],P->det,Temp2); + prat("",Temp1,Temp2); + changesign(P->A[0][P->Col[i]]); + } + fprintf (lrs_ofp, "\n"); + lrs_clear_mp (Temp1); + lrs_clear_mp (Temp2); +#endif + } +/***********************/ +/* end of lrs_lpoutput */ +/***********************/ +void +lrs_printrow (char name[], lrs_dat * Q, lrs_mp_vector output, long rowd) +/* print a row of A matrix in output in "original" form */ +/* rowd+1 is the dimension of output vector */ +/* if input is H-rep. output[0] contains the RHS */ +/* if input is V-rep. vertices are scaled by 1/output[1] */ +{ + long i; + + fprintf (lrs_ofp, "\n%s", name); + if (!Q->hull) /* input was inequalities, print directly */ + + { + + for (i = 0; i <= rowd; i++) + pmp ("", output[i]); + return; + } + +/* input was vertex/ray */ + + if (zero (output[1])) /*non-vertex */ + { + for (i = 1; i <= rowd; i++) + pmp ("", output[i]); + + } + else + { /* vertex */ + fprintf (lrs_ofp, " 1 "); + for (i = 2; i <= rowd; i++) + prat ("", output[i], output[1]); + } + + return; + +} /* end of lrs_printrow */ + +long +lrs_getsolution (lrs_dic * P, lrs_dat * Q, lrs_mp_vector output, long col) + /* check if column indexed by col in this dictionary */ + /* contains output */ + /* col=0 for vertex 1....d for ray/facet */ +{ + + + long j; /* cobasic index */ + + lrs_mp_matrix A = P->A; + long *Row = P->Row; + + if (col == ZERO) /* check for lexmin vertex */ + return lrs_getvertex (P, Q, output); + +/* check for rays: negative in row 0 , positive if lponly */ + + if (Q->lponly) + { + if (!positive (A[0][col])) + return FALSE; + } + + else if (!negative (A[0][col])) + return FALSE; + +/* and non-negative for all basic non decision variables */ + + j = Q->lastdv + 1; + while (j <= P->m && !negative (A[Row[j]][col])) + j++; + + if (j <= P->m) + return FALSE; + + if (Q->geometric || Q->allbases || lexmin (P, Q, col) || Q->lponly) + + return lrs_getray (P, Q, col, Q->n, output); + + return FALSE; /* no more output in this dictionary */ + +} /* end of lrs_getsolution */ + + +long +lrs_init (char *name) /* returns TRUE if successful, else FALSE */ +{ + + printf ("%s", name); + printf (TITLE); + printf (VERSION); + printf ("("); + printf (BIT); + printf (","); + printf (ARITH); + if (!lrs_mp_init (ZERO, stdin, stdout)) /* initialize arithmetic */ + return FALSE; + printf (")"); + + + lrs_global_count = 0; + lrs_checkpoint_seconds = 0; +#ifdef SIGNALS + setup_signals (); +#endif + return TRUE; +} + +void +lrs_close (char *name) +{ + + fprintf (lrs_ofp, "\n*%s", name); + fprintf (lrs_ofp, TITLE); + fprintf (lrs_ofp, VERSION); + fprintf (lrs_ofp, "("); + fprintf (lrs_ofp, BIT); + fprintf (lrs_ofp, ","); + fprintf (lrs_ofp, ARITH); + fprintf (lrs_ofp, ")"); + +#ifdef MP + fprintf (lrs_ofp, " max digits=%ld/%ld", DIG2DEC (lrs_record_digits), DIG2DEC (lrs_digits)); +#endif + +#ifdef TIMES + ptimes (); +#endif + + fprintf (lrs_ofp, "\n"); + fclose (lrs_ifp); + if (lrs_ofp != stdout) + fclose (lrs_ofp); +} + +/***********************************/ +/* allocate and initialize lrs_dat */ +/***********************************/ +lrs_dat * +lrs_alloc_dat (const char *name) +{ + lrs_dat *Q; + long i; + + + if (lrs_global_count >= MAX_LRS_GLOBALS) + { + fprintf (stderr, + "Fatal: Attempt to allocate more than %ld global data blocks\n", MAX_LRS_GLOBALS); + exit (1); + + } + + Q = (lrs_dat *) malloc (sizeof (lrs_dat)); + if (Q == NULL) + return Q; /* failure to allocate */ + + lrs_global_list[lrs_global_count] = Q; + Q->id = lrs_global_count; + lrs_global_count++; + Q->name=(char *) CALLOC ((unsigned) strlen(name)+1, sizeof (char)); + strcpy(Q->name,name); + +/* initialize variables */ + Q->m = 0L; + Q->n = 0L; + Q->inputd = 0L; + Q->deepest = 0L; + Q->nlinearity = 0L; + Q->nredundcol = 0L; + Q->runs = 0L; + Q->subtreesize=MAXD; + Q->seed = 1234L; + Q->totalnodes = 0L; + for (i = 0; i < 10; i++) + { + Q->count[i] = 0L; + Q->cest[i] = 0.0; + if(i < 5) + Q->startcount[i] = 0L; + } + Q->count[2] = 1L; /* basis counter */ + Q->startcount[2] = 0L; /* starting basis counter */ +/* initialize flags */ + Q->allbases = FALSE; + Q->bound = FALSE; /* upper/lower bound on objective function given */ + Q->countonly = FALSE; /* produce the usual output */ + Q->debug = FALSE; + Q->frequency = 0L; + Q->dualdeg = FALSE; /* TRUE if dual degenerate starting dictionary */ + Q->geometric = FALSE; + Q->getvolume = FALSE; + Q->homogeneous = TRUE; + Q->polytope = FALSE; + Q->hull = FALSE; + Q->incidence = FALSE; + Q->lponly = FALSE; + Q->maxdepth = MAXD; + Q->mindepth = -MAXD; + Q->maxoutput = 0L; + Q->maxcobases = 0L; /* after maxcobases have been found unexplored subtrees reported */ + Q->nash = FALSE; + Q->nonnegative = FALSE; + Q->printcobasis = FALSE; + Q->printslack = FALSE; + Q->truncate = FALSE; /* truncate tree when moving from opt vertex */ + Q->verbose=FALSE; + Q->voronoi = FALSE; + Q->maximize = FALSE; /*flag for LP maximization */ + Q->minimize = FALSE; /*flag for LP minimization */ + Q->restart = FALSE; /* TRUE if restarting from some cobasis */ + Q->givenstart = FALSE; /* TRUE if a starting cobasis is given */ + Q->strace = -1L; /* turn on debug at basis # strace */ + Q->etrace = -1L; /* turn off debug at basis # etrace */ + + Q->saved_flag = 0; /* no cobasis saved initially, db */ + lrs_alloc_mp (Q->Nvolume); + lrs_alloc_mp (Q->Dvolume); + lrs_alloc_mp (Q->sumdet); + lrs_alloc_mp (Q->saved_det); + lrs_alloc_mp (Q->boundn); + lrs_alloc_mp (Q->boundd); + itomp (ZERO, Q->Nvolume); + itomp (ONE, Q->Dvolume); + itomp (ZERO, Q->sumdet); +/* 2012.6.1 */ + Q->unbounded = FALSE; + + return Q; +} /* end of allocate and initialize lrs_dat */ + +/*******************************/ +/* lrs_read_dat */ +/*******************************/ +long +lrs_read_dat (lrs_dat * Q, int argc, char *argv[]) +{ + char name[100]; + long dec_digits = 0; + long infile=0; /*input file number to open if any */ + long firstline = TRUE; /*flag for picking off name at line 1 */ + + int c; /* for fgetc */ + + + if(argc > 1 ) + infile=1; + if(Q->nash && argc == 2) /* open second nash input file */ + infile=2; + + if (infile > 0) /* command line argument overides stdin */ + { + if ((lrs_ifp = fopen (argv[infile], "r")) == NULL) + { + printf ("\nBad input file name\n"); + return (FALSE); + } + else + { if (infile==1) + printf ("\n*Input taken from file %s", argv[infile]); + } + } + + /* command line argument overides stdout */ + if ((!Q->nash && argc == 3) || (Q->nash && argc == 4)) + { + if ((lrs_ofp = fopen (argv[argc-1], "w")) == NULL) + { + printf ("\nBad output file name\n"); + return (FALSE); + } + else + printf ("\n*Output sent to file %s\n", argv[argc-1]); + } + + +/* process input file */ + if( fscanf (lrs_ifp, "%s", name) == EOF) + { + fprintf (lrs_ofp, "\nNo begin line"); + return (FALSE); + } + + while (strcmp (name, "begin") != 0) /*skip until "begin" found processing options */ + { + if (strncmp (name, "*", 1) == 0) /* skip any line beginning with * */ + { + c = name[0]; + while (c != EOF && c != '\n') + c = fgetc (lrs_ifp); + } + + else if (strcmp (name, "H-representation") == 0) + Q->hull = FALSE; + else if ((strcmp (name, "hull") == 0) || (strcmp (name, "V-representation") == 0)) + { + Q->hull = TRUE; + Q->polytope = TRUE; /* will be updated as input read */ + } + else if (strcmp (name, "digits") == 0) + { + if (fscanf (lrs_ifp, "%ld", &dec_digits) == EOF) + { + fprintf (lrs_ofp, "\nNo begin line"); + return (FALSE); + } + if (!lrs_set_digits(dec_digits)) + return (FALSE); + } + else if (strcmp (name, "linearity") == 0) + { + if (!readlinearity (Q)) + return FALSE; + } + else if (strcmp (name, "nonnegative") == 0) + { + if(Q->nash) + fprintf (lrs_ofp, "\nNash incompatibile with nonnegative option - skipped"); + else + Q->nonnegative = TRUE; + } + else if (firstline) + { + stringcpy (Q->fname, name); + fprintf (lrs_ofp, "\n%s", Q->fname); + firstline = FALSE; + } + + if (fscanf (lrs_ifp, "%s", name) == EOF) + { + fprintf (lrs_ofp, "\nNo begin line"); + return (FALSE); + } + + } /* end of while */ + + + if (fscanf (lrs_ifp, "%ld %ld %s", &Q->m, &Q->n, name) == EOF) + { + fprintf (lrs_ofp, "\nNo data in file"); + return (FALSE); + } + if (strcmp (name, "integer") != 0 && strcmp (name, "rational") != 0) + { + fprintf (lrs_ofp, "\nData type must be integer of rational"); + return (FALSE); + } + + + if (Q->m == 0) + { + fprintf (lrs_ofp, "\nNo input given"); /* program dies ungracefully */ + return (FALSE); + } + + + + /* inputd may be reduced in preprocessing of linearities and redund cols */ + + return TRUE; +} /* end of lrs_read_dat */ + +/****************************/ +/* set up lrs_dic structure */ +/****************************/ +long +lrs_read_dic (lrs_dic * P, lrs_dat * Q) +/* read constraint matrix and set up problem and dictionary */ + +{ + lrs_mp Temp,Tempn,Tempd, mpone, mpten; + lrs_mp_vector oD; /* Denom for objective function */ + + long i, j; + char name[100]; + int c; /* fgetc actually returns an int. db */ + +/* assign local variables to structures */ + + lrs_mp_matrix A; + lrs_mp_vector Gcd, Lcm; + long hull = Q->hull; + long m, d; + long dualperturb=FALSE; /* dualperturb=TRUE: objective function perturbed */ + + lrs_alloc_mp(Temp); lrs_alloc_mp(mpone); + lrs_alloc_mp(Tempn); lrs_alloc_mp(Tempd); lrs_alloc_mp(mpten); + A = P->A; + m = Q->m; + d = Q->inputd; + Gcd = Q->Gcd; + Lcm = Q->Lcm; + + oD = lrs_alloc_mp_vector (d); + + + + + itomp (ONE, mpone); + itomp(10L,mpten); + itomp (ONE, A[0][0]); + itomp (ONE, Lcm[0]); + itomp (ONE, Gcd[0]); + + for (i = 1; i <= m; i++) /* read in input matrix row by row */ + { + itomp (ONE, Lcm[i]); /* Lcm of denominators */ + itomp (ZERO, Gcd[i]); /* Gcd of numerators */ + for (j = hull; j <= d; j++) /* hull data copied to cols 1..d */ + { + if (readrat (A[i][j], A[0][j])) + lcm (Lcm[i], A[0][j]); /* update lcm of denominators */ + copy (Temp, A[i][j]); + gcd (Gcd[i], Temp); /* update gcd of numerators */ + } + + if (hull) + { + itomp (ZERO, A[i][0]); /*for hull, we have to append an extra column of zeroes */ + if (!one (A[i][1]) || !one (A[0][1])) /* all rows must have a one in column one */ + Q->polytope = FALSE; + } + if (!zero (A[i][hull])) /* for H-rep, are zero in column 0 */ + Q->homogeneous = FALSE; /* for V-rep, all zero in column 1 */ + + + storesign (Gcd[i], POS); + storesign (Lcm[i], POS); + if (mp_greater (Gcd[i], mpone) || mp_greater (Lcm[i], mpone)) + for (j = 0; j <= d; j++) + { + exactdivint (A[i][j], Gcd[i], Temp); /*reduce numerators by Gcd */ + mulint (Lcm[i], Temp, Temp); /*remove denominators */ + exactdivint (Temp, A[0][j], A[i][j]); /*reduce by former denominator */ + } + + } /* end of for i= */ + +/* 2010.4.26 patch */ + if(Q->nonnegative) /* set up Gcd and Lcm for nonexistent nongative inequalities */ + for (i=m+1;i<=m+d;i++) + { itomp (ONE, Lcm[i]); + itomp (ONE, Gcd[i]); + } + + if (Q->homogeneous && Q->verbose) + { + fprintf (lrs_ofp, "\n*Input is homogeneous, column 1 not treated as redundant"); + } + + +/* read in flags */ + while (fscanf (lrs_ifp, "%s", name) != EOF) + { + if (strncmp (name, "*", 1) == 0) /* skip any line beginning with * */ + { + c = name[0]; + while (c != EOF && c != '\n') + c = fgetc (lrs_ifp); + } + + + if (strcmp (name, "checkpoint") == 0) + { + long seconds; + + if(fscanf (lrs_ifp, "%ld", &seconds) == EOF) + { + fprintf (lrs_ofp, "\nInvalid checkpoint option"); + return (FALSE); + } + +#ifdef SIGNALS + if (seconds > 0) + { + lrs_checkpoint_seconds = seconds; + errcheck ("signal", signal (SIGALRM, timecheck)); + alarm (lrs_checkpoint_seconds); + } +#endif + } + + if (strcmp (name, "debug") == 0) + { + Q->etrace =0; + if(fscanf (lrs_ifp, "%ld %ld", &Q->strace, &Q->etrace)==EOF) + Q->strace =0; + fprintf (lrs_ofp, "\n*%s from B#%ld to B#%ld", name, Q->strace, Q->etrace); + Q->verbose=TRUE; + if (Q->strace <= 1) + Q->debug = TRUE; + } + if (strcmp (name, "startingcobasis") == 0) + { + if(Q->nonnegative) + fprintf (lrs_ofp, "\n*startingcobasis incompatible with nonnegative option:skipped"); + else + { + fprintf (lrs_ofp, "\n*startingcobasis"); + Q->givenstart = TRUE; + if (!readfacets (Q, Q->inequality)) + return FALSE; + } + } + + if (strcmp (name, "restart") == 0) + { + Q->restart = TRUE; + if(Q->voronoi) + { + if(fscanf (lrs_ifp, "%ld %ld %ld %ld", &Q->count[1], &Q->count[0], &Q->count[2], &P->depth)==EOF) + return FALSE; + fprintf (lrs_ofp, "\n*%s V#%ld R#%ld B#%ld h=%ld data points", name, Q->count[1], Q->count[0], Q->count[2], P->depth); + } + else if(hull) + { + if( fscanf (lrs_ifp, "%ld %ld %ld", &Q->count[0], &Q->count[2], &P->depth)==EOF) + fprintf (lrs_ofp, "\n*%s F#%ld B#%ld h=%ld vertices/rays", name, Q->count[0], Q->count[2], P->depth); + } + else + { + if(fscanf (lrs_ifp, "%ld %ld %ld %ld", &Q->count[1], &Q->count[0], &Q->count[2], &P->depth)==EOF) + return FALSE; + fprintf (lrs_ofp, "\n*%s V#%ld R#%ld B#%ld h=%ld facets", name, Q->count[1], Q->count[0], Q->count[2], P->depth); + } + if (!readfacets (Q, Q->facet)) + return FALSE; + } /* end of restart */ + +/* The next flag request a LP solution only */ + if (strcmp (name, "lponly") == 0) + { + if (Q->hull) + fprintf (lrs_ofp, "\n*lponly option not valid for V-representation-skipped"); + else + Q->lponly = TRUE; + } + + +/* The LP will be solved after initialization to get starting vertex */ +/* Used also with lponly flag */ + if (strcmp (name, "maximize") == 0 || strcmp (name, "minimize") == 0) + { + if (Q->hull) + fprintf (lrs_ofp, "\n*%s option not valid for V-representation-skipped", name); + else + { + { + if (strcmp (name, "maximize") == 0) + Q->maximize = TRUE; + else + Q->minimize = TRUE; + } + fprintf (lrs_ofp,"\n*%s", name); + + if(dualperturb) /* apply a perturbation to objective function */ + { + fprintf (lrs_ofp, " - Objective function perturbed"); + copy(Temp,mpten); + for (j = 0; j <= 10; j++) + mulint(mpten,Temp,Temp); + } + + fprintf (lrs_ofp, ": "); + + for (j = 0; j <= d; j++) + { + if (readrat (A[0][j], oD[j]) || dualperturb ) + { + if(dualperturb && j > 0 && j < d ) + { + if (Q->maximize) + linrat(A[0][j], oD[j],ONE,mpone,Temp,ONE,Tempn,Tempd); + else + linrat(A[0][j], oD[j],ONE,mpone,Temp,-1L,Tempn,Tempd); + + copy(A[0][j],Tempn); + copy(oD[j],Tempd); + mulint(mpten,Temp,Temp); + } + + reduce (A[0][j], oD[j]); + lcm (Q->Lcm[0], oD[j]); /* update lcm of denominators */ + } + prat ("", A[0][j], oD[j]); + if (!Q->maximize) + changesign (A[0][j]); + } + storesign (Q->Lcm[0], POS); + if (mp_greater (Q->Lcm[0], mpone)) + for (j = 0; j <= d; j++) + { + mulint (Q->Lcm[0], A[0][j], A[0][j]); /*remove denominators */ + copy (Temp, A[0][j]); + exactdivint (Temp, oD[j], A[0][j]); + } + if (Q->debug) + printA (P, Q); + } + } /* end of LP setup */ + if (strcmp (name, "volume") == 0) + { + fprintf (lrs_ofp, "\n*%s", name); + Q->getvolume = TRUE; + } + if (strcmp (name, "geometric") == 0) + { + fprintf (lrs_ofp, "\n*%s", name); + if (hull & !Q->voronoi) + fprintf (lrs_ofp, " - option for H-representation or voronoi only, skipped"); + else + Q->geometric = TRUE; + } + if (strcmp (name, "allbases") == 0) + { + fprintf (lrs_ofp, "\n*%s", name); + Q->allbases = TRUE; + } + + if (strcmp (name, "countonly") == 0) + { + fprintf (lrs_ofp, "\n*%s", name); + Q->countonly = TRUE; + } + if (strcmp (name, "dualperturb") == 0) + { + dualperturb = TRUE; + } + + if (strcmp (name, "incidence") == 0) + { + fprintf (lrs_ofp, "\n*%s", name); + Q->incidence = TRUE; + } + + if (strcmp (name, "#incidence") == 0) /* number of incident inequalities only */ + { + Q->printcobasis = TRUE; + } + + if (strcmp (name, "printcobasis") == 0) + { + if(fscanf (lrs_ifp, "%ld", &Q->frequency)==EOF) +/*2010.7.7 set default to zero = print only when outputting vertex/ray/facet */ + Q->frequency=0; + fprintf (lrs_ofp, "\n*%s", name); + if (Q->frequency > 0) + fprintf(lrs_ofp," %ld", Q->frequency); + Q->printcobasis = TRUE; + } + + if (strcmp (name, "printslack") == 0) + { + Q->printslack = TRUE; + } + + if (strcmp (name, "cache") == 0) + { + if(fscanf (lrs_ifp, "%ld", &dict_limit)==EOF) + dict_limit=1; + fprintf (lrs_ofp, "\n*cache %ld", dict_limit); + if (dict_limit < 1) + dict_limit = 1; + } + if (strcmp (name, "linearity") == 0) + { + if (!readlinearity (Q)) + return FALSE; + } + + if (strcmp (name, "maxdepth") == 0) + { + if(fscanf (lrs_ifp, "%ld", &Q->maxdepth)==EOF) + Q->maxdepth=MAXD; + fprintf (lrs_ofp, "\n*%s %ld", name, Q->maxdepth); + } + + if (strcmp (name, "maxoutput") == 0) + { + if(fscanf (lrs_ifp, "%ld", &Q->maxoutput)==EOF) + Q->maxoutput = 100; + fprintf (lrs_ofp, "\n*%s %ld", name, Q->maxoutput); + } + + if (strcmp (name, "maxcobases") == 0) + { + if(fscanf (lrs_ifp, "%ld", &Q->maxcobases)==EOF) + Q->maxcobases = 1000; + fprintf (lrs_ofp, "\n*%s %ld", name, Q->maxcobases); + } + + if (strcmp (name, "mindepth") == 0) + { + if( fscanf (lrs_ifp, "%ld", &Q->mindepth)==EOF) + Q->mindepth = 0; + fprintf (lrs_ofp, "\n*%s %ld", name, Q->mindepth); + } + + if (strcmp (name, "truncate") == 0) + { + fprintf (lrs_ofp, "\n*%s", name); + if (!hull) + Q->truncate = TRUE; + else + fprintf (lrs_ofp, " - option for H-representation only, skipped"); + } + + + if (strcmp (name, "verbose") == 0) + Q->verbose = TRUE; + + if (strcmp (name, "bound") == 0) + { + readrat(Q->boundn,Q->boundd); + Q->bound = TRUE; + } + + if (strcmp (name, "nonnegative") == 0) + { + fprintf (lrs_ofp, "\n*%s", name); + fprintf (lrs_ofp, " - option must come before begin line - skipped"); + } + + if (strcmp (name, "seed") == 0) + { + if(fscanf (lrs_ifp, "%ld", &Q->seed)==EOF) + Q->seed = 3142; + fprintf (lrs_ofp, "\n*seed= %ld ", Q->seed); + } + + if (strcmp (name, "estimates") == 0) + { + if(fscanf (lrs_ifp, "%ld", &Q->runs)==EOF) + Q->runs=1; + fprintf (lrs_ofp, "\n*%ld %s", Q->runs, name); + } + +// 2015.2.9 Estimates will continue until estimate is less than subtree size + if (strcmp (name, "subtreesize") == 0) + { + if(fscanf (lrs_ifp, "%ld", &Q->subtreesize)==EOF) + Q->subtreesize=MAXD; + fprintf (lrs_ofp, "\n*%s %ld", name, Q->subtreesize); + } + + + + if ((strcmp (name, "voronoi") == 0) || (strcmp (name, "Voronoi") == 0)) + { + if (!hull) + fprintf (lrs_ofp, "\n*voronoi requires V-representation - option skipped"); + else + { + Q->voronoi = TRUE; + Q->polytope = FALSE; + } + } + + } /* end of while for reading flags */ + + if (Q->polytope) + Q->getvolume = TRUE; /* might as well get volume, it doesn't cost much */ + + if (Q->bound && Q->maximize) + prat("\n*Lower bound on objective function:",Q->boundn,Q->boundd); + + if (Q->bound && Q->minimize) + prat("\n*Upper bound on objective function:",Q->boundn,Q->boundd); + +/* Certain options are incompatible, this is fixed here */ + + if (Q->restart) + Q->getvolume = FALSE; /* otherwise incorrect volume reported */ + + if (Q->restart && Q->maxcobases > 0) //2015.4.3 adjust for restart + Q->maxcobases = Q->maxcobases + Q->count[2]; + + if (Q->incidence) + { + Q->printcobasis = TRUE; +/* 2010.5.7 No need to reset this, as it may have been set by printcobasis */ +/* Q->frequency = ZERO; */ + } + + if (Q->debug) + { + printA (P, Q); + fprintf (lrs_ofp, "\nexiting lrs_read_dic"); + } + lrs_clear_mp(Temp); lrs_clear_mp(mpone); + lrs_clear_mp(Tempn); lrs_clear_mp(Tempd); lrs_clear_mp(mpten); + lrs_clear_mp_vector (oD,d); + return TRUE; + +} + + /* end of if(voronoi) */ + +/* In lrs_getfirstbasis and lrs_getnextbasis we use D instead of P */ +/* since the dictionary P may change, ie. &P in calling routine */ + +#define D (*D_p) + +long +lrs_getfirstbasis (lrs_dic ** D_p, lrs_dat * Q, lrs_mp_matrix * Lin, long no_output) +/* gets first basis, FALSE if none */ +/* P may get changed if lin. space Lin found */ +/* no_output is TRUE supresses output headers */ +{ + lrs_mp scale, Temp; + + long i, j, k; + +/* assign local variables to structures */ + + lrs_mp_matrix A; + long *B, *C, *Col; + long *inequality; + long *linearity; + long hull = Q->hull; + long m, d, lastdv, nlinearity, nredundcol; + + lrs_alloc_mp(Temp); lrs_alloc_mp(scale); + + if (Q->lponly) + no_output = TRUE; + m = D->m; + d = D->d; + + + + lastdv = Q->lastdv; + + nredundcol = 0L; /* will be set after getabasis */ + nlinearity = Q->nlinearity; /* may be reset if new linearity read or in getabasis*/ + linearity = Q->linearity; + + + + A = D->A; + B = D->B; + C = D->C; + Col = D->Col; + inequality = Q->inequality; + + + if (Q->nlinearity > 0 && Q->nonnegative) + { + fprintf (lrs_ofp, "\n*linearity and nonnegative options incompatible"); + fprintf (lrs_ofp, " - all linearities are skipped"); + fprintf (lrs_ofp, "\n*add nonnegative constraints explicitly and "); + fprintf (lrs_ofp, " remove nonnegative option"); + } + + if (Q->nlinearity && Q->voronoi){ + fprintf (lrs_ofp, "\n*linearity and Voronoi options set - results unpredictable"); + } + + if (Q->lponly && !Q->maximize && !Q->minimize) + fprintf (lrs_ofp, "\n*LP has no objective function given - assuming all zero"); + + + if (Q->runs > 0) /* arrays for estimator */ + { + Q->isave = (long *) CALLOC ((unsigned) (m * d), sizeof (long)); + Q->jsave = (long *) CALLOC ((unsigned) (m * d), sizeof (long)); + } +/* default is to look for starting cobasis using linearies first, then */ +/* filling in from last rows of input as necessary */ +/* linearity array is assumed sorted here */ +/* note if restart/given start inequality indices already in place */ +/* from nlinearity..d-1 */ + for (i = 0; i < nlinearity; i++) /* put linearities first in the order */ + inequality[i] = linearity[i]; + + k = 0; /* index for linearity array */ + + if (Q->givenstart) + k = d; + else + k = nlinearity; + for (i = m; i >= 1; i--) + { + j = 0; + while (j < k && inequality[j] != i) + j++; /* see if i is in inequality */ + if (j == k) + inequality[k++] = i; + } + #ifndef PLRS + if (Q->debug) + { + fprintf (lrs_ofp, "\n*Starting cobasis uses input row order"); + for (i = 0; i < m; i++) + fprintf (lrs_ofp, " %ld", inequality[i]); + + } + #endif +/* for voronoi convert to h-description using the transform */ +/* a_0 .. a_d-1 -> (a_0^2 + ... a_d-1 ^2)-2a_0x_0-...-2a_d-1x_d-1 + x_d >= 0 */ +/* note constant term is stored in column d, and column d-1 is all ones */ +/* the other coefficients are multiplied by -2 and shifted one to the right */ + if (Q->debug) + printA (D, Q); + if (Q->voronoi) + { + Q->hull = FALSE; + hull = FALSE; + for (i = 1; i <= m; i++) + { + if (zero (A[i][1])) + { + printf("\nWith voronoi option column one must be all one\n"); + return (FALSE); + } + copy (scale, A[i][1]); /*adjust for scaling to integers of rationals */ + itomp (ZERO, A[i][0]); + for (j = 2; j <= d; j++) /* transform each input row */ + { + copy (Temp, A[i][j]); + mulint (A[i][j], Temp, Temp); + linint (A[i][0], ONE, Temp, ONE); + linint (A[i][j - 1], ZERO, A[i][j], -TWO); + mulint (scale, A[i][j - 1], A[i][j - 1]); + } /* end of for (j=1;..) */ + copy (A[i][d], scale); + mulint (scale, A[i][d], A[i][d]); + }/* end of for (i=1;..) */ + #ifndef PLRS + if (Q->debug) + printA (D, Q); + #endif + } /* end of if(voronoi) */ + if (!Q->maximize && !Q->minimize) + for (j = 0; j <= d; j++) + itomp (ZERO, A[0][j]); + +/* Now we pivot to standard form, and then find a primal feasible basis */ +/* Note these steps MUST be done, even if restarting, in order to get */ +/* the same index/inequality correspondance we had for the original prob. */ +/* The inequality array is used to give the insertion order */ +/* and is defaulted to the last d rows when givenstart=FALSE */ + + if(Q->nonnegative) + { +/* no need for initial pivots here, labelling already done */ + Q->lastdv = d; + Q->nredundcol = 0; + } + else + { + if (!getabasis (D, Q, inequality)) + return FALSE; +/* bug fix 2009.12.2 */ + nlinearity=Q->nlinearity; /*may have been reset if some lins are redundant*/ + } + + + +#ifndef PLRS + if(Q->debug) + { + + fprintf(lrs_ofp,"\nafter getabasis"); + printA(D, Q); + + } +#endif + nredundcol = Q->nredundcol; + lastdv = Q->lastdv; + d = D->d; + + + +/********************************************************************/ +/* now we start printing the output file unless no output requested */ +/********************************************************************/ + + if (!no_output || Q->debug) + { + + + + if (Q->voronoi){ + #ifndef PLRS + fprintf (lrs_ofp, "\n*Voronoi Diagram: Voronoi vertices and rays are output"); + #else + char *type = "header"; + char *data = "*Voronoi Diagram: Voronoi vertices and rays are output"; + //post output in a nonblocking manner (a consumer thread will manage output) + post_output(type,data); + #endif + } + if (hull){ + #ifndef PLRS + fprintf (lrs_ofp, "\nH-representation"); + #else + char *type = "header"; + char *data = "H-representation"; + //post output in a nonblocking manner (a consumer thread will manage output) + post_output(type, data); + #endif + } + else{ + #ifndef PLRS + fprintf (lrs_ofp, "\nV-representation"); + #else + char *type = "header"; + char *data = "V-representation"; + //post output in a nonblocking manner (a consumer thread will manage output) + post_output(type,data); + #endif + } + + +/* Print linearity space */ +/* Don't print linearity if first column zero in hull computation */ + + if (hull && Q->homogeneous) + k = 1; /* 0 normally, 1 for homogeneous case */ + else + k = 0; + + if (nredundcol > k) + { + #ifndef PLRS + fprintf (lrs_ofp, "\nlinearity %ld ", nredundcol - k); /*adjust nredundcol for homog. */ + #else + stringstream ss; + char *type = "header"; + ss<<"linearity "<<(nredundcol -k); + #endif + for (i = 1; i <= nredundcol - k; i++){ + #ifndef PLRS + fprintf (lrs_ofp, " %ld", i); + #else + ss<<" "<<i; + #endif + } + #ifdef PLRS + //post output in a nonblocking manner (a consumer thread will manage output) + post_output(type, ss.str().c_str()); + #endif + } /* end print of linearity space */ + + #ifndef PLRS + fprintf (lrs_ofp, "\nbegin"); + fprintf (lrs_ofp, "\n***** %ld rational", Q->n); + #else + char *type = "header"; + stringstream ss; + ss<<"begin"<<endl<<"***** "<<Q->n<<" rational"; + post_output(type, ss.str().c_str()); + #endif + } + + /* end of if !no_output ....... */ + + +/* Reset up the inequality array to remember which index is which input inequality */ +/* inequality[B[i]-lastdv] is row number of the inequality with index B[i] */ +/* inequality[C[i]-lastdv] is row number of the inequality with index C[i] */ + + for (i = 1; i <= m; i++) + inequality[i] = i; + if (nlinearity > 0) /* some cobasic indices will be removed */ + { + for (i = 0; i < nlinearity; i++) /* remove input linearity indices */ + inequality[linearity[i]] = 0; + k = 1; /* counter for linearities */ + for (i = 1; i <= m - nlinearity; i++) + { + while (k <= m && inequality[k] == 0) + k++; /* skip zeroes in corr. to linearity */ + inequality[i] = inequality[k++]; + } + } + /* end if linearity */ + + #ifndef PLRS + if (Q->debug) + { + fprintf (lrs_ofp, "\ninequality array initialization:"); + for (i = 1; i <= m - nlinearity; i++) + fprintf (lrs_ofp, " %ld", inequality[i]); + + } + #endif + + + + + if (nredundcol > 0) + { + const unsigned int Qn = Q->n; + *Lin = lrs_alloc_mp_matrix (nredundcol, Qn); + + for (i = 0; i < nredundcol; i++) + { + + + if (!(Q->homogeneous && Q->hull && i == 0)) /* skip redund col 1 for homog. hull */ + { + + lrs_getray (D, Q, Col[0], D->C[0] + i - hull, (*Lin)[i]); /* adjust index for deletions */ + } + + if (!removecobasicindex (D, Q, 0L)) + { + lrs_clear_mp_matrix (*Lin, nredundcol, Qn); + return FALSE; + } + } + + + } /* end if nredundcol > 0 */ + + + + if (Q->lponly || Q->nash ){ + if (Q->verbose) + { + fprintf (lrs_ofp, "\nNumber of pivots for starting dictionary: %ld",Q->count[3]); + if(Q->lponly) + printA (D, Q); + } + } + +/* Do dual pivots to get primal feasibility */ + if (!primalfeasible (D, Q)) + { +#ifndef LRS_QUIET + fprintf (lrs_ofp, "\nNo feasible solution\n"); +#endif + if (Q->nash && Q->verbose ) + { + fprintf (lrs_ofp, "\nNumber of pivots for feasible solution: %ld",Q->count[3]); + fprintf (lrs_ofp, " - No feasible solution"); + } + return FALSE; + } + + if (Q->lponly || Q->nash ) + if (Q->verbose) + { + fprintf (lrs_ofp, "\nNumber of pivots for feasible solution: %ld",Q->count[3]); + if(Q->lponly) + printA (D, Q); + } + + + +/* Now solve LP if objective function was given */ + if (Q->maximize || Q->minimize) + { + Q->unbounded = !lrs_solvelp (D, Q, Q->maximize); + if (Q->lponly) + { + + #ifndef PLRS + if (Q->verbose) + { + fprintf (lrs_ofp, "\nNumber of pivots for optimum solution: %ld",Q->count[3]); + printA (D, Q); + } + #endif + lrs_clear_mp(Temp); lrs_clear_mp(scale); + return TRUE; + } + + else /* check to see if objective is dual degenerate */ + { + j = 1; + while (j <= d && !zero (A[0][j])) + j++; + if (j <= d) + Q->dualdeg = TRUE; + } + } + else +/* re-initialize cost row to -det */ + { + for (j = 1; j <= d; j++) + { + copy (A[0][j], D->det); + storesign (A[0][j], NEG); + } + + itomp (ZERO, A[0][0]); /* zero optimum objective value */ + } + + +/* reindex basis to 0..m if necessary */ +/* we use the fact that cobases are sorted by index value */ +#ifndef PLRS + if (Q->debug) + printA (D, Q); +#endif + + + + while (C[0] <= m) + { + i = C[0]; + j = inequality[B[i] - lastdv]; + inequality[B[i] - lastdv] = inequality[C[0] - lastdv]; + inequality[C[0] - lastdv] = j; + C[0] = B[i]; + B[i] = i; + reorder1 (C, Col, ZERO, d); + } + + + +#ifndef PLRS + if (Q->debug) + { + fprintf (lrs_ofp, "\n*Inequality numbers for indices %ld .. %ld : ", lastdv + 1, m + d); + for (i = 1; i <= m - nlinearity; i++) + fprintf (lrs_ofp, " %ld ", inequality[i]); + printA (D, Q); + } +#endif + + + + if (Q->restart) + { + #ifndef PLRS + if (Q->debug) + fprintf (lrs_ofp, "\nPivoting to restart co-basis"); + #endif + if (!restartpivots (D, Q)) + return FALSE; + D->lexflag = lexmin (D, Q, ZERO); /* see if lexmin basis */ + #ifndef PLRS + if (Q->debug) + printA (D, Q); + #endif + } + +/* Check to see if necessary to resize */ + if (Q->inputd > d) + *D_p = resize (D, Q); + + lrs_clear_mp(Temp); lrs_clear_mp(scale); + return TRUE; +} +/********* end of lrs_getfirstbasis ***************/ + + +/*****************************************/ +/* getnextbasis in reverse search order */ +/*****************************************/ + + +long +lrs_getnextbasis (lrs_dic ** D_p, lrs_dat * Q, long backtrack) + /* gets next reverse search tree basis, FALSE if none */ + /* switches to estimator if maxdepth set */ + /* backtrack TRUE means backtrack from here */ + +{ + /* assign local variables to structures */ + long i = 0L, j = 0L; + long m = D->m; + long d = D->d; + long saveflag; + long cob_est=0; /* estimated number of cobases in subtree from current node */ + + + if (backtrack && D->depth == 0) + return FALSE; /* cannot backtrack from root */ + + if (Q->maxoutput > 0 && Q->count[0]+Q->count[1]-Q->hull >= Q->maxoutput) + return FALSE; /* output limit reached */ + + while ((j < d) || (D->B[m] != m)) /*main while loop for getnextbasis */ + { + if (D->depth >= Q->maxdepth) + { + if (Q->runs > 0 && !backtrack ) /*get an estimate of remaining tree */ + { + +//2015.2.9 do iterative estimation backtracking when estimate is small + + saveflag=Q->printcobasis; + Q->printcobasis=FALSE; + cob_est=lrs_estimate (D, Q); + Q->printcobasis=saveflag; + if(cob_est <= Q->subtreesize) /* stop iterative estimation */ + { + if(cob_est > 0) /* when zero we are at a leaf */ + { lrs_printcobasis(D,Q,ZERO); +#ifndef PLRS + fprintf(lrs_ofp," cob_est= %ld *subtree",cob_est); +#else + if (PLRS_DEBUG) + { + stringstream ss; + ss<< "cob_est= " << cob_est << " *subtree" << endl; + post_output("debug", ss.str().c_str()); + } +#endif + } + backtrack=TRUE; + } + + } + else // either not estimating or we are backtracking + + if (!backtrack && !Q->printcobasis) + if(!lrs_leaf(D,Q)) /* 2015.6.5 cobasis returned if not a leaf */ + lrs_printcobasis(D,Q,ZERO); + + backtrack = TRUE; + + + if (Q->maxdepth == 0 && cob_est <= Q->subtreesize) /* root estimate only */ + return FALSE; /* no nextbasis */ + } // if (D->depth >= Q->maxdepth) + + +/* if ( Q->truncate && negative(D->A[0][0]))*/ /* truncate when moving from opt. vertex */ +/* backtrack = TRUE; 2011.7.14 */ + + if (backtrack) /* go back to prev. dictionary, restore i,j */ + { + backtrack = FALSE; + + if (check_cache (D_p, Q, &i, &j)) + { + if (Q->debug) + fprintf (lrs_ofp, "\n Cached Dict. restored to depth %ld\n", D->depth); + } + else + { + D->depth--; + selectpivot (D, Q, &i, &j); + pivot (D, Q, i, j); + update (D, Q, &i, &j); /*Update B,C,i,j */ + } + + if (Q->debug) + { + fprintf (lrs_ofp, "\n Backtrack Pivot: indices i=%ld j=%ld depth=%ld", i, j, D->depth); + printA (D, Q); + }; + + j++; /* go to next column */ + } /* end of if backtrack */ + + if (D->depth < Q->mindepth) + break; + + /* try to go down tree */ + +/* 2011.7.14 patch */ + while ((j < d) && (!reverse (D, Q, &i, j) || (Q->truncate && Q->minratio[D->m]==1))) + j++; + if (j == d ) + backtrack = TRUE; + else + /*reverse pivot found */ + { + cache_dict (D_p, Q, i, j); + /* Note that the next two lines must come _after_ the + call to cache_dict */ + + D->depth++; + if (D->depth > Q->deepest) + Q->deepest++; + + pivot (D, Q, i, j); + update (D, Q, &i, &j); /*Update B,C,i,j */ + + D->lexflag = lexmin (D, Q, ZERO); /* see if lexmin basis */ + Q->count[2]++; + Q->totalnodes++; + + save_basis (*D_p, Q); + if (Q->strace == Q->count[2]) + Q->debug = TRUE; + if (Q->etrace == Q->count[2]) + Q->debug = FALSE; + return TRUE; /*return new dictionary */ + } + + + } /* end of main while loop for getnextbasis */ + return FALSE; /* done, no more bases */ +} /*end of lrs_getnextbasis */ + +/*************************************/ +/* print out one line of output file */ +/*************************************/ +long +lrs_getvertex (lrs_dic * P, lrs_dat * Q, lrs_mp_vector output) +/*Print out current vertex if it is lexmin and return it in output */ +/* return FALSE if no output generated */ +{ + lrs_mp_matrix A = P->A; + + long i; + long ind; /* output index */ + long ired; /* counts number of redundant columns */ +/* assign local variables to structures */ + long *redundcol = Q->redundcol; + long *count = Q->count; + long *B = P->B; + long *Row = P->Row; + + long lastdv = Q->lastdv; + + long hull; + long lexflag; + + + + hull = Q->hull; + lexflag = P->lexflag; + if (lexflag || Q->allbases) + ++(Q->count[1]); +#ifdef PLRS + // do not print vertex again in PLRS at root + if(P->depth == Q->mindepth ){ + return FALSE; + } + +#else + //If we are at minimum depth and not at root do not print vertex + if(P->depth == Q->mindepth && Q->mindepth != 0){ + return FALSE; + } +#endif + + if (Q->debug) + printA (P, Q); + + linint (Q->sumdet, 1, P->det, 1); + if (Q->getvolume) + { + updatevolume (P, Q); + if(Q->verbose) /* this will print out a triangulation */ + lrs_printcobasis(P,Q,ZERO); + } + + + /*print cobasis if printcobasis=TRUE and count[2] a multiple of frequency */ + /* or for lexmin basis, except origin for hull computation - ugly! */ + + if (Q->printcobasis) + if ((lexflag && !hull) || ((Q->frequency > 0) && (count[2] == (count[2] / Q->frequency) * Q->frequency))) + if(P->depth != Q->mindepth || Q->mindepth == 0) //Don't print cobasis if this is a restart cobasis + lrs_printcobasis(P,Q,ZERO); + + if (hull) + return FALSE; /* skip printing the origin */ + + if (!lexflag && !Q->allbases && !Q->lponly) /* not lexmin, and not printing forced */ + return FALSE; + + + /* copy column 0 to output */ + + i = 1; + ired = 0; + copy (output[0], P->det); + + for (ind = 1; ind < Q->n; ind++) /* extract solution */ + + if ((ired < Q->nredundcol) && (redundcol[ired] == ind)) + /* column was deleted as redundant */ + { + itomp (ZERO, output[ind]); + ired++; + } + else + /* column not deleted as redundant */ + { + getnextoutput (P, Q, i, ZERO, output[ind]); + i++; + } + + reducearray (output, Q->n); + if (lexflag && one(output[0])) + ++Q->count[4]; /* integer vertex */ + + +/* uncomment to print nonzero basic variables + + printf("\n nonzero basis: vars"); + for(i=1;i<=lastdv; i++) + { + if ( !zero(A[Row[i]][0]) ) + printf(" %ld ",B[i]); + } +*/ + +/* printslack inequality indices */ + + if (Q->printslack) + { + fprintf(lrs_ofp,"\nslack ineq:"); + for(i=lastdv+1;i<=P->m; i++) + { + if (!zero(A[Row[i]][0])) + fprintf(lrs_ofp," %ld ", Q->inequality[B[i]-lastdv]); + } + } + + + + return TRUE; +} /* end of lrs_getvertex */ + +long +lrs_getray (lrs_dic * P, lrs_dat * Q, long col, long redcol, lrs_mp_vector output) +/*Print out solution in col and return it in output */ +/*redcol =n for ray/facet 0..n-1 for linearity column */ +/*hull=1 implies facets will be recovered */ +/* return FALSE if no output generated in column col */ +{ + long i; + long ind; /* output index */ + long ired; /* counts number of redundant columns */ +/* assign local variables to structures */ + long *redundcol = Q->redundcol; + long *count = Q->count; + long hull = Q->hull; + long n = Q->n; + + long *B = P->B; + long *Row = P->Row; + long lastdv = Q->lastdv; + +#ifdef PLRS + // do not print vertex again in PLRS at root + if(P->depth == Q->mindepth ){ + return FALSE; + } + +#else + //If we are at minimum depth and not at origin do not print ray + if(P->depth == Q->mindepth && Q->mindepth != 0){ + return FALSE; + } +#endif + + + if (Q->debug) + { + printA (P, Q); + for (i = 0; i < Q->nredundcol; i++) + fprintf (lrs_ofp, " %ld", redundcol[i]); + fflush(lrs_ofp); + } + + if (redcol == n) + { + ++count[0]; + if (Q->printcobasis) + if(P->depth != Q->mindepth || Q->mindepth == 0) //Don't print cobasis if this is a restart cobasis + lrs_printcobasis(P,Q,col); + + } + + i = 1; + ired = 0; + + for (ind = 0; ind < n; ind++) /* print solution */ + { + if (ind == 0 && !hull) /* must have a ray, set first column to zero */ + itomp (ZERO, output[0]); + + else if ((ired < Q->nredundcol) && (redundcol[ired] == ind)) + /* column was deleted as redundant */ + { + if (redcol == ind) /* true for linearity on this cobasic index */ + /* we print reduced determinant instead of zero */ + copy (output[ind], P->det); + else + itomp (ZERO, output[ind]); + ired++; + } + else + /* column not deleted as redundant */ + { + getnextoutput (P, Q, i, col, output[ind]); + i++; + } + + } + reducearray (output, n); +/* printslack for rays: 2006.10.10 */ +/* printslack inequality indices */ + + if (Q->printslack) + { + fprintf(lrs_ofp,"\nslack ineq:"); + for(i=lastdv+1;i<=P->m; i++) + { + if (!zero(P->A[Row[i]][col])) + fprintf(lrs_ofp," %ld ", Q->inequality[B[i]-lastdv]); + } + } + + + + return TRUE; +} /* end of lrs_getray */ + + +void +getnextoutput (lrs_dic * P, lrs_dat * Q, long i, long col, lrs_mp out) + /* get A[B[i][col] and copy to out */ +{ + long row; + long m = P->m; + long d = P->d; + long lastdv = Q->lastdv; + lrs_mp_matrix A = P->A; + long *B = P->B; + long *Row = P->Row; + long j; + + if (i == d && Q->voronoi) + return; /* skip last column if voronoi set */ + + row = Row[i]; + + if (Q->nonnegative) /* if m+i basic get correct value from dictionary */ + /* the slack for the inequality m-d+i contains decision */ + /* variable x_i. We first see if this is in the basis */ + /* otherwise the value of x_i is zero, except for a ray */ + /* when it is one (det/det) for the actual column it is in */ + { + for (j = lastdv+ 1; j <= m; j++) + { + if ( Q->inequality[B[j]-lastdv] == m-d+i ) + { + copy (out, A[Row[j]][col]); + return; + } + } +/* did not find inequality m-d+i in basis */ + if ( i == col ) + copy(out,P->det); + else + itomp(ZERO,out); + + } + else + copy (out, A[row][col]); + +} /* end of getnextoutput */ + +void +lrs_printcobasis (lrs_dic * P, lrs_dat * Q, long col) +/* col is output column being printed */ +{ + + #ifdef PLRS + long i; + long rflag;/* used to find inequality number for ray column */ + /* assign local variables to structures */ + lrs_mp_matrix A = P->A; + lrs_mp Nvol, Dvol; /* hold rescaled det of current basis */ + long *B = P->B; + long *C = P->C; + long *Col = P->Col; + long *Row = P->Row; + long *inequality = Q->inequality; + long *temparray = Q->temparray; + long *count = Q->count; + long hull = Q->hull; + long d = P->d; + long lastdv = Q->lastdv; + long m=P->m; + long firstime=TRUE; + long nincidence; /* count number of tight inequalities */ + + //Make new output node + char *type = "cobasis"; + //Make stream to collect prat / pmp data + stringstream ss; + + + lrs_alloc_mp(Nvol); lrs_alloc_mp(Dvol); + + if (hull) + ss<<"F#"<<count[0]<<" B#"<<count[2]<<" h="<<P->depth<<" vertices/rays "; + else if (Q->voronoi) + ss<<"V#"<<count[1]<<" R#"<<count[0]<<" B#"<<count[2]<<" h="<<P->depth<<" data points "; + else + ss<<"V#"<<count[1]<<" R#"<<count[0]<<" B#"<<count[2]<<" h="<<P->depth<<" facets "; + + rflag = (-1); + for (i = 0; i < d; i++) + { + temparray[i] = inequality[C[i] - lastdv]; + if (Col[i] == col) + rflag = temparray[i]; /* look for ray index */ + } + for (i = 0; i < d; i++) + reorder (temparray, d); + for (i = 0; i < d; i++) + { + ss<<" "<<temparray[i]; + + /* missing cobasis element for ray */ + if (!(col == ZERO) && (rflag == temparray[i])){ + ss<<"*"; + type = "V cobasis"; + } + + } + + /* get and print incidence information */ + if ( col == 0 ) + nincidence = d; + else + nincidence = d-1; + + for(i=lastdv+1;i<=m;i++) + if ( zero (A[Row[i]][0] )) + if( ( col == ZERO ) || zero (A[Row[i]] [col]) ){ + nincidence++; + if( Q->incidence ){ + if (firstime){ + ss<<" :"; + firstime = FALSE; + } + ss<<inequality[B[i] - lastdv ]; + } + } + + ss<<" I#"<<nincidence; + + ss<<pmp (" det=", P->det); + //fflush (lrs_ofp); + rescaledet (P, Q, Nvol, Dvol); /* scales determinant in case input rational */ + + ss<<prat(" in_det=",Nvol,Dvol); + + //pipe stream into output node + //post output in a nonblocking manner (a consumer thread will manage output) + post_output(type, ss.str().c_str()); + + lrs_clear_mp(Nvol); lrs_clear_mp(Dvol); + + + #else + long i; + long rflag; /* used to find inequality number for ray column */ + /* assign local variables to structures */ + lrs_mp_matrix A = P->A; + lrs_mp Nvol, Dvol; /* hold rescaled det of current basis */ + long *B = P->B; + long *C = P->C; + long *Col = P->Col; + long *Row = P->Row; + long *inequality = Q->inequality; + long *temparray = Q->temparray; + long *count = Q->count; + long hull = Q->hull; + long d = P->d; + long lastdv = Q->lastdv; + long m=P->m; + long firstime=TRUE; + long nincidence; /* count number of tight inequalities */ + + lrs_alloc_mp(Nvol); lrs_alloc_mp(Dvol); + + if (hull) + fprintf (lrs_ofp, "\nF#%ld B#%ld h=%ld vertices/rays ", count[0], count[2], P->depth); + else if (Q->voronoi) + fprintf (lrs_ofp, "\nV#%ld R#%ld B#%ld h=%ld data points ", count[1], count[0], count[2], P->depth); + else + fprintf (lrs_ofp, "\nV#%ld R#%ld B#%ld h=%ld facets ", count[1], count[0], count[2], P->depth); + + rflag = (-1); + for (i = 0; i < d; i++) + { + temparray[i] = inequality[C[i] - lastdv]; + if (Col[i] == col) + rflag = temparray[i]; /* look for ray index */ + } + for (i = 0; i < d; i++) + reorder (temparray, d); + for (i = 0; i < d; i++) + { + fprintf (lrs_ofp, " %ld", temparray[i]); + + if (!(col == ZERO) && (rflag == temparray[i])) /* missing cobasis element for ray */ + fprintf (lrs_ofp, "*"); + + } + + /* get and print incidence information */ + if ( col == 0 ) + nincidence = d; + else + nincidence = d-1; + + for(i=lastdv+1;i<=m;i++) + if ( zero (A[Row[i]][0] )) + if( ( col == ZERO ) || zero (A[Row[i]] [col]) ) + { + nincidence++; + if( Q->incidence ) + { + if (firstime) + { + fprintf (lrs_ofp," :"); + firstime = FALSE; + } + fprintf(lrs_ofp," %ld",inequality[B[i] - lastdv ] ); + } + } + + fprintf(lrs_ofp," I#%ld",nincidence); + + pmp (" det=", P->det); + fflush (lrs_ofp); + rescaledet (P, Q, Nvol, Dvol); /* scales determinant in case input rational */ + prat(" in_det=",Nvol,Dvol); + prat (" z=", P->objnum, P->objden); + lrs_clear_mp(Nvol); lrs_clear_mp(Dvol); + #endif + + +} /* end of lrs_printcobasis */ + +/*********************/ +/* print final totals */ +/*********************/ +void +lrs_printtotals (lrs_dic * P, lrs_dat * Q) +{ + + +#ifdef PLRS + + long *count = Q->count; + long *startcount = Q->startcount; + std::stringstream ss; + + //output node number of basis + ss.str(""); + ss<<count[2] - startcount[2]; + post_output("basis count", ss.str().c_str()); + + if(Q->hull){ + //output node for number of facets + ss.str(""); + ss<<count[0] - startcount[0]; + post_output("facet count", ss.str().c_str()); + + + rescalevolume (P, Q, Q->Nvolume, Q->Dvolume); + + ss.str(""); + string str1 = prat("",Q->Nvolume,Q->Dvolume); +//strip trailing blank introduced by prat +//for some reason next line fails for mp library ! 2014.12.3 so no volume is reported! +#if (defined(LRSLONG) || defined(GMP)) + ss << str1.substr (0,str1.length()-1); +#endif + post_output("volume", ss.str().c_str()); + + + + }else{ + //output node for number of vertices + ss.str(""); + ss<<count[1] - startcount[1]; + post_output("vertex count", ss.str().c_str()); + + //output node for number of rays + ss.str(""); + ss<<count[0] - startcount[0]; + post_output("ray count", ss.str().c_str()); + + //output node for number of integer vertices +/* inaccurate for plrs as restart command does not contain number of integer vertices : an overcount is produced */ + + ss.str(""); + ss<<count[4] - startcount[4]; + post_output("integer vertex count", ss.str().c_str()); + } + +#else + long i; + double x; +/* local assignments */ + double *cest = Q->cest; + long *count = Q->count; + long *inequality = Q->inequality; + long *linearity = Q->linearity; + long *temparray = Q->temparray; + + long *C = P->C; + + long hull = Q->hull; + long homogeneous = Q->homogeneous; + long nlinearity = Q->nlinearity; + long nredundcol = Q->nredundcol; + long d, lastdv; + d = P->d; + lastdv = Q->lastdv; + + fprintf (lrs_ofp, "\nend"); + if (Q->dualdeg) + { + fprintf (lrs_ofp, "\n*Warning: Starting dictionary is dual degenerate"); + fprintf (lrs_ofp, "\n*Complete enumeration may not have been produced"); + if (Q->maximize) + fprintf(lrs_ofp,"\n*Recommendation: Add dualperturb option before maximize in input file\n"); + else + fprintf(lrs_ofp,"\n*Recommendation: Add dualperturb option before minimize in input file\n"); + } + + if (Q->unbounded) + { + fprintf (lrs_ofp, "\n*Warning: Starting dictionary contains rays"); + fprintf (lrs_ofp, "\n*Complete enumeration may not have been produced"); + if (Q->maximize) + fprintf(lrs_ofp,"\n*Recommendation: Change or remove maximize option or add bounds\n"); + else + fprintf(lrs_ofp,"\n*Recommendation: Change or remove minimize option or add bounds\n"); + } + if (Q->truncate) + fprintf(lrs_ofp,"\n*Tree truncated at each new vertex"); + if (Q->maxdepth < MAXD) + fprintf (lrs_ofp, "\n*Tree truncated at depth %ld", Q->maxdepth); + if (Q->maxoutput > 0L) + fprintf (lrs_ofp, "\n*Maximum number of output lines = %ld", Q->maxoutput); + + +#ifdef LRSLONG + fprintf (lrs_ofp, "\n*Caution: no overflow checking with long integer arithemtic"); +#else + if( Q->verbose) + { + fprintf (lrs_ofp, "\n*Sum of det(B)="); + pmp ("", Q->sumdet); + } +#endif + +/* next block with volume rescaling must come before estimates are printed */ + + if (Q->getvolume) + { + rescalevolume (P, Q, Q->Nvolume, Q->Dvolume); + + if (Q->polytope) + prat ("\n*Volume=", Q->Nvolume, Q->Dvolume); + else + prat ("\n*Pseudovolume=", Q->Nvolume, Q->Dvolume); + } + + if (hull) /* output things that are specific to hull computation */ + { + fprintf (lrs_ofp, "\n*Totals: facets=%ld bases=%ld", count[0], count[2]); + + if (nredundcol > homogeneous) /* don't count column 1 as redundant if homogeneous */ + { + fprintf (lrs_ofp, " linearities=%ld", nredundcol - homogeneous); + fprintf (lrs_ofp, " facets+linearities=%ld",nredundcol-homogeneous+count[0]); + } + if(lrs_ofp != stdout) + { + printf ("\n*Totals: facets=%ld bases=%ld", count[0], count[2]); + + if (nredundcol > homogeneous) /* don't count column 1 as redundant if homogeneous */ + { + printf (" linearities=%ld", nredundcol - homogeneous); + printf (" facets+linearities=%ld",nredundcol-homogeneous+count[0]); + } + } + + + if ((cest[2] > 0) || (cest[0] > 0)) + { + fprintf (lrs_ofp, "\n*Estimates: facets=%.0f bases=%.0f", count[0] + cest[0], count[2] + cest[2]); + if (Q->getvolume) + { + rattodouble (Q->Nvolume, Q->Dvolume, &x); + for (i = 2; i < d; i++) + cest[3] = cest[3] / i; /*adjust for dimension */ + fprintf (lrs_ofp, " volume=%g", cest[3] + x); + } + + fprintf (lrs_ofp, "\n*Total number of tree nodes evaluated: %ld", Q->totalnodes); +#ifdef TIMES + fprintf (lrs_ofp, "\n*Estimated total running time=%.1f secs ",(count[2]+cest[2])/Q->totalnodes*get_time () ); +#endif + + } +/* Should not happen since we homogenize */ +/* + if ( Q-> restart || Q->allbases || (count[0] > 1 && !Q->homogeneous && !Q->polytope)) + fprintf (lrs_ofp, "\n*Note! Duplicate facets may be present"); +*/ + + } + else /* output things specific to vertex/ray computation */ + { + fprintf (lrs_ofp, "\n*Totals: vertices=%ld rays=%ld bases=%ld", count[1], count[0], count[2]); + + fprintf (lrs_ofp, " integer_vertices=%ld ",count[4]); + + if (nredundcol > 0) + fprintf (lrs_ofp, " linearities=%ld", nredundcol); + if ( count[0] + nredundcol > 0 ) + { + fprintf (lrs_ofp, " vertices+rays"); + if ( nredundcol > 0 ) + fprintf (lrs_ofp, "+linearities"); + fprintf (lrs_ofp, "=%ld",nredundcol+count[0]+count[1]); + } + + if(lrs_ofp != stdout) + { + printf ("\n*Totals: vertices=%ld rays=%ld bases=%ld", count[1], count[0], count[2]); + + printf (" integer_vertices=%ld ",count[4]); + + if (nredundcol > 0) + printf (" linearities=%ld", nredundcol); + if ( count[0] + nredundcol > 0 ) + { + printf (" vertices+rays"); + if ( nredundcol > 0 ) + printf ("+linearities"); + printf ("=%ld",nredundcol+count[0]+count[1]); + } + } /* end lrs_ofp != stdout */ + + + if ((cest[2] > 0) || (cest[0] > 0)) + { + fprintf (lrs_ofp, "\n*Estimates: vertices=%.0f rays=%.0f", count[1]+cest[1], count[0]+cest[0]); + fprintf (lrs_ofp, " bases=%.0f integer_vertices=%.0f ",count[2]+cest[2], count[4]+cest[4]); + + if (Q->getvolume) + { + rattodouble (Q->Nvolume, Q->Dvolume, &x); + for (i = 2; i <= d-homogeneous; i++) + cest[3] = cest[3] / i; /*adjust for dimension */ + fprintf (lrs_ofp, " pseudovolume=%g", cest[3] + x); + } + fprintf (lrs_ofp, "\n*Total number of tree nodes evaluated: %ld", Q->totalnodes); +#ifdef TIMES + fprintf (lrs_ofp, "\n*Estimated total running time=%.1f secs ",(count[2]+cest[2])/Q->totalnodes*get_time () ); +#endif + } + + if (Q->restart || Q->allbases) /* print warning */ + fprintf (lrs_ofp, "\n*Note! Duplicate vertices/rays may be present"); + + else if ( (count[0] > 1 && !Q->homogeneous)) + fprintf (lrs_ofp, "\n*Note! Duplicate rays may be present"); + + } /* end of output for vertices/rays */ + + fprintf (lrs_ofp, "\n*Dictionary Cache: max size= %ld misses= %ld/%ld Tree Depth= %ld", dict_count, cache_misses, cache_tries, Q->deepest); + if(lrs_ofp != stdout) + printf ("\n*Dictionary Cache: max size= %ld misses= %ld/%ld Tree Depth= %ld", dict_count, cache_misses, cache_tries, Q->deepest); + + if(!Q->verbose) + return; + + fprintf (lrs_ofp, "\n*Input size m=%ld rows n=%ld columns", P->m, Q->n); + if (hull) + fprintf (lrs_ofp, " working dimension=%ld", d - 1 + homogeneous); + else + fprintf (lrs_ofp, " working dimension=%ld", d); + + fprintf (lrs_ofp, "\n*Starting cobasis defined by input rows"); + for (i = 0; i < nlinearity; i++) + temparray[i] = linearity[i]; + for (i = nlinearity; i < lastdv; i++) + temparray[i] = inequality[C[i - nlinearity] - lastdv]; + for (i = 0; i < lastdv; i++) + reorder (temparray, lastdv); + for (i = 0; i < lastdv; i++) + fprintf (lrs_ofp, " %ld", temparray[i]); + + +#endif + + +} /* end of lrs_printtotals */ +/************************/ +/* Estimation function */ +/************************/ +long +lrs_estimate (lrs_dic * P, lrs_dat * Q) + /*returns estimate of subtree size (no. cobases) from current node */ + /*current node is not counted. */ + /*cest[0]rays [1]vertices [2]bases [3]volume */ + /* [4] integer vertices */ +{ + + lrs_mp_vector output; /* holds one line of output; ray,vertex,facet,linearity */ + lrs_mp Nvol, Dvol; /* hold volume of current basis */ + long estdepth = 0; /* depth of basis/vertex in subtree for estimate */ + long i = 0, j = 0, k, nchild, runcount, col; + double prod = 0.0; + double cave[] = + {0.0, 0.0, 0.0, 0.0, 0.0}; + double nvertices, nbases, nrays, nvol, nivertices; + long rays = 0; + double newvol = 0.0; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *isave = Q->isave; + long *jsave = Q->jsave; + double *cest = Q->cest; + long d = P->d; + lrs_alloc_mp(Nvol); lrs_alloc_mp(Dvol); +/* Main Loop of Estimator */ + + output = lrs_alloc_mp_vector (Q->n); /* output holds one line of output from dictionary */ + + for (runcount = 1; runcount <= Q->runs; runcount++) + { /* runcount counts number of random probes */ + j = 0; + nchild = 1; + prod = 1; + nvertices = 0.0; + nbases = 0.0; + nrays = 0.0; + nvol = 0.0; + nivertices =0.0; + + while (nchild != 0) /* while not finished yet */ + { + + nchild = 0; + while (j < d) + { + if (reverse (P, Q, &i, j)) + { + isave[nchild] = i; + jsave[nchild] = j; + nchild++; + } + j++; + } + + if (estdepth == 0 && nchild == 0) + { + cest[0] = cest[0] + rays; /* may be some rays here */ + lrs_clear_mp(Nvol); lrs_clear_mp(Dvol); + lrs_clear_mp_vector(output, Q->n); + return(0L); /*subtree is a leaf */ + } + + prod = prod * nchild; + nbases = nbases + prod; + if (Q->debug) + { + fprintf (lrs_ofp, " degree= %ld ", nchild); + fprintf (lrs_ofp, "\nPossible reverse pivots: i,j="); + for (k = 0; k < nchild; k++) + fprintf (lrs_ofp, "%ld,%ld ", isave[k], jsave[k]); + } + + if (nchild > 0) /*reverse pivot found choose random child */ + { + k = myrandom (Q->seed, nchild); + Q->seed = myrandom (Q->seed, 977L); + i = isave[k]; + j = jsave[k]; + if (Q->debug) + fprintf (lrs_ofp, " selected pivot k=%ld seed=%ld ", k, Q->seed); + estdepth++; + Q->totalnodes++; /* calculate total number of nodes evaluated */ + pivot (P, Q, i, j); + update (P, Q, &i, &j); /*Update B,C,i,j */ + if (lexmin (P, Q, ZERO)) /* see if lexmin basis for vertex */ + { + nvertices = nvertices + prod; + /* integer vertex estimate */ + if( lrs_getvertex(P,Q,output)) + { --Q->count[1]; + if (one(output[0] )) + { --Q->count[4]; + nivertices = nivertices + prod; + } + } + } + + rays = 0; + for (col = 1; col <= d; col++) + if (negative (A[0][col]) && (lrs_ratio (P, Q, col) == 0) && lexmin (P, Q, col)) + rays++; + nrays = nrays + prod * rays; /* update ray info */ + + if (Q->getvolume) + { + rescaledet (P, Q, Nvol, Dvol); /* scales determinant in case input rational */ + rattodouble (Nvol, Dvol, &newvol); + nvol = nvol + newvol * prod; /* adjusts volume for degree */ + } + j = 0; + } + } + cave[0] = cave[0] + nrays; + cave[1] = cave[1] + nvertices; + cave[2] = cave[2] + nbases; + cave[3] = cave[3] + nvol; + cave[4] = cave[4] + nivertices; + +/* backtrack to root and do it again */ + + while (estdepth > 0) + { + estdepth = estdepth - 1; + selectpivot (P, Q, &i, &j); + pivot (P, Q, i, j); + update (P, Q, &i, &j); /*Update B,C,i,j */ + /*fprintf(lrs_ofp,"\n0 +++"); */ + if (Q->debug) + { + fprintf (lrs_ofp, "\n Backtrack Pivot: indices i,j %ld %ld ", i, j); + printA (P, Q); + } + j++; + } + + } /* end of for loop on runcount */ + + j=(long) cave[2]/Q->runs; + +//2015.2.9 Do not update totals if we do iterative estimating and subtree is too big + if(Q->subtreesize == 0 || j <= Q->subtreesize ) + for (i = 0; i < 5; i++) + cest[i] = cave[i] / Q->runs + cest[i]; + + + lrs_clear_mp(Nvol); lrs_clear_mp(Dvol); + lrs_clear_mp_vector(output, Q->n); + return(j); +} /* end of lrs_estimate */ + + +/*********************************/ +/* Internal functions */ +/*********************************/ +/* Basic Dictionary functions */ +/******************************* */ + +long +reverse (lrs_dic * P, lrs_dat * Q, long *r, long s) +/* find reverse indices */ +/* TRUE if B[*r] C[s] is a reverse lexicographic pivot */ +{ + long i, j, enter, row, col; + +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *B = P->B; + long *C = P->C; + long *Row = P->Row; + long *Col = P->Col; + long d = P->d; + + enter = C[s]; + col = Col[s]; + if (Q->debug) + { + fprintf (lrs_ofp, "\n+reverse: col index %ld C %ld Col %ld ", s, enter, col); + fflush (lrs_ofp); + } + if (!negative (A[0][col])) + { + if (Q->debug) + fprintf (lrs_ofp, " Pos/Zero Cost Coeff"); + Q->minratio[P->m]=0; /* 2011.7.14 */ + return (FALSE); + } + + *r = lrs_ratio (P, Q, col); + if (*r == 0) /* we have a ray */ + { + if (Q->debug) + fprintf (lrs_ofp, " Pivot col non-negative: ray found"); + Q->minratio[P->m]=0; /* 2011.7.14 */ + return (FALSE); + } + + row = Row[*r]; + +/* check cost row after "pivot" for smaller leaving index */ +/* ie. j s.t. A[0][j]*A[row][col] < A[0][col]*A[row][j] */ +/* note both A[row][col] and A[0][col] are negative */ + + for (i = 0; i < d && C[i] < B[*r]; i++) + if (i != s) + { + j = Col[i]; + if (positive (A[0][j]) || negative (A[row][j])) /*or else sign test fails trivially */ + if ((!negative (A[0][j]) && !positive (A[row][j])) || + comprod (A[0][j], A[row][col], A[0][col], A[row][j]) == -1) + { /*+ve cost found */ + if (Q->debug) + { + fprintf (lrs_ofp, "\nPositive cost found: index %ld C %ld Col %ld", i, C[i], j); + fflush(lrs_ofp); + } + Q->minratio[P->m]=0; /* 2011.7.14 */ + + return (FALSE); + } + } + if (Q->debug) + { + fprintf (lrs_ofp, "\n+end of reverse : indices r %ld s %ld \n", *r, s); + fflush (stdout); + } + return (TRUE); +} /* end of reverse */ + +long +selectpivot (lrs_dic * P, lrs_dat * Q, long *r, long *s) +/* select pivot indices using lexicographic rule */ +/* returns TRUE if pivot found else FALSE */ +/* pivot variables are B[*r] C[*s] in locations Row[*r] Col[*s] */ +{ + long j, col; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *Col = P->Col; + long d = P->d; + + *r = 0; + *s = d; + j = 0; + +/*find positive cost coef */ + while ((j < d) && (!positive (A[0][Col[j]]))) + j++; + + if (j < d) /* pivot column found! */ + { + *s = j; + col = Col[j]; + + /*find min index ratio */ + *r = lrs_ratio (P, Q, col); + if (*r != 0) + return (TRUE); /* unbounded */ + } + return (FALSE); +} /* end of selectpivot */ +/******************************************************* */ + +void +pivot (lrs_dic * P, lrs_dat * Q, long bas, long cob) + /* Qpivot routine for array A */ + /* indices bas, cob are for Basis B and CoBasis C */ + /* corresponding to row Row[bas] and column */ + /* Col[cob] respectively */ +{ + long r, s; + long i, j; + lrs_mp Ns, Nt, Ars; +/* assign local variables to structures */ + + lrs_mp_matrix A = P->A; + long *B = P->B; + long *C = P->C; + long *Row = P->Row; + long *Col = P->Col; + long d, m_A; + + lrs_alloc_mp(Ns); lrs_alloc_mp(Nt); lrs_alloc_mp(Ars); + + d = P->d; + m_A = P->m_A; + Q->count[3]++; /* count the pivot */ + + r = Row[bas]; + s = Col[cob]; + +/* Ars=A[r][s] */ + if (Q->debug) + { + fprintf (lrs_ofp, "\n pivot B[%ld]=%ld C[%ld]=%ld ", bas, B[bas], cob, C[cob]); + printA(P,Q); + fflush (stdout); + } + copy (Ars, A[r][s]); + storesign (P->det, sign (Ars)); /*adjust determinant to new sign */ + + + for (i = 0; i <= m_A; i++) + if (i != r) + for (j = 0; j <= d; j++) + if (j != s) + { +/* A[i][j]=(A[i][j]*Ars-A[i][s]*A[r][j])/P->det; */ + + mulint (A[i][j], Ars, Nt); + mulint (A[i][s], A[r][j], Ns); + decint (Nt, Ns); + exactdivint (Nt, P->det, A[i][j]); + } /* end if j .... */ + + if (sign (Ars) == POS) + { + for (j = 0; j <= d; j++) /* no need to change sign if Ars neg */ + /* A[r][j]=-A[r][j]; */ + if (!zero (A[r][j])) + changesign (A[r][j]); + } /* watch out for above "if" when removing this "}" ! */ + else + for (i = 0; i <= m_A; i++) + if (!zero (A[i][s])) + changesign (A[i][s]); + + /* A[r][s]=P->det; */ + + copy (A[r][s], P->det); /* restore old determinant */ + copy (P->det, Ars); + storesign (P->det, POS); /* always keep positive determinant */ + + + if (Q->debug) + { + fprintf (lrs_ofp, " depth=%ld ", P->depth); + pmp ("det=", P->det); + fflush(stdout); + } +/* set the new rescaled objective function value */ + + mulint (P->det, Q->Lcm[0], P->objden); + mulint (Q->Gcd[0], A[0][0], P->objnum); + + if (!Q->maximize) + changesign (P->objnum); + if (zero (P->objnum)) + storesign (P->objnum, POS); + else + reduce (P->objnum,P->objden); + + + lrs_clear_mp(Ns); lrs_clear_mp(Nt); lrs_clear_mp(Ars); +} /* end of pivot */ + +long +primalfeasible (lrs_dic * P, lrs_dat * Q) +/* Do dual pivots to get primal feasibility */ +/* Note that cost row is all zero, so no ratio test needed for Dual Bland's rule */ +{ + long primalinfeasible = TRUE; + long i, j; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *Row = P->Row; + long *Col = P->Col; + long m, d, lastdv; + m = P->m; + d = P->d; + lastdv = Q->lastdv; + +/*temporary: try to get new start after linearity */ + + while (primalinfeasible) + { + i=lastdv+1; + while (i <= m && !negative (A[Row[i]][0]) ) + i++; + if (i <= m ) + { + j = 0; /*find a positive entry for in row */ + while (j < d && !positive (A[Row[i]][Col[j]])) + j++; + if (j >= d) + return (FALSE); /* no positive entry */ + pivot (P, Q, i, j); + update (P, Q, &i, &j); + } + else + primalinfeasible = FALSE; + } /* end of while primalinfeasibile */ + return (TRUE); +} /* end of primalfeasible */ + + +long +lrs_solvelp (lrs_dic * P, lrs_dat * Q, long maximize) +/* Solve primal feasible lp by Dantzig`s rule and lexicographic ratio test */ +/* return TRUE if bounded, FALSE if unbounded */ +{ + long i, j; +/* assign local variables to structures */ + long d = P->d; + + while (dan_selectpivot (P, Q, &i, &j)) + { + Q->count[3]++; + pivot (P, Q, i, j); + update (P, Q, &i, &j); /*Update B,C,i,j */ + } + if (Q->debug) + printA (P, Q); + + if (j < d && i == 0) /* selectpivot gives information on unbounded solution */ + { +#ifndef LRS_QUIET + if (Q->lponly) + fprintf (lrs_ofp, "\n*Unbounded solution"); +#endif + return FALSE; + } + return TRUE; +} /* end of lrs_solvelp */ + +long +getabasis (lrs_dic * P, lrs_dat * Q, long order[]) + +/* Pivot Ax<=b to standard form */ +/*Try to find a starting basis by pivoting in the variables x[1]..x[d] */ +/*If there are any input linearities, these appear first in order[] */ +/* Steps: (a) Try to pivot out basic variables using order */ +/* Stop if some linearity cannot be made to leave basis */ +/* (b) Permanently remove the cobasic indices of linearities */ +/* (c) If some decision variable cobasic, it is a linearity, */ +/* and will be removed. */ + +{ + long i, j, k; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *B = P->B; + long *C = P->C; + long *Row = P->Row; + long *Col = P->Col; + long *linearity = Q->linearity; + long *redundcol = Q->redundcol; + long m, d, nlinearity; + long nredundcol = 0L; /* will be calculated here */ + m = P->m; + d = P->d; + nlinearity = Q->nlinearity; + + + + if (Q->debug) + { + fprintf (lrs_ofp, "\ngetabasis from inequalities given in order"); + for (i = 0l; i < m; i++) + fprintf (lrs_ofp, " %ld", order[i]); + } + for (j = 0l; j < m; j++) + { + i = 0l; + while (i <= m && B[i] != d + order[j]) + i++; /* find leaving basis index i */ + if (j < nlinearity && i > m) /* cannot pivot linearity to cobasis */ + { + if (Q->debug) + printA (P, Q); + #ifndef LRS_QUIET + fprintf (lrs_ofp, "\nCannot find linearity in the basis"); + #endif + return FALSE; + } + if (i <= m) + { /* try to do a pivot */ + k = 0l; + while (C[k] <= d && zero (A[Row[i]][Col[k]])){ + k++; + } + if (C[k] <= d) + { + + pivot (P, Q, i, k); + update (P, Q, &i, &k); + } + else if (j < nlinearity) + { /* cannot pivot linearity to cobasis */ + if (zero (A[Row[i]][0])) + { + #ifndef LRS_QUIET + fprintf (lrs_ofp, "\n*Input linearity in row %ld is redundant--converted to inequality", order[j]); + #endif + linearity[j]=0l; + } + else + { + if (Q->debug) + printA (P, Q); + #ifndef LRS_QUIET + fprintf (lrs_ofp, "\n*Input linearity in row %ld is inconsistent with earlier linearities", order[j]); + fprintf (lrs_ofp, "\n*No feasible solution"); + #endif + return FALSE; + } + } + + + } + } + + +/* update linearity array to get rid of redundancies */ + i = 0; + k = 0; /* counters for linearities */ + while (k < nlinearity) + { + while (k < nlinearity && linearity[k] == 0) + k++; + if (k < nlinearity) + linearity[i++] = linearity[k++]; + } + + nlinearity = i; +/* bug fix, 2009.6.27 */ Q->nlinearity = i; + +/* column dependencies now can be recorded */ +/* redundcol contains input column number 0..n-1 where redundancy is */ + k = 0; + while (k < d && C[k] <= d) + { + if (C[k] <= d){ /* decision variable still in cobasis */ + redundcol[nredundcol++] = C[k] - Q->hull; /* adjust for hull indices */ + + } + k++; + } + +/* now we know how many decision variables remain in problem */ + Q->nredundcol = nredundcol; + Q->lastdv = d - nredundcol; + if (Q->debug) + { + fprintf (lrs_ofp, "\nend of first phase of getabasis: "); + fprintf (lrs_ofp, "lastdv=%ld nredundcol=%ld", Q->lastdv, Q->nredundcol); + fprintf (lrs_ofp, "\nredundant cobases:"); + for (i = 0; i < nredundcol; i++) + fprintf (lrs_ofp, " %ld", redundcol[i]); + printA (P, Q); + } + +/* Remove linearities from cobasis for rest of computation */ +/* This is done in order so indexing is not screwed up */ + + for (i = 0; i < nlinearity; i++) + { /* find cobasic index */ + k = 0; + while (k < d && C[k] != linearity[i] + d) + k++; + if (k >= d) + { + fprintf (lrs_ofp, "\nError removing linearity"); + return FALSE; + } + if (!removecobasicindex (P, Q, k)) + return FALSE; + d = P->d; + } + if (Q->debug && nlinearity > 0) + printA (P, Q); +/* set index value for first slack variable */ + +/* Check feasability */ + if (Q->givenstart) + { + i = Q->lastdv + 1; + while (i <= m && !negative (A[Row[i]][0])) + i++; + if (i <= m) + fprintf (lrs_ofp, "\n*Infeasible startingcobasis - will be modified"); + } + return TRUE; +} /* end of getabasis */ + +long +removecobasicindex (lrs_dic * P, lrs_dat * Q, long k) +/* remove the variable C[k] from the problem */ +/* used after detecting column dependency */ +{ + long i, j, cindex, deloc; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *B = P->B; + long *C = P->C; + long *Col = P->Col; + long m, d; + m = P->m; + d = P->d; + + if (Q->debug) + fprintf (lrs_ofp, "\nremoving cobasic index k=%ld C[k]=%ld", k, C[k]); + cindex = C[k]; /* cobasic index to remove */ + deloc = Col[k]; /* matrix column location to remove */ + + for (i = 1; i <= m; i++) /* reduce basic indices by 1 after index */ + if (B[i] > cindex) + B[i]--; + + for (j = k; j < d; j++) /* move down other cobasic variables */ + { + C[j] = C[j + 1] - 1; /* cobasic index reduced by 1 */ + Col[j] = Col[j + 1]; + } + + if (deloc != d) + { + /* copy col d to deloc */ + for (i = 0; i <= m; i++) + copy (A[i][deloc], A[i][d]); + + /* reassign location for moved column */ + j = 0; + while (Col[j] != d) + j++; + + Col[j] = deloc; + } + + P->d--; + if (Q->debug) + printA (P, Q); + return TRUE; +} /* end of removecobasicindex */ + +lrs_dic * +resize (lrs_dic * P, lrs_dat * Q) + /* resize the dictionary after some columns are deleted, ie. inputd>d */ + /* a new lrs_dic record is created with reduced size, and items copied over */ +{ + lrs_dic *P1; /* to hold new dictionary in case of resizing */ + + long i, j; + long m, d, m_A; + + + m = P->m; + d = P->d; + m_A = P->m_A; + +/* get new dictionary record */ + + P1 = new_lrs_dic (m, d, m_A); + +/* copy data from P to P1 */ + P1->i = P->i; + P1->j = P->j; + P1->depth = P->depth; + P1->m = P->m; + P1->d = P1->d_orig = d; + P1->lexflag = P->lexflag; + P1->m_A = P->m_A; + copy (P1->det, P->det); + copy (P1->objnum, P->objnum); + copy (P1->objden, P->objden); + + for (i = 0; i <= m; i++) + { + P1->B[i] = P->B[i]; + P1->Row[i] = P->Row[i]; + } + for (i = 0; i <= m_A; i++) + { + for (j = 0; j <= d; j++) + copy (P1->A[i][j], P->A[i][j]); + } + + + for (j = 0; j <= d; j++) + { + P1->Col[j] = P->Col[j]; + P1->C[j] = P->C[j]; + } + + if (Q->debug) + { + fprintf (lrs_ofp, "\nDictionary resized from d=%ld to d=%ld", Q->inputd, P->d); + printA (P1, Q); + } + + lrs_free_dic (P,Q); + +/* Reassign cache pointers */ + + Q->Qhead = P1; + Q->Qtail = P1; + P1->next = P1; + P1->prev = P1; + + return P1; + +} +/********* resize ***************/ + + +long +restartpivots (lrs_dic * P, lrs_dat * Q) +/* facet contains a list of the inequalities in the cobasis for the restart */ +/* inequality contains the relabelled inequalities after initialization */ +{ + long i, j, k; + long *Cobasic; /* when restarting, Cobasic[j]=1 if j is in cobasis */ +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *B = P->B; + long *C = P->C; + long *Row = P->Row; + long *Col = P->Col; + long *inequality = Q->inequality; + long *facet = Q->facet; + long nlinearity = Q->nlinearity; + long m, d, lastdv; + m = P->m; + d = P->d; + lastdv = Q->lastdv; + + Cobasic = (long *) CALLOC ((unsigned) m + d + 2, sizeof (long)); + + if (Q->debug) + fprintf(lrs_ofp,"\nCobasic flags in restartpivots"); + /* set Cobasic flags */ + for (i = 0; i < m + d + 1; i++) + Cobasic[i] = 0; + for (i = 0; i < d; i++) /* find index corresponding to facet[i] */ + { + j = 1; + while (facet[i + nlinearity] != inequality[j]) + j++; + Cobasic[j + lastdv] = 1; + if (Q->debug) + fprintf(lrs_ofp," %ld %ld;",facet[i+nlinearity],j+lastdv); + } + + /* Note that the order of doing the pivots is important, as */ + /* the B and C vectors are reordered after each pivot */ + +/* code below replaced 2006.10.30 */ +/* + + for (i = m; i >= d + 1; i--) + if (Cobasic[B[i]]) + { + k = d - 1; + while ((k >= 0) && + (zero (A[Row[i]][Col[k]]) || Cobasic[C[k]])) + k--; + if (k >= 0) + { + pivot (P, Q, i, k); + update (P, Q, &i, &k); + } + else + { + fprintf (lrs_ofp, "\nInvalid Co-basis - does not have correct rank"); + free(Cobasic); + return FALSE; + } + } +*/ +/*end of code that was replaced */ + +/* Suggested new code from db starts */ + i=m; + while (i>d){ + while(Cobasic[B[i]]){ + k = d - 1; + while ((k >= 0) && (zero (A[Row[i]][Col[k]]) || Cobasic[C[k]])){ + k--; + } + if (k >= 0) { + /*db asks: should i really be modified here? (see old code) */ + /*da replies: modifying i only makes is larger, and so */ + /*the second while loop will put it back where it was */ + /*faster (and safer) as done below */ + long ii=i; + pivot (P, Q, ii, k); + update (P, Q, &ii, &k); + } else { + fprintf (lrs_ofp, "\nInvalid Co-basis - does not have correct rank"); + free(Cobasic); + return FALSE; + } + } + i--; + } +/* Suggested new code from db ends */ + + if (lexmin (P, Q, ZERO)) + --Q->count[1]; /* decrement vertex count if lexmin */ +/* check restarting from a primal feasible dictionary */ + for (i = lastdv + 1; i <= m; i++) + if (negative (A[Row[i]][0])) + { + fprintf (lrs_ofp, "\nTrying to restart from infeasible dictionary"); + free(Cobasic); + return FALSE; + } + free(Cobasic); + return TRUE; + +} /* end of restartpivots */ + + +long +lrs_ratio (lrs_dic * P, lrs_dat * Q, long col) /*find lex min. ratio */ + /* find min index ratio -aig/ais, ais<0 */ + /* if multiple, checks successive basis columns */ + /* recoded Dec 1997 */ +{ + long i, j, comp, ratiocol, basicindex, start, nstart, cindex, bindex; + long firstime; /*For ratio test, true on first pass,else false */ + lrs_mp Nmin, Dmin; + long degencount, ndegencount; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *B = P->B; + long *Row = P->Row; + long *Col = P->Col; + long *minratio = Q->minratio; + long m, d, lastdv; + + m = P->m; + d = P->d; + lastdv = Q->lastdv; + + + nstart=0; + ndegencount=0; + degencount = 0; + minratio[P->m]=1; /*2011.7.14 non-degenerate pivot flag */ + + for (j = lastdv + 1; j <= m; j++) + { + /* search rows with negative coefficient in dictionary */ + /* minratio contains indices of min ratio cols */ + if (negative (A[Row[j]][col])) + { + minratio[degencount++] = j; + if(zero (A[Row[j]][0])) + minratio[P->m]=0; /*2011.7.14 degenerate pivot flag */ + } + } /* end of for loop */ + if (Q->debug) + { + fprintf (lrs_ofp, " Min ratios: "); + for (i = 0; i < degencount; i++) + fprintf (lrs_ofp, " %ld ", B[minratio[i]]); + } + if (degencount == 0) + return (degencount); /* non-negative pivot column */ + + lrs_alloc_mp(Nmin); lrs_alloc_mp(Dmin); + ratiocol = 0; /* column being checked, initially rhs */ + start = 0; /* starting location in minratio array */ + bindex = d + 1; /* index of next basic variable to consider */ + cindex = 0; /* index of next cobasic variable to consider */ + basicindex = d; /* index of basis inverse for current ratio test, except d=rhs test */ + while (degencount > 1) /*keep going until unique min ratio found */ + { + if (B[bindex] == basicindex) /* identity col in basis inverse */ + { + if (minratio[start] == bindex) + /* remove this index, all others stay */ + { + start++; + degencount--; + } + bindex++; + } + else + /* perform ratio test on rhs or column of basis inverse */ + { + firstime = TRUE; + /*get next ratio column and increment cindex */ + if (basicindex != d) + ratiocol = Col[cindex++]; + for (j = start; j < start + degencount; j++) + { + i = Row[minratio[j]]; /* i is the row location of the next basic variable */ + comp = 1; /* 1: lhs>rhs; 0:lhs=rhs; -1: lhs<rhs */ + if (firstime) + firstime = FALSE; /*force new min ratio on first time */ + else + { + if (positive (Nmin) || negative (A[i][ratiocol])) + { + if (negative (Nmin) || positive (A[i][ratiocol])) + comp = comprod (Nmin, A[i][col], A[i][ratiocol], Dmin); + else + comp = -1; + } + + else if (zero (Nmin) && zero (A[i][ratiocol])) + comp = 0; + + if (ratiocol == ZERO) + comp = -comp; /* all signs reversed for rhs */ + } + if (comp == 1) + { /*new minimum ratio */ + nstart = j; + copy (Nmin, A[i][ratiocol]); + copy (Dmin, A[i][col]); + ndegencount = 1; + } + else if (comp == 0) /* repeated minimum */ + minratio[nstart + ndegencount++] = minratio[j]; + + } /* end of for (j=start.... */ + degencount = ndegencount; + start = nstart; + } /* end of else perform ratio test statement */ + basicindex++; /* increment column of basis inverse to check next */ + if (Q->debug) + { + fprintf (lrs_ofp, " ratiocol=%ld degencount=%ld ", ratiocol, degencount); + fprintf (lrs_ofp, " Min ratios: "); + for (i = start; i < start + degencount; i++) + fprintf (lrs_ofp, " %ld ", B[minratio[i]]); + } + } /*end of while loop */ + lrs_clear_mp(Nmin); lrs_clear_mp(Dmin); + return (minratio[start]); +} /* end of ratio */ + + + +long +lexmin (lrs_dic * P, lrs_dat * Q, long col) + /*test if basis is lex-min for vertex or ray, if so TRUE */ + /* FALSE if a_r,g=0, a_rs !=0, r > s */ +{ +/*do lexmin test for vertex if col=0, otherwise for ray */ + long r, s, i, j; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *B = P->B; + long *C = P->C; + long *Row = P->Row; + long *Col = P->Col; + long m = P->m; + long d = P->d; + + for (i = Q->lastdv + 1; i <= m; i++) + { + r = Row[i]; + if (zero (A[r][col])) /* necessary for lexmin to fail */ + for (j = 0; j < d; j++) + { + s = Col[j]; + if (B[i] > C[j]) /* possible pivot to reduce basis */ + { + if (zero (A[r][0])) /* no need for ratio test, any pivot feasible */ + { + if (!zero (A[r][s])) + return (FALSE); + } + else if (negative (A[r][s]) && ismin (P, Q, r, s)) + { + return (FALSE); + } + } /* end of if B[i] ... */ + } + } + if ((col != ZERO) && Q->debug) + { + fprintf (lrs_ofp, "\n lexmin ray in col=%ld ", col); + printA (P, Q); + } + return (TRUE); +} /* end of lexmin */ + +long +ismin (lrs_dic * P, lrs_dat * Q, long r, long s) +/*test if A[r][s] is a min ratio for col s */ +{ + long i; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long m_A = P->m_A; + + for (i = 1; i <= m_A; i++) + if ((i != r) && + negative (A[i][s]) && comprod (A[i][0], A[r][s], A[i][s], A[r][0])) + { + return (FALSE); + } + + return (TRUE); +} + +void +update (lrs_dic * P, lrs_dat * Q, long *i, long *j) + /*update the B,C arrays after a pivot */ + /* involving B[bas] and C[cob] */ +{ + + long leave, enter; +/* assign local variables to structures */ + long *B = P->B; + long *C = P->C; + long *Row = P->Row; + long *Col = P->Col; + long m = P->m; + long d = P->d; + + leave = B[*i]; + enter = C[*j]; + B[*i] = enter; + reorder1 (B, Row, *i, m + 1); + C[*j] = leave; + reorder1 (C, Col, *j, d); +/* restore i and j to new positions in basis */ + for (*i = 1; B[*i] != enter; (*i)++); /*Find basis index */ + for (*j = 0; C[*j] != leave; (*j)++); /*Find co-basis index */ +} /* end of update */ + +long +lrs_degenerate (lrs_dic * P, lrs_dat * Q) +/* TRUE if the current dictionary is primal degenerate */ +/* not thoroughly tested 2000/02/15 */ +{ + long i; + long *Row; + + lrs_mp_matrix A = P->A; + long d = P->d; + long m = P->m; + + Row = P->Row; + + for (i = d + 1; i <= m; i++) + if (zero (A[Row[i]][0])) + return TRUE; + + return FALSE; +} + + +/*********************************************************/ +/* Miscellaneous */ +/******************************************************* */ + +void +reorder (long a[], long range) +/*reorder array in increasing order with one misplaced element */ +{ + long i, temp; + for (i = 0; i < range - 1; i++) + if (a[i] > a[i + 1]) + { + temp = a[i]; + a[i] = a[i + 1]; + a[i + 1] = temp; + } + for (i = range - 2; i >= 0; i--) + if (a[i] > a[i + 1]) + { + temp = a[i]; + a[i] = a[i + 1]; + a[i + 1] = temp; + } + +} /* end of reorder */ + +void +reorder1 (long a[], long b[], long newone, long range) +/*reorder array a in increasing order with one misplaced element at index newone */ +/*elements of array b are updated to stay aligned with a */ +{ + long temp; + while (newone > 0 && a[newone] < a[newone - 1]) + { + temp = a[newone]; + a[newone] = a[newone - 1]; + a[newone - 1] = temp; + temp = b[newone]; + b[newone] = b[newone - 1]; + b[--newone] = temp; + } + while (newone < range - 1 && a[newone] > a[newone + 1]) + { + temp = a[newone]; + a[newone] = a[newone + 1]; + a[newone + 1] = temp; + temp = b[newone]; + b[newone] = b[newone + 1]; + b[++newone] = temp; + } +} /* end of reorder1 */ + + +void +rescaledet (lrs_dic * P, lrs_dat * Q, lrs_mp Vnum, lrs_mp Vden) + /* rescale determinant to get its volume */ + /* Vnum/Vden is volume of current basis */ +{ + lrs_mp gcdprod; /* to hold scale factors */ + long i; +/* assign local variables to structures */ + long *B = P->B; + long *C = P->C; + long m, d, lastdv; + + lrs_alloc_mp(gcdprod); + m = P->m; + d = P->d; + lastdv = Q->lastdv; + + itomp (ONE, gcdprod); + itomp (ONE, Vden); + for (i = 0; i < d; i++) + if (B[i] <= m) + { + mulint (Q->Gcd[Q->inequality[C[i] - lastdv]], gcdprod, gcdprod); + mulint (Q->Lcm[Q->inequality[C[i] - lastdv]], Vden, Vden); + } + mulint (P->det, gcdprod, Vnum); + reduce (Vnum, Vden); + lrs_clear_mp(gcdprod); +} /* end rescaledet */ + +void +rescalevolume (lrs_dic * P, lrs_dat * Q, lrs_mp Vnum, lrs_mp Vden) +/* adjust volume for dimension */ +{ + lrs_mp temp, dfactorial; +/* assign local variables to structures */ + long lastdv = Q->lastdv; + + lrs_alloc_mp(temp); lrs_alloc_mp(dfactorial); + + /*reduce Vnum by d factorial */ + getfactorial (dfactorial, lastdv); + mulint (dfactorial, Vden, Vden); + if (Q->hull && !Q->homogeneous) + { /* For hull option multiply by d to correct for lifting */ + itomp (lastdv, temp); + mulint (temp, Vnum, Vnum); + } + + reduce (Vnum, Vden); + lrs_clear_mp(temp); lrs_clear_mp(dfactorial); +} + + +void +updatevolume (lrs_dic * P, lrs_dat * Q) /* rescale determinant and update the volume */ +{ + lrs_mp tN, tD, Vnum, Vden; + lrs_alloc_mp(tN); lrs_alloc_mp(tD); lrs_alloc_mp(Vnum); lrs_alloc_mp(Vden); + rescaledet (P, Q, Vnum, Vden); + copy (tN, Q->Nvolume); + copy (tD, Q->Dvolume); + linrat (tN, tD, ONE, Vnum, Vden, ONE, Q->Nvolume, Q->Dvolume); + if (Q->debug) + { + prat ("\n*Volume=", Q->Nvolume, Q->Dvolume); + pmp (" Vnum=", Vnum); + pmp (" Vden=", Vden); + } + lrs_clear_mp(tN); lrs_clear_mp(tD); lrs_clear_mp(Vnum); lrs_clear_mp(Vden); + +} /* end of updatevolume */ + + + +/***************************************************/ +/* Routines for redundancy checking */ +/***************************************************/ + +long +checkredund (lrs_dic * P, lrs_dat * Q) +/* Solve primal feasible lp by least subscript and lex min basis method */ +/* to check redundancy of a row in objective function */ +/* returns TRUE if redundant, else FALSE */ +{ + lrs_mp Ns, Nt; + long i, j; + long r, s; + +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *Row, *Col; + long d = P->d; + + lrs_alloc_mp(Ns); lrs_alloc_mp(Nt); + Row = P->Row; + Col = P->Col; + + while (selectpivot (P, Q, &i, &j)) + { + Q->count[2]++; + +/* sign of new value of A[0][0] */ +/* is A[0][s]*A[r][0]-A[0][0]*A[r][s] */ + + r = Row[i]; + s = Col[j]; + + mulint (A[0][s], A[r][0], Ns); + mulint (A[0][0], A[r][s], Nt); + + if (mp_greater (Ns, Nt)) + { + lrs_clear_mp(Ns); lrs_clear_mp(Nt); + return FALSE; /* non-redundant */ + } + + pivot (P, Q, i, j); + update (P, Q, &i, &j); /*Update B,C,i,j */ + + } + + lrs_clear_mp(Ns); lrs_clear_mp(Nt); + + return !(j < d && i == 0); /* unbounded is also non-redundant */ + + +} /* end of checkredund */ + +long +checkcobasic (lrs_dic * P, lrs_dat * Q, long index) +/* TRUE if index is cobasic and nonredundant */ +/* FALSE if basic, or degen. cobasic, where it will get pivoted out */ + +{ + +/* assign local variables to structures */ + + lrs_mp_matrix A = P->A; + long *B, *C, *Row, *Col; + long d = P->d; + long m = P->m; + long debug = Q->debug; + long i = 0; + long j = 0; + long s; + + B = P->B; + C = P->C; + Row = P->Row; + Col = P->Col; + + + while ((j < d) && C[j] != index) + j++; + + if (j == d) + return FALSE; /* not cobasic index */ + + +/* index is cobasic */ + + if (debug) + fprintf (lrs_ofp, "\nindex=%ld cobasic", index); +/* not debugged for new LOC + s=LOC[index]; + */ + s = Col[j]; + i = Q->lastdv + 1; + + while ((i <= m) && + (zero (A[Row[i]][s]) || !zero (A[Row[i]][0]))) + i++; + + if (i > m) + { + if (debug) + fprintf (lrs_ofp, " is non-redundant"); + return TRUE; + } + if (debug) + fprintf (lrs_ofp, " is degenerate B[i]=%ld", B[i]); + + pivot (P, Q, i, j); + update (P, Q, &i, &j); /*Update B,C,i,j */ + + return FALSE; /*index is no longer cobasic */ + +} /* end of checkcobasic */ + +long +checkindex (lrs_dic * P, lrs_dat * Q, long index) +/* 0 if index is non-redundant inequality */ +/* 1 if index is redundant inequality */ +/* 2 if index is input linearity */ +/*NOTE: row is returned all zero if redundant!! */ +{ + long i, j; + + lrs_mp_matrix A = P->A; + long *Row = P->Row; + long *B = P->B; + long d = P->d; + long m = P->m; + + if (Q->debug) + printA (P, Q); + +/* each slack index must be checked for redundancy */ +/* if in cobasis, it is pivoted out if degenerate */ +/* else it is non-redundant */ + + if (checkcobasic (P, Q, index)) + return ZERO; + +/* index is basic */ +/* not debugged for new LOC + i=LOC[index]; + */ + j = 1; + while ((j <= m) && (B[j] != index)) + j++; + + i = Row[j]; + + /* copy row i to cost row, and set it to zero */ + + for (j = 0; j <= d; j++) + { + copy (A[0][j], A[i][j]); + changesign (A[0][j]); + itomp (ZERO, A[i][j]); + } + + + if (checkredund (P, Q)) + return ONE; + +/* non-redundant, copy back and change sign */ + + for (j = 0; j <= d; j++) + { + copy (A[i][j], A[0][j]); + changesign (A[i][j]); + } + + return ZERO; + +} /* end of checkindex */ + + +/***************************************************************/ +/* */ +/* Package of I/O routines */ +/* */ +/***************************************************************/ + +void +lprat (const char *name, long Nt, long Dt) +/*print the long precision rational Nt/Dt without reducing */ +{ + if ( Nt > 0 ) + fprintf (lrs_ofp, " "); + fprintf (lrs_ofp, "%s%ld", name, Nt); + if (Dt != 1) + fprintf (lrs_ofp, "/%ld", Dt); + fprintf (lrs_ofp, " "); +} /* lprat */ + +long +lreadrat (long *Num, long *Den) + /* read a rational string and convert to long */ + /* returns true if denominator is not one */ +{ + char in[MAXINPUT], num[MAXINPUT], den[MAXINPUT]; + if(fscanf (lrs_ifp, "%s", in) == EOF) + return(FALSE); + atoaa (in, num, den); /*convert rational to num/dem strings */ + *Num = atol (num); + if (den[0] == '\0') + { + *Den = 1L; + return (FALSE); + } + *Den = atol (den); + return (TRUE); +} + +void +lrs_getinput(lrs_dic *P,lrs_dat *Q,long *num,long *den, long m, long d) +/* code for reading data matrix in lrs/cdd format */ +{ + long j,row; + + printf("\nEnter each row: b_i a_ij j=1..%ld",d); + for (row=1;row<=m;row++) + { + printf("\nEnter row %ld: ",row ); + for(j=0;j<=d;j++) + { + lreadrat(&num[j],&den[j]); + lprat(" ",num[j],den[j]); + } + + lrs_set_row(P,Q,row,num,den,GE); + } + + printf("\nEnter objective row c_j j=1..%ld: ",d); + num[0]=0; den[0]=1; + for(j=1;j<=d;j++) + { + lreadrat(&num[j],&den[j]); + lprat(" ",num[j],den[j]); + } + + lrs_set_obj(P,Q,num,den,MAXIMIZE); +} + + +long +readlinearity (lrs_dat * Q) /* read in and check linearity list */ +{ + long i, j; + long nlinearity; + if(fscanf (lrs_ifp, "%ld", &nlinearity)==EOF ) + { + fprintf (lrs_ofp, "\nLinearity option invalid, no indices "); + return (FALSE); + } + if (nlinearity < 1) + { + fprintf (lrs_ofp, "\nLinearity option invalid, indices must be positive"); + return (FALSE); + } + + Q->linearity = (long int*) CALLOC ((nlinearity + 1), sizeof (long)); + + for (i = 0; i < nlinearity; i++) + { + if(fscanf (lrs_ifp, "%ld", &j)==EOF) + { + fprintf (lrs_ofp, "\nLinearity option invalid, missing indices"); + return (FALSE); + } + Q->linearity[i] = j; + + } + for (i = 1; i < nlinearity; i++) /*sort in order */ + reorder (Q->linearity, nlinearity); + + Q->nlinearity = nlinearity; + Q->polytope = FALSE; + return TRUE; +} /* end readlinearity */ + +#ifdef PLRS +void plrs_readlinearity(lrs_dat *Q, string line){ + istringstream ss(line); + long nlinearity; + if(!(ss>>nlinearity)){ + printf("\nLinearity option invalid, no indices\n"); + exit(1); + } + if(nlinearity < 1) + { + printf("\nLinearity option invalid, indices must be positive\n"); + exit(1); + } + + Q->linearity = (long int*) CALLOC ((nlinearity + 1), sizeof (long)); + + for (int i = 0; i < nlinearity; i++) + { + if(!(ss>>Q->linearity[i])){ + printf("\nLinearity option invalid, missing indices\n"); + exit(1); + } + } + + for(int i = 1; i < nlinearity; i++) + reorder (Q->linearity, nlinearity); + + Q->nlinearity = nlinearity; + Q->polytope = FALSE; + +} +#endif + +long +readfacets (lrs_dat * Q, long facet[]) +/* read and check facet list for obvious errors during start/restart */ +/* this must be done after linearity option is processed!! */ +{ + long i, j; +/* assign local variables to structures */ + long m, d; + long *linearity = Q->linearity; + m = Q->m; + d = Q->inputd; + + for (j = Q->nlinearity; j < d; j++) /* note we place these after the linearity indices */ + { + if(fscanf (lrs_ifp, "%ld", &facet[j])==EOF) + { + fprintf (lrs_ofp, "\nrestart: facet list missing indices"); + return (FALSE); + } + + + fprintf (lrs_ofp, " %ld", facet[j]); +/* 2010.4.26 nonnegative option needs larger range of indices */ + if(Q->nonnegative) + if (facet[j] < 1 || facet[j] > m+d) + { + fprintf (lrs_ofp, "\n Start/Restart cobasic indices must be in range 1 .. %ld ", m+d); + return FALSE; + } + if(!Q->nonnegative) + if (facet[j] < 1 || facet[j] > m) + { + fprintf (lrs_ofp, "\n Start/Restart cobasic indices must be in range 1 .. %ld ", m); + return FALSE; + } + for (i = 0; i < Q->nlinearity; i++) + if (linearity[i] == facet[j]) + { + fprintf (lrs_ofp, "\n Start/Restart cobasic indices should not include linearities"); + return FALSE; + } +/* bug fix 2011.8.1 reported by Steven Wu*/ + for (i = Q->nlinearity; i < j; i++) +/* end bug fix 2011.8.1 */ + + if (facet[i] == facet[j]) + { + fprintf (lrs_ofp, "\n Start/Restart cobasic indices must be distinct"); + return FALSE; + } + } + return TRUE; +} /* end of readfacets */ + +void +printA (lrs_dic * P, lrs_dat * Q) /* print the integer m by n array A + with B,C,Row,Col vectors */ +{ + long i, j; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *B = P->B; + long *C = P->C; + long *Row = P->Row; + long *Col = P->Col; + long m, d; + m = P->m; + d = P->d; + + fprintf (lrs_ofp, "\n Basis "); + for (i = 0; i <= m; i++) + fprintf (lrs_ofp, "%ld ", B[i]); + fprintf (lrs_ofp, " Row "); + for (i = 0; i <= m; i++) + fprintf (lrs_ofp, "%ld ", Row[i]); + fprintf (lrs_ofp, "\n Co-Basis "); + for (i = 0; i <= d; i++) + fprintf (lrs_ofp, "%ld ", C[i]); + fprintf (lrs_ofp, " Column "); + for (i = 0; i <= d; i++) + fprintf (lrs_ofp, "%ld ", Col[i]); + pmp (" det=", P->det); + fprintf (lrs_ofp, "\n"); + i=0; + while ( i<= m ) + { + for (j = 0; j <= d; j++) + pimat (P, i, j, A[Row[i]][Col[j]], "A"); + fprintf (lrs_ofp, "\n"); + if (i==0 && Q->nonnegative) /* skip basic rows - don't exist! */ + i=d; + i++; + fflush (stdout); + } + fflush (stdout); +} + + +void +pimat (lrs_dic * P, long r, long s, lrs_mp Nt, char name[]) + /*print the long precision integer in row r col s of matrix A */ +{ + long *B = P->B; + long *C = P->C; + if (s == 0) + fprintf (lrs_ofp, "%s[%ld][%ld]=", name, B[r], C[s]); + else + fprintf (lrs_ofp, "[%ld]=", C[s]); + pmp ("", Nt); + +} + +/***************************************************************/ +/* */ +/* Routines for caching, allocating etc. */ +/* */ +/***************************************************************/ + +/* From here mostly Bremner's handiwork */ + +static void +cache_dict (lrs_dic ** D_p, lrs_dat * global, long i, long j) +{ + + if (dict_limit > 1) + { + /* save row, column indicies */ + (*D_p)->i = i; + (*D_p)->j = j; + +/* Make a new, blank spot at the end of the queue to copy into */ + + pushQ (global, (*D_p)->m, (*D_p)->d, (*D_p)->m_A); + + copy_dict (global, global->Qtail, *D_p); /* Copy current dictionary */ + } + *D_p = global->Qtail; + +} + +void +copy_dict (lrs_dat * global, lrs_dic * dest, lrs_dic * src) +{ + long m = src->m; + long m_A = src->m_A; /* number of rows in A */ + long d = src->d; + long r,s; + +#ifdef GMP + for ( r=0;r<=m_A;r++) + for( s=0;s<=d;s++) + copy(dest->A[r][s],src->A[r][s]); + +#else /* fast copy for MP and LRSLONG arithmetic */ + /* Note that the "A" pointer trees need not be copied, since they + always point to the same places within the corresponding space +*/ +/* I wish I understood the above remark. For the time being, do it the easy way for Nash */ + if(global->nash) + { + for ( r=0;r<=m_A;r++) + for( s=0;s<=d;s++) + copy(dest->A[r][s],src->A[r][s]); + } + else + memcpy (dest->A[0][0], (global->Qtail->prev)->A[0][0], + (d + 1) * (lrs_digits + 1) * (m_A + 1) * sizeof (long)); + +#endif + + dest->i = src->i; + dest->j = src->j; + dest->m = m; + dest->d = d; + dest->m_A = src->m_A; + + dest->depth = src->depth; + dest->lexflag = src->lexflag; + + copy (dest->det, src->det); + copy (dest->objnum, src->objnum); + copy (dest->objden, src->objden); + + if (global->debug) + fprintf (lrs_ofp, "\nSaving dict at depth %ld\n", src->depth); + + memcpy (dest->B, src->B, (m + 1) * sizeof (long)); + memcpy (dest->C, src->C, (d + 1) * sizeof (long)); + memcpy (dest->Row, src->Row, (m + 1) * sizeof (long)); + memcpy (dest->Col, src->Col, (d + 1) * sizeof (long)); +} + +/* + * pushQ(lrs_dat *globals,m,d): + * this routine ensures that Qtail points to a record that + * may be copied into. + * + * It may create a new record, or it may just move the head pointer + * forward so that know that the old record has been overwritten. + */ +#if 0 +#define TRACE(s) fprintf(stderr,"\n%s %p %p\n",s,global->Qhead,global->Qtail); +#else +#define TRACE(s) +#endif + +static void +pushQ (lrs_dat * global, long m, long d ,long m_A) +{ + + if ((global->Qtail->next) == global->Qhead) + { + /* the Queue is full */ + if (dict_count < dict_limit) + { + /* but we are allowed to create more */ + lrs_dic *p; + + p = new_lrs_dic (m, d, m_A); + + if (p) + { + + /* we successfully created another record */ + + p->next = global->Qtail->next; + (global->Qtail->next)->prev = p; + (global->Qtail->next) = p; + p->prev = global->Qtail; + + dict_count++; + global->Qtail = p; + + TRACE ("Added new record to Q"); + + } + else + { + /* virtual memory exhausted. bummer */ + global->Qhead = global->Qhead->next; + global->Qtail = global->Qtail->next; + + TRACE ("VM exhausted"); + } + } + else + { + /* + * user defined limit reached. start overwriting the + * beginning of Q + */ + global->Qhead = global->Qhead->next; + global->Qtail = global->Qtail->next; + TRACE ("User limit"); + + } + } + + else + { + global->Qtail = global->Qtail->next; + TRACE ("Reusing"); + } +} + +lrs_dic * +lrs_getdic(lrs_dat *Q) +/* create another dictionary for Q without copying any values */ +/* derived from lrs_alloc_dic, used by nash.c */ +{ +lrs_dic *p; + + long m; + + m = Q->m; + +/* nonnegative flag set means that problem is d rows "bigger" */ +/* since nonnegative constraints are not kept explicitly */ + + + if(Q->nonnegative) + m = m+Q->inputd; + + p = new_lrs_dic (m, Q->inputd, Q->m); + if (!p) + return NULL; + + p->next = p; + p->prev = p; + Q->Qhead = p; + Q->Qtail = p; + + return p; +} + + +#define NULLRETURN(e) if (!(e)) return NULL; + +static lrs_dic * +new_lrs_dic (long m, long d, long m_A) +{ + lrs_dic *p; + + NULLRETURN (p = (lrs_dic *) malloc (sizeof (lrs_dic))); + + + NULLRETURN (p->B = (long int*) calloc ((m + 1), sizeof (long))); + NULLRETURN (p->Row = (long int*) calloc ((m + 1), sizeof (long))); + + NULLRETURN (p->C = (long int*) calloc ((d + 1), sizeof (long))); + NULLRETURN (p->Col = (long int*) calloc ((d + 1), sizeof (long))); + +#ifdef GMP + lrs_alloc_mp(p->det); + lrs_alloc_mp(p->objnum); + lrs_alloc_mp(p->objden); +#endif + + p->d_orig=d; + p->A=lrs_alloc_mp_matrix(m_A,d); + + + return p; +} + +void +lrs_free_dic (lrs_dic * P, lrs_dat *Q) +{ +/* do the same steps as for allocation, but backwards */ +/* gmp variables cannot be cleared using free: use lrs_clear_mp* */ + lrs_dic *P1; + +/* repeat until cache is empty */ + + do + { + /* I moved these here because I'm not certain the cached dictionaries + need to be the same size. Well, it doesn't cost anything to be safe. db */ + + long d = P->d_orig; + long m_A = P->m_A; + + lrs_clear_mp_matrix (P->A,m_A,d); + +/* "it is a ghastly error to free something not assigned my malloc" KR167 */ +/* so don't try: free (P->det); */ + + lrs_clear_mp (P->det); + lrs_clear_mp (P->objnum); + lrs_clear_mp (P->objden); + + free (P->Row); + free (P->Col); + free (P->C); + free (P->B); + +/* go to next record in cache if any */ + P1 =P->next; + free (P); + P=P1; + + } while (Q->Qhead != P ); + + +} + +void +lrs_free_dic2 (lrs_dic * P, lrs_dat *Q) +{ +/* do the same steps as for allocation, but backwards */ +/* same as lrs_free_dic except no cache for P */ + /* I moved these here because I'm not certain the cached dictionaries + need to be the same size. Well, it doesn't cost anything to be safe. db */ + + long d = P->d_orig; + long m_A = P->m_A; + + + lrs_clear_mp_matrix (P->A,m_A,d); + +/* "it is a ghastly error to free something not assigned my malloc" KR167 */ +/* so don't try: free (P->det); */ + +printf("\n hello 2"); fflush(stdout); + lrs_clear_mp (P->det); + lrs_clear_mp (P->objnum); + lrs_clear_mp (P->objden); +printf("\n hello 2"); fflush(stdout); + + free (P->Row); + free (P->Col); + free (P->C); + free (P->B); + +printf("\n hello 2"); fflush(stdout); + free (P); + +} + +void +lrs_free_dat ( lrs_dat *Q ) +{ + long m=Q->m; + +/* most of these items were allocated in lrs_alloc_dic */ + + lrs_clear_mp_vector (Q->Gcd,m); + lrs_clear_mp_vector (Q->Lcm,m); + + lrs_clear_mp (Q->sumdet); + lrs_clear_mp (Q->Nvolume); + lrs_clear_mp (Q->Dvolume); + lrs_clear_mp (Q->saved_det); + lrs_clear_mp (Q->boundd); + lrs_clear_mp (Q->boundn); + + free (Q->inequality); + free (Q->facet); + free (Q->redundcol); + free (Q->linearity); + free (Q->minratio); + free (Q->temparray); + + free (Q->name); + free (Q->saved_C); + + lrs_global_count--; + + free(Q); +} + + +static long +check_cache (lrs_dic ** D_p, lrs_dat * global, long *i_p, long *j_p) +{ +/* assign local variables to structures */ + + + + cache_tries++; + + if (global->Qtail == global->Qhead) + { + TRACE ("cache miss"); + /* Q has only one element */ + cache_misses++; + return 0; + + } + else + { + global->Qtail = global->Qtail->prev; + + *D_p = global->Qtail; + + *i_p = global->Qtail->i; + *j_p = global->Qtail->j; + + TRACE ("restoring dict"); + return 1; + } +} + + +lrs_dic * +lrs_alloc_dic (lrs_dat * Q) +/* allocate and initialize lrs_dic */ +{ + + lrs_dic *p; + long i, j; + long m, d, m_A; + + if (Q->hull) /* d=col dimension of A */ + Q->inputd = Q->n; /* extra column for hull */ + else + Q->inputd = Q->n - 1; + + m = Q->m; + d = Q->inputd; + m_A = m; /* number of rows in A */ + +/* nonnegative flag set means that problem is d rows "bigger" */ +/* since nonnegative constraints are not kept explicitly */ + + if(Q->nonnegative) + m = m+d; + + p = new_lrs_dic (m, d, m_A); + if (!p) + return NULL; + + p->next = p; + p->prev = p; + Q->Qhead = p; + Q->Qtail = p; + + + dict_count = 1; + dict_limit = 50; + cache_tries = 0; + cache_misses = 0; + +/* Initializations */ + + p->d = p->d_orig = d; + p->m = m; + p->m_A = m_A; + p->depth = 0L; + p->lexflag = TRUE; + itomp (ONE, p->det); + itomp (ZERO, p->objnum); + itomp (ONE, p->objden); + +/*m+d+1 is the number of variables, labelled 0,1,2,...,m+d */ +/* initialize array to zero */ + for (i = 0; i <= m_A; i++) + for (j = 0; j <= d; j++) + itomp (ZERO, p->A[i][j]); + + Q->inequality = (long int*) CALLOC ((m + 1), sizeof (long)); + if (Q->nlinearity == ZERO) /* linearity may already be allocated */ + Q->linearity = (long int*) CALLOC ((m + 1), sizeof (long)); + + Q->facet = (long int*) CALLOC ((unsigned) d + 1, sizeof (long)); + Q->redundcol = (long int*) CALLOC ((d + 1), sizeof (long)); + Q->minratio = (long int*) CALLOC ((m + 1), sizeof (long)); + /* 2011.7.14 minratio[m]=0 for degen =1 for nondegen pivot*/ + Q->temparray = (long int*) CALLOC ((unsigned) d + 1, sizeof (long)); + + Q->inequality[0] = 2L; + Q->Gcd = lrs_alloc_mp_vector(m); + Q->Lcm = lrs_alloc_mp_vector(m); + Q->saved_C = (long int*) CALLOC (d + 1, sizeof (long)); + + Q->lastdv = d; /* last decision variable may be decreased */ + /* if there are redundant columns */ + +/*initialize basis and co-basis indices, and row col locations */ +/*if nonnegative, we label differently to avoid initial pivots */ +/* set basic indices and rows */ + if(Q->nonnegative) + for (i = 0; i <= m; i++) + { + p->B[i] = i; + if (i <= d ) + p->Row[i]=0; /* no row for decision variables */ + else + p->Row[i]=i-d; + } + else + for (i = 0; i <= m; i++) + { + if (i == 0 ) + p->B[0]=0; + else + p->B[i] = d + i; + p->Row[i] = i; + } + + for (j = 0; j < d; j++) + { + if(Q->nonnegative) + p->C[j] = m+j+1; + else + p->C[j] = j + 1; + p->Col[j] = j + 1; + } + p->C[d] = m + d + 1; + p->Col[d] = 0; + return p; +} /* end of lrs_alloc_dic */ + + +/* + this routine makes a copy of the information needed to restart, + so that we can guarantee that if a signal is received, we + can guarantee that nobody is messing with it. + This as opposed to adding all kinds of critical regions in + the main line code. + + It is also used to make sure that in case of overflow, we + have a valid cobasis to restart from. + */ +static void +save_basis (lrs_dic * P, lrs_dat * Q) +{ + int i; +/* assign local variables to structures */ + long *C = P->C; + long d; + +#ifdef SIGNALS + sigset_t oset, blockset; + sigemptyset (&blockset); + sigaddset (&blockset, SIGTERM); + sigaddset (&blockset, SIGHUP); + sigaddset (&blockset, SIGUSR1); + + errcheck ("sigprocmask", sigprocmask (SIG_BLOCK, &blockset, &oset)); +#endif + d = P->d; + + Q->saved_flag = 1; + + for (i = 0; i < 3; i++) + Q->saved_count[i] = Q->count[i]; + + for (i = 0; i < d + 1; i++) + Q->saved_C[i] = C[i]; + + copy (Q->saved_det, P->det); + + Q->saved_d = P->d; + Q->saved_depth = P->depth; + +#ifdef SIGNALS + errcheck ("sigprocmask", sigprocmask (SIG_SETMASK, &oset, 0)); +#endif +} + +/* digits overflow is a call from lrs_mp package */ + +void +digits_overflow () +{ + fprintf (lrs_ofp, "\nOverflow at digits=%ld", DIG2DEC (lrs_digits)); + fprintf (lrs_ofp, "\nRerun with option: digits n, where n > %ld\n", DIG2DEC (lrs_digits)); + lrs_dump_state (); + + notimpl(""); +} + +static void +lrs_dump_state () +{ + long i; + + fprintf (stderr, "\n\nlrs_lib: checkpointing:\n"); + + fprintf (stderr, "lrs_lib: Current digits at %ld out of %ld\n", + DIG2DEC (lrs_record_digits), + DIG2DEC (lrs_digits)); + + for (i = 0; i < lrs_global_count; i++) + { + print_basis (stderr, lrs_global_list[i]); + } + fprintf (stderr, "lrs_lib: checkpoint finished\n"); +} + + +/* print out the saved copy of the basis */ +void +print_basis (FILE * fp, lrs_dat * global) +{ + int i; +/* assign local variables to structures */ + fprintf (fp, "lrs_lib: State #%ld: (%s)\t", global->id, global->name); + + if (global->saved_flag) + { + + fprintf (fp, "V#%ld R#%ld B#%ld h=%ld facets ", + global->saved_count[1], + global->saved_count[0], + global->saved_count[2], + global->saved_depth); + for (i = 0; i < global->saved_d; i++) + fprintf (fp, "%ld ", + global->inequality[global->saved_C[i] - global->lastdv]); + pmp (" det=", global->saved_det); + fprintf (fp, "\n"); + + } + else + { + fprintf (fp, "lrs_lib: Computing initial basis\n"); + } + + + fflush (fp); +} + +#ifdef SIGNALS + +/* + If given a signal + USR1 print current cobasis and continue + TERM print current cobasis and terminate + INT (ctrl-C) ditto + HUP ditto + */ +static void +setup_signals () +{ + errcheck ("signal", signal (SIGTERM, die_gracefully)); + errcheck ("signal", signal (SIGALRM, timecheck)); + errcheck ("signal", signal (SIGHUP, die_gracefully)); + errcheck ("signal", signal (SIGINT, die_gracefully)); + errcheck ("signal", signal (SIGUSR1, checkpoint)); +} + +static void +timecheck () +{ + lrs_dump_state (); + errcheck ("signal", signal (SIGALRM, timecheck)); + alarm (lrs_checkpoint_seconds); +} + +static void +checkpoint () +{ + lrs_dump_state (); + errcheck ("signal", signal (SIGUSR1, checkpoint)); +} + +static void +die_gracefully () +{ + lrs_dump_state (); + + exit (1); +} + +#endif + +#ifdef TIMES +/* + * Not sure about the portability of this yet, + * - db + */ +#include <sys/resource.h> +#define double_time(t) ((double)(t.tv_sec)+(double)(t.tv_usec)/1000000) + +static void +ptimes () +{ + struct rusage rusage; + getrusage (RUSAGE_SELF, &rusage); + fprintf (lrs_ofp, "\n*%0.3fu %0.3fs %ldKb %ld flts %ld swaps %ld blks-in %ld blks-out \n", + double_time (rusage.ru_utime), + double_time (rusage.ru_stime), + rusage.ru_maxrss, rusage.ru_majflt, rusage.ru_nswap, + rusage.ru_inblock, rusage.ru_oublock); + if(lrs_ofp != stdout) + printf ("\n*%0.3fu %0.3fs %ldKb %ld flts %ld swaps %ld blks-in %ld blks-out \n", + double_time (rusage.ru_utime), + double_time (rusage.ru_stime), + rusage.ru_maxrss, rusage.ru_majflt, rusage.ru_nswap, + rusage.ru_inblock, rusage.ru_oublock); +} + +static double get_time() +{ + struct rusage rusage; + getrusage (RUSAGE_SELF, &rusage); + return ( double_time (rusage.ru_utime)); + +} + +#endif + +/* Routines based on lp_solve */ + +void +lrs_set_row(lrs_dic *P, lrs_dat *Q, long row, long num[], long den[], long ineq) +/* convert to lrs_mp then call lrs_set_row */ +{ + lrs_mp_vector Num, Den; + long d; + long j; + + d = P->d; + + Num=lrs_alloc_mp_vector(d+1); + Den=lrs_alloc_mp_vector(d+1); + + for (j=0;j<=d;j++) + { + itomp(num[j],Num[j]); + itomp(den[j],Den[j]); + } + + lrs_set_row_mp(P,Q,row,Num,Den,ineq); + + lrs_clear_mp_vector(Num,d+1); + lrs_clear_mp_vector(Den,d+1); + +} + +void +lrs_set_row_mp(lrs_dic *P, lrs_dat *Q, long row, lrs_mp_vector num, lrs_mp_vector den, long ineq) +/* set row of dictionary using num and den arrays for rational input */ +/* ineq = 1 (GE) - ordinary row */ +/* = 0 (EQ) - linearity */ +{ + lrs_mp Temp, mpone; + lrs_mp_vector oD; /* denominator for row */ + + long i, j; + +/* assign local variables to structures */ + + lrs_mp_matrix A; + lrs_mp_vector Gcd, Lcm; + long hull; + long m, d; + lrs_alloc_mp(Temp); lrs_alloc_mp(mpone); + hull = Q->hull; + A = P->A; + m = P->m; + d = P->d; + Gcd = Q->Gcd; + Lcm = Q->Lcm; + + oD = lrs_alloc_mp_vector (d); + itomp (ONE, mpone); + itomp (ONE, oD[0]); + + i=row; + itomp (ONE, Lcm[i]); /* Lcm of denominators */ + itomp (ZERO, Gcd[i]); /* Gcd of numerators */ + for (j = hull; j <= d; j++) /* hull data copied to cols 1..d */ + { + copy( A[i][j],num[j-hull]); + copy(oD[j],den[j-hull]); + if (!one(oD[j])) + lcm (Lcm[i], oD[j]); /* update lcm of denominators */ + copy (Temp, A[i][j]); + gcd (Gcd[i], Temp); /* update gcd of numerators */ + } + + if (hull) + { + itomp (ZERO, A[i][0]); /*for hull, we have to append an extra column of zeroes */ + if (!one (A[i][1]) || !one (oD[1])) /* all rows must have a one in column one */ + Q->polytope = FALSE; + } + if (!zero (A[i][hull])) /* for H-rep, are zero in column 0 */ + Q->homogeneous = FALSE; /* for V-rep, all zero in column 1 */ + + storesign (Gcd[i], POS); + storesign (Lcm[i], POS); + if (mp_greater (Gcd[i], mpone) || mp_greater (Lcm[i], mpone)) + for (j = 0; j <= d; j++) + { + exactdivint (A[i][j], Gcd[i], Temp); /*reduce numerators by Gcd */ + mulint (Lcm[i], Temp, Temp); /*remove denominators */ + exactdivint (Temp, oD[j], A[i][j]); /*reduce by former denominator */ + } + + if ( ineq == EQ ) /* input is linearity */ + { + Q->linearity[Q->nlinearity]=row; + Q->nlinearity++; + } + +/* 2010.4.26 Set Gcd and Lcm for the non-existant rows when nonnegative set */ + + + if(Q->nonnegative && row==m) + for(j=1;j<=d;j++) + { itomp (ONE, Lcm[m+j]); + itomp (ONE, Gcd[m+j]); + } + + + lrs_clear_mp_vector (oD,d); + lrs_clear_mp(Temp); lrs_clear_mp(mpone); +} /* end of lrs_set_row_mp */ + +void +lrs_set_obj(lrs_dic *P, lrs_dat *Q, long num[], long den[], long max) +{ + long i; + + if (max == MAXIMIZE) + Q->maximize=TRUE; + else + { + Q->minimize=TRUE; + for(i=0;i<=P->d;i++) + num[i]=-num[i]; + } + + lrs_set_row(P,Q,0L,num,den,GE); +} + +void +lrs_set_obj_mp(lrs_dic *P, lrs_dat *Q, lrs_mp_vector num, lrs_mp_vector den, long max) +{ + long i; + + if (max == MAXIMIZE) + Q->maximize=TRUE; + else + { + Q->minimize=TRUE; + for(i=0;i<=P->d;i++) + changesign(num[i]); + } + + lrs_set_row_mp(P,Q,0L,num,den,GE); +} + + +long +lrs_solve_lp(lrs_dic *P, lrs_dat *Q) +/* user callable function to solve lp only */ +{ + lrs_mp_matrix Lin; /* holds input linearities if any are found */ + long col; + + Q->lponly = TRUE; + + if (!lrs_getfirstbasis (&P, Q, &Lin, FALSE)) + return FALSE; + +/* There may have been column redundancy */ +/* If so the linearity space is obtained and redundant */ +/* columns are removed. User can access linearity space */ +/* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ + + for (col = 0; col < Q->nredundcol; col++) /* print linearity space */ + lrs_printoutput (Q, Lin[col]); /* Array Lin[][] holds the coeffs. */ + + return TRUE; +} /* end of lrs_solve_lp */ + + +long +dan_selectpivot (lrs_dic * P, lrs_dat * Q, long *r, long *s) +/* select pivot indices using dantzig simplex method */ +/* largest coefficient with lexicographic rule to avoid cycling */ +/* Bohdan Kaluzny's handiwork */ +/* returns TRUE if pivot found else FALSE */ +/* pivot variables are B[*r] C[*s] in locations Row[*r] Col[*s] */ +{ + long j,k,col; + lrs_mp coeff; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *Col = P->Col; + long d = P->d; + + lrs_alloc_mp (coeff); + *r = 0; + *s = d; + j = 0; + k = 0; + + itomp(0,coeff); +/*find positive cost coef */ + while (k < d) + { + if(mp_greater(A[0][Col[k]],coeff)) + { + j = k; + copy(coeff,A[0][Col[j]]); + } + k++; + } + + if (positive(coeff)) /* pivot column found! */ + { + *s = j; + col = Col[j]; + + /*find min index ratio */ + *r = lrs_ratio (P, Q, col); + if (*r != 0) + { + lrs_clear_mp(coeff); + return (TRUE); /* unbounded */ + } + } + lrs_clear_mp(coeff); + return (FALSE); +} /* end of dan_selectpivot */ + + +long +phaseone (lrs_dic * P, lrs_dat * Q) +/* Do a dual pivot to get primal feasibility (pivot in X_0)*/ +/* Bohdan Kaluzny's handiwork */ +{ + long i, j, k; +/* assign local variables to structures */ + lrs_mp_matrix A = P->A; + long *Row = P->Row; + long *Col = P->Col; + long m, d; + lrs_mp b_vector; + lrs_alloc_mp (b_vector); + m = P->m; + d = P->d; + i = 0; + k = d+1; + + itomp(0,b_vector); + + fprintf (lrs_ofp, "\nLP: Phase One: Dual pivot on artificial variable"); + +/*find most negative b vector */ + while (k <= m) + { + if(mp_greater(b_vector,A[Row[k]][0])) + { + i = k; + copy(b_vector,A[Row[i]][0]); + } + k++; + } + + if (negative(b_vector)) /* pivot row found! */ + { + j = 0; /*find a positive entry for in row */ + while (j < d && !positive (A[Row[i]][Col[j]])) + j++; + if (j >= d) + { + lrs_clear_mp (b_vector); + return (FALSE); /* no positive entry */ + } + pivot (P, Q, i, j); + update (P, Q, &i, &j); + } + lrs_clear_mp (b_vector); + return (TRUE); +} + + +long +lrs_set_digits(long dec_digits) +{ +/* convert user specified decimal digits to mp digits */ + + fprintf (lrs_ofp, "\n*digits %ld", dec_digits); + if (dec_digits > 0) + lrs_digits = DEC2DIG (dec_digits); + if (lrs_digits > MAX_DIGITS) + { + fprintf (lrs_ofp, "\nDigits must be at most %ld\nChange MAX_DIGITS and recompile", + DIG2DEC (MAX_DIGITS)); + fflush(stdout); + return (FALSE); + } + return (TRUE); +} + +long +lrs_checkbound(lrs_dic *P, lrs_dat *Q) +{ +/* check bound on objective and return TRUE if exceeded */ + + if(!Q->bound) + return FALSE; + + if( Q->maximize && comprod(Q->boundn,P->objden,P->objnum,Q->boundd) == 1 ) + { + #ifndef PLRS + if(Q->verbose) + { + prat(" \nObj value: ",P->objnum,P->objden); + fprintf(lrs_ofp," Pruning "); + } + #endif + return TRUE; + } + if( Q->minimize && comprod(Q->boundn,P->objden,P->objnum,Q->boundd) == -1 ) + { + #ifndef PLRS + if(Q->verbose) + { + prat(" \nObj value: ",P->objnum,P->objden); + fprintf(lrs_ofp," Pruning "); + } + #endif + return TRUE; + } + return FALSE; +} + + +long +lrs_leaf(lrs_dic *P, lrs_dat *Q) +{ +/* check if current dictionary is a leaf of reverse search tree */ + long col=0; + long tmp=0; + + while (col < P->d && !reverse(P,Q,&tmp,col)) + col++; + if(col < P->d) + return 0; /* dictionary is not a leaf */ + else + return 1; +}