1 | /* $Id: ClpSimplexPrimal.hpp 1665 2011-01-04 17:55:54Z lou $ */ |
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 | Authors |
7 | |
8 | John Forrest |
9 | |
10 | */ |
11 | #ifndef ClpSimplexPrimal_H |
12 | #define ClpSimplexPrimal_H |
13 | |
14 | #include "ClpSimplex.hpp" |
15 | |
16 | /** This solves LPs using the primal simplex method |
17 | |
18 | It inherits from ClpSimplex. It has no data of its own and |
19 | is never created - only cast from a ClpSimplex object at algorithm time. |
20 | |
21 | */ |
22 | |
23 | class ClpSimplexPrimal : public ClpSimplex { |
24 | |
25 | public: |
26 | |
27 | /**@name Description of algorithm */ |
28 | //@{ |
29 | /** Primal algorithm |
30 | |
31 | Method |
32 | |
33 | It tries to be a single phase approach with a weight of 1.0 being |
34 | given to getting optimal and a weight of infeasibilityCost_ being |
35 | given to getting primal feasible. In this version I have tried to |
36 | be clever in a stupid way. The idea of fake bounds in dual |
37 | seems to work so the primal analogue would be that of getting |
38 | bounds on reduced costs (by a presolve approach) and using |
39 | these for being above or below feasible region. I decided to waste |
40 | memory and keep these explicitly. This allows for non-linear |
41 | costs! I have not tested non-linear costs but will be glad |
42 | to do something if a reasonable example is provided. |
43 | |
44 | The code is designed to take advantage of sparsity so arrays are |
45 | seldom zeroed out from scratch or gone over in their entirety. |
46 | The only exception is a full scan to find incoming variable for |
47 | Dantzig row choice. For steepest edge we keep an updated list |
48 | of dual infeasibilities (actually squares). |
49 | On easy problems we don't need full scan - just |
50 | pick first reasonable. This method has not been coded. |
51 | |
52 | One problem is how to tackle degeneracy and accuracy. At present |
53 | I am using the modification of costs which I put in OSL and which was |
54 | extended by Gill et al. I am still not sure whether we will also |
55 | need explicit perturbation. |
56 | |
57 | The flow of primal is three while loops as follows: |
58 | |
59 | while (not finished) { |
60 | |
61 | while (not clean solution) { |
62 | |
63 | Factorize and/or clean up solution by changing bounds so |
64 | primal feasible. If looks finished check fake primal bounds. |
65 | Repeat until status is iterating (-1) or finished (0,1,2) |
66 | |
67 | } |
68 | |
69 | while (status==-1) { |
70 | |
71 | Iterate until no pivot in or out or time to re-factorize. |
72 | |
73 | Flow is: |
74 | |
75 | choose pivot column (incoming variable). if none then |
76 | we are primal feasible so looks as if done but we need to |
77 | break and check bounds etc. |
78 | |
79 | Get pivot column in tableau |
80 | |
81 | Choose outgoing row. If we don't find one then we look |
82 | primal unbounded so break and check bounds etc. (Also the |
83 | pivot tolerance is larger after any iterations so that may be |
84 | reason) |
85 | |
86 | If we do find outgoing row, we may have to adjust costs to |
87 | keep going forwards (anti-degeneracy). Check pivot will be stable |
88 | and if unstable throw away iteration and break to re-factorize. |
89 | If minor error re-factorize after iteration. |
90 | |
91 | Update everything (this may involve changing bounds on |
92 | variables to stay primal feasible. |
93 | |
94 | } |
95 | |
96 | } |
97 | |
98 | TODO's (or maybe not) |
99 | |
100 | At present we never check we are going forwards. I overdid that in |
101 | OSL so will try and make a last resort. |
102 | |
103 | Needs partial scan pivot in option. |
104 | |
105 | May need other anti-degeneracy measures, especially if we try and use |
106 | loose tolerances as a way to solve in fewer iterations. |
107 | |
108 | I like idea of dynamic scaling. This gives opportunity to decouple |
109 | different implications of scaling for accuracy, iteration count and |
110 | feasibility tolerance. |
111 | |
112 | for use of exotic parameter startFinishoptions see Clpsimplex.hpp |
113 | */ |
114 | |
115 | int primal(int ifValuesPass = 0, int startFinishOptions = 0); |
116 | //@} |
117 | |
118 | /**@name For advanced users */ |
119 | //@{ |
120 | /// Do not change infeasibility cost and always say optimal |
121 | void alwaysOptimal(bool onOff); |
122 | bool alwaysOptimal() const; |
123 | /** Normally outgoing variables can go out to slightly negative |
124 | values (but within tolerance) - this is to help stability and |
125 | and degeneracy. This can be switched off |
126 | */ |
127 | void exactOutgoing(bool onOff); |
128 | bool exactOutgoing() const; |
129 | //@} |
130 | |
131 | /**@name Functions used in primal */ |
132 | //@{ |
133 | /** This has the flow between re-factorizations |
134 | |
135 | Returns a code to say where decision to exit was made |
136 | Problem status set to: |
137 | |
138 | -2 re-factorize |
139 | -4 Looks optimal/infeasible |
140 | -5 Looks unbounded |
141 | +3 max iterations |
142 | |
143 | valuesOption has original value of valuesPass |
144 | */ |
145 | int whileIterating(int valuesOption); |
146 | |
147 | /** Do last half of an iteration. This is split out so people can |
148 | force incoming variable. If solveType_ is 2 then this may |
149 | re-factorize while normally it would exit to re-factorize. |
150 | Return codes |
151 | Reasons to come out (normal mode/user mode): |
152 | -1 normal |
153 | -2 factorize now - good iteration/ NA |
154 | -3 slight inaccuracy - refactorize - iteration done/ same but factor done |
155 | -4 inaccuracy - refactorize - no iteration/ NA |
156 | -5 something flagged - go round again/ pivot not possible |
157 | +2 looks unbounded |
158 | +3 max iterations (iteration done) |
159 | |
160 | With solveType_ ==2 this should |
161 | Pivot in a variable and choose an outgoing one. Assumes primal |
162 | feasible - will not go through a bound. Returns step length in theta |
163 | Returns ray in ray_ |
164 | */ |
165 | int pivotResult(int ifValuesPass = 0); |
166 | |
167 | |
168 | /** The primals are updated by the given array. |
169 | Returns number of infeasibilities. |
170 | After rowArray will have cost changes for use next iteration |
171 | */ |
172 | int updatePrimalsInPrimal(CoinIndexedVector * rowArray, |
173 | double theta, |
174 | double & objectiveChange, |
175 | int valuesPass); |
176 | /** |
177 | Row array has pivot column |
178 | This chooses pivot row. |
179 | Rhs array is used for distance to next bound (for speed) |
180 | For speed, we may need to go to a bucket approach when many |
181 | variables go through bounds |
182 | If valuesPass non-zero then compute dj for direction |
183 | */ |
184 | void primalRow(CoinIndexedVector * rowArray, |
185 | CoinIndexedVector * rhsArray, |
186 | CoinIndexedVector * spareArray, |
187 | int valuesPass); |
188 | /** |
189 | Chooses primal pivot column |
190 | updateArray has cost updates (also use pivotRow_ from last iteration) |
191 | Would be faster with separate region to scan |
192 | and will have this (with square of infeasibility) when steepest |
193 | For easy problems we can just choose one of the first columns we look at |
194 | */ |
195 | void primalColumn(CoinIndexedVector * updateArray, |
196 | CoinIndexedVector * spareRow1, |
197 | CoinIndexedVector * spareRow2, |
198 | CoinIndexedVector * spareColumn1, |
199 | CoinIndexedVector * spareColumn2); |
200 | |
201 | /** Checks if tentative optimal actually means unbounded in primal |
202 | Returns -3 if not, 2 if is unbounded */ |
203 | int checkUnbounded(CoinIndexedVector * ray, CoinIndexedVector * spare, |
204 | double changeCost); |
205 | /** Refactorizes if necessary |
206 | Checks if finished. Updates status. |
207 | lastCleaned refers to iteration at which some objective/feasibility |
208 | cleaning too place. |
209 | |
210 | type - 0 initial so set up save arrays etc |
211 | - 1 normal -if good update save |
212 | - 2 restoring from saved |
213 | saveModel is normally NULL but may not be if doing Sprint |
214 | */ |
215 | void statusOfProblemInPrimal(int & lastCleaned, int type, |
216 | ClpSimplexProgress * progress, |
217 | bool doFactorization, |
218 | int ifValuesPass, |
219 | ClpSimplex * saveModel = nullptr); |
220 | /// Perturbs problem (method depends on perturbation()) |
221 | void perturb(int type); |
222 | /// Take off effect of perturbation and say whether to try dual |
223 | bool unPerturb(); |
224 | /// Unflag all variables and return number unflagged |
225 | int unflag(); |
226 | /** Get next superbasic -1 if none, |
227 | Normal type is 1 |
228 | If type is 3 then initializes sorted list |
229 | if 2 uses list. |
230 | */ |
231 | int nextSuperBasic(int superBasicType, CoinIndexedVector * columnArray); |
232 | |
233 | /// Create primal ray |
234 | void primalRay(CoinIndexedVector * rowArray); |
235 | /// Clears all bits and clears rowArray[1] etc |
236 | void clearAll(); |
237 | |
238 | /// Sort of lexicographic resolve |
239 | int lexSolve(); |
240 | |
241 | //@} |
242 | }; |
243 | #endif |
244 | |