/* $Id$ */
// Copyright (C) 2002, International Business Machines
// Corporation and others.  All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).

#include "CoinPragma.hpp"
#include <iostream>
#include <cassert>

#include "CoinIndexedVector.hpp"

#include "ClpSimplex.hpp"
#include "CoinHelperFunctions.hpp"
#include "ClpNonLinearCost.hpp"
#include "ClpEventHandler.hpp"
//#############################################################################
// Constructors / Destructor / Assignment
//#############################################################################

//-------------------------------------------------------------------
// Default Constructor
//-------------------------------------------------------------------
ClpNonLinearCost::ClpNonLinearCost()
  : changeCost_(0.0)
  , feasibleCost_(0.0)
  , infeasibilityWeight_(-1.0)
  , largestInfeasibility_(0.0)
  , sumInfeasibilities_(0.0)
  , averageTheta_(0.0)
  , numberRows_(0)
  , numberColumns_(0)
  , start_(NULL)
  , whichRange_(NULL)
  , offset_(NULL)
  , lower_(NULL)
  , cost_(NULL)
  , model_(NULL)
  , infeasible_(NULL)
  , numberInfeasibilities_(-1)
  , status_(NULL)
  , bound_(NULL)
  , cost2_(NULL)
  , method_(1)
  , convex_(true)
  , bothWays_(false)
{
}
//#define VALIDATE
#ifdef VALIDATE
static double *saveLowerV = NULL;
static double *saveUpperV = NULL;
#ifdef NDEBUG
Validate sgould not be set if no debug
#endif
#endif
/* Constructor from simplex.
   This will just set up wasteful arrays for linear, but
   later may do dual analysis and even finding duplicate columns
*/
ClpNonLinearCost::ClpNonLinearCost(ClpSimplex * model, int method)
{
  method = 2;
  model_ = model;
  numberRows_ = model_->numberRows();
  //if (numberRows_==402) {
  //model_->setLogLevel(63);
  //model_->setMaximumIterations(30000);
  //}
  numberColumns_ = model_->numberColumns();
  // If gub then we need this extra
  int numberExtra = model_->numberExtraRows();
  if (numberExtra)
    method = 1;
  int numberTotal1 = numberRows_ + numberColumns_;
  int numberTotal = numberTotal1 + numberExtra;
  convex_ = true;
  bothWays_ = false;
  method_ = method;
  numberInfeasibilities_ = 0;
  changeCost_ = 0.0;
  feasibleCost_ = 0.0;
  infeasibilityWeight_ = -1.0;
  double *cost = model_->costRegion();
  // check if all 0
  int iSequence;
  bool allZero = true;
  for (iSequence = 0; iSequence < numberTotal1; iSequence++) {
    if (cost[iSequence]) {
      allZero = false;
      break;
    }
  }
  if (allZero && model_->clpMatrix()->type() < 15
      && model_->objectiveAsObject()->type() == 1)
    model_->setInfeasibilityCost(1.0);
  double infeasibilityCost = model_->infeasibilityCost();
  sumInfeasibilities_ = 0.0;
  averageTheta_ = 0.0;
  largestInfeasibility_ = 0.0;
  // All arrays NULL to start
  status_ = NULL;
  bound_ = NULL;
  cost2_ = NULL;
  start_ = NULL;
  whichRange_ = NULL;
  offset_ = NULL;
  lower_ = NULL;
  cost_ = NULL;
  infeasible_ = NULL;

  double *upper = model_->upperRegion();
  double *lower = model_->lowerRegion();

  // See how we are storing things
  bool always4 = (model_->clpMatrix()->generalExpanded(model_, 10, iSequence) != 0);
  if (always4)
    method_ = 1;
  if (CLP_METHOD1) {
    start_ = new int[numberTotal + 1];
    whichRange_ = new int[numberTotal];
    offset_ = new int[numberTotal];
    memset(offset_, 0, numberTotal * sizeof(int));

    // First see how much space we need
    int put = 0;

    // For quadratic we need -inf,0,0,+inf
    for (iSequence = 0; iSequence < numberTotal1; iSequence++) {
      if (!always4) {
        if (lower[iSequence] > -COIN_DBL_MAX)
          put++;
        if (upper[iSequence] < COIN_DBL_MAX)
          put++;
        put += 2;
      } else {
        put += 4;
      }
    }

    // and for extra
    put += 4 * numberExtra;
#ifndef NDEBUG
    int kPut = put;
#endif
    lower_ = new double[put];
    cost_ = new double[put];
    infeasible_ = new unsigned int[(put + 31) >> 5];
    memset(infeasible_, 0, ((put + 31) >> 5) * sizeof(unsigned int));

    put = 0;

    start_[0] = 0;

    for (iSequence = 0; iSequence < numberTotal1; iSequence++) {
      if (!always4) {
        if (lower[iSequence] > -COIN_DBL_MAX) {
          lower_[put] = -COIN_DBL_MAX;
          setInfeasible(put, true);
          cost_[put++] = cost[iSequence] - infeasibilityCost;
        }
        whichRange_[iSequence] = put;
        lower_[put] = lower[iSequence];
        cost_[put++] = cost[iSequence];
        lower_[put] = upper[iSequence];
        cost_[put++] = cost[iSequence] + infeasibilityCost;
        if (upper[iSequence] < COIN_DBL_MAX) {
          lower_[put] = COIN_DBL_MAX;
          setInfeasible(put - 1, true);
          cost_[put++] = 1.0e50;
        }
      } else {
        lower_[put] = -COIN_DBL_MAX;
        setInfeasible(put, true);
        cost_[put++] = cost[iSequence] - infeasibilityCost;
        whichRange_[iSequence] = put;
        lower_[put] = lower[iSequence];
        cost_[put++] = cost[iSequence];
        lower_[put] = upper[iSequence];
        cost_[put++] = cost[iSequence] + infeasibilityCost;
        lower_[put] = COIN_DBL_MAX;
        setInfeasible(put - 1, true);
        cost_[put++] = 1.0e50;
      }
      start_[iSequence + 1] = put;
    }
    for (; iSequence < numberTotal; iSequence++) {

      lower_[put] = -COIN_DBL_MAX;
      setInfeasible(put, true);
      put++;
      whichRange_[iSequence] = put;
      lower_[put] = 0.0;
      cost_[put++] = 0.0;
      lower_[put] = 0.0;
      cost_[put++] = 0.0;
      lower_[put] = COIN_DBL_MAX;
      setInfeasible(put - 1, true);
      cost_[put++] = 1.0e50;
      start_[iSequence + 1] = put;
    }
    assert(put <= kPut);
  }
#ifdef FAST_CLPNON
  // See how we are storing things
  CoinAssert(model_->clpMatrix()->generalExpanded(model_, 10, iSequence) == 0);
#endif
  if (CLP_METHOD2) {
    assert(!numberExtra);
    bound_ = new double[numberTotal];
    cost2_ = new double[numberTotal];
    status_ = new unsigned char[numberTotal];
#ifdef VALIDATE
    delete[] saveLowerV;
    saveLowerV = CoinCopyOfArray(model_->lowerRegion(), numberTotal);
    delete[] saveUpperV;
    saveUpperV = CoinCopyOfArray(model_->upperRegion(), numberTotal);
#endif
    for (iSequence = 0; iSequence < numberTotal; iSequence++) {
      bound_[iSequence] = 0.0;
      cost2_[iSequence] = cost[iSequence];
      setInitialStatus(status_[iSequence]);
    }
  }
}
#if 0
// Refresh - assuming regions OK
void 
ClpNonLinearCost::refresh()
{
     int numberTotal = numberRows_ + numberColumns_;
     numberInfeasibilities_ = 0;
     sumInfeasibilities_ = 0.0;
     largestInfeasibility_ = 0.0;
     double infeasibilityCost = model_->infeasibilityCost();
     double primalTolerance = model_->currentPrimalTolerance();
     double * cost = model_->costRegion();
     double * upper = model_->upperRegion();
     double * lower = model_->lowerRegion();
     double * solution = model_->solutionRegion();
     for (int iSequence = 0; iSequence < numberTotal; iSequence++) {
       cost2_[iSequence] = cost[iSequence];
       double value = solution[iSequence];
       double lowerValue = lower[iSequence];
       double upperValue = upper[iSequence];
       if (value - upperValue <= primalTolerance) {
	 if (value - lowerValue >= -primalTolerance) {
	   // feasible
	   status_[iSequence] = static_cast<unsigned char>(CLP_FEASIBLE | (CLP_SAME << 4));
	   bound_[iSequence] = 0.0;
	 } else {
	   // below
	   double infeasibility = lowerValue - value - primalTolerance;
	   sumInfeasibilities_ += infeasibility;
	   largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility);
	   cost[iSequence] -= infeasibilityCost;
	   numberInfeasibilities_++;
	   status_[iSequence] = static_cast<unsigned char>(CLP_BELOW_LOWER | (CLP_SAME << 4));
	   bound_[iSequence] = upperValue;
	   upper[iSequence] = lowerValue;
	   lower[iSequence] = -COIN_DBL_MAX;
	 }
       } else {
	 // above
	 double infeasibility = value - upperValue - primalTolerance;
	 sumInfeasibilities_ += infeasibility;
	 largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility);
	 cost[iSequence] += infeasibilityCost;
	 numberInfeasibilities_++;
	 status_[iSequence] = static_cast<unsigned char>(CLP_ABOVE_UPPER | (CLP_SAME << 4));
	 bound_[iSequence] = lowerValue;
	 lower[iSequence] = upperValue;
	 upper[iSequence] = COIN_DBL_MAX;
       }
     }
     //     checkInfeasibilities(model_->primalTolerance());
     
}
#endif
// Refresh one- assuming regions OK
void ClpNonLinearCost::refresh(int iSequence)
{
  double infeasibilityCost = model_->infeasibilityCost();
  double primalTolerance = model_->currentPrimalTolerance();
  double *cost = model_->costRegion();
  double *upper = model_->upperRegion();
  double *lower = model_->lowerRegion();
  double *solution = model_->solutionRegion();
  cost2_[iSequence] = cost[iSequence];
  double value = solution[iSequence];
  double lowerValue = lower[iSequence];
  double upperValue = upper[iSequence];
  if (value - upperValue <= primalTolerance) {
    if (value - lowerValue >= -primalTolerance) {
      // feasible
      status_[iSequence] = static_cast< unsigned char >(CLP_FEASIBLE | (CLP_SAME << 4));
      bound_[iSequence] = 0.0;
    } else {
      // below
      cost[iSequence] -= infeasibilityCost;
      status_[iSequence] = static_cast< unsigned char >(CLP_BELOW_LOWER | (CLP_SAME << 4));
      bound_[iSequence] = upperValue;
      upper[iSequence] = lowerValue;
      lower[iSequence] = -COIN_DBL_MAX;
    }
  } else {
    // above
    cost[iSequence] += infeasibilityCost;
    status_[iSequence] = static_cast< unsigned char >(CLP_ABOVE_UPPER | (CLP_SAME << 4));
    bound_[iSequence] = lowerValue;
    lower[iSequence] = upperValue;
    upper[iSequence] = COIN_DBL_MAX;
  }
}
// Refreshes costs always makes row costs zero
void ClpNonLinearCost::refreshCosts(const double *columnCosts)
{
  double *cost = model_->costRegion();
  // zero row costs
  memset(cost + numberColumns_, 0, numberRows_ * sizeof(double));
  // copy column costs
  CoinMemcpyN(columnCosts, numberColumns_, cost);
  if ((method_ & 1) != 0) {
    for (int iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) {
      int start = start_[iSequence];
      int end = start_[iSequence + 1] - 1;
      double thisFeasibleCost = cost[iSequence];
      if (infeasible(start)) {
        cost_[start] = thisFeasibleCost - infeasibilityWeight_;
        cost_[start + 1] = thisFeasibleCost;
      } else {
        cost_[start] = thisFeasibleCost;
      }
      if (infeasible(end - 1)) {
        cost_[end - 1] = thisFeasibleCost + infeasibilityWeight_;
      }
    }
  }
  if (CLP_METHOD2) {
    for (int iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) {
      cost2_[iSequence] = cost[iSequence];
    }
  }
}
ClpNonLinearCost::ClpNonLinearCost(ClpSimplex *model, const int *starts,
  const double *lowerNon, const double *costNon)
{
#ifndef FAST_CLPNON
  // what about scaling? - only try without it initially
  assert(!model->scalingFlag());
  model_ = model;
  numberRows_ = model_->numberRows();
  numberColumns_ = model_->numberColumns();
  int numberTotal = numberRows_ + numberColumns_;
  convex_ = true;
  bothWays_ = true;
  start_ = new int[numberTotal + 1];
  whichRange_ = new int[numberTotal];
  offset_ = new int[numberTotal];
  memset(offset_, 0, numberTotal * sizeof(int));

  double whichWay = model_->optimizationDirection();
  COIN_DETAIL_PRINT(printf("Direction %g\n", whichWay));

  numberInfeasibilities_ = 0;
  changeCost_ = 0.0;
  feasibleCost_ = 0.0;
  double infeasibilityCost = model_->infeasibilityCost();
  infeasibilityWeight_ = infeasibilityCost;
  ;
  largestInfeasibility_ = 0.0;
  sumInfeasibilities_ = 0.0;

  int iSequence;
  assert(!model_->rowObjective());
  double *cost = model_->objective();

  // First see how much space we need
  // Also set up feasible bounds
  int put = starts[numberColumns_];

  double *columnUpper = model_->columnUpper();
  double *columnLower = model_->columnLower();
  for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
    if (columnLower[iSequence] > -1.0e20)
      put++;
    if (columnUpper[iSequence] < 1.0e20)
      put++;
  }

  double *rowUpper = model_->rowUpper();
  double *rowLower = model_->rowLower();
  for (iSequence = 0; iSequence < numberRows_; iSequence++) {
    if (rowLower[iSequence] > -1.0e20)
      put++;
    if (rowUpper[iSequence] < 1.0e20)
      put++;
    put += 2;
  }
  lower_ = new double[put];
  cost_ = new double[put];
  infeasible_ = new unsigned int[(put + 31) >> 5];
  memset(infeasible_, 0, ((put + 31) >> 5) * sizeof(unsigned int));

  // now fill in
  put = 0;

  start_[0] = 0;
  for (iSequence = 0; iSequence < numberTotal; iSequence++) {
    lower_[put] = -COIN_DBL_MAX;
    whichRange_[iSequence] = put + 1;
    double thisCost;
    double lowerValue;
    double upperValue;
    if (iSequence >= numberColumns_) {
      // rows
      lowerValue = rowLower[iSequence - numberColumns_];
      upperValue = rowUpper[iSequence - numberColumns_];
      if (lowerValue > -1.0e30) {
        setInfeasible(put, true);
        cost_[put++] = -infeasibilityCost;
        lower_[put] = lowerValue;
      }
      cost_[put++] = 0.0;
      thisCost = 0.0;
    } else {
      // columns - move costs and see if convex
      lowerValue = columnLower[iSequence];
      upperValue = columnUpper[iSequence];
      if (lowerValue > -1.0e30) {
        setInfeasible(put, true);
        cost_[put++] = whichWay * cost[iSequence] - infeasibilityCost;
        lower_[put] = lowerValue;
      }
      int iIndex = starts[iSequence];
      int end = starts[iSequence + 1];
      assert(fabs(columnLower[iSequence] - lowerNon[iIndex]) < 1.0e-8);
      thisCost = -COIN_DBL_MAX;
      for (; iIndex < end; iIndex++) {
        if (lowerNon[iIndex] < columnUpper[iSequence] - 1.0e-8) {
          lower_[put] = lowerNon[iIndex];
          cost_[put++] = whichWay * costNon[iIndex];
          // check convexity
          if (whichWay * costNon[iIndex] < thisCost - 1.0e-12)
            convex_ = false;
          thisCost = whichWay * costNon[iIndex];
        } else {
          break;
        }
      }
    }
    lower_[put] = upperValue;
    setInfeasible(put, true);
    cost_[put++] = thisCost + infeasibilityCost;
    if (upperValue < 1.0e20) {
      lower_[put] = COIN_DBL_MAX;
      cost_[put++] = 1.0e50;
    }
    int iFirst = start_[iSequence];
    if (lower_[iFirst] != -COIN_DBL_MAX) {
      setInfeasible(iFirst, true);
      whichRange_[iSequence] = iFirst + 1;
    } else {
      whichRange_[iSequence] = iFirst;
    }
    start_[iSequence + 1] = put;
  }
  // can't handle non-convex at present
  assert(convex_);
  status_ = NULL;
  bound_ = NULL;
  cost2_ = NULL;
  method_ = 1;
