1/* $Id: CoinPresolveFixed.cpp 1448 2011-06-19 15:34:41Z stefan $ */
2// Copyright (C) 2002, 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 <stdio.h>
7#include <math.h>
8
9#include "CoinPresolveMatrix.hpp"
10#include "CoinPresolveFixed.hpp"
11#include "CoinHelperFunctions.hpp"
12#include "CoinFinite.hpp"
13
14#if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY
15#include "CoinPresolvePsdebug.hpp"
16#endif
17
18/* Begin routines associated with remove_fixed_action */
19
20const char *remove_fixed_action::name() const
21{
22 return ("remove_fixed_action");
23}
24
25/*
26 * Original comment:
27 *
28 * invariant: both reps are loosely packed.
29 * coefficients of both reps remain consistent.
30 *
31 * Note that this concerns variables whose column bounds determine that
32 * they are slack; this does NOT concern singleton row constraints that
33 * determine that the relevant variable is slack.
34 *
35 * Invariant: col and row rep are consistent
36 */
37
38/*
39 This routine empties the columns for the list of fixed variables passed in
40 (fcols, nfcols). As each coefficient a<ij> is set to 0, rlo<i> and rup<i>
41 are adjusted accordingly. Note, however, that c<j> is not considered to be
42 removed from the objective until column j is physically removed from the
43 matrix (drop_empty_cols_action), so the correction to the objective is
44 adjusted there.
45
46 If a column solution is available, row activity (acts_) is adjusted.
47 remove_fixed_action implicitly assumes that the value of the variable has
48 already been forced within bounds. If this isn't true, the correction to
49 acts_ will be wrong. See make_fixed_action if you need to force the value
50 within bounds first.
51*/
52const remove_fixed_action*
53 remove_fixed_action::presolve (CoinPresolveMatrix *prob,
54 int *fcols,
55 int nfcols,
56 const CoinPresolveAction *next)
57{
58 double *colels = prob->colels_;
59 int *hrow = prob->hrow_;
60 CoinBigIndex *mcstrt = prob->mcstrt_;
61 int *hincol = prob->hincol_;
62
63 double *rowels = prob->rowels_;
64 int *hcol = prob->hcol_;
65 CoinBigIndex *mrstrt = prob->mrstrt_;
66 int *hinrow = prob->hinrow_;
67
68 double *clo = prob->clo_;
69 double *rlo = prob->rlo_;
70 double *rup = prob->rup_;
71 double *sol = prob->sol_;
72 double *acts = prob->acts_;
73
74 presolvehlink *clink = prob->clink_;
75 presolvehlink *rlink = prob->rlink_;
76
77 action *actions = new action[nfcols+1];
78
79# if PRESOLVE_DEBUG
80 std::cout << "Entering remove_fixed_action::presolve." << std::endl ;
81 presolve_check_sol(prob) ;
82 presolve_check_nbasic(prob) ;
83# endif
84
85/*
86 Scan columns to be removed and total up the number of coefficients.
87*/
88 int estsize=0;
89 int ckc;
90 for (ckc = 0 ; ckc < nfcols ; ckc++) {
91 int j = fcols[ckc];
92 estsize += hincol[j];
93 }
94// Allocate arrays to hold coefficients and associated row indices
95 double * els_action = new double[estsize];
96 int * rows_action = new int[estsize];
97 int actsize=0;
98 // faster to do all deletes in row copy at once
99 int nrows = prob->nrows_;
100 CoinBigIndex * rstrt = new int[nrows+1];
101 CoinZeroN(rstrt,nrows);
102/*
103 Open a loop to excise each column a<j>. The first thing to do is load the
104 action entry with the index j, the value of x<j>, and the number of
105 entries in a<j>. After we walk the column and tweak the row-major
106 representation, we'll simply claim this column is empty by setting
107 hincol[j] = 0.
108*/
109 for (ckc = 0 ; ckc < nfcols ; ckc++) {
110 int j = fcols[ckc];
111 double solj = clo[j];
112 CoinBigIndex kcs = mcstrt[j];
113 CoinBigIndex kce = kcs + hincol[j];
114 CoinBigIndex k;
115
116 { action &f = actions[ckc];
117 f.col = j;
118 f.sol = solj;
119 f.start = actsize;
120 }
121/*
122 Now walk a<j>. For each row i with a coefficient a<ij> != 0:
123 * save the coefficient and row index,
124 * substitute the value of x<j>, adjusting the row bounds and lhs value
125 accordingly, then
126 * delete a<ij> from the row-major representation.
127 * Finally: mark the row as changed and add it to the list of rows to be
128 processed next. Then, for each remaining column in the row, do the same.
129 (It makes sense to put the columns on the `to be processed' list, but
130 I'm wondering about the wisdom of marking them as changed.
131 -- lh, 040824 -- )
132*/
133 for (k = kcs ; k < kce ; k++) {
134 int row = hrow[k];
135 double coeff = colels[k];
136
137 els_action[actsize]=coeff;
138 rstrt[row]++; // increase counts
139 rows_action[actsize++]=row;
140
141 // Avoid reducing finite infinity.
142 if (-PRESOLVE_INF < rlo[row])
143 rlo[row] -= solj*coeff;
144 if (rup[row] < PRESOLVE_INF)
145 rup[row] -= solj*coeff;
146 if (sol) {
147 acts[row] -= solj*coeff;
148 }
149#define TRY2
150#ifndef TRY2
151 presolve_delete_from_row(row,j,mrstrt,hinrow,hcol,rowels);
152 if (hinrow[row] == 0)
153 { PRESOLVE_REMOVE_LINK(rlink,row) ; }
154
155 // mark unless already marked
156 if (!prob->rowChanged(row)) {
157 prob->addRow(row);
158 CoinBigIndex krs = mrstrt[row];
159 CoinBigIndex kre = krs + hinrow[row];
160 for (CoinBigIndex k=krs; k<kre; k++) {
161 int jcol = hcol[k];
162 prob->addCol(jcol);
163 }
164 }
165#endif
166 }
167/*
168 Remove the column's link from the linked list of columns, and declare
169 it empty in the column-major representation. Link removal must execute
170 even if the column is already of length 0 when it arrives.
171*/
172 PRESOLVE_REMOVE_LINK(clink, j);
173 hincol[j] = 0;
174 }
175/*
176 Set the actual end of the coefficient and row index arrays.
177*/
178 actions[nfcols].start=actsize;
179# if PRESOLVE_SUMMARY
180 printf("NFIXED: %d", nfcols);
181 if (estsize-actsize > 0)
182 { printf(", overalloc %d",estsize-actsize) ; }
183 printf("\n") ;
184# endif
185 // Now get columns by row
186 int * column = new int[actsize];
187 int nel=0;
188 int iRow;
189 for (iRow=0;iRow<nrows;iRow++) {
190 int n=rstrt[iRow];
191 rstrt[iRow]=nel;
192 nel += n;
193 }
194 rstrt[nrows]=nel;
195 for (ckc = 0 ; ckc < nfcols ; ckc++) {
196 int kcs = actions[ckc].start;
197 int j=actions[ckc].col;
198 int kce;
199 if (ckc<nfcols-1)
200 kce = actions[ckc+1].start;
201 else
202 kce = actsize;
203 for (int k=kcs;k<kce;k++) {
204 int iRow = rows_action[k];
205 CoinBigIndex put = rstrt[iRow];
206 rstrt[iRow]++;
207 column[put]=j;
208 }
209 }
210 // Now do rows
211 int ncols = prob->ncols_;
212 char * mark = new char[ncols];
213 memset(mark,0,ncols);
214 // rstrts are now one out i.e. rstrt[0] is end of row 0
215 nel=0;
216#ifdef TRY2
217 for (iRow=0;iRow<nrows;iRow++) {
218 int k;
219 for (k=nel;k<rstrt[iRow];k++) {
220 mark[column[k]]=1;
221 }
222 presolve_delete_many_from_major(iRow,mark,mrstrt,hinrow,hcol,rowels);
223#ifndef NDEBUG
224 for (k=nel;k<rstrt[iRow];k++) {
225 assert(mark[column[k]]==0);
226 }
227#endif
228 if (hinrow[iRow] == 0)
229 {
230 PRESOLVE_REMOVE_LINK(rlink,iRow) ;
231 }
232 // mark unless already marked
233 if (!prob->rowChanged(iRow)) {
234 prob->addRow(iRow);
235 CoinBigIndex krs = mrstrt[iRow];
236 CoinBigIndex kre = krs + hinrow[iRow];
237 for (CoinBigIndex k=krs; k<kre; k++) {
238 int jcol = hcol[k];
239 prob->addCol(jcol);
240 }
241 }
242 nel=rstrt[iRow];
243 }
244#endif
245 delete [] mark;
246 delete [] column;
247 delete [] rstrt;
248
249# if PRESOLVE_DEBUG
250 presolve_check_sol(prob) ;
251 std::cout << "Leaving remove_fixed_action::presolve." << std::endl ;
252# endif
253
254/*
255 Create the postsolve object, link it at the head of the list of postsolve
256 objects, and return a pointer.
257*/
258 return (new remove_fixed_action(nfcols,
259 actions,els_action,rows_action,next));
260}
261
262
263remove_fixed_action::remove_fixed_action(int nactions,
264 action *actions,
265 double * els_action,
266 int * rows_action,
267 const CoinPresolveAction *next) :
268 CoinPresolveAction(next),
269 colrows_(rows_action),
270 colels_(els_action),
271 nactions_(nactions),
272 actions_(actions)
273{
274}
275
276remove_fixed_action::~remove_fixed_action()
277{
278 deleteAction(actions_,action*);
279 delete [] colels_;
280 delete [] colrows_;
281}
282
283/*
284 * Say we determined that cup - clo <= ztolzb, so we fixed sol at clo.
285 * This involved subtracting clo*coeff from ub/lb for each row the
286 * variable occurred in.
287 * Now when we put the variable back in, by construction the variable
288 * is within tolerance, the non-slacks are unchanged, and the
289 * distances of the affected slacks from their bounds should remain
290 * unchanged (ignoring roundoff errors).
291 * It may be that by adding the term back in, the affected constraints
292 * now aren't as accurate due to round-off errors; this could happen
293 * if only one summand and the slack in the original formulation were large
294 * (and naturally had opposite signs), and the new term in the constraint
295 * is about the size of the old slack, so the new slack becomes about 0.
296 * It may be that there is catastrophic cancellation in the summation,
297 * so it might not compute to 0.
298 */
299void remove_fixed_action::postsolve(CoinPostsolveMatrix *prob) const
300{
301 action * actions = actions_;
302 const int nactions = nactions_;
303
304 double *colels = prob->colels_;
305 int *hrow = prob->hrow_;
306 CoinBigIndex *mcstrt = prob->mcstrt_;
307 int *hincol = prob->hincol_;
308 int *link = prob->link_;
309 CoinBigIndex &free_list = prob->free_list_;
310
311 double *clo = prob->clo_;
312 double *cup = prob->cup_;
313 double *rlo = prob->rlo_;
314 double *rup = prob->rup_;
315
316 double *sol = prob->sol_;
317 double *dcost = prob->cost_;
318 double *rcosts = prob->rcosts_;
319
320 double *acts = prob->acts_;
321 double *rowduals = prob->rowduals_;
322
323 unsigned char *colstat = prob->colstat_;
324
325 const double maxmin = prob->maxmin_;
326
327# if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY
328 char *cdone = prob->cdone_;
329
330 std::cout << "Entering remove_fixed_action::postsolve." << std::endl ;
331 presolve_check_threads(prob) ;
332 presolve_check_free_list(prob) ;
333 presolve_check_sol(prob) ;
334 presolve_check_nbasic(prob) ;
335# endif
336
337 double * els_action = colels_;
338 int * rows_action = colrows_;
339 int end = actions[nactions].start;
340
341/*
342 At one point, it turned out that forcing_constraint_action was putting
343 duplicates in the column list it passed to remove_fixed_action. This is now
344 fixed, but ... it looks to me like we could be in trouble here if we
345 reinstate a column multiple times. Hence the assert.
346*/
347 for (const action *f = &actions[nactions-1]; actions<=f; f--) {
348 int icol = f->col;
349 const double thesol = f->sol;
350
351# if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY
352 assert(cdone[icol] != FIXED_VARIABLE) ;
353 cdone[icol] = FIXED_VARIABLE ;
354# endif
355
356 sol[icol] = thesol;
357 clo[icol] = thesol;
358 cup[icol] = thesol;
359
360 int cs = NO_LINK ;
361 int start = f->start;
362 double dj = maxmin * dcost[icol];
363
364 for (int i=start; i<end; ++i) {
365 int row = rows_action[i];
366 double coeff =els_action[i];
367
368 // pop free_list
369 CoinBigIndex k = free_list;
370 assert(k >= 0 && k < prob->bulk0_) ;
371 free_list = link[free_list];
372 // restore
373 hrow[k] = row;
374 colels[k] = coeff;
375 link[k] = cs;
376 cs = k;
377
378 if (-PRESOLVE_INF < rlo[row])
379 rlo[row] += coeff * thesol;
380 if (rup[row] < PRESOLVE_INF)
381 rup[row] += coeff * thesol;
382 acts[row] += coeff * thesol;
383
384 dj -= rowduals[row] * coeff;
385 }
386
387# if PRESOLVE_CONSISTENCY
388 presolve_check_free_list(prob) ;
389# endif
390
391 mcstrt[icol] = cs;
392
393 rcosts[icol] = dj;
394 hincol[icol] = end-start;
395 end=start;
396
397 /* Original comment:
398 * the bounds in the reduced problem were tightened.
399 * that means that this variable may not have been basic
400 * because it didn't have to be,
401 * but now it may have to.
402 * no - the bounds aren't changed by this operation
403 */
404/*
405 We've reintroduced the variable, but it's still fixed (equal bounds).
406 Pick the nonbasic status that agrees with the reduced cost. Later, if
407 postsolve unfixes the variable, we'll need to confirm that this status is
408 still viable. We live in a minimisation world here.
409*/
410 if (colstat)
411 { if (dj < 0)
412 prob->setColumnStatus(icol,CoinPrePostsolveMatrix::atUpperBound);
413 else
414 prob->setColumnStatus(icol,CoinPrePostsolveMatrix::atLowerBound); }
415
416 }
417
418
419# if PRESOLVE_CONSISTENCY || PRESOLVE_DEBUG
420 presolve_check_threads(prob) ;
421 presolve_check_sol(prob) ;
422 presolve_check_nbasic(prob) ;
423 std::cout << "Leaving remove_fixed_action::postsolve." << std::endl ;
424# endif
425
426 return ;
427}
428
429/*
430 Scan the problem for variables that are already fixed, and remove them.
431 There's an implicit assumption that the value of the variable is already
432 within bounds. If you want to protect against this possibility, you want to
433 use make_fixed.
434*/
435const CoinPresolveAction *remove_fixed (CoinPresolveMatrix *prob,
436 const CoinPresolveAction *next)
437{
438 int ncols = prob->ncols_;
439 int *fcols = new int[ncols];
440 int nfcols = 0;
441
442 int *hincol = prob->hincol_;
443
444 double *clo = prob->clo_;
445 double *cup = prob->cup_;
446
447 for (int i = 0 ; i < ncols ; i++)
448 if (hincol[i] > 0 && clo[i] == cup[i]&&!prob->colProhibited2(i))
449 fcols[nfcols++] = i;
450
451 if (nfcols > 0)
452 { next = remove_fixed_action::presolve(prob, fcols, nfcols, next) ; }
453 delete[]fcols;
454 return (next);
455}
456
457/* End routines associated with remove_fixed_action */
458
459/* Begin routines associated with make_fixed_action */
460
461const char *make_fixed_action::name() const
462{
463 return ("make_fixed_action");
464}
465
466
467/*
468 This routine does the actual job of fixing one or more variables. The set
469 of indices to be fixed is specified by nfcols and fcols. fix_to_lower
470 specifies the bound where the variable(s) should be fixed. The other bound
471 is preserved as part of the action and the bounds are set equal. Note that
472 you don't get to specify the bound on a per-variable basis.
473
474 If a primal solution is available, make_fixed_action will adjust the the
475 row activity to compensate for forcing the variable within bounds. If the
476 bounds are already equal, and the variable is within bounds, you should
477 consider remove_fixed_action.
478*/
479const CoinPresolveAction*
480make_fixed_action::presolve (CoinPresolveMatrix *prob,
481 int *fcols, int nfcols,
482 bool fix_to_lower,
483 const CoinPresolveAction *next)
484
485{ double *clo = prob->clo_;
486 double *cup = prob->cup_;
487 double *csol = prob->sol_;
488
489 double *colels = prob->colels_;
490 int *hrow = prob->hrow_;
491 CoinBigIndex *mcstrt = prob->mcstrt_;
492 int *hincol = prob->hincol_;
493
494 double *acts = prob->acts_;
495
496/*
497 Shouldn't happen, but ...
498*/
499 if (nfcols <= 0) return (next) ;
500
501 action *actions = new action[nfcols];
502
503/*
504 Scan the set of indices specifying variables to be fixed. For each variable,
505 stash the unused bound in the action and set the bounds equal. If the client
506 has passed in a primal solution, update it if the value of the variable
507 changes.
508*/
509 for (int ckc = 0 ; ckc < nfcols ; ckc++)
510 { int j = fcols[ckc] ;
511 double movement = 0 ;
512
513 action &f = actions[ckc] ;
514
515 f.col = j ;
516 if (fix_to_lower) {
517 f.bound = cup[j];
518 cup[j] = clo[j];
519 if (csol) {
520 movement = clo[j]-csol[j] ;
521 csol[j] = clo[j] ;
522 }
523 } else {
524 f.bound = clo[j];
525 clo[j] = cup[j];
526 if (csol) {
527 movement = cup[j]-csol[j];
528 csol[j] = cup[j];
529 }
530 }
531 if (movement) {
532 CoinBigIndex k;
533 for (k = mcstrt[j] ; k < mcstrt[j]+hincol[j] ; k++) {
534 int row = hrow[k];
535 acts[row] += movement*colels[k];
536 }
537 }
538 }
539/*
540 Original comment:
541 This is unusual in that the make_fixed_action transform
542 contains within it a remove_fixed_action transform
543 bad idea?
544
545 Explanatory comment:
546 Now that we've adjusted the bounds, time to create the postsolve action
547 that will restore the original bounds. But wait! We're not done. By calling
548 remove_fixed_action::presolve, we will remove these variables from the
549 model, caching the postsolve transform that will restore them inside the
550 postsolve transform for fixing the bounds.
551*/
552 if (nfcols > 0)
553 { next = new make_fixed_action(nfcols, actions, fix_to_lower,
554 remove_fixed_action::presolve(prob,fcols, nfcols,0),
555 next) ; }
556 return (next) ;
557}
558
559/*
560 Recall that in presolve, make_fixed_action forced a bound to fix a variable,
561 then called remove_fixed_action to empty the column. removed_fixed_action
562 left a postsolve object hanging off faction_, and our first act here is to
563 call r_f_a::postsolve to repopulate the columns. The m_f_a postsolve activity
564 consists of relaxing one of the bounds and making sure that the status is
565 still viable (we can potentially eliminate the bound here).
566*/
567void make_fixed_action::postsolve(CoinPostsolveMatrix *prob) const
568{
569 const action *const actions = actions_;
570 const int nactions = nactions_;
571 const bool fix_to_lower = fix_to_lower_;
572
573 double *clo = prob->clo_;
574 double *cup = prob->cup_;
575 double *sol = prob->sol_ ;
576 unsigned char *colstat = prob->colstat_;
577/*
578 Repopulate the columns.
579*/
580 assert(nactions == faction_->nactions_) ;
581 faction_->postsolve(prob);
582/*
583 Walk the actions: restore each bound and check that the status is still
584 appropriate. Given that we're unfixing a fixed variable, it's safe to assume
585 that the unaffected bound is finite.
586*/
587 for (int cnt = nactions-1 ; cnt >= 0 ; cnt--)
588 { const action *f = &actions[cnt];
589 int icol = f->col;
590 double xj = sol[icol] ;
591
592 assert(faction_->actions_[cnt].col == icol) ;
593
594 if (fix_to_lower)
595 { double ub = f->bound ;
596 cup[icol] = ub ;
597 if (colstat)
598 { if (ub >= PRESOLVE_INF || xj != ub)
599 { prob->setColumnStatus(icol,
600 CoinPrePostsolveMatrix::atLowerBound) ; } } }
601 else
602 { double lb = f->bound ;
603 clo[icol] = lb ;
604 if (colstat)
605 { if (lb <= -PRESOLVE_INF || xj != lb)
606 { prob->setColumnStatus(icol,
607 CoinPrePostsolveMatrix::atUpperBound) ; } } } }
608
609# if PRESOLVE_CONSISTENCY || PRESOLVE_DEBUG
610 presolve_check_threads(prob) ;
611 presolve_check_sol(prob) ;
612 presolve_check_nbasic(prob) ;
613 std::cout << "Leaving make_fixed_action::postsolve." << std::endl ;
614# endif
615 return ; }
616
617/*!
618 Scan the columns and collect indices of columns that have upper and lower
619 bounds within the zero tolerance of one another. Hand this list to
620 make_fixed_action::presolve() to do the heavy lifting.
621
622 make_fixed_action will compensate for variables which are infeasible, forcing
623 them to feasibility and correcting the row activity, before invoking
624 remove_fixed_action to remove the variable from the problem. If you're
625 confident of feasibility, consider remove_fixed.
626*/
627const CoinPresolveAction *make_fixed (CoinPresolveMatrix *prob,
628 const CoinPresolveAction *next)
629{
630 int ncols = prob->ncols_;
631 int *fcols = new int[ncols];
632 int nfcols = 0;
633
634 int *hincol = prob->hincol_;
635
636 double *clo = prob->clo_;
637 double *cup = prob->cup_;
638
639 for (int i = 0 ; i < ncols ; i++)
640 { if (hincol[i] > 0 &&
641 fabs(cup[i] - clo[i]) < ZTOLDP && !prob->colProhibited2(i))
642 { fcols[nfcols++] = i ; } }
643
644/*
645 Call m_f_a::presolve to do the heavy lifting. This will create a new
646 CoinPresolveAction, which will become the head of the list of
647 CoinPresolveAction's currently pointed to by next.
648*/
649 next = make_fixed_action::presolve(prob,fcols,nfcols,true,next) ;
650
651 delete[]fcols ;
652 return (next) ; }
653// Transfers costs
654void
655transferCosts(CoinPresolveMatrix * prob)
656{
657 double *colels = prob->colels_;
658 int *hrow = prob->hrow_;
659 CoinBigIndex *mcstrt = prob->mcstrt_;
660 int *hincol = prob->hincol_;
661
662 double *rowels = prob->rowels_;
663 int *hcol = prob->hcol_;
664 CoinBigIndex *mrstrt = prob->mrstrt_;
665 int *hinrow = prob->hinrow_;
666
667 double *rlo = prob->rlo_;
668 double *rup = prob->rup_;
669 double *clo = prob->clo_;
670 double *cup = prob->cup_;
671 int ncols = prob->ncols_;
672 double *dcost = prob->cost_;
673 unsigned char * integerType = prob->integerType_;
674 double bias = prob->dobias_;
675 int icol;
676 int numberIntegers=0;
677 for (icol=0;icol<ncols;icol++) {
678 if (integerType[icol])
679 numberIntegers++;
680 }
681 int nchanged=0;
682 for (icol=0;icol<ncols;icol++) {
683 if (dcost[icol]&&hincol[icol]==1&&cup[icol]>clo[icol]) {
684 int irow=hrow[mcstrt[icol]];
685 if (rlo[irow]==rup[irow]) {
686 // transfer costs so can be made slack
687 double ratio = dcost[icol]/colels[mcstrt[icol]];
688 bias += rlo[irow]*ratio;
689 for (CoinBigIndex j=mrstrt[irow];j<mrstrt[irow]+hinrow[irow];j++) {
690 int jcol = hcol[j];
691 double value = rowels[j];
692 dcost[jcol] -= ratio*value;
693 }
694 dcost[icol]=0.0;
695 nchanged++;
696 }
697 }
698 }
699 //if (nchanged)
700 //printf("%d singleton columns have transferred costs\n",nchanged);
701 if (numberIntegers) {
702 int changed=-1;
703 while (changed) {
704 changed=0;
705 for (icol=0;icol<ncols;icol++) {
706 if (dcost[icol]&&cup[icol]>clo[icol]) {
707 for (CoinBigIndex k=mcstrt[icol];k<mcstrt[icol]+hincol[icol];k++) {
708 int irow=hrow[k];
709 if (rlo[irow]==rup[irow]) {
710 // See if can give more integer variables costs
711 CoinBigIndex j;
712 int nNow = integerType[icol] ? 1 : 0;
713 int nThen=0;
714 for (j=mrstrt[irow];j<mrstrt[irow]+hinrow[irow];j++) {
715 int jcol = hcol[j];
716 if (!dcost[jcol]&&integerType[jcol])
717 nThen++;
718 }
719 if (nThen>nNow) {
720 // transfer costs so can be made slack
721 double ratio = dcost[icol]/colels[mcstrt[icol]];
722 bias += rlo[irow]*ratio;
723 for (j=mrstrt[irow];j<mrstrt[irow]+hinrow[irow];j++) {
724 int jcol = hcol[j];
725 double value = rowels[j];
726 dcost[jcol] -= ratio*value;
727 }
728 dcost[icol]=0.0;
729 changed++;
730 break;
731 }
732 }
733 }
734 }
735 }
736 if (changed) {
737 nchanged+=changed;
738 //printf("%d changed this pass\n",changed);
739 }
740 }
741 }
742 //if (bias!=prob->dobias_)
743 //printf("new bias %g\n",bias);
744 prob->dobias_ = bias;
745}
746