limp-cbc-0.3.2.0: cbits/coin/ClpLinearObjective.cpp
/* $Id: ClpLinearObjective.cpp 1665 2011-01-04 17:55:54Z lou $ */
// Copyright (C) 2003, 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 "CoinIndexedVector.hpp"
#include "ClpFactorization.hpp"
#include "ClpSimplex.hpp"
#include "ClpLinearObjective.hpp"
#include "CoinHelperFunctions.hpp"
//#############################################################################
// Constructors / Destructor / Assignment
//#############################################################################
//-------------------------------------------------------------------
// Default Constructor
//-------------------------------------------------------------------
ClpLinearObjective::ClpLinearObjective ()
: ClpObjective()
{
type_ = 1;
objective_ = NULL;
numberColumns_ = 0;
}
//-------------------------------------------------------------------
// Useful Constructor
//-------------------------------------------------------------------
ClpLinearObjective::ClpLinearObjective (const double * objective ,
int numberColumns)
: ClpObjective()
{
type_ = 1;
numberColumns_ = numberColumns;
objective_ = CoinCopyOfArray(objective, numberColumns_, 0.0);
}
//-------------------------------------------------------------------
// Copy constructor
//-------------------------------------------------------------------
ClpLinearObjective::ClpLinearObjective (const ClpLinearObjective & rhs)
: ClpObjective(rhs)
{
numberColumns_ = rhs.numberColumns_;
objective_ = CoinCopyOfArray(rhs.objective_, numberColumns_);
}
/* Subset constructor. Duplicates are allowed
and order is as given.
*/
ClpLinearObjective::ClpLinearObjective (const ClpLinearObjective &rhs,
int numberColumns,
const int * whichColumn)
: ClpObjective(rhs)
{
objective_ = NULL;
numberColumns_ = 0;
if (numberColumns > 0) {
// check valid lists
int numberBad = 0;
int i;
for (i = 0; i < numberColumns; i++)
if (whichColumn[i] < 0 || whichColumn[i] >= rhs.numberColumns_)
numberBad++;
if (numberBad)
throw CoinError("bad column list", "subset constructor",
"ClpLinearObjective");
numberColumns_ = numberColumns;
objective_ = new double[numberColumns_];
for (i = 0; i < numberColumns_; i++)
objective_[i] = rhs.objective_[whichColumn[i]];
}
}
//-------------------------------------------------------------------
// Destructor
//-------------------------------------------------------------------
ClpLinearObjective::~ClpLinearObjective ()
{
delete [] objective_;
}
//----------------------------------------------------------------
// Assignment operator
//-------------------------------------------------------------------
ClpLinearObjective &
ClpLinearObjective::operator=(const ClpLinearObjective& rhs)
{
if (this != &rhs) {
ClpObjective::operator=(rhs);
numberColumns_ = rhs.numberColumns_;
delete [] objective_;
objective_ = CoinCopyOfArray(rhs.objective_, numberColumns_);
}
return *this;
}
// Returns gradient
double *
ClpLinearObjective::gradient(const ClpSimplex * /*model*/,
const double * /*solution*/, double & offset,
bool /*refresh*/,
int /*includeLinear*/)
{
// not sure what to do about scaling
//assert (!model);
//assert (includeLinear==2); //otherwise need to return all zeros
offset = 0.0;
return objective_;
}
/* Returns reduced gradient.Returns an offset (to be added to current one).
*/
double
ClpLinearObjective::reducedGradient(ClpSimplex * model, double * region,
bool /*useFeasibleCosts*/)
{
int numberRows = model->numberRows();
//work space
CoinIndexedVector * workSpace = model->rowArray(0);
CoinIndexedVector arrayVector;
arrayVector.reserve(numberRows + 1);
int iRow;
#ifdef CLP_DEBUG
workSpace->checkClear();
#endif
double * array = arrayVector.denseVector();
int * index = arrayVector.getIndices();
int number = 0;
const double * cost = model->costRegion();
//assert (!useFeasibleCosts);
const int * pivotVariable = model->pivotVariable();
for (iRow = 0; iRow < numberRows; iRow++) {
int iPivot = pivotVariable[iRow];
double value = cost[iPivot];
if (value) {
array[iRow] = value;
index[number++] = iRow;
}
}
arrayVector.setNumElements(number);
int numberColumns = model->numberColumns();
// Btran basic costs
double * work = workSpace->denseVector();
model->factorization()->updateColumnTranspose(workSpace, &arrayVector);
ClpFillN(work, numberRows, 0.0);
// now look at dual solution
double * rowReducedCost = region + numberColumns;
double * dual = rowReducedCost;
double * rowCost = model->costRegion(0);
for (iRow = 0; iRow < numberRows; iRow++) {
dual[iRow] = array[iRow];
}
double * dj = region;
ClpDisjointCopyN(model->costRegion(1), numberColumns, dj);
model->transposeTimes(-1.0, dual, dj);
for (iRow = 0; iRow < numberRows; iRow++) {
// slack
double value = dual[iRow];
value += rowCost[iRow];
rowReducedCost[iRow] = value;
}
return 0.0;
}
/* Returns step length which gives minimum of objective for
solution + theta * change vector up to maximum theta.
arrays are numberColumns+numberRows
*/
double
ClpLinearObjective::stepLength(ClpSimplex * model,
const double * solution,
const double * change,
double maximumTheta,
double & currentObj,
double & predictedObj,
double & thetaObj)
{
const double * cost = model->costRegion();
double delta = 0.0;
int numberRows = model->numberRows();
int numberColumns = model->numberColumns();
currentObj = 0.0;
thetaObj = 0.0;
for (int iColumn = 0; iColumn < numberColumns + numberRows; iColumn++) {
delta += cost[iColumn] * change[iColumn];
currentObj += cost[iColumn] * solution[iColumn];
}
thetaObj = currentObj + delta * maximumTheta;
predictedObj = currentObj + delta * maximumTheta;
if (delta < 0.0) {
return maximumTheta;
} else {
printf("odd linear direction %g\n", delta);
return 0.0;
}
}
// Return objective value (without any ClpModel offset) (model may be NULL)
double
ClpLinearObjective::objectiveValue(const ClpSimplex * model, const double * solution) const
{
const double * cost = objective_;
if (model && model->costRegion())
cost = model->costRegion();
double currentObj = 0.0;
for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
currentObj += cost[iColumn] * solution[iColumn];
}
return currentObj;
}
//-------------------------------------------------------------------
// Clone
//-------------------------------------------------------------------
ClpObjective * ClpLinearObjective::clone() const
{
return new ClpLinearObjective(*this);
}
/* Subset clone. Duplicates are allowed
and order is as given.
*/
ClpObjective *
ClpLinearObjective::subsetClone (int numberColumns,
const int * whichColumns) const
{
return new ClpLinearObjective(*this, numberColumns, whichColumns);
}
// Resize objective
void
ClpLinearObjective::resize(int newNumberColumns)
{
if (numberColumns_ != newNumberColumns) {
int i;
double * newArray = new double[newNumberColumns];
if (objective_)
CoinMemcpyN(objective_, CoinMin(newNumberColumns, numberColumns_), newArray);
delete [] objective_;
objective_ = newArray;
for (i = numberColumns_; i < newNumberColumns; i++)
objective_[i] = 0.0;
numberColumns_ = newNumberColumns;
}
}
// Delete columns in objective
void
ClpLinearObjective::deleteSome(int numberToDelete, const int * which)
{
if (objective_) {
int i ;
char * deleted = new char[numberColumns_];
int numberDeleted = 0;
CoinZeroN(deleted, numberColumns_);
for (i = 0; i < numberToDelete; i++) {
int j = which[i];
if (j >= 0 && j < numberColumns_ && !deleted[j]) {
numberDeleted++;
deleted[j] = 1;
}
}
int newNumberColumns = numberColumns_ - numberDeleted;
double * newArray = new double[newNumberColumns];
int put = 0;
for (i = 0; i < numberColumns_; i++) {
if (!deleted[i]) {
newArray[put++] = objective_[i];
}
}
delete [] objective_;
objective_ = newArray;
delete [] deleted;
numberColumns_ = newNumberColumns;
}
}
// Scale objective
void
ClpLinearObjective::reallyScale(const double * columnScale)
{
for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
objective_[iColumn] *= columnScale[iColumn];
}
}