#else
  printf("recompile ClpNonLinearCost without FAST_CLPNON\n");
  abort();
#endif
}
//-------------------------------------------------------------------
// Copy constructor
//-------------------------------------------------------------------
ClpNonLinearCost::ClpNonLinearCost(const ClpNonLinearCost &rhs)
  : changeCost_(0.0)
  , feasibleCost_(0.0)
  , infeasibilityWeight_(-1.0)
  , largestInfeasibility_(0.0)
  , sumInfeasibilities_(0.0)
  , averageTheta_(0.0)
  , numberRows_(rhs.numberRows_)
  , numberColumns_(rhs.numberColumns_)
  , start_(NULL)
  , whichRange_(NULL)
  , offset_(NULL)
  , lower_(NULL)
  , cost_(NULL)
  , model_(NULL)
  , infeasible_(NULL)
  , numberInfeasibilities_(-1)
  , status_(NULL)
  , bound_(NULL)
  , cost2_(NULL)
  , method_(rhs.method_)
  , convex_(true)
  , bothWays_(rhs.bothWays_)
{
  if (numberRows_) {
    int numberTotal = numberRows_ + numberColumns_;
    model_ = rhs.model_;
    numberInfeasibilities_ = rhs.numberInfeasibilities_;
    changeCost_ = rhs.changeCost_;
    feasibleCost_ = rhs.feasibleCost_;
    infeasibilityWeight_ = rhs.infeasibilityWeight_;
    largestInfeasibility_ = rhs.largestInfeasibility_;
    sumInfeasibilities_ = rhs.sumInfeasibilities_;
    averageTheta_ = rhs.averageTheta_;
    convex_ = rhs.convex_;
    if (CLP_METHOD1) {
      start_ = new int[numberTotal + 1];
      CoinMemcpyN(rhs.start_, (numberTotal + 1), start_);
      whichRange_ = new int[numberTotal];
      CoinMemcpyN(rhs.whichRange_, numberTotal, whichRange_);
      offset_ = new int[numberTotal];
      CoinMemcpyN(rhs.offset_, numberTotal, offset_);
      int numberEntries = start_[numberTotal];
      lower_ = new double[numberEntries];
      CoinMemcpyN(rhs.lower_, numberEntries, lower_);
      cost_ = new double[numberEntries];
      CoinMemcpyN(rhs.cost_, numberEntries, cost_);
      infeasible_ = new unsigned int[(numberEntries + 31) >> 5];
      CoinMemcpyN(rhs.infeasible_, ((numberEntries + 31) >> 5), infeasible_);
    }
    if (CLP_METHOD2) {
      bound_ = CoinCopyOfArray(rhs.bound_, numberTotal);
      cost2_ = CoinCopyOfArray(rhs.cost2_, numberTotal);
      status_ = CoinCopyOfArray(rhs.status_, numberTotal);
    }
  }
}

