Dip-All  0.91.0
GAP_KnapPisinger.h
Go to the documentation of this file.
1 //===========================================================================//
2 // This file is part of the Decomp Solver Framework. //
3 // //
4 // Decomp is distributed under the Common Public License as part of the //
5 // COIN-OR repository (http://www.coin-or.org). //
6 // //
7 // Author: Matthew Galati, Lehigh University //
8 // //
9 // Copyright (C) 2002-2015, Lehigh University, Matthew Galati, and Ted Ralphs//
10 // All Rights Reserved. //
11 //===========================================================================//
12 
13 #ifndef GAP_KNAP_PISINGER_INCLUDED
14 #define GAP_KNAP_PISINGER_INCLUDED
15 
16 // --------------------------------------------------------------------- //
61 // --------------------------------------------------------------------- //
62 extern "C" {
63 #include "combo.h"
64 }
65 
66 // --------------------------------------------------------------------- //
67 #include "UtilMacros.h"
68 
69 // --------------------------------------------------------------------- //
71 
72 private:
73  int m_nItems; //< number of items (== nTasks)
74  item* m_items; //< array of items for Pisinger solver
75  int m_capacity; //< capacity of knapsack
76  int* m_weight; //< weight of items
77  int* m_profit; //< profit of items
78  double* m_workDbl; //< temp work space
79 
80 private:
81  inline const int getIndexIJ(const int i,
82  const int j) const {
83  return (i * m_nItems) + j;
84  }
85 
86  //1.0e-6 seems to cause overflow
87  int calcScaleFactor(const double* redCost,
88  const double epsTol = 1.0e-4) {
89  //---
90  //--- A very simple function to scale an array of doubles to integers.
91  //--- Note: epstol denotes the preferred accuracy,
92  //--- so, we will scale by 1.0/epstol, unless something smaller works.
93  //--- It returns the scale factor.
94  //---
95  //--- Since the knapsack solver solves the max problem, we will
96  //--- flip the sign of the redCost first (max p == min -p).
97  //---
98  //--- This also means that we can look just at redCost[i] <= 0.
99  //---
100  int i, scaleFactor = 1, n_aFrac = 0, factorToBig = 0;
101  double fractionalPart, rcFlipped;
102  double oneOverEps = 1.0 / epsTol;
103 
104  for (i = 0; i < m_nItems; i++) {
105  if (redCost[i] >= 0) {
106  continue;
107  }
108 
109  rcFlipped = -redCost[i];
110  fractionalPart = UtilFracPart(rcFlipped);
111 
112  if (!UtilIsZero(fractionalPart)) {
113  fractionalPart *= oneOverEps;
114  m_workDbl[n_aFrac++] = (int)fractionalPart * (double)epsTol;
115  }
116  }
117 
118  for (i = 0; i < n_aFrac; i++) {
119  CoinAssertDebug(m_workDbl[i] < (COIN_INT_MAX / scaleFactor));
120  m_workDbl[i] *= scaleFactor;
121 
122  while (!UtilIsZero(UtilFracPart(m_workDbl[i]))) {
123  scaleFactor *= 10;
124 
125  if (scaleFactor >= oneOverEps) {
126  factorToBig = 1;
127  break;
128  }
129 
131  m_workDbl[i] *= 10;
132  CoinAssertDebug(m_workDbl[i] >= 0);
133  }
134 
135  if (factorToBig) {
136  break;
137  }
138  }
139 
140  return scaleFactor;
141  }
142 
143 public:
144  void solve(const int blockB,
145  const double* redCost,
146  const double* origCost,
147  vector<int>& solInd,
148  vector<double>& solEls,
149  double& varRedCost,
150  double& varOrigCost) {
151  //---
152  //--- Since we want to find min redCost, and the constraint is a
153  //--- simple knapsack constraint, we know that if redCost[i] >= 0
154  //--- then we can fix x[i]=0. It makes no sense to select.
155  //---
156  //--- The knapsack solver solves maximization problem, so we also
157  //--- need to fip the sign of the redCost.
158  //---
159  //--- The knapsack solver also expects integers for weight and profit,
160  //--- the weights are already integer, but since the profits are coming
161  //--- from reduced cost, we need to scale them to integers
162  //---
163  int i, j;
164  int nItems = 0;
165  int scaleFactor = calcScaleFactor(redCost);
166  double rcScaled;
167  int weightSum = 0;
168  vector<int> shrunkToOrig;
169 
170  for (i = 0; i < m_nItems; i++) {
171  if (redCost[i] < 0.0) {
172  rcScaled = (-redCost[i]) * scaleFactor;
173  long rcLong = static_cast<long>(floor(rcScaled + 0.5));
174  CoinAssert(rcScaled < COIN_INT_MAX);
175  m_items[nItems].p = rcLong;
176  CoinAssert(m_items[nItems].p >= 0);
177  m_items[nItems].w = m_weight[i];
178  m_items[nItems].i = nItems;
179  m_items[nItems].x = 0;
180  weightSum += m_weight[i];
181  shrunkToOrig.push_back(i);
182  nItems++;
183  }
184  }
185 
186  //---
187  //--- print the current problem
188  //---
189  /*
190  printf("COMBO Knap Max (nItems = %d, cap=%d)\n", nItems, m_capacity);
191  for(i = 0; i < nItems; i++){
192  j = shrunkToOrig[i];
193  printf("[%d->%d] pOrig:%g, p:%ld, w:%ld\n",
194  i, j, -redCost[j], m_items[i].p, m_items[i].w);
195  }
196  */
197 
198  //---
199  //--- solve the knapsack problem
200  //--- first deal with some trivial cases
201  if (nItems == 1) {
202  CoinAssert(m_items[0].w <= m_capacity);
203  m_items[0].x = 1;
204  } else if (weightSum <= m_capacity) {
205  //---
206  //--- then put all items in the knapsack (to max profit)
207  //---
208  for (i = 0; i < nItems; i++) {
209  m_items[i].x = 1;
210  }
211  } else if (nItems == 2) {
212  CoinAssert(m_items[0].w <= m_capacity);
213  CoinAssert(m_items[1].w <= m_capacity);
214  int w0 = m_items[0].w;
215  int w1 = m_items[1].w;
216  int p0 = m_items[0].p;
217  int p1 = m_items[1].p;
218  double bestObj = 0;
219 
220  if ( (w1 <= m_capacity) && (p1 > bestObj) ) {
221  bestObj = p1;
222  m_items[0].x = 0;
223  m_items[1].x = 1;
224  }
225 
226  if ( (w0 <= m_capacity) && (p0 > bestObj) ) {
227  bestObj = p0;
228  m_items[0].x = 1;
229  m_items[1].x = 0;
230  }
231 
232  if ( (w0 + w1 <= m_capacity) && (p0 + p1 > bestObj) ) {
233  bestObj = p0 + p1;
234  m_items[0].x = 1;
235  m_items[1].x = 1;
236  }
237  } else if (nItems > 2) {
238  item* fItem = m_items;
239  item* lItem = m_items + (nItems - 1);
240  long obj = 0;
241  obj = combo(fItem, //first item
242  lItem, //last item
243  m_capacity, //capacity of knapsack
244  -COIN_INT_MAX, //obj lower bound
245  COIN_INT_MAX, //obj upper bound
246  1, //define sol vector
247  0); //do not solve relaxed prob
248  //printf("combo obj = %ld\n", obj);
249  }
250 
251  int origColIndex;
252  /*int wtSum = 0;
253  for(i = 0; i < nItems; i++)
254  printf("m_items[%d].x=%d i=%d p=%ld w=%ld\n",
255  i,
256  m_items[i].i,
257  m_items[i].x,
258  m_items[i].p,
259  m_items[i].w);*/
260 
261  for (i = 0; i < nItems; i++) {
262  if (m_items[i].x == 1) {
263  j = shrunkToOrig[m_items[i].i];
264  origColIndex = getIndexIJ(blockB, j);
265  varRedCost += redCost[j];
266  varOrigCost += origCost[j];
267  solInd.push_back(origColIndex);
268  solEls.push_back(1.0);
269  }
270  }
271  }
272 
273 public:
274  GAP_KnapPisinger(const int nItems,
275  const int capacity,
276  const int* weight,
277  const int* profit) :
278  m_nItems (nItems),
279  m_items (0),
280  m_capacity (capacity),
281  m_weight (0),
282  m_profit (0),
283  m_workDbl (0) {
284  m_items = new item[nItems];
285  m_weight = new int[nItems];
286  m_profit = new int[nItems];
287  m_workDbl = new double[nItems];
289  "Error: Out of Memory");
290  memcpy(m_weight, weight, nItems * sizeof(int));
291  memcpy(m_profit, profit, nItems * sizeof(int));
292  }
298  }
299 };
300 
301 
302 #endif
const int getIndexIJ(const int i, const int j) const
bool UtilIsZero(const double x, const double etol=1.0e-8)
Definition: UtilMacros.h:272
void solve(const int blockB, const double *redCost, const double *origCost, vector< int > &solInd, vector< double > &solEls, double &varRedCost, double &varOrigCost)
#define UTIL_DELARR(x)
Definition: UtilMacros.h:29
#define CoinAssertHint(expression, hint)
Definition: CoinError.hpp:180
const int COIN_INT_MAX
Definition: CoinFinite.hpp:19
int calcScaleFactor(const double *redCost, const double epsTol=1.0e-4)
Types and protos for combo algorithm API:
GAP_KnapPisinger(const int nItems, const int capacity, const int *weight, const int *profit)
#define CoinAssertDebug(expression)
Definition: CoinError.hpp:177
double UtilFracPart(const double x)
Definition: UtilMacros.h:243
#define CoinAssert(expression)
Definition: CoinError.hpp:179