Пример #1
0
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) ; }
Пример #2
0
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 ; }
Пример #3
0
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 ; }
Пример #4
0
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 ; }
Пример #5
0
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 ; }