//-------------------------------------------------------------------
// Destructor
//-------------------------------------------------------------------
ClpNonLinearCost::~ClpNonLinearCost()
{
  delete[] start_;
  delete[] whichRange_;
  delete[] offset_;
  delete[] lower_;
  delete[] cost_;
  delete[] infeasible_;
  delete[] status_;
  delete[] bound_;
  delete[] cost2_;
}

//----------------------------------------------------------------
// Assignment operator
//-------------------------------------------------------------------
ClpNonLinearCost &
ClpNonLinearCost::operator=(const ClpNonLinearCost &rhs)
{
  if (this != &rhs) {
    numberRows_ = rhs.numberRows_;
    numberColumns_ = rhs.numberColumns_;
    delete[] start_;
    delete[] whichRange_;
    delete[] offset_;
    delete[] lower_;
    delete[] cost_;
    delete[] infeasible_;
    delete[] status_;
    delete[] bound_;
    delete[] cost2_;
    start_ = NULL;
    whichRange_ = NULL;
    lower_ = NULL;
    cost_ = NULL;
    infeasible_ = NULL;
    status_ = NULL;
    bound_ = NULL;
    cost2_ = NULL;
    method_ = rhs.method_;
    if (numberRows_) {
      int numberTotal = numberRows_ + numberColumns_;
      if (CLP_METHOD1) {
        start_ = new int[numberTotal + 1];
        CoinMemcpyN(rhs.start_, (numberTotal + 1), start_);
        whichRange_ = new int[numberTotal];
        CoinMemcpyN(rhs.whichRange_, numberTotal, whichRange_);
        offset_ = new int[numberTotal];
        CoinMemcpyN(rhs.offset_, numberTotal, offset_);
        int numberEntries = start_[numberTotal];
        lower_ = new double[numberEntries];
        CoinMemcpyN(rhs.lower_, numberEntries, lower_);
        cost_ = new double[numberEntries];
        CoinMemcpyN(rhs.cost_, numberEntries, cost_);
        infeasible_ = new unsigned int[(numberEntries + 31) >> 5];
        CoinMemcpyN(rhs.infeasible_, ((numberEntries + 31) >> 5), infeasible_);
      }
      if (CLP_METHOD2) {
        bound_ = CoinCopyOfArray(rhs.bound_, numberTotal);
        cost2_ = CoinCopyOfArray(rhs.cost2_, numberTotal);
        status_ = CoinCopyOfArray(rhs.status_, numberTotal);
      }
    }
    model_ = rhs.model_;
    numberInfeasibilities_ = rhs.numberInfeasibilities_;
    changeCost_ = rhs.changeCost_;
    feasibleCost_ = rhs.feasibleCost_;
    infeasibilityWeight_ = rhs.infeasibilityWeight_;
    largestInfeasibility_ = rhs.largestInfeasibility_;
    sumInfeasibilities_ = rhs.sumInfeasibilities_;
    averageTheta_ = rhs.averageTheta_;
    convex_ = rhs.convex_;
    bothWays_ = rhs.bothWays_;
  }
  return *this;
}
// Changes infeasible costs and computes number and cost of infeas
// We will need to re-think objective offsets later
// We will also need a 2 bit per variable array for some
// purpose which will come to me later
void ClpNonLinearCost::checkInfeasibilities(double oldTolerance)
{
  numberInfeasibilities_ = 0;
  double infeasibilityCost = model_->infeasibilityCost();
  changeCost_ = 0.0;
  largestInfeasibility_ = 0.0;
  sumInfeasibilities_ = 0.0;
  double primalTolerance = model_->currentPrimalTolerance();
  int iSequence;
  double *solution = model_->solutionRegion();
  double *upper = model_->upperRegion();
  double *lower = model_->lowerRegion();
  double *cost = model_->costRegion();
  bool toNearest = oldTolerance <= 0.0;
  feasibleCost_ = 0.0;
  //bool checkCosts = (infeasibilityWeight_ != infeasibilityCost);
  infeasibilityWeight_ = infeasibilityCost;
  int numberTotal = numberColumns_ + numberRows_;
  //#define NONLIN_DEBUG
#ifdef NONLIN_DEBUG
  double *saveSolution = NULL;
  double *saveLower = NULL;
  double *saveUpper = NULL;
  unsigned char *saveStatus = NULL;
  if (method_ == 3) {
    // Save solution as we will be checking
    saveSolution = CoinCopyOfArray(solution, numberTotal);
    saveLower = CoinCopyOfArray(lower, numberTotal);
    saveUpper = CoinCopyOfArray(upper, numberTotal);
    saveStatus = CoinCopyOfArray(model_->statusArray(), numberTotal);
  }
#else
  assert(method_ != 3);
#endif
  if (CLP_METHOD1) {
    // nonbasic should be at a valid bound
    for (iSequence = 0; iSequence < numberTotal; iSequence++) {
      double lowerValue;
      double upperValue;
      double value = solution[iSequence];
      int iRange;
      // get correct place
      int start = start_[iSequence];
      int end = start_[iSequence + 1] - 1;
      // correct costs for this infeasibility weight
      // If free then true cost will be first
      double thisFeasibleCost = cost_[start];
      if (infeasible(start)) {
        thisFeasibleCost = cost_[start + 1];
        cost_[start] = thisFeasibleCost - infeasibilityCost;
      }
      if (infeasible(end - 1)) {
        thisFeasibleCost = cost_[end - 2];
        cost_[end - 1] = thisFeasibleCost + infeasibilityCost;
      }
      for (iRange = start; iRange < end; iRange++) {
        if (value < lower_[iRange + 1] + primalTolerance) {
          // put in better range if infeasible
          if (value >= lower_[iRange + 1] - primalTolerance && infeasible(iRange) && iRange == start)
            iRange++;
          whichRange_[iSequence] = iRange;
          break;
        }
      }
      assert(iRange < end);
      lowerValue = lower_[iRange];
      upperValue = lower_[iRange + 1];
      ClpSimplex::Status status = model_->getStatus(iSequence);
      if (upperValue == lowerValue && status != ClpSimplex::isFixed) {
        if (status != ClpSimplex::basic) {
          model_->setStatus(iSequence, ClpSimplex::isFixed);
          status = ClpSimplex::isFixed;
        }
      }
      //#define PRINT_DETAIL7 2
#if PRINT_DETAIL7 > 1
      printf("NL %d sol %g bounds %g %g\n",
        iSequence, solution[iSequence],
        lowerValue, upperValue);
#endif
      switch (status) {

      case ClpSimplex::basic:
      case ClpSimplex::superBasic:
        // iRange is in correct place
        // slot in here
        if (infeasible(iRange)) {
          if (lower_[iRange] < -1.0e50) {
            //cost_[iRange] = cost_[iRange+1]-infeasibilityCost;
            // possibly below
            lowerValue = lower_[iRange + 1];
            if (value - lowerValue < -primalTolerance) {
              value = lowerValue - value - primalTolerance;
#ifndef NDEBUG
              if (value > 1.0e15)
                printf("nonlincostb %d %g %g %g\n",
                  iSequence, lowerValue, solution[iSequence], lower_[iRange + 2]);
#endif
#if PRINT_DETAIL7
              printf("**NL %d sol %g below %g\n",
                iSequence, solution[iSequence],
                lowerValue);
#endif
              sumInfeasibilities_ += value;
              largestInfeasibility_ = CoinMax(largestInfeasibility_, value);
              changeCost_ -= lowerValue * (cost_[iRange] - cost[iSequence]);
              numberInfeasibilities_++;
            }
          } else {
            //cost_[iRange] = cost_[iRange-1]+infeasibilityCost;
            // possibly above
            upperValue = lower_[iRange];
            if (value - upperValue > primalTolerance) {
              value = value - upperValue - primalTolerance;
#ifndef NDEBUG
              if (value > 1.0e15)
                printf("nonlincostu %d %g %g %g\n",
                  iSequence, lower_[iRange - 1], solution[iSequence], upperValue);
#endif
#if PRINT_DETAIL7
              printf("**NL %d sol %g above %g\n",
                iSequence, solution[iSequence],
                upperValue);
#endif
              sumInfeasibilities_ += value;
              largestInfeasibility_ = CoinMax(largestInfeasibility_, value);
              changeCost_ -= upperValue * (cost_[iRange] - cost[iSequence]);
              numberInfeasibilities_++;
            }
          }
        }
        //lower[iSequence] = lower_[iRange];
        //upper[iSequence] = lower_[iRange+1];
        //cost[iSequence] = cost_[iRange];
        break;
      case ClpSimplex::isFree:
        //if (toNearest)
        //solution[iSequence] = 0.0;
        break;
      case ClpSimplex::atUpperBound:
        if (!toNearest) {
          // With increasing tolerances - we may be at wrong place
          if (fabs(value - upperValue) > oldTolerance * 1.0001) {
            if (fabs(value - lowerValue) <= oldTolerance * 1.0001) {
              if (fabs(value - lowerValue) > primalTolerance)
                solution[iSequence] = lowerValue;
              model_->setStatus(iSequence, ClpSimplex::atLowerBound);
            } else {
              model_->setStatus(iSequence, ClpSimplex::superBasic);
            }
          } else if (fabs(value - upperValue) > primalTolerance) {
            solution[iSequence] = upperValue;
          }
        } else {
          // Set to nearest and make at upper bound
          int kRange;
          iRange = -1;
          double nearest = COIN_DBL_MAX;
          for (kRange = start; kRange < end; kRange++) {
            if (fabs(lower_[kRange] - value) < nearest) {
              nearest = fabs(lower_[kRange] - value);
              iRange = kRange;
            }
          }
          assert(iRange >= 0);
          iRange--;
          whichRange_[iSequence] = iRange;
          solution[iSequence] = lower_[iRange + 1];
        }
        break;
      case ClpSimplex::atLowerBound:
        if (!toNearest) {
          // With increasing tolerances - we may be at wrong place
          // below stops compiler error with gcc 3.2!!!
          if (iSequence == -119)
            printf("ZZ %g %g %g %g\n", lowerValue, value, upperValue, oldTolerance);
          if (fabs(value - lowerValue) > oldTolerance * 1.0001) {
            if (fabs(value - upperValue) <= oldTolerance * 1.0001) {
              if (fabs(value - upperValue) > primalTolerance)
                solution[iSequence] = upperValue;
              model_->setStatus(iSequence, ClpSimplex::atUpperBound);
            } else {
              model_->setStatus(iSequence, ClpSimplex::superBasic);
            }
          } else if (fabs(value - lowerValue) > primalTolerance) {
            solution[iSequence] = lowerValue;
          }
        } else {
          // Set to nearest and make at lower bound
          int kRange;
          iRange = -1;
          double nearest = COIN_DBL_MAX;
          for (kRange = start; kRange < end; kRange++) {
            if (fabs(lower_[kRange] - value) < nearest) {
              nearest = fabs(lower_[kRange] - value);
              iRange = kRange;
            }
          }
          assert(iRange >= 0);
          whichRange_[iSequence] = iRange;
          solution[iSequence] = lower_[iRange];
        }
        break;
      case ClpSimplex::isFixed:
        if (toNearest) {
          // Set to true fixed
          for (iRange = start; iRange < end; iRange++) {
            if (lower_[iRange] == lower_[iRange + 1])
              break;
          }
          if (iRange == end) {
            // Odd - but make sensible
            // Set to nearest and make at lower bound
            int kRange;
            iRange = -1;
            double nearest = COIN_DBL_MAX;
            for (kRange = start; kRange < end; kRange++) {
              if (fabs(lower_[kRange] - value) < nearest) {
                nearest = fabs(lower_[kRange] - value);
                iRange = kRange;
              }
            }
            assert(iRange >= 0);
            whichRange_[iSequence] = iRange;
            if (lower_[iRange] != lower_[iRange + 1])
              model_->setStatus(iSequence, ClpSimplex::atLowerBound);
            else
              model_->setStatus(iSequence, ClpSimplex::atUpperBound);
          }
          solution[iSequence] = lower_[iRange];
        }
        break;
      }
      lower[iSequence] = lower_[iRange];
      upper[iSequence] = lower_[iRange + 1];
      cost[iSequence] = cost_[iRange];
      feasibleCost_ += thisFeasibleCost * solution[iSequence];
      //assert (iRange==whichRange_[iSequence]);
    }
  }
#ifdef NONLIN_DEBUG
  double saveCost = feasibleCost_;
  if (method_ == 3) {
    feasibleCost_ = 0.0;
    // Put back solution as we will be checking
    unsigned char *statusA = model_->statusArray();
    for (iSequence = 0; iSequence < numberTotal; iSequence++) {
      double value = solution[iSequence];
      solution[iSequence] = saveSolution[iSequence];
      saveSolution[iSequence] = value;
      value = lower[iSequence];
      lower[iSequence] = saveLower[iSequence];
      saveLower[iSequence] = value;
      value = upper[iSequence];
      upper[iSequence] = saveUpper[iSequence];
      saveUpper[iSequence] = value;
      unsigned char value2 = statusA[iSequence];
      statusA[iSequence] = saveStatus[iSequence];
      saveStatus[iSequence] = value2;
    }
  }
#endif
  if (CLP_METHOD2) {
    //#define CLP_NON_JUST_BASIC
#ifndef CLP_NON_JUST_BASIC
    // nonbasic should be at a valid bound
    for (iSequence = 0; iSequence < numberTotal; iSequence++) {
#else
    const int *pivotVariable = model_->pivotVariable();
    for (int i = 0; i < numberRows_; i++) {
      int iSequence = pivotVariable[i];
#endif
      double value = solution[iSequence];
      unsigned char iStatus = status_[iSequence];
      assert(currentStatus(iStatus) == CLP_SAME);
      double lowerValue = lower[iSequence];
      double upperValue = upper[iSequence];
      double costValue = cost2_[iSequence];
      double trueCost = costValue;
      int iWhere = originalStatus(iStatus);
      if (iWhere == CLP_BELOW_LOWER) {
        lowerValue = upperValue;
        upperValue = bound_[iSequence];
        costValue -= infeasibilityCost;
      } else if (iWhere == CLP_ABOVE_UPPER) {
        upperValue = lowerValue;
        lowerValue = bound_[iSequence];
        costValue += infeasibilityCost;
      }
      // get correct place
      int newWhere = CLP_FEASIBLE;
      ClpSimplex::Status status = model_->getStatus(iSequence);
      if (upperValue == lowerValue && status != ClpSimplex::isFixed) {
        if (status != ClpSimplex::basic) {
          model_->setStatus(iSequence, ClpSimplex::isFixed);
          status = ClpSimplex::isFixed;
        }
      }
      switch (status) {

      case ClpSimplex::basic:
      case ClpSimplex::superBasic:
        if (value - upperValue <= primalTolerance) {
          if (value - lowerValue >= -primalTolerance) {
            // feasible
            //newWhere=CLP_FEASIBLE;
          } else {
            // below
            newWhere = CLP_BELOW_LOWER;
            assert(fabs(lowerValue) < 1.0e100);
            double infeasibility = lowerValue - value - primalTolerance;
            sumInfeasibilities_ += infeasibility;
            largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility);
            costValue = trueCost - infeasibilityCost;
            changeCost_ -= lowerValue * (costValue - cost[iSequence]);
            numberInfeasibilities_++;
          }
        } else {
          // above
          newWhere = CLP_ABOVE_UPPER;
          double infeasibility = value - upperValue - primalTolerance;
          sumInfeasibilities_ += infeasibility;
          largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility);
          costValue = trueCost + infeasibilityCost;
          changeCost_ -= upperValue * (costValue - cost[iSequence]);
          numberInfeasibilities_++;
        }
        break;
      case ClpSimplex::isFree:
        break;
      case ClpSimplex::atUpperBound:
        if (!toNearest) {
          // With increasing tolerances - we may be at wrong place
          if (fabs(value - upperValue) > oldTolerance * 1.0001) {
            if (fabs(value - lowerValue) <= oldTolerance * 1.0001) {
              if (fabs(value - lowerValue) > primalTolerance) {
                solution[iSequence] = lowerValue;
                value = lowerValue;
              }
              model_->setStatus(iSequence, ClpSimplex::atLowerBound);
            } else {
              if (value < upperValue) {
                if (value > lowerValue) {
                  model_->setStatus(iSequence, ClpSimplex::superBasic);
                } else {
                  // set to lower bound as infeasible
                  solution[iSequence] = lowerValue;
                  value = lowerValue;
                  model_->setStatus(iSequence, ClpSimplex::atLowerBound);
                }
              } else {
                // set to upper bound as infeasible
                solution[iSequence] = upperValue;
                value = upperValue;
              }
            }
          } else if (fabs(value - upperValue) > primalTolerance) {
            solution[iSequence] = upperValue;
            value = upperValue;
          }
        } else {
          // Set to nearest and make at bound
          if (fabs(value - lowerValue) < fabs(value - upperValue)) {
            solution[iSequence] = lowerValue;
            value = lowerValue;
            model_->setStatus(iSequence, ClpSimplex::atLowerBound);
          } else {
            solution[iSequence] = upperValue;
            value = upperValue;
          }
        }
        break;
      case ClpSimplex::atLowerBound:
        if (!toNearest) {
          // With increasing tolerances - we may be at wrong place
          if (fabs(value - lowerValue) > oldTolerance * 1.0001) {
            if (fabs(value - upperValue) <= oldTolerance * 1.0001) {
              if (fabs(value - upperValue) > primalTolerance) {
                solution[iSequence] = upperValue;
                value = upperValue;
              }
              model_->setStatus(iSequence, ClpSimplex::atUpperBound);
            } else {
              if (value < upperValue) {
                if (value > lowerValue) {
                  model_->setStatus(iSequence, ClpSimplex::superBasic);
                } else {
                  // set to lower bound as infeasible
                  solution[iSequence] = lowerValue;
                  value = lowerValue;
                }
              } else {
                // set to upper bound as infeasible
                solution[iSequence] = upperValue;
                value = upperValue;
                model_->setStatus(iSequence, ClpSimplex::atUpperBound);
              }
            }
          } else if (fabs(value - lowerValue) > primalTolerance) {
            solution[iSequence] = lowerValue;
            value = lowerValue;
          }
        } else {
          // Set to nearest and make at bound
          if (fabs(value - lowerValue) < fabs(value - upperValue)) {
            solution[iSequence] = lowerValue;
            value = lowerValue;
          } else {
            solution[iSequence] = upperValue;
            value = upperValue;
            model_->setStatus(iSequence, ClpSimplex::atUpperBound);
          }
        }
        break;
      case ClpSimplex::isFixed:
        solution[iSequence] = lowerValue;
        value = lowerValue;
        break;
      }
#ifdef NONLIN_DEBUG
      double lo = saveLower[iSequence];
      double up = saveUpper[iSequence];
      double cc = cost[iSequence];
      unsigned char ss = saveStatus[iSequence];
      unsigned char snow = model_->statusArray()[iSequence];
#endif
      if (iWhere != newWhere) {
        setOriginalStatus(status_[iSequence], newWhere);
        if (newWhere == CLP_BELOW_LOWER) {
          bound_[iSequence] = upperValue;
          upperValue = lowerValue;
          lowerValue = -COIN_DBL_MAX;
          costValue = trueCost - infeasibilityCost;
        } else if (newWhere == CLP_ABOVE_UPPER) {
          bound_[iSequence] = lowerValue;
          lowerValue = upperValue;
          upperValue = COIN_DBL_MAX;
          costValue = trueCost + infeasibilityCost;
        } else {
          costValue = trueCost;
        }
        lower[iSequence] = lowerValue;
        upper[iSequence] = upperValue;
        assert(lowerValue <= upperValue);
      }
      // always do as other things may change
      cost[iSequence] = costValue;
#ifdef NONLIN_DEBUG
      if (method_ == 3) {
        assert(ss == snow);
        assert(cc == cost[iSequence]);
        assert(lo == lower[iSequence]);
        assert(up == upper[iSequence]);
        assert(value == saveSolution[iSequence]);
      }
#endif
      feasibleCost_ += trueCost * value;
    }
  }
