コード例 #1
0
ファイル: dy_basis.c プロジェクト: coin-or/DyLP
static void luf_adjustsize (void)
/*
  This routine sets the proper working size in the basis. It also checks that
  the allocated capacity of the basis is sufficient for the current size of
  the constraint system and increases it if necessary.

  Parameters: none

  Returns: undefined
*/

{ double upd_tol,piv_tol,zero_tol,max_gro ;
  int factor,look,capacity ;
# ifndef DYLP_NDEBUG
  int oldcapacity ;
# endif
/*
  Check that we're within the allocated limits, and resize if necessary.
  Preserve the tolerance settings that we may have tweaked.
*/
  if (dy_sys->concnt > luf_capacity)
  { factor = luf_basis->hh_max ;
    upd_tol = luf_basis->upd_tol ;
    zero_tol = luf_basis->luf->eps_tol ;
    piv_tol = luf_basis->luf->piv_tol ;
    look = luf_basis->luf->piv_lim ;
    max_gro = luf_basis->luf->max_gro ;
#   ifndef DYLP_NDEBUG
    oldcapacity = luf_basis->m ;
#   endif
    dy_freebasis() ;
    capacity = (int) (dy_sys->concnt*1.5) ;
    dy_initbasis(capacity,factor,zero_tol) ;
    luf_basis->upd_tol = upd_tol ;
    luf_basis->luf->eps_tol = zero_tol ;
    luf_basis->luf->piv_tol = piv_tol ;
    luf_basis->luf->piv_lim = look ;
    luf_basis->luf->max_gro = max_gro ;
#   ifndef DYLP_NDEBUG
    if (dy_opts->print.basis >= 2)
    { dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n    increased basis capacity from %d to %d constraints",
		  oldcapacity,luf_basis->m) ;
      dyio_outfmt(dy_logchn,dy_gtxecho,", piv lim %d.",luf_basis->hh_max) ; }
#   endif
  }
/*
  Now set the working size.
*/
  luf_basis->m = dy_sys->concnt ;
  luf_basis->luf->n = dy_sys->concnt ;

  return ; }
コード例 #2
0
ファイル: dy_basis.c プロジェクト: coin-or/DyLP
double dy_chkpiv (double abarij, double maxabar)

/*
  This routine checks that the pivot element satisfies a stability test. The
  stability test is
    |abarij/maxabar| > dy_tols->pivot*piv_tol

  The motivation for the check is to try and choose reasonably stable pivots
  --- inv_update will do what we tell it, might as well try to choose half
  wisely. Balance that against the desire to make progress toward the
  optimum. Setting dy_tols->pivot to 1 would give the same selection criteria
  as is used during factorization.

  Parameters:
    abarij:	the pivot element (only the absolute value is used)
    maxabar:	(primal) max{i} |abar<i,j>|
		(dual)   max{j} |abar<i,j>|

  Returns: |abarij/(dy_tols->pivot*piv_tol*maxabar)|
	   return value < 1.0 indicates an unstable pivot
*/

{ double ratio,abspiv,stable ;
  
# if defined(DYLP_PARANOIA) || !defined(DYLP_NDEBUG)
  const char *rtnnme = "dy_chkpiv" ;
# endif

# ifdef DYLP_PARANOIA
  if (luf_basis == NULL)
  { errmsg(2,rtnnme,"luf_basis") ;
    return (dyrFATAL) ; }
# endif

/*
  In some instances (for example, netlib/grow22), we run into trouble because
  column coefficients inflate to outrageous values --- 1.0e18, for example.
  Take the attitude that any pivot s.t. |abar<ij> > 1.0| should be accepted,
  to give a bit more choice in pivot selection. To do this, lie about the
  stability ratio,
*/
  abspiv = fabs(abarij) ;
  ratio = dy_tols->pivot*luf_basis->luf->piv_tol ;
  stable = ratio*maxabar ;
# ifndef DYLP_NDEBUG
  if (dy_opts->print.pivoting >= 1)
  { if (abspiv/stable < 1.0)
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n%s: %s pivot = %g < %g; column max = %g, ratio = %g.",
		  rtnnme,(abspiv < 1.0)?"rejecting":"tolerating",
		  abarij,stable,maxabar,ratio) ; }
# endif
  
  if (abspiv/stable >= 1.0)
    return (abspiv/stable) ;
  else
  if (abspiv >= 1.0)
    return (1.0) ;
  else
    return (abspiv/stable) ; }
コード例 #3
0
ファイル: osi_dylp.c プロジェクト: sednanref/tesis
static void print_version (ioid chn, bool echo,
			   const char *cmd, const char *nme, const char *ver)
/*
  Print version, copyright, and free software disclaimer.
*/

{ const char *disc1 = "This is free software; see the source for copying"
		      " conditions. There is NO" ;
  const char *disc2 = "warranty; not even for MERCHANTABILITY or FITNESS FOR A"
		      " PARTICULAR PURPOSE." ;

  dyio_outfmt(dy_logchn,dy_gtxecho,"\n%s (%s) V %s",cmd,nme,ver) ;
  dyio_outfmt(dy_logchn,dy_gtxecho,"\nCopyright (C) 2004 Lou Hafer") ;
  dyio_outfmt(dy_logchn,dy_gtxecho,"\n%s\n%s\n",disc1,disc2) ;

  return ; }
コード例 #4
0
ファイル: osi_dylp.c プロジェクト: sednanref/tesis
static void prt_timeval (ioid chn, bool echo, struct timeval *tv)

/*
  A little local utility to print a timeval as hh:mm:ss.ss.

  Parameters:
    chn:	output channel id
    echo:	controls echo to stdout
    tv:		timeval to be printed
  
  Returns: undefined
*/

{ int hrs, mins, secs, csecs ;

  hrs = tv->tv_sec/3600 ;
  mins = tv->tv_sec%3600 ;
  secs = mins%60 ;
  mins = mins/60 ;
  csecs = tv->tv_usec/1e4 ;
  dyio_outfmt(chn,echo,"%d:%02d:%02d.%02d",hrs,mins,secs,csecs) ;

  return ; }
コード例 #5
0
ファイル: dy_hotstart.c プロジェクト: coin-or/DyLP
void dy_setfinalstatus (void)

/*
  This code is common to all three start routines (coldstart, warmstart,
  hotstart). It scans the newly calculated basic variables and assigns
  them their final status. In the process, it calculates the number of
  infeasible variables, and the total infeasibility.

  Parameters: none

  Returns: undefined
*/

{ int aindx, xkndx ;
  double xk,lbk,ubk ;

# ifdef DYLP_PARANOIA
  const char *rtnnme = "dy_setfinalstatus" ;
# endif

# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 2)
    dyio_outfmt(dy_logchn,dy_gtxecho,"\n\testablishing final status ...") ;
# endif

  dy_lp->infeas = 0.0 ;
  dy_lp->infeascnt = 0 ;

/*
  Step through the constraints, and have a look at the basic variable in each
  position.

  The paranoid check will complain if the basis is corrupt, but since nothing
  can go wrong if we're not paranoid, it just complains and moves to the next
  entry.
*/
  for (aindx = 1 ; aindx <= dy_sys->concnt ; aindx++)
  { xkndx = dy_basis[aindx] ;
    xk = dy_xbasic[aindx] ;
    lbk = dy_sys->vlb[xkndx] ;
    ubk = dy_sys->vub[xkndx] ;
#   ifdef DYLP_PARANOIA
    if (xkndx <= 0 || xkndx > dy_sys->varcnt)
    { errmsg(303,rtnnme,dy_sys->nme,aindx,1,xkndx,dy_sys->varcnt) ;
      continue ; }
#   endif
    switch (dy_status[xkndx])
    { case vstatB:
      { if (atbnd(xk,lbk))
	{ dy_status[xkndx] = vstatBLB ; }
	else
	if (belowbnd(xk,lbk))
	{ dy_lp->infeascnt++ ;
	  dy_lp->infeas += lbk-xk ;
	  dy_status[xkndx] = vstatBLLB ; }
	else
	if (atbnd(xk,ubk))
	{ dy_status[xkndx] = vstatBUB ; }
	else
	if (abovebnd(xk,ubk))
	{ dy_lp->infeascnt++ ;
	  dy_lp->infeas += xk-ubk ;
	  dy_status[xkndx] = vstatBUUB ; }
	break ; }
      case vstatBFX:
      { if (!atbnd(xk,lbk))
	{ if (belowbnd(xk,lbk))
	  { dy_lp->infeascnt++ ; 
	    dy_lp->infeas += lbk-xk ;
	    dy_status[xkndx] = vstatBLLB ; }
	  else
	  { dy_lp->infeascnt++ ;
	    dy_lp->infeas += xk-ubk ;
	    dy_status[xkndx] = vstatBUUB ; } }
	break ; } }
#   ifndef DYLP_NDEBUG
    if (dy_opts->print.crash >= 4)
    { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t  %s (%d) %s",
		  consys_nme(dy_sys,'v',xkndx,FALSE,NULL),xkndx,
		  dy_prtvstat(dy_status[xkndx])) ;
      if (lbk > -dy_tols->inf)
	dyio_outfmt(dy_logchn,dy_gtxecho,", lb = %g",lbk) ;
      dyio_outfmt(dy_logchn,dy_gtxecho,", val = %g",xk) ;
      if (ubk < dy_tols->inf)
	dyio_outfmt(dy_logchn,dy_gtxecho,", ub = %g",ubk) ;
      if (flgon(dy_status[xkndx],vstatBLLB|vstatBUUB))
      { dyio_outfmt(dy_logchn,dy_gtxecho,", infeasibility = ") ;
	if (flgon(dy_status[xkndx],vstatBLLB))
	  dyio_outfmt(dy_logchn,dy_gtxecho,"%g",lbk-xk) ;
	else
	  dyio_outfmt(dy_logchn,dy_gtxecho,"%g",xk-ubk) ; }
      dyio_outchr(dy_logchn,dy_gtxecho,'.') ; }
#   endif
  }
  setcleanzero(dy_lp->infeas,dy_tols->zero) ;

  return ; }
コード例 #6
0
ファイル: dy_hotstart.c プロジェクト: coin-or/DyLP
static void process_active (lpprob_struct *orig_lp, int oxkndx)

/*
  This routine handles the data structure updates for an active variable
  x<k>.  We need to copy the new values for l<k>, u<k>, and c<k> into the
  active system. For nonbasic variables, we need to choose a status based on
  the bounds.  For basic variables, the status vector encodes the basis
  index, so we need to decide on an initial status --- either B, BFX, or BFR.

  The routine expects that bounds have been groomed (i.e., if the difference
  between l<k> and u<k> is less than the feasibility tolerance, they have been
  forced to exact equality).

  Parameters:
    orig_lp:	the original lp problem
    oxkndx:	index of x<k> in orig_sys
  
  Returns: undefined (the only possible error is a paranoid check)
*/

{ int xkndx ;
  double lk,uk,xk ;
  flags xkstatus ;
  consys_struct *orig_sys ;

# ifdef DYLP_PARANOIA
  const char *rtnnme = "process_active" ;
# endif

  orig_sys = orig_lp->consys ;
/*
  Get the index of the variable in the active system, and the status.
  The paranoid check is that we're not attempting to convert between
  basic and nonbasic status.
*/
  xkndx = dy_origvars[oxkndx] ;
  xkstatus = dy_status[xkndx] ;

# ifdef DYLP_PARANOIA
  if ((flgon(xkstatus,vstatBASIC) &&
       ((int) orig_lp->status[oxkndx]) > 0) ||
      (flgon(xkstatus,vstatNONBASIC|vstatNBFR) &&
       ((int) orig_lp->status[oxkndx]) < 0))
  { char buf[30] ;
    if (((int) orig_lp->status[oxkndx]) > 0)
      strcpy(buf,dy_prtvstat(orig_lp->status[oxkndx])) ;
    else
      strcpy(buf,"unspecified basic") ;
    errmsg(398,rtnnme,dy_sys->nme,consys_nme(dy_sys,'v',xkndx,FALSE,NULL),
	   xkndx,dy_prtvstat(xkstatus),buf) ;
    return ; }
# endif
/*
  Update the bounds and objective coefficient.
*/
  lk = orig_sys->vlb[oxkndx] ;
  dy_sys->vlb[xkndx] = lk ;
  uk = orig_sys->vub[oxkndx] ;
  dy_sys->vub[xkndx] = uk ;
  dy_sys->obj[xkndx] = orig_sys->obj[oxkndx] ;
/*
  For nonbasic variables, set the proper status based on the bounds and put
  the proper value in dy_x. Because the bounds can change arbitrarily and the
  client may not be maintaining the status vector, it's easiest to start from
  scratch, using the value from dy_x to decide the best new status.

  For basic variables, just decide between strictly basic (B), basic fixed
  (BFX), and basic free (BFR).  This will be correct, in the absence of bound
  changes, and the values held in dy_x and dy_xbasic are unchanged. If bounds
  have changed, we'll recalculate the primal variables and then decide on the
  final status of basic variables (which could be BLLB or BUUB).
*/
  if (flgon(dy_status[xkndx],vstatNONBASIC|vstatNBFR))
  { if (lk > -dy_tols->inf && uk < dy_tols->inf)
    { if (lk == uk)
      { xkstatus = vstatNBFX ;
	xk = lk ; }
      else
      if ((dy_x[xkndx] - lk) < (uk-dy_x[xkndx]))
      { xkstatus = vstatNBLB ;
	xk = lk ; }
      else
      { xkstatus = vstatNBUB ;
	xk = uk ; } }
    else
    if (lk > -dy_tols->inf)
    { xkstatus = vstatNBLB ;
      xk = lk ; }
    else
    if (uk < dy_tols->inf)
    { xkstatus = vstatNBUB ;
      xk = uk ; }
    else
    { xkstatus = vstatNBFR ;
      xk = 0 ; }
    dy_x[xkndx] = xk ; }
  else
  { if (lk == uk)
      xkstatus = vstatBFX ;
    else
    if (lk <= -dy_tols->inf && uk >= dy_tols->inf)
      xkstatus = vstatBFR ;
    else
      xkstatus = vstatB ; }
  dy_status[xkndx] = xkstatus ;
/*
  We're done. Print some information and return.
*/
# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 4)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t  %s (%d) %s active",
		consys_nme(dy_sys,'v',xkndx,FALSE,NULL),xkndx,
		dy_prtvstat(dy_status[xkndx])) ;
    if (flgon(xkstatus,vstatNONBASIC|vstatNBFR))
      dyio_outfmt(dy_logchn,dy_gtxecho," with value %g.",dy_x[xkndx]) ;
    else
      dyio_outchr(dy_logchn,dy_gtxecho,'.') ; }
# endif

  return ; }
コード例 #7
0
ファイル: dy_solutions.c プロジェクト: sednanref/tesis
void dy_logStatus (lpprob_struct *orig_lp, flags **p_logstat)

/*
  This routine returns the status of the primal logical variables, in row
  order for the original system. The routine reports out the full set of dylp
  status codes.

  It's actually a fair bit of work to get the status right for inactive
  constraints. Because we're reporting the full set of dylp status codes, and
  the client might be calling in a situation where the outcome was infeasible
  or unbounded, we need to calculate the value and assign the appropriate
  status code. 

  Parameters:
    orig_lp:	the original lp problem
    p_logstat:	(i) vector to hold the status of the primal logical variables;
		    if NULL, a vector of appropriate size will be allocated
		(o) status of the primal logical variables, in the
		    original system frame of reference

  Returns: undefined
*/

{ int i,m,i_orig,m_orig ;
  flags stati ;
  double rhsi,rhslowi,lhsi,xi,lbi,ubi ;

  consys_struct *orig_sys ;
  flags *logstat ;
  double *x ;

  char *rtnnme = "dy_logStatus" ;

# ifndef DYLP_NDEBUG
  int v,n_orig ;
# endif

# ifdef DYLP_PARANOIA
  if (dy_std_paranoia(orig_lp,rtnnme) == FALSE)
  { return ; }
  if (p_logstat == NULL)
  { errmsg(2,rtnnme,"logstat") ;
    return ; }
# endif

  orig_sys = orig_lp->consys ;
  m_orig = orig_sys->concnt ;
  m = dy_sys->concnt ;
/*
  If we're not playing with a full deck, we'll need the values of the
  architecturals to determine the appropriate status for the logical.
*/
  x = NULL ;
  if (m < m_orig)
  { dy_colPrimals(orig_lp,&x) ; }
/*
  Do we need a vector?
*/
  if (*p_logstat != NULL)
  { logstat = *p_logstat ;
    memset(logstat,0,(m_orig+1)*sizeof(flags)) ; }
  else
  { logstat = (flags *) CALLOC((m_orig+1),sizeof(flags)) ; }
/*
  Walk the rows of the original system. For active constraints, copy the
  status of the logical from dy_status. For inactive constraints, we need to
  actually calculate the value of the logical and assign the appropriate
  status. This is more work than you'd think, because we need to determine the
  appropriate bounds for the logical based on the constraint type, and we need
  to allow for the possibility that the problem was infeasible or unbounded and
  the logical is not within bounds. We also need to allow for the possibility
  that dylp deactivated a tight constraint with y<i> = 0. The convention for
  logicals in the original system is that all have a coefficient of 1.0. Thus
  we have bounds of (0,infty) for a slack (contypLE), (0,0) for an artificial
  (contypEQ), (-infty,0) for a surplus (contypGE), and (0,rhs-rhslow) for a
  bounded slack (contypRNG).
*/
  for (i_orig = 1 ; i_orig <= m_orig ; i_orig++)
  { if (ACTIVE_CON(i_orig))
    { i = dy_origcons[i_orig] ;
      stati = dy_status[i] ; }
    else
    { lhsi = consys_dotrow(orig_sys,i_orig,x) ;
      rhsi = orig_sys->rhs[i_orig] ;
      xi = rhsi-lhsi ;
      setcleanzero(xi,dy_tols->zero) ;
      lbi = -dy_tols->inf ;
      ubi = dy_tols->inf ;
      switch (orig_sys->ctyp[i_orig])
      { case contypLE:
	{ lbi = 0.0 ;
	  break ; }
	case contypEQ:
	{ lbi = 0.0 ;
	  ubi = 0.0 ;
	  break ; }
        case contypGE:
	{ ubi = 0.0 ;
	  break ; }
	case contypRNG:
	{ rhslowi = orig_sys->rhslow[i_orig] ;
	  lbi = 0 ;
	  ubi = rhsi-rhslowi ;
	  break ; }
	case contypNB:
	{ continue ; }
	default:
	{ errmsg(1,rtnnme,__LINE__) ;
	  break ; } }
      if (belowbnd(xi,lbi))
      { stati = vstatBLLB ; }
      else
      if (atbnd(xi,lbi))
      { stati = vstatBLB ; }
      else
      if (atbnd(xi,ubi))
      { stati = vstatBUB ; }
      else
      if (abovebnd(xi,ubi))
      { stati = vstatBUUB ; }
      else
      { stati = vstatB ; } }
    logstat[i_orig] = stati ; }

  if (x != NULL) FREE(x) ;

# ifndef DYLP_NDEBUG
  if (dy_opts->print.soln >= 3)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\trowstat =") ;
    n_orig = orig_sys->varcnt ;
    v = 0 ;
    for (i_orig = 1 ; i_orig <= m_orig ; i_orig++)
    { if ((++v)%3 == 0)
      { v = 0 ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t   ") ; }
      dyio_outfmt(dy_logchn,dy_gtxecho," (%s %d %s)",
		  consys_nme(orig_sys,'v',i_orig+n_orig,FALSE,NULL),i_orig,
		  dy_prtvstat(logstat[i_orig])) ; } }
# endif

/*
  That's it. Return the vector.
*/
  *p_logstat = logstat ;

  return ; }
コード例 #8
0
ファイル: dy_solutions.c プロジェクト: sednanref/tesis
void dy_logPrimals (lpprob_struct *orig_lp, double **p_logx)

/*
  This routine returns the values of the primal logical variables, unscaled,
  in the frame of reference of the original system (i.e., the value of the
  logical for constraint i is in position i of the vector). Unscaling is
  straightforward:

  sc_x<B> = sc_inv(B)sc_b
	  = inv(S<B>)inv(B)inv(R)Rb
	  = inv(S<B>)(inv(B)b)

  so all that's needed to recover x<B> = inv(B)b is to multiply by S<B>. We
  just have to remember that for a logical, S<i> = 1/R<i>. It's more work to
  get the value of the logical for an inactive constraint --- we have to
  actually calculate b - dot(a<i>,x).

  Parameters:
    orig_lp:	the original lp problem
    p_logx:	(i) vector to hold the primal logical variables;
		    if NULL, a vector of appropriate size will be allocated
		(o) values of the primal logical variables, unscaled,
		    in the original system frame of reference

  Returns: undefined
*/

{ int j,m,i_orig,m_orig ;
  double xj,lhs ;

  consys_struct *orig_sys ;
  double *logx,*x ;

  bool scaled ;
  const double *rscale,*cscale ;

# ifndef DYLP_NDEBUG
  int v,n_orig ;
# endif
# ifdef DYLP_PARANOIA
  char *rtnnme = "dy_logPrimals" ;

  if (dy_std_paranoia(orig_lp,rtnnme) == FALSE)
  { return ; }
  if (p_logx == NULL)
  { errmsg(2,rtnnme,"logx") ;
    return ; }
# endif

/*
  Is unscaling required? Acquire the scaling vectors. If we have inactive
  constraints, we'll need the values of the architecturals in order to
  calculate the value of the associated logical.
*/
  scaled = dy_isscaled() ;
  if (scaled == TRUE)
  { dy_scaling_vectors(&rscale,&cscale) ; }

  orig_sys = orig_lp->consys ;
  m_orig = orig_sys->concnt ;
  m = dy_sys->concnt ;

  x = NULL ;
  if (m < m_orig)
  { dy_colPrimals(orig_lp,&x) ; }
/*
  Do we need a vector?
*/
  if (*p_logx != NULL)
  { logx = *p_logx ;
    memset(logx,0,(m_orig+1)*sizeof(double)) ; }
  else
  { logx = (double *) CALLOC((m_orig+1),sizeof(double)) ; }
/*
  Walk the rows of the original system. For each constraint that's active, we
  can obtain the value of the associated logical from dy_x. For each
  constraint that's inactive, we have to actually calculate the row activity
  dot(x,a<i>) and do the arithmetic.
*/
  for (i_orig = 1 ; i_orig <= m_orig ; i_orig++)
  { if (ACTIVE_CON(i_orig))
    { j = dy_origcons[i_orig] ;
      if (scaled == TRUE)
      { xj = (1/rscale[i_orig])*dy_x[j] ; }
      else
      { xj = dy_x[j] ; } }
    else
    { lhs = consys_dotrow(orig_sys,i_orig,x) ;
      xj = orig_sys->rhs[i_orig]-lhs ; }

    setcleanzero(xj,dy_tols->zero) ;
    logx[i_orig] = xj ; }

  if (x != NULL) FREE(x) ;

# ifndef DYLP_NDEBUG
  if (dy_opts->print.soln >= 3)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\tlogx =") ;
    n_orig = orig_sys->varcnt ;
    v = 0 ;
    for (i_orig = 1 ; i_orig <= m_orig ; i_orig++)
    { if (logx[i_orig] != 0)
      { if ((++v)%3 == 0)
	{ v = 0 ;
	  dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t   ") ; }
	dyio_outfmt(dy_logchn,dy_gtxecho," (%d %g %s)",
		    i_orig,logx[i_orig],
		    consys_nme(orig_sys,'v',n_orig+i_orig,FALSE,NULL)) ; } } }
# endif

/*
  That's it. Return the vector.
*/
  *p_logx = logx ;

  return ; }
コード例 #9
0
ファイル: dy_solutions.c プロジェクト: sednanref/tesis
void dy_colPrimals (lpprob_struct *orig_lp, double **p_x)

/*
  This routine returns the values of the primal architectural variables
  (basic and nonbasic), unscaled, in the frame of reference of the original
  system. Unscaling is straightforward. For basic variables, we have

  sc_x<B> = sc_inv(B)sc_b
	  = inv(S<B>)inv(B)inv(R)Rb
	  = inv(S<B>)(inv(B)b)

  so all that's needed to recover x<B> = inv(B)b is to multiply by S<B>.
  Upper and lower bounds on variables have the same scaling (inv(S)).

  Parameters:
    orig_lp:	the original lp problem
    p_x:	(i) vector to hold the primal architectural variables;
		    if NULL, a vector of appropriate size will be allocated
		(o) values of the primal architectural variables, unscaled,
		    in the original system frame of reference

  Returns: undefined
*/

{ int j,j_orig,n_orig ;
  double xj ;
  flags statj ;

  consys_struct *orig_sys ;
  double *x ;

  bool scaled ;
  const double *rscale,*cscale ;

  char *rtnnme = "dy_colPrimals" ;

# ifndef DYLP_NDEBUG
  int v ;
# endif

# ifdef DYLP_PARANOIA
  if (dy_std_paranoia(orig_lp,rtnnme) == FALSE)
  { return ; }
  if (p_x == NULL)
  { errmsg(2,rtnnme,"x") ;
    return ; }
# endif

/*
  Is unscaling required? Acquire the scaling vectors.
  accordingly.
*/
  scaled = dy_isscaled() ;
  if (scaled == TRUE)
  { dy_scaling_vectors(&rscale,&cscale) ; }

  orig_sys = orig_lp->consys ;
  n_orig = orig_sys->varcnt ;
/*
  Do we need a vector?
*/
  if (*p_x != NULL)
  { x = *p_x ;
    memset(x,0,(n_orig+1)*sizeof(double)) ; }
  else
  { x = (double *) CALLOC((n_orig+1),sizeof(double)) ; }
/*
  Walk the columns of the original system. For each variable that's active
  (basic or nonbasic), we can obtain the value from dy_x and unscale. For
  each variable that's inactive, we have to do a bit of work to decode the
  status and look up the appropriate bound value.
*/
  for (j_orig = 1 ; j_orig <= n_orig ; j_orig++)
  { if (ACTIVE_VAR(j_orig))
    { j = dy_origvars[j_orig] ;
      if (scaled == TRUE)
      { xj = cscale[j_orig]*dy_x[j] ; }
      else
      { xj = dy_x[j] ; } }
    else
    { statj = (flags)(-dy_origvars[j_orig]) ;
      switch (statj)
      { case vstatNBFX:
	case vstatNBLB:
	{ xj = orig_sys->vlb[j_orig] ;
	  break ; }
	case vstatNBUB:
	{ xj = orig_sys->vub[j_orig] ;
	  break ; }
	case vstatNBFR:
	{ xj = 0 ;
	  break ; }
	default:
	{ warn(359,rtnnme,orig_sys->nme,
	       consys_nme(orig_sys,'v',j_orig,FALSE,NULL),j_orig,
		 dy_prtvstat(statj)) ;
	  xj = 0.0 ;
	  break ; } } }

    setcleanzero(xj,dy_tols->zero) ;
    x[j_orig] = xj ; }

# ifndef DYLP_NDEBUG
  if (dy_opts->print.soln >= 3)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\tx =") ;
    v = 0 ;
    for (j_orig = 1 ; j_orig <= n_orig ; j_orig++)
    { if (x[j_orig] != 0)
      { if ((++v)%3 == 0)
	{ v = 0 ;
	  dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t   ") ; }
	dyio_outfmt(dy_logchn,dy_gtxecho," (%d %g %s)",
		    j_orig,x[j_orig],
		    consys_nme(orig_sys,'v',j_orig,FALSE,NULL)) ; } } }
# endif

/*
  That's it. Return the vector.
*/
  *p_x = x ;

  return ; }
