1 // (C) Copyright Francois Margot and Carnegie Mellon University 2011
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License (EPL).
4 //
5 // Authors :
6 // Francois Margot, Tepper School of Business, Carnegie Mellon University,
7 //
8 // Date : 3/31/2011
9
10 #include<cstdio>
11 #include<cstdlib>
12 #include<cstring>
13 #include<cmath>
14
15 #include "CoinHelperFunctions.hpp"
16
17 #include "CouenneProblem.hpp"
18 #include "CouenneRecordBestSol.hpp"
19
20 using namespace Couenne;
21
22 //#define TRACE
23
24 /*************************************************************/
25 /** Default constructor. */
CouenneRecordBestSol()26 CouenneRecordBestSol::CouenneRecordBestSol() {
27
28 cardInitDom = -1;
29 initIsInt = NULL;
30 initDomLb = NULL;
31 initDomUb = NULL;
32
33 hasSol = false;
34 cardSol = -1;
35 sol = NULL;
36 val = -1;
37 maxViol = -1;
38
39 cardModSol = -1;
40 modSol = NULL;
41 modSolVal = -1;
42 modSolMaxViol = -1;
43 }
44
45 /*************************************************************/
46 // copy constructor
CouenneRecordBestSol(const CouenneRecordBestSol & other)47 CouenneRecordBestSol::CouenneRecordBestSol(const CouenneRecordBestSol &other) {
48
49 cardInitDom = other.cardInitDom;
50 if(cardInitDom > -1) {
51 initIsInt = new bool[other.cardInitDom];
52 initDomLb = new CouNumber[other.cardInitDom];
53 initDomUb = new CouNumber[other.cardInitDom];
54
55 CoinCopyN(other.initIsInt, cardInitDom, initIsInt);
56 CoinCopyN(other.initDomLb, cardInitDom, initDomLb);
57 CoinCopyN(other.initDomUb, cardInitDom, initDomUb);
58 }
59 else {
60 initIsInt = NULL;
61 initDomLb = NULL;
62 initDomUb = NULL;
63 }
64
65 for(unsigned int i=0; i<other.listInt.size(); i++) {
66 listInt.push_back(other.listInt[i]);
67 }
68
69 hasSol = other.hasSol;
70 cardSol = other.cardSol;
71 val = other.val;
72 maxViol = other.maxViol;
73
74 if(other.sol != NULL) {
75 sol = new double[other.cardSol];
76 CoinCopyN(other.sol, cardSol, sol);
77 }
78 else {
79 sol = NULL;
80 }
81
82 if (other.modSol != NULL) {
83 modSol = new double[other.cardSol];
84 CoinCopyN(other.modSol, cardSol, modSol);
85 }
86 else {
87 modSol = NULL;
88 }
89 cardModSol = other.cardModSol;
90 modSolVal = other.modSolVal;
91 modSolMaxViol = other.modSolMaxViol;
92 }
93
94 /*************************************************************/
95 /** Destructor. */
~CouenneRecordBestSol()96 CouenneRecordBestSol::~CouenneRecordBestSol(){
97
98 if(cardInitDom > -1) {
99 delete[] initIsInt;
100 delete[] initDomLb;
101 delete[] initDomUb;
102 }
103
104 if(sol != NULL) {
105 delete[] sol;
106 }
107
108 if(modSol != NULL) {
109 delete[] modSol;
110 }
111 }
112
113 /*****************************************************************************/
setInitIsInt(const bool * givenIsInt,const int givenCard)114 void CouenneRecordBestSol::setInitIsInt(const bool *givenIsInt,
115 const int givenCard) {
116
117 if(initIsInt == NULL) {
118 if(cardInitDom == -1) {
119 cardInitDom = givenCard;
120 }
121 if(givenCard != cardInitDom) {
122 printf("### ERROR: CouenneRecordBestSol::setInitIsInt(): cardInitDom: %d givenCard: %d\n", cardInitDom, givenCard);
123 exit(1);
124 }
125 initIsInt = new bool[givenCard];
126 }
127 else {
128 if(givenCard != cardInitDom) {
129 printf("### ERROR: CouenneRecordBestSol::setInitIsInt(): cardInitDom: %d givenCard: %d\n", cardInitDom, givenCard);
130 exit(1);
131 }
132 }
133 CoinCopyN(givenIsInt, givenCard, initIsInt);
134
135 listInt.empty();
136 for(int i=0; i<givenCard; i++) {
137 if(initIsInt[i]) {
138 listInt.push_back(i);
139 }
140 }
141 } /* setInitIsInt */
142
143 /*****************************************************************************/
setInitDomLb(const CouNumber * givenLb,const int givenCard)144 void CouenneRecordBestSol::setInitDomLb(const CouNumber *givenLb,
145 const int givenCard) {
146 if(initDomLb == NULL) {
147 if(cardInitDom == -1) {
148 cardInitDom = givenCard;
149 }
150 if(givenCard != cardInitDom) {
151 printf("### ERROR: CouenneRecordBestSol::setInitDomLb(): cardInitDom: %d givenCard: %d\n", cardInitDom, givenCard);
152 exit(1);
153 }
154 initDomLb = new CouNumber[givenCard];
155 }
156 else {
157 if(givenCard != cardInitDom) {
158 printf("### ERROR: CouenneRecordBestSol::setInitDomLb(): cardInitDom: %d givenCard: %d\n", cardInitDom, givenCard);
159 exit(1);
160 }
161 }
162 CoinCopyN(givenLb, givenCard, initDomLb);
163 } /* setInitDomLb */
164
165 /*****************************************************************************/
setInitDomUb(const CouNumber * givenUb,const int givenCard)166 void CouenneRecordBestSol::setInitDomUb(const CouNumber *givenUb,
167 const int givenCard) {
168 if(initDomUb == NULL) {
169 if(cardInitDom == -1) {
170 cardInitDom = givenCard;
171 }
172 if(givenCard != cardInitDom) {
173 printf("### ERROR: CouenneRecordBestSol::setInitDomUb(): cardInitDom: %d givenCard: %d\n", cardInitDom, givenCard);
174 exit(1);
175 }
176 initDomUb = new CouNumber[givenCard];
177 }
178 else {
179 if(givenCard != cardInitDom) {
180 printf("### ERROR: CouenneRecordBestSol::setInitDomUb(): cardInitDom: %d givenCard: %d\n", cardInitDom, givenCard);
181 exit(1);
182 }
183 }
184 CoinCopyN(givenUb, givenCard, initDomUb);
185 } /* setInitDomUb */
186
187 /*****************************************************************************/
setHasSol(const bool givenHasSol)188 void CouenneRecordBestSol::setHasSol(const bool givenHasSol) {
189 hasSol = givenHasSol;
190 }
191
192 /*****************************************************************************/
setCardSol(const int givenCard)193 void CouenneRecordBestSol::setCardSol(const int givenCard) {
194 cardSol = givenCard;
195 }
196
197 /*****************************************************************************/
setSol(const double * givenSol,const int givenCard,const double givenMaxViol)198 void CouenneRecordBestSol::setSol(const double *givenSol, const int givenCard,
199 const double givenMaxViol) {
200 if(sol == NULL) {
201 cardSol = givenCard;
202 sol = new double[givenCard];
203 if(modSol == NULL) {
204 modSol = new double[givenCard];
205 }
206 }
207 else {
208 if(givenCard != cardSol) {
209 //printf("CouenneRecordBestSol::setSol(): ### ERROR: givenCard: %d cardSol: %d", givenCard, cardSol);
210 //exit(1);
211
212 double *newSol = new double [givenCard];
213 CoinCopyN (givenSol, givenCard, newSol);
214 delete [] modSol;
215 modSol = newSol;
216 cardSol = givenCard;
217 }
218 }
219 CoinCopyN(givenSol, givenCard, sol);
220 maxViol = givenMaxViol;
221
222 #ifdef TRACE
223 printf("CouenneRecordBestSol::setSol(): New solution set\n");
224 #endif
225
226 } /* setSol */
227
228 /*****************************************************************************/
setVal(const double givenVal)229 void CouenneRecordBestSol::setVal(const double givenVal) {
230
231 #ifdef TRACE
232 printf("CouenneRecordBestSol::setVal(): set to %10.6f\n", givenVal);
233 #endif
234
235 val = givenVal;
236 hasSol = true;
237 }
238
239 /*****************************************************************************/
update(const double * givenSol,const int givenCard,const double givenVal,const double givenMaxViol)240 void CouenneRecordBestSol::update(const double *givenSol, const int givenCard,
241 const double givenVal, const double givenMaxViol) {
242 if (!hasSol || (givenVal < val)) {
243 setSol(givenSol, givenCard, givenMaxViol);
244 setVal(givenVal);
245 }
246 } /* update */
247
248 /*****************************************************************************/
update()249 void CouenneRecordBestSol::update() {
250 if(modSol == NULL) {
251 printf(" CouenneRecordBestSol::update(): ### ERROR: modSol == NULL\n");
252 exit(1);
253 }
254
255 update(modSol, cardModSol, modSolVal, modSolMaxViol);
256 } /* update */
257
258 /*****************************************************************************/
compareAndSave(const double * solA,const double solAVal,const double solAMaxViol,const bool solAIsFeas,const double * solB,const double solBVal,const double solBMaxViol,const bool solBIsFeas,const int cardSol,const double precision)259 int CouenneRecordBestSol::compareAndSave(const double *solA, const double solAVal, const double solAMaxViol, const bool solAIsFeas,
260 const double *solB, const double solBVal, const double solBMaxViol, const bool solBIsFeas,
261 const int cardSol,
262 const double precision) {
263 int retval = -2;
264 if(solBIsFeas) {
265 if(solAIsFeas) {
266 if(solAVal < solBVal - precision) {
267 retval = 0;
268 }
269 else {
270 retval = 1;
271 }
272 }
273 else {
274 retval = 1;
275 }
276 }
277 else {
278 if(solAIsFeas) {
279 retval = 0;
280 }
281 else { // both solutions are infeasible; select the one with min viol.
282 if(solAVal < 1e49) {
283 if(solBVal < 1e49) {
284 if(solAMaxViol < solBMaxViol) {
285 retval = 0;
286 }
287 else {
288 retval = 1;
289 }
290 }
291 else {
292 retval = 0;
293 }
294 }
295 else {
296 if(solBVal < 1e49) {
297 retval = 1;
298 }
299 else {
300 retval = -1;
301 }
302 }
303 }
304 }
305
306 switch (retval) {
307 case 0: update(solA, cardSol, solAVal, solAMaxViol); break;
308 case 1: update(solB, cardSol, solBVal, solBMaxViol); break;
309 case -1: break;
310 default: printf("CouenneRecordBestSol::compareAndSave(): ### ERROR: retval: %d\n",
311 retval); break;
312 }
313
314 return(retval);
315 } /* compareAndSave */
316
317 /*****************************************************************************/
getModSol(const int expectedCard)318 double * CouenneRecordBestSol::getModSol(const int expectedCard) {
319 if(modSol == NULL) {
320 cardModSol = expectedCard;
321 modSol = new double[expectedCard];
322 }
323 else {
324 if(expectedCard != cardModSol) {
325 printf("CouenneRecordBestSol::getModSol(): ### ERROR: expectedCard: %d cardModSol: %d", expectedCard, cardModSol);
326 exit(1);
327 }
328 }
329 return modSol;
330 } /* getModSol */
331
332 /*****************************************************************************/
setModSol(const double * givenModSol,const int givenModCard,const double givenModVal,const double givenModMaxViol)333 void CouenneRecordBestSol::setModSol(const double *givenModSol,
334 const int givenModCard,
335 const double givenModVal,
336 const double givenModMaxViol) {
337
338 if(givenModSol != NULL) {
339 if(modSol == NULL) {
340 cardModSol = givenModCard;
341 modSol = new double[givenModCard];
342 }
343 else {
344 if(givenModCard != cardModSol) {
345 // printf("CouenneRecordBestSol::setModSol(): ### ERROR: givenModCard: %d cardModSol: %d", givenModCard, cardModSol);
346 // exit(1);
347
348 double *newModSol = new double [givenModCard];
349 CoinCopyN (givenModSol, givenModCard, newModSol);
350 delete [] modSol;
351 modSol = newModSol;
352 cardModSol = givenModCard;
353 }
354 }
355 CoinCopyN(givenModSol, givenModCard, modSol);
356 }
357 modSolVal = givenModVal;
358 modSolMaxViol = givenModMaxViol;
359 } /* setModSol */
360
361 /*****************************************************************************/
printSol(FILE * fsol) const362 void CouenneRecordBestSol::printSol(FILE *fsol) const {
363
364 if(sol != NULL) {
365 fprintf(fsol, "%d\n", cardSol);
366 for(int i=0; i<cardSol; i++) {
367 fprintf(fsol, " %12.8f", sol[i]);
368 if(i % 10 == 9) {
369 fprintf(fsol, "\n");
370 }
371 }
372 if(cardSol % 10 != 0) {
373 fprintf(fsol, "\n");
374 }
375 fprintf(fsol, "Value: %16.14g\n", val);
376 fprintf(fsol, "Tolerance: %16.14g\n", maxViol);
377 }
378 } /* printSol */
379