#ifdef NONLIN_DEBUG
  if (method_ == 3)
    assert(fabs(saveCost - feasibleCost_) < 0.001 * (1.0 + CoinMax(fabs(saveCost), fabs(feasibleCost_))));
  delete[] saveSolution;
  delete[] saveLower;
  delete[] saveUpper;
  delete[] saveStatus;
#endif
  //feasibleCost_ /= (model_->rhsScale()*model_->objScale());
}
// Puts feasible bounds into lower and upper
void ClpNonLinearCost::feasibleBounds()
{
  if (CLP_METHOD2) {
    int iSequence;
    double *upper = model_->upperRegion();
    double *lower = model_->lowerRegion();
    double *cost = model_->costRegion();
    int numberTotal = numberColumns_ + numberRows_;
    for (iSequence = 0; iSequence < numberTotal; iSequence++) {
      unsigned char iStatus = status_[iSequence];
      assert(currentStatus(iStatus) == CLP_SAME);
      double lowerValue = lower[iSequence];
      double upperValue = upper[iSequence];
      double costValue = cost2_[iSequence];
      int iWhere = originalStatus(iStatus);
      if (iWhere == CLP_BELOW_LOWER) {
        lowerValue = upperValue;
        upperValue = bound_[iSequence];
        assert(fabs(lowerValue) < 1.0e100);
      } else if (iWhere == CLP_ABOVE_UPPER) {
        upperValue = lowerValue;
        lowerValue = bound_[iSequence];
      }
      setOriginalStatus(status_[iSequence], CLP_FEASIBLE);
      lower[iSequence] = lowerValue;
      upper[iSequence] = upperValue;
      cost[iSequence] = costValue;
    }
  }
}
/* Goes through one bound for each variable.
   If array[i]*multiplier>0 goes down, otherwise up.
   The indices are row indices and need converting to sequences
*/
void ClpNonLinearCost::goThru(int numberInArray, double multiplier,
  const int *index, const double *array,
  double *rhs)
{
  assert(model_ != NULL);
  abort();
  const int *pivotVariable = model_->pivotVariable();
  if (CLP_METHOD1) {
    for (int i = 0; i < numberInArray; i++) {
      int iRow = index[i];
      int iSequence = pivotVariable[iRow];
      double alpha = multiplier * array[iRow];
      // get where in bound sequence
      int iRange = whichRange_[iSequence];
      iRange += offset_[iSequence]; //add temporary bias
      double value = model_->solution(iSequence);
      if (alpha > 0.0) {
        // down one
        iRange--;
        assert(iRange >= start_[iSequence]);
        rhs[iRow] = value - lower_[iRange];
      } else {
        // up one
        iRange++;
        assert(iRange < start_[iSequence + 1] - 1);
        rhs[iRow] = lower_[iRange + 1] - value;
      }
      offset_[iSequence] = iRange - whichRange_[iSequence];
    }
  }
#ifdef NONLIN_DEBUG
  double *saveRhs = NULL;
  if (method_ == 3) {
    int numberRows = model_->numberRows();
    saveRhs = CoinCopyOfArray(rhs, numberRows);
  }
#endif
  if (CLP_METHOD2) {
    const double *solution = model_->solutionRegion();
    const double *upper = model_->upperRegion();
    const double *lower = model_->lowerRegion();
    for (int i = 0; i < numberInArray; i++) {
      int iRow = index[i];
      int iSequence = pivotVariable[iRow];
      double alpha = multiplier * array[iRow];
      double value = solution[iSequence];
      unsigned char iStatus = status_[iSequence];
      int iWhere = currentStatus(iStatus);
      if (iWhere == CLP_SAME)
        iWhere = originalStatus(iStatus);
      if (iWhere == CLP_FEASIBLE) {
        if (alpha > 0.0) {
          // going below
          iWhere = CLP_BELOW_LOWER;
          rhs[iRow] = value - lower[iSequence];
        } else {
          // going above
          iWhere = CLP_ABOVE_UPPER;
          rhs[iRow] = upper[iSequence] - value;
        }
      } else if (iWhere == CLP_BELOW_LOWER) {
        assert(alpha < 0);
        // going feasible
        iWhere = CLP_FEASIBLE;
        rhs[iRow] = upper[iSequence] - value;
      } else {
        assert(iWhere == CLP_ABOVE_UPPER);
        // going feasible
        iWhere = CLP_FEASIBLE;
        rhs[iRow] = value - lower[iSequence];
      }
#ifdef NONLIN_DEBUG
      if (method_ == 3)
        assert(rhs[iRow] == saveRhs[iRow]);
#endif
      setCurrentStatus(status_[iSequence], iWhere);
    }
  }
#ifdef NONLIN_DEBUG
  delete[] saveRhs;
#endif
}
/* Takes off last iteration (i.e. offsets closer to 0)
 */
