44
55const bool dev_run = false ;
66
7- struct IterationCount {
8- HighsInt simplex;
9- HighsInt ipm;
10- HighsInt crossover;
11- };
127
138void testDualObjective (const std::string model) {
149 HighsStatus return_status;
@@ -30,295 +25,6 @@ void testDualObjective(const std::string model) {
3025 REQUIRE (relative_primal_dual_gap < 1e-12 );
3126}
3227
33- void testSolver (Highs& highs, const std::string solver,
34- IterationCount& default_iteration_count,
35- const HighsInt int_simplex_strategy = 0 ) {
36- double default_time_limit;
37- HighsInt default_simplex_iteration_limit;
38- HighsInt default_ipm_iteration_limit;
39- HighsModelStatus model_status;
40- HighsStatus return_status;
41- const bool perform_timeout_test = false ; // true; //
42- bool use_simplex = solver == " simplex" ;
43- const HighsInfo& info = highs.getInfo ();
44-
45- if (!dev_run) highs.setOptionValue (" output_flag" , false );
46- return_status = highs.setOptionValue (" solver" , solver);
47- REQUIRE (return_status == HighsStatus::kOk );
48-
49- if (use_simplex) {
50- SimplexStrategy simplex_strategy =
51- static_cast <SimplexStrategy>(int_simplex_strategy);
52- if (simplex_strategy == SimplexStrategy::kSimplexStrategyDualTasks ) return ;
53- if (dev_run)
54- printf (" Simplex strategy %" HIGHSINT_FORMAT " \n " , int_simplex_strategy);
55- return_status = highs.setOptionValue (" simplex_strategy" , simplex_strategy);
56- REQUIRE (return_status == HighsStatus::kOk );
57- }
58-
59- return_status = highs.getOptionValue (" time_limit" , default_time_limit);
60- REQUIRE (return_status == HighsStatus::kOk );
61-
62- if (use_simplex) {
63- return_status = highs.getOptionValue (" simplex_iteration_limit" ,
64- default_simplex_iteration_limit);
65- REQUIRE (return_status == HighsStatus::kOk );
66- // Clear the solver information - necessary if this is the second
67- // or subsequent call to testSolver
68- return_status = highs.clearSolver ();
69- REQUIRE (return_status == HighsStatus::kOk );
70- } else {
71- return_status = highs.getOptionValue (" ipm_iteration_limit" ,
72- default_ipm_iteration_limit);
73- REQUIRE (return_status == HighsStatus::kOk );
74- }
75-
76- // Vanilla solve: get solution time to calibrate time limit test
77- double run_time = highs.getRunTime ();
78- return_status = highs.run ();
79- REQUIRE (return_status == HighsStatus::kOk );
80- const double single_solve_run_time = highs.getRunTime () - run_time;
81-
82- if (use_simplex) {
83- REQUIRE (info.simplex_iteration_count == default_iteration_count.simplex );
84- } else {
85- if (dev_run)
86- printf (" IPM: %" HIGHSINT_FORMAT " ; Crossover: %" HIGHSINT_FORMAT " \n " ,
87- info.ipm_iteration_count , info.crossover_iteration_count );
88- REQUIRE (info.ipm_iteration_count == default_iteration_count.ipm );
89- REQUIRE (info.crossover_iteration_count ==
90- default_iteration_count.crossover );
91- }
92- // Following simplex or IPM+Crossover, nonbasic variables are on bounds
93- // complementarity_violation
94- REQUIRE (info.max_complementarity_violation == 0 );
95- REQUIRE (info.sum_complementarity_violations == 0 );
96-
97- // Only perform the time limit test if the solve time is large enough
98- const double min_run_time_for_test = 0.001 ;
99- if (perform_timeout_test && single_solve_run_time > min_run_time_for_test) {
100- const HighsInt ideal_num_solve = 10 ;
101- const double local_time_limit = ideal_num_solve * single_solve_run_time;
102-
103- // Solve with time limit
104- run_time = highs.getRunTime ();
105- if (dev_run) printf (" Current run time is %g\n " , run_time);
106-
107- double use_time_limit = run_time + local_time_limit;
108- return_status = highs.setOptionValue (" time_limit" , use_time_limit);
109- REQUIRE (return_status == HighsStatus::kOk );
110-
111- const HighsInt max_num_solve = 10 * ideal_num_solve;
112- HighsInt num_solve;
113- for (num_solve = 0 ; num_solve < max_num_solve; num_solve++) {
114- if (use_simplex) return_status = highs.setBasis ();
115- return_status = highs.run ();
116- if (highs.getModelStatus () == HighsModelStatus::kTimeLimit ) break ;
117- }
118- REQUIRE (num_solve < max_num_solve);
119- run_time = highs.getRunTime ();
120- if (dev_run)
121- printf (" Current run time is %g: time limit is %g (difference = %g)\n " ,
122- run_time, use_time_limit, run_time - use_time_limit);
123-
124- if (dev_run)
125- printf (" Required %" HIGHSINT_FORMAT " solves (ideally %" HIGHSINT_FORMAT
126- " - max %" HIGHSINT_FORMAT " )\n " ,
127- num_solve, ideal_num_solve, max_num_solve);
128- } else {
129- if (dev_run)
130- printf (
131- " Not performed the time limit test since solve time is %g <= %g = "
132- " min_run_time_for_test\n " ,
133- single_solve_run_time, min_run_time_for_test);
134- }
135- return_status = highs.setOptionValue (" time_limit" , default_time_limit);
136- REQUIRE (return_status == HighsStatus::kOk );
137- if (!use_simplex) {
138- if (dev_run)
139- printf (" IPM: %" HIGHSINT_FORMAT " ; Crossover: %" HIGHSINT_FORMAT " \n " ,
140- info.ipm_iteration_count , info.crossover_iteration_count );
141- }
142- // Solve with iteration limit
143- // First of all check that no iterations are performed if the
144- // iteration limit is zero
145- if (use_simplex) {
146- return_status = highs.setOptionValue (" simplex_iteration_limit" , 0 );
147- REQUIRE (return_status == HighsStatus::kOk );
148-
149- return_status = highs.setBasis ();
150- REQUIRE (return_status == HighsStatus::kOk );
151- } else {
152- return_status = highs.setOptionValue (" ipm_iteration_limit" , 0 );
153- REQUIRE (return_status == HighsStatus::kOk );
154- }
155-
156- return_status = highs.run ();
157- model_status = highs.getModelStatus ();
158- if (dev_run)
159- printf (" Returns status = %" HIGHSINT_FORMAT " ; model status = %s\n " ,
160- (HighsInt)return_status,
161- highs.modelStatusToString (model_status).c_str ());
162- REQUIRE (return_status == HighsStatus::kWarning );
163- REQUIRE (model_status == HighsModelStatus::kIterationLimit );
164-
165- if (use_simplex) {
166- REQUIRE (info.simplex_iteration_count == 0 );
167- } else {
168- REQUIRE (info.ipm_iteration_count == 0 );
169- }
170-
171- // Now check that simplex/IPM stops after 10/5 iterations
172- const HighsInt further_simplex_iterations = 10 ;
173- const HighsInt further_ipm_iterations = 5 ;
174- if (use_simplex) {
175- if (dev_run)
176- printf (" Setting simplex_iteration_limit = %" HIGHSINT_FORMAT " \n " ,
177- further_simplex_iterations);
178- return_status = highs.setOptionValue (" simplex_iteration_limit" ,
179- further_simplex_iterations);
180- REQUIRE (return_status == HighsStatus::kOk );
181- return_status = highs.clearSolver ();
182- REQUIRE (return_status == HighsStatus::kOk );
183- } else {
184- if (dev_run)
185- printf (" Setting ipm_iteration_limit = %" HIGHSINT_FORMAT " \n " ,
186- further_ipm_iterations);
187- return_status =
188- highs.setOptionValue (" ipm_iteration_limit" , further_ipm_iterations);
189- REQUIRE (return_status == HighsStatus::kOk );
190- }
191-
192- return_status = highs.run ();
193- REQUIRE (return_status == HighsStatus::kWarning );
194- REQUIRE (highs.getModelStatus () == HighsModelStatus::kIterationLimit );
195-
196- if (use_simplex) {
197- REQUIRE (info.simplex_iteration_count == further_simplex_iterations);
198- return_status = highs.setOptionValue (" simplex_iteration_limit" ,
199- default_simplex_iteration_limit);
200- REQUIRE (return_status == HighsStatus::kOk );
201- } else {
202- REQUIRE (info.ipm_iteration_count == further_ipm_iterations);
203- return_status = highs.setOptionValue (" ipm_iteration_limit" ,
204- default_ipm_iteration_limit);
205- REQUIRE (return_status == HighsStatus::kOk );
206- }
207- }
208-
209- void testSolversSetup (const std::string model,
210- IterationCount& model_iteration_count,
211- vector<HighsInt>& simplex_strategy_iteration_count) {
212- if (model.compare (" adlittle" ) == 0 ) {
213- simplex_strategy_iteration_count[(
214- int )SimplexStrategy::kSimplexStrategyChoose ] = 87 ;
215- simplex_strategy_iteration_count[(
216- int )SimplexStrategy::kSimplexStrategyDualPlain ] = 87 ;
217- simplex_strategy_iteration_count[(
218- int )SimplexStrategy::kSimplexStrategyDualTasks ] = 72 ;
219- simplex_strategy_iteration_count[(
220- int )SimplexStrategy::kSimplexStrategyDualMulti ] = 73 ;
221- simplex_strategy_iteration_count[(
222- int )SimplexStrategy::kSimplexStrategyPrimal ] = 94 ;
223- model_iteration_count.ipm = 13 ;
224- model_iteration_count.crossover = 2 ;
225- }
226- }
227-
228- void testSolvers (Highs& highs, IterationCount& model_iteration_count,
229- const vector<HighsInt>& simplex_strategy_iteration_count) {
230- bool have_omp = true ;
231-
232- /*
233- HighsInt i = (HighsInt)SimplexStrategy::kSimplexStrategyPrimal;
234- model_iteration_count.simplex = simplex_strategy_iteration_count[i];
235- testSolver(highs, "simplex", model_iteration_count, i);
236- */
237-
238- HighsInt from_i = (HighsInt)SimplexStrategy::kSimplexStrategyMin ;
239- HighsInt to_i =
240- (HighsInt)SimplexStrategy::kSimplexStrategyDualMulti ; // PRIMAL; // NUM;
241- for (HighsInt i = from_i; i < to_i; i++) {
242- if (!have_omp) {
243- if (i == (HighsInt)SimplexStrategy::kSimplexStrategyDualTasks ) continue ;
244- if (i == (HighsInt)SimplexStrategy::kSimplexStrategyDualMulti ) continue ;
245- }
246- model_iteration_count.simplex = simplex_strategy_iteration_count[i];
247- testSolver (highs, " simplex" , model_iteration_count, i);
248- }
249- testSolver (highs, " ipm" , model_iteration_count);
250- }
251-
252- // No commas in test case name.
253- TEST_CASE (" LP-solver" , " [highs_lp_solver]" ) {
254- std::string model;
255- std::string model_file;
256- IterationCount model_iteration_count;
257- vector<HighsInt> simplex_strategy_iteration_count;
258- simplex_strategy_iteration_count.resize (
259- (HighsInt)SimplexStrategy::kSimplexStrategyNum );
260-
261- HighsLp lp;
262- // HighsStatus run_status;
263- HighsStatus return_status;
264- HighsStatus read_status;
265-
266- Highs highs;
267- if (!dev_run) highs.setOptionValue (" output_flag" , false );
268-
269- // Read mps
270- model = " adlittle" ;
271- model_file = std::string (HIGHS_DIR) + " /check/instances/" + model + " .mps" ;
272- testSolversSetup (model, model_iteration_count,
273- simplex_strategy_iteration_count);
274-
275- read_status = highs.readModel (model_file);
276- REQUIRE (read_status == HighsStatus::kOk );
277-
278- return_status = highs.setBasis ();
279- REQUIRE (return_status == HighsStatus::kOk );
280-
281- return_status = highs.run ();
282- REQUIRE (return_status == HighsStatus::kOk );
283-
284- testSolvers (highs, model_iteration_count, simplex_strategy_iteration_count);
285-
286- // Now check that we can change model within the same Highs instance
287- // First reset all the options to their default values
288- return_status = highs.resetOptions ();
289- REQUIRE (return_status == HighsStatus::kOk );
290-
291- if (!dev_run) highs.setOptionValue (" output_flag" , false );
292-
293- model_file = std::string (HIGHS_DIR) + " /check/instances/etamacro.mps" ;
294- read_status = highs.readModel (model_file);
295- REQUIRE (read_status == HighsStatus::kOk );
296-
297- return_status = highs.setBasis ();
298- REQUIRE (return_status == HighsStatus::kOk );
299-
300- return_status = highs.run ();
301- REQUIRE (return_status == HighsStatus::kOk );
302-
303- const HighsInfo& info = highs.getInfo ();
304- REQUIRE (info.num_dual_infeasibilities == 0 );
305-
306- // REQUIRE(info.simplex_iteration_count == 472); // differs on macOS
307-
308- HighsModelStatus model_status = highs.getModelStatus ();
309- REQUIRE (model_status == HighsModelStatus::kOptimal );
310-
311- // Test the solver without scaling
312- REQUIRE (highs.readModel (model_file) == HighsStatus::kOk );
313- REQUIRE (highs.setOptionValue (" simplex_scale_strategy" , 0 ) ==
314- HighsStatus::kOk );
315-
316- return_status = highs.run ();
317- REQUIRE (return_status == HighsStatus::kOk );
318-
319- // REQUIRE(info.simplex_iteration_count == 592); // differs on macOS
320- }
321-
32228TEST_CASE (" mip-with-lp-solver" , " [highs_lp_solver]" ) {
32329 // When solving the relaxation of a MIP. Exposed #1406
32430 HighsStatus status;
0 commit comments