#include "setoper.h"
#include "cdd.h"
#include "random.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#if defined GMPRATIONAL
#include "cdd_f.h"
#endif
#include "random.h"
#define dd_CDDLPVERSION "Version 0.94b (August 25, 2005)"
#define dd_FALSE 0
#define dd_TRUE 1
typedef set_type rowset;
typedef set_type colset;
void dd_CrissCrossSolve(dd_LPPtr lp,dd_ErrorType *);
void dd_DualSimplexSolve(dd_LPPtr lp,dd_ErrorType *);
void dd_CrissCrossMinimize(dd_LPPtr,dd_ErrorType *);
void dd_CrissCrossMaximize(dd_LPPtr,dd_ErrorType *);
void dd_DualSimplexMinimize(dd_LPPtr,dd_ErrorType *);
void dd_DualSimplexMaximize(dd_LPPtr,dd_ErrorType *);
void dd_FindLPBasis(dd_rowrange,dd_colrange,dd_Amatrix,dd_Bmatrix,dd_rowindex,dd_rowset,
dd_colindex,dd_rowindex,dd_rowrange,dd_colrange,
dd_colrange *,int *,dd_LPStatusType *,long *);
void dd_FindDualFeasibleBasis(dd_rowrange,dd_colrange,dd_Amatrix,dd_Bmatrix,dd_rowindex,
dd_colindex,long *,dd_rowrange,dd_colrange,dd_boolean,
dd_colrange *,dd_ErrorType *,dd_LPStatusType *,long *, long maxpivots);
#ifdef GMPRATIONAL
void dd_BasisStatus(ddf_LPPtr lpf, dd_LPPtr lp, dd_boolean*);
void dd_BasisStatusMinimize(dd_rowrange,dd_colrange, dd_Amatrix,dd_Bmatrix,dd_rowset,
dd_rowrange,dd_colrange,ddf_LPStatusType,mytype *,dd_Arow,dd_Arow,dd_rowset,ddf_colindex,
ddf_rowrange,ddf_colrange,dd_colrange *,long *, int *, int *);
void dd_BasisStatusMaximize(dd_rowrange,dd_colrange,dd_Amatrix,dd_Bmatrix,dd_rowset,
dd_rowrange,dd_colrange,ddf_LPStatusType,mytype *,dd_Arow,dd_Arow,dd_rowset,ddf_colindex,
ddf_rowrange,ddf_colrange,dd_colrange *,long *, int *, int *);
#endif
void dd_WriteBmatrix(FILE *f,dd_colrange d_size,dd_Bmatrix T);
void dd_SetNumberType(char *line,dd_NumberType *number,dd_ErrorType *Error);
void dd_ComputeRowOrderVector2(dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,
dd_rowindex OV,dd_RowOrderType ho,unsigned int rseed);
void dd_SelectPreorderedNext2(dd_rowrange m_size,dd_colrange d_size,
rowset excluded,dd_rowindex OV,dd_rowrange *hnext);
void dd_SetSolutions(dd_rowrange,dd_colrange,
dd_Amatrix,dd_Bmatrix,dd_rowrange,dd_colrange,dd_LPStatusType,
mytype *,dd_Arow,dd_Arow,dd_rowset,dd_colindex,dd_rowrange,dd_colrange,dd_rowindex);
void dd_WriteTableau(FILE *,dd_rowrange,dd_colrange,dd_Amatrix,dd_Bmatrix,
dd_colindex,dd_rowindex);
void dd_WriteSignTableau(FILE *,dd_rowrange,dd_colrange,dd_Amatrix,dd_Bmatrix,
dd_colindex,dd_rowindex);
dd_LPSolutionPtr dd_CopyLPSolution(dd_LPPtr lp)
{
dd_LPSolutionPtr lps;
dd_colrange j;
long i;
lps=(dd_LPSolutionPtr) calloc(1,sizeof(dd_LPSolutionType));
for (i=1; i<=dd_filenamelen; i++) lps->filename[i-1]=lp->filename[i-1];
lps->objective=lp->objective;
lps->solver=lp->solver;
lps->m=lp->m;
lps->d=lp->d;
lps->numbtype=lp->numbtype;
lps->LPS=lp->LPS;
dd_init(lps->optvalue);
dd_set(lps->optvalue,lp->optvalue);
dd_InitializeArow(lp->d+1,&(lps->sol));
dd_InitializeArow(lp->d+1,&(lps->dsol));
lps->nbindex=(long*) calloc((lp->d)+1,sizeof(long));
for (j=0; j<=lp->d; j++){
dd_set(lps->sol[j],lp->sol[j]);
dd_set(lps->dsol[j],lp->dsol[j]);
lps->nbindex[j]=lp->nbindex[j];
}
lps->pivots[0]=lp->pivots[0];
lps->pivots[1]=lp->pivots[1];
lps->pivots[2]=lp->pivots[2];
lps->pivots[3]=lp->pivots[3];
lps->pivots[4]=lp->pivots[4];
lps->total_pivots=lp->total_pivots;
return lps;
}
dd_LPPtr dd_CreateLPData(dd_LPObjectiveType obj,
dd_NumberType nt,dd_rowrange m,dd_colrange d)
{
dd_LPType *lp;
lp=(dd_LPPtr) calloc(1,sizeof(dd_LPType));
lp->solver=dd_choiceLPSolverDefault;
lp->d=d;
lp->m=m;
lp->numbtype=nt;
lp->objrow=m;
lp->rhscol=1L;
lp->objective=dd_LPnone;
lp->LPS=dd_LPSundecided;
lp->eqnumber=0;
lp->nbindex=(long*) calloc(d+1,sizeof(long));
lp->given_nbindex=(long*) calloc(d+1,sizeof(long));
set_initialize(&(lp->equalityset),m);
lp->redcheck_extensive=dd_FALSE;
lp->ired=0;
set_initialize(&(lp->redset_extra),m);
set_initialize(&(lp->redset_accum),m);
set_initialize(&(lp->posset_extra),m);
lp->lexicopivot=dd_choiceLexicoPivotQ;
lp->m_alloc=lp->m+2;
lp->d_alloc=lp->d+2;
lp->objective=obj;
dd_InitializeBmatrix(lp->d_alloc,&(lp->B));
dd_InitializeAmatrix(lp->m_alloc,lp->d_alloc,&(lp->A));
dd_InitializeArow(lp->d_alloc,&(lp->sol));
dd_InitializeArow(lp->d_alloc,&(lp->dsol));
dd_init(lp->optvalue);
return lp;
}
dd_LPPtr dd_Matrix2LP(dd_MatrixPtr M, dd_ErrorType *err)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPType *lp;
dd_boolean localdebug=dd_FALSE;
*err=dd_NoError;
linc=set_card(M->linset);
m=M->rowsize+1+linc;
d=M->colsize;
if (localdebug) fprintf(stderr,"number of equalities = %ld\n", linc);
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_TRUE;
lp->eqnumber=linc;
irev=M->rowsize;
for (i = 1; i <= M->rowsize; i++) {
if (set_member(i, M->linset)) {
irev=irev+1;
set_addelem(lp->equalityset,i);
for (j = 1; j <= M->colsize; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-1]);
}
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
}
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-1]);
if (j==1 && i<M->rowsize && dd_Nonzero(M->matrix[i-1][j-1])) lp->Homogeneous = dd_FALSE;
}
}
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[m-1][j-1],M->rowvec[j-1]);
}
return lp;
}
dd_LPPtr dd_Matrix2Feasibility(dd_MatrixPtr M, dd_ErrorType *err)
{
dd_rowrange m, linc;
dd_colrange j;
dd_LPType *lp;
*err=dd_NoError;
linc=set_card(M->linset);
m=M->rowsize+1+linc;
lp=dd_Matrix2LP(M, err);
lp->objective = dd_LPmax;
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[m-1][j-1],dd_purezero);
}
return lp;
}
dd_LPPtr dd_Matrix2Feasibility2(dd_MatrixPtr M, dd_rowset R, dd_rowset S, dd_ErrorType *err)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPType *lp;
dd_rowset L;
dd_boolean localdebug=dd_FALSE;
*err=dd_NoError;
set_initialize(&L, M->rowsize);
set_uni(L,M->linset,R);
linc=set_card(L);
m=M->rowsize+1+linc+1;
d=M->colsize+1;
if (localdebug) fprintf(stderr,"number of equalities = %ld\n", linc);
lp=dd_CreateLPData(dd_LPmax, M->numbtype, m, d);
lp->Homogeneous = dd_TRUE;
lp->eqnumber=linc;
irev=M->rowsize;
for (i = 1; i <= M->rowsize; i++) {
if (set_member(i, L)) {
irev=irev+1;
set_addelem(lp->equalityset,i);
for (j = 1; j <= M->colsize; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-1]);
}
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
} else if (set_member(i, S)) {
dd_set(lp->A[i-1][M->colsize],dd_minusone);
}
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-1]);
if (j==1 && i<M->rowsize && dd_Nonzero(M->matrix[i-1][j-1])) lp->Homogeneous = dd_FALSE;
}
}
for (j = 1; j <= d; j++) {
dd_set(lp->A[m-2][j-1],dd_purezero);
}
dd_set(lp->A[m-2][0],dd_one);
dd_set(lp->A[m-2][M->colsize],dd_minusone);
for (j = 1; j <= d; j++) {
dd_set(lp->A[m-1][j-1],dd_purezero);
}
dd_set(lp->A[m-1][M->colsize],dd_one);
set_free(L);
return lp;
}
void dd_FreeLPData(dd_LPPtr lp)
{
if ((lp)!=NULL){
dd_clear(lp->optvalue);
dd_FreeArow(lp->d_alloc,lp->dsol);
dd_FreeArow(lp->d_alloc,lp->sol);
dd_FreeBmatrix(lp->d_alloc,lp->B);
dd_FreeAmatrix(lp->m_alloc,lp->d_alloc,lp->A);
set_free(lp->equalityset);
set_free(lp->redset_extra);
set_free(lp->redset_accum);
set_free(lp->posset_extra);
free(lp->nbindex);
free(lp->given_nbindex);
free(lp);
}
}
void dd_FreeLPSolution(dd_LPSolutionPtr lps)
{
if (lps!=NULL){
free(lps->nbindex);
dd_FreeArow(lps->d+1,lps->dsol);
dd_FreeArow(lps->d+1,lps->sol);
dd_clear(lps->optvalue);
free(lps);
}
}
int dd_LPReverseRow(dd_LPPtr lp, dd_rowrange i)
{
dd_colrange j;
int success=0;
if (i>=1 && i<=lp->m){
lp->LPS=dd_LPSundecided;
for (j=1; j<=lp->d; j++) {
dd_neg(lp->A[i-1][j-1],lp->A[i-1][j-1]);
}
success=1;
}
return success;
}
int dd_LPReplaceRow(dd_LPPtr lp, dd_rowrange i, dd_Arow a)
{
dd_colrange j;
int success=0;
if (i>=1 && i<=lp->m){
lp->LPS=dd_LPSundecided;
for (j=1; j<=lp->d; j++) {
dd_set(lp->A[i-1][j-1],a[j-1]);
}
success=1;
}
return success;
}
dd_Arow dd_LPCopyRow(dd_LPPtr lp, dd_rowrange i)
{
dd_colrange j;
dd_Arow a;
if (i>=1 && i<=lp->m){
dd_InitializeArow(lp->d, &a);
for (j=1; j<=lp->d; j++) {
dd_set(a[j-1],lp->A[i-1][j-1]);
}
}
return a;
}
void dd_SetNumberType(char *line,dd_NumberType *number,dd_ErrorType *Error)
{
if (strncmp(line,"integer",7)==0) {
*number = dd_Integer;
return;
}
else if (strncmp(line,"rational",8)==0) {
*number = dd_Rational;
return;
}
else if (strncmp(line,"real",4)==0) {
*number = dd_Real;
return;
}
else {
*number=dd_Unknown;
*Error=dd_ImproperInputFormat;
}
}
void dd_WriteTableau(FILE *f,dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_colindex nbindex,dd_rowindex bflag)
{
dd_colrange j;
dd_rowrange i;
mytype x;
dd_init(x);
fprintf(f," %ld %ld real\n",m_size,d_size);
fprintf(f," |");
for (j=1; j<= d_size; j++) {
fprintf(f," %ld",nbindex[j]);
} fprintf(f,"\n");
for (j=1; j<= d_size+1; j++) {
fprintf(f," ----");
} fprintf(f,"\n");
for (i=1; i<= m_size; i++) {
fprintf(f," %3ld(%3ld) |",i,bflag[i]);
for (j=1; j<= d_size; j++) {
dd_TableauEntry(&x,m_size,d_size,A,T,i,j);
dd_WriteNumber(f,x);
}
fprintf(f,"\n");
}
fprintf(f,"end\n");
dd_clear(x);
}
void dd_WriteSignTableau(FILE *f,dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_colindex nbindex,dd_rowindex bflag)
{
dd_colrange j;
dd_rowrange i;
mytype x;
dd_init(x);
fprintf(f," %ld %ld real\n",m_size,d_size);
fprintf(f," |");
for (j=1; j<= d_size; j++) {
fprintf(f,"%3ld",nbindex[j]);
} fprintf(f,"\n ------- | ");
for (j=1; j<= d_size; j++) {
fprintf(f,"---");
} fprintf(f,"\n");
for (i=1; i<= m_size; i++) {
fprintf(f," %3ld(%3ld) |",i,bflag[i]);
for (j=1; j<= d_size; j++) {
dd_TableauEntry(&x,m_size,d_size,A,T,i,j);
if (dd_Positive(x)) fprintf(f, " +");
else if (dd_Negative(x)) fprintf(f, " -");
else fprintf(f, " 0");
}
fprintf(f,"\n");
}
fprintf(f,"end\n");
dd_clear(x);
}
void dd_WriteSignTableau2(FILE *f,dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_colindex nbindex_ref, dd_colindex nbindex,dd_rowindex bflag)
{
dd_colrange j;
dd_rowrange i;
mytype x;
dd_init(x);
fprintf(f," %ld %ld real\n",m_size,d_size);
fprintf(f," |");
for (j=1; j<= d_size; j++) fprintf(f,"%3ld",nbindex_ref[j]);
fprintf(f,"\n |");
for (j=1; j<= d_size; j++) {
fprintf(f,"%3ld",nbindex[j]);
} fprintf(f,"\n ------- | ");
for (j=1; j<= d_size; j++) {
fprintf(f,"---");
} fprintf(f,"\n");
for (i=1; i<= m_size; i++) {
fprintf(f," %3ld(%3ld) |",i,bflag[i]);
for (j=1; j<= d_size; j++) {
dd_TableauEntry(&x,m_size,d_size,A,T,i,j);
if (dd_Positive(x)) fprintf(f, " +");
else if (dd_Negative(x)) fprintf(f, " -");
else fprintf(f, " 0");
}
fprintf(f,"\n");
}
fprintf(f,"end\n");
dd_clear(x);
}
void dd_GetRedundancyInformation(dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_colindex nbindex,dd_rowindex bflag, dd_rowset redset)
{
dd_colrange j;
dd_rowrange i;
mytype x;
dd_boolean red=dd_FALSE,localdebug=dd_FALSE;
long numbred=0;
dd_init(x);
for (i=1; i<= m_size; i++) {
red=dd_TRUE;
for (j=1; j<= d_size; j++) {
dd_TableauEntry(&x,m_size,d_size,A,T,i,j);
if (red && dd_Negative(x)) red=dd_FALSE;
}
if (bflag[i]<0 && red) {
numbred+=1;
set_addelem(redset,i);
}
}
if (localdebug) fprintf(stderr,"\ndd_GetRedundancyInformation: %ld redundant rows over %ld\n",numbred, m_size);
dd_clear(x);
}
void dd_SelectDualSimplexPivot(dd_rowrange m_size,dd_colrange d_size,
int Phase1,dd_Amatrix A,dd_Bmatrix T,dd_rowindex OV,
dd_colindex nbindex_ref, dd_colindex nbindex,dd_rowindex bflag,
dd_rowrange objrow,dd_colrange rhscol, dd_boolean lexicopivot,
dd_rowrange *r,dd_colrange *s,int *selected,dd_LPStatusType *lps)
{
dd_boolean colselected=dd_FALSE,rowselected=dd_FALSE,
dualfeasible=dd_TRUE,localdebug=dd_FALSE;
dd_rowrange i,iref;
dd_colrange j,k;
mytype val,valn, minval,rat,minrat;
static dd_Arow rcost;
static dd_colrange d_last=0;
static dd_colset tieset,stieset;
dd_init(val); dd_init(valn); dd_init(minval); dd_init(rat); dd_init(minrat);
if (d_last<d_size) {
if (d_last>0) {
for (j=1; j<=d_last; j++){ dd_clear(rcost[j-1]);}
free(rcost);
set_free(tieset);
set_free(stieset);
}
rcost=(mytype*) calloc(d_size,sizeof(mytype));
for (j=1; j<=d_size; j++){ dd_init(rcost[j-1]);}
set_initialize(&tieset,d_size);
set_initialize(&stieset,d_size);
}
d_last=d_size;
*r=0; *s=0;
*selected=dd_FALSE;
*lps=dd_LPSundecided;
for (j=1; j<=d_size; j++){
if (j!=rhscol){
dd_TableauEntry(&(rcost[j-1]),m_size,d_size,A,T,objrow,j);
if (dd_Positive(rcost[j-1])) {
dualfeasible=dd_FALSE;
}
}
}
if (dualfeasible){
while ((*lps==dd_LPSundecided) && (!rowselected) && (!colselected)) {
for (i=1; i<=m_size; i++) {
if (i!=objrow && bflag[i]==-1) {
if (Phase1){
dd_TableauEntry(&val, m_size,d_size,A,T,i,bflag[m_size]);
dd_neg(val,val);
}
else {dd_TableauEntry(&val,m_size,d_size,A,T,i,rhscol);}
if (dd_Smaller(val,minval)) {
*r=i;
dd_set(minval,val);
}
}
}
if (dd_Nonnegative(minval)) {
*lps=dd_Optimal;
}
else {
rowselected=dd_TRUE;
set_emptyset(tieset);
for (j=1; j<=d_size; j++){
dd_TableauEntry(&val,m_size,d_size,A,T,*r,j);
if (j!=rhscol && dd_Positive(val)) {
dd_div(rat,rcost[j-1],val);
dd_neg(rat,rat);
if (*s==0 || dd_Smaller(rat,minrat)){
dd_set(minrat,rat);
*s=j;
set_emptyset(tieset);
set_addelem(tieset, j);
} else if (dd_Equal(rat,minrat)){
set_addelem(tieset,j);
}
}
}
if (*s>0) {
if (!lexicopivot || set_card(tieset)==1){
colselected=dd_TRUE; *selected=dd_TRUE;
} else {
if (localdebug) {printf("Tie occurred at:"); set_write(tieset); printf("\n");
dd_WriteTableau(stderr,m_size,d_size,A,T,nbindex,bflag);
}
*s=0;
k=2;
do {
iref=nbindex_ref[k];
if (iref>0) {
j=bflag[iref];
if (j>0) {
if (set_member(j,tieset) && set_card(tieset)==1) {
*s=j;
colselected=dd_TRUE;
} else {
set_delelem(tieset, j);
}
} else {
*s=0;
for (j=1; j<=d_size; j++){
if (set_member(j,tieset)) {
dd_TableauEntry(&val,m_size,d_size,A,T,*r,j);
dd_TableauEntry(&valn,m_size,d_size,A,T,iref,j);
if (j!=rhscol && dd_Positive(val)) {
dd_div(rat,valn,val);
if (*s==0 || dd_Smaller(rat,minrat)){
dd_set(minrat,rat);
*s=j;
set_emptyset(stieset);
set_addelem(stieset, j);
} else if (dd_Equal(rat,minrat)){
set_addelem(stieset,j);
}
}
}
}
set_copy(tieset,stieset);
if (set_card(tieset)==1) colselected=dd_TRUE;
}
}
k+=1;
} while (!colselected && k<=d_size);
*selected=dd_TRUE;
}
} else *lps=dd_Inconsistent;
}
}
}
if (localdebug) {
if (Phase1) fprintf(stderr,"Phase 1 : select %ld,%ld\n",*r,*s);
else fprintf(stderr,"Phase 2 : select %ld,%ld\n",*r,*s);
}
dd_clear(val); dd_clear(valn); dd_clear(minval); dd_clear(rat); dd_clear(minrat);
}
void dd_TableauEntry(mytype *x,dd_rowrange m_size, dd_colrange d_size, dd_Amatrix X, dd_Bmatrix T,
dd_rowrange r, dd_colrange s)
{
dd_colrange j;
mytype temp;
dd_init(temp);
dd_set(*x,dd_purezero);
for (j=0; j< d_size; j++) {
dd_mul(temp,X[r-1][j], T[j][s-1]);
dd_add(*x, *x, temp);
}
dd_clear(temp);
}
void dd_SelectPivot2(dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_RowOrderType roworder,dd_rowindex ordervec, rowset equalityset,
dd_rowrange rowmax,rowset NopivotRow,
colset NopivotCol,dd_rowrange *r,dd_colrange *s,
dd_boolean *selected)
{
int stop;
dd_rowrange i,rtemp;
rowset rowexcluded;
mytype Xtemp;
dd_boolean localdebug=dd_FALSE;
stop = dd_FALSE;
localdebug=dd_debug;
dd_init(Xtemp);
set_initialize(&rowexcluded,m_size);
set_copy(rowexcluded,NopivotRow);
for (i=rowmax+1;i<=m_size;i++) {
set_addelem(rowexcluded,i);
}
*selected = dd_FALSE;
do {
rtemp=0; i=1;
while (i<=m_size && rtemp==0) {
if (set_member(i,equalityset) && !set_member(i,rowexcluded)){
if (localdebug) fprintf(stderr,"marked set %ld chosen as a candidate\n",i);
rtemp=i;
}
i++;
}
if (rtemp==0) dd_SelectPreorderedNext2(m_size,d_size,rowexcluded,ordervec,&rtemp);;
if (rtemp>=1) {
*r=rtemp;
*s=1;
while (*s <= d_size && !*selected) {
dd_TableauEntry(&Xtemp,m_size,d_size,A,T,*r,*s);
if (!set_member(*s,NopivotCol) && dd_Nonzero(Xtemp)) {
*selected = dd_TRUE;
stop = dd_TRUE;
} else {
(*s)++;
}
}
if (!*selected) {
set_addelem(rowexcluded,rtemp);
}
}
else {
*r = 0;
*s = 0;
stop = dd_TRUE;
}
} while (!stop);
set_free(rowexcluded); dd_clear(Xtemp);
}
void dd_GaussianColumnPivot(dd_rowrange m_size, dd_colrange d_size,
dd_Amatrix X, dd_Bmatrix T, dd_rowrange r, dd_colrange s)
{
dd_colrange j, j1;
mytype Xtemp0, Xtemp1, Xtemp;
static dd_Arow Rtemp;
static dd_colrange last_d=0;
dd_init(Xtemp0); dd_init(Xtemp1); dd_init(Xtemp);
if (last_d!=d_size){
if (last_d>0) {
for (j=1; j<=last_d; j++) dd_clear(Rtemp[j-1]);
free(Rtemp);
}
Rtemp=(mytype*)calloc(d_size,sizeof(mytype));
for (j=1; j<=d_size; j++) dd_init(Rtemp[j-1]);
last_d=d_size;
}
for (j=1; j<=d_size; j++) {
dd_TableauEntry(&(Rtemp[j-1]), m_size, d_size, X, T, r,j);
}
dd_set(Xtemp0,Rtemp[s-1]);
for (j = 1; j <= d_size; j++) {
if (j != s) {
dd_div(Xtemp,Rtemp[j-1],Xtemp0);
dd_set(Xtemp1,dd_purezero);
for (j1 = 1; j1 <= d_size; j1++){
dd_mul(Xtemp1,Xtemp,T[j1-1][s - 1]);
dd_sub(T[j1-1][j-1],T[j1-1][j-1],Xtemp1);
}
}
}
for (j = 1; j <= d_size; j++)
dd_div(T[j-1][s - 1],T[j-1][s - 1],Xtemp0);
dd_clear(Xtemp0); dd_clear(Xtemp1); dd_clear(Xtemp);
}
void dd_GaussianColumnPivot2(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A,dd_Bmatrix T,dd_colindex nbindex,dd_rowindex bflag,dd_rowrange r,dd_colrange s)
{
int localdebug=dd_FALSE;
long entering;
if (dd_debug) localdebug=dd_debug;
dd_GaussianColumnPivot(m_size,d_size,A,T,r,s);
entering=nbindex[s];
bflag[r]=s;
nbindex[s]=r;
if (entering>0) bflag[entering]=-1;
if (localdebug) {
fprintf(stderr,"dd_GaussianColumnPivot2\n");
fprintf(stderr," pivot: (leaving, entering) = (%ld, %ld)\n", r,entering);
fprintf(stderr, " bflag[%ld] is set to %ld\n", r, s);
}
}
void dd_ResetTableau(dd_rowrange m_size,dd_colrange d_size,dd_Bmatrix T,
dd_colindex nbindex,dd_rowindex bflag,dd_rowrange objrow,dd_colrange rhscol)
{
dd_rowrange i;
dd_colrange j;
for (j=1; j<=d_size; j++) nbindex[j]=-j;
nbindex[rhscol]=0;
dd_SetToIdentity(d_size,T);
for (i=1; i<=m_size; i++) bflag[i]=-1;
bflag[objrow]= 0;
for (j=1; j<=d_size; j++) if (nbindex[j]>0) bflag[nbindex[j]]=j;
}
void dd_SelectCrissCrossPivot(dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_rowindex bflag,dd_rowrange objrow,dd_colrange rhscol,
dd_rowrange *r,dd_colrange *s,
int *selected,dd_LPStatusType *lps)
{
int colselected=dd_FALSE,rowselected=dd_FALSE;
dd_rowrange i;
mytype val;
dd_init(val);
*selected=dd_FALSE;
*lps=dd_LPSundecided;
while ((*lps==dd_LPSundecided) && (!rowselected) && (!colselected)) {
for (i=1; i<=m_size; i++) {
if (i!=objrow && bflag[i]==-1) {
dd_TableauEntry(&val,m_size,d_size,A,T,i,rhscol);
if (dd_Negative(val)) {
rowselected=dd_TRUE;
*r=i;
break;
}
}
else if (bflag[i] >0) {
dd_TableauEntry(&val,m_size,d_size,A,T,objrow,bflag[i]);
if (dd_Positive(val)) {
colselected=dd_TRUE;
*s=bflag[i];
break;
}
}
}
if ((!rowselected) && (!colselected)) {
*lps=dd_Optimal;
return;
}
else if (rowselected) {
for (i=1; i<=m_size; i++) {
if (bflag[i] >0) {
dd_TableauEntry(&val,m_size,d_size,A,T,*r,bflag[i]);
if (dd_Positive(val)) {
colselected=dd_TRUE;
*s=bflag[i];
*selected=dd_TRUE;
break;
}
}
}
}
else if (colselected) {
for (i=1; i<=m_size; i++) {
if (i!=objrow && bflag[i]==-1) {
dd_TableauEntry(&val,m_size,d_size,A,T,i,*s);
if (dd_Negative(val)) {
rowselected=dd_TRUE;
*r=i;
*selected=dd_TRUE;
break;
}
}
}
}
if (!rowselected) {
*lps=dd_DualInconsistent;
}
else if (!colselected) {
*lps=dd_Inconsistent;
}
}
dd_clear(val);
}
void dd_CrissCrossSolve(dd_LPPtr lp, dd_ErrorType *err)
{
switch (lp->objective) {
case dd_LPmax:
dd_CrissCrossMaximize(lp,err);
break;
case dd_LPmin:
dd_CrissCrossMinimize(lp,err);
break;
case dd_LPnone: *err=dd_NoLPObjective; break;
}
}
void dd_DualSimplexSolve(dd_LPPtr lp, dd_ErrorType *err)
{
switch (lp->objective) {
case dd_LPmax:
dd_DualSimplexMaximize(lp,err);
break;
case dd_LPmin:
dd_DualSimplexMinimize(lp,err);
break;
case dd_LPnone: *err=dd_NoLPObjective; break;
}
}
#ifdef GMPRATIONAL
dd_LPStatusType LPSf2LPS(ddf_LPStatusType lpsf)
{
dd_LPStatusType lps=dd_LPSundecided;
switch (lpsf) {
case ddf_LPSundecided: lps=dd_LPSundecided; break;
case ddf_Optimal: lps=dd_Optimal; break;
case ddf_Inconsistent: lps=dd_Inconsistent; break;
case ddf_DualInconsistent: lps=dd_DualInconsistent; break;
case ddf_StrucInconsistent: lps=dd_StrucInconsistent; break;
case ddf_StrucDualInconsistent: lps=dd_StrucDualInconsistent; break;
case ddf_Unbounded: lps=dd_Unbounded; break;
case ddf_DualUnbounded: lps=dd_DualUnbounded; break;
}
return lps;
}
void dd_BasisStatus(ddf_LPPtr lpf, dd_LPPtr lp, dd_boolean *LPScorrect)
{
int i;
dd_colrange se, j;
dd_boolean basisfound;
switch (lp->objective) {
case dd_LPmax:
dd_BasisStatusMaximize(lp->m,lp->d,lp->A,lp->B,lp->equalityset,lp->objrow,lp->rhscol,
lpf->LPS,&(lp->optvalue),lp->sol,lp->dsol,lp->posset_extra,lpf->nbindex,lpf->re,lpf->se,&se,lp->pivots,
&basisfound, LPScorrect);
if (*LPScorrect) {
lp->LPS=LPSf2LPS(lpf->LPS);
lp->re=lpf->re;
lp->se=se;
for (j=1; j<=lp->d; j++) lp->nbindex[j]=lpf->nbindex[j];
}
for (i=1; i<=5; i++) lp->pivots[i-1]+=lpf->pivots[i-1];
break;
case dd_LPmin:
dd_BasisStatusMinimize(lp->m,lp->d,lp->A,lp->B,lp->equalityset,lp->objrow,lp->rhscol,
lpf->LPS,&(lp->optvalue),lp->sol,lp->dsol,lp->posset_extra,lpf->nbindex,lpf->re,lpf->se,&se,lp->pivots,
&basisfound, LPScorrect);
if (*LPScorrect) {
lp->LPS=LPSf2LPS(lpf->LPS);
lp->re=lpf->re;
lp->se=se;
for (j=1; j<=lp->d; j++) lp->nbindex[j]=lpf->nbindex[j];
}
for (i=1; i<=5; i++) lp->pivots[i-1]+=lpf->pivots[i-1];
break;
case dd_LPnone: break;
}
}
#endif
void dd_FindLPBasis(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A, dd_Bmatrix T,dd_rowindex OV,dd_rowset equalityset, dd_colindex nbindex,
dd_rowindex bflag,dd_rowrange objrow,dd_colrange rhscol,
dd_colrange *cs,int *found,dd_LPStatusType *lps,long *pivot_no)
{
int chosen,stop;
long pivots_p0=0,rank;
colset ColSelected;
rowset RowSelected;
mytype val;
dd_rowrange r;
dd_colrange j,s;
dd_init(val);
*found=dd_FALSE; *cs=0; rank=0;
stop=dd_FALSE;
*lps=dd_LPSundecided;
set_initialize(&RowSelected,m_size);
set_initialize(&ColSelected,d_size);
set_addelem(RowSelected,objrow);
set_addelem(ColSelected,rhscol);
stop=dd_FALSE;
do {
dd_SelectPivot2(m_size,d_size,A,T,dd_MinIndex,OV,equalityset,
m_size,RowSelected,ColSelected,&r,&s,&chosen);
if (chosen) {
set_addelem(RowSelected,r);
set_addelem(ColSelected,s);
dd_GaussianColumnPivot2(m_size,d_size,A,T,nbindex,bflag,r,s);
pivots_p0++;
rank++;
} else {
for (j=1;j<=d_size && *lps==dd_LPSundecided; j++) {
if (j!=rhscol && nbindex[j]<0){
dd_TableauEntry(&val,m_size,d_size,A,T,objrow,j);
if (dd_Nonzero(val)){
*lps=dd_StrucDualInconsistent;
*cs=j;
}
}
}
if (*lps==dd_LPSundecided) *found=dd_TRUE;
stop=dd_TRUE;
}
if (rank==d_size-1) {
stop = dd_TRUE;
*found=dd_TRUE;
}
} while (!stop);
*pivot_no=pivots_p0;
dd_statBApivots+=pivots_p0;
set_free(RowSelected);
set_free(ColSelected);
dd_clear(val);
}
void dd_FindLPBasis2(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A, dd_Bmatrix T,dd_rowindex OV,dd_rowset equalityset, dd_colindex nbindex,
dd_rowindex bflag,dd_rowrange objrow,dd_colrange rhscol,
dd_colrange *cs,int *found,long *pivot_no)
{
int chosen,stop;
long pivots_p0=0,rank;
dd_colset ColSelected,DependentCols;
dd_rowset RowSelected, NopivotRow;
mytype val;
dd_boolean localdebug=dd_FALSE;
dd_rowrange r,negcount=0;
dd_colrange j,s;
dd_init(val);
*found=dd_FALSE; *cs=0; rank=0;
set_initialize(&RowSelected,m_size);
set_initialize(&DependentCols,d_size);
set_initialize(&ColSelected,d_size);
set_initialize(&NopivotRow,m_size);
set_addelem(RowSelected,objrow);
set_addelem(ColSelected,rhscol);
set_compl(NopivotRow, NopivotRow);
for (j=2; j<=d_size; j++)
if (nbindex[j]>0)
set_delelem(NopivotRow, nbindex[j]);
else if (nbindex[j]<0){
negcount++;
set_addelem(DependentCols, -nbindex[j]);
set_addelem(ColSelected, -nbindex[j]);
}
set_uni(RowSelected, RowSelected, NopivotRow);
stop=dd_FALSE;
do {
dd_SelectPivot2(m_size,d_size,A,T,dd_MinIndex,OV,equalityset, m_size,RowSelected,ColSelected,&r,&s,&chosen);
if (chosen) {
set_addelem(RowSelected,r);
set_addelem(ColSelected,s);
dd_GaussianColumnPivot2(m_size,d_size,A,T,nbindex,bflag,r,s);
if (localdebug && m_size <=10){
dd_WriteBmatrix(stderr,d_size,T);
dd_WriteTableau(stderr,m_size,d_size,A,T,nbindex,bflag);
}
pivots_p0++;
rank++;
} else{
*found=dd_FALSE;
stop=dd_TRUE;
}
if (rank==d_size-1-negcount) {
if (negcount){
set_diff(ColSelected, ColSelected, DependentCols);
dd_SelectPivot2(m_size,d_size,A,T,dd_MinIndex,OV,equalityset, m_size,RowSelected,ColSelected,&r,&s,&chosen);
if (chosen) *found=dd_FALSE;
else *found=dd_TRUE;
if (localdebug){
printf("Try to check the dependent cols:");
set_write(DependentCols);
if (chosen) printf("They are not dependent. Can still pivot on (%ld, %ld)\n",r, s);
else printf("They are indeed dependent.\n");
}
} else {
*found=dd_TRUE;
}
stop = dd_TRUE;
}
} while (!stop);
for (j=1; j<=d_size; j++) if (nbindex[j]>0) bflag[nbindex[j]]=j;
*pivot_no=pivots_p0;
set_free(RowSelected);
set_free(ColSelected);
set_free(NopivotRow);
set_free(DependentCols);
dd_clear(val);
}
void dd_FindDualFeasibleBasis(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A,dd_Bmatrix T,dd_rowindex OV,
dd_colindex nbindex,dd_rowindex bflag,dd_rowrange objrow,dd_colrange rhscol, dd_boolean lexicopivot,
dd_colrange *s,dd_ErrorType *err,dd_LPStatusType *lps,long *pivot_no, long maxpivots)
{
dd_boolean phase1,dualfeasible=dd_TRUE;
dd_boolean localdebug=dd_FALSE,chosen,stop;
dd_LPStatusType LPSphase1;
long pivots_p1=0;
dd_rowrange i,r_val;
dd_colrange j,l,ms=0,s_val,local_m_size;
mytype x,val,maxcost,axvalue,maxratio;
static dd_colrange d_last=0;
static dd_Arow rcost;
static dd_colindex nbindex_ref;
mytype scaling,svalue;
mytype minval;
if (dd_debug) localdebug=dd_debug;
dd_init(x); dd_init(val); dd_init(scaling); dd_init(svalue); dd_init(axvalue);
dd_init(maxcost); dd_set(maxcost,dd_minuszero);
dd_init(maxratio); dd_set(maxratio,dd_minuszero);
if (d_last<d_size) {
if (d_last>0) {
for (j=1; j<=d_last; j++){ dd_clear(rcost[j-1]);}
free(rcost);
free(nbindex_ref);
}
rcost=(mytype*) calloc(d_size,sizeof(mytype));
nbindex_ref=(long*) calloc(d_size+1,sizeof(long));
for (j=1; j<=d_size; j++){ dd_init(rcost[j-1]);}
}
d_last=d_size;
*err=dd_NoError; *lps=dd_LPSundecided; *s=0;
local_m_size=m_size+1;
ms=0;
for (j=1; j<=d_size; j++){
if (j!=rhscol){
dd_TableauEntry(&(rcost[j-1]),local_m_size,d_size,A,T,objrow,j);
if (dd_Larger(rcost[j-1],maxcost)) {dd_set(maxcost,rcost[j-1]); ms = j;}
}
}
if (dd_Positive(maxcost)) dualfeasible=dd_FALSE;
if (!dualfeasible){
for (j=1; j<=d_size; j++){
dd_set(A[local_m_size-1][j-1], dd_purezero);
for (l=1; l<=d_size; l++){
if (nbindex[l]>0) {
dd_set_si(scaling,l+10);
dd_mul(svalue,A[nbindex[l]-1][j-1],scaling);
dd_sub(A[local_m_size-1][j-1],A[local_m_size-1][j-1],svalue);
}
}
}
if (localdebug){
fprintf(stderr,"\ndd_FindDualFeasibleBasis: curruent basis is not dual feasible.\n");
fprintf(stderr,"because of the column %ld assoc. with var %ld dual cost =",
ms,nbindex[ms]);
dd_WriteNumber(stderr, maxcost);
if (localdebug) {
if (m_size <=100 && d_size <=30){
printf("\ndd_FindDualFeasibleBasis: the starting dictionary.\n");
dd_WriteTableau(stdout,m_size+1,d_size,A,T,nbindex,bflag);
}
}
}
ms=0;
for (j=1; j<=d_size; j++){
if ((j!=rhscol) && dd_Positive(rcost[j-1])){
dd_TableauEntry(&axvalue,local_m_size,d_size,A,T,local_m_size,j);
if (dd_Nonnegative(axvalue)) {
*err=dd_NumericallyInconsistent;
if (localdebug) fprintf(stderr,"dd_FindDualFeasibleBasis: Numerical Inconsistency detected.\n");
goto _L99;
}
dd_neg(axvalue,axvalue);
dd_div(axvalue,rcost[j-1],axvalue);
if (dd_Larger(axvalue,maxratio)) {
dd_set(maxratio,axvalue);
ms = j;
}
}
}
if (ms==0) {
*err=dd_NumericallyInconsistent;
if (localdebug) fprintf(stderr,"dd_FindDualFeasibleBasis: Numerical Inconsistency detected.\n");
goto _L99;
}
dd_GaussianColumnPivot2(local_m_size,d_size,A,T,nbindex,bflag,local_m_size,ms);
pivots_p1=pivots_p1+1;
if (localdebug) {
printf("\ndd_FindDualFeasibleBasis: Pivot on %ld %ld.\n",local_m_size,ms);
}
for (j=1; j<=d_size; j++) nbindex_ref[j]=nbindex[j];
if (localdebug){
fprintf(stderr, "Store the current feasible basis:");
for (j=1; j<=d_size; j++) fprintf(stderr, " %ld", nbindex_ref[j]);
fprintf(stderr, "\n");
if (m_size <=100 && d_size <=30)
dd_WriteSignTableau2(stdout,m_size+1,d_size,A,T,nbindex_ref,nbindex,bflag);
}
phase1=dd_TRUE; stop=dd_FALSE;
do {
chosen=dd_FALSE; LPSphase1=dd_LPSundecided;
if (pivots_p1>maxpivots) {
*err=dd_LPCycling;
fprintf(stderr,"max number %ld of pivots performed in Phase I. Switch to the anticycling phase.\n", maxpivots);
goto _L99;
}
dd_SelectDualSimplexPivot(local_m_size,d_size,phase1,A,T,OV,nbindex_ref,nbindex,bflag,
objrow,rhscol,lexicopivot,&r_val,&s_val,&chosen,&LPSphase1);
if (!chosen) {
dd_TableauEntry(&x,local_m_size,d_size,A,T,objrow,ms);
if (dd_Negative(x)){
*err=dd_NoError; *lps=dd_DualInconsistent; *s=ms;
}
if (localdebug) {
fprintf(stderr,"\ndd_FindDualFeasibleBasis: the auxiliary variable was forced to enter the basis (# pivots = %ld).\n",pivots_p1);
fprintf(stderr," -- objrow %ld, ms %ld entry: ",objrow,ms);
dd_WriteNumber(stderr, x); fprintf(stderr,"\n");
if (dd_Negative(x)){
fprintf(stderr,"->The basis is dual inconsistent. Terminate.\n");
} else {
fprintf(stderr,"->The basis is feasible. Go to phase II.\n");
}
}
dd_init(minval);
r_val=0;
for (i=1; i<=local_m_size; i++){
if (bflag[i]<0) {
dd_TableauEntry(&val,local_m_size,d_size,A,T,i,ms);
if (dd_Smaller(val, minval)) {
r_val=i;
dd_set(minval,val);
}
}
}
dd_clear(minval);
if (r_val==0) {
*err=dd_NumericallyInconsistent;
if (localdebug) fprintf(stderr,"dd_FindDualFeasibleBasis: Numerical Inconsistency detected (r_val is 0).\n");
goto _L99;
}
dd_GaussianColumnPivot2(local_m_size,d_size,A,T,nbindex,bflag,r_val,ms);
pivots_p1=pivots_p1+1;
if (localdebug) {
printf("\ndd_FindDualFeasibleBasis: make the %ld-th pivot on %ld %ld to force the auxiliary variable to enter the basis.\n",pivots_p1,r_val,ms);
if (m_size <=100 && d_size <=30)
dd_WriteSignTableau2(stdout,m_size+1,d_size,A,T,nbindex_ref,nbindex,bflag);
}
stop=dd_TRUE;
} else {
dd_GaussianColumnPivot2(local_m_size,d_size,A,T,nbindex,bflag,r_val,s_val);
pivots_p1=pivots_p1+1;
if (localdebug) {
printf("\ndd_FindDualFeasibleBasis: make a %ld-th pivot on %ld %ld\n",pivots_p1,r_val,s_val);
if (m_size <=100 && d_size <=30)
dd_WriteSignTableau2(stdout,local_m_size,d_size,A,T,nbindex_ref,nbindex,bflag);
}
if (bflag[local_m_size]<0) {
stop=dd_TRUE;
if (localdebug)
fprintf(stderr,"\nDualSimplex Phase I: the auxiliary variable entered the basis (# pivots = %ld).\nGo to phase II\n",pivots_p1);
}
}
} while(!stop);
}
_L99:
*pivot_no=pivots_p1;
dd_statDS1pivots+=pivots_p1;
dd_clear(x); dd_clear(val); dd_clear(maxcost); dd_clear(maxratio);
dd_clear(scaling); dd_clear(svalue); dd_clear(axvalue);
}
void dd_DualSimplexMinimize(dd_LPPtr lp,dd_ErrorType *err)
{
dd_colrange j;
*err=dd_NoError;
for (j=1; j<=lp->d; j++)
dd_neg(lp->A[lp->objrow-1][j-1],lp->A[lp->objrow-1][j-1]);
dd_DualSimplexMaximize(lp,err);
dd_neg(lp->optvalue,lp->optvalue);
for (j=1; j<=lp->d; j++){
if (lp->LPS!=dd_Inconsistent) {
dd_neg(lp->dsol[j-1],lp->dsol[j-1]);
}
dd_neg(lp->A[lp->objrow-1][j-1],lp->A[lp->objrow-1][j-1]);
}
}
void dd_DualSimplexMaximize(dd_LPPtr lp,dd_ErrorType *err)
{
int stop,chosen,phase1,found;
long pivots_ds=0,pivots_p0=0,pivots_p1=0,pivots_pc=0,maxpivots,maxpivfactor=20;
dd_boolean localdebug=dd_FALSE,localdebug1=dd_FALSE;
#if !defined GMPRATIONAL
long maxccpivots,maxccpivfactor=100;
#endif
dd_rowrange i,r;
dd_colrange j,s;
static dd_rowindex bflag;
static long mlast=0,nlast=0;
static dd_rowindex OrderVector;
static dd_colindex nbindex_ref;
double redpercent=0,redpercent_prev=0,redgain=0;
unsigned int rseed=1;
if (dd_debug) localdebug=dd_debug;
set_emptyset(lp->redset_extra);
for (i=0; i<= 4; i++) lp->pivots[i]=0;
maxpivots=maxpivfactor*lp->d;
#if !defined GMPRATIONAL
maxccpivots=maxccpivfactor*lp->d;
#endif
if (mlast!=lp->m || nlast!=lp->d){
if (mlast>0) {
free(OrderVector);
free(bflag);
free(nbindex_ref);
}
OrderVector=(long *)calloc(lp->m+1,sizeof(*OrderVector));
bflag=(long *) calloc(lp->m+2,sizeof(*bflag));
nbindex_ref=(long*) calloc(lp->d+1,sizeof(long));
mlast=lp->m;nlast=lp->d;
}
dd_ComputeRowOrderVector2(lp->m,lp->d,lp->A,OrderVector,dd_MinIndex,rseed);
lp->re=0; lp->se=0;
dd_ResetTableau(lp->m,lp->d,lp->B,lp->nbindex,bflag,lp->objrow,lp->rhscol);
dd_FindLPBasis(lp->m,lp->d,lp->A,lp->B,OrderVector,lp->equalityset,lp->nbindex,bflag,
lp->objrow,lp->rhscol,&s,&found,&(lp->LPS),&pivots_p0);
lp->pivots[0]=pivots_p0;
if (!found){
lp->se=s;
goto _L99;
}
dd_FindDualFeasibleBasis(lp->m,lp->d,lp->A,lp->B,OrderVector,lp->nbindex,bflag,
lp->objrow,lp->rhscol,lp->lexicopivot,&s, err,&(lp->LPS),&pivots_p1, maxpivots);
lp->pivots[1]=pivots_p1;
for (j=1; j<=lp->d; j++) nbindex_ref[j]=lp->nbindex[j];
if (localdebug){
fprintf(stderr, "dd_DualSimplexMaximize: Store the current feasible basis:");
for (j=1; j<=lp->d; j++) fprintf(stderr, " %ld", nbindex_ref[j]);
fprintf(stderr, "\n");
if (lp->m <=100 && lp->d <=30)
dd_WriteSignTableau2(stdout,lp->m+1,lp->d,lp->A,lp->B,nbindex_ref,lp->nbindex,bflag);
}
if (*err==dd_LPCycling || *err==dd_NumericallyInconsistent){
if (localdebug) fprintf(stderr, "Phase I failed and thus switch to the Criss-Cross method\n");
dd_CrissCrossMaximize(lp,err);
return;
}
if (lp->LPS==dd_DualInconsistent){
lp->se=s;
goto _L99;
}
stop=dd_FALSE;
do {
chosen=dd_FALSE; lp->LPS=dd_LPSundecided; phase1=dd_FALSE;
if (pivots_ds<maxpivots) {
dd_SelectDualSimplexPivot(lp->m,lp->d,phase1,lp->A,lp->B,OrderVector,nbindex_ref,lp->nbindex,bflag,
lp->objrow,lp->rhscol,lp->lexicopivot,&r,&s,&chosen,&(lp->LPS));
}
if (chosen) {
pivots_ds=pivots_ds+1;
if (lp->redcheck_extensive) {
dd_GetRedundancyInformation(lp->m,lp->d,lp->A,lp->B,lp->nbindex, bflag, lp->redset_extra);
set_uni(lp->redset_accum, lp->redset_accum,lp->redset_extra);
redpercent=100*(double)set_card(lp->redset_extra)/(double)lp->m;
redgain=redpercent-redpercent_prev;
redpercent_prev=redpercent;
if (localdebug1){
fprintf(stderr,"\ndd_DualSimplexMaximize: Phase II pivot %ld on (%ld, %ld).\n",pivots_ds,r,s);
fprintf(stderr," redundancy %f percent: redset size = %ld\n",redpercent,set_card(lp->redset_extra));
}
}
}
if (!chosen && lp->LPS==dd_LPSundecided) {
if (localdebug1){
fprintf(stderr,"Warning: an emergency CC pivot in Phase II is performed\n");
if (localdebug && lp->m <=100 && lp->d <=30){
fprintf(stderr,"\ndd_DualSimplexMaximize: The current dictionary.\n");
dd_WriteSignTableau2(stdout,lp->m,lp->d,lp->A,lp->B,nbindex_ref,lp->nbindex,bflag);
}
}
#if !defined GMPRATIONAL
if (pivots_pc>maxccpivots) {
*err=dd_LPCycling;
stop=dd_TRUE;
goto _L99;
}
#endif
dd_SelectCrissCrossPivot(lp->m,lp->d,lp->A,lp->B,bflag,
lp->objrow,lp->rhscol,&r,&s,&chosen,&(lp->LPS));
if (chosen) pivots_pc=pivots_pc+1;
}
if (chosen) {
dd_GaussianColumnPivot2(lp->m,lp->d,lp->A,lp->B,lp->nbindex,bflag,r,s);
if (localdebug && lp->m <=100 && lp->d <=30){
fprintf(stderr,"\ndd_DualSimplexMaximize: The current dictionary.\n");
dd_WriteSignTableau2(stdout,lp->m,lp->d,lp->A,lp->B,nbindex_ref,lp->nbindex,bflag);
}
} else {
switch (lp->LPS){
case dd_Inconsistent: lp->re=r;
case dd_DualInconsistent: lp->se=s;
default: break;
}
stop=dd_TRUE;
}
} while(!stop);
_L99:
lp->pivots[2]=pivots_ds;
lp->pivots[3]=pivots_pc;
dd_statDS2pivots+=pivots_ds;
dd_statACpivots+=pivots_pc;
dd_SetSolutions(lp->m,lp->d,lp->A,lp->B,lp->objrow,lp->rhscol,lp->LPS,&(lp->optvalue),lp->sol,lp->dsol,lp->posset_extra,lp->nbindex,lp->re,lp->se,bflag);
}
void dd_CrissCrossMinimize(dd_LPPtr lp,dd_ErrorType *err)
{
dd_colrange j;
*err=dd_NoError;
for (j=1; j<=lp->d; j++)
dd_neg(lp->A[lp->objrow-1][j-1],lp->A[lp->objrow-1][j-1]);
dd_CrissCrossMaximize(lp,err);
dd_neg(lp->optvalue,lp->optvalue);
for (j=1; j<=lp->d; j++){
if (lp->LPS!=dd_Inconsistent) {
dd_neg(lp->dsol[j-1],lp->dsol[j-1]);
}
dd_neg(lp->A[lp->objrow-1][j-1],lp->A[lp->objrow-1][j-1]);
}
}
void dd_CrissCrossMaximize(dd_LPPtr lp,dd_ErrorType *err)
{
int stop,chosen,found;
long pivots0,pivots1;
#if !defined GMPRATIONAL
long maxpivots,maxpivfactor=1000;
#endif
dd_rowrange i,r;
dd_colrange s;
static dd_rowindex bflag;
static long mlast=0;
static dd_rowindex OrderVector;
unsigned int rseed=1;
dd_colindex nbtemp;
*err=dd_NoError;
#if !defined GMPRATIONAL
maxpivots=maxpivfactor*lp->d;
#endif
nbtemp=(long *) calloc(lp->d+1,sizeof(long));
for (i=0; i<= 4; i++) lp->pivots[i]=0;
if (bflag==NULL || mlast!=lp->m){
if (mlast!=lp->m && mlast>0) {
free(bflag);
free(OrderVector);
}
bflag=(long *) calloc(lp->m+1,sizeof(long));
OrderVector=(long *)calloc(lp->m+1,sizeof(long));
mlast=lp->m;
}
dd_ComputeRowOrderVector2(lp->m,lp->d,lp->A,OrderVector,dd_MinIndex,rseed);
lp->re=0; lp->se=0; pivots1=0;
dd_ResetTableau(lp->m,lp->d,lp->B,lp->nbindex,bflag,lp->objrow,lp->rhscol);
dd_FindLPBasis(lp->m,lp->d,lp->A,lp->B,OrderVector,lp->equalityset,
lp->nbindex,bflag,lp->objrow,lp->rhscol,&s,&found,&(lp->LPS),&pivots0);
lp->pivots[0]+=pivots0;
if (!found){
lp->se=s;
goto _L99;
}
stop=dd_FALSE;
do {
#if !defined GMPRATIONAL
if (pivots1>maxpivots) {
*err=dd_LPCycling;
fprintf(stderr,"max number %ld of pivots performed by the criss-cross method. Most likely due to the floating-point arithmetics error.\n", maxpivots);
goto _L99;
}
#endif
dd_SelectCrissCrossPivot(lp->m,lp->d,lp->A,lp->B,bflag,
lp->objrow,lp->rhscol,&r,&s,&chosen,&(lp->LPS));
if (chosen) {
dd_GaussianColumnPivot2(lp->m,lp->d,lp->A,lp->B,lp->nbindex,bflag,r,s);
pivots1++;
} else {
switch (lp->LPS){
case dd_Inconsistent: lp->re=r;
case dd_DualInconsistent: lp->se=s;
default: break;
}
stop=dd_TRUE;
}
} while(!stop);
_L99:
lp->pivots[1]+=pivots1;
dd_statCCpivots+=pivots1;
dd_SetSolutions(lp->m,lp->d,lp->A,lp->B,
lp->objrow,lp->rhscol,lp->LPS,&(lp->optvalue),lp->sol,lp->dsol,lp->posset_extra,lp->nbindex,lp->re,lp->se,bflag);
free(nbtemp);
}
void dd_SetSolutions(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A,dd_Bmatrix T,
dd_rowrange objrow,dd_colrange rhscol,dd_LPStatusType LPS,
mytype *optvalue,dd_Arow sol,dd_Arow dsol,dd_rowset posset, dd_colindex nbindex,
dd_rowrange re,dd_colrange se,dd_rowindex bflag)
{
dd_rowrange i;
dd_colrange j;
mytype x,sw;
int localdebug=dd_FALSE;
dd_init(x); dd_init(sw);
if (localdebug) fprintf(stderr,"SetSolutions:\n");
switch (LPS){
case dd_Optimal:
for (j=1;j<=d_size; j++) {
dd_set(sol[j-1],T[j-1][rhscol-1]);
dd_TableauEntry(&x,m_size,d_size,A,T,objrow,j);
dd_neg(dsol[j-1],x);
dd_TableauEntry(optvalue,m_size,d_size,A,T,objrow,rhscol);
if (localdebug) {fprintf(stderr,"dsol[%ld]= ",nbindex[j]); dd_WriteNumber(stderr, dsol[j-1]); }
}
for (i=1; i<=m_size; i++) {
if (bflag[i]==-1) {
dd_TableauEntry(&x,m_size,d_size,A,T,i,rhscol);
if (dd_Positive(x)) set_addelem(posset, i);
}
}
break;
case dd_Inconsistent:
if (localdebug) fprintf(stderr,"SetSolutions: LP is inconsistent.\n");
for (j=1;j<=d_size; j++) {
dd_set(sol[j-1],T[j-1][rhscol-1]);
dd_TableauEntry(&x,m_size,d_size,A,T,re,j);
dd_neg(dsol[j-1],x);
if (localdebug) {fprintf(stderr,"dsol[%ld]=",nbindex[j]);
dd_WriteNumber(stderr,dsol[j-1]);
fprintf(stderr,"\n");
}
}
break;
case dd_DualInconsistent:
if (localdebug) printf( "SetSolutions: LP is dual inconsistent.\n");
for (j=1;j<=d_size; j++) {
dd_set(sol[j-1],T[j-1][se-1]);
dd_TableauEntry(&x,m_size,d_size,A,T,objrow,j);
dd_neg(dsol[j-1],x);
if (localdebug) {fprintf(stderr,"dsol[%ld]=",nbindex[j]);
dd_WriteNumber(stderr,dsol[j-1]);
fprintf(stderr,"\n");
}
}
break;
case dd_StrucDualInconsistent:
dd_TableauEntry(&x,m_size,d_size,A,T,objrow,se);
if (dd_Positive(x)) dd_set(sw,dd_one);
else dd_neg(sw,dd_one);
for (j=1;j<=d_size; j++) {
dd_mul(sol[j-1],sw,T[j-1][se-1]);
dd_TableauEntry(&x,m_size,d_size,A,T,objrow,j);
dd_neg(dsol[j-1],x);
if (localdebug) {fprintf(stderr,"dsol[%ld]= ",nbindex[j]);dd_WriteNumber(stderr,dsol[j-1]);}
}
if (localdebug) fprintf(stderr,"SetSolutions: LP is dual inconsistent.\n");
break;
default:break;
}
dd_clear(x); dd_clear(sw);
}
void dd_RandomPermutation2(dd_rowindex OV,long t,unsigned int seed)
{
long k,j,ovj;
double u,xk,r,rand_max=(double) RAND_MAX;
int localdebug=dd_FALSE;
portable_srand(seed);
for (j=t; j>1 ; j--) {
r=portable_rand();
u=r/rand_max;
xk=(double)(j*u +1);
k=(long)xk;
if (localdebug) fprintf(stderr,"u=%g, k=%ld, r=%g, randmax= %g\n",u,k,r,rand_max);
ovj=OV[j];
OV[j]=OV[k];
OV[k]=ovj;
if (localdebug) fprintf(stderr,"row %ld is exchanged with %ld\n",j,k);
}
}
void dd_ComputeRowOrderVector2(dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,
dd_rowindex OV,dd_RowOrderType ho,unsigned int rseed)
{
long i,itemp;
OV[0]=0;
switch (ho){
case dd_MaxIndex:
for(i=1; i<=m_size; i++) OV[i]=m_size-i+1;
break;
case dd_LexMin:
for(i=1; i<=m_size; i++) OV[i]=i;
dd_QuickSort(OV,1,m_size,A,d_size);
break;
case dd_LexMax:
for(i=1; i<=m_size; i++) OV[i]=i;
dd_QuickSort(OV,1,m_size,A,d_size);
for(i=1; i<=m_size/2;i++){
itemp=OV[i];
OV[i]=OV[m_size-i+1];
OV[m_size-i+1]=itemp;
}
break;
case dd_RandomRow:
for(i=1; i<=m_size; i++) OV[i]=i;
if (rseed<=0) rseed=1;
dd_RandomPermutation2(OV,m_size,rseed);
break;
case dd_MinIndex:
for(i=1; i<=m_size; i++) OV[i]=i;
break;
default:
for(i=1; i<=m_size; i++) OV[i]=i;
break;
}
}
void dd_SelectPreorderedNext2(dd_rowrange m_size,dd_colrange d_size,
rowset excluded,dd_rowindex OV,dd_rowrange *hnext)
{
dd_rowrange i,k;
*hnext=0;
for (i=1; i<=m_size && *hnext==0; i++){
k=OV[i];
if (!set_member(k,excluded)) *hnext=k ;
}
}
#ifdef GMPRATIONAL
ddf_LPObjectiveType Obj2Obj(dd_LPObjectiveType obj)
{
ddf_LPObjectiveType objf=ddf_LPnone;
switch (obj) {
case dd_LPnone: objf=ddf_LPnone; break;
case dd_LPmax: objf=ddf_LPmax; break;
case dd_LPmin: objf=ddf_LPmin; break;
}
return objf;
}
ddf_LPPtr dd_LPgmp2LPf(dd_LPPtr lp)
{
dd_rowrange i;
dd_colrange j;
ddf_LPType *lpf;
double val;
dd_boolean localdebug=dd_FALSE;
if (localdebug) fprintf(stderr,"Converting a GMP-LP to a float-LP.\n");
lpf=ddf_CreateLPData(Obj2Obj(lp->objective), ddf_Real, lp->m, lp->d);
lpf->Homogeneous = lp->Homogeneous;
lpf->eqnumber=lp->eqnumber;
for (i = 1; i <= lp->m; i++) {
if (set_member(i, lp->equalityset)) set_addelem(lpf->equalityset,i);
for (j = 1; j <= lp->d; j++) {
val=mpq_get_d(lp->A[i-1][j-1]);
ddf_set_d(lpf->A[i-1][j-1],val);
}
}
return lpf;
}
#endif
dd_boolean dd_LPSolve(dd_LPPtr lp,dd_LPSolverType solver,dd_ErrorType *err)
{
int i;
dd_boolean found=dd_FALSE;
#ifdef GMPRATIONAL
ddf_LPPtr lpf;
ddf_ErrorType errf;
dd_boolean LPScorrect=dd_FALSE;
dd_boolean localdebug=dd_FALSE;
if (dd_debug) localdebug=dd_debug;
#endif
*err=dd_NoError;
lp->solver=solver;
time(&lp->starttime);
#ifndef GMPRATIONAL
switch (lp->solver) {
case dd_CrissCross:
dd_CrissCrossSolve(lp,err);
break;
case dd_DualSimplex:
dd_DualSimplexSolve(lp,err);
break;
}
#else
lpf=dd_LPgmp2LPf(lp);
switch (lp->solver) {
case dd_CrissCross:
ddf_CrissCrossSolve(lpf,&errf);
if (errf==ddf_NoError){
dd_BasisStatus(lpf,lp, &LPScorrect);
} else {LPScorrect=dd_FALSE;}
if (!LPScorrect) {
if (localdebug) printf("BasisStatus: the current basis is NOT verified with GMP. Rerun with GMP.\n");
dd_CrissCrossSolve(lp,err);
} else {
if (localdebug) printf("BasisStatus: the current basis is verified with GMP. The LP Solved.\n");
}
break;
case dd_DualSimplex:
ddf_DualSimplexSolve(lpf,&errf);
if (errf==ddf_NoError){
dd_BasisStatus(lpf,lp, &LPScorrect);
} else {LPScorrect=dd_FALSE;}
if (!LPScorrect){
if (localdebug) printf("BasisStatus: the current basis is NOT verified with GMP. Rerun with GMP.\n");
dd_DualSimplexSolve(lp,err);
if (localdebug){
printf("*total number pivots = %ld (ph0 = %ld, ph1 = %ld, ph2 = %ld, ph3 = %ld, ph4 = %ld)\n",
lp->total_pivots,lp->pivots[0],lp->pivots[1],lp->pivots[2],lp->pivots[3],lp->pivots[4]);
ddf_WriteLPResult(stdout, lpf, errf);
dd_WriteLP(stdout, lp);
}
} else {
if (localdebug) printf("BasisStatus: the current basis is verified with GMP. The LP Solved.\n");
}
break;
}
ddf_FreeLPData(lpf);
#endif
time(&lp->endtime);
lp->total_pivots=0;
for (i=0; i<=4; i++) lp->total_pivots+=lp->pivots[i];
if (*err==dd_NoError) found=dd_TRUE;
return found;
}
dd_boolean dd_LPSolve0(dd_LPPtr lp,dd_LPSolverType solver,dd_ErrorType *err)
{
int i;
dd_boolean found=dd_FALSE;
*err=dd_NoError;
lp->solver=solver;
time(&lp->starttime);
switch (lp->solver) {
case dd_CrissCross:
dd_CrissCrossSolve(lp,err);
break;
case dd_DualSimplex:
dd_DualSimplexSolve(lp,err);
break;
}
time(&lp->endtime);
lp->total_pivots=0;
for (i=0; i<=4; i++) lp->total_pivots+=lp->pivots[i];
if (*err==dd_NoError) found=dd_TRUE;
return found;
}
dd_LPPtr dd_MakeLPforInteriorFinding(dd_LPPtr lp)
{
dd_rowrange m;
dd_colrange d;
dd_NumberType numbtype;
dd_LPObjectiveType obj;
dd_LPType *lpnew;
dd_rowrange i;
dd_colrange j;
mytype bm,bmax,bceil;
int localdebug=dd_FALSE;
dd_init(bm); dd_init(bmax); dd_init(bceil);
dd_add(bm,dd_one,dd_one); dd_set(bmax,dd_one);
numbtype=lp->numbtype;
m=lp->m+1;
d=lp->d+1;
obj=dd_LPmax;
lpnew=dd_CreateLPData(obj, numbtype, m, d);
for (i=1; i<=lp->m; i++) {
if (dd_Larger(lp->A[i-1][lp->rhscol-1],bmax))
dd_set(bmax,lp->A[i-1][lp->rhscol-1]);
}
dd_mul(bceil,bm,bmax);
if (localdebug) {fprintf(stderr,"bceil is set to "); dd_WriteNumber(stderr, bceil);}
for (i=1; i <= lp->m; i++) {
for (j=1; j <= lp->d; j++) {
dd_set(lpnew->A[i-1][j-1],lp->A[i-1][j-1]);
}
}
for (i=1;i<=lp->m; i++){
dd_neg(lpnew->A[i-1][lp->d],dd_one);
}
for (j=1;j<=lp->d;j++){
dd_set(lpnew->A[m-2][j-1],dd_purezero);
}
dd_set(lpnew->A[m-2][0],bceil);
for (j=1;j<= d-1;j++) {
dd_set(lpnew->A[m-1][j-1],dd_purezero);
}
dd_set(lpnew->A[m-1][d-1],dd_one);
if (localdebug) dd_WriteAmatrix(stderr, lp->A, lp->m, lp->d);
if (localdebug) dd_WriteAmatrix(stderr, lpnew->A, lpnew->m, lpnew->d);
dd_clear(bm); dd_clear(bmax); dd_clear(bceil);
return lpnew;
}
void dd_WriteLPResult(FILE *f,dd_LPPtr lp,dd_ErrorType err)
{
long j;
fprintf(f,"* cdd LP solver result\n");
if (err!=dd_NoError) {
dd_WriteErrorMessages(f,err);
goto _L99;
}
dd_WriteProgramDescription(f);
fprintf(f,"* #constraints = %ld\n",lp->m-1);
fprintf(f,"* #variables = %ld\n",lp->d-1);
switch (lp->solver) {
case dd_DualSimplex:
fprintf(f,"* Algorithm: dual simplex algorithm\n");break;
case dd_CrissCross:
fprintf(f,"* Algorithm: criss-cross method\n");break;
}
switch (lp->objective) {
case dd_LPmax:
fprintf(f,"* maximization is chosen\n");break;
case dd_LPmin:
fprintf(f,"* minimization is chosen\n");break;
case dd_LPnone:
fprintf(f,"* no objective type (max or min) is chosen\n");break;
}
if (lp->objective==dd_LPmax||lp->objective==dd_LPmin){
fprintf(f,"* Objective function is\n");
for (j=0; j<lp->d; j++){
if (j>0 && dd_Nonnegative(lp->A[lp->objrow-1][j]) ) fprintf(f," +");
if (j>0 && (j % 5) == 0) fprintf(f,"\n");
dd_WriteNumber(f,lp->A[lp->objrow-1][j]);
if (j>0) fprintf(f," X[%3ld]",j);
}
fprintf(f,"\n");
}
switch (lp->LPS){
case dd_Optimal:
fprintf(f,"* LP status: a dual pair (x,y) of optimal solutions found.\n");
fprintf(f,"begin\n");
fprintf(f," primal_solution\n");
for (j=1; j<lp->d; j++) {
fprintf(f," %3ld : ",j);
dd_WriteNumber(f,lp->sol[j]);
fprintf(f,"\n");
}
fprintf(f," dual_solution\n");
for (j=1; j<lp->d; j++){
if (lp->nbindex[j+1]>0) {
fprintf(f," %3ld : ",lp->nbindex[j+1]);
dd_WriteNumber(f,lp->dsol[j]); fprintf(f,"\n");
}
}
fprintf(f," optimal_value : "); dd_WriteNumber(f,lp->optvalue);
fprintf(f,"\nend\n");
break;
case dd_Inconsistent:
fprintf(f,"* LP status: LP is inconsistent.\n");
fprintf(f,"* The positive combination of original inequalities with\n");
fprintf(f,"* the following coefficients will prove the inconsistency.\n");
fprintf(f,"begin\n");
fprintf(f," dual_direction\n");
fprintf(f," %3ld : ",lp->re);
dd_WriteNumber(f,dd_one); fprintf(f,"\n");
for (j=1; j<lp->d; j++){
if (lp->nbindex[j+1]>0) {
fprintf(f," %3ld : ",lp->nbindex[j+1]);
dd_WriteNumber(f,lp->dsol[j]); fprintf(f,"\n");
}
}
fprintf(f,"end\n");
break;
case dd_DualInconsistent: case dd_StrucDualInconsistent:
fprintf(f,"* LP status: LP is dual inconsistent.\n");
fprintf(f,"* The linear combination of columns with\n");
fprintf(f,"* the following coefficients will prove the dual inconsistency.\n");
fprintf(f,"* (It is also an unbounded direction for the primal LP.)\n");
fprintf(f,"begin\n");
fprintf(f," primal_direction\n");
for (j=1; j<lp->d; j++) {
fprintf(f," %3ld : ",j);
dd_WriteNumber(f,lp->sol[j]);
fprintf(f,"\n");
}
fprintf(f,"end\n");
break;
default:
break;
}
fprintf(f,"* number of pivot operations = %ld (ph0 = %ld, ph1 = %ld, ph2 = %ld, ph3 = %ld, ph4 = %ld)\n",lp->total_pivots,lp->pivots[0],lp->pivots[1],lp->pivots[2],lp->pivots[3],lp->pivots[4]);
dd_WriteLPTimes(f, lp);
_L99:;
}
dd_LPPtr dd_CreateLP_H_ImplicitLinearity(dd_MatrixPtr M)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPPtr lp;
dd_boolean localdebug=dd_FALSE;
linc=set_card(M->linset);
m=M->rowsize+1+linc+1;
d=M->colsize+1;
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_TRUE;
lp->objective = dd_LPmax;
lp->eqnumber=linc;
lp->redcheck_extensive=dd_FALSE;
irev=M->rowsize;
for (i = 1; i <= M->rowsize; i++) {
if (set_member(i, M->linset)) {
irev=irev+1;
set_addelem(lp->equalityset,i);
for (j = 1; j <= M->colsize; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-1]);
}
} else {
dd_set(lp->A[i-1][d-1],dd_minusone);
}
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-1]);
if (j==1 && i<M->rowsize && dd_Nonzero(M->matrix[i-1][j-1])) lp->Homogeneous = dd_FALSE;
}
}
dd_set(lp->A[m-2][0],dd_one); dd_set(lp->A[m-2][d-1],dd_minusone);
dd_set(lp->A[m-1][d-1],dd_one);
if (localdebug) {
fprintf(stderr,"dd_CreateLP_H_ImplicitLinearity: an new lp is\n");
dd_WriteLP(stderr,lp);
}
return lp;
}
dd_LPPtr dd_CreateLP_V_ImplicitLinearity(dd_MatrixPtr M)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPPtr lp;
dd_boolean localdebug=dd_FALSE;
linc=set_card(M->linset);
m=M->rowsize+1+linc+1;
d=(M->colsize)+2;
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_FALSE;
lp->objective = dd_LPmax;
lp->eqnumber=linc;
lp->redcheck_extensive=dd_FALSE;
irev=M->rowsize;
for (i = 1; i <= M->rowsize; i++) {
dd_set(lp->A[i-1][0],dd_purezero);
if (set_member(i, M->linset)) {
irev=irev+1;
set_addelem(lp->equalityset,i);
for (j = 2; j <= (M->colsize)+1; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-2]);
}
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
} else {
dd_set(lp->A[i-1][d-1],dd_minusone);
}
for (j = 2; j <= (M->colsize)+1; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-2]);
}
}
dd_set(lp->A[m-2][0],dd_one); dd_set(lp->A[m-2][d-1],dd_minusone);
dd_set(lp->A[m-1][d-1],dd_one);
if (localdebug) {
fprintf(stderr,"dd_CreateLP_V_ImplicitLinearity: an new lp is\n");
dd_WriteLP(stderr,lp);
}
return lp;
}
dd_LPPtr dd_CreateLP_H_Redundancy(dd_MatrixPtr M, dd_rowrange itest)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPPtr lp;
dd_boolean localdebug=dd_FALSE;
linc=set_card(M->linset);
m=M->rowsize+1+linc;
d=M->colsize;
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_TRUE;
lp->objective = dd_LPmin;
lp->eqnumber=linc;
lp->redcheck_extensive=dd_FALSE;
irev=M->rowsize;
for (i = 1; i <= M->rowsize; i++) {
if (set_member(i, M->linset)) {
irev=irev+1;
set_addelem(lp->equalityset,i);
for (j = 1; j <= M->colsize; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-1]);
}
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
}
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-1]);
if (j==1 && i<M->rowsize && dd_Nonzero(M->matrix[i-1][j-1])) lp->Homogeneous = dd_FALSE;
}
}
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[m-1][j-1],M->matrix[itest-1][j-1]);
}
dd_add(lp->A[itest-1][0],lp->A[itest-1][0],dd_one);
return lp;
}
dd_LPPtr dd_CreateLP_V_Redundancy(dd_MatrixPtr M, dd_rowrange itest)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPPtr lp;
dd_boolean localdebug=dd_FALSE;
linc=set_card(M->linset);
m=M->rowsize+1+linc;
d=(M->colsize)+1;
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_FALSE;
lp->objective = dd_LPmin;
lp->eqnumber=linc;
lp->redcheck_extensive=dd_FALSE;
irev=M->rowsize;
for (i = 1; i <= M->rowsize; i++) {
if (i==itest){
dd_set(lp->A[i-1][0],dd_one);
} else {
dd_set(lp->A[i-1][0],dd_purezero);
}
if (set_member(i, M->linset)) {
irev=irev+1;
set_addelem(lp->equalityset,i);
for (j = 2; j <= (M->colsize)+1; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-2]);
}
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
}
for (j = 2; j <= (M->colsize)+1; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-2]);
}
}
for (j = 2; j <= (M->colsize)+1; j++) {
dd_set(lp->A[m-1][j-1],M->matrix[itest-1][j-2]);
}
dd_set(lp->A[m-1][0],dd_purezero);
if (localdebug) dd_WriteLP(stdout, lp);
return lp;
}
dd_LPPtr dd_CreateLP_V_SRedundancy(dd_MatrixPtr M, dd_rowrange itest)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPPtr lp;
dd_boolean localdebug=dd_FALSE;
linc=set_card(M->linset);
m=M->rowsize+1+linc+2;
d=(M->colsize)+1;
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_FALSE;
lp->objective = dd_LPmax;
lp->eqnumber=linc;
irev=M->rowsize;
for (i = 1; i <= M->rowsize; i++) {
if (i==itest){
dd_set(lp->A[i-1][0],dd_purezero);
} else {
dd_set(lp->A[i-1][0],dd_purezero);
}
if (set_member(i, M->linset) || i==itest) {
irev=irev+1;
set_addelem(lp->equalityset,i);
for (j = 2; j <= (M->colsize)+1; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-2]);
}
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
}
for (j = 2; j <= (M->colsize)+1; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-2]);
dd_add(lp->A[m-1][j-1],lp->A[m-1][j-1],lp->A[i-1][j-1]);
}
}
for (j = 2; j <= (M->colsize)+1; j++) {
dd_neg(lp->A[m-2][j-1],lp->A[m-1][j-1]);
}
dd_set(lp->A[m-2][0],dd_one);
if (localdebug) dd_WriteLP(stdout, lp);
return lp;
}
dd_boolean dd_Redundant(dd_MatrixPtr M, dd_rowrange itest, dd_Arow certificate, dd_ErrorType *error)
{
dd_colrange j;
dd_LPPtr lp;
dd_LPSolutionPtr lps;
dd_ErrorType err=dd_NoError;
dd_boolean answer=dd_FALSE,localdebug=dd_FALSE;
*error=dd_NoError;
if (set_member(itest, M->linset)){
if (localdebug) printf("The %ld th row is linearity and redundancy checking is skipped.\n",itest);
goto _L99;
}
if (M->representation==dd_Generator){
lp=dd_CreateLP_V_Redundancy(M, itest);
} else {
lp=dd_CreateLP_H_Redundancy(M, itest);
}
dd_LPSolve(lp,dd_choiceRedcheckAlgorithm,&err);
if (err!=dd_NoError){
*error=err;
goto _L999;
} else {
lps=dd_CopyLPSolution(lp);
for (j=0; j<lps->d; j++) {
dd_set(certificate[j], lps->sol[j]);
}
if (dd_Negative(lps->optvalue)){
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th row is nonredundant.\n",itest);
} else {
answer=dd_TRUE;
if (localdebug) fprintf(stderr,"==> %ld th row is redundant.\n",itest);
}
dd_FreeLPSolution(lps);
}
_L999:
dd_FreeLPData(lp);
_L99:
return answer;
}
dd_boolean dd_RedundantExtensive(dd_MatrixPtr M, dd_rowrange itest, dd_Arow certificate,
dd_rowset *redset,dd_ErrorType *error)
{
dd_colrange j;
dd_LPPtr lp;
dd_LPSolutionPtr lps;
dd_ErrorType err=dd_NoError;
dd_boolean answer=dd_FALSE,localdebug=dd_FALSE;
*error=dd_NoError;
if (set_member(itest, M->linset)){
if (localdebug) printf("The %ld th row is linearity and redundancy checking is skipped.\n",itest);
goto _L99;
}
if (M->representation==dd_Generator){
lp=dd_CreateLP_V_Redundancy(M, itest);
} else {
lp=dd_CreateLP_H_Redundancy(M, itest);
}
lp->redcheck_extensive=dd_TRUE;
dd_LPSolve0(lp,dd_DualSimplex,&err);
if (err!=dd_NoError){
*error=err;
goto _L999;
} else {
set_copy(*redset,lp->redset_extra);
set_delelem(*redset, itest);
if (localdebug){
fprintf(stderr, "dd_RedundantExtensive: checking for %ld, extra redset with cardinality %ld (%ld)\n",itest,set_card(*redset),set_card(lp->redset_extra));
set_fwrite(stderr, *redset); fprintf(stderr, "\n");
}
lps=dd_CopyLPSolution(lp);
for (j=0; j<lps->d; j++) {
dd_set(certificate[j], lps->sol[j]);
}
if (dd_Negative(lps->optvalue)){
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th row is nonredundant.\n",itest);
} else {
answer=dd_TRUE;
if (localdebug) fprintf(stderr,"==> %ld th row is redundant.\n",itest);
}
dd_FreeLPSolution(lps);
}
_L999:
dd_FreeLPData(lp);
_L99:
return answer;
}
dd_rowset dd_RedundantRows(dd_MatrixPtr M, dd_ErrorType *error)
{
dd_rowrange i,m;
dd_colrange d;
dd_rowset redset;
dd_MatrixPtr Mcopy;
dd_Arow cvec;
dd_boolean localdebug=dd_FALSE;
m=M->rowsize;
if (M->representation==dd_Generator){
d=(M->colsize)+1;
} else {
d=M->colsize;
}
Mcopy=dd_MatrixCopy(M);
dd_InitializeArow(d,&cvec);
set_initialize(&redset, m);
for (i=m; i>=1; i--) {
if (dd_Redundant(Mcopy, i, cvec, error)) {
if (localdebug) printf("dd_RedundantRows: the row %ld is redundant.\n", i);
set_addelem(redset, i);
dd_MatrixRowRemove(&Mcopy, i);
} else {
if (localdebug) printf("dd_RedundantRows: the row %ld is essential.\n", i);
}
if (*error!=dd_NoError) goto _L99;
}
_L99:
dd_FreeMatrix(Mcopy);
dd_FreeArow(d, cvec);
return redset;
}
dd_boolean dd_MatrixRedundancyRemove(dd_MatrixPtr *M, dd_rowset *redset,dd_rowindex *newpos, dd_ErrorType *error)
{
dd_rowrange i,k,m,m1;
dd_colrange d;
dd_rowset redset1;
dd_rowindex newpos1;
dd_MatrixPtr M1=NULL;
dd_Arow cvec;
dd_boolean success=dd_FALSE, localdebug=dd_FALSE;
m=(*M)->rowsize;
set_initialize(redset, m);
M1=dd_MatrixSortedUniqueCopy(*M,newpos);
for (i=1; i<=m; i++){
if ((*newpos)[i]<=0) set_addelem(*redset,i);
if (localdebug) printf(" %ld:%ld",i,(*newpos)[i]);
}
if (localdebug) printf("\n");
if ((*M)->representation==dd_Generator){
d=((*M)->colsize)+1;
} else {
d=(*M)->colsize;
}
m1=M1->rowsize;
if (localdebug){
fprintf(stderr,"dd_MatrixRedundancyRemove: By sorting, %ld rows have been removed. The remaining has %ld rows.\n",m-m1,m1);
}
dd_InitializeArow(d,&cvec);
set_initialize(&redset1, M1->rowsize);
k=1;
do {
if (dd_RedundantExtensive(M1, k, cvec, &redset1,error)) {
set_addelem(redset1, k);
dd_MatrixRowsRemove2(&M1,redset1,&newpos1);
for (i=1; i<=m; i++){
if ((*newpos)[i]>0){
if (set_member((*newpos)[i],redset1)){
set_addelem(*redset,i);
(*newpos)[i]=0;
} else {
(*newpos)[i]=newpos1[(*newpos)[i]];
}
}
}
set_free(redset1);
set_initialize(&redset1, M1->rowsize);
if (localdebug) {
printf("dd_MatrixRedundancyRemove: the row %ld is redundant. The new matrix has %ld rows.\n", k, M1->rowsize);
}
free(newpos1);
} else {
if (set_card(redset1)>0) {
dd_MatrixRowsRemove2(&M1,redset1,&newpos1);
for (i=1; i<=m; i++){
if ((*newpos)[i]>0){
if (set_member((*newpos)[i],redset1)){
set_addelem(*redset,i);
(*newpos)[i]=0;
} else {
(*newpos)[i]=newpos1[(*newpos)[i]];
}
}
}
set_free(redset1);
set_initialize(&redset1, M1->rowsize);
free(newpos1);
}
if (localdebug) {
printf("dd_MatrixRedundancyRemove: the row %ld is essential. The new matrix has %ld rows.\n", k, M1->rowsize);
}
k=k+1;
}
if (*error!=dd_NoError) goto _L99;
} while (k<=M1->rowsize);
if (localdebug) dd_WriteMatrix(stderr, M1);
success=dd_TRUE;
_L99:
dd_FreeMatrix(*M);
*M=M1;
dd_FreeArow(d, cvec);
set_free(redset1);
return success;
}
dd_boolean dd_SRedundant(dd_MatrixPtr M, dd_rowrange itest, dd_Arow certificate, dd_ErrorType *error)
{
dd_colrange j;
dd_LPPtr lp;
dd_LPSolutionPtr lps;
dd_ErrorType err=dd_NoError;
dd_boolean answer=dd_FALSE,localdebug=dd_FALSE;
*error=dd_NoError;
if (set_member(itest, M->linset)){
if (localdebug) printf("The %ld th row is linearity and strong redundancy checking is skipped.\n",itest);
goto _L99;
}
if (M->representation==dd_Generator){
lp=dd_CreateLP_V_Redundancy(M, itest);
} else {
lp=dd_CreateLP_H_Redundancy(M, itest);
}
dd_LPSolve(lp,dd_choiceRedcheckAlgorithm,&err);
if (err!=dd_NoError){
*error=err;
goto _L999;
} else {
lps=dd_CopyLPSolution(lp);
for (j=0; j<lps->d; j++) {
dd_set(certificate[j], lps->sol[j]);
}
if (localdebug){
printf("Optimum value:");
dd_WriteNumber(stdout, lps->optvalue);
printf("\n");
}
if (M->representation==dd_Inequality){
if (dd_Positive(lps->optvalue)){
answer=dd_TRUE;
if (localdebug) fprintf(stderr,"==> %ld th inequality is strongly redundant.\n",itest);
} else {
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th inequality is not strongly redundant.\n",itest);
}
} else {
if (dd_Negative(lps->optvalue)){
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th point is not strongly redundant.\n",itest);
} else {
dd_FreeLPData(lp);
dd_FreeLPSolution(lps);
lp=dd_CreateLP_V_SRedundancy(M, itest);
dd_LPSolve(lp,dd_DualSimplex,&err);
lps=dd_CopyLPSolution(lp);
if (localdebug) dd_WriteLPResult(stdout,lp,err);
if (dd_Positive(lps->optvalue)){
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th point is not strongly redundant.\n",itest);
} else {
answer=dd_TRUE;
if (localdebug) fprintf(stderr,"==> %ld th point is strongly redundant.\n",itest);
}
}
}
dd_FreeLPSolution(lps);
}
_L999:
dd_FreeLPData(lp);
_L99:
return answer;
}
dd_rowset dd_SRedundantRows(dd_MatrixPtr M, dd_ErrorType *error)
{
dd_rowrange i,m;
dd_colrange d;
dd_rowset redset;
dd_MatrixPtr Mcopy;
dd_Arow cvec;
dd_boolean localdebug=dd_FALSE;
m=M->rowsize;
if (M->representation==dd_Generator){
d=(M->colsize)+1;
} else {
d=M->colsize;
}
Mcopy=dd_MatrixCopy(M);
dd_InitializeArow(d,&cvec);
set_initialize(&redset, m);
for (i=m; i>=1; i--) {
if (dd_SRedundant(Mcopy, i, cvec, error)) {
if (localdebug) printf("dd_SRedundantRows: the row %ld is strongly redundant.\n", i);
set_addelem(redset, i);
dd_MatrixRowRemove(&Mcopy, i);
} else {
if (localdebug) printf("dd_SRedundantRows: the row %ld is not strongly redundant.\n", i);
}
if (*error!=dd_NoError) goto _L99;
}
_L99:
dd_FreeMatrix(Mcopy);
dd_FreeArow(d, cvec);
return redset;
}
dd_rowset dd_RedundantRowsViaShooting(dd_MatrixPtr M, dd_ErrorType *error)
{
dd_rowrange i,m, ired, irow=0;
dd_colrange j,k,d;
dd_rowset redset;
dd_rowindex rowflag;
dd_MatrixPtr M1;
dd_Arow shootdir, cvec=NULL;
dd_LPPtr lp0, lp;
dd_LPSolutionPtr lps;
dd_ErrorType err;
dd_LPSolverType solver=dd_DualSimplex;
dd_boolean localdebug=dd_FALSE;
m=M->rowsize;
d=M->colsize;
M1=dd_CreateMatrix(m,d);
M1->rowsize=0;
set_initialize(&redset, m);
dd_InitializeArow(d, &shootdir);
dd_InitializeArow(d, &cvec);
rowflag=(long *)calloc(m+1, sizeof(long));
lp0=dd_Matrix2LP(M, &err);
lp=dd_MakeLPforInteriorFinding(lp0);
dd_FreeLPData(lp0);
dd_LPSolve(lp, solver, &err);
lps=dd_CopyLPSolution(lp);
if (dd_Positive(lps->optvalue)){
for (j=1; j<d; j++){
for (k=1; k<=d; k++) dd_set(shootdir[k-1], dd_purezero);
dd_set(shootdir[j], dd_one);
ired=dd_RayShooting(M, lps->sol, shootdir);
if (localdebug) printf("nonredundant row %3ld found by shooting.\n", ired);
if (ired>0 && rowflag[ired]<=0) {
irow++;
rowflag[ired]=irow;
for (k=1; k<=d; k++) dd_set(M1->matrix[irow-1][k-1], M->matrix[ired-1][k-1]);
}
dd_neg(shootdir[j], dd_one);
ired=dd_RayShooting(M, lps->sol, shootdir);
if (localdebug) printf("nonredundant row %3ld found by shooting.\n", ired);
if (ired>0 && rowflag[ired]<=0) {
irow++;
rowflag[ired]=irow;
for (k=1; k<=d; k++) dd_set(M1->matrix[irow-1][k-1], M->matrix[ired-1][k-1]);
}
}
M1->rowsize=irow;
if (localdebug) {
printf("The initial nonredundant set is:");
for (i=1; i<=m; i++) if (rowflag[i]>0) printf(" %ld", i);
printf("\n");
}
i=1;
while(i<=m){
if (rowflag[i]==0){
if (localdebug) fprintf(stderr, "Checking redundancy of %ld th inequality\n", i);
irow++; M1->rowsize=irow;
for (k=1; k<=d; k++) dd_set(M1->matrix[irow-1][k-1], M->matrix[i-1][k-1]);
if (!dd_Redundant(M1, irow, cvec, &err)){
for (k=1; k<=d; k++) dd_sub(shootdir[k-1], cvec[k-1], lps->sol[k-1]);
ired=dd_RayShooting(M, lps->sol, shootdir);
rowflag[ired]=irow;
for (k=1; k<=d; k++) dd_set(M1->matrix[irow-1][k-1], M->matrix[ired-1][k-1]);
if (localdebug) {
fprintf(stderr, "The %ld th inequality is nonredundant for the subsystem\n", i);
fprintf(stderr, "The nonredundancy of %ld th inequality is found by shooting.\n", ired);
}
} else {
if (localdebug) fprintf(stderr, "The %ld th inequality is redundant for the subsystem and thus for the whole.\n", i);
rowflag[i]=-1;
set_addelem(redset, i);
i++;
}
} else {
i++;
}
}
} else {
redset=dd_RedundantRows(M, error);
}
dd_FreeLPData(lp);
dd_FreeLPSolution(lps);
M1->rowsize=m; M1->colsize=d;
dd_FreeMatrix(M1);
dd_FreeArow(d, shootdir);
dd_FreeArow(d, cvec);
free(rowflag);
return redset;
}
dd_SetFamilyPtr dd_Matrix2Adjacency(dd_MatrixPtr M, dd_ErrorType *error)
{
dd_rowrange i,m;
dd_colrange d;
dd_rowset redset;
dd_MatrixPtr Mcopy;
dd_SetFamilyPtr F=NULL;
m=M->rowsize;
d=M->colsize;
if (m<=0 ||d<=0) {
*error=dd_EmptyRepresentation;
goto _L999;
}
Mcopy=dd_MatrixCopy(M);
F=dd_CreateSetFamily(m, m);
for (i=1; i<=m; i++) {
if (!set_member(i, M->linset)){
set_addelem(Mcopy->linset, i);
redset=dd_RedundantRows(Mcopy, error);
set_uni(redset, redset, Mcopy->linset);
set_compl(F->set[i-1], redset);
set_delelem(Mcopy->linset, i);
set_free(redset);
if (*error!=dd_NoError) goto _L99;
}
}
_L99:
dd_FreeMatrix(Mcopy);
_L999:
return F;
}
dd_SetFamilyPtr dd_Matrix2WeakAdjacency(dd_MatrixPtr M, dd_ErrorType *error)
{
dd_rowrange i,m;
dd_colrange d;
dd_rowset redset;
dd_MatrixPtr Mcopy;
dd_SetFamilyPtr F=NULL;
m=M->rowsize;
d=M->colsize;
if (m<=0 ||d<=0) {
*error=dd_EmptyRepresentation;
goto _L999;
}
Mcopy=dd_MatrixCopy(M);
F=dd_CreateSetFamily(m, m);
for (i=1; i<=m; i++) {
if (!set_member(i, M->linset)){
set_addelem(Mcopy->linset, i);
redset=dd_SRedundantRows(Mcopy, error);
set_uni(redset, redset, Mcopy->linset);
set_compl(F->set[i-1], redset);
set_delelem(Mcopy->linset, i);
set_free(redset);
if (*error!=dd_NoError) goto _L99;
}
}
_L99:
dd_FreeMatrix(Mcopy);
_L999:
return F;
}
dd_boolean dd_ImplicitLinearity(dd_MatrixPtr M, dd_rowrange itest, dd_Arow certificate, dd_ErrorType *error)
{
dd_colrange j;
dd_LPPtr lp;
dd_LPSolutionPtr lps;
dd_ErrorType err=dd_NoError;
dd_boolean answer=dd_FALSE,localdebug=dd_FALSE;
*error=dd_NoError;
if (set_member(itest, M->linset)){
if (localdebug) printf("The %ld th row is linearity and redundancy checking is skipped.\n",itest);
goto _L99;
}
if (M->representation==dd_Generator){
lp=dd_CreateLP_V_Redundancy(M, itest);
} else {
lp=dd_CreateLP_H_Redundancy(M, itest);
}
lp->objective = dd_LPmax;
dd_LPSolve(lp,dd_choiceRedcheckAlgorithm,&err);
if (err!=dd_NoError){
*error=err;
goto _L999;
} else {
lps=dd_CopyLPSolution(lp);
for (j=0; j<lps->d; j++) {
dd_set(certificate[j], lps->sol[j]);
}
if (lps->LPS==dd_Optimal && dd_EqualToZero(lps->optvalue)){
answer=dd_TRUE;
if (localdebug) fprintf(stderr,"==> %ld th data is an implicit linearity.\n",itest);
} else {
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th data is not an implicit linearity.\n",itest);
}
dd_FreeLPSolution(lps);
}
_L999:
dd_FreeLPData(lp);
_L99:
return answer;
}
int dd_FreeOfImplicitLinearity(dd_MatrixPtr M, dd_Arow certificate, dd_rowset *imp_linrows, dd_ErrorType *error)
{
dd_LPPtr lp;
dd_rowrange i,m;
dd_colrange j,d1;
dd_ErrorType err=dd_NoError;
dd_Arow cvec;
int answer=0,localdebug=dd_FALSE;
*error=dd_NoError;
if (M->representation==dd_Generator){
lp=dd_CreateLP_V_ImplicitLinearity(M);
} else {
lp=dd_CreateLP_H_ImplicitLinearity(M);
}
dd_LPSolve(lp,dd_choiceRedcheckAlgorithm,&err);
if (err!=dd_NoError){
*error=err;
goto _L999;
} else {
for (j=0; j<lp->d; j++) {
dd_set(certificate[j], lp->sol[j]);
}
if (localdebug) dd_WriteLPResult(stderr,lp,err);
if (localdebug) {
fprintf(stderr,"==> The following variables are not implicit linearity:\n");
set_fwrite(stderr, lp->posset_extra);
fprintf(stderr,"\n");
}
if (M->representation==dd_Generator){
d1=(M->colsize)+1;
} else {
d1=M->colsize;
}
m=M->rowsize;
dd_InitializeArow(d1,&cvec);
set_initialize(imp_linrows,m);
if (lp->LPS==dd_Optimal){
if (dd_Positive(lp->optvalue)){
answer=1;
if (localdebug) fprintf(stderr,"==> The matrix has no implicit linearity.\n");
} else if (dd_Negative(lp->optvalue)) {
answer=-1;
if (localdebug) fprintf(stderr,"==> The matrix defines the trivial system.\n");
} else {
answer=0;
if (localdebug) fprintf(stderr,"==> The matrix has some implicit linearity.\n");
}
} else {
answer=-2;
if (localdebug) fprintf(stderr,"==> The LP fails.\n");
}
if (answer==0){
for (i=m; i>=1; i--) {
if (!set_member(i,lp->posset_extra)) {
if (dd_ImplicitLinearity(M, i, cvec, error)) {
set_addelem(*imp_linrows, i);
if (localdebug) {
fprintf(stderr," row %ld is implicit linearity\n",i);
fprintf(stderr,"\n");
}
}
if (*error!=dd_NoError) goto _L999;
}
}
}
if (answer==-1) {
for (i=m; i>=1; i--) set_addelem(*imp_linrows, i);
}
dd_FreeArow(d1,cvec);
}
_L999:
dd_FreeLPData(lp);
return answer;
}
dd_rowset dd_ImplicitLinearityRows(dd_MatrixPtr M, dd_ErrorType *error)
{
dd_colrange d;
dd_rowset imp_linset;
dd_Arow cvec;
int foi;
dd_boolean localdebug=dd_FALSE;
if (M->representation==dd_Generator){
d=(M->colsize)+2;
} else {
d=M->colsize+1;
}
dd_InitializeArow(d,&cvec);
if (localdebug) fprintf(stdout, "\ndd_ImplicitLinearityRows: Check whether the system contains any implicit linearity.\n");
foi=dd_FreeOfImplicitLinearity(M, cvec, &imp_linset, error);
if (localdebug){
switch (foi) {
case 1:
fprintf(stdout, " It is free of implicit linearity.\n");
break;
case 0:
fprintf(stdout, " It is not free of implicit linearity.\n");
break;
case -1:
fprintf(stdout, " The input system is trivial (i.e. the empty H-polytope or the V-rep of the whole space.\n");
break;
default:
fprintf(stdout, " The LP was not solved correctly.\n");
break;
}
}
if (localdebug){
fprintf(stderr, " Implicit linearity rows are:\n");
set_fwrite(stderr,imp_linset);
fprintf(stderr, "\n");
}
dd_FreeArow(d, cvec);
return imp_linset;
}
dd_boolean dd_MatrixCanonicalizeLinearity(dd_MatrixPtr *M, dd_rowset *impl_linset,dd_rowindex *newpos,
dd_ErrorType *error)
{
dd_rowrange rank;
dd_rowset linrows,ignoredrows,basisrows;
dd_colset ignoredcols,basiscols;
dd_rowrange i,k,m;
dd_rowindex newpos1;
dd_boolean success=dd_FALSE;
linrows=dd_ImplicitLinearityRows(*M, error);
if (*error!=dd_NoError) goto _L99;
m=(*M)->rowsize;
set_uni((*M)->linset, (*M)->linset, linrows);
set_initialize(&ignoredrows, (*M)->rowsize);
set_initialize(&ignoredcols, (*M)->colsize);
set_compl(ignoredrows, (*M)->linset);
rank=dd_MatrixRank(*M,ignoredrows,ignoredcols,&basisrows,&basiscols);
set_diff(ignoredrows, (*M)->linset, basisrows);
dd_MatrixRowsRemove2(M,ignoredrows,newpos);
dd_MatrixShiftupLinearity(M,&newpos1);
for (i=1; i<=m; i++){
k=(*newpos)[i];
if (k>0) {
(*newpos)[i]=newpos1[k];
}
}
*impl_linset=linrows;
success=dd_TRUE;
free(newpos1);
set_free(basisrows);
set_free(basiscols);
set_free(ignoredrows);
set_free(ignoredcols);
_L99:
return success;
}
dd_boolean dd_MatrixCanonicalize(dd_MatrixPtr *M, dd_rowset *impl_linset, dd_rowset *redset,
dd_rowindex *newpos, dd_ErrorType *error)
{
dd_rowrange i,k,m;
dd_rowindex newpos1,revpos;
dd_rowset redset1;
dd_boolean success=dd_TRUE;
m=(*M)->rowsize;
set_initialize(redset, m);
revpos=(long *)calloc(m+1,sizeof(long));
success=dd_MatrixCanonicalizeLinearity(M, impl_linset, newpos, error);
if (!success) goto _L99;
for (i=1; i<=m; i++){
k=(*newpos)[i];
if (k>0) revpos[k]=i;
}
success=dd_MatrixRedundancyRemove(M, &redset1, &newpos1, error);
if (!success) goto _L99;
for (i=1; i<=m; i++){
k=(*newpos)[i];
if (k>0) {
(*newpos)[i]=newpos1[k];
if (newpos1[k]<0) (*newpos)[i]=-revpos[-newpos1[k]];
if (set_member(k,redset1)) set_addelem(*redset, i);
}
}
_L99:
set_free(redset1);
free(newpos1);
free(revpos);
return success;
}
dd_boolean dd_ExistsRestrictedFace(dd_MatrixPtr M, dd_rowset R, dd_rowset S, dd_ErrorType *err)
{
dd_boolean answer=dd_FALSE;
dd_LPPtr lp=NULL;
lp=dd_Matrix2Feasibility2(M, R, S, err);
if (*err!=dd_NoError) goto _L99;
dd_LPSolve(lp, dd_DualSimplex, err);
if (*err!=dd_NoError) goto _L99;
if (lp->LPS==dd_Optimal && dd_Positive(lp->optvalue)) {
answer=dd_TRUE;
}
dd_FreeLPData(lp);
_L99:
return answer;
}
dd_boolean dd_ExistsRestrictedFace2(dd_MatrixPtr M, dd_rowset R, dd_rowset S, dd_LPSolutionPtr *lps, dd_ErrorType *err)
{
dd_boolean answer=dd_FALSE;
dd_LPPtr lp=NULL;
lp=dd_Matrix2Feasibility2(M, R, S, err);
if (*err!=dd_NoError) goto _L99;
dd_LPSolve(lp, dd_DualSimplex, err);
if (*err!=dd_NoError) goto _L99;
if (lp->LPS==dd_Optimal && dd_Positive(lp->optvalue)) {
answer=dd_TRUE;
}
(*lps)=dd_CopyLPSolution(lp);
dd_FreeLPData(lp);
_L99:
return answer;
}
dd_boolean dd_FindRelativeInterior(dd_MatrixPtr M, dd_rowset *ImL, dd_rowset *Lbasis, dd_LPSolutionPtr *lps, dd_ErrorType *err)
{
dd_rowset S;
dd_colset T, Lbasiscols;
dd_boolean success=dd_FALSE;
dd_rowrange i;
dd_colrange rank;
*ImL=dd_ImplicitLinearityRows(M, err);
if (*err!=dd_NoError) goto _L99;
set_initialize(&S, M->rowsize);
for (i=1; i <=M->rowsize; i++) {
if (!set_member(i, M->linset) && !set_member(i, *ImL)){
set_addelem(S, i);
}
}
if (dd_ExistsRestrictedFace2(M, *ImL, S, lps, err)){
success=dd_TRUE;
}
set_initialize(&T, M->colsize);
rank=dd_MatrixRank(M,S,T,Lbasis,&Lbasiscols);
set_free(S);
set_free(T);
set_free(Lbasiscols);
_L99:
return success;
}
dd_rowrange dd_RayShooting(dd_MatrixPtr M, dd_Arow p, dd_Arow r)
{
dd_rowrange imin=-1,i,m;
dd_colrange j, d;
dd_Arow vecmin, vec;
mytype min,t1,t2,alpha, t1min;
dd_boolean started=dd_FALSE;
dd_boolean localdebug=dd_FALSE;
m=M->rowsize;
d=M->colsize;
if (!dd_Equal(dd_one, p[0])){
fprintf(stderr, "Warning: RayShooting is called with a point with first coordinate not 1.\n");
dd_set(p[0],dd_one);
}
if (!dd_EqualToZero(r[0])){
fprintf(stderr, "Warning: RayShooting is called with a direction with first coordinate not 0.\n");
dd_set(r[0],dd_purezero);
}
dd_init(alpha); dd_init(min); dd_init(t1); dd_init(t2); dd_init(t1min);
dd_InitializeArow(d,&vecmin);
dd_InitializeArow(d,&vec);
for (i=1; i<=m; i++){
dd_InnerProduct(t1, d, M->matrix[i-1], p);
if (dd_Positive(t1)) {
dd_InnerProduct(t2, d, M->matrix[i-1], r);
dd_div(alpha, t2, t1);
if (!started){
imin=i; dd_set(min, alpha);
dd_set(t1min, t1);
started=dd_TRUE;
if (localdebug) {
fprintf(stderr," Level 1: imin = %ld and min = ", imin);
dd_WriteNumber(stderr, min);
fprintf(stderr,"\n");
}
} else {
if (dd_Smaller(alpha, min)){
imin=i; dd_set(min, alpha);
dd_set(t1min, t1);
if (localdebug) {
fprintf(stderr," Level 2: imin = %ld and min = ", imin);
dd_WriteNumber(stderr, min);
fprintf(stderr,"\n");
}
} else {
if (dd_Equal(alpha, min)) {
for (j=1; j<= d; j++){
dd_div(vecmin[j-1], M->matrix[imin-1][j-1], t1min);
dd_div(vec[j-1], M->matrix[i-1][j-1], t1);
}
if (dd_LexSmaller(vec,vecmin, d)){
imin=i; dd_set(min, alpha);
dd_set(t1min, t1);
if (localdebug) {
fprintf(stderr," Level 3: imin = %ld and min = ", imin);
dd_WriteNumber(stderr, min);
fprintf(stderr,"\n");
}
}
}
}
}
}
}
dd_clear(alpha); dd_clear(min); dd_clear(t1); dd_clear(t2); dd_clear(t1min);
dd_FreeArow(d, vecmin);
dd_FreeArow(d, vec);
return imin;
}
#ifdef GMPRATIONAL
void dd_BasisStatusMaximize(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A,dd_Bmatrix T,dd_rowset equalityset,
dd_rowrange objrow,dd_colrange rhscol,ddf_LPStatusType LPS,
mytype *optvalue,dd_Arow sol,dd_Arow dsol,dd_rowset posset, ddf_colindex nbindex,
ddf_rowrange re,ddf_colrange se, dd_colrange *nse, long *pivots, int *found, int *LPScorrect)
{
long pivots0,pivots1,fbasisrank;
dd_rowrange i,is;
dd_colrange s,senew,j;
static dd_rowindex bflag;
static long mlast=0;
static dd_rowindex OrderVector;
unsigned int rseed=1;
mytype val;
dd_colindex nbtemp;
dd_LPStatusType ddlps;
dd_boolean localdebug=dd_FALSE;
if (dd_debug) localdebug=dd_debug;
if (localdebug){
printf("\nEvaluating dd_BasisStatusMaximize:\n");
}
dd_init(val);
nbtemp=(long *) calloc(d_size+1,sizeof(long));
for (i=0; i<= 4; i++) pivots[i]=0;
if (bflag==NULL || mlast!=m_size){
if (mlast!=m_size && mlast>0) {
free(bflag);
free(OrderVector);
}
bflag=(long *) calloc(m_size+1,sizeof(long));
OrderVector=(long *)calloc(m_size+1,sizeof(long));
mlast=m_size;
}
dd_ComputeRowOrderVector2(m_size,d_size,A,OrderVector,dd_MinIndex,rseed);
pivots1=0;
dd_ResetTableau(m_size,d_size,T,nbtemp,bflag,objrow,rhscol);
if (localdebug){
printf("\nnbindex:");
for (j=1; j<=d_size; j++) printf(" %ld", nbindex[j]);
printf("\n");
printf("re = %ld, se=%ld\n", re, se);
}
is=nbindex[se];
if (localdebug) printf("se=%ld, is=%ld\n", se, is);
fbasisrank=d_size-1;
for (j=1; j<=d_size; j++){
if (nbindex[j]<0) fbasisrank=fbasisrank-1;
}
if (fbasisrank<d_size-1) {
if (localdebug) {
printf("d_size = %ld, the size of basis = %ld\n", d_size, fbasisrank);
printf("dd_BasisStatusMaximize: the size of basis is smaller than d-1.\nIt is safer to run the LP solver with GMP\n");
}
*found=dd_FALSE;
goto _L99;
}
dd_FindLPBasis2(m_size,d_size,A,T,OrderVector, equalityset,nbindex,bflag,
objrow,rhscol,&s,found,&pivots0);
senew=bflag[is];
is=nbindex[senew];
if (localdebug) printf("new se=%ld, is=%ld\n", senew, is);
pivots[4]=pivots0;
dd_statBSpivots+=pivots0;
if (!(*found)){
if (localdebug) {
printf("dd_BasisStatusMaximize: a specified basis DOES NOT exist.\n");
}
goto _L99;
}
if (localdebug) {
printf("dd_BasisStatusMaximize: a specified basis exists.\n");
if (m_size <=100 && d_size <=30)
dd_WriteTableau(stdout,m_size,d_size,A,T,nbindex,bflag);
}
*LPScorrect=dd_TRUE;
switch (LPS){
case dd_Optimal:
for (i=1; i<=m_size; i++) {
if (i!=objrow && bflag[i]==-1) {
dd_TableauEntry(&val,m_size,d_size,A,T,i,rhscol);
if (dd_Negative(val)) {
if (localdebug) printf("RHS entry for %ld is negative\n", i);
*LPScorrect=dd_FALSE;
break;
}
} else if (bflag[i] >0) {
dd_TableauEntry(&val,m_size,d_size,A,T,objrow,bflag[i]);
if (dd_Positive(val)) {
if (localdebug) printf("Reduced cost entry for %ld is positive\n", i);
*LPScorrect=dd_FALSE;
break;
}
}
};
break;
case dd_Inconsistent:
for (j=1; j<=d_size; j++){
dd_TableauEntry(&val,m_size,d_size,A,T,re,j);
if (j==rhscol){
if (dd_Nonnegative(val)){
if (localdebug) printf("RHS entry for %ld is nonnegative\n", re);
*LPScorrect=dd_FALSE;
break;
}
} else if (dd_Positive(val)){
if (localdebug) printf("the row entry for(%ld, %ld) is positive\n", re, j);
*LPScorrect=dd_FALSE;
break;
}
};
break;
case dd_DualInconsistent:
for (i=1; i<=m_size; i++){
dd_TableauEntry(&val,m_size,d_size,A,T,i,bflag[is]);
if (i==objrow){
if (dd_Nonpositive(val)){
if (localdebug) printf("Reduced cost entry for %ld is nonpositive\n", bflag[is]);
*LPScorrect=dd_FALSE;
break;
}
} else if (dd_Negative(val)){
if (localdebug) printf("the column entry for(%ld, %ld) is positive\n", i, bflag[is]);
*LPScorrect=dd_FALSE;
break;
}
};
break;
;
default: break;
}
ddlps=LPSf2LPS(LPS);
dd_SetSolutions(m_size,d_size,A,T,
objrow,rhscol,ddlps,optvalue,sol,dsol,posset,nbindex,re,senew,bflag);
*nse=senew;
_L99:
dd_clear(val);
free(nbtemp);
}
void dd_BasisStatusMinimize(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A,dd_Bmatrix T,dd_rowset equalityset,
dd_rowrange objrow,dd_colrange rhscol,ddf_LPStatusType LPS,
mytype *optvalue,dd_Arow sol,dd_Arow dsol, dd_rowset posset, ddf_colindex nbindex,
ddf_rowrange re,ddf_colrange se,dd_colrange *nse,long *pivots, int *found, int *LPScorrect)
{
dd_colrange j;
for (j=1; j<=d_size; j++) dd_neg(A[objrow-1][j-1],A[objrow-1][j-1]);
dd_BasisStatusMaximize(m_size,d_size,A,T,equalityset, objrow,rhscol,
LPS,optvalue,sol,dsol,posset,nbindex,re,se,nse,pivots,found,LPScorrect);
dd_neg(*optvalue,*optvalue);
for (j=1; j<=d_size; j++){
if (LPS!=dd_Inconsistent) {
dd_neg(dsol[j-1],dsol[j-1]);
}
dd_neg(A[objrow-1][j-1],A[objrow-1][j-1]);
}
}
#endif