source: trunk/Clp/src/ClpLinearObjective.cpp @ 2385

Last change on this file since 2385 was 2385, checked in by unxusr, 4 months ago

formatting

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.3 KB
Line 
1/* $Id: ClpLinearObjective.cpp 2385 2019-01-06 19:43:06Z unxusr $ */
2// Copyright (C) 2003, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#include "CoinPragma.hpp"
7#include "CoinIndexedVector.hpp"
8#include "ClpFactorization.hpp"
9#include "ClpSimplex.hpp"
10#include "ClpLinearObjective.hpp"
11#include "CoinHelperFunctions.hpp"
12
13//#############################################################################
14// Constructors / Destructor / Assignment
15//#############################################################################
16
17//-------------------------------------------------------------------
18// Default Constructor
19//-------------------------------------------------------------------
20ClpLinearObjective::ClpLinearObjective()
21  : ClpObjective()
22{
23  type_ = 1;
24  objective_ = NULL;
25  numberColumns_ = 0;
26}
27
28//-------------------------------------------------------------------
29// Useful Constructor
30//-------------------------------------------------------------------
31ClpLinearObjective::ClpLinearObjective(const double *objective,
32  int numberColumns)
33  : ClpObjective()
34{
35  type_ = 1;
36  numberColumns_ = numberColumns;
37  objective_ = CoinCopyOfArray(objective, numberColumns_, 0.0);
38}
39
40//-------------------------------------------------------------------
41// Copy constructor
42//-------------------------------------------------------------------
43ClpLinearObjective::ClpLinearObjective(const ClpLinearObjective &rhs)
44  : ClpObjective(rhs)
45{
46  numberColumns_ = rhs.numberColumns_;
47  objective_ = CoinCopyOfArray(rhs.objective_, numberColumns_);
48}
49/* Subset constructor.  Duplicates are allowed
50   and order is as given.
51*/
52ClpLinearObjective::ClpLinearObjective(const ClpLinearObjective &rhs,
53  int numberColumns,
54  const int *whichColumn)
55  : ClpObjective(rhs)
56{
57  objective_ = NULL;
58  numberColumns_ = 0;
59  if (numberColumns > 0) {
60    // check valid lists
61    int numberBad = 0;
62    int i;
63    for (i = 0; i < numberColumns; i++)
64      if (whichColumn[i] < 0 || whichColumn[i] >= rhs.numberColumns_)
65        numberBad++;
66    if (numberBad)
67      throw CoinError("bad column list", "subset constructor",
68        "ClpLinearObjective");
69    numberColumns_ = numberColumns;
70    objective_ = new double[numberColumns_];
71    for (i = 0; i < numberColumns_; i++)
72      objective_[i] = rhs.objective_[whichColumn[i]];
73  }
74}
75
76//-------------------------------------------------------------------
77// Destructor
78//-------------------------------------------------------------------
79ClpLinearObjective::~ClpLinearObjective()
80{
81  delete[] objective_;
82}
83
84//----------------------------------------------------------------
85// Assignment operator
86//-------------------------------------------------------------------
87ClpLinearObjective &
88ClpLinearObjective::operator=(const ClpLinearObjective &rhs)
89{
90  if (this != &rhs) {
91    ClpObjective::operator=(rhs);
92    numberColumns_ = rhs.numberColumns_;
93    delete[] objective_;
94    objective_ = CoinCopyOfArray(rhs.objective_, numberColumns_);
95  }
96  return *this;
97}
98
99// Returns gradient
100double *
101ClpLinearObjective::gradient(const ClpSimplex * /*model*/,
102  const double * /*solution*/, double &offset,
103  bool /*refresh*/,
104  int /*includeLinear*/)
105{
106  // not sure what to do about scaling
107  //assert (!model);
108  //assert (includeLinear==2); //otherwise need to return all zeros
109  offset = 0.0;
110  return objective_;
111}
112
113/* Returns reduced gradient.Returns an offset (to be added to current one).
114 */
115double
116ClpLinearObjective::reducedGradient(ClpSimplex *model, double *region,
117  bool /*useFeasibleCosts*/)
118{
119  int numberRows = model->numberRows();
120  //work space
121  CoinIndexedVector *workSpace = model->rowArray(0);
122
123  CoinIndexedVector arrayVector;
124  arrayVector.reserve(numberRows + 1);
125
126  int iRow;
127#ifdef CLP_DEBUG
128  workSpace->checkClear();
129#endif
130  double *array = arrayVector.denseVector();
131  int *index = arrayVector.getIndices();
132  int number = 0;
133  const double *cost = model->costRegion();
134  //assert (!useFeasibleCosts);
135  const int *pivotVariable = model->pivotVariable();
136  for (iRow = 0; iRow < numberRows; iRow++) {
137    int iPivot = pivotVariable[iRow];
138    double value = cost[iPivot];
139    if (value) {
140      array[iRow] = value;
141      index[number++] = iRow;
142    }
143  }
144  arrayVector.setNumElements(number);
145
146  int numberColumns = model->numberColumns();
147
148  // Btran basic costs
149  double *work = workSpace->denseVector();
150  model->factorization()->updateColumnTranspose(workSpace, &arrayVector);
151  ClpFillN(work, numberRows, 0.0);
152  // now look at dual solution
153  double *rowReducedCost = region + numberColumns;
154  double *dual = rowReducedCost;
155  double *rowCost = model->costRegion(0);
156  for (iRow = 0; iRow < numberRows; iRow++) {
157    dual[iRow] = array[iRow];
158  }
159  double *dj = region;
160  ClpDisjointCopyN(model->costRegion(1), numberColumns, dj);
161  model->transposeTimes(-1.0, dual, dj);
162  for (iRow = 0; iRow < numberRows; iRow++) {
163    // slack
164    double value = dual[iRow];
165    value += rowCost[iRow];
166    rowReducedCost[iRow] = value;
167  }
168  return 0.0;
169}
170/* Returns step length which gives minimum of objective for
171   solution + theta * change vector up to maximum theta.
172
173   arrays are numberColumns+numberRows
174*/
175double
176ClpLinearObjective::stepLength(ClpSimplex *model,
177  const double *solution,
178  const double *change,
179  double maximumTheta,
180  double &currentObj,
181  double &predictedObj,
182  double &thetaObj)
183{
184  const double *cost = model->costRegion();
185  double delta = 0.0;
186  int numberRows = model->numberRows();
187  int numberColumns = model->numberColumns();
188  currentObj = 0.0;
189  thetaObj = 0.0;
190  for (int iColumn = 0; iColumn < numberColumns + numberRows; iColumn++) {
191    delta += cost[iColumn] * change[iColumn];
192    currentObj += cost[iColumn] * solution[iColumn];
193  }
194  thetaObj = currentObj + delta * maximumTheta;
195  predictedObj = currentObj + delta * maximumTheta;
196  if (delta < 0.0) {
197    return maximumTheta;
198  } else {
199    printf("odd linear direction %g\n", delta);
200    return 0.0;
201  }
202}
203// Return objective value (without any ClpModel offset) (model may be NULL)
204double
205ClpLinearObjective::objectiveValue(const ClpSimplex *model, const double *solution) const
206{
207  const double *cost = objective_;
208  if (model && model->costRegion())
209    cost = model->costRegion();
210  double currentObj = 0.0;
211  for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
212    currentObj += cost[iColumn] * solution[iColumn];
213  }
214  return currentObj;
215}
216//-------------------------------------------------------------------
217// Clone
218//-------------------------------------------------------------------
219ClpObjective *ClpLinearObjective::clone() const
220{
221  return new ClpLinearObjective(*this);
222}
223/* Subset clone.  Duplicates are allowed
224   and order is as given.
225*/
226ClpObjective *
227ClpLinearObjective::subsetClone(int numberColumns,
228  const int *whichColumns) const
229{
230  return new ClpLinearObjective(*this, numberColumns, whichColumns);
231}
232// Resize objective
233void ClpLinearObjective::resize(int newNumberColumns)
234{
235  if (numberColumns_ != newNumberColumns) {
236    int i;
237    double *newArray = new double[newNumberColumns];
238    if (objective_)
239      CoinMemcpyN(objective_, CoinMin(newNumberColumns, numberColumns_), newArray);
240    delete[] objective_;
241    objective_ = newArray;
242    for (i = numberColumns_; i < newNumberColumns; i++)
243      objective_[i] = 0.0;
244    numberColumns_ = newNumberColumns;
245  }
246}
247// Delete columns in  objective
248void ClpLinearObjective::deleteSome(int numberToDelete, const int *which)
249{
250  if (objective_) {
251    int i;
252    char *deleted = new char[numberColumns_];
253    int numberDeleted = 0;
254    CoinZeroN(deleted, numberColumns_);
255    for (i = 0; i < numberToDelete; i++) {
256      int j = which[i];
257      if (j >= 0 && j < numberColumns_ && !deleted[j]) {
258        numberDeleted++;
259        deleted[j] = 1;
260      }
261    }
262    int newNumberColumns = numberColumns_ - numberDeleted;
263    double *newArray = new double[newNumberColumns];
264    int put = 0;
265    for (i = 0; i < numberColumns_; i++) {
266      if (!deleted[i]) {
267        newArray[put++] = objective_[i];
268      }
269    }
270    delete[] objective_;
271    objective_ = newArray;
272    delete[] deleted;
273    numberColumns_ = newNumberColumns;
274  }
275}
276// Scale objective
277void ClpLinearObjective::reallyScale(const double *columnScale)
278{
279  for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
280    objective_[iColumn] *= columnScale[iColumn];
281  }
282}
283
284/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
285*/
Note: See TracBrowser for help on using the repository browser.