void ClpNonLinearCost::goBack(int numberInArray, const int *index,
  double *rhs)
{
  assert(model_ != NULL);
  abort();
  const int *pivotVariable = model_->pivotVariable();
  if (CLP_METHOD1) {
    for (int i = 0; i < numberInArray; i++) {
      int iRow = index[i];
      int iSequence = pivotVariable[iRow];
      // get where in bound sequence
      int iRange = whichRange_[iSequence];
      // get closer to original
      if (offset_[iSequence] > 0) {
        offset_[iSequence]--;
        assert(offset_[iSequence] >= 0);
        iRange += offset_[iSequence]; //add temporary bias
        double value = model_->solution(iSequence);
        // up one
        assert(iRange < start_[iSequence + 1] - 1);
        rhs[iRow] = lower_[iRange + 1] - value; // was earlier lower_[iRange]
      } else {
        offset_[iSequence]++;
        assert(offset_[iSequence] <= 0);
        iRange += offset_[iSequence]; //add temporary bias
        double value = model_->solution(iSequence);
        // down one
        assert(iRange >= start_[iSequence]);
        rhs[iRow] = value - lower_[iRange]; // was earlier lower_[iRange+1]
      }
    }
  }
#ifdef NONLIN_DEBUG
  double *saveRhs = NULL;
  if (method_ == 3) {
    int numberRows = model_->numberRows();
    saveRhs = CoinCopyOfArray(rhs, numberRows);
  }
#endif
  if (CLP_METHOD2) {
    const double *solution = model_->solutionRegion();
    const double *upper = model_->upperRegion();
    const double *lower = model_->lowerRegion();
    for (int i = 0; i < numberInArray; i++) {
      int iRow = index[i];
      int iSequence = pivotVariable[iRow];
      double value = solution[iSequence];
      unsigned char iStatus = status_[iSequence];
      int iWhere = currentStatus(iStatus);
      int original = originalStatus(iStatus);
      assert(iWhere != CLP_SAME);
      if (iWhere == CLP_FEASIBLE) {
        if (original == CLP_BELOW_LOWER) {
          // going below
          iWhere = CLP_BELOW_LOWER;
          rhs[iRow] = lower[iSequence] - value;
        } else {
          // going above
          iWhere = CLP_ABOVE_UPPER;
          rhs[iRow] = value - upper[iSequence];
        }
      } else if (iWhere == CLP_BELOW_LOWER) {
        // going feasible
        iWhere = CLP_FEASIBLE;
        rhs[iRow] = value - upper[iSequence];
      } else {
        // going feasible
        iWhere = CLP_FEASIBLE;
        rhs[iRow] = lower[iSequence] - value;
      }
#ifdef NONLIN_DEBUG
      if (method_ == 3)
        assert(rhs[iRow] == saveRhs[iRow]);
#endif
      setCurrentStatus(status_[iSequence], iWhere);
    }
  }
#ifdef NONLIN_DEBUG
  delete[] saveRhs;
#endif
}
void ClpNonLinearCost::goBackAll(const CoinIndexedVector *update)
{
  assert(model_ != NULL);
  const int *pivotVariable = model_->pivotVariable();
  int number = update->getNumElements();
  const int *index = update->getIndices();
  if (CLP_METHOD1) {
    for (int i = 0; i < number; i++) {
      int iRow = index[i];
      int iSequence = pivotVariable[iRow];
      offset_[iSequence] = 0;
    }
#ifdef CLP_DEBUG
    for (i = 0; i < numberRows_ + numberColumns_; i++)
      assert(!offset_[i]);
#endif
  }
  if (CLP_METHOD2) {
    for (int i = 0; i < number; i++) {
      int iRow = index[i];
      int iSequence = pivotVariable[iRow];
      setSameStatus(status_[iSequence]);
    }
  }
}
void ClpNonLinearCost::checkInfeasibilities(int numberInArray, const int *index)
{
  assert(model_ != NULL);
  double primalTolerance = model_->currentPrimalTolerance();
  const int *pivotVariable = model_->pivotVariable();
  if (CLP_METHOD1) {
    for (int i = 0; i < numberInArray; i++) {
      int iRow = index[i];
      int iSequence = pivotVariable[iRow];
      // get where in bound sequence
      int iRange;
      int currentRange = whichRange_[iSequence];
      double value = model_->solution(iSequence);
      int start = start_[iSequence];
      int end = start_[iSequence + 1] - 1;
      for (iRange = start; iRange < end; iRange++) {
        if (value < lower_[iRange + 1] + primalTolerance) {
          // put in better range
          if (value >= lower_[iRange + 1] - primalTolerance && infeasible(iRange) && iRange == start)
            iRange++;
          break;
        }
      }
      assert(iRange < end);
      assert(model_->getStatus(iSequence) == ClpSimplex::basic);
      double &lower = model_->lowerAddress(iSequence);
      double &upper = model_->upperAddress(iSequence);
      double &cost = model_->costAddress(iSequence);
      whichRange_[iSequence] = iRange;
      if (iRange != currentRange) {
        if (infeasible(iRange))
          numberInfeasibilities_++;
        if (infeasible(currentRange))
          numberInfeasibilities_--;
      }
      lower = lower_[iRange];
      upper = lower_[iRange + 1];
      cost = cost_[iRange];
    }
  }
  if (CLP_METHOD2) {
    double *solution = model_->solutionRegion();
    double *upper = model_->upperRegion();
    double *lower = model_->lowerRegion();
    double *cost = model_->costRegion();
    for (int i = 0; i < numberInArray; i++) {
      int iRow = index[i];
      int iSequence = pivotVariable[iRow];
      double value = solution[iSequence];
      unsigned char iStatus = status_[iSequence];
      assert(currentStatus(iStatus) == CLP_SAME);
      double lowerValue = lower[iSequence];
      double upperValue = upper[iSequence];
      double costValue = cost2_[iSequence];
      int iWhere = originalStatus(iStatus);
      if (iWhere == CLP_BELOW_LOWER) {
        lowerValue = upperValue;
        upperValue = bound_[iSequence];
        numberInfeasibilities_--;
        assert(fabs(lowerValue) < 1.0e100);
      } else if (iWhere == CLP_ABOVE_UPPER) {
        upperValue = lowerValue;
        lowerValue = bound_[iSequence];
        numberInfeasibilities_--;
      }
      // get correct place
      int newWhere = CLP_FEASIBLE;
      if (value - upperValue <= primalTolerance) {
        if (value - lowerValue >= -primalTolerance) {
          // feasible
          //newWhere=CLP_FEASIBLE;
        } else {
          // below
          newWhere = CLP_BELOW_LOWER;
          assert(fabs(lowerValue) < 1.0e100);
          costValue -= infeasibilityWeight_;
          numberInfeasibilities_++;
        }
      } else {
        // above
        newWhere = CLP_ABOVE_UPPER;
        costValue += infeasibilityWeight_;
        numberInfeasibilities_++;
      }
      if (iWhere != newWhere) {
        setOriginalStatus(status_[iSequence], newWhere);
        if (newWhere == CLP_BELOW_LOWER) {
          bound_[iSequence] = upperValue;
          upperValue = lowerValue;
          lowerValue = -COIN_DBL_MAX;
        } else if (newWhere == CLP_ABOVE_UPPER) {
          bound_[iSequence] = lowerValue;
          lowerValue = upperValue;
          upperValue = COIN_DBL_MAX;
        }
        lower[iSequence] = lowerValue;
        upper[iSequence] = upperValue;
        cost[iSequence] = costValue;
      }
    }
  }
}
/* Puts back correct infeasible costs for each variable
   The input indices are row indices and need converting to sequences
   for costs.
   On input array is empty (but indices exist).  On exit just
   changed costs will be stored as normal CoinIndexedVector
*/
void ClpNonLinearCost::checkChanged(int numberInArray, CoinIndexedVector *update)
{
  assert(model_ != NULL);
  double primalTolerance = model_->currentPrimalTolerance();
  const int *pivotVariable = model_->pivotVariable();
  int number = 0;
  int *index = update->getIndices();
  double *work = update->denseVector();
  if (CLP_METHOD1) {
    for (int i = 0; i < numberInArray; i++) {
      int iRow = index[i];
      int iSequence = pivotVariable[iRow];
      // get where in bound sequence
      int iRange;
      double value = model_->solution(iSequence);
      int start = start_[iSequence];
      int end = start_[iSequence + 1] - 1;
      for (iRange = start; iRange < end; iRange++) {
        if (value < lower_[iRange + 1] + primalTolerance) {
          // put in better range
          if (value >= lower_[iRange + 1] - primalTolerance && infeasible(iRange) && iRange == start)
            iRange++;
          break;
        }
      }
      assert(iRange < end);
      assert(model_->getStatus(iSequence) == ClpSimplex::basic);
      int jRange = whichRange_[iSequence];
      if (iRange != jRange) {
        // changed
        work[iRow] = cost_[jRange] - cost_[iRange];
        index[number++] = iRow;
        double &lower = model_->lowerAddress(iSequence);
        double &upper = model_->upperAddress(iSequence);
        double &cost = model_->costAddress(iSequence);
        whichRange_[iSequence] = iRange;
        if (infeasible(iRange))
          numberInfeasibilities_++;
        if (infeasible(jRange))
          numberInfeasibilities_--;
        lower = lower_[iRange];
        upper = lower_[iRange + 1];
        cost = cost_[iRange];
      }
    }
  }
  if (CLP_METHOD2) {
    double *solution = model_->solutionRegion();
    double *upper = model_->upperRegion();
    double *lower = model_->lowerRegion();
    double *cost = model_->costRegion();
    for (int i = 0; i < numberInArray; i++) {
      int iRow = index[i];
      int iSequence = pivotVariable[iRow];
      double value = solution[iSequence];
      unsigned char iStatus = status_[iSequence];
      assert(currentStatus(iStatus) == CLP_SAME);
      double lowerValue = lower[iSequence];
      double upperValue = upper[iSequence];
      double costValue = cost2_[iSequence];
      int iWhere = originalStatus(iStatus);
      if (iWhere == CLP_BELOW_LOWER) {
        lowerValue = upperValue;
        upperValue = bound_[iSequence];
        numberInfeasibilities_--;
        assert(fabs(lowerValue) < 1.0e100);
      } else if (iWhere == CLP_ABOVE_UPPER) {
        upperValue = lowerValue;
        lowerValue = bound_[iSequence];
        numberInfeasibilities_--;
      }
      // get correct place
      int newWhere = CLP_FEASIBLE;
      if (value - upperValue <= primalTolerance) {
        if (value - lowerValue >= -primalTolerance) {
          // feasible
          //newWhere=CLP_FEASIBLE;
        } else {
          // below
          newWhere = CLP_BELOW_LOWER;
          costValue -= infeasibilityWeight_;
          numberInfeasibilities_++;
          assert(fabs(lowerValue) < 1.0e100);
        }
      } else {
        // above
        newWhere = CLP_ABOVE_UPPER;
        costValue += infeasibilityWeight_;
        numberInfeasibilities_++;
      }
      if (iWhere != newWhere) {
        work[iRow] = cost[iSequence] - costValue;
        index[number++] = iRow;
        setOriginalStatus(status_[iSequence], newWhere);
        if (newWhere == CLP_BELOW_LOWER) {
          bound_[iSequence] = upperValue;
          upperValue = lowerValue;
          lowerValue = -COIN_DBL_MAX;
        } else if (newWhere == CLP_ABOVE_UPPER) {
          bound_[iSequence] = lowerValue;
          lowerValue = upperValue;
          upperValue = COIN_DBL_MAX;
        }
        lower[iSequence] = lowerValue;
        upper[iSequence] = upperValue;
        cost[iSequence] = costValue;
      }
    }
  }
  update->setNumElements(number);
}
/* Sets bounds and cost for one variable - returns change in cost*/
double
ClpNonLinearCost::setOne(int iSequence, double value)
{
  assert(model_ != NULL);
  double primalTolerance = model_->currentPrimalTolerance();
  // difference in cost
  double difference = 0.0;
  if (CLP_METHOD1) {
    // get where in bound sequence
    int iRange;
    int currentRange = whichRange_[iSequence];
    int start = start_[iSequence];
    int end = start_[iSequence + 1] - 1;
    if (!bothWays_) {
      // If fixed try and get feasible
      if (lower_[start + 1] == lower_[start + 2] && fabs(value - lower_[start + 1]) < 1.001 * primalTolerance) {
        iRange = start + 1;
      } else {
        for (iRange = start; iRange < end; iRange++) {
          if (value <= lower_[iRange + 1] + primalTolerance) {
            // put in better range
            if (value >= lower_[iRange + 1] - primalTolerance && infeasible(iRange) && iRange == start)
              iRange++;
            break;
          }
        }
      }
    } else {
      // leave in current if possible
      iRange = whichRange_[iSequence];
      if (value < lower_[iRange] - primalTolerance || value > lower_[iRange + 1] + primalTolerance) {
        for (iRange = start; iRange < end; iRange++) {
          if (value < lower_[iRange + 1] + primalTolerance) {
            // put in better range
            if (value >= lower_[iRange + 1] - primalTolerance && infeasible(iRange) && iRange == start)
              iRange++;
            break;
          }
        }
      }
    }
    assert(iRange < end);
    whichRange_[iSequence] = iRange;
    if (iRange != currentRange) {
      if (infeasible(iRange))
        numberInfeasibilities_++;
      if (infeasible(currentRange))
        numberInfeasibilities_--;
    }
    double &lower = model_->lowerAddress(iSequence);
    double &upper = model_->upperAddress(iSequence);
    double &cost = model_->costAddress(iSequence);
    lower = lower_[iRange];
    upper = lower_[iRange + 1];
    ClpSimplex::Status status = model_->getStatus(iSequence);
    if (upper == lower) {
      if (status != ClpSimplex::basic) {
        model_->setStatus(iSequence, ClpSimplex::isFixed);
        status = ClpSimplex::basic; // so will skip
      }
    }
    switch (status) {

    case ClpSimplex::basic:
    case ClpSimplex::superBasic:
    case ClpSimplex::isFree:
      break;
    case ClpSimplex::atUpperBound:
    case ClpSimplex::atLowerBound:
    case ClpSimplex::isFixed:
      // set correctly
      if (fabs(value - lower) <= primalTolerance * 1.001) {
        model_->setStatus(iSequence, ClpSimplex::atLowerBound);
      } else if (fabs(value - upper) <= primalTolerance * 1.001) {
        model_->setStatus(iSequence, ClpSimplex::atUpperBound);
      } else {
        // set superBasic
        model_->setStatus(iSequence, ClpSimplex::superBasic);
      }
      break;
    }
    difference = cost - cost_[iRange];
    cost = cost_[iRange];
  }
  if (CLP_METHOD2) {
    double *upper = model_->upperRegion();
    double *lower = model_->lowerRegion();
    double *cost = model_->costRegion();
    unsigned char iStatus = status_[iSequence];
    assert(currentStatus(iStatus) == CLP_SAME);
    double lowerValue = lower[iSequence];
    double upperValue = upper[iSequence];
    double costValue = cost2_[iSequence];
    int iWhere = originalStatus(iStatus);
#undef CLP_USER_DRIVEN
#ifdef CLP_USER_DRIVEN
    clpUserStruct info;
    info.type = 3;
    info.sequence = iSequence;
    info.value = value;
    info.change = 0;
    info.lower = lowerValue;
    info.upper = upperValue;
    info.cost = costValue;
#endif
    if (iWhere == CLP_BELOW_LOWER) {
      lowerValue = upperValue;
      upperValue = bound_[iSequence];
      numberInfeasibilities_--;
      assert(fabs(lowerValue) < 1.0e100);
    } else if (iWhere == CLP_ABOVE_UPPER) {
      upperValue = lowerValue;
      lowerValue = bound_[iSequence];
      numberInfeasibilities_--;
    }
    // get correct place
    int newWhere = CLP_FEASIBLE;
    if (value - upperValue <= primalTolerance) {
      if (value - lowerValue >= -primalTolerance) {
        // feasible
        //newWhere=CLP_FEASIBLE;
      } else {
        // below
        newWhere = CLP_BELOW_LOWER;
        costValue -= infeasibilityWeight_;
        numberInfeasibilities_++;
        assert(fabs(lowerValue) < 1.0e100);
      }
    } else {
      // above
      newWhere = CLP_ABOVE_UPPER;
      costValue += infeasibilityWeight_;
      numberInfeasibilities_++;
    }
    if (iWhere != newWhere) {
      difference = cost[iSequence] - costValue;
      setOriginalStatus(status_[iSequence], newWhere);
      if (newWhere == CLP_BELOW_LOWER) {
        bound_[iSequence] = upperValue;
        upperValue = lowerValue;
        lowerValue = -COIN_DBL_MAX;
      } else if (newWhere == CLP_ABOVE_UPPER) {
        bound_[iSequence] = lowerValue;
        lowerValue = upperValue;
        upperValue = COIN_DBL_MAX;
      }
      lower[iSequence] = lowerValue;
      upper[iSequence] = upperValue;
      cost[iSequence] = costValue;
    }
    ClpSimplex::Status status = model_->getStatus(iSequence);
    if (upperValue == lowerValue) {
      if (status != ClpSimplex::basic) {
        model_->setStatus(iSequence, ClpSimplex::isFixed);
        status = ClpSimplex::basic; // so will skip
      }
    }
    switch (status) {

    case ClpSimplex::basic:
    case ClpSimplex::superBasic:
    case ClpSimplex::isFree:
      break;
    case ClpSimplex::atUpperBound:
    case ClpSimplex::atLowerBound:
    case ClpSimplex::isFixed:
      // set correctly
      if (fabs(value - lowerValue) <= primalTolerance * 1.001) {
        model_->setStatus(iSequence, ClpSimplex::atLowerBound);
      } else if (fabs(value - upperValue) <= primalTolerance * 1.001) {
        model_->setStatus(iSequence, ClpSimplex::atUpperBound);
      } else {
        // set superBasic
        model_->setStatus(iSequence, ClpSimplex::superBasic);
      }
      break;
    }
#ifdef CLP_USER_DRIVEN
    model_->eventHandler()->eventWithInfo(ClpEventHandler::pivotRow,
      &info);
    if (info.change) {
    }
#endif
  }
  changeCost_ += value * difference;
  return difference;
}
/* Sets bounds and infeasible cost and true cost for one variable
   This is for gub and column generation etc */
void ClpNonLinearCost::setOne(int sequence, double solutionValue, double lowerValue, double upperValue,
  double costValue)
{
  if (CLP_METHOD1) {
    int iRange = -1;
    int start = start_[sequence];
    double infeasibilityCost = model_->infeasibilityCost();
    cost_[start] = costValue - infeasibilityCost;
    lower_[start + 1] = lowerValue;
    cost_[start + 1] = costValue;
    lower_[start + 2] = upperValue;
    cost_[start + 2] = costValue + infeasibilityCost;
    double primalTolerance = model_->currentPrimalTolerance();
    if (solutionValue - lowerValue >= -primalTolerance) {
      if (solutionValue - upperValue <= primalTolerance) {
        iRange = start + 1;
      } else {
        iRange = start + 2;
      }
    } else {
      iRange = start;
    }
    model_->costRegion()[sequence] = cost_[iRange];
    whichRange_[sequence] = iRange;
  }
  if (CLP_METHOD2) {
    bound_[sequence] = 0.0;
    cost2_[sequence] = costValue;
    setInitialStatus(status_[sequence]);
  }
}
/* Sets bounds and cost for outgoing variable
   may change value
   Returns direction */
int ClpNonLinearCost::setOneOutgoing(int iSequence, double &value)
{
  assert(model_ != NULL);
  double primalTolerance = model_->currentPrimalTolerance();
  // difference in cost
  double difference = 0.0;
  int direction = 0;
#ifdef CLP_USER_DRIVEN
  double saveLower = model_->lowerRegion()[iSequence];
  double saveUpper = model_->upperRegion()[iSequence];
  double saveCost = model_->costRegion()[iSequence];
#endif
  if (CLP_METHOD1) {
    // get where in bound sequence
    int iRange;
    int currentRange = whichRange_[iSequence];
    int start = start_[iSequence];
    int end = start_[iSequence + 1] - 1;
    // Set perceived direction out
    if (value <= lower_[currentRange] + 1.001 * primalTolerance) {
      direction = 1;
    } else if (value >= lower_[currentRange + 1] - 1.001 * primalTolerance) {
      direction = -1;
    } else {
      // odd
      direction = 0;
    }
    // If fixed try and get feasible
    if (lower_[start + 1] == lower_[start + 2] && fabs(value - lower_[start + 1]) < 1.001 * primalTolerance) {
      iRange = start + 1;
    } else {
      // See if exact
      for (iRange = start; iRange < end; iRange++) {
        if (value == lower_[iRange + 1]) {
          // put in better range
          if (infeasible(iRange) && iRange == start)
            iRange++;
          break;
        }
      }
      if (iRange == end) {
        // not exact
        for (iRange = start; iRange < end; iRange++) {
          if (value <= lower_[iRange + 1] + primalTolerance) {
            // put in better range
            if (value >= lower_[iRange + 1] - primalTolerance && infeasible(iRange) && iRange == start)
              iRange++;
            break;
          }
        }
      }
    }
    assert(iRange < end);
    whichRange_[iSequence] = iRange;
    if (iRange != currentRange) {
      if (infeasible(iRange))
        numberInfeasibilities_++;
      if (infeasible(currentRange))
        numberInfeasibilities_--;
    }
    double &lower = model_->lowerAddress(iSequence);
    double &upper = model_->upperAddress(iSequence);
    double &cost = model_->costAddress(iSequence);
    lower = lower_[iRange];
    upper = lower_[iRange + 1];
    if (upper == lower) {
      value = upper;
    } else {
      // set correctly
      if (fabs(value - lower) <= primalTolerance * 1.001) {
        value = CoinMin(value, lower + primalTolerance);
      } else if (fabs(value - upper) <= primalTolerance * 1.001) {
        value = CoinMax(value, upper - primalTolerance);
      } else {
        //printf("*** variable wandered off bound %g %g %g!\n",
        //     lower,value,upper);
        if (value - lower <= upper - value)
          value = lower + primalTolerance;
        else
          value = upper - primalTolerance;
      }
    }
    difference = cost - cost_[iRange];
    cost = cost_[iRange];
  }
  if (CLP_METHOD2) {
    double *upper = model_->upperRegion();
    double *lower = model_->lowerRegion();
    double *cost = model_->costRegion();
    unsigned char iStatus = status_[iSequence];
    assert(currentStatus(iStatus) == CLP_SAME);
    double lowerValue = lower[iSequence];
    double upperValue = upper[iSequence];
    double costValue = cost2_[iSequence];
    // Set perceived direction out
    if (value <= lowerValue + 1.001 * primalTolerance) {
      direction = 1;
    } else if (value >= upperValue - 1.001 * primalTolerance) {
      direction = -1;
    } else {
      // odd
      direction = 0;
    }
    int iWhere = originalStatus(iStatus);
    if (iWhere == CLP_BELOW_LOWER) {
      lowerValue = upperValue;
      upperValue = bound_[iSequence];
      numberInfeasibilities_--;
      assert(fabs(lowerValue) < 1.0e100);
    } else if (iWhere == CLP_ABOVE_UPPER) {
      upperValue = lowerValue;
      lowerValue = bound_[iSequence];
      numberInfeasibilities_--;
    }
    // get correct place
    // If fixed give benefit of doubt
    if (lowerValue == upperValue)
      value = lowerValue;
    int newWhere = CLP_FEASIBLE;
    if (value - upperValue <= primalTolerance) {
      if (value - lowerValue >= -primalTolerance) {
        // feasible
        //newWhere=CLP_FEASIBLE;
      } else {
        // below
        newWhere = CLP_BELOW_LOWER;
        costValue -= infeasibilityWeight_;
        numberInfeasibilities_++;
        assert(fabs(lowerValue) < 1.0e100);
      }
    } else {
      // above
      newWhere = CLP_ABOVE_UPPER;
      costValue += infeasibilityWeight_;
      numberInfeasibilities_++;
    }
    if (iWhere != newWhere) {
      difference = cost[iSequence] - costValue;
      setOriginalStatus(status_[iSequence], newWhere);
      if (newWhere == CLP_BELOW_LOWER) {
        bound_[iSequence] = upperValue;
        upper[iSequence] = lowerValue;
        lower[iSequence] = -COIN_DBL_MAX;
      } else if (newWhere == CLP_ABOVE_UPPER) {
        bound_[iSequence] = lowerValue;
        lower[iSequence] = upperValue;
        upper[iSequence] = COIN_DBL_MAX;
      } else {
        lower[iSequence] = lowerValue;
        upper[iSequence] = upperValue;
      }
      cost[iSequence] = costValue;
    }
    // set correctly
    if (fabs(value - lowerValue) <= primalTolerance * 1.001) {
      value = CoinMin(value, lowerValue + primalTolerance);
    } else if (fabs(value - upperValue) <= primalTolerance * 1.001) {
      value = CoinMax(value, upperValue - primalTolerance);
    } else {
      //printf("*** variable wandered off bound %g %g %g!\n",
      //     lowerValue,value,upperValue);
      if (value - lowerValue <= upperValue - value)
        value = lowerValue + primalTolerance;
      else
        value = upperValue - primalTolerance;
    }
  }
  changeCost_ += value * difference;
#ifdef CLP_USER_DRIVEN
  //if (iSequence>=model_->numberColumns)
  if (difference || saveCost != model_->costRegion()[iSequence]) {
    printf("Out %d (%d) %g <= %g <= %g cost %g x=>x %g < %g cost %g\n",
      iSequence, iSequence - model_->numberColumns(),
      saveLower, value, saveUpper, saveCost,
      model_->lowerRegion()[iSequence],
      model_->upperRegion()[iSequence],
      model_->costRegion()[iSequence]);
  }
#endif
  return direction;
}
// Returns nearest bound
double
ClpNonLinearCost::nearest(int iSequence, double solutionValue)
{
  assert(model_ != NULL);
  double nearest = 0.0;
  if (CLP_METHOD1) {
    // get where in bound sequence
    int iRange;
    int start = start_[iSequence];
    int end = start_[iSequence + 1];
    int jRange = -1;
    nearest = COIN_DBL_MAX;
    for (iRange = start; iRange < end; iRange++) {
      if (fabs(solutionValue - lower_[iRange]) < nearest) {
        jRange = iRange;
        nearest = fabs(solutionValue - lower_[iRange]);
      }
    }
    assert(jRange < end);
    nearest = lower_[jRange];
  }
  if (CLP_METHOD2) {
    const double *upper = model_->upperRegion();
    const double *lower = model_->lowerRegion();
    double lowerValue = lower[iSequence];
    double upperValue = upper[iSequence];
    int iWhere = originalStatus(status_[iSequence]);
    if (iWhere == CLP_BELOW_LOWER) {
      lowerValue = upperValue;
      upperValue = bound_[iSequence];
      assert(fabs(lowerValue) < 1.0e100);
    } else if (iWhere == CLP_ABOVE_UPPER) {
      upperValue = lowerValue;
      lowerValue = bound_[iSequence];
    }
    if (fabs(solutionValue - lowerValue) < fabs(solutionValue - upperValue))
      nearest = lowerValue;
    else
      nearest = upperValue;
  }
  return nearest;
}
/// Feasible cost with offset and direction (i.e. for reporting)
double
ClpNonLinearCost::feasibleReportCost() const
{
  double value;
  model_->getDblParam(ClpObjOffset, value);
  return (feasibleCost_ + model_->objectiveAsObject()->nonlinearOffset()) * model_->optimizationDirection() / (model_->objectiveScale() * model_->rhsScale()) - value;
}
// Get rid of real costs (just for moment)
void ClpNonLinearCost::zapCosts()
{
  int iSequence;
  double infeasibilityCost = model_->infeasibilityCost();
  // zero out all costs
  int numberTotal = numberColumns_ + numberRows_;
  if (CLP_METHOD1) {
    int n = start_[numberTotal];
    memset(cost_, 0, n * sizeof(double));
    for (iSequence = 0; iSequence < numberTotal; iSequence++) {
      int start = start_[iSequence];
      int end = start_[iSequence + 1] - 1;
      // correct costs for this infeasibility weight
      if (infeasible(start)) {
        cost_[start] = -infeasibilityCost;
      }
      if (infeasible(end - 1)) {
        cost_[end - 1] = infeasibilityCost;
      }
    }
  }
  if (CLP_METHOD2) {
  }
}
#ifdef VALIDATE
// For debug
void ClpNonLinearCost::validate()
{
  double primalTolerance = model_->currentPrimalTolerance();
  int iSequence;
  const double *solution = model_->solutionRegion();
  const double *upper = model_->upperRegion();
  const double *lower = model_->lowerRegion();
  const double *cost = model_->costRegion();
  double infeasibilityCost = model_->infeasibilityCost();
  int numberTotal = numberRows_ + numberColumns_;
  int numberInfeasibilities = 0;
  double sumInfeasibilities = 0.0;

  for (iSequence = 0; iSequence < numberTotal; iSequence++) {
    double value = solution[iSequence];
    int iStatus = status_[iSequence];
    assert(currentStatus(iStatus) == CLP_SAME);
    double lowerValue = lower[iSequence];
    double upperValue = upper[iSequence];
    double costValue = cost2_[iSequence];
    int iWhere = originalStatus(iStatus);
    if (iWhere == CLP_BELOW_LOWER) {
      lowerValue = upperValue;
      upperValue = bound_[iSequence];
      assert(fabs(lowerValue) < 1.0e100);
      costValue -= infeasibilityCost;
      assert(value <= lowerValue - primalTolerance);
      numberInfeasibilities++;
      sumInfeasibilities += lowerValue - value - primalTolerance;
      assert(model_->getStatus(iSequence) == ClpSimplex::basic);
    } else if (iWhere == CLP_ABOVE_UPPER) {
      upperValue = lowerValue;
      lowerValue = bound_[iSequence];
      costValue += infeasibilityCost;
      assert(value >= upperValue + primalTolerance);
      numberInfeasibilities++;
      sumInfeasibilities += value - upperValue - primalTolerance;
      assert(model_->getStatus(iSequence) == ClpSimplex::basic);
    } else {
      assert(value >= lowerValue - primalTolerance && value <= upperValue + primalTolerance);
    }
    assert(lowerValue == saveLowerV[iSequence]);
    assert(upperValue == saveUpperV[iSequence]);
    assert(costValue == cost[iSequence]);
  }
  if (numberInfeasibilities)
    printf("JJ %d infeasibilities summing to %g\n",
      numberInfeasibilities, sumInfeasibilities);
}
#endif

/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
*/