コード例 #10
0
ファイル: dy_warmstart.c プロジェクト: sednanref/tesis
static void correct_for_patch (void)

/*
  This routine scans dy_status looking for architectural variables that are
  recorded as basic but have been booted out of the basis by a patch
  operation. It's a very special-purpose routine, separated out so it doesn't
  clutter up the code in dy_warmstart.
  Parameters: none

  Returns: undefined
*/

{ int j,cnt ;
  flags statj ;
  double *vlb,*vub ;

  vlb = dy_sys->vlb ;
  vub = dy_sys->vub ;
/*
  Open a loop to scan the status array, checking that variables recorded as
  basic are really basic. dy_patch clears the var2basis entry when it makes
  the patch, so we're looking for basic status with a 0 in var2basis.

  When we find a variable that needs to be corrected, decide an appropriate
  nonbasic status based on the sign of the objective coefficient and the
  presence/absence of finite bounds.
*/

# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 3)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n\tcorrecting status due to basis patch ...") ; }
# endif
  
  cnt = 0 ;
  for (j = dy_sys->concnt+1 ; j <= dy_sys->varcnt ; j++)
  { statj = dy_status[j] ;
    if (flgon(statj,vstatBASIC) && dy_var2basis[j] == 0)
    { if (vlb[j] > -dy_tols->inf && vub[j] < dy_tols->inf)
      { if (vub[j] == vlb[j])
	{ dy_status[j] = vstatNBFX ;
	  dy_x[j] = vub[j] ; }
	else
	if (dy_sys->obj[j] >= 0)
	{ dy_status[j] = vstatNBLB ;
	  dy_x[j] = vlb[j] ; }
	else
	{ dy_status[j] = vstatNBUB ;
	  dy_x[j] = vub[j] ; } }
      else
      if (vlb[j] > -dy_tols->inf)
      { dy_status[j] = vstatNBLB ;
	dy_x[j] = vlb[j] ; }
      else
      if (vub[j] < dy_tols->inf)
      { dy_status[j] = vstatNBUB ;
	dy_x[j] = vub[j] ; }
      else
      { dy_status[j] = vstatNBFR ;
	dy_x[j] = 0 ; }
#     ifndef DYLP_NDEBUG
      if (dy_opts->print.crash >= 4)
      { dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n\t  changing status for %s (%d) to %s,",
		    consys_nme(dy_sys,'v',j,FALSE,NULL),j,
		    dy_prtvstat(dy_status[j])) ;
	dyio_outfmt(dy_logchn,dy_gtxecho," value %g.",dy_x[j]) ; }
#     endif
      cnt++ ; } }

# ifndef DYLP_NDEBUG
/*
  Given that this routine has been called, there should be corrections to be
  made, but it's possible that the patch involved only logicals. If so,
  dy_warmstart has already dealt with the problem and we simply can't tell.
  (The necessary data structure is not exported from dy_basis.c) The least we
  can do is print a message.
*/
  if (cnt == 0 && dy_opts->print.crash >= 4)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t  no architecturals corrected.") ; }
# endif

  return ; }
コード例 #11
0
ファイル: osi_dylp.c プロジェクト: sednanref/tesis
static void print_help (ioid chn, bool echo, const char *name)
/*
  Print help message.
*/
{ dyio_outfmt(chn,echo,"\nusage: %s [<options>] [<problem-file>]",name) ;

  dyio_outfmt(chn,echo,"\n\nThe options presently in place are:\n") ;

  dyio_outfmt(chn,echo,"\n  %s\t\t\t%s","-s",
	      "Run silent: turns off echo of all generated text to") ;
  dyio_outfmt(chn,echo,"\n\t\t\t%s",
	      "stdout. The default output-file path is changed") ;
  dyio_outfmt(chn,echo,"\n\t\t\t%s",
	      "from stdout to NULL. Silent overpowers terse, in") ;
  dyio_outfmt(chn,echo,"\n\t\t\t%s","the event both are specified.") ;

  dyio_outfmt(chn,echo,"\n  %s\t\t\t%s","-t",
	      "Terse output on stdout. Behaviour is as for silent,") ;
  dyio_outfmt(chn,echo,"\n\t\t\t%s",
	      "but allows an opening title and closing message") ;
  dyio_outfmt(chn,echo,"\n\t\t\t%s","giving the result of the LP.") ;

  dyio_outfmt(chn,echo,"\n  %s\t\t%s","-p <num>",
  	      "Set overall print level to <num>, [0..5].") ;

  dyio_outfmt(chn,echo,"\n  %s\t%s","-e <errmsg-file>",
	      "Source text for error messages (defaults to") ;
  dyio_outfmt(chn,echo,"\n\t\t\t%s","dy_errmsgs.txt).") ;

  dyio_outfmt(chn,echo,"\n  %s\t%s","-E <errlog-file>",
	       "A logging file for error messages (default is to") ;
  dyio_outfmt(chn,echo,
	      "\n\t\t\t%s","direct error messages to the log file).") ;

  dyio_outfmt(chn,echo,"\n  %s\t%s","-o <option-file>",
# if defined(_MSC_VER) || defined(__MSVCRT__)
	      "Disabled on Windows.") ;
# else
	      "Control ('.spc') options file (default is no file).") ;
# endif

  dyio_outfmt(chn,echo,"\n  %s\t%s","-m <problem-file>",
	      "The problem ('.mps') specification (no default).") ;

  dyio_outfmt(chn,echo,"\n  %s\t\t%s","-L <log-file>",
	      "A log of execution (default is no execution") ;
  dyio_outfmt(chn,echo,"\n\t\t\t%s","logging).") ;

  dyio_outfmt(chn,echo,"\n  %s\t%s","-O <output-file>",
	      "The output file. Defaults to stdout unless the -s or -t") ;
  dyio_outfmt(chn,echo,"\n\t\t\t%s",
	      "options are present, in which case the default is no") ;
  dyio_outfmt(chn,echo,"\n\t\t\t%s","output.") ;

  dyio_outfmt(chn,echo,"\n  %s\t\t\t%s","-h",
	      "Print this help message and exit.") ;
  dyio_outfmt(chn,echo,"\n  %s\t\t\t%s","-v",
	      "Print version and exit.") ;

  dyio_outfmt(chn,echo,"\n\n%s %s",
	      "The -m option is just an alternate way to specify the",
	      "<problem-file>.") ;

  dyio_outfmt(chn,echo,"\n\n%s\n%s\n%s\n",
  "The error log file is a duplicate of the error messages printed on",
  "stderr; the execution log file is a duplicate of output on stdout unless",
  "-s is specified to suppress output to stdout.") ;

  return ; }
コード例 #12
0
ファイル: dy_basis.c プロジェクト: coin-or/DyLP
static dyret_enum adjust_therest (int patchcnt, patch_struct *patches)

/*
  We're here because we've successfully patched a singular basis. The patches
  array contains entries of the form <basis pos'n, x<j>, x<i>>, where x<j>
  has just been kicked out of the basis and replaced by x<i>.  The basis and
  var2basis vectors are already corrected (we needed them to complete the
  factorization).  Now we need to adjust other dylp data structures to
  reflect the unexpected change.  The amount of additional work to be done
  depends on the phase of the simplex algorithm.

    dyINIT: We're done. We've just factored the initial basis and none of the
	    other data structures have been initialised. We didn't really
	    need this call, but the code is cleaner this way.

  If we're farther along, we might be in the middle of simplex (dyPRIMAL1,
  dyPRIMAL2, or dyDUAL), or we might be manipulating the constraint system.

  If we're running simplex, the first actions are cleanup: clear the pivot
  reject list and back out any antidegeneracy activity.
    
  Next, set the status of the newly nonbasic variables, consistent with their
  previous status. The general rule is to perturb the solution as little as
  possible. If we're in a primal or dual simplex phase, try to make decisions
  that are compatible with primal or dual feasibility. Two specific points:
    * Superbasic (SB) variables are only created in dyPRIMAL2.
    * Nonbasic free (NBFR) variables imply loss of dual feasibility.

  Once we have nonbasic status set, we can calculate new primals, duals, and
  reduced costs and fine-tune the status of the newly basic variables. If
  we've arrived here from one of the constraint system manipulation phases,
  there will almost certainly be duplication of effort once we return. But
  hey, how often does a basis patch happen, anyway?
  
  If we're in a simplex phase, there's still some work to do to make the
  patch as transparent as possible.

  For dual simplex, we'll check the status of the nonbasic variables and
  try to maintain dual feasibility. This may not be possible. If we do
  maintain dual feasibility, reset the DSE norms.

  For primal simplex, we need to reset the PSE norms.

  Parameters:
    patchcnt:	the number of basis changes
    patches:	array of basis changes

  Returns: dyrOK if the repair proceeds without error, dyrLOSTDFEAS if
	   feasibility is lost in dual phase II, and dyrFATAL if anything
	   else goes wrong.
*/

{ int i,j,pndx ;
  pkvec_struct *aj ;
  flags statj ;
  dyret_enum retval ;
  dyphase_enum phase ;
  double valj,cbarj,*vub,*vlb,*obj ;

  const char *rtnnme = "adjust_therest" ;

# ifndef DYLP_NDEBUG
  flags stati ;
  double vali ;
# endif

# ifdef DYLP_PARANOIA
  if (dy_sys == NULL)
  { errmsg(2,rtnnme,"dy_sys") ;
    return (dyrFATAL) ; }
  if (dy_basis == NULL)
  { errmsg(2,rtnnme,"basis") ;
    return (dyrFATAL) ; }
  if (dy_var2basis == NULL)
  { errmsg(2,rtnnme,"var2basis") ;
    return (dyrFATAL) ; }
  if (patches == NULL)
  { errmsg(2,rtnnme,"patch") ;
    return (dyrFATAL) ; }
# endif

  phase = dy_lp->phase ;

# ifdef DYLP_PARANOIA
  if (!(phase == dyINIT || phase == dyADDVAR || phase == dyADDCON ||
	phase == dyPRIMAL1 || phase == dyPRIMAL2 || phase == dyDUAL ||
	phase == dyFORCEPRIMAL || phase == dyFORCEDUAL))
  { errmsg(1,rtnnme,__LINE__) ;
    return (dyrFATAL) ; }
  if (!(phase == dyINIT))
  { if (dy_status == NULL)
    { errmsg(2,rtnnme,"status") ;
      return (dyrFATAL) ; }
    if (dy_x == NULL)
    { errmsg(2,rtnnme,"x") ;
      return (dyrFATAL) ; }
    if (dy_xbasic == NULL)
    { errmsg(2,rtnnme,"x<B>") ;
      return (dyrFATAL) ; } }
#endif

  if (phase == dyINIT) return (dyrOK) ;

  vlb = dy_sys->vlb ;
  vub = dy_sys->vub ;
  obj = dy_sys->obj ;
  aj = NULL ;
  retval = dyrOK ;

/*
  If we're in one of the simplex phases, back out any antidegeneracy activity
  and clear the pivot rejection list.  It's easiest to clear the pivot reject
  list ahead of the status modifications so that we don't have to worry about
  the NOPIVOT qualifier when checking status values.
*/
  if (phase == dyPRIMAL1 || phase == dyPRIMAL2 || phase == dyDUAL)
  { if (dy_clrpivrej(NULL) != TRUE) return (dyrFATAL) ;
    if (dy_lp->degen > 0)
    { if (phase == dyDUAL)
      { (void) dy_dualdegenout(0) ; }
      else
      { (void) dy_degenout(0) ; } } }
/*
  Now correct the status for newly nonbasic variables. We need to correct
  dy_x if the status change forces a change in value.  If we end up with a
  NBFR variable, we've lost dual feasibility.

  While we're walking the patches, set the status for x<i> (the newly basic
  variable) to vstatB. No need to be more precise at this point.
*/

  for (pndx = 0 ; pndx < patchcnt ; pndx++)
  { i = patches[pndx].in ;
#   ifndef DYLP_NDEBUG
    stati = dy_status[i] ;
    vali = dy_x[i] ;
#   endif
    dy_status[i] = vstatB ;
    j = patches[pndx].out ;
    statj = dy_status[j] ;
    valj = dy_x[j] ;
    switch (statj)
    { case vstatBLLB:
      { dy_status[j] = vstatNBLB ;
	dy_x[j] = vlb[j] ;
	break ; }
      case vstatBLB:
      { dy_status[j] = vstatNBLB ;
	break ; }
      case vstatB:
      { if (phase == dyPRIMAL2)
	  dy_status[j] = vstatSB ;
	else
	if (valj-vlb[j] < vub[j]-valj)
	{ dy_status[j] = vstatNBLB ;
	  dy_x[j] = vlb[j] ; }
	else
	{ dy_status[j] = vstatNBUB ;
	  dy_x[j] = vub[j] ; }
	break ; }
      case vstatBUB:
      { dy_status[j] = vstatNBUB ;
	break ; }
      case vstatBUUB:
      { dy_status[j] = vstatNBUB ;
	dy_x[j] = vub[j] ;
	break ; }
      case vstatBFX:
      { dy_status[j] = vstatNBFX ;
	break ; }
      case vstatBFR:
      { dy_status[j] = vstatNBFR ;
	if (phase == dyDUAL)
	{ 
#	  ifndef DYLP_NDEBUG
	  if (dy_opts->print.dual >= 1)
	  { dywarn(346,rtnnme,
		 dy_sys->nme,dy_prtlpphase(phase,TRUE),dy_lp->tot.iters+1,
		 dy_prtvstat(statj),consys_nme(dy_sys,'v',j,FALSE,NULL),j) ; }
#	  endif
	  retval = dyrLOSTDFEAS ; }
	break ; }
      default:
      { errmsg(380,rtnnme,dy_sys->nme,consys_nme(dy_sys,'v',j,FALSE,NULL),j,
	       dy_prtvstat(statj),"basic") ;
	return (dyrFATAL) ; } }
#   ifndef DYLP_NDEBUG
    if (dy_opts->print.basis >= 3)
    { dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n\t%s (%d) had status %s, value %g, ",
		  consys_nme(dy_sys,'v',i,FALSE,NULL),i,
		  dy_prtvstat(stati),vali) ;
      dyio_outfmt(dy_logchn,dy_gtxecho,"now status %s.",
		  dy_prtvstat(dy_status[i])) ;
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n\t%s (%d) had status %s, value %g, ",
		  consys_nme(dy_sys,'v',j,FALSE,NULL),j,
		  dy_prtvstat(statj),valj) ;
      dyio_outfmt(dy_logchn,dy_gtxecho,"now status %s, value %g.",
		  dy_prtvstat(dy_status[j]),dy_x[j]) ; }
#   endif
  }

# ifdef DYLP_PARANOIA
/*
  If paranoid checks are in place, we need agreement between dy_status, dy_x,
  and dy_xbasic, lest dy_calccbar fail. Call dy_calcprimals and
  dy_setbasicstatus to get the basic status right. This is restricted to
  paranoid mode because the proper place to do this is after making
  corrections to nonbasic status for dual feasibility.
*/
  if (dy_calcprimals() == FALSE) return (dyrFATAL) ;
  dy_setbasicstatus() ;
# endif

/*
  Calculate the duals and reduced costs.
*/
  dy_calcduals() ;
  if (dy_calccbar() == FALSE)
  { errmsg(384,rtnnme,
	   dy_sys->nme,dy_prtlpphase(phase,TRUE),dy_lp->tot.iters) ;
    return (dyrFATAL) ; }

/*
  If we're in phase dyDUAL, it's worth a scan to check dual feasibility and
  make adjustments to maintain it, if possible. (retval = dyrLOSTDFEAS says
  we introduced a NBFR variable, in which case we have no hope).

  Open a loop to scan the nonbasic variables. NBFX variables are always dual
  feasible, NBFR variables are never dual feasible.  We're minimising, so
  dual feasibility (primal optimality) is cbarj < 0 && x<j> at upper bound,
  or cbarj > 0 && x<j> at lower bound.  It's important that the zero
  tolerance for cbar<j> here be the same as the one used in dy_dualin when it
  checks for loss of dual feasibility.
*/
  if (phase == dyDUAL && retval != dyrLOSTDFEAS)
  { for (j = 1 ; j <= dy_sys->varcnt ; j++)
    { statj = dy_status[j] ;
      if (flgon(statj,vstatBASIC|vstatNBFX)) continue ;
      if (flgon(statj,vstatNBFR))
      { retval = dyrLOSTDFEAS ;
#	ifndef DYLP_NDEBUG
	cbarj = dy_cbar[j] ;
	if (dy_opts->print.dual >= 1)
	{ dywarn(347,rtnnme,
	       dy_sys->nme,dy_prtlpphase(phase,TRUE),dy_lp->tot.iters+1,
	       consys_nme(dy_sys,'v',j,FALSE,NULL),j,
	       dy_prtvstat(statj),j,cbarj,dy_tols->dfeas) ; }
#	endif
	break ; }
      cbarj = dy_cbar[j] ;
      if (cbarj < -dy_tols->dfeas && flgoff(statj,vstatNBUB))
      { if (vub[j] >= dy_tols->inf)
	{
#	  ifndef DYLP_NDEBUG
	  if (dy_opts->print.dual >= 1)
	  { dywarn(347,rtnnme,
		 dy_sys->nme,dy_prtlpphase(phase,TRUE),dy_lp->tot.iters+1,
		 consys_nme(dy_sys,'v',j,FALSE,NULL),j,
		 dy_prtvstat(statj),j,cbarj,dy_tols->dfeas) ; }
#	  endif
	  retval = dyrLOSTDFEAS ;
	  break ; }
	else
	{ dy_status[j] = vstatNBUB ;
	  dy_x[j] = vub[j] ; } }
      else
      if (cbarj > dy_tols->dfeas && flgoff(statj,vstatNBLB))
      { if (vlb[j] >= dy_tols->inf)
	{
#	  ifndef DYLP_NDEBUG
	  if (dy_opts->print.dual >= 1)
	  { dywarn(347,rtnnme,
		 dy_sys->nme,dy_prtlpphase(phase,TRUE),dy_lp->tot.iters+1,
		 consys_nme(dy_sys,'v',j,FALSE,NULL),j,
		 dy_prtvstat(statj),j,cbarj,dy_tols->dfeas) ; }
#	  endif
	  retval = dyrLOSTDFEAS ;
	  break ; }
	else
	{ dy_status[j] = vstatNBLB ;
	  dy_x[j] = vlb[j] ; } }
#     ifndef DYLP_NDEBUG
      if (dy_opts->print.basis >= 3 && dy_status[j] != statj)
      { dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n\tchanged status of %s (%d) from %s to",
		    consys_nme(dy_sys,'v',j,FALSE,NULL),j,dy_prtvstat(statj)) ;
	dyio_outfmt(dy_logchn,dy_gtxecho,
		    " %s to maintain dual feasibility; cbar = %g.",
		    dy_prtvstat(dy_status[j]),cbarj) ; }
#     endif
    } }

/*
  The dual variables and reduced costs have been recalculated, and we have
  the final status for all nonbasic variables.  Recalculate the primal
  variables and set the status of the basic variables.
*/
  if (dy_calcprimals() == FALSE) return (dyrFATAL) ;
  dy_setbasicstatus() ;
/*
  If we're running primal simplex, reset the PSE reference frame. If we're
  running dual simplex and haven't lost dual feasibility, recalculate the
  basis inverse row norms.
*/
  if (phase == dyPRIMAL1 || phase == dyPRIMAL2)
  { dy_pseinit() ; }
  else
  if (phase == dyDUAL && retval != dyrLOSTDFEAS)
  { dy_dseinit() ; }

  return (retval) ; }
コード例 #13
0
ファイル: dy_basis.c プロジェクト: coin-or/DyLP
static void adjust_basis (int *p_patchcnt, patch_struct **p_patches)

/*
  This routine corrects the dylp basis arrays when glpinv/glpluf declares
  the current basis to be singular. glpluf doesn't actually salvage the
  basis --- it just reports the linearly dependent (hence unpivoted) columns
  and corresponding unpivoted rows. Once we've adjusted the basis accordingly,
  we can make another attempt to factor.

  The convention is as follows: luf_basis.rank gives the rank of the basis.
  qq_col[rank+1 .. m] contain the indices of the basic columns that must
  be removed from the basis. pp_row[rank+1 .. m] contain the indices of the
  basic rows that remain unpivoted; we'll put the logicals for these rows into
  the basis.

  Both of the above are expressed in terms of basis positions. For the rows,
  basis position i is equivalent to constraint i; for the columns, we need
  to look up the variable j in basis position i.

  Recognise that in general this is the easiest part of salvaging the
  situation. We record the changes for adjust_therest, which will do the
  remainder of the work after the basis is successfully factored.

  Parameters:
    p_patchcnt:	(o) the number of basis corrections
    p_patches:	(o) patch array recording the basis corrections

  Returns: undefined
*/

{ int *qq_col, *pp_row ;
  int rank,pqndx,i,j,k,pndx ;
  patch_struct *patches ;


#if defined(DYLP_PARANOIA) || MALLOC_DEBUG == 2
  const char *rtnnme = "adjust_basis" ;

  if (dy_sys == NULL)
  { errmsg(2,rtnnme,"dy_sys") ;
    return ; }
  if (dy_basis == NULL)
  { errmsg(2,rtnnme,"basis") ;
    return ; }
  if (dy_var2basis == NULL)
  { errmsg(2,rtnnme,"var2basis") ;
    return ; }
  if (luf_basis == NULL)
  { errmsg(2,rtnnme,"LUF basis") ;
    return ; }
  if (p_patches == NULL)
  { errmsg(2,rtnnme,"p_patches") ;
    return ; }
#endif

  qq_col = luf_basis->luf->qq_col ;
  pp_row = luf_basis->luf->pp_row ;
  rank = luf_basis->luf->rank ;

  patches =
    (patch_struct *) MALLOC((dy_sys->concnt-rank)*sizeof(patch_struct)) ;

/*
  Walk qq_col, retrieving the basis position that must be corrected. Remove
  the corresponding variable from the basis, and put in its place the slack
  for the basis row.
*/
  for (pqndx = rank+1, pndx = 0 ; pqndx <= dy_sys->concnt ; pqndx++, pndx++)
  { k = qq_col[pqndx] ;
    j = dy_basis[k] ;
    i = pp_row[pqndx] ;
    dy_basis[k] = i ;
    dy_var2basis[j] = 0 ;
    dy_var2basis[i] = k ;
    patches[pndx].pos = k ;
    patches[pndx].out = j ;
    patches[pndx].in = i ;
#   ifndef DYLP_NDEBUG
    if (dy_opts->print.basis >= 3)
    { dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n      pos'n %d (%s (%d)) replacing %s (%d) with %s (%d).",
		  k,consys_nme(dy_sys,'c',k,FALSE,NULL),k,
		  consys_nme(dy_sys,'v',j,FALSE,NULL),j,
		  consys_nme(dy_sys,'v',i,FALSE,NULL),i) ; }
#   endif
  }

  *p_patchcnt = pndx ;
  *p_patches = patches ;
  return ; }
コード例 #14
0
ファイル: dy_basis.c プロジェクト: coin-or/DyLP
void dy_initbasis (int concnt, int factor, double zero_tol)

/*
  This routine calls the glpk routine inv_create to initialize the basis
  data structures, then sets values for the zero tolerance (eps_tol), pivot
  ratio (piv_tol) and number of candidates examined (piv_lim).

  NOTE: This routine can be (and typically is) called before any of the main
	dylp data structures exist. Be careful what you reference.

  Parameters:
    concnt:	the number of constraints (rows) that the basis representation
		should be capable of handling
    factor:	the planned refactorisation frequency; passed to glpk as the
		basis inverse update capacity (i.e., the limit on the number
		of pivots between refactorisations)
    zero_tol:	zero tolerance; a value of 0.0 uses the glpk default
		(INV->LUF->eps_tol = 1.0e-15).

  Returns: void
*/

{ int sva_size ;
  const char *rtnnme = "dy_initbasis" ;

/*
  Create the basis. Allow for at least five constraints (also handles
  pathological examples with no explicit constraints).
*/
  luf_capacity = maxx(concnt,5) ;
  luf_basis = inv_create(luf_capacity,factor) ;
  if (luf_basis == NULL)
  { if (dy_lp == NULL)
    { errmsg(302,rtnnme,"empty","pre-init",0,"create") ; }
    else
    { errmsg(302,rtnnme,dy_sys->nme,dy_prtlpphase(dy_lp->phase,TRUE),
	     dy_lp->tot.iters,"create") ; }
    return ; }
/*
  WARNING: We're going to reach inside glpluf to get it to triple the amount
  of space that it allocates for the sparse vector area. We're doing this by
  triggering the reallocation mechanism built into luf_decomp (called by
  inv_decomp).
*/
  sva_size = luf_basis->luf->sv_size ;
  luf_basis->luf->new_sva = 3*sva_size ;
# ifndef DYLP_NDEBUG
  if (dy_opts != NULL && dy_opts->print.basis >= 2)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
	        "\ninitbasis: %s(%d) basis capacity %d, piv lim %d.",
	        dy_prtlpphase(dy_lp->phase,TRUE),dy_lp->tot.iters,
	        luf_basis->luf->n,luf_basis->hh_max) ; }
/*
  XX_DEBUG_XX

  There's no good way to control this output, given the timing of the call
  (before dy_opts is initialised), but it's sometimes useful when debugging.
  
  else
  { dyio_outfmt(dy_logchn,TRUE,
	        "\ninitbasis: EXTERN(0) basis capacity %d, piv lim %d.",
	        luf_basis->luf->n,luf_basis->hh_max) ; }
*/
# endif
/*
  Set the initial pivot level to {.01,4}, and allow it to drop to {.01,4}.
*/

  pivlevel = 0 ;
  minpivlevel = 0 ;

  if (zero_tol != 0.0) luf_basis->luf->eps_tol = zero_tol ;
  luf_basis->luf->piv_tol = pivtols[pivlevel].stable ;
  luf_basis->luf->piv_lim =  pivtols[pivlevel].look ;
  luf_basis->luf->max_gro = 1.0e7 ;
/*
  This is the smallest value that can appear on the diagonal of U after a
  pivot update. dylp will (in extremis) drop its pivot selection tolerance
  tols.pivot to 1e-9 (or thereabouts), so upd_tol had better be less or we
  spend a lot of time refactoring. This should probably be adjusted as
  needed, in response to adjustments in tols.pivot, but I need to sit down and
  really think about the math. In the meantime, this seems to be adequate.
*/
  luf_basis->upd_tol = 1.0e-10 ;

  return ; }
コード例 #15
0
ファイル: unitTest.c プロジェクト: sednanref/tesis
int main (int argc, char **argv)

{ bool errecho = TRUE ;

  ioid ttyin,ttyout,outchn ;
  const char *errmsgpath = DYLP_ERRMSGPATH ;
  char *errlogpath = NULL ;

/*
  These need to be globals to keep cmdint.c::process_cmds happy.

  lpopts_struct *main_lpopts ;
  lptols_struct *main_lptols ;
*/
  consys_struct *main_sys ;
  lpprob_struct *main_lp ;
  lpret_enum lpretval ;

  double z ;
  int errcnt,cnt ;

/*
  Set this to TRUE if you want to see the solutions for the test lp problems.
*/
  bool dumpsoln = TRUE ;

  char *rtnnme = argv[0] ;

  /* dy_basis.c */

  extern void dy_initbasis(int concnt, int factor_freq, double zero_tol),
	      dy_freebasis(void) ;

  /* dytest_problems.c */

  extern consys_struct *dytest_exmip1sys(lptols_struct *tols) ;
  extern consys_struct *dytest_exprimalraysys(lptols_struct *tols) ;
  extern consys_struct *dytest_exdualraysys(lptols_struct *tols) ;
  extern consys_struct *dytest_galenetbndssys(lptols_struct *tols) ;
  extern consys_struct *dytest_galenetleqsys(lptols_struct *tols) ;
  extern consys_struct *dytest_galenetmixedsys(lptols_struct *tols) ;
  extern consys_struct *dytest_galenetsys(lptols_struct *tols) ;

  extern consys_struct *dytest_afirosys(lptols_struct *tols) ;
  extern consys_struct *dytest_boeing2sys(lptols_struct *tols) ;

  /* dytest_tableau.c */

  extern int dytest_betaj(lpprob_struct *lp,
			  lptols_struct *lptols,lpopts_struct *lpopts) ;
  extern int dytest_betai(lpprob_struct *lp,
			  lptols_struct *lptols,lpopts_struct *lpopts) ;
  extern int dytest_abarj(lpprob_struct *lp,
			  lptols_struct *lptols,lpopts_struct *lpopts) ;
  extern int dytest_abari(lpprob_struct *lp,
			  lptols_struct *lptols,lpopts_struct *lpopts) ;

  /* dytest_solutions.c */

  extern int dytest_rowDuals(lpprob_struct *lp,
			     lptols_struct *lptols,lpopts_struct *lpopts) ;
  extern int dytest_allDuals(lpprob_struct *lp,
			      lptols_struct *lptols,lpopts_struct *lpopts) ;
  extern int dytest_colDuals(lpprob_struct *lp,
			     lptols_struct *lptols,lpopts_struct *lpopts) ;
  extern int dytest_colPrimals(lpprob_struct *lp,
			       lptols_struct *lptols,lpopts_struct *lpopts) ;
  extern int dytest_rowPrimals(lpprob_struct *lp,
			       lptols_struct *lptols,lpopts_struct *lpopts) ;

  /* dytest_rays.c */

  extern int dytest_primalRays(int *p_numRays,lpprob_struct *lp,
			       lptols_struct *lptols,lpopts_struct *lpopts) ;
  extern int dytest_dualRays(int *p_numRays,lpprob_struct *lp,
			     lptols_struct *lptols,lpopts_struct *lpopts) ;

  outchn = IOID_INV ;
/*
  Execute initialization routines for the i/o and error reporting packages.
*/
  errinit(errmsgpath,errlogpath,errecho) ;
  if (dyio_ioinit() != TRUE)
  { errmsg(1,rtnnme,__LINE__) ;
    exit (2) ; }
/*
  Connect ttyout to the standard output. Initialize ttyin, setting the mode to
  line-oriented. Serious internal confusion if we can't manage these. Set the
  initial command input channel to stdin.
*/
  ttyout = dyio_openfile("stdout","w") ;
  if (ttyout == IOID_INV)
  { errmsg(1,rtnnme,__LINE__) ;
    exit(3) ; }
  ttyin = dyio_openfile("stdin","r") ;
  if (ttyin == IOID_INV)
  { errmsg(1,rtnnme,__LINE__) ;
    exit(4) ; }
  (void) dyio_setmode(ttyin,'l') ;
  dy_cmdchn = ttyin ;
  dy_logchn = IOID_NOSTRM ;
  dy_cmdecho = TRUE ;
  dy_gtxecho = TRUE ;
/*
  Announce we're running.
*/
  dyio_outfmt(ttyout,dy_gtxecho,"Dylp v%s unit test start.\n",DYLP_VERSION) ;
  dyio_flushio(ttyout,dy_gtxecho) ;
  errcnt = 0 ;
/*
  Acquire default option and tolerance structures. Allocate an
  lpprob_struct to be our top-level handle.
*/
  main_lpopts = NULL ;
  main_lptols = NULL ;
  dy_defaults(&main_lpopts,&main_lptols) ;
  main_lp = (lpprob_struct *) CALLOC(1,sizeof(lpprob_struct)) ;
/*
  Initialise the basis factorisation package with a data structure capable of
  50 constraints.  The second parameter controls how many basis updates the
  basis can hold before it requires refactoring.  Adding 5 to dylp's refactor
  interval should give a safety margin.
*/
  dy_initbasis(50,main_lpopts->factor+5,0.0) ;

#if RUN_EXMIP1 > 0
/*
  Load the exmip1 example and see if we can solve it.
*/
  dyio_outfmt(ttyout,dy_gtxecho,
	      "\n\nLoading exmip1 example from static data.\n") ;
  main_sys = dytest_exmip1sys(main_lptols) ;
  if (main_sys == NULL)
  { dyio_outfmt(ttyout,dy_gtxecho,
		"Failed to load exmip1 constraint system.\n") ;
    errcnt++ ; }
/*
  Check over the option settings, now that we know how big the constraint
  system will be.
*/
  else
  { dy_checkdefaults(main_sys,main_lpopts,main_lptols) ;
/*
  Initialise the main_lp structure to pass the problem in to dylp.
    * We need to retain the data structures (NOFREE) so that we can
      consult them when dylp returns.
    * The phase needs to be dyINV at the start.
    * We need to specify the constraint system, and its size.
    * Let dylp work with a partial system and purge at the end. This stresses
      the routines we're testing; they need to synthesize parts of the values
      they return.
    * The remaining options specify an all-logical basis, allow scaling, and
      force a cold start.
*/
    setflg(main_lp->ctlopts,lpctlNOFREE) ;
    main_lp->phase = dyINV ;
    main_lp->consys = main_sys ;
    main_lp->rowsze = main_sys->rowsze ;
    main_lp->colsze = main_sys->colsze ;
    main_lpopts->forcecold = TRUE ;
    main_lpopts->fullsys = FALSE ;
    main_lpopts->finpurge.vars = TRUE ;
    main_lpopts->finpurge.cons = TRUE ;
    main_lpopts->coldbasis = ibLOGICAL ;
    main_lpopts->scaling = 0 ;
    main_lpopts->forcecold = TRUE ;
/*
    main_lpopts->print.major = 1 ;
    main_lpopts->print.scaling = 1 ;
    main_lpopts->print.setup = 6 ;
    main_lpopts->print.crash = 3 ;
    main_lpopts->print.conmgmt = 3 ;
    main_lpopts->print.varmgmt = 3 ;
    main_lpopts->print.soln = 3 ;
*/
/*
  Solve.
*/
    dyio_outfmt(ttyout,dy_gtxecho,"Solving exmip1 ... ") ;
    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
/*
  And the result is ...
*/
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    z = 3.236842105263 ;
    if (!(fabs(main_lp->obj-z) <= main_lptols->cost))
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: z = %g, expected %g, error %g, tol %g.\n",
		  main_lp->obj,z,fabs(main_lp->obj-z),main_lptols->cost) ; }
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }
/*
  Test the tableau, solution, and ray routines. The tests are predominantly
  mathematical identities, with a bit of data structure consistency thrown in
  for good measure. Completely problem-independent.
*/
    errcnt += dytest_betaj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abarj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_betai(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abari(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_allDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colPrimals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowPrimals(main_lp,main_lptols,main_lpopts) ;
/*
  Call dylp to free internal structures, then free main_sys.
*/
    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    dylp(main_lp,main_lpopts,main_lptols,NULL) ;
    consys_free(main_sys) ;
    main_sys = NULL ;
    main_lp->consys = NULL ;
    dy_freesoln(main_lp) ; }
#endif

#if RUN_AFIRO > 0
/*
  Let's try another. Load and solve afiro.
*/
  dyio_outfmt(ttyout,dy_gtxecho,
	      "\n\nLoading afiro example from static data.\n") ;
  main_sys = dytest_afirosys(main_lptols) ;
  if (main_sys == NULL)
  { dyio_outfmt(ttyout,dy_gtxecho,
		"Failed to load afiro constraint system.\n") ;
    errcnt++ ; }
  else
  { dy_checkdefaults(main_sys,main_lpopts,main_lptols) ;
    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    main_lp->phase = dyINV ;
    main_lp->consys = main_sys ;
    main_lp->rowsze = main_sys->rowsze ;
    main_lp->colsze = main_sys->colsze ;
    main_lpopts->forcecold = TRUE ;
    main_lpopts->fullsys = FALSE ;
    main_lpopts->finpurge.vars = TRUE ;
    main_lpopts->finpurge.cons = TRUE ;
    main_lpopts->coldbasis = ibLOGICAL ;
    main_lpopts->scaling = 2 ;

    dyio_outfmt(ttyout,dy_gtxecho,"Solving afiro ... ") ;
    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    z = -464.753142857143 ;
    if (!(fabs(main_lp->obj-z) <= main_lptols->cost))
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: z = %g, expected %g, error %g, tol %g.\n",
		  main_lp->obj,z,fabs(main_lp->obj-z),main_lptols->cost) ; }
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }

    errcnt += dytest_betaj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abarj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_betai(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abari(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_allDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colPrimals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowPrimals(main_lp,main_lptols,main_lpopts) ;

    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    dylp(main_lp,main_lpopts,main_lptols,NULL) ;
    consys_free(main_sys) ;
    main_sys = NULL ;
    main_lp->consys = NULL ;
    dy_freesoln(main_lp) ; }
#endif

#if RUN_BOEING2 > 0
/*
  Let's try another. Load and solve boeing2.
*/
  dyio_outfmt(ttyout,dy_gtxecho,
	      "\n\nLoading boeing2 example from static data.\n") ;
  main_sys = dytest_boeing2sys(main_lptols) ;
  if (main_sys == NULL)
  { dyio_outfmt(ttyout,dy_gtxecho,
		"Failed to load boeing2 constraint system.\n") ;
    errcnt++ ; }
  else
  { dy_checkdefaults(main_sys,main_lpopts,main_lptols) ;
    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    main_lp->phase = dyINV ;
    main_lp->consys = main_sys ;
    main_lp->rowsze = main_sys->rowsze ;
    main_lp->colsze = main_sys->colsze ;
    main_lpopts->forcecold = TRUE ;
    main_lpopts->fullsys = FALSE ;
    main_lpopts->finpurge.vars = TRUE ;
    main_lpopts->finpurge.cons = TRUE ;
    main_lpopts->coldbasis = ibLOGICAL ;
    main_lpopts->scaling = 2 ;

    main_lpopts->print.phase2 = 0 ;
/*
    main_lpopts->print.major = 1 ;
    main_lpopts->print.phase1 = 4 ;
    main_lpopts->print.dual = 4 ;
    main_lpopts->print.tableau = 4 ;
    main_lpopts->print.soln = 3 ;
    main_lpopts->print.rays = 5 ;
*/

    dyio_outfmt(ttyout,dy_gtxecho,"Solving boeing2 ... ") ;
    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    z = -315.0187280152 ;
    if (!(fabs(main_lp->obj-z) <= main_lptols->cost))
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: z = %g, expected %g, error %g, tol %g.\n",
		  main_lp->obj,z,fabs(main_lp->obj-z),main_lptols->cost) ; }
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }

    errcnt += dytest_betaj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abarj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_betai(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abari(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_allDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colPrimals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowPrimals(main_lp,main_lptols,main_lpopts) ;

    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    dylp(main_lp,main_lpopts,main_lptols,NULL) ;
    consys_free(main_sys) ;
    main_sys = NULL ;
    main_lp->consys = NULL ;
    dy_freesoln(main_lp) ; }
#endif

#if RUN_EXPRIMALRAY > 0
/*
  Let's try another. Load and solve exprimalray.  The polyhedron for
  exprimalray is carefully crafted to provide an initial bounded optimum
  point with two rays that are exposed by the proper change in objective.
  Force dylp to use the full system for this test and do not allow final
  purging, lest we miss the point and rays we're aiming for.
*/
  dyio_outfmt(ttyout,dy_gtxecho,
	      "\n\nLoading exprimalray example from static data.\n") ;
  main_sys = dytest_exprimalraysys(main_lptols) ;
  if (main_sys == NULL)
  { dyio_outfmt(ttyout,dy_gtxecho,
		"Failed to load exprimalray constraint system.\n") ;
    errcnt++ ; }
  else
  { dy_checkdefaults(main_sys,main_lpopts,main_lptols) ;
    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    main_lp->phase = dyINV ;
    main_lp->consys = main_sys ;
    main_lp->rowsze = main_sys->rowsze ;
    main_lp->colsze = main_sys->colsze ;
    main_lpopts->forcecold = TRUE ;
    main_lpopts->fullsys = TRUE ;
    main_lpopts->finpurge.vars = FALSE ;
    main_lpopts->finpurge.cons = FALSE ;
    main_lpopts->coldbasis = ibLOGICAL ;
    main_lpopts->scaling = 2 ;

    dyio_outfmt(ttyout,dy_gtxecho,"Solving exprimalray ... ") ;

    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    z = -21 ;
    if (!(fabs(main_lp->obj-z) <= main_lptols->cost))
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: z = %g, expected %g, error %g, tol %g.\n",
		  main_lp->obj,z,fabs(main_lp->obj-z),main_lptols->cost) ; }
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }
/*
  Now tweak the objective to 3x1+x2+x3, giving us two rays. Solve, then test
  that we have valid primal rays. First ask for just one, then ask for five,
  expecting two.
*/
    main_sys->obj[1] = -1.0 ;
    main_sys->obj[2] = -4.0 ;
    setflg(main_lp->ctlopts,lpctlOBJCHG) ;
    main_lpopts->forcecold = FALSE ;

    dyio_outfmt(dy_logchn,dy_gtxecho,"Resolving exprimalray ...") ;
    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }

    cnt = 1 ;
    errcnt += dytest_primalRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 1)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d primal rays returned, expected %d.\n",
		  cnt,1) ; }
    cnt = 5 ;
    errcnt += dytest_primalRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 2)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d primal rays returned, expected %d.\n",
		  cnt,2) ; }
/*
  Run the remainder of the tests, to make sure they run without error when
  dylp finishes unbounded.
*/
    errcnt += dytest_betaj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abarj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_betai(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abari(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_allDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colPrimals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowPrimals(main_lp,main_lptols,main_lpopts) ;

    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    dylp(main_lp,main_lpopts,main_lptols,NULL) ;
    consys_free(main_sys) ;
    main_sys = NULL ;
    main_lp->consys = NULL ;
    dy_freesoln(main_lp) ; }
#endif

#if RUN_EXDUALRAY > 0
/*
  Let's try another. Load and solve exdualray. Exdualray takes advantage of
  duality: The dual polyhedron is exactly the primal polyhedron of the
  previous problem.  The symmetry should be clear from the output (objective,
  dual, and primal values are negated, but otherwise identical)
*/
  dyio_outfmt(ttyout,dy_gtxecho,
	      "\n\nLoading exdualray example from static data.\n") ;
  main_sys = dytest_exdualraysys(main_lptols) ;
  if (main_sys == NULL)
  { dyio_outfmt(ttyout,dy_gtxecho,
		"Failed to load exdualray constraint system.\n") ;
    errcnt++ ; }
  else
  { dy_checkdefaults(main_sys,main_lpopts,main_lptols) ;
    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    main_lp->phase = dyINV ;
    main_lp->consys = main_sys ;
    main_lp->rowsze = main_sys->rowsze ;
    main_lp->colsze = main_sys->colsze ;
    main_lpopts->forcecold = TRUE ;
    main_lpopts->fullsys = TRUE ;
    main_lpopts->finpurge.vars = FALSE ;
    main_lpopts->finpurge.cons = FALSE ;
    main_lpopts->coldbasis = ibLOGICAL ;
    main_lpopts->scaling = 2 ;
/*
    main_lpopts->print.major = 1 ;
    main_lpopts->print.phase1 = 4 ;
    main_lpopts->print.phase2 = 4 ;
    main_lpopts->print.dual = 4 ;
    main_lpopts->print.tableau = 4 ;
    main_lpopts->print.soln = 3 ;
    main_lpopts->print.rays = 5 ;
*/

    dyio_outfmt(ttyout,dy_gtxecho,"Solving exdualray ... ") ;
    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    z = 21 ;
    if (!(fabs(main_lp->obj-z) <= main_lptols->cost))
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: z = %g, expected %g, error %g, tol %g.\n",
		  main_lp->obj,z,fabs(main_lp->obj-z),main_lptols->cost) ; }
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }
/*
  Tweak the rhs to (-1)*(-1 -4 1) to produce a pair of rays in the dual.
*/
    main_sys->rhs[2] =  4.0 ;
    setflg(main_lp->ctlopts,lpctlRHSCHG) ;
    main_lpopts->forcecold = FALSE ;
    main_lpopts->print.force = 1 ;
    dyio_outfmt(dy_logchn,dy_gtxecho,"Resolving exdualray ...") ;
    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }
/*
  Test that we have valid dual rays. First ask for just one, then ask for
  five, expecting two.
*/
    errcnt += dytest_rowDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_allDuals(main_lp,main_lptols,main_lpopts) ;
    cnt = 1 ;
    errcnt += dytest_dualRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 1)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d dual rays returned, expected %d.\n",
		  cnt,1) ; }
    cnt = 5 ;
    errcnt += dytest_dualRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 2)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d dual rays returned, expected %d.\n",
		  cnt,2) ; }
/*
  Run the remainder of the tests, to make sure they run without error when
  dylp finishes infeasible.
*/
    errcnt += dytest_betaj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abarj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_betai(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abari(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colPrimals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowPrimals(main_lp,main_lptols,main_lpopts) ;

    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    dylp(main_lp,main_lpopts,main_lptols,NULL) ;
    consys_free(main_sys) ;
    main_sys = NULL ;
    main_lp->consys = NULL ;
    dy_freesoln(main_lp) ; }
#endif

#if RUN_GALENETBNDS > 0
/*
  Now a sequence of three problems based on galenet that really exercise the
  dual ray code. Galenet is a straightforward primal infeasible / dual
  unbounded problem. The objective is identically zero, so it's a pure
  feasibility problem. The objective returned from dylp will be z = 48, the
  amount of primal infeasibility.

  The first version is galenetbnds. All equalities from galenet are converted
  to inequalities, all implicit bounds are converted to explicit bound
  constraints, and then all >= constraints are converted to <= constraints.
  This is the simplest possible case for returning dual rays.
*/
  dyio_outfmt(ttyout,dy_gtxecho,
	      "\n\nLoading galenetbnds example from static data.\n") ;
  main_sys = dytest_galenetbndssys(main_lptols) ;
  if (main_sys == NULL)
  { dyio_outfmt(ttyout,dy_gtxecho,
		"Failed to load galenetbnds constraint system.\n") ;
    errcnt++ ; }
  else
  { dy_checkdefaults(main_sys,main_lpopts,main_lptols) ;
    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    main_lp->phase = dyINV ;
    main_lp->consys = main_sys ;
    main_lp->rowsze = main_sys->rowsze ;
    main_lp->colsze = main_sys->colsze ;
    main_lpopts->forcecold = TRUE ;
    main_lpopts->fullsys = TRUE ;
    main_lpopts->finpurge.vars = FALSE ;
    main_lpopts->finpurge.cons = FALSE ;
    main_lpopts->coldbasis = ibLOGICAL ;
    main_lpopts->scaling = 2 ;
/*
    main_lpopts->print.major = 1 ;
    main_lpopts->print.phase1 = 4 ;
    main_lpopts->print.phase2 = 4 ;
    main_lpopts->print.dual = 4 ;
    main_lpopts->print.tableau = 4 ;
    main_lpopts->print.soln = 3 ;
    main_lpopts->print.rays = 5 ;
*/

    dyio_outfmt(ttyout,dy_gtxecho,"Solving galenetbnds ... ") ;
    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    z = 48.0 ;
    if (!(fabs(main_lp->obj-z) <= main_lptols->cost))
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: z = %g, expected %g, error %g, tol %g.\n",
		  main_lp->obj,z,fabs(main_lp->obj-z),main_lptols->cost) ; }
    dumpsoln = TRUE ;
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }
/*
  Test that we have valid dual rays. First ask for just one, then ask for
  five, expecting three.
*/
    cnt = 1 ;
    errcnt += dytest_dualRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 1)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d dual rays returned, expected %d.\n",
		  cnt,1) ; }
    cnt = 5 ;
    errcnt += dytest_dualRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 3)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d dual rays returned, expected %d.\n",
		  cnt,2) ; }
/*
  Run the remainder of the tests, to make sure they run without error when
  dylp finishes infeasible.
*/
    errcnt += dytest_betaj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abarj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_betai(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abari(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_allDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colPrimals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowPrimals(main_lp,main_lptols,main_lpopts) ;

    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    dylp(main_lp,main_lpopts,main_lptols,NULL) ;
    consys_free(main_sys) ;
    main_sys = NULL ;
    main_lp->consys = NULL ;
    dy_freesoln(main_lp) ; }
#endif

#if RUN_GALENETLEQ > 0
/*
  Now load and solve galenetleq --- galenetbnds, but the
  bound constraints on variables are now handled in the usual manner, as
  implicit bounds. We'll need the full ray (explicit duals y = c<B>inv(B)
  as well as duals associated with nonbasic bounded variables) in order to pass
  the mathematical tests rb < 0, rA > 0.
*/
  dyio_outfmt(ttyout,dy_gtxecho,
	      "\n\nLoading galenetleq example from static data.\n") ;
  main_sys = dytest_galenetleqsys(main_lptols) ;
  if (main_sys == NULL)
  { dyio_outfmt(ttyout,dy_gtxecho,
		"Failed to load galenetleq constraint system.\n") ;
    errcnt++ ; }
  else
  { dy_checkdefaults(main_sys,main_lpopts,main_lptols) ;
    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    main_lp->phase = dyINV ;
    main_lp->consys = main_sys ;
    main_lp->rowsze = main_sys->rowsze ;
    main_lp->colsze = main_sys->colsze ;
    main_lpopts->forcecold = TRUE ;
    main_lpopts->fullsys = TRUE ;
    main_lpopts->finpurge.vars = FALSE ;
    main_lpopts->finpurge.cons = FALSE ;
    main_lpopts->coldbasis = ibLOGICAL ;
    main_lpopts->scaling = 2 ;
/*
    main_lpopts->print.major = 1 ;
    main_lpopts->print.phase1 = 4 ;
    main_lpopts->print.phase2 = 4 ;
    main_lpopts->print.dual = 4 ;
    main_lpopts->print.tableau = 4 ;
    main_lpopts->print.soln = 3 ;
    main_lpopts->print.rays = 5 ;
*/

    dyio_outfmt(ttyout,dy_gtxecho,"Solving galenetleq ... ") ;
    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    z = 48.0 ;
    if (!(fabs(main_lp->obj-z) <= main_lptols->cost))
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: z = %g, expected %g, error %g, tol %g.\n",
		  main_lp->obj,z,fabs(main_lp->obj-z),main_lptols->cost) ; }
    dumpsoln = TRUE ;
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }
/*
  Test that we have valid dual rays. First ask for just one, then ask for
  five, expecting three.
*/
    cnt = 1 ;
    errcnt += dytest_dualRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 1)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d dual rays returned, expected %d.\n",
		  cnt,1) ; }
    cnt = 5 ;
    errcnt += dytest_dualRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 3)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d dual rays returned, expected %d.\n",
		  cnt,2) ; }
/*
  Run the remainder of the tests, to make sure they run without error when
  dylp finishes infeasible.
*/
    errcnt += dytest_betaj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abarj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_betai(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abari(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_allDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colPrimals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowPrimals(main_lp,main_lptols,main_lpopts) ;

    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    dylp(main_lp,main_lpopts,main_lptols,NULL) ;
    consys_free(main_sys) ;
    main_sys = NULL ;
    main_lp->consys = NULL ;
    dy_freesoln(main_lp) ; }
#endif

#if RUN_GALENETMIXED > 0
/*
  Now load and solve galenetmixed --- bound constraints on variables are
  handled implicitly, and the constraint system is a mix of <= and >=
  constraints (the equalities are handled as a pair of inequalities).  As
  with galenetleq, we'll need the full ray (explicit duals y = c<B>inv(B) as
  well as duals associated with nonbasic bounded variables) in order to pass
  the mathematical tests rb < 0, rA > 0.
*/
  dyio_outfmt(ttyout,dy_gtxecho,
	      "\n\nLoading galenetmixed example from static data.\n") ;
  main_sys = dytest_galenetmixedsys(main_lptols) ;
  if (main_sys == NULL)
  { dyio_outfmt(ttyout,dy_gtxecho,
		"Failed to load galenetmixed constraint system.\n") ;
    errcnt++ ; }
  else
  { dy_checkdefaults(main_sys,main_lpopts,main_lptols) ;
    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    main_lp->phase = dyINV ;
    main_lp->consys = main_sys ;
    main_lp->rowsze = main_sys->rowsze ;
    main_lp->colsze = main_sys->colsze ;
    main_lpopts->forcecold = TRUE ;
    main_lpopts->fullsys = TRUE ;
    main_lpopts->finpurge.vars = FALSE ;
    main_lpopts->finpurge.cons = FALSE ;
    main_lpopts->coldbasis = ibLOGICAL ;
    main_lpopts->scaling = 2 ;
/*
    main_lpopts->print.major = 1 ;
    main_lpopts->print.phase1 = 4 ;
    main_lpopts->print.phase2 = 4 ;
    main_lpopts->print.dual = 4 ;
    main_lpopts->print.tableau = 4 ;
    main_lpopts->print.soln = 3 ;
    main_lpopts->print.rays = 5 ;
*/

    dyio_outfmt(ttyout,dy_gtxecho,"Solving galenetmixed ... ") ;
    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    z = 48.0 ;
    if (!(fabs(main_lp->obj-z) <= main_lptols->cost))
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: z = %g, expected %g, error %g, tol %g.\n",
		  main_lp->obj,z,fabs(main_lp->obj-z),main_lptols->cost) ; }
    dumpsoln = TRUE ;
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }
/*
  Test that we have valid dual rays. First ask for just one, then ask for
  five, expecting three.
*/
    cnt = 1 ;
    errcnt += dytest_dualRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 1)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d dual rays returned, expected %d.\n",
		  cnt,1) ; }
    cnt = 5 ;
    errcnt += dytest_dualRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 3)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d dual rays returned, expected %d.\n",
		  cnt,2) ; }
/*
  Run the remainder of the tests, to make sure they run without error when
  dylp finishes infeasible.
*/
    errcnt += dytest_betaj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abarj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_betai(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abari(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_allDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colPrimals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowPrimals(main_lp,main_lptols,main_lpopts) ;

    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    dylp(main_lp,main_lpopts,main_lptols,NULL) ;
    consys_free(main_sys) ;
    main_sys = NULL ;
    main_lp->consys = NULL ;
    dy_freesoln(main_lp) ; }
#endif

#if RUN_GALENET > 0
/*
  Now load and solve the original galenet --- bound constraints on variables
  are handled implicitly, and the constraint system is a mix of <=, =, and >=
  constraints.  As with galenetleq, we'll need the full ray (explicit duals y
  = c<B>inv(B) as well as duals associated with nonbasic bounded variables)
  in order to pass the mathematical tests rb < 0, rA > 0.
*/
  dyio_outfmt(ttyout,dy_gtxecho,
	      "\n\nLoading galenet example from static data.\n") ;
  main_sys = dytest_galenetsys(main_lptols) ;
  if (main_sys == NULL)
  { dyio_outfmt(ttyout,dy_gtxecho,
		"Failed to load galenet constraint system.\n") ;
    errcnt++ ; }
  else
  { dy_checkdefaults(main_sys,main_lpopts,main_lptols) ;
    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    main_lp->phase = dyINV ;
    main_lp->consys = main_sys ;
    main_lp->rowsze = main_sys->rowsze ;
    main_lp->colsze = main_sys->colsze ;
    main_lpopts->forcecold = TRUE ;
    main_lpopts->fullsys = TRUE ;
    main_lpopts->finpurge.vars = FALSE ;
    main_lpopts->finpurge.cons = FALSE ;
    main_lpopts->coldbasis = ibLOGICAL ;
    main_lpopts->scaling = 2 ;
/*
    main_lpopts->print.major = 1 ;
    main_lpopts->print.phase1 = 4 ;
    main_lpopts->print.phase2 = 4 ;
    main_lpopts->print.dual = 4 ;
    main_lpopts->print.tableau = 4 ;
    main_lpopts->print.soln = 3 ;
    main_lpopts->print.rays = 5 ;
*/

    dyio_outfmt(ttyout,dy_gtxecho,"Solving galenet ... ") ;
    lpretval = do_lp(main_lp,main_lptols,main_lpopts,1) ;
    dyio_outfmt(ttyout,dy_gtxecho,"\n  %s, z = %.12f.\n",
		dy_prtlpret(lpretval),main_lp->obj) ;
    z = 46.0 ;
    if (!(fabs(main_lp->obj-z) <= main_lptols->cost))
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: z = %g, expected %g, error %g, tol %g.\n",
		  main_lp->obj,z,fabs(main_lp->obj-z),main_lptols->cost) ; }
    dumpsoln = TRUE ;
    if (dumpsoln == TRUE)
    { dy_dumpcompact(dy_logchn,dy_gtxecho,main_lp,FALSE) ; }
/*
  Test that we have valid dual rays. First ask for just one, then ask for
  five, expecting two. Note that we end up at a different vertex than the
  previous expanded versions of galenet.
*/
    cnt = 1 ;
    errcnt += dytest_dualRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 1)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d dual rays returned, expected %d.\n",
		  cnt,1) ; }
    cnt = 5 ;
    errcnt += dytest_dualRays(&cnt,main_lp,main_lptols,main_lpopts) ;
    if (cnt != 2)
    { errcnt++ ;
      dyio_outfmt(ttyout,dy_gtxecho,
		  "  ERROR: %d dual rays returned, expected %d.\n",
		  cnt,2) ; }
/*
  Run the remainder of the tests, to make sure they run without error when
  dylp finishes infeasible.
*/
    errcnt += dytest_betaj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abarj(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_betai(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_abari(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_allDuals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_colPrimals(main_lp,main_lptols,main_lpopts) ;
    errcnt += dytest_rowPrimals(main_lp,main_lptols,main_lpopts) ;

    comflg(main_lp->ctlopts,lpctlONLYFREE|lpctlNOFREE) ;
    dylp(main_lp,main_lpopts,main_lptols,NULL) ;
    consys_free(main_sys) ;
    main_sys = NULL ;
    main_lp->consys = NULL ;
    dy_freesoln(main_lp) ; }
#endif

/*
  Report the result before we shut down.
*/
  if (errcnt > 0)
  { dyio_outfmt(ttyout,dy_gtxecho,
		"\n  ERROR: %d total errors for all tests.\n\n", errcnt) ; }
  else
  { dyio_outfmt(ttyout,dy_gtxecho,
		"\n  All tests completed successfully.\n\n") ; }
  dy_freebasis() ;

/*
  Final cleanup. Free space used by the remaining main_* structures and close
  down any i/o.
*/
  if (main_lp != NULL)
  { dy_freesoln(main_lp) ;
    if (main_lp->consys != NULL) consys_free(main_lp->consys) ;
    FREE(main_lp) ; }
  if (main_lpopts != NULL) FREE(main_lpopts) ;
  if (main_lptols != NULL) FREE(main_lptols) ;

  if (outchn != IOID_INV && outchn != ttyout)
  { (void) dyio_closefile(outchn) ; }

  if (dy_logchn != IOID_INV && dy_logchn != IOID_NOSTRM)
  { (void) dyio_closefile(dy_logchn) ; }
  dyio_ioterm() ;
  errterm() ;

  return (errcnt) ; }
コード例 #16
0
ファイル: osi_dylp.c プロジェクト: sednanref/tesis
static void stats_lp (const char *outpath, bool echo, lpprob_struct *lp,
		      struct timeval *lptime, lpstats_struct *lpstats)

/*
  A little shell routine to handle writing detailed statistics on an LP to
  the output file.
  
  Parameters:
    outpath:	the output file path name.
    echo:	TRUE to echo to stdout, FALSE otherwise
    lp:	  	lp problem structure
    lptime:	elapsed time for call to do_lp
    lpstats:	lp statistics structure
 
  Returns : undefined
*/

{ ioid chn ;
  int vndx,bpos ;
  const char *rtnnme = "stats_lp" ;

/*
  Set up the output. Don't echo this to stdout twice.
*/
  if (outpath == NULL)
  { warn(2,rtnnme,"file name") ;
    chn = IOID_NOSTRM ; }
  else
  { chn = dyio_pathtoid(outpath,NULL) ;
    if (chn == IOID_INV) chn = dyio_openfile(outpath,"w") ;
    if (chn == IOID_INV)
    { warn(10,rtnnme,outpath,"w") ;
      chn = IOID_NOSTRM ; }
    if (strcmp(outpath,"stdout") == 0) echo = FALSE ; }
/*
  Print a few items from the lp structure --- name, status, pivot count, and
  lp return code.
*/
  if (lp == NULL)
  { dyio_outfmt(chn,echo,
	        "\n\n<< %s: LP problem structure is NULL! >>\n", rtnnme) ; }
  else
  { dyio_outfmt(chn,echo,
		"\n\nSystem: %s\t\t\tfinal status: %s after %d iterations.",
	        lp->consys->nme,dy_prtlpphase(lp->phase,FALSE),lp->iters) ;
    if (lp->phase == dyDONE)
    { dyio_outfmt(chn,echo,"\n    lp status: %s",dy_prtlpret(lp->lpret)) ;
      switch (lp->lpret)
      { case lpOPTIMAL:
	{ dyio_outfmt(chn,echo,"\t\tobjective: %.9g",lp->obj) ;
	  break ; }
	case lpINFEAS:
	{ dyio_outfmt(chn,echo,"\t\tinfeasibility: %.9g",lp->obj) ;
	  break ; }
	case lpUNBOUNDED:
	{ if (lp->obj != 0)
	  { if (lp->obj < 0)
	    { vndx = abs((int) lp->obj) ;
	      bpos = -1 ; }
	    else
	    { vndx = (int) lp->obj ;
	      bpos = 1 ; }
	    dyio_outfmt(chn,echo,"\t\tunbounded variable %s (%d) (%s)",
		        consys_nme(lp->consys,'v',vndx,FALSE,NULL),vndx,
		        (bpos < 0)?"decreasing":"increasing") ; }
	  break ; }
	default:
	{ break ; } } }
    if (lptime != NULL)
    { dyio_outfmt(chn,echo,"\n    lp time: ") ;
      prt_timeval(chn,echo,lptime) ;
      dyio_outfmt(chn,echo," (%.2f)",lptime->tv_sec+lptime->tv_usec/1e6) ; } }
# ifdef DYLP_STATISTICS
  if (lpstats != NULL) dy_dumpstats(chn,echo,lpstats,lp->consys) ;
# endif
  
  dyio_outfmt(chn,echo,"\n") ;

  dyio_flushio(chn,echo) ;

  return ; }
コード例 #17
0
ファイル: dy_warmstart.c プロジェクト: sednanref/tesis
dyret_enum dy_warmstart (lpprob_struct *orig_lp)

/*
  This routine is responsible for recreating the active constraint system,
  basis, and status specified by the user in orig_lp. It will handle even the
  pathological case of 0 active constraints and 0 active variables. If the
  user has supplied an active variable vector, only those variables will be
  activated. Clearly, the supplied basis, status, and active variable vector
  should be consistent, or bad things will happen.

  If we're operating in fullsys mode, we need to check here for additions to
  the constraint system.

  << In the very near future, this routine should also be upgraded to cope
     with the possibility that constraints specified in the warm start basis
     have disappeared. >>

  Parameters:
    orig_lp:	The original lp problem structure

  Returns: dyrOK if the setup completes without error, any of a number of
	   error codes otherwise (dyrFATAL, dyrINV, or a code from dy_factor)
*/

{ int vndx,dyvndx,bpos,cndx,dycndx,dycsze,dyvsze,nbfxcnt ;
  double *vlb,*vub,vlbj,vubj,obj ;
  consys_struct *orig_sys ;
  flags *orig_status,vstat,calcflgs ;
  dyret_enum retval ;
  basisel_struct *orig_basis ;
  bool *orig_actvars,rngseen,noactvarspec ;
  pkvec_struct *pkcol ;
  char nmebuf[50] ;

  flags parts = CONSYS_OBJ|CONSYS_VUB|CONSYS_VLB|CONSYS_RHS|CONSYS_RHSLOW|
		CONSYS_VTYP|CONSYS_CTYP,
	opts = CONSYS_LVARS|CONSYS_WRNATT ;
  
  const char *rtnnme = "dy_warmstart" ;

  extern void dy_setfinalstatus(void) ;		/* dy_hotstart.c */

# if defined(DYLP_PARANOIA) || !defined(DYLP_NDEBUG)
  double xi ;
# endif

  retval = dyrINV ;
  nbfxcnt = -1 ;

/*
  Do a little unpacking.
*/
  orig_sys = orig_lp->consys ;
  orig_status = orig_lp->status ;
  orig_basis = orig_lp->basis->el ;
  if (flgon(orig_lp->ctlopts,lpctlACTVARSIN) && dy_opts->fullsys == FALSE)
  { orig_actvars = orig_lp->actvars ;
    noactvarspec = FALSE ; }
  else
  { orig_actvars = NULL ;
    noactvarspec = TRUE ; }
/*
  Initialise the statistics on loadable/unloadable variables and constraints.
*/
  dy_lp->sys.forcedfull = FALSE ;
  dy_lp->sys.vars.loadable = orig_sys->varcnt ;
  dy_lp->sys.vars.unloadable = 0 ;
  dy_lp->sys.cons.loadable = orig_sys->concnt ;
  dy_lp->sys.cons.unloadable = 0 ;
/*
  Create the dy_sys constraint system to match the user's basis and active
  variables (if specified). We'll create the system with logicals enabled.
  
  For variables, if there is an active variable vector, skim it for a count.
  Otherwise, skim the status array and count the number of nonbasic fixed
  variables (which will never become active).

  For constraints, we need to consider the possibility that the user has
  added cuts and is trusting dylp to deal with it. If we're operating in the
  usual dynamic mode, this will be picked up automatically, and we can size
  the constraint system to the active constraints of the basis. But if we're
  operating in fullsys mode, we need to add them here. In this case, the
  number of constraints is the current size of the constraint system.

  Take this opportunity to clean the bounds arrays, making sure that bounds
  within the feasibility tolerance of one another are set to be exactly
  equal.  (This simplifies handling fixed variables.) For nonbasic variables,
  force the status to NBFX and cancel activation if actvars is present. Basic
  variables which need BFX are picked up later, after the basis is
  established.
*/
  vub = orig_sys->vub ;
  vlb = orig_sys->vlb ;
  dyio_outfxd(nmebuf,-((int) (sizeof(nmebuf)-1)),
	      'l',"%s[actv]",orig_sys->nme) ;
  if (noactvarspec == FALSE)
  { dyvsze = 0 ;
    for (vndx = 1 ; vndx <= orig_sys->varcnt ; vndx++)
    { vlbj = vlb[vndx] ;
      vubj = vub[vndx] ;
      if (atbnd(vlbj,vubj))
      { if (vlbj != vubj)
	{ 
#	  ifndef DYLP_NDEBUG
	  if (dy_opts->print.setup >= 3)
	  { dyio_outfmt(dy_logchn,dy_gtxecho,
		        "\n\tForcing equal bound %g for %s (%d)",
		        (vlbj+vubj)/2,consys_nme(orig_sys,'v',vndx,0,0),vndx) ;
	    dyio_outfmt(dy_logchn,dy_gtxecho,
		        "\n\t  original lb = %g, ub = %g, diff = %g, tol = %g",
		        vlbj,vubj,vubj-vlbj,dy_tols->pfeas) ; }
#	  endif
	  vlb[vndx] = (vlbj+vubj)/2 ;
	  vub[vndx] = vlb[vndx] ; }
	if (((int) orig_status[vndx]) > 0)
	{ orig_status[vndx] = vstatNBFX ;
	  orig_actvars[vndx] = FALSE ; } }
      if (vlb[vndx] > vub[vndx])
      { dy_lp->lpret = lpINFEAS ;
#     ifndef DYLP_NDEBUG
      if (dy_opts->print.setup >= 1)
      { dyio_outfmt(dy_logchn,dy_gtxecho,
	       "\n\tTrivial infeasibility for %s (%d), lb = %g > ub = %g.",
	       consys_nme(orig_sys,'v',vndx,0,0),vndx,vlb[vndx],vub[vndx]) ; }
#     endif
      }
      if (orig_actvars[vndx] == TRUE) dyvsze++ ; } }
  else
  { nbfxcnt = 0 ;
    for (vndx = 1 ; vndx <= orig_sys->varcnt ; vndx++)
    { vlbj = vlb[vndx] ;
      vubj = vub[vndx] ;
      if (atbnd(vlbj,vubj))
      { if (vlbj != vubj)
	{ 
#	  ifndef DYLP_NDEBUG
	  if (dy_opts->print.setup >= 3)
	  { dyio_outfmt(dy_logchn,dy_gtxecho,
			"\n\tForcing equal bound %g for %s (g)",
		        (vlbj+vubj)/2,consys_nme(orig_sys,'v',vndx,0,0),vndx) ;
	    dyio_outfmt(dy_logchn,dy_gtxecho,
		   "\n\t  original lb = %g, ub = %g, diff = %g, tol = %g",
		   vlbj,vubj,vubj-vlbj,dy_tols->pfeas) ; }
#	  endif
	  vlb[vndx] = (vlbj+vubj)/2 ;
	  vub[vndx] = vlb[vndx] ; }
	if (((int) orig_status[vndx]) > 0)
	{ orig_status[vndx] = vstatNBFX ; } }
      if (vlb[vndx] > vub[vndx])
      { dy_lp->lpret = lpINFEAS ; }
      if ((((int) orig_status[vndx]) > 0) &&
	  flgon(orig_status[vndx],vstatNBFX))
      { nbfxcnt++ ; } }
    dyvsze = orig_sys->varcnt-nbfxcnt ; }
  if (dy_opts->fullsys == TRUE)
    dycsze = orig_sys->concnt ;
  else
    dycsze = orig_lp->basis->len ;
  dyvsze += dycsze ;
# ifndef DYLP_NDEBUG
  if (dy_opts->print.setup >= 1)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n  creating constraint system %s (%d x %d+%d)",
		nmebuf,dycsze,dyvsze-dycsze,dycsze) ;
    if (dy_opts->print.setup >= 3)
    { if (flgoff(orig_lp->ctlopts,lpctlACTVARSIN))
        dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n      %d nonbasic fixed variables excluded.",
		    nbfxcnt) ; } }
# endif
  dy_sys = consys_create(nmebuf,parts,opts,dycsze,dyvsze,dy_tols->inf) ;
  if (dy_sys == NULL)
  { errmsg(152,rtnnme,nmebuf) ;
    return (dyrFATAL) ; }
/*
  Hang a set of translation vectors onto each system: origcons and origvars
  on orig_sys, and actcons and actvars on dy_sys.
*/
  if (consys_attach(dy_sys,CONSYS_ROW,
		    sizeof(int),(void **) &dy_actvars) == FALSE)
  { errmsg(100,rtnnme,dy_sys->nme,"active -> original variable map") ;
    return (dyrFATAL) ; }
  if (consys_attach(dy_sys,CONSYS_COL,
		    sizeof(int),(void **) &dy_actcons) == FALSE)
  { errmsg(100,rtnnme,dy_sys->nme,"active -> original constraint map") ;
    return (dyrFATAL) ; }
  if (consys_attach(orig_sys,CONSYS_ROW,
		    sizeof(int),(void **) &dy_origvars) == FALSE)
  { errmsg(100,rtnnme,orig_sys->nme,"original -> active variable map") ;
    return (dyrFATAL) ; }
  if (consys_attach(orig_sys,CONSYS_COL,
		    sizeof(int),(void **) &dy_origcons) == FALSE)
  { errmsg(100,rtnnme,orig_sys->nme,"original -> active constraint map") ;
    return (dyrFATAL) ; }
/*
  dy_origvars is cleared to 0 as it's attached, indicating that the original
  variables have no predefined status. We need to correct this.

  If the caller's supplied an active variable vector, we can use it to
  activate variables prior to adding constraints. (But in any case don't
  activate nonbasic fixed variables.) It's illegal to declare a formerly
  basic variable to be inactive by the simple expedient of setting
  actvars[vndx] = FALSE, hence the paranoid check.

  Otherwise, we'll need to depend on dy_loadcon to activate the variables
  referenced in the active constraints. We'll still fill in origvars, with
  two purposes:
    * We can avoid activating nonbasic fixed variables.
    * We can use dy_origvars == 0 as a paranoid check from here on out.
  Inactive variables are required to be nonbasic, so in this case the proper
  status for formerly basic variables is SB.
*/
  if (noactvarspec == FALSE)
  { 
#   ifndef DYLP_NDEBUG
    if (dy_opts->print.setup >= 1)
    { dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n  processing active variable list ...") ; }
#   endif
    pkcol = pkvec_new(0) ;
    for (vndx = 1 ; vndx <= orig_sys->varcnt ; vndx++)
    { if (((int) orig_status[vndx]) > 0)
	vstat = orig_status[vndx] ;
      else
	vstat = vstatB ;
      if (orig_actvars[vndx] == TRUE && flgoff(vstat,vstatNBFX))
      { if (consys_getcol_pk(orig_sys,vndx,&pkcol) == FALSE)
	{ errmsg(122,rtnnme,orig_sys->nme,"variable",
		 consys_nme(orig_sys,'v',vndx,TRUE,NULL),vndx) ;
	  retval = dyrFATAL ;
	  break ; }
	if (consys_addcol_pk(dy_sys,vartypCON,pkcol,
			     orig_sys->obj[vndx],vlb[vndx],vub[vndx]) == FALSE)
	{ errmsg(156,rtnnme,"variable",dy_sys->nme,pkcol->nme) ;
	  retval = dyrFATAL ;
	  break ; }
	dyvndx = pkcol->ndx ;
	dy_origvars[vndx] = dyvndx ;
	dy_actvars[dyvndx] = vndx ;
#       ifndef DYLP_NDEBUG
	if (dy_opts->print.setup >= 3)
	{ dyio_outfmt(dy_logchn,dy_gtxecho,
		      "\n\tactivating %s variable %s (%d) to index %d.",
		      consys_prtvartyp(orig_sys->vtyp[vndx]),
		      consys_nme(orig_sys,'v',vndx,FALSE,NULL),vndx,dyvndx) ; }
#       endif
      }
      else
      {
#       ifdef DYLP_PARANOIA
	if (flgon(vstat,vstatBASIC))
	{ errmsg(380,rtnnme,orig_sys->nme,
		 consys_nme(orig_sys,'v',vndx,FALSE,NULL),vndx,
		 dy_prtvstat(vstat),"non-basic") ;
	  retval = dyrFATAL ;
	  break ; }
#	endif
	dy_origvars[vndx] = -((int) vstat) ; } }
    pkvec_free(pkcol) ;
    if (retval != dyrINV) return (retval) ; }
  else
  { for (vndx = 1 ; vndx <= orig_sys->varcnt ; vndx++)
    { if (((int) orig_status[vndx]) > 0)
	vstat = orig_status[vndx] ;
      else
	vstat = vstatSB ;
      MARK_INACTIVE_VAR(vndx,-((int) vstat)) ; } }
/*
  Walk the basis and install the constraints in order. When we're finished
  with this, the active system will be up and about. In the case where
  there's no active variable specification, some of the status information
  written into dy_origvars may have been overwritten; only variables with
  vstatNBFX are guaranteed to remain inactive.
*/
  rngseen = FALSE ;
  for (bpos = 1 ; bpos <= orig_lp->basis->len ; bpos++)
  { cndx = orig_basis[bpos].cndx ;
#   ifndef DYLP_NDEBUG
    if (dy_opts->print.setup >= 2)
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n    activating %s %s (%d) in pos'n %d",
		  consys_prtcontyp(orig_sys->ctyp[cndx]),
		  consys_nme(orig_sys,'c',cndx,FALSE,NULL),cndx,bpos) ;
#   endif
#   ifdef DYLP_STATISTICS
    if (dy_stats != NULL) dy_stats->cons.init[cndx] = TRUE ;
#   endif
    if (dy_loadcon(orig_sys,cndx,noactvarspec,NULL) == FALSE)
    { errmsg(430,rtnnme,
	     dy_sys->nme,dy_prtlpphase(dy_lp->phase,TRUE),dy_lp->tot.iters,
	     "activate","constraint",
	     consys_nme(orig_sys,'c',cndx,TRUE,NULL),cndx) ;
      return (dyrFATAL) ; }
    if (orig_sys->ctyp[cndx] == contypRNG) rngseen = TRUE ; }
/*
  If we're in fullsys mode, repeat constraint installation actions for any
  cuts added after this basis was assembled.
*/
  if (dy_opts->fullsys == TRUE)
  { for (cndx = orig_lp->basis->len+1 ; cndx <= orig_sys->concnt ; cndx++)
    { 
#     ifndef DYLP_NDEBUG
      if (dy_opts->print.setup >= 2)
	dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n    activating %s %s (%d) in pos'n %d",
		    consys_prtcontyp(orig_sys->ctyp[cndx]),
		    consys_nme(orig_sys,'c',cndx,FALSE,NULL),cndx,cndx) ;
#     endif
#     ifdef DYLP_STATISTICS
      if (dy_stats != NULL) dy_stats->cons.init[cndx] = TRUE ;
#     endif
      if (dy_loadcon(orig_sys,cndx,noactvarspec,NULL) == FALSE)
      { errmsg(430,rtnnme,
	       dy_sys->nme,dy_prtlpphase(dy_lp->phase,TRUE),dy_lp->tot.iters,
	       "activate","constraint",
	       consys_nme(orig_sys,'c',cndx,TRUE,NULL),cndx) ;
	return (dyrFATAL) ; }
      if (orig_sys->ctyp[cndx] == contypRNG) rngseen = TRUE ; } }
# ifdef DYLP_PARANOIA
/*
  Paranoid checks and informational print statements.
*/
  if (dy_chkdysys(orig_sys) == FALSE) return (dyrINV) ;
# endif
# ifndef DYLP_NDEBUG
  if (dy_opts->print.setup >= 1)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n    system %s has %d constraints, %d+%d variables",
	        dy_sys->nme,dy_sys->concnt,dy_sys->archvcnt,dy_sys->logvcnt) ;
    dyio_outfmt(dy_logchn,dy_gtxecho,
	  "\n    %d constraints, %d variables remain inactive in system %s.",
	  orig_sys->concnt-dy_sys->concnt,orig_sys->archvcnt-dy_sys->archvcnt,
	  orig_sys->nme) ;
    if (dy_opts->print.setup >= 4)
    { nbfxcnt = 0 ;
      for (vndx = 1 ; vndx <= orig_sys->varcnt ; vndx++)
      { if (INACTIVE_VAR(vndx))
	{ vstat = (flags) (-dy_origvars[vndx]) ;
	  switch (getflg(vstat,vstatSTATUS))
	  { case vstatNBUB:
	    { xi = orig_sys->vub[vndx] ;
	      break ; }
	    case vstatNBLB:
	    case vstatNBFX:
	    { xi = orig_sys->vlb[vndx] ;
	      break ; }
	    case vstatNBFR:
	    { xi = 0 ;
	      break ; }
	    default:
	    { errmsg(433,rtnnme,dy_sys->nme,
		     dy_prtlpphase(dy_lp->phase,TRUE),dy_lp->tot.iters,
		     "inactive",consys_nme(orig_sys,'v',vndx,TRUE,NULL),
		     vndx,dy_prtvstat(vstat)) ;
	      return (dyrINV) ; } }
	  if (xi != 0)
	  { if (nbfxcnt == 0)
	      dyio_outfmt(dy_logchn,dy_gtxecho,
			  "\n\tinactive variables with nonzero values:") ;
	    nbfxcnt++ ;
	    dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t%s (%d) = %g, status %s",
		        consys_nme(orig_sys,'v',vndx,FALSE,NULL),vndx,xi,
		        dy_prtvstat(vstat)) ; } } }
      if (nbfxcnt == 0)
	dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n\tall inactive variables are zero.") ; } }
# endif
/*
  Time to assemble the basis. Attach the basis and inverse basis vectors to
  the constraint system. consys_attach will initialise them to 0.
*/
  if (consys_attach(dy_sys,CONSYS_COL,
		    sizeof(int),(void **) &dy_basis) == FALSE)
  { errmsg(100,rtnnme,dy_sys->nme,"basis vector") ;
    return (dyrFATAL) ; }
  if (consys_attach(dy_sys,CONSYS_ROW,
		    sizeof(int),(void **) &dy_var2basis) == FALSE)
  { errmsg(100,rtnnme,dy_sys->nme,"inverse basis vector") ;
    return (dyrFATAL) ; }
# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 1)
  { if (dy_opts->print.setup == 0)
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n %s: regenerating the basis ...",rtnnme) ;
    else
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n  regenerating the basis.",rtnnme) ; }
# endif
/*
  Load the basis. For variables, we need to translate architecturals using
  dy_origvars, and watch out for logicals (vndx = negative of associated
  constraint index). After all the paranoia, we finally update dy_basis and
  dy_var2basis.

  Because we loaded the constraints in the order they were listed in the
  basis, we should have that dycndx = bpos, hence dy_actcons[bpos] = cndx.

  If we're installing a basic variable, it should be active already.  For
  architectural variables, the check is made in dy_origvars.  For a logical,
  the associated constraint should be active, hence a non-zero entry in
  dy_origcons.  For architecturals, we also check if there are any non-zero
  coefficients remaining in the column (who knows what the user has done to
  the constraint system).  This rates a message if the print level is high
  enough, but the basis pacakge is capable of patching the basis. (Indeed,
  it's hard to do it correctly here.) 
*/
# ifdef DYLP_PARANOIA
  pkcol = pkvec_new(0) ;
  retval = dyrOK ;
# endif
  for (bpos = 1 ; bpos <= orig_lp->basis->len ; bpos++)
  { cndx = orig_basis[bpos].cndx ;
    dycndx = dy_origcons[cndx] ;
    vndx = orig_basis[bpos].vndx ;
    if (vndx < 0)
    { dyvndx = dy_origcons[-vndx] ; }
    else
    { dyvndx = dy_origvars[vndx] ; }

#   ifdef DYLP_PARANOIA
    if (dycndx <= 0)
    { errmsg(369,rtnnme,orig_sys->nme,"constraint",
	     consys_nme(orig_sys,'c',cndx,FALSE,NULL),cndx,
	     "cons",cndx,dycndx) ;
      retval = dyrINV ;
      break ; }
    if (dy_actcons[bpos] != cndx)
    { errmsg(370,rtnnme,dy_sys->nme,
	     consys_nme(orig_sys,'c',cndx,FALSE,NULL),cndx,bpos,
	     consys_nme(orig_sys,'c',dy_actcons[bpos],FALSE,NULL),
	     dy_actcons[bpos]) ;
      if (dycndx != bpos) { errmsg(1,rtnnme,__LINE__) ; }
      retval = dyrINV ;
      break ; }

    if (vndx < 0)
    { if (dyvndx <= 0)
      { errmsg(369,rtnnme,orig_sys->nme,"constraint",
	       consys_nme(orig_sys,'c',-vndx,FALSE,NULL),-vndx,
	       "cons",-vndx,dyvndx) ;
	retval = dyrINV ;
	break ; } }
    else
    { if (dyvndx <= 0)
      { errmsg(369,rtnnme,orig_sys->nme,"variable",
	       consys_nme(orig_sys,'v',vndx,FALSE,NULL),vndx,
	       "vars",vndx,dyvndx) ;
	retval = dyrINV ;
	break ; }
      if (consys_getcol_pk(dy_sys,dyvndx,&pkcol) == FALSE)
      { errmsg(122,rtnnme,orig_sys->nme,"variable",
	       consys_nme(orig_sys,'v',vndx,TRUE,NULL),vndx) ;
	retval = dyrFATAL ;
	break ; }
      if (pkcol->cnt == 0 && dy_opts->print.crash >= 4)
      { dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n      %s (%d) has no non-zeros in active constraints.",
		    consys_nme(dy_sys,'v',dyvndx,TRUE,NULL),dyvndx) ; } }
#   endif

    dy_basis[dycndx] = dyvndx ;
    dy_var2basis[dyvndx] = dycndx ; }
/*
  If we're in fullsys mode, make the logical basic for any remaining
  constraints.
*/
  if (dy_opts->fullsys == TRUE)
  { for ( ; bpos <= dy_sys->concnt ; bpos++)
    { dy_basis[bpos] = bpos ;
      dy_var2basis[bpos] = bpos ; } }

# ifdef DYLP_PARANOIA
  pkvec_free(pkcol) ;
  if (retval != dyrOK) return (retval) ;
# endif

# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 4)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n\t    Pos'n Variable           Constraint") ;
    for (bpos = 1 ; bpos <= orig_lp->basis->len ; bpos++)
    { vndx = dy_basis[bpos] ;
      dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t     %3d  (%3d) %-15s",bpos,vndx,
		  consys_nme(dy_sys,'v',vndx,FALSE,NULL)) ;
      dyio_outfmt(dy_logchn,dy_gtxecho,"%-15s",
		  consys_nme(dy_sys,'c',bpos,FALSE,NULL)) ; } }
# endif

/*
  Factor the basis. We don't want any of the primal or dual variables
  calculated just yet. If this fails we're in deep trouble. Don't do this
  if we're dealing with a constraint system with no constraints!
*/
  if (dy_sys->concnt > 0)
  {
#   ifndef DYLP_NDEBUG
    if (dy_opts->print.crash >= 2)
      dyio_outfmt(dy_logchn,dy_gtxecho,"\n    factoring ...") ;
#   endif
    calcflgs = 0 ;
    retval = dy_factor(&calcflgs) ;
    switch (retval)
    { case dyrOK:
      case dyrPATCHED:
      { break ; }
      default:
      { errmsg(309,rtnnme,dy_sys->nme) ;
	return (retval) ; } } }
/*
  Attach and clear the vectors which will hold the status, values of primal and
  dual variables, and reduced costs.
*/
  if (consys_attach(dy_sys,CONSYS_ROW,
		    sizeof(flags),(void **) &dy_status) == FALSE)
  { errmsg(100,rtnnme,dy_sys->nme,"status vector") ;
    return (dyrFATAL) ; }
  if (consys_attach(dy_sys,CONSYS_COL,
		    sizeof(double),(void **) &dy_xbasic) == FALSE)
  { errmsg(100,rtnnme,dy_sys->nme,"basic variable vector") ;
    return (dyrFATAL) ; }
  if (consys_attach(dy_sys,CONSYS_ROW,
		    sizeof(double),(void **) &dy_x) == FALSE)
  { errmsg(100,rtnnme,dy_sys->nme,"primal variable vector") ;
    return (dyrFATAL) ; }
  if (consys_attach(dy_sys,CONSYS_COL,
		    sizeof(double),(void **) &dy_y) == FALSE)
  { errmsg(100,rtnnme,dy_sys->nme,"dual variable vector") ;
    return (dyrFATAL) ; }
  if (consys_attach(dy_sys,CONSYS_ROW,
		    sizeof(double),(void **) &dy_cbar) == FALSE)
  { errmsg(100,rtnnme,dy_sys->nme,"reduced cost vector") ;
    return (dyrFATAL) ; }
/*
  Calculate dual variables and reduced costs. Might as well make a try for a
  dual feasible start, eh?
*/
# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 2)
    dyio_outfmt(dy_logchn,dy_gtxecho,"\n    calculating dual values ...") ;
# endif
  dy_calcduals() ;
  if (dy_calccbar() == FALSE)
  { errmsg(384,rtnnme,dy_sys->nme,
	   dy_prtlpphase(dy_lp->phase,TRUE),dy_lp->tot.iters) ;
    return (dyrFATAL) ; }
/*
  Initialise dy_status for logicals, using dy_var2basis and dy_cbar as guides.

  We have to consider the type of constraint so that we can give artificials
  NBFX status (thus avoiding the issue of whether NBLB or NBUB gives dual
  feasibility), and so that we can check the sign of the associated reduced
  cost to determine the proper bound for the logical associated with a range
  constraint.
*/
  vlb = dy_sys->vlb ;
  vub = dy_sys->vub ;
# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 2)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
	        "\n    establishing initial status and reference frame ...") ;
    dyio_outfmt(dy_logchn,dy_gtxecho,"\n      logicals ...") ; }
# endif
  for (dyvndx = 1 ; dyvndx <= dy_sys->concnt ; dyvndx++)
  { if (dy_var2basis[dyvndx] != 0)
    { if (vub[dyvndx] == vlb[dyvndx])
	dy_status[dyvndx] = vstatBFX ;
      else
	dy_status[dyvndx] = vstatB ; }
    else
    { switch (dy_sys->ctyp[dyvndx])
      { case contypLE:
	case contypGE:
	{ dy_status[dyvndx] = vstatNBLB ;
	  dy_x[dyvndx] = 0 ;
	  break ; }
        case contypEQ:
	{ dy_status[dyvndx] = vstatNBFX ;
	  dy_x[dyvndx] = 0 ;
	  break ; }
        case contypRNG:
	{ if (vub[dyvndx] == vlb[dyvndx])
	  { dy_status[dyvndx] = vstatNBFX ;
	    dy_x[dyvndx] = vub[dyvndx] ; }
	  else
	  if (dy_cbar[dyvndx] < 0)
	  { dy_status[dyvndx] = vstatNBUB ;
	    dy_x[dyvndx] = vub[dyvndx] ; }
	  else
	  { dy_status[dyvndx] = vstatNBLB ;
	    dy_x[dyvndx] = vlb[dyvndx] ; }
	  break ; }
	default:
	{ errmsg(1,rtnnme,__LINE__) ;
	  return (dyrFATAL) ; } } }
#   ifndef DYLP_NDEBUG
    if (dy_opts->print.crash >= 4)
    { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t  %s (%d) %s",
		  consys_nme(dy_sys,'v',dyvndx,FALSE,NULL),dyvndx,
		  dy_prtvstat(dy_status[dyvndx])) ;
      if (flgon(dy_status[dyvndx],vstatNONBASIC|vstatNBFR))
	dyio_outfmt(dy_logchn,dy_gtxecho," with value %g.",dy_x[dyvndx]) ;
      else
	dyio_outchr(dy_logchn,dy_gtxecho,'.') ; }
#   endif
  }
/*
  Scan dy_origvars, with two purposes in mind:
    * For active architectural variables, initialise dy_status from
      orig_status, using the actual status for nonbasic variables, and
      vstatB, vstatBFX, or vstatBFR for basic variables. (We'll tune this
      once we have the values of the basic variables.) Initialise dy_x to the
      proper value for nonbasic variables. We shouldn't see NBFX here, as
      those variables should have been left inactive.
    * For inactive architectural variables, accumulate the objective function
      correction. Nonbasic free variables are assumed to have value 0.
*/
# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 2)
    dyio_outfmt(dy_logchn,dy_gtxecho,"\n      architecturals ...") ;
# endif
  dy_lp->inactzcorr = 0 ;
  for (vndx = 1 ; vndx <= orig_sys->varcnt ; vndx++)
  { dyvndx = dy_origvars[vndx] ;
    if (dyvndx < 0)
    { obj = orig_sys->obj[vndx] ;
      switch ((flags) (-dyvndx))
      { case vstatNBFX:
        case vstatNBLB:
	{ dy_lp->inactzcorr += obj*orig_sys->vlb[vndx] ;
	  break ; }
        case vstatNBUB:
	{ dy_lp->inactzcorr += obj*orig_sys->vub[vndx] ;
	  break ; }
#       ifdef DYLP_PARANOIA
	case vstatNBFR:
	{ break ; }
	default:
	{ errmsg(1,rtnnme,__LINE__) ;
	  return (dyrINV) ; }
#	endif
      } }
    else
    { if (((int) orig_status[vndx]) < 0)
      { if (vlb[dyvndx] == vub[dyvndx])
	  dy_status[dyvndx] = vstatBFX ;
	else
	if (vlb[dyvndx] <= -dy_tols->inf && vub[dyvndx] >= dy_tols->inf)
	  dy_status[dyvndx] = vstatBFR ;
	else
	  dy_status[dyvndx] = vstatB ; }
      else
      { dy_status[dyvndx] = orig_status[vndx] ;
	switch (dy_status[dyvndx])
	{ case vstatNBLB:
	  { dy_x[dyvndx] = vlb[dyvndx] ;
	    break ; }
	  case vstatNBUB:
	  { dy_x[dyvndx] = vub[dyvndx] ;
	    break ; }
	  case vstatNBFR:
	  { dy_x[dyvndx] = 0 ;
	    break ; }
#	  ifdef DYLP_PARANOIA
	  default:
	  { errmsg(1,rtnnme,__LINE__) ;
	    return (dyrINV) ; }
#	  endif
	} }
#     ifndef DYLP_NDEBUG
      if (dy_opts->print.crash >= 4)
      { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t  %s (%d) %s",
		    consys_nme(dy_sys,'v',dyvndx,FALSE,NULL),dyvndx,
		    dy_prtvstat(dy_status[dyvndx])) ;
	if (flgon(dy_status[dyvndx],vstatNONBASIC|vstatNBFR))
	  dyio_outfmt(dy_logchn,dy_gtxecho," with value %g.",dy_x[dyvndx]) ;
	else
	  dyio_outchr(dy_logchn,dy_gtxecho,'.') ; }
#     endif
    } }
/*
  Did we patch the basis? If so, we need to scan the status array and correct
  the entries for the architectural variables that were booted out during the
  patch.
*/
  if (retval == dyrPATCHED) correct_for_patch() ;
/*
  Ok, status is set. Now it's time to calculate initial values for the primal
  variables and objective.  Arguably we don't need the true objective for
  phase I, but it's cheap to calculate.  Once we have the primal variables,
  adjust the status for any that are pinned against a bound or out of bounds,
  and see how it looks, in terms of primal infeasibility.
*/
# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 2)
    dyio_outfmt(dy_logchn,dy_gtxecho,"\n    calculating primal values ...") ;
# endif
  if (dy_calcprimals() == FALSE)
  { errmsg(316,rtnnme,dy_sys->nme) ;
    return (dyrFATAL) ; }
  dy_lp->z = dy_calcobj() ;
  dy_setfinalstatus() ;
/*
  Make the check for primal and/or dual feasibility, and set the initial
  simplex phase accordingly.
*/
  calcflgs = ladPRIMFEAS|ladPFQUIET|ladDUALFEAS|ladDFQUIET ;
  retval = dy_accchk(&calcflgs) ;
  if (retval != dyrOK)
  { errmsg(304,rtnnme,dy_sys->nme,
	   dy_prtlpphase(dy_lp->phase,TRUE),dy_lp->tot.iters) ;
    return (retval) ; }
  if (flgoff(calcflgs,ladPRIMFEAS))
  { dy_lp->simplex.next = dyPRIMAL2 ; }
  else
  if (flgoff(calcflgs,ladDUALFEAS))
  { dy_lp->simplex.next = dyDUAL ; }
  else
  { dy_lp->simplex.next = dyPRIMAL1 ; }

# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 2)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n    phase %s, initial objective %g",
	        dy_prtlpphase(dy_lp->simplex.next,FALSE),dy_lp->z) ;
    if (dy_lp->infeascnt != 0)
      dyio_outfmt(dy_logchn,dy_gtxecho,", %d infeasible vars, infeas = %g",
		  dy_lp->infeascnt,dy_lp->infeas) ;
    dyio_outchr(dy_logchn,dy_gtxecho,'.') ; }
  if (dy_opts->print.crash >= 3)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n\nPos'n\tConstraint\tDual\t\tPrimal\n") ;
    for (bpos = 1 ; bpos <= dy_sys->concnt; bpos++)
    { cndx = dy_actcons[bpos] ;
      dyvndx = dy_basis[bpos] ;
      if (dyvndx <= dy_sys->concnt)
	vndx = orig_sys->varcnt+dyvndx ;
      else
	vndx = dy_actvars[dyvndx] ;
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n%5d\t(%4d) %-8s\t%12.4g\t(%4d) %-8s %12.4g",
		  bpos,cndx,
		  consys_nme(dy_sys,'c',bpos,FALSE,NULL),dy_y[bpos],vndx,
		  consys_nme(dy_sys,'v',dyvndx,FALSE,NULL),dy_x[dyvndx]) ; } }
# endif

  return (dyrOK) ; }
コード例 #18
0
ファイル: osi_dylp.c プロジェクト: sednanref/tesis
int main (int argc, char *argv[])

{ time_t timeval ;
  struct tm *tm ;
  char runtime[50] ;
  ioid ttyin,ttyout,outchn ;
  int optlett,printlvl ;
  bool silent,terse,swaperrs,errecho,doversion,dohelp ;
  const char *errmsgpath,*errlogpath,*optpath,*mpspath,*logpath ;

  struct timeval lptime ;
  
  const char *rtnnme = argv[0] ;

/*
  getopt() --- we need explicit declarations under strict ANSI compliance
  mode. This function seems to be quite common, however. Present in GCC.
*/
  int getopt(int argc, char*const *argv, const char *optstring) ;
  extern char *optarg ;
  extern int opterr,optind,optopt ;

  const char *optstring = "e:stp:E:o:m:L:O:hv";

  extern struct tm *localtime(const time_t *clock) ;

  /* mpsio.c */

  extern bool dy_mpsin(const char *mpspath,
  		       consys_struct **consys, double infinity);

  /* dy_basis.c */

  extern void dy_initbasis(int concnt, int factor_freq, double zero_tol),
	      dy_freebasis(void) ;

/*
  Set up some defaults, then process the command line options. This is all very
  specific to Unix and SunOS.
*/
  errmsgpath = DYLP_ERRMSGPATH ;
  errlogpath = NULL ;
  optpath = NULL ;
  mpspath = NULL ;
  outpath = NULL ;
  logpath = NULL ;

  ttyout = IOID_INV ;
  ttyin = IOID_INV ;
  dy_logchn = IOID_INV ;
  outchn = IOID_INV ;

  silent = FALSE ;
  terse = FALSE ;
  dy_gtxecho = TRUE ;
  dy_cmdecho = FALSE ;
  doversion = FALSE ;
  dohelp = FALSE ;

  printlvl = -1 ;

  opterr = 0 ;
  for (optlett = getopt(argc,argv,optstring) ;
       optlett != -1 ;
       optlett = getopt(argc,argv,optstring))
    switch (optlett)
    { case 'e':
      { errmsgpath = optarg ;
	break ; }
      case 'E':
      { errlogpath = optarg ;
	break ; }
      case 'o':
      { optpath = optarg ;
	break ; }
      case 'm':
      { mpspath = optarg ;
	break ; }
      case 'L':
      { logpath = optarg ;
	break ; }
      case 'O':
      { outpath = optarg ;
	break ; }
      case 's':
      { silent = TRUE ;
	dy_gtxecho = FALSE ;
	break ; }
      case 't':
      { terse = TRUE ;
	dy_gtxecho = FALSE ;
	break ; }
      case 'p':
      { printlvl = atoi(optarg) ;
	break ; }
      case 'v':
      { doversion = TRUE ;
	break ; }
      case 'h':
      { dohelp = TRUE ;
	break ; }
      case '?':
      { errinit(errmsgpath,errlogpath,TRUE) ;
	dyio_ioinit() ;
	errmsg(3,rtnnme,"command line option",optopt) ;
	exit (1) ; } }
/*
  If there's still a parameter left, it must be the mps file, specified without
  using the -m option. There should not be more than one parameter remaining.
*/
  if (optind < argc)
  { mpspath = argv[optind] ;
    optind++ ; }
  if (optind < argc)
  { dohelp = TRUE ; } 
/*
  What's our output level? If the user has specified a print level, go with it.
  Otherwise, take a cue from any -s or -t flags. Default to print level 2.
*/
  if (printlvl < 0)
  { if (silent == TRUE)
      printlvl = 0 ;
    else
    if (terse == TRUE)
      printlvl = 1 ;
    else
      printlvl = 2 ; }
/*
  Output file name: if the user hasn't specified one, and we're not running
  silent, default to stdout.
*/
  if (outpath == NULL && silent == FALSE) outpath = "stdout" ;
/*
  Grab the time and format it nicely.
*/
  if (time(&timeval) == (time_t)(-1))
  { warn(19,rtnnme) ;
    osidylp_time = "n/a" ; }
  else
  { tm = localtime(&timeval) ;
    if (tm != NULL)
    { strftime(runtime,sizeof(runtime),"%A, %B %d, %Y,  %I:%M:%S %p",tm) ;
      osidylp_time = runtime ; }
    else
    { osidylp_time = "n/a" ; } }
/*
  Figure out the appropriate settings for silent and terse.
  silent is set to (silent || terse), and is passed to process_cmds so that
	 it can properly handle dy_cmdecho and dy_gtxecho.
  terse	 is set for ease of controlling the output specifically mentioned in
	 conjunction with terse mode (which is controlled from this routine).
	 The proper value is (terse || !silent).
  The cryptic little if statement below accomplishes this (try a decision tree
  to convince yourself).
*/
  if (terse == TRUE)
  { if (silent == TRUE)
      terse = FALSE ;
    else
      silent = TRUE ; }
  else
  { if (silent == FALSE) terse = TRUE ; }
/*
  Execute initialization routines for the i/o and error reporting packages.
*/
  if (silent == TRUE)
    errecho = FALSE ;
  else
    errecho = TRUE ;
  errinit(errmsgpath,errlogpath,errecho) ;
  if (dyio_ioinit() != TRUE)
  { errmsg(1,rtnnme,__LINE__) ;
    exit (2) ; }
/*
  Connect ttyout to the standard output. Initialize ttyin, setting the mode to
  line-oriented. Serious internal confusion if we can't manage these. Set the
  initial command input channel to stdin.
*/
  ttyout = dyio_openfile("stdout","w") ;
  if (ttyout == IOID_INV)
  { errmsg(1,rtnnme,__LINE__) ;
    exit(3) ; }
  ttyin = dyio_openfile("stdin","r") ;
  if (ttyin == IOID_INV)
  { errmsg(1,rtnnme,__LINE__) ;
    exit(4) ; }
  (void) dyio_setmode(ttyin,'l') ;
  dy_cmdchn = ttyin ;
/*
  Initialize logging.
*/
  if (logpath != NULL)
  { dy_logchn = dyio_openfile(logpath,"w") ;
    if (dy_logchn == IOID_INV)
    { warn(201,rtnnme,logpath) ;
      dy_logchn = IOID_NOSTRM ; } }
  else
  { dy_logchn = IOID_NOSTRM ; }
/*
  Are we supposed to merge the error messages with the log stream? (Note that
  errors will be echoed to stderr unless we're running silent. If the user's
  turned off logging too, well, it's their business.) swaperrs just tells the
  code that it should reset the error logging channel if it ever resets the
  main logging channel.
*/
  if (errlogpath == NULL && dy_logchn != IOID_NOSTRM)
  { swaperrs = TRUE ;
    errlogpath = logpath ;
    if (dyio_chgerrlog(errlogpath,errecho) == FALSE)
    { warn(18,rtnnme,"<null>",errlogpath) ; } }
/*
  Ok, after all that work, check if we've been asked for the version or usage
  messages. If so, do it and head for the exit. Version preempts help.
*/
  if (doversion == TRUE)
  { print_version(dy_logchn,dy_gtxecho,argv[0],rtnnme,osidylp_version) ;
    goto NOOUTFILE_CLEANUP ; }
  if (dohelp == TRUE)
  { print_help(dy_logchn,dy_gtxecho,argv[0]) ;
    goto NOOUTFILE_CLEANUP ; }
/*
  We're up! Banners to the appropriate places.
*/
  dyio_outfmt(dy_logchn,terse,"\n\t\t    %s\tV %s\n",rtnnme,osidylp_version) ;
  dyio_outfmt(dy_logchn,terse,"\n\t\t%s",runtime) ;
  dyio_outfmt(dy_logchn,terse,"\n\n") ;
  if (outpath != NULL && strcmp(outpath,"stdout") != 0)
  { outchn = dyio_pathtoid(outpath,NULL) ;
    if (outchn == IOID_INV) outchn = dyio_openfile(outpath,"w") ;
    if (outchn == IOID_INV)
    { warn(10,rtnnme,outpath,"w") ; }
    else
    { dyio_outfmt(outchn,FALSE,"\n\t\t    %s\tV %s\n",rtnnme,osidylp_version) ;
      dyio_outfmt(outchn,FALSE,"\n\t\t%s",runtime) ;
      dyio_outfmt(outchn,FALSE,"\n\n") ; } }
/*
  Time to set up the lp options. Establish a set of defaults, then read the
  options file to see what the user has in mind. Because this is a standalone
  shell, doing a one-time solution for an LP, set up a default of cold start
  using the full system and a logical basis. This can be overridden in a .spc
  file if desired.

  For reasons that escape me at the moment, the parser fails on Windows. This
  may get fixed eventually. For now, disabled by the simple expedient of
  forcing optpath to NULL.
*/
  dy_defaults(&main_lpopts,&main_lptols) ;
  main_lpopts->forcecold = TRUE ;
  main_lpopts->fullsys = TRUE ;
  main_lpopts->coldbasis = ibLOGICAL ;
# if defined(_MSC_VER) || defined(__MSVCRT__)
  optpath = NULL ;
# endif
  if (optpath != NULL)
  { dy_cmdchn = dyio_openfile(optpath,"r") ;
    if (dy_cmdchn == IOID_INV) exit (1) ;
    (void) dyio_setmode(dy_cmdchn,'l') ;
    switch (process_cmds(silent))
    { case cmdOK:
      { break ; }
      case cmdHALTERROR:
      { exit (1) ; }
      case cmdHALTNOERROR:
      { exit (0) ; }
      default:
      { exit (1) ; } }
    if (dy_cmdchn != ttyin)
    { (void) dyio_closefile(dy_cmdchn) ;
      dy_cmdchn = IOID_INV ; } }
/*
  Make an attempt to read the mps input file.
*/
  if (dy_mpsin(mpspath,&main_sys,main_lptols->inf) == FALSE)
  { exit (10) ;}
/*
  Check over the option settings, now that we know how big the constraint
  system will be.
*/
  dy_checkdefaults(main_sys,main_lpopts,main_lptols) ;
/*
  Initialise the basis maintenance package. The second parameter controls how
  many basis updates the basis can hold before it requires refactoring.
  Adding 5 to dylp's refactor interval should give a safety margin.
*/
  dy_initbasis(2*main_sys->concnt,main_lpopts->factor+5,0.0) ;
/*
  Run the lp.
*/
  if (do_lp(&lptime,printlvl) == FALSE)
  { errmsg(443,rtnnme,main_sys->nme,dy_prtlpphase(main_lp->phase,TRUE),
	   main_lp->iters) ; }
/*
  Should we produce any output? Print to a file, if requested.
*/
  if (outchn != IOID_INV && outchn != ttyout)
  { dy_dumpcompact(outchn,FALSE,main_lp,FALSE) ; }
/*
  Any final terminal output we should do?
*/
  if (printlvl >= 1)
  { if (printlvl >= 2)
    { dy_dumpcompact(dy_logchn,
		     (dy_logchn == IOID_INV)?TRUE:FALSE,main_lp,FALSE) ; }
    dyio_outfmt(dy_logchn,TRUE,"\nReturn code %s",dy_prtlpret(main_lp->lpret)) ;
    if (main_lp->phase == dyDONE)
      dyio_outfmt(dy_logchn,TRUE," after %d pivots",main_lp->iters) ;
    if (main_lp->lpret == lpOPTIMAL)
    { dyio_outfmt(dy_logchn,TRUE,"; objective %.8g",main_lp->obj) ; }
    dyio_outfmt(dy_logchn,TRUE,
		" (%.2f sec.)",lptime.tv_sec+lptime.tv_usec/1e6) ;
    dyio_outfmt(dy_logchn,TRUE,".\n") ;
    dyio_flushio(dy_logchn,dy_gtxecho) ; }
/*
  Final cleanup. Free space used by the remaining main_* structures.
*/
  dy_freebasis() ;

  if (main_lp != NULL)
  { dy_freesoln(main_lp) ;
    if (main_lp->consys != NULL) consys_free(main_lp->consys) ;
    FREE(main_lp) ; }
  if (main_lpopts != NULL) FREE(main_lpopts) ;
  if (main_lptols != NULL) FREE(main_lptols) ;
/*
  Leap to here for shutdown when we opened the output file but didn't solve
  an LP.
*/
  if (outchn != IOID_INV && outchn != ttyout)
  { (void) dyio_closefile(outchn) ; }
/*
  Leap to here for shutdown in cases where we never get as far as opening
  an output file. We still need to close the log file and shut down the i/o
  subsystem.
*/
  NOOUTFILE_CLEANUP:
  if (dy_logchn != IOID_INV && dy_logchn != IOID_NOSTRM)
  { (void) dyio_closefile(dy_logchn) ; }
  dyio_ioterm() ;
  errterm() ;

  exit(0) ;
  
/*
  Just to suppress the silly warning from the compiler, which isn't satisfied
  with the immediately preceding `exit'.
*/

  return (0) ; }
コード例 #19
0
ファイル: dy_solutions.c プロジェクト: sednanref/tesis
void dy_rowDuals (lpprob_struct *orig_lp, double **p_y, bool trueDuals)

/*
  This routine returns the unscaled vector of row duals, commonly referred to
  as the dual variables, c<B>inv(B). The values are unscaled and returned in a
  vector matching the original system frame of reference. Duals associated with
  inactive rows are always zero.
  
  In dylp's min primal <=> min dual pairing, the duals have the wrong sign
  for the true dual variables used by the min dual problem. If you'd prefer
  that the duals have a sign convention appropriate for the min dual problem,
  specify trueDuals = false.

  The relevant bit of unscaling is:

  sc_y<i> = sc_c<B>sc_inv(B)
	  = c<B>S<B>inv(S<B>)inv(B)inv(R)
	  = c<B>inv(B)inv(R)

  So, to recover y<i> we need to postmultiply by inv(R). The appropriate row
  factor is the one associated with the original row.

  Parameters:
    orig_lp:	the original lp problem
    p_y:	(i) vector to hold the dual variables; if NULL, a vector of
		    appropriate size will be allocated
		(o) values of the dual variables, unscaled, in the original
		    system frame of reference

  Returns: undefined
*/

{ int i,m,n,i_orig,m_orig,n_orig ;
  double yi ;
  double *y ;

  consys_struct *orig_sys ;
  contyp_enum *ctyp ;

  bool scaled ;
  const double *rscale,*cscale ;

# ifndef DYLP_NDEBUG
  int j,v ;
# endif
# ifdef DYLP_PARANOIA
  char *rtnnme = "dy_rowDuals" ;

  if (dy_std_paranoia(orig_lp,rtnnme) == FALSE)
  { return ; }
  if (p_y == NULL)
  { errmsg(2,rtnnme,"y") ;
    return ; }
# endif

/*
  Is unscaling required? Acquire the scaling vectors.
  accordingly.
*/
  scaled = dy_isscaled() ;
  if (scaled == TRUE)
  { dy_scaling_vectors(&rscale,&cscale) ; }

  orig_sys = orig_lp->consys ;
  n_orig = orig_sys->varcnt ;
  m_orig = orig_sys->concnt ;
  n = dy_sys->varcnt ;
  m = dy_sys->concnt ;
  ctyp = orig_sys->ctyp ;
/*
  Do we need a vector?
*/
  if (*p_y != NULL)
  { y = *p_y ;
    memset(y,0,(m_orig+1)*sizeof(double)) ; }
  else
  { y = (double *) CALLOC((m_orig+1),sizeof(double)) ; }
/*
  Step through the constraints of the original system. For active constraints,
  acquire and unscale the dual value.
*/
  for (i_orig = 1 ; i_orig <= m_orig ; i_orig++)
  { if (ACTIVE_CON(i_orig))
    { i = dy_origcons[i_orig] ;
      yi = dy_y[i] ;
      if (scaled == TRUE)
      { yi *= rscale[i_orig] ; }
      setcleanzero(yi,dy_tols->cost) ; }
    else
    { yi = 0.0 ; }
/*
  The true duals are the negative of the minimisation duals here.
*/
    if (trueDuals == TRUE)
      y[i_orig] = -yi ;
    else
      y[i_orig] = yi ; }

# ifndef DYLP_NDEBUG
  if (dy_opts->print.soln >= 3)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\ty =") ;
    v = 0 ;
    for (i_orig = 1 ; i_orig <= m_orig ; i_orig++)
    { if (y[i_orig] != 0)
      { if ((++v)%3 == 0)
	{ v = 0 ;
	  dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t   ") ; }
	i = dy_origcons[i_orig] ;
	j = dy_basis[i] ;
	dyio_outfmt(dy_logchn,dy_gtxecho," (%d %g %s %d)",
		    i_orig,y[i_orig],
		    consys_nme(dy_sys,'v',j,FALSE,NULL),j) ; } } }
# endif

/*
  That's it. Return the vector.
*/
  *p_y = y ;

  return ; }
コード例 #20
0
ファイル: dytest_solutions.c プロジェクト: sednanref/tesis
int dytest_colDuals (lpprob_struct *main_lp, lptols_struct *main_lptols,
		     lpopts_struct *main_lpopts)
/*
  This routine checks the dual variables returned by dy_colDuals (more
  usually called the reduced costs of the architectural variables).
  
  It checks that cbar<N> = c<N> - yN, where y is the vector of row duals
  returned by dy_rowDuals and N is the set of nonbasic architectural columns
  of A (or the matching index set, as appropriate). It also checks that the
  reduced cost is in agreement with the status.

  Parameters:
    main_lp:	 the lp problem structure
    main_lptols: the lp tolerance structure
    main_lpopts: the lp options structure

  Returns: 0 if cbar<N> = c<N> - yN, error count otherwise.
*/

{ int j,m,n ;
  flags statj ;

  consys_struct *sys ;
  double *obj ;
  double *y ;
  flags *status ;

  double *cbarN ;
  double cbarj ;

  int errcnt ;
  bool staterr ;
  char *errstring ;

  char *rtnnme = "dytest_colDuals" ;

/*
  Do a little initialisation. Mention that we've started.
*/
  sys = main_lp->consys ;
  m = sys->concnt ;
  n = sys->varcnt ;

# ifndef DYLP_NDEBUG
  if (main_lpopts->print.soln >= 1)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: checking cbar<N> = c<N> - yN using %s (%d x %d).",
		rtnnme,sys->nme,m,n) ; }
# endif
/*
  Acquire the row duals, column duals, status vector, and objective.  We want
  both the (row) duals and reduced costs (column duals) to come through with
  sign unchanged, appropriate for a minimisation primal.
*/
  y = NULL ;
  dy_rowDuals(main_lp,&y,FALSE) ;
  cbarN = NULL ;
  dy_colDuals(main_lp,&cbarN,FALSE) ;
  status = NULL ;
  dy_colStatus(main_lp,&status) ;
  obj = sys->obj ;
/*
  Now step through the columns checking that cbar<j> = c<j> - dot(y,a<j>).
  Also check to see that the sign is correct for the status of the variable
  in a minimisation problem.  For status values not listed (vstatSB and any
  of the basic status codes), there's no `correct' sign.
*/
  errcnt = 0 ;
  for (j = 1 ; j <= n ; j++)
  { cbarj = obj[j] - consys_dotcol(sys,j,y) ;
    statj = status[j] ;
    if (fabs(cbarj-cbarN[j]) > main_lptols->cost)
    { errcnt++ ;
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\nERROR: col %s (%d) %s cbar<%d> = %g; expected %g;",
		  consys_nme(sys,'v',j,FALSE,NULL),j,dy_prtvstat(statj),
		  j,cbarj,cbarN[j]) ;
      dyio_outfmt(dy_logchn,dy_gtxecho," error %g, tol %g.",
		  fabs(cbarj),main_lptols->cost) ; }
    staterr = FALSE ;
    switch (statj)
    { case vstatNBLB:
      { if (cbarj < -main_lptols->zero)
	{ staterr = TRUE ;
	  errstring = "positive" ; }
	break ; }
      case vstatNBUB:
      { if (cbarj > main_lptols->zero)
	{ staterr = TRUE ;
	  errstring = "negative" ; }
	break ; }
      case vstatNBFR:
      { if (fabs(cbarj) > main_lptols->zero)
	{ staterr = TRUE ;
	  errstring = "zero" ; }
	break ; }
      default:
      { break ; } }
    if (staterr == TRUE)
    { errcnt++ ;
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\nERROR: col %s (%d) %s cbar<%d> = %g; should be %s.",
		  consys_nme(sys,'v',j,FALSE,NULL),j,dy_prtvstat(statj),
		  j,cbarj,errstring) ; } }
/*
  Free up space and report the result.
*/
  if (y != NULL) FREE(y) ;
  if (cbarN != NULL) FREE(cbarN) ;
  if (status != NULL) FREE(status) ;

  if (errcnt != 0)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: found %d errors testing cbar<N> = c<N> - yN.\n",
		rtnnme,errcnt) ; }
  else
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: pass cbar<N> = c<N> - yN.\n",rtnnme) ; }

  return (errcnt) ; }
コード例 #21
0
ファイル: dy_solutions.c プロジェクト: sednanref/tesis
void dy_rowPrimals (lpprob_struct *orig_lp, double **p_xB, int **p_indB)

/*
  This routine returns the values of the primal basic variables, unscaled, in
  row (basis) order in the frame of reference of the original system.

  Unscaling is straightforward:

  sc_x<B> = sc_inv(B)sc_b
	  = inv(S<B>)inv(B)inv(R)Rb
	  = inv(S<B>)(inv(B)b)

  so all that's needed to recover x<B> = inv(B)b is to multiply by S<B>. For
  logicals, recall that S<i> = 1/R<i>.

  By construction, the basic variable for inactive constraints is the logical
  for the constraint. Generating beta<i> = [ -a<B,i>inv(B) 1 ] for an inactive
  row, correcting b<i> for nonbasic, nonzero variables (active and inactive),
  and calculating dot(beta<i>,b) is a lot of work. Much easier to call
  colPrimals for the complete solution vector and calculate b<i> - dot(a<i>,x)
  in the original system.

  Parameters:
    orig_lp:	the original lp problem
    p_xB:	(i) vector to hold the values of the primal basic variables;
		    if NULL, a vector of appropriate size will be allocated
		(o) values of the primal basic variables, unscaled, in the
		    original system frame of reference
    p_indB:	(i) vector to hold the indices of the primal basic variables;
		    if NULL, a vector of appropriate size will be allocated
		(o) indices of the primal basic variables, unscaled, in the
		    original system frame of reference; indices of logical
		    variables are encoded as the negative of the constraint
		    index

  Returns: undefined
*/

{ int i,j,m,i_orig,j_orig,m_orig,n_orig ;
  double xj,lhs ;

  consys_struct *orig_sys ;
  double *x,*xB ;
  int *indB ;

  bool scaled ;
  const double *rscale,*cscale ;

# ifndef DYLP_NDEBUG
  int v ;
# endif
# ifdef DYLP_PARANOIA
  char *rtnnme = "dy_rowPrimals" ;

  if (dy_std_paranoia(orig_lp,rtnnme) == FALSE)
  { return ; }
  if (p_xB == NULL)
  { errmsg(2,rtnnme,"x") ;
    return ; }
  if (p_indB == NULL)
  { errmsg(2,rtnnme,"x") ;
    return ; }
# endif

/*
  Is unscaling required? Acquire the scaling vectors.

  If there are inactive constraints, we'll need the primal architecturals in
  order to calculate the value of the associated (basic) logical.
*/
  scaled = dy_isscaled() ;
  if (scaled == TRUE)
  { dy_scaling_vectors(&rscale,&cscale) ; }

  orig_sys = orig_lp->consys ;
  n_orig = orig_sys->varcnt ;
  m_orig = orig_sys->concnt ;
  m = dy_sys->concnt ;

  x = NULL ;
  if (m < m_orig)
  { dy_colPrimals(orig_lp,&x) ; }

/*
  Do we need vectors? Do the necessary setup.
*/
  if (*p_xB != NULL)
  { xB = *p_xB ;
    memset(xB,0,(m_orig+1)*sizeof(double)) ; }
  else
  { xB = (double *) CALLOC((m_orig+1),sizeof(double)) ; }
  if (*p_indB != NULL)
  { indB = *p_indB ;
    memset(indB,0,(m_orig+1)*sizeof(int)) ; }
  else
  { indB = (int *) CALLOC((m_orig+1),sizeof(int)) ; }
/*
  Walk the constraints of the original system. For each constraint that's
  active, we can obtain the value from dy_xbasic. For each inactive constraint,
  we need to calculate the value of the logical.

  Indices of logicals are recorded in indB as the negative of the constraint
  index.
*/
  for (i_orig = 1 ; i_orig <= m_orig ; i_orig++)
  { if (ACTIVE_CON(i_orig))
    { i = dy_origcons[i_orig] ;
      j = dy_basis[i] ;
      if (j <= m)
      { j_orig = dy_actcons[j] ; }
      else
      { j_orig = dy_actvars[j] ; }
      if (scaled == TRUE)
      { if (j <= m)
	{ xj = (1/rscale[j_orig])*dy_xbasic[i] ; }
	else
	{ xj = cscale[j_orig]*dy_xbasic[i] ; } }
      else
      { xj = dy_xbasic[i] ; }
      if (j <= m)
      { indB[i_orig] = -j_orig ; }
      else
      { indB[i_orig] = j_orig ; } }
    else
    { lhs = consys_dotrow(orig_sys,i_orig,x) ;
      xj = orig_sys->rhs[i_orig]-lhs ;
      indB[i_orig] = -i_orig ; }

    setcleanzero(xj,dy_tols->zero) ;
    xB[i_orig] = xj ; }

  if (x != NULL) FREE(x) ;

# ifndef DYLP_NDEBUG
  if (dy_opts->print.soln >= 3)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\txB =") ;
    v = 0 ;
    for (i_orig = 1 ; i_orig <= m_orig ; i_orig++)
    { if ((++v)%3 == 0)
      { v = 0 ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t   ") ; }
      j_orig = indB[i_orig] ;
      if (j_orig < 0)
      { j = n_orig-j_orig ; }
      else
      { j = j_orig ; }
      dyio_outfmt(dy_logchn,dy_gtxecho," (%d %g %s %d)",
		  i_orig,xB[i_orig],
		  consys_nme(orig_sys,'v',j,FALSE,NULL),j_orig) ; } }
# endif

/*
  That's it. Return the vectors.
*/
  *p_xB = xB ;
  *p_indB = indB ;

  return ; }
コード例 #22
0
ファイル: dytest_solutions.c プロジェクト: sednanref/tesis
int dytest_rowDuals (lpprob_struct *main_lp, lptols_struct *main_lptols,
		     lpopts_struct *main_lpopts)
/*
  This routine checks the dual variables returned by dy_rowDuals. It checks
  that y<i> = c<B>(inv(B))<i>. Columns of the basis inverse are obtained from
  the routine dy_betaj.

  Parameters:
    main_lp:	 the lp problem structure
    main_lptols: the lp tolerance structure
    main_lpopts: the lp options structure

  Returns: 0 if y = c<B>inv(B), error count otherwise.
*/

{ int i,j,k,m,n ;
  consys_struct *sys ;
  flags *status ;

  double *y ;

  double *cB ;
  int *basis2sys ;
  basisel_struct *basisVec ;
  int basisLen ;

  double *betai ;
  double cBdotbetai ;
  int errcnt ;

  char *rtnnme = "dytest_rowDuals" ;

/*
  Do a little initialisation. Mention that we've started.
*/
  sys = main_lp->consys ;
  m = sys->concnt ;
  n = sys->varcnt ;

# ifndef DYLP_NDEBUG
  if (main_lpopts->print.soln >= 1)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: checking y = c<B>inv(B) using %s (%d x %d).",
		rtnnme,sys->nme,m,n) ;
    if (main_lpopts->print.soln >= 2)
    { dyio_outfmt(dy_logchn,dy_gtxecho,
		  "  basis contains %d entries.\n",main_lp->basis->len) ; } }
# endif
/*
  Acquire the row duals and the status vector. For this check, we can use
  the min primal sign convention.
*/
  y = NULL ;
  dy_rowDuals(main_lp,&y,FALSE) ;
  status = main_lp->status ;
/*
  Make a vector c<B> of objective coefficients in basis order. This is
  considerably easier than creating a basis matrix (as is done for tableau
  testing). By construction, the basic variables for inactive constraints
  are the logicals, which have an objective coefficient of zero, and this
  is how cB and basis2sys are initialised. All that need be done for c<B>
  is to change the entries that are associated with architecturals. For the
  basis, we need to set all entries (logicals can be basic out of natural
  position). Recall that basic logicals are represented by negative indices.
*/
  cB = (double *) MALLOC((m+1)*sizeof(double)) ;
  basis2sys = (int *) MALLOC((m+1)*sizeof(int)) ;
  for (i = 1 ; i <= m ; i++)
  { cB[i] = 0.0 ;
    basis2sys[i] = -i ; }
  basisLen = main_lp->basis->len ;
  basisVec = main_lp->basis->el ;
  for (k = 1 ; k <= basisLen ; k++)
  { i = basisVec[k].cndx ;
    j = basisVec[k].vndx ;
    if (j > 0)
    { cB[i] = sys->obj[j] ;
      basis2sys[i] = j ; }
    else
    { basis2sys[i] = j ; } }
# ifndef DYLP_NDEBUG
  if (main_lpopts->print.soln >= 5)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\tc<B> =") ;
    k = 0 ;
    for (i = 1 ; i <= m ; i++)
    { if (cB[i] != 0)
      { if ((++k)%4 == 0)
	{ k = 0 ;
	  dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t      ") ; }
	j = basis2sys[i] ;
	dyio_outfmt(dy_logchn,dy_gtxecho," (%d %g  %s %d)",
		    i,cB[i],consys_nme(sys,'v',j,FALSE,NULL),j) ; } } }
#   endif
/*
  Now step through the rows (equivalently, walk the basis) and see if
  y<i> = c<B>beta<j>, where beta<j> is the column of inv(B) such that
  x<j> is basic in pos'n i.
*/
  errcnt = 0 ;
  betai = NULL ;
  for (i = 1 ; i <= m ; i++)
  { j = basis2sys[i] ;
    if (dy_betaj(main_lp,j,&betai) == FALSE)
    { errcnt++ ;
      if (j < 0)
      { j = n-j ; }
      errmsg(952,rtnnme,sys->nme,"column",i,"variable",
	     consys_nme(sys,'v',j,FALSE,NULL),j-n) ;
      continue ; }
    cBdotbetai = 0 ;
    for (k = 1 ; k <= m ; k++)
    { 
      /*
         dyio_outfmt(dy_logchn,dy_gtxecho,
    		  "\n %s (%d) %g * %g",
		  consys_nme(sys,'c',k,FALSE,NULL),k,cB[k],betai[k]) ;
      */
      cBdotbetai += cB[k]*betai[k] ; }
    if (fabs(cBdotbetai-y[i]) > main_lptols->cost)
    { errcnt++ ;
      if (j < 0)
      { j = n-j ; }
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n  ERROR: pos'n %d %s (%d) c<B> dot beta<j> = %g; ",
		    i,consys_nme(sys,'v',j,FALSE,NULL),j-n,cBdotbetai) ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"expected %g; err %g, tol %g.",
		    y[i],(cBdotbetai-y[i]),main_lptols->zero) ; } }
/*
  Free up space and report the result.
*/
  if (cB != NULL) FREE(cB) ;
  if (basis2sys != NULL) FREE(basis2sys) ;
  if (betai != NULL) FREE(betai) ;
  if (y != NULL) FREE(y) ;

  if (errcnt != 0)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: found %d errors testing y = c<B>inv(B).\n",
		rtnnme,errcnt) ; }
  else
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n%s: pass y = c<B>inv(B).\n",rtnnme) ; }

  return (errcnt) ; }
コード例 #23
0
ファイル: dy_solutions.c プロジェクト: sednanref/tesis
void dy_colStatus (lpprob_struct *orig_lp, flags **p_colstat)

/*
  This routine returns the status of the primal architectural variables, in
  column order for the original system. The routine reports out the full set of
  dylp status codes.

  Parameters:
    orig_lp:	the original lp problem
    p_colstat:	(i) vector to hold the status of the primal architectural
		    variables; if NULL, a vector of appropriate size will
		    be allocated
		(o) status of the primal architectural variables, in the
		    original system frame of reference

  Returns: undefined
*/

{ int j,j_orig,n_orig ;
  flags statj ;

  consys_struct *orig_sys ;
  flags *colstat ;

# ifndef DYLP_NDEBUG
  int v ;
# endif
# ifdef DYLP_PARANOIA
  char *rtnnme = "dy_colStatus" ;

  if (dy_std_paranoia(orig_lp,rtnnme) == FALSE)
  { return ; }
  if (p_colstat == NULL)
  { errmsg(2,rtnnme,"colstat") ;
    return ; }
# endif

  orig_sys = orig_lp->consys ;
  n_orig = orig_sys->varcnt ;
/*
  Do we need a vector?
*/
  if (*p_colstat != NULL)
  { colstat = *p_colstat ;
    memset(colstat,0,(n_orig+1)*sizeof(flags)) ; }
  else
  { colstat = (flags *) CALLOC((n_orig+1),sizeof(flags)) ; }
/*
  Walk the columns of the original system. For active variables, copy the
  status from dy_status. For inactive variables, we acquire it from
  dy_origvars.
*/
  for (j_orig = 1 ; j_orig <= n_orig ; j_orig++)
  { if (ACTIVE_VAR(j_orig))
    { j = dy_origvars[j_orig] ;
      statj = dy_status[j] ; }
    else
    { statj = (flags)(-dy_origvars[j_orig]) ; }
    colstat[j_orig] = statj ; }

# ifndef DYLP_NDEBUG
  if (dy_opts->print.soln >= 3)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\tcolstat =") ;
    v = 0 ;
    for (j_orig = 1 ; j_orig <= n_orig ; j_orig++)
    { if ((++v)%3 == 0)
      { v = 0 ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t   ") ; }
      dyio_outfmt(dy_logchn,dy_gtxecho," (%s %d %s)",
		  consys_nme(orig_sys,'v',j_orig,FALSE,NULL),j_orig,
		  dy_prtvstat(colstat[j_orig])) ; } }
# endif

/*
  That's it. Return the vector.
*/
  *p_colstat = colstat ;

  return ; }
コード例 #24
0
ファイル: dytest_solutions.c プロジェクト: sednanref/tesis
int dytest_allDuals (lpprob_struct *main_lp, lptols_struct *main_lptols,
		     lpopts_struct *main_lpopts)
/*
  This routine uses the dual variables returned by dy_rowDuals and
  dy_colDuals and checks that yA >= (-c) (row duals only) and y'A' = (-c),
  where y' is both row and column duals and A' is A, expanded as needed with
  coefficients to add explicit bound constraints for nonbasic architecturals.

  As with so many things involving faking dual simplex on the primal
  constraint system with implicit bounds, we have to be a bit careful when
  working with the duals corresponding to nonbasic primal variables. Consider
  a primal variable x<j> NBUB. The reduced cost cbar<j> will be negative at
  optimality in dylp's min primal world. This is not correct for the sign
  convention of the true dual problem, where all duals are positive, so it's
  negated when we ask for the true dual sign convention. But then only a
  little thought reveals that we're considering yA + y<j> = (-c), and if y<j>
  >= 0 it's clear that yA <= (-c). So we have to invert the sense of that
  test when processing a column with an NBUB primal. Since the sign of the
  reduced cost for an NBFX variable can go either way, no test is possible
  using only the row duals.

  Parameters:
    main_lp:	 the lp problem structure
    main_lptols: the lp tolerance structure
    main_lpopts: the lp options structure

  Returns: 0 if yA = c, error count otherwise.
*/

{ int i,j,k,m,n ;
  consys_struct *sys ;
  double *obj ;

  double *y,*cbar ;
  double ydotaj,cj,cbarj ;

  flags *status ;
  flags statj ;

  int errcnt ;

  char *rtnnme = "dytest_allDuals" ;

/*
  Do a little initialisation. Mention that we've started.
*/
  sys = main_lp->consys ;
  m = sys->concnt ;
  n = sys->varcnt ;
  obj = sys->obj ;

# ifndef DYLP_NDEBUG
  if (main_lpopts->print.soln >= 1)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: checking yA = c using %s (%d x %d).",
		rtnnme,sys->nme,m,n) ; }
# endif
/*
  Acquire the row and column duals and column status. Go with the sign
  convention that matches the true dual problem.
*/
  y = NULL ;
  dy_rowDuals(main_lp,&y,TRUE) ;
  cbar = NULL ;
  dy_colDuals(main_lp,&cbar,TRUE) ;
  status = NULL ;
  dy_colStatus(main_lp,&status) ;
/*
  Open a loop to walk the columns. First check that yA >= (-c) for a column
  with an NBLB primal variable, yA <= (-c) for a column with an NBUB primal
  variable. For an NBFX variable, the dual could go either way, so we can't
  check.
*/
  errcnt = 0 ;
  for (j = 1 ; j <= n ; j++)
  { statj = status[j] ;
    cj = -obj[j] ;
    ydotaj = consys_dotcol(sys,j,y) ;
    if ((flgon(statj,vstatNBLB) && ydotaj-cj < -main_lptols->cost) ||
	(flgon(statj,vstatNBUB) && ydotaj-cj > main_lptols->cost))
    { errcnt++ ;
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n  ERROR: %s (%d) y dot a<j> = %g; ",
		    consys_nme(sys,'v',j,FALSE,NULL),j,ydotaj) ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"expected %s %g; err %g, tol %g.",
		    (flgon(statj,vstatNBUB)?"<=":">="),
		    cj,ydotaj-cj,main_lptols->cost) ; }
/*
  Now add any contribution due to an architectural at bound. After this we
  should have equality. For an upper bound, we have x<j> <= u<j>.
  For a lower bound, it's -x<j> <= -l<j>. For a fixed variable, it's an
  equality x<j> = u<j>, so lump NBFX with NBUB.
*/
    if (flgon(statj,vstatNONBASIC))
    { cbarj = cbar[j] ;
      switch (statj)
      { case vstatNBLB:
	{ ydotaj -= cbarj ;
	  break ; }
	case vstatNBUB:
	case vstatNBFX:
	{ ydotaj += cbarj ;
	  break ; }
	default:
	{ errmsg(1,rtnnme,__LINE__) ;
	  errcnt += 10000 ;
	  ydotaj = quiet_nan(42.0L) ;
	  break ; } } }
    if (fabs(ydotaj-cj) > main_lptols->cost)
    { errcnt++ ;
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n  ERROR: %s (%d) y dot a<j> = %g; ",
		    consys_nme(sys,'v',j,FALSE,NULL),j,ydotaj) ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"expected %g; err %g, tol %g.",
		    cj,fabs(ydotaj-cj),main_lptols->cost) ; } }
/*
  Free up space and report the result.
*/
  if (y != NULL) FREE(y) ;
  if (cbar != NULL) FREE(cbar) ;
  if (status != NULL) FREE(status) ;

  if (errcnt != 0)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: found %d errors testing yA = c.\n",
		rtnnme,errcnt) ; }
  else
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n%s: pass yA = c.\n",rtnnme) ; }

  return (errcnt) ; }
コード例 #25
0
ファイル: dy_hotstart.c プロジェクト: coin-or/DyLP
static bool process_inactive (lpprob_struct *orig_lp, int oxkndx)

/*
  This routine handles the data structure updates for an inactive variable
  x<k>.  We need to have a look at the bounds l<k> and u<k>, and perhaps
  update the status kept in dy_origvars. We need to add the contribution
  c<k>l<k> or c<k>u<k> to the objective function. Finally, if we've reloaded
  b & blow due to a bound or rhs change, we need to walk the column a<k>
  and adjust b<i> (and perhaps blow<i>) for each nonzero a<ik> in the active
  system.

  Parameters:
    orig_lp:	the original lp problem
    oxkndx:	index of x<k> in orig_sys
  
  Returns: TRUE if the update is made without incident, FALSE otherwise.
*/

{ int oaindx,aindx,ndx ;
  double xk,lk,uk,ck ;
  pkvec_struct *ak ;
  pkcoeff_struct *aik ;
  consys_struct *orig_sys ;
  flags xkstatus ;
  const char *rtnnme = "process_inactive" ;

  orig_sys = orig_lp->consys ;

  xkstatus = getflg(orig_lp->status[oxkndx],vstatSTATUS) ;

# ifdef DYLP_PARANOIA
/*
  Any inactive variable should be nonbasic, and the paranoid check is looking
  to make sure of this.
*/
  if (!VALID_STATUS(xkstatus))
  { errmsg(300,rtnnme,(int) xkstatus,
	   consys_nme(orig_sys,'v',oxkndx,FALSE,NULL),oxkndx) ;
    return (FALSE) ; }
  if (flgoff(xkstatus,vstatNONBASIC|vstatNBFR))
  { errmsg(433,rtnnme,
	   dy_sys->nme,dy_prtlpphase(dy_lp->phase,TRUE),dy_lp->tot.iters,
	   "inactive",consys_nme(orig_sys,'v',oxkndx,TRUE,NULL),oxkndx,
	   dy_prtvstat(xkstatus)) ;
    return (FALSE) ; }
# endif
/*
  The bounds can change arbitrarily, and the client may not be maintaining
  the status vector, but we're limited in what we can do --- bounds and status
  are our only clues to the value of an inactive variable. (Contrast with the
  equivalent section in process_active.)
*/
  lk = orig_sys->vlb[oxkndx] ;
  uk = orig_sys->vub[oxkndx] ;
  ck = orig_sys->obj[oxkndx] ;
/*
  Start with the case that both bounds are finite. Use a previous status of
  NBLB or NBUB. Otherwise, guess from the sign of the objective coefficient.
  `Dirty' fixed variables are marked as unloadable.
*/
  if (lk > -dy_tols->inf && uk < dy_tols->inf)
  { if (atbnd(lk,uk) && lk != uk)
    { if (flgon(xkstatus,vstatNBLB|vstatNBUB))
      { setflg(xkstatus,vstatNOLOAD) ; }
      else
      { if (ck < 0)
	{ xkstatus = vstatNBUB|vstatNOLOAD ; }
	else
	{ xkstatus = vstatNBLB|vstatNOLOAD ; } }
#     ifndef DYLP_NDEBUG
      if (dy_opts->print.setup >= 3)
      { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\tDirty fixed variable %s (%d)",
		    consys_nme(orig_sys,'v',oxkndx,0,0),oxkndx) ;
	dyio_outfmt(dy_logchn,dy_gtxecho,
		    " assigned status %s.",dy_prtvstat(xkstatus)) ;
	dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n\t  original lb = %g, ub = %g, diff = %g, tol = %g",
		    lk,uk,uk-lk,dy_tols->pfeas) ; }
#     endif
    }
    else
    if (lk == uk)
    { xkstatus = vstatNBFX|vstatNOLOAD ; }
    else
    if (flgon(xkstatus,vstatNBLB|vstatNBUB))
    { xkstatus = orig_lp->status[oxkndx] ; }
    else
    { if (ck < 0)
      { xkstatus = vstatNBUB ; }
      else
      { xkstatus = vstatNBLB ; } } }
/*
  Variables with one bound, or no bounds. No choices here.
*/
  else
  if (lk > -dy_tols->inf)
  { xkstatus = vstatNBLB ; }
  else
  if (uk < dy_tols->inf)
  { xkstatus = vstatNBUB ; }
  else
  { xkstatus = vstatNBFR ; }
/*
  Determine the variable's value and set up the status entries.

  The default case in the switch below should never execute, but it serves
  for paranoia and lets gcc conclude xk will always have a value.

  Consider whether it's really a good idea to change orig_lp->status.
*/
  switch (getflg(xkstatus,vstatSTATUS))
  { case vstatNBLB:
    case vstatNBFX:
    { xk = lk ;
      break ; }
    case vstatNBUB:
    { xk = uk ;
      break ; }
    case vstatNBFR:
    { xk = 0 ;
      break ; }
    default:
    { xk = 0 ;
      errmsg(1,rtnnme,__LINE__) ;
      return (FALSE) ; } }
  orig_lp->status[oxkndx] = xkstatus ;
  dy_origvars[oxkndx] = -((int) xkstatus) ;
/*
  Note any contribution to the objective and constraint rhs & rhslow values.
*/
  dy_lp->inactzcorr += xk*orig_sys->obj[oxkndx] ;
  if (flgon(orig_lp->ctlopts,lpctlRHSCHG|lpctlLBNDCHG|lpctlUBNDCHG))
  { ak = NULL ;
    if (consys_getcol_pk(orig_sys,oxkndx,&ak) == FALSE)
    { errmsg(122,rtnnme,orig_sys->nme,"variable",
	     consys_nme(orig_sys,'v',oxkndx,TRUE,NULL),oxkndx) ;
      if (ak != NULL) pkvec_free(ak) ;
      return (FALSE) ; }
    for (ndx = 0, aik = &ak->coeffs[0] ; ndx < ak->cnt ; ndx++, aik++)
    { oaindx = aik->ndx ;
      if (ACTIVE_CON(oaindx))
      { aindx = dy_origcons[oaindx] ;
        dy_sys->rhs[aindx] -= aik->val*xk ;
	if (dy_sys->ctyp[aindx] == contypRNG)
	  dy_sys->rhslow[aindx] -= aik->val*xk ; } }
    pkvec_free(ak) ; }
/*
  And we're done. Print some information and return.
*/

# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 4)
  { dyio_outfmt(dy_logchn,dy_gtxecho,"\n\t  %s (%d) %s inactive with value ",
	        consys_nme(orig_sys,'v',oxkndx,FALSE,NULL),oxkndx,
	        dy_prtvstat(xkstatus)) ;
    switch (getflg(xkstatus,vstatSTATUS))
    { case vstatNBFX:
      case vstatNBLB:
      case vstatNBUB:
      case vstatNBFR:
      { dyio_outfmt(dy_logchn,dy_gtxecho,"%g.",xk) ;
	break ; }
      default:
      { dyio_outfmt(dy_logchn,dy_gtxecho,"??.") ;
	break ; } } }
# endif

return (TRUE) ; }
コード例 #26
0
ファイル: dytest_solutions.c プロジェクト: sednanref/tesis
int dytest_colPrimals (lpprob_struct *main_lp, lptols_struct *main_lptols,
		       lpopts_struct *main_lpopts)
/*
  This routine checks the values of the primal architectural variables
  returned by dy_colPrimals.
  
  For basic variables x<B>, the routine checks
    x<B> =  inv(B)b - inv(B)Nx<N>
  To do this, the routine accumulates the values of the basic variables
  during the column scan. When the current column is basic in pos'n i, the
  routine calculates dot(beta<i>,b) and adds it to the total. When the current
  column is nonbasic, the routine calculates abar<j>x<j> and subtracts it
  from the total. Just to make things really annoying, we have to account for
  nonbasic bounded slacks due to range constraints tight at their lower bound
  (which makes the slack nonbasic at its upper bound).

  For a nonbasic variable, the routine checks the value of x<j> against the
  bound specified by the status of x<j>.

  Parameters:
    main_lp:     the lp problem structure
    main_lptols: the lp tolerance structure
    main_lpopts: the lp options structure

  Returns: 0 if the values check out, error count otherwise.
*/

{ int i,i_bpos,j,k,m,n ;
  flags statj,stati ;
  double xj,lbj,ubj,betaidotb ;

  consys_struct *sys ;
  flags *status,*logstatus ;
  double *rhs,*rhslow,*vlb,*vub,*betai,*xB,*abarj ;
  contyp_enum *ctyp ;
  basisel_struct *basis ;

  double *x ;

  int berrs,nberrs ;
  bool staterr ;

  char *rtnnme = "dytest_colPrimals" ;

/*
  Do a little initialisation. Mention that we've started.
*/
  sys = main_lp->consys ;
  m = sys->concnt ;
  n = sys->varcnt ;

# ifndef DYLP_NDEBUG
  if (main_lpopts->print.soln >= 1)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
	  "\n%s: checking primal architectural variables using %s (%d x %d).",
	  rtnnme,sys->nme,m,n) ; }
# endif
/*
  Acquire the variable bound and status vectors, the constraint type, rhs,
  and rhslow vectors, the basis vector, and the values of the primal
  architectural variables. Allocate a vector to accumulate x<B>
*/
  x = NULL ;
  dy_colPrimals(main_lp,&x) ;
  basis = main_lp->basis->el ;
  status = main_lp->status ;
  ctyp = sys->ctyp ;
  rhs = sys->rhs ;
  rhslow = sys->rhslow ;
  vlb = sys->vlb ;
  vub = sys->vub ;
  xB = (double *) CALLOC((m+1),sizeof(double)) ;
/*
  Now step through the columns checking the values in x. For a variable basic
  in pos'n i, add dot(beta<i>,b) to the running total for the basic variable.
  
  For a nonbasic variable, confirm that the value, bound, and status agree.
  Then subtract abar<j>x<j> from x<B> if x<j> is at a nonzero bound.

  The only nonbasic status code not explicitly listed is SB (superbasic). This
  really should never appear. The only legitimate reason is that dylp patched
  the basis in primal phase II and then discovered the problem to be unbounded
  before the SB variable could be pivoted back into the basis. This is
  sufficiently exotic to deserve a message.
*/
  berrs = 0 ;
  nberrs = 0 ;
  betai = NULL ;
  abarj = NULL ;
  for (j = 1 ; j <= n ; j++)
  { statj = status[j] ;
    xj = x[j] ;
    if (((int) statj) < 0)
    { k = -((int) statj) ;
      i_bpos = basis[k].cndx ;
      if (dy_betai(main_lp,i_bpos,&betai) == FALSE)
      { berrs++ ;
	errmsg(952,rtnnme,sys->nme,"row",i_bpos,"variable",
	       consys_nme(sys,'v',j,FALSE,NULL),j) ;
	continue ; }
      betaidotb = 0 ;
      for (i = 1 ; i <= m ; i++)
      { betaidotb += betai[i]*rhs[i] ; }
      xB[i_bpos] += betaidotb ; }
    else
    { staterr = FALSE ;
      lbj = vlb[j] ;
      ubj = vub[j] ;
      statj = getflg(statj,vstatSTATUS) ;
      switch (statj)
      { case vstatNBLB:
	{ if (fabs(xj-lbj) > main_lptols->zero)
	  { staterr = TRUE ;
	    betaidotb = lbj ; }
	  break ; }
	case vstatNBUB:
	{ if (fabs(xj-ubj) > main_lptols->zero)
	  { staterr = TRUE ;
	    betaidotb = ubj ; }
	  break ; }
	case vstatNBFX:
	{ if (fabs(xj-lbj) > main_lptols->zero)
	  { staterr = TRUE ;
	    betaidotb = lbj ; }
	  break ; }
	case vstatNBFR:
	{ if (fabs(xj) > main_lptols->zero)
	  { staterr = TRUE ;
	    betaidotb = 0.0 ; }
	  break ; }
	default:
	{ staterr = TRUE ;
	  betaidotb = quiet_nan(42.0L) ;
	  break ; } }
    if (staterr == TRUE)
    { nberrs++ ;
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\nERROR: %s col %s (%d) = %g; expected %g;",
		  dy_prtvstat(statj),consys_nme(sys,'v',j,FALSE,NULL),j,
		  xj,betaidotb) ;
      dyio_outfmt(dy_logchn,dy_gtxecho," error %g, tol %g.",
		  fabs(xj-betaidotb),main_lptols->zero) ;
      continue ; }
    if (xj == 0.0) continue ;
    if (dy_abarj(main_lp,j,&abarj) == FALSE)
    { nberrs++ ;
      errmsg(953,rtnnme,sys->nme,"ftran'd","column",
	     consys_nme(sys,'v',j,FALSE,NULL),j) ;
      continue ; }
    for (k = 1 ; k <= m ; k++)
    { xB[k] -= abarj[k]*xj ; } } }
/*
  But wait! We're not quite done. We need to account for bounded slacks
  associated with range constraints. If the constraint is tight at its lower
  bound, the slack is nonbasic at its upper bound.
*/
  logstatus = NULL ;
  dy_logStatus(main_lp,&logstatus) ;
  for (i = 1 ; i <= m ; i++)
  { stati = getflg(logstatus[i],vstatSTATUS) ;
    if (ctyp[i] == contypRNG && stati == vstatNBUB)
    { xj = rhs[i]-rhslow[i] ;
      if (dy_abarj(main_lp,-i,&abarj) == FALSE)
      { nberrs++ ;
	errmsg(953,rtnnme,sys->nme,"ftran'd","column",
	       consys_nme(sys,'v',n+i,FALSE,NULL),i) ;
	continue ; }
      for (k = 1 ; k <= m ; k++)
      { xB[k] -= abarj[k]*xj ; } } }
/*
  Scan the variables one more time and check the values of the basic variables.
*/
  for (j = 1 ; j <= n ; j++)
  { statj = status[j] ;
    xj = x[j] ;
    if (((int) statj) < 0)
    { k = -((int) statj) ;
      i_bpos = basis[k].cndx ;
      if (fabs(xj-xB[i_bpos]) > main_lptols->zero)
      { berrs++ ;
	dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\nERROR: basis pos'n %d %s (%d) = %g; expected %g;",
		    i_bpos,consys_nme(sys,'v',j,FALSE,NULL),j,xj,xB[i_bpos]) ;
	dyio_outfmt(dy_logchn,dy_gtxecho," error %g, tol %g.",
		    fabs(xj-xB[i_bpos]),main_lptols->zero) ; } } }
/*
  Free up space and report the result.
*/
  if (logstatus != NULL) FREE(logstatus) ;
  if (abarj != NULL) FREE(abarj) ;
  if (xB != NULL) FREE(xB) ;
  if (betai != NULL) FREE(betai) ;
  if (x != NULL) FREE(x) ;

  if ((berrs+nberrs) != 0)
  { if (berrs != 0)
    { dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n%s: found %d errors testing x<B> = inv(B)b.\n",
		  rtnnme,berrs) ; }
    if (nberrs != 0)
    { dyio_outfmt(dy_logchn,dy_gtxecho,
	      "\n%s: found %d errors testing x<N> against bounds & status.\n",
	      rtnnme,nberrs) ; } }
  else
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: pass test of primal architectural variable values.\n",
		rtnnme) ; }

  return (berrs+nberrs) ; }
コード例 #27
0
ファイル: dy_hotstart.c プロジェクト: coin-or/DyLP
dyret_enum dy_hotstart (lpprob_struct *orig_lp)

/*
  This routine is responsible for handling a hot start. The assumption is
  that all data structures are in place, and that the user is allowed to change
  the bounds on variables and any of the rhs and objective coefficients. See
  the comments at the head of the file.

  Changes to the rhs and bounds are handled first. We reinstall the rhs
  array, then scan the variables, updating bounds and status and making the
  rhs corrections required for inactive variables.  If the bounds or rhs
  change, we need new primals. After we calculate new primals, we'll need to
  scan the basic variables and make sure their final status is correct.

  If the objective or bounds change, we need to recalculate the contribution
  to the objective from inactive variables. If the objective changes, we need
  new duals.  (It's also true that if the objective changes, we need new
  reduced costs, but that's handled in commonstart.)

  The most likely situation is that we haven't pivoted since refactoring as
  part of the preoptimality sequence, so we shouldn't need to refactor here.
  Instead, we leave it to dy_duenna to pick this up with the next pivot, as
  well as any possible accuracy check.

  Once all the changes have been incorporated, calculate primals and duals to
  determine primal and dual feasibility, and select the appropriate simplex
  phase in dy_lp->simplex.next.

  Parameters:
    orig_lp:	The original lp problem structure

  Returns: dyrOK if the setup completes without error, dyrINV or dyrFATAL
	   otherwise.
*/

{ int oxkndx,xkndx,oaindx,aindx ;
  double *ogvlb,*dyvlb,*ogvub,*dyvub,*ogobj,*dyobj,*dyrhs,*ogrhs ;
  double lbj,ubj ;
  consys_struct *orig_sys ;
  flags *ogstatus,calcflgs,statk ;
  dyret_enum retval ;
  lpret_enum lpret ;
  dyphase_enum phase ;
  const char *rtnnme = "dy_hotstart" ;

  /* dy_scaling.c */
  extern void dy_refreshlclsystem(flags what) ;

  /* dy_force.c */
  extern dyphase_enum dy_forceFull(consys_struct *orig_sys) ;

/*
  It could happen that there are no changes, in which case there's no point
  in going through the motions.
*/
  if (flgoff(orig_lp->ctlopts,
	     lpctlLBNDCHG|lpctlUBNDCHG|lpctlOBJCHG|lpctlRHSCHG))
  {
#   ifndef DYLP_NDEBUG
    if (dy_opts->print.crash >= 1)
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\n  no data structure changes at hot start.") ;
#   endif
    hot_updateMiscState(lpINV) ;
    return (dyrOK) ; }
/*
  But it's far more likely there are changes, and we need to get on with them.
*/
# ifndef DYLP_NDEBUG
  if (dy_opts->print.crash >= 1)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n  updating data structures at hot start ...") ;
    if (dy_opts->print.crash >= 2)
    { dyio_outfmt(dy_logchn,dy_gtxecho,"\n    scanning changes to") ;
      if (flgon(orig_lp->ctlopts,lpctlRHSCHG))
	dyio_outfmt(dy_logchn,dy_gtxecho," rhs") ;
      if (flgon(orig_lp->ctlopts,lpctlLBNDCHG))
	dyio_outfmt(dy_logchn,dy_gtxecho," vlb") ;
      if (flgon(orig_lp->ctlopts,lpctlUBNDCHG))
	dyio_outfmt(dy_logchn,dy_gtxecho," vub") ;
      if (flgon(orig_lp->ctlopts,lpctlOBJCHG))
	dyio_outfmt(dy_logchn,dy_gtxecho," obj") ;
      dyio_outfmt(dy_logchn,dy_gtxecho," ...") ; } }
#   endif

/*
  Transfer any changes from the client's system to the scaled local copy, if
  it exists. Then set up convenient handles for the various vectors.
*/
  dy_refreshlclsystem(orig_lp->ctlopts) ;

  orig_sys = orig_lp->consys ;
  dyrhs = dy_sys->rhs ;
  ogrhs = orig_sys->rhs ;
  ogvlb = orig_sys->vlb ;
  dyvlb = dy_sys->vlb ;
  ogvub = orig_sys->vub ;
  dyvub = dy_sys->vub ;
  ogobj = orig_sys->obj ;
  dyobj = dy_sys->obj ;
  ogstatus = orig_lp->status ;
/*
  If any of the rhs or bounds have been changed, we need to reinstall the rhs
  and bounds.  Begin by scanning the orig_sys rhs array, updating the dy_sys
  entries for the active constraints. If a range constraint comes by, we also
  need to set the upper bound of the associated logical.
*/
  if (flgon(orig_lp->ctlopts,lpctlLBNDCHG|lpctlUBNDCHG|lpctlRHSCHG))
  { 
    for (aindx = 1 ; aindx <= dy_sys->concnt ; aindx++)
    { oaindx = dy_actcons[aindx] ;
      if (oaindx > 0)
      { dyrhs[aindx] = ogrhs[oaindx] ;
	if (dy_sys->ctyp[aindx] == contypRNG)
	{ dy_sys->rhslow[aindx] = orig_sys->rhslow[oaindx] ;
	  dyvub[aindx] = dyrhs[aindx]-dy_sys->rhslow[aindx] ; } } } }
/*
  We need to scan the columns no matter what changed.  Objective coefficient
  changes are just copied into the active system as needed. The real action
  is updating bounds and dealing with the side effects of bounded variables.
    * Recalculate the contribution to inactzcorr for each inactive variable.
    * Update dy_sys->vlb, dy_sys->vub, and dy_sys->obj for each active
      variable.
    * Update dy_status for each active variable.
    * Update dy_x for each nonbasic active variable.
    * Update loadable/unloadable accounting.
*/
  dy_lp->inactzcorr = 0 ;
  lpret = lpINV ;
  dy_lp->sys.vars.loadable = 0 ;
  dy_lp->sys.vars.unloadable = 0 ;
  for (oxkndx = 1 ; oxkndx <= orig_sys->varcnt ; oxkndx++)
  { xkndx = dy_origvars[oxkndx] ;
    lbj = ogvlb[oxkndx] ;
    ubj = ogvub[oxkndx] ;
    if (ogvlb[oxkndx] > ogvub[oxkndx])
    { lpret = lpINFEAS ;
#     ifndef DYLP_NDEBUG
      if (dy_opts->print.setup >= 1)
      { dyio_outfmt(dy_logchn,dy_gtxecho,
		 "\n\tTrivial infeasibility for %s (%d), lb = %g > ub = %g.",
		 consys_nme(orig_sys,'v',oxkndx,0,0),oxkndx,
		 ogvlb[oxkndx],ogvub[oxkndx]) ; }
#     endif
    }
/*
  Inactive variables: update the status in dy_origvars and calculate the
  contribution to inactzcorr. If we've reloaded rhs and rhslow, correct
  them to account for the value of the variable.

  Active variables: touch up bounds for fixed variables, update vlb, vub,
  and obj arrays for dy_sys, update dy_status, and update dy_x for nonbasic
  variables.
*/
    if (xkndx < 0)
    { if (process_inactive(orig_lp,oxkndx) == FALSE) return (dyrFATAL) ;
      statk = (flags) -dy_origvars[oxkndx] ;
      if (flgon(statk,vstatNOLOAD))
      { dy_lp->sys.vars.unloadable++ ; }
      else
      { dy_lp->sys.vars.loadable++ ; } }
    else
    { process_active(orig_lp,oxkndx) ; } }
/*
  Now, what do we need? Calculate primal values first.  If we calculate new
  primal variables, we need to reset the status of the basic variables, which
  means we need to do a quick scan of the logicals to reset their status.
  Arguably this is not necessary if only the objective changed, but overall
  it's a good investment of our time.
*/
  if (dy_calcprimals() == FALSE)
  { errmsg(316,rtnnme,dy_sys->nme) ;
    return (dyrFATAL) ; }
  for (xkndx = 1 ; xkndx <= dy_sys->concnt ; xkndx++)
  { if (dy_var2basis[xkndx] != 0)
    { if (dyvub[xkndx] == dyvlb[xkndx])
	dy_status[xkndx] = vstatBFX ;
      else
	dy_status[xkndx] = vstatB ; } }
  dy_setfinalstatus() ;
/*
  Is the phase I objective installed? If so, remove it. This hurts a bit,
  particularly if we ultimately end up targetting primal phase I as the
  starting simplex, but it's the only way to test for a dual feasible start.
  And if we have dual feasibility, it's a big win.
*/
  if (dy_lp->p1obj.installed == TRUE)
  { if (dy_swapobjs(dyPRIMAL2) == FALSE)
    { errmsg(318,rtnnme,dy_sys->nme,dy_prtlpphase(dy_lp->phase,TRUE),
	     dy_lp->tot.iters,"remove") ;
      return (dyrFATAL) ; } }
/*
  Calculate duals and reduced costs and see if we're primal or dual feasible.
  Calculate the objective just for kicks.
*/
  dy_calcduals() ;
  if (dy_calccbar() == FALSE)
  { errmsg(384,rtnnme,dy_sys->nme,
	   dy_prtlpphase(dy_lp->phase,TRUE),dy_lp->tot.iters) ;
    return (dyrFATAL) ; }
  dy_lp->z = dy_calcobj() ;

  calcflgs = ladPRIMFEAS|ladPFQUIET|ladDUALFEAS|ladDFQUIET ;
  retval = dy_accchk(&calcflgs) ;
  if (retval != dyrOK)
  { errmsg(304,rtnnme,dy_sys->nme,
	   dy_prtlpphase(dy_lp->phase,TRUE),dy_lp->tot.iters) ;
    return (retval) ; }
  if (flgoff(calcflgs,ladPRIMFEAS))
  { dy_lp->simplex.next = dyPRIMAL2 ; }
  else
  if (flgoff(calcflgs,ladDUALFEAS))
  { dy_lp->simplex.next = dyDUAL ; }
  else
  { dy_lp->simplex.next = dyPRIMAL1 ; }
/*
  Reset a few control variables and counts in dy_lp.
*/
  hot_updateMiscState(lpret) ;
/*
  And that should do it. Let's make a paranoid check or two, then we're
  off and running.
*/
# ifdef DYLP_PARANOIA
  if (dy_chkdysys(orig_sys) == FALSE) return (dyrFATAL) ;
# endif
/*
  Now, is the client forcing the full system on top of the hot start? If so,
  do it here. We're up and running at this point, so dy_forceFull can do its
  thing.

  Normally, dy_forceFull is called when we've failed at primal simplex with a
  partial system, then tried and failed to force dual feasibility. Make it
  look like this while we're working.  Reset phase to dyINIT and dy_lp->lpret
  to dyrINV when we're done so that dylp() sees the codes it expects.

  This is an exceptional activity, so I'm not going out of my way to do this
  in the most efficient manner. There really isn't a legitimate reason for
  this --- it's most likely careless coding on the part of the client, but we
  can cope without too much trouble.

  TODO (100817) I might want to rethink this, because I'm going to take the
  attitude that the OsiSimplex interface will force the full system from
  enableFactorization and enableSimplexInterface.
*/
  if (dy_opts->fullsys == TRUE &&
      (dy_lp->sys.cons.loadable > 0 || dy_lp->sys.vars.loadable > 0))
  {
#   ifndef DYLP_NDEBUG
    if (dy_opts->print.force >= 1)
    { dyio_outfmt(dy_logchn,dy_gtxecho,"\n  Forcing full system.") ; }
#   endif
    dy_lp->lpret = lpFORCEDUAL ;
    dy_lp->phase = dyFORCEFULL ;
    phase = dy_forceFull(orig_sys) ;
    if (phase == dyINV)
    { retval = dyrFATAL ; }
    else
    { dy_lp->lpret = lpINV ;
      dy_lp->phase = dyINIT ;
      retval = dyrOK ; } }
  else
  { retval = dyrOK ; }

  return (retval) ; }
コード例 #28
0
ファイル: dytest_solutions.c プロジェクト: sednanref/tesis
int dytest_rowPrimals (lpprob_struct *main_lp, lptols_struct *main_lptols,
		       lpopts_struct *main_lpopts)
/*
  This routine checks the ind<B> and x<B> vectors returned by dy_rowPrimals.
  It first cross-checks the basis, status and indB arrays, bailing out if the
  cross-checks fail.
  
  Next it checks the values of the basic variables, architectural and logical.

  For basic variables x<B>, the routine checks x<B> =  inv(B)b - inv(B)Nx<N>
    To do this, it first walks the rows of the constraint system and
    initialises x<B> with dot(beta<i>,b). Then it walks the columns and
    accumulates the contributions abar<j>x<j> from nonzero nonbasic
    variables.  Finally, it walks the rows again and subtracts the
    contributions from nonbasic bounded logicals (due to range constraints
    tight at the lower bound).

  Parameters:
    main_lp:     the lp problem structure
    main_lptols: the lp tolerance structure
    main_lpopts: the lp options structure

  Returns: 0 if the basic variables validate, error count otherwise.
*/

{ int i,j,k,m,n,i_basis ;
  flags statj,stati ;
  double xj,betaidotb,tol ;

  consys_struct *sys ;
  flags *status,*logstatus ;
  double *rhs,*rhslow,*vlb,*vub,*betai,*xBaccum,*abarj ;
  contyp_enum *ctyp ;
  basisel_struct *basis ;
  int basisLen ;

  double *xB ;
  int *indB ;

  int berrs,nberrs,inderrs ;

  char *rtnnme = "dytest_rowPrimals" ;

/*
  Do a little initialisation. Mention that we've started.
*/
  sys = main_lp->consys ;
  m = sys->concnt ;
  n = sys->varcnt ;

# ifndef DYLP_NDEBUG
  if (main_lpopts->print.soln >= 1)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
	  "\n%s: checking primal basic variables using %s (%d x %d).",
	  rtnnme,sys->nme,m,n) ; }
# endif
/*
  Acquire the variable bound and status vectors, the constraint type, rhs,
  and rhslow vectors, and the basis vector.
*/
  basisLen = main_lp->basis->len ;
  basis = main_lp->basis->el ;
  status = main_lp->status ;
  ctyp = sys->ctyp ;
  rhs = sys->rhs ;
  rhslow = sys->rhslow ;
  vlb = sys->vlb ;
  vub = sys->vub ;
/*
  Call dy_rowPrimals to acquire x<B> (values of basic variables) and ind<B>
  (indices of basic variables).
*/
  xB = NULL ;
  indB = NULL ;
  dy_rowPrimals(main_lp,&xB,&indB) ;
/*
  Validate ind<B>, status, and basis against each other, within the limits of
  each.

  IndB specifies basic variables in row order. Logicals are specified as the
  negative of the row. IndB contains an entry for every constraint. By
  construction, the basic variable for an inactive constraint should be the
  logical for the constraint.

  Basis has one entry for each active constraint. Each entry in basis
  specifies a constraint and a basic variable. Basic logicals are specified
  by the negative of the constraint index. Then for an active constraint i
  and a basis entry k such that basis[k].cndx == i, indB[i] == basis[k].vndx.

  Status only contains information on architecturals. A basic architectural
  is specified as the negative of its entry in the basis vector. Thus
  basis[-status[j]].vndx == j. 
*/
  inderrs = 0 ;
  for (i = 1 ; i <= m ; i++)
  { 
/*
  Scan the basis vector for an entry for this constraint. If it's not present,
  assume the constraint is inactive.
*/
    i_basis = -1 ;
    for (k = 1 ; k <= basisLen ; k++)
    { if (basis[k].cndx == i)
      { i_basis = k ;
	break ; } }
    j = indB[i] ;
/*
  Inactive constraints should specify the associated logical as the basic
  variable.
*/
    if (i_basis < 0)
    { if (j > 0)
      { inderrs++ ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"\nERROR: constraint %s (%d)",
		    consys_nme(sys,'c',i,FALSE,NULL),i) ;
	dyio_outfmt(dy_logchn,dy_gtxecho,
		    "; basis entry = %d; should specify a logical.",j) ; }
      else
      if (-j != i)
      { inderrs++ ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"\nERROR: basis[%d] (%s)",
		    i,consys_nme(sys,'c',i,FALSE,NULL)) ;
	dyio_outfmt(dy_logchn,dy_gtxecho," is %s (%d);",
		    consys_nme(sys,'c',n-j,FALSE,NULL),-j) ;
	dyio_outfmt(dy_logchn,dy_gtxecho," expected %s (%d).",
		    consys_nme(sys,'c',n+i,FALSE,NULL),i) ; } }
/*
  The constraint is active. We should have indB[i] = basis[i_basis].vndx. It
  takes way more work than it should to construct the error message.
*/
    else
    { k = basis[i_basis].vndx ;
      if (j != k)
      { inderrs++ ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"\nERROR: constraint %s (%d)",
		    consys_nme(sys,'c',i,FALSE,NULL),i) ;
	statj = (k < 0)?(n-k):(k) ;
	dyio_outfmt(dy_logchn,dy_gtxecho,
		    "; basis[%d] specifies %s (%d)",
		    i_basis,consys_nme(sys,'v',statj,FALSE,NULL),k) ;
	statj = (j < 0)?(n-j):(j) ;
	dyio_outfmt(dy_logchn,dy_gtxecho,
		    "; indB[%d] specifies %s (%d); they should agree.",
		    i,consys_nme(sys,'v',statj,FALSE,NULL),j) ; }
/*
  If the basic variable k is an architectural, status[k] should agree that it's
  basic and point to the basis vector entry.
*/
      if (k > 0)
      { statj = -((int) status[k]) ;
	if (i_basis != statj)
	{ inderrs++ ;
	  dyio_outfmt(dy_logchn,dy_gtxecho,"\nERROR: constraint %s (%d)",
		      consys_nme(sys,'c',i,FALSE,NULL),i) ;
	  dyio_outfmt(dy_logchn,dy_gtxecho,
		      "; status[%d] = %d but basis[%d].vndx = %d",
		      k,statj,i_basis,k) ;
	  dyio_outfmt(dy_logchn,dy_gtxecho,
		      "; they should point to each other.") ; } } } }
  if (inderrs > 0)
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: found %d errors cross-checking basis index vectors.\n",
		rtnnme,inderrs) ;
    dyio_outfmt(dy_logchn,dy_gtxecho,
		"\tTests of basic variable values not performed.\n") ;
    if (xB != NULL) FREE(xB) ;
    if (indB != NULL) FREE(indB) ;
    return (inderrs) ; }
/*
  Now we know the index arrays are correct and we can use them with
  confidence.  Step through the rows, placing the initial component
  dot(beta<i>,b) into each position.
*/
  xBaccum = (double *) CALLOC((m+1),sizeof(double)) ;
  berrs = 0 ;
  betai = NULL ;
  for (i = 1 ; i <= m ; i++)
  { if (dy_betai(main_lp,i,&betai) == FALSE)
    { berrs++ ;
      j = indB[i] ;
      if (j < 0)
      { statj = n-j ; }
      else
      { statj = j ; }
      errmsg(952,rtnnme,sys->nme,"row",i,"basic variable",
	     consys_nme(sys,'v',statj,FALSE,NULL),j) ;
      continue ; }
    betaidotb = 0 ;
    for (k = 1 ; k <= m ; k++)
    { betaidotb += betai[k]*rhs[k] ; }
    xBaccum[i] += betaidotb ; }
/*
  Now step through the columns. Subtract abar<j>x<j> from x<B> if x<j> is at
  a nonzero bound. Anything other than the enumerated status codes is
  extraordinary. vstatSB might be correct if dylp declared unboundedness
  immediately after refactoring in primal phase II, but that's such an unlikely
  coincidence it deserves attention. Anything else is outright wrong.
*/
  nberrs = 0 ;
  abarj = NULL ;
  for (j = 1 ; j <= n ; j++)
  { statj = status[j] ;
    if (((int) statj) < 0) continue ;
    statj = getflg(statj,vstatSTATUS) ;
    switch (statj)
    { case vstatNBLB:
      case vstatNBFX:
      { xj = vlb[j] ;
	break ; }
      case vstatNBUB:
      { xj = vub[j] ;
	break ; }
      case vstatNBFR:
      { xj = 0.0 ;
	break ; }
      default:
      { nberrs++ ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"\nERROR: constraint %s (%d)",
		    consys_nme(sys,'c',i,FALSE,NULL),i) ;
	dyio_outfmt(dy_logchn,dy_gtxecho,"; status of %s (%d) is %s.",
		    consys_nme(sys,'v',j,FALSE,NULL),j,dy_prtvstat(statj)) ;
	xj = 0.0 ;
	break ; } }
    if (xj == 0.0) continue ;
    if (dy_abarj(main_lp,j,&abarj) == FALSE)
    { nberrs++ ;
      errmsg(953,rtnnme,sys->nme,"ftran'd","column",
	     consys_nme(sys,'v',j,FALSE,NULL),j) ;
      continue ; }
    for (k = 1 ; k <= m ; k++)
    { xBaccum[k] -= abarj[k]*xj ; } }
/*
  We're not quite done. We need to account for bounded slacks
  associated with range constraints. If the constraint is tight at its lower
  bound, the slack is nonbasic at its upper bound.
*/
  logstatus = NULL ;
  dy_logStatus(main_lp,&logstatus) ;
  for (i = 1 ; i <= m ; i++)
  { stati = getflg(logstatus[i],vstatSTATUS) ;
    if (ctyp[i] == contypRNG && stati == vstatNBUB)
    { xj = rhs[i]-rhslow[i] ;
      if (dy_abarj(main_lp,-i,&abarj) == FALSE)
      { nberrs++ ;
	errmsg(953,rtnnme,sys->nme,"ftran'd","column",
	       consys_nme(sys,'v',n+i,FALSE,NULL),i) ;
	continue ; }
      for (k = 1 ; k <= m ; k++)
      { xBaccum[k] -= abarj[k]*xj ; } } }
/*
  Scan the rows one more time and check the values of the basic variables.
  Scale this test just a bit so we don't get spurious indications due to
  roundoff. The average of the two values seems safest as a scaling factor.
*/
  for (i = 1 ; i <= m ; i++)
  { tol = ((fabs(xBaccum[i])+fabs(xB[i]))/2)+1 ;
    if (fabs(xBaccum[i]-xB[i]) > tol*main_lptols->zero)
    { berrs++ ;
      j = indB[i] ;
      if (j < 0)
      { statj = n-j ; }
      else
      { statj = j ; }
      dyio_outfmt(dy_logchn,dy_gtxecho,
		  "\nERROR: basis pos'n %d %s (%d) = %g; expected %g;",
		  i,consys_nme(sys,'v',statj,FALSE,NULL),j,xB[i],xBaccum[i]) ;
      dyio_outfmt(dy_logchn,dy_gtxecho," error %g, tol %g.",
		  fabs(xB[i]-xBaccum[i]),main_lptols->zero) ; } }
/*
  Free up space and report the result.
*/
  if (logstatus != NULL) FREE(logstatus) ;
  if (abarj != NULL) FREE(abarj) ;
  if (xB != NULL) FREE(xB) ;
  if (indB != NULL) FREE(indB) ;
  if (xBaccum != NULL) FREE(xBaccum) ;
  if (betai != NULL) FREE(betai) ;

  if ((berrs+nberrs) != 0)
  { if (berrs != 0)
    { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: found %d errors testing x<B> = inv(B)b.\n",
		rtnnme,berrs) ; }
    if (nberrs != 0)
    { dyio_outfmt(dy_logchn,dy_gtxecho,
	      "\n%s: found %d errors attempting to use nonbasic variables.\n",
	      rtnnme,nberrs) ; } }
  else
  { dyio_outfmt(dy_logchn,dy_gtxecho,
		"\n%s: pass test of primal basic variable values.\n",
		rtnnme) ; }

  return (berrs+nberrs) ; }
コード例 #29
0
ファイル: dy_consys_scaling.c プロジェクト: sednanref/tesis
bool consys_equiscale (consys_struct *consys,
		       double **p_rowscale, double **p_colscale)
/*
  Given the constraint matrix A (consys), this routine will calculate diagonal
  scaling matrices R (rowscale) and S (colscale) using equilibration scaling.

  The routine assumes it is scaling the matrix R*A*S, and the parameters
  rowscale and colscale are updated with new scaling coefficients. The
  constraint system is >> not << scaled.

  This routine is light on paranoia, on the assumption that the matrix has
  just been scanned with consys_evalsys, which is heavy on paranoia.

  Parameters:
    consys:	constraint system
    p_rowscale:	(i) initial row scaling coefficients; created if null
		(o) revised row scaling coefficients
    p_colscale:	(i) initial column scaling coefficients; created if null
		(o) revised column scaling coefficients

  Returns: TRUE if no errors occurred while calculating the scaling
	   coefficients, FALSE otherwise.
*/

{ int i,j ;
  double sqm,sqm_old,eps,aij,rcmax,rcmin,maxaij,minaij ;
  double *rowscale,*colscale ;
  coeff_struct *coeffij ;

# if defined(DYLP_PARANOIA) || CONSYS_SCALING_DEBUG >= 1

  char *rtnnme = "consys_equiscale" ;

  if (consys == NULL)
  { errmsg(2,rtnnme,"consys") ;
    return (FALSE) ; }
  if (consys->mtx.rows == NULL)
  { errmsg(2,rtnnme,"row header") ;
    return (FALSE) ; }
  if (consys->mtx.cols == NULL)
  { errmsg(2,rtnnme,"column header") ;
    return (FALSE) ; }
  if (p_rowscale == NULL)
  { errmsg(2,rtnnme,"&rowscale") ;
    return (FALSE) ; }
  if (p_colscale == NULL)
  { errmsg(2,rtnnme,"&colscale") ;
    return (FALSE) ; }
# endif

/*
  If the client didn't supply initial scaling matrices, create them now and
  initialise them to 1.
*/
  if (*p_rowscale == NULL)
  { rowscale = (double *) MALLOC((consys->concnt+1)*sizeof(double)) ;
    rowscale[0] = 0 ;
    for (i = 1 ; i <= consys->concnt ; i++) rowscale[i] = 1.0 ; }
  else
  { rowscale = *p_rowscale ; }
  if (*p_colscale == NULL)
  { colscale = (double *) MALLOC((consys->varcnt+1)*sizeof(double)) ;
    colscale[0] = 0 ;
    for (j = 1 ; j <= consys->varcnt ; j++) colscale[j] = 1.0 ; }
  else
  { colscale = *p_colscale ; }

  sqm_old = sqrt(consys->maxaij/consys->minaij) ;
  eps = 1.0 ;

/*
  Update the column scaling vector.
*/
  maxaij = 0.0 ;
  minaij = consys->inf ;
  for (j = 1 ; j <= consys->varcnt ; j++)
  { coeffij = consys->mtx.cols[j]->coeffs ;
    if (coeffij == NULL) continue ;
    rcmax = 0.0 ;
    rcmin = consys->inf ;
    for ( ; coeffij != NULL ; coeffij = coeffij->colnxt)
    { aij = fabs(coeffij->val) ;
      if (aij == 0) continue ;
      i = coeffij->rowhdr->ndx ;
      aij *= rowscale[i] ;
      if (aij > rcmax) rcmax = aij ;
      if (aij < rcmin) rcmin = aij ; }
    colscale[j] = 1/rcmax ;
    if (colscale[j]*rcmax > maxaij) maxaij = colscale[j]*rcmax ;
    if (colscale[j]*rcmin < minaij) minaij = colscale[j]*rcmin ; }
  sqm = sqrt(maxaij/minaij) ;
  eps = (sqm_old-sqm)/sqm_old ;
# if (CONSYS_SCALING_DEBUG >= 1)
  dyio_outfmt(dy_logchn,dy_gtxecho,
	      "\n  %s: %g <= a<ij> <= %g, geom = %g, eps = %g",
	      rtnnme,minaij,maxaij,sqm,eps) ;
# endif

  consys->maxaij = maxaij ;
  consys->minaij = minaij ;

  *p_rowscale = rowscale ;
  *p_colscale = colscale ;

  return (TRUE) ; }
コード例 #30
0
ファイル: dy_basis.c プロジェクト: coin-or/DyLP
bool dy_setpivparms (int curdelta, int mindelta)

/*
  This routine exists to allow other parts of the lp code to adjust the pivot
  regimen used when the basis is factored.  curdelta is the change in the
  current pivot level, mindelta the change in the minimum pivot level.  A
  positive delta increases (tightens) the tolerances by delta steps, and a
  negative delta lowers (loosens) them.

  If either delta is 0, there's no change. A large positive or negative
  value slams the tolerance to the appropriate extreme.


  Parameters:
    curdelta:	change to the current pivot level
    mindelta:	change to the minimum pivot level

  Returns: TRUE if any change actually occurred, FALSE if we were already
	   at the relevant limit(s) (BE CAREFUL interpreting the return value
	   if you're changing both at once)
*/

{ bool minretval,curretval ;

# ifdef DYLP_PARANOIA
  const char *rtnnme = "dy_setpivparms" ;

  if (luf_basis == NULL)
  { errmsg(2,rtnnme,"luf_basis") ;
    return (FALSE) ; }
# endif

  minretval = FALSE ;
  curretval = FALSE ;
/*
  Adjust the minimum pivot level first. This may imply an adjustment in the
  current pivot level.
*/
  if (mindelta != 0)
  { if ((minpivlevel <= 0 && mindelta < 0) ||
	(minpivlevel >= MAX_PIVLEVEL && mindelta > 0))
    { 
#     ifndef DYLP_NDEBUG
      if ((dy_opts->print.basis >= 3) ||
          (dy_opts->print.basis >= 2 && mindelta > 0))
      { dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n\t    min. pivot ratio unchanged at %s (%d)",
		    dy_prtpivparms(minpivlevel),minpivlevel) ; }
#     endif
    }
    else
    { minretval = TRUE ;
      minpivlevel += mindelta ;
      if (minpivlevel < 0)
	minpivlevel = 0 ;
      else
      if (minpivlevel > MAX_PIVLEVEL)
	minpivlevel = MAX_PIVLEVEL ;
      if (pivlevel < minpivlevel) 
	curdelta = maxx(curdelta,(minpivlevel-pivlevel)) ;
#     ifndef DYLP_NDEBUG
      if (dy_opts->print.basis >= 2)
      { dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n\t    setting min. pivot ratio to %s (%d)",
		    dy_prtpivparms(minpivlevel),minpivlevel) ; }
#     endif
    } }
/*
  Adjust the current pivot level.
*/
  if (curdelta != 0)
  { if ((pivlevel <= minpivlevel && curdelta < 0) ||
	(pivlevel >= MAX_PIVLEVEL && curdelta > 0))
    { 
#     ifndef DYLP_NDEBUG
      if ((dy_opts->print.basis >= 3) ||
          (dy_opts->print.basis >= 2 && mindelta > 0))
      { dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n\t    cur. pivot ratio unchanged at %s (%d)",
		    dy_prtpivparms(-1),pivlevel) ; }
#     endif
    }
    else
    { curretval = TRUE ;
      pivlevel += curdelta ;
      if (pivlevel < minpivlevel)
	pivlevel = minpivlevel ;
      else
      if (pivlevel > MAX_PIVLEVEL)
	pivlevel = MAX_PIVLEVEL ;
      luf_basis->luf->piv_tol = pivtols[pivlevel].stable ;
      luf_basis->luf->piv_lim =  pivtols[pivlevel].look ;
#     ifndef DYLP_NDEBUG
      if (dy_opts->print.basis >= 2)
      { dyio_outfmt(dy_logchn,dy_gtxecho,
		    "\n\t    setting cur. pivot ratio to %s (%d)",
		    dy_prtpivparms(-1),pivlevel) ; }
#     endif
    } }

  if (curretval == FALSE && minretval == FALSE)
    return (FALSE) ;
  else
    return (TRUE) ; }