[Cbc] Solution callbacks
Gleb Belov
gleb.belov at monash.edu
Fri Feb 26 01:31:54 EST 2016
Hi John,
first of all, I'd like to thank you and other contributors. I have been
testing cbc for several months now with various MiniZinc benchmarks and,
thanks to the numerous bug fixes made by you and others, mzn-cbc (the
MiniZinc solver with Cbc backend) runs without contradicting answers on
the 400 instances of the last 4 MZN Challenges. Wow, I haven't expected
that. We compare results to CPLEX and Gurobi, with various CP->MIP
translation options, and also without pre-processing.
Continuous printing of new solutions is not essential but has been
requested. I have printed the post-processed solutions from the
callback, they have fractional values, so I am sure they are just LP
solutions. (As opposed to model_->bestSolution() as in the original
interrupt.cpp.) I cannot answer your question why there are sometimes 2
event calls after a new solution. I have inserted log messages before
each relevant event call in CbcModel.cpp, printing "event(.....) + line
number". Attached file cbcCallbacks_photo.log has the output of my
solver for the example photo.mps.gz. The callback also prints deduced
bounds info + MiniZinc output (if new). The modified CbcModel.cpp is
also attached.
If you consider it reasonable effort to fix this (is not urgent), you
can use the modified example interrupt.cpp. It prints both
model_->bestSolution() as well as (post-processed)
origModel->getColSolution(). The output on photo.mps is in
photo_interrupt.log. In photo.mps, x[8] is the objective function value.
You see that both model_->getObjValue() as well as
origModel->getObjValue() not always correspond to the Cbc log's new best
obj value.
Moreover, such a callback should also handle the case without
preprocessing, which is reflected in the new code.
Finally, on ff_cbc.mps, there is a segfault after 37k nodes. It happens
in postProcess().
Gleb
On 26/02/2016 6:23 AM, John Forrest wrote:
> Gleb,
>
> So I don't understand why you get two VALUE messages but only one Cbc
> message.
>
> John
> On 25/02/16 18:34, Gleb Belov wrote:
>>
>> John,
>>
>> Checking for parentModel()==NULL is being done as in interrupt.cpp,
>> sorry for not mentioning.
>>
>> Gleb
>>
>> On Feb 26, 2016 4:15 AM, "John Forrest" <john.forrest at fastercoin.com
>> <mailto:john.forrest at fastercoin.com>> wrote:
>>
>> Gleb,
>>
>> On 25/02/16 05:21, Gleb Belov wrote:
>>> -- Thank you John,
>>>
>>> a,b) this is not a very clean interface... maybe put this into
>>> postProcess so I can access the correct obj from originalModel()?
>>>
>>> c) what do you mean by size? The preprocessed model has always
>>> smaller NumColumns() than the start model in my examples and
>>> originalModel() has always the same number. In the meantime I
>>> have an example where postProcess() crashes, probably on a model
>>> which is not intended to be post-processed.
>>
>> A cleaner way than checking size would be to pick up
>> model->parentModel() and don't report if this is not NULL.
>>>
>>> How is it with cut generators, do they get LP solution for the
>>> original model?
>>>
>> Preprocessed model
>>> I'd be happy to access the current number of open (unexplored)
>>> nodes by some interface method. Also in the solution callback,
>>> assuming we get it to work.
>>>
>> Crude way would be to pass in a print handler - just does as
>> normal but checks if message is Cbc0010 and gets open nodes.
>>> I noticed when performing postprocessing in the callback, the
>>> solution way differs... probably because post-processing calls
>>> some LP resolving procedures? I tried to create a copy of
>>> *cbcCglPreProcess each time but the copy crashes.
>>>
>>> Gleb
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://list.coin-or.org/pipermail/cbc/attachments/20160226/c2534099/attachment-0001.html>
-------------- next part --------------
NICTA MiniZinc to FlatZinc converter, version 2.0.11
Copyright (C) 2014-2016 Monash University and NICTA
Parsing 'examples/photo.mzn' ...processing file 'examples/photo.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/globals.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/value_precede_chain.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/value_precede_chain_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/value_precede_chain_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/value_precede.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/value_precede_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/value_precede_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/table.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/table_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/table_bool.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/symmetric_all_different.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/sum_pred.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/subcircuit.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/alldifferent.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/strict_lex2.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/span.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/sort_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/sort.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/sliding_sum.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/roots_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/roots.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/regular_nfa.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/regular.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/range_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/range.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/partition_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/nvalue_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/nvalue.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/network_flow.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/minimum.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/member.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/set_member.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/member_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/member_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/member_float.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/member_bool.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/maximum.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/link_set_to_booleans.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex2.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_less.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_less_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_less_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_less_float.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_less_bool.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_lesseq.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_lesseq_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_lesseq_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_lesseq_float.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/lex_lesseq_bool.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_greatereq.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/lex_greater.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/knapsack.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/inverse_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/inverse_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/inverse.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/int_set_channel.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/increasing.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/increasing_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/increasing_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/increasing_float.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/increasing_bool.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/global_cardinality_low_up_closed.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/global_cardinality_low_up.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/global_cardinality_closed_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/global_cardinality_closed.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/global_cardinality_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/global_cardinality.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/geost.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/exactly.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/exactly_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/exactly_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/element.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/element_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/element_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/element_float.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/element_bool.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/distribute_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/distribute.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/disjunctive_strict_opt.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/disjunctive_opt.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/disjunctive_strict.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/disjunctive.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/disjoint.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/diffn_nonstrict_k.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/diffn_k.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/diffn_nonstrict.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/diffn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/decreasing.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/decreasing_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/decreasing_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/decreasing_float.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/decreasing_bool.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/cumulative_opt.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/cumulative.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/count_lt.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/count_leq.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/count_gt.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/count_geq.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/count_neq.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/count_eq.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/count_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/count.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/circuit.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/bin_packing_load_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/bin_packing_load.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/bin_packing_capa.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/bin_packing.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/at_most1.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/at_most.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/at_most_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/at_most_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/at_least.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/at_least_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/at_least_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/arg_max.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/arg_max_float.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/arg_max_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/arg_min.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/arg_min_float.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/arg_min_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/arg_sort.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/arg_sort_float.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/arg_sort_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/among_fn.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/among.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/alternative.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/all_equal.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/all_equal_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/all_equal_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/all_disjoint.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/alldifferent_except_0.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/all_different.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/all_different_set.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/all_different_int.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/domain_encodings.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/stdlib.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/builtins.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/redefinitions-2.0.2.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/redefinitions-2.0.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/redefinitions.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/nosets.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/redefs_lin_halfreifs.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/redefs_lin_reifs.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/redefs_bool_reifs.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/linear/options.mzn'
processing file '/media/sf_SHARED/prj/libmzn/install/build/../share/minizinc/std/flatzinc_builtins.mzn'
done parsing (133 ms)
Typechecking ... done (61 ms)
Flattening ... done (82 ms), max stack depth 21
MIP domains ... done (1 ms)
Optimizing ... done (0 ms)
Converting to old FlatZinc ... done (1 ms)
Generated FlatZinc statistics:
Variables: 198 int
Constraints: 247 int
Maximum memory 5 Mbytes.
Flattening done, 0.28 s
% SOLVING PHASE
MIP solver plugin, compiled Feb 26 2016, using: MIP wrapper for OSICBC 2.9, using CLP 1.16 Compiled Feb 26 2016 14:09:21
MIP: objective variable index (0-based): 9
MIP_osicbc_wrapper: delaying physical addition of variables...
MIP_solverinstance: adding constraints... done, 247 rows && 198 columns in total.
MIP_solverinstance: this is a MAXimization problem.
MIP_solverinstance: bounds for the objective function: 0, 8
MIP_wrapper: adding the 198 Phase-1 variables... done.
MIP_osicbc_wrapper: adding constraints physically... done.
Model creation...
Calling callCbc with options ' -solve -quit'...
1 integer variables out of 196 objects (196 integer) have cost of -1 - high priority
branch on satisfied Y create fake objective Y random cost Y
Initial state - 94 integers unsatisfied sum - 26.8016
Pass 1: suminf. 18.52650 (76) obj. -5.62745 iterations 74
Pass 2: suminf. 17.02540 (72) obj. -5.71726 iterations 13
Pass 3: suminf. 11.61466 (49) obj. -6 iterations 21
Pass 4: suminf. 11.26452 (49) obj. -6 iterations 20
Pass 5: suminf. 5.50308 (30) obj. -6 iterations 32
Pass 6: suminf. 5.31400 (34) obj. -6 iterations 15
Pass 7: suminf. 3.36481 (31) obj. -5.98485 iterations 30
Pass 8: suminf. 3.28579 (34) obj. -5.96248 iterations 13
Pass 9: suminf. 6.04255 (34) obj. -5.88889 iterations 22
Pass 10: suminf. 4.99869 (31) obj. -5.90523 iterations 15
Pass 11: suminf. 1.94497 (15) obj. -6 iterations 23
Pass 12: suminf. 4.54524 (25) obj. -5.88889 iterations 28
Pass 13: suminf. 2.60476 (18) obj. -5.85714 iterations 22
Pass 14: suminf. 5.97778 (30) obj. -4.77778 iterations 30
Pass 15: suminf. 2.51905 (16) obj. -5 iterations 29
Pass 16: suminf. 5.97778 (30) obj. -4.77778 iterations 31
Pass 17: suminf. 2.11508 (13) obj. -4.71429 iterations 23
Pass 18: suminf. 0.65000 (6) obj. -3 iterations 23
Pass 19: suminf. 0.75794 (6) obj. -3 iterations 12
Pass 20: suminf. 14.48742 (66) obj. -5.88383 iterations 72
Pass 21: suminf. 11.17259 (47) obj. -4.50817 iterations 37
Pass 22: suminf. 11.17259 (47) obj. -4.50817 iterations 2
Pass 23: suminf. 7.82659 (29) obj. -4 iterations 37
Pass 24: suminf. 6.83823 (35) obj. -3.51984 iterations 18
Pass 25: suminf. 4.31201 (26) obj. -2.01344 iterations 31
Pass 26: suminf. 4.21587 (17) obj. -1.88889 iterations 13
Pass 27: suminf. 2.46984 (11) obj. -1 iterations 28
Pass 28: suminf. 1.74286 (12) obj. -0.857143 iterations 13
Pass 29: suminf. 2.88095 (14) obj. 0 iterations 24
Pass 30: suminf. 1.25000 (8) obj. 0 iterations 22
Pass 31: suminf. 0.84444 (6) obj. 0 iterations 15
Pass 32: suminf. 0.75000 (6) obj. 0 iterations 16
Pass 33: suminf. 5.91528 (29) obj. -0.444444 iterations 45
Pass 34: suminf. 2.20000 (10) obj. 0 iterations 30
Pass 35: suminf. 0.68571 (6) obj. 0 iterations 25
Pass 36: suminf. 0.90000 (6) obj. 0 iterations 25
Pass 37: suminf. 8.18333 (34) obj. -2.02778 iterations 76
Pass 38: suminf. 5.34286 (20) obj. -1.93056 iterations 44
Pass 39: suminf. 4.34286 (18) obj. -1.93056 iterations 6
Pass 40: suminf. 4.85000 (22) obj. -1.80952 iterations 30
Pass 41: suminf. 2.81735 (14) obj. -1.71429 iterations 15
Pass 42: suminf. 2.01508 (10) obj. -1 iterations 26
Pass 43: suminf. 1.86111 (12) obj. -0.902778 iterations 20
Pass 44: suminf. 0.45000 (4) obj. -1 iterations 20
Pass 45: suminf. 0.45000 (4) obj. -1 iterations 2
Pass 46: suminf. 0.47222 (4) obj. -1 iterations 14
Pass 47: suminf. 14.17176 (52) obj. -2.46838 iterations 51
Pass 48: suminf. 7.41481 (31) obj. -1.92593 iterations 52
Pass 49: suminf. 4.35476 (21) obj. -1.14286 iterations 38
Pass 50: suminf. 3.44662 (26) obj. -1 iterations 55
Pass 51: suminf. 0.67222 (6) obj. -1 iterations 24
Pass 52: suminf. 0.67222 (6) obj. -1 iterations 3
Pass 53: suminf. 0.73571 (6) obj. -1 iterations 25
Pass 54: suminf. 7.86071 (28) obj. -1 iterations 57
Pass 55: suminf. 7.30913 (30) obj. -1.14286 iterations 25
Pass 56: suminf. 7.30913 (30) obj. -1.14286 iterations 3
Pass 57: suminf. 4.18016 (18) obj. -0.888889 iterations 19
Pass 58: suminf. 4.52857 (20) obj. -1 iterations 6
Pass 59: suminf. 4.16111 (20) obj. -0.888889 iterations 25
Pass 60: suminf. 3.01508 (19) obj. -0.857143 iterations 17
Pass 61: suminf. 3.08651 (12) obj. -0.571429 iterations 10
Pass 62: suminf. 0.78571 (6) obj. 0 iterations 31
Pass 63: suminf. 0.62222 (6) obj. 0 iterations 8
Pass 64: suminf. 9.21845 (33) obj. -1.66667 iterations 62
Pass 65: suminf. 6.01944 (30) obj. -1.1746 iterations 26
Pass 66: suminf. 2.96032 (12) obj. -0.888889 iterations 33
Pass 67: suminf. 1.96032 (10) obj. -0.888889 iterations 8
Pass 68: suminf. 0.00000 (0) obj. -1 iterations 17
Solution found of -1
event(heuristicSolution) CbcModel.cpp:13363 % OBJ VAL RAW: -1 OBJ VAL ORIG(?): 1 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196 objVAR: 8
Positions: [2, 3, 4, 2, 3, 5, 7, 7, 5]
Preferences satisfied: 8
----------
% MIP Status: feasible from a callback
% obj, bound, CPU_time, nodes (left): 1, 8, 0.032, 0 ( -1 )
Cleaned solution of -1
Before mini branch and bound, 17 integers at bound fixed and 0 continuous
Full problem 247 rows 196 columns, reduced to 231 rows 173 columns - 13 fixed gives 205, 133 - still too large
Mini branch and bound did not improve solution (0.03 seconds)
Round again with cutoff of -2.59991
Pass 69: suminf. 18.52650 (76) obj. -5.62745 iterations 0
Pass 70: suminf. 17.02540 (72) obj. -5.71726 iterations 16
Pass 71: suminf. 10.72577 (47) obj. -6 iterations 28
Pass 72: suminf. 10.31419 (47) obj. -6 iterations 14
Pass 73: suminf. 5.45079 (23) obj. -6 iterations 33
Pass 74: suminf. 6.35895 (36) obj. -6 iterations 9
Pass 75: suminf. 5.94410 (34) obj. -6 iterations 29
Pass 76: suminf. 4.84966 (30) obj. -5.87302 iterations 24
Pass 77: suminf. 5.17302 (24) obj. -4 iterations 42
Pass 78: suminf. 5.73770 (24) obj. -4 iterations 18
Pass 79: suminf. 5.69008 (24) obj. -4 iterations 13
Pass 80: suminf. 3.79921 (18) obj. -3.88889 iterations 28
Pass 81: suminf. 4.37917 (36) obj. -4 iterations 20
Pass 82: suminf. 9.75556 (36) obj. -4 iterations 32
Pass 83: suminf. 4.69008 (20) obj. -4 iterations 22
Pass 84: suminf. 3.21587 (18) obj. -3.85714 iterations 12
Pass 85: suminf. 3.97488 (28) obj. -3 iterations 34
Pass 86: suminf. 3.97488 (28) obj. -3 iterations 5
Pass 87: suminf. 4.81111 (21) obj. -3 iterations 49
Pass 88: suminf. 4.03413 (20) obj. -3 iterations 25
Pass 89: suminf. 2.86667 (13) obj. -3 iterations 7
Pass 90: suminf. 3.31667 (13) obj. -3 iterations 42
Pass 91: suminf. 2.81667 (13) obj. -3 iterations 11
Pass 92: suminf. 2.81667 (13) obj. -3 iterations 6
Pass 93: suminf. 4.03413 (20) obj. -3 iterations 30
Pass 94: suminf. 3.98889 (19) obj. -3 iterations 13
Pass 95: suminf. 4.75833 (19) obj. -3 iterations 21
Pass 96: suminf. 4.75833 (19) obj. -3 iterations 15
Pass 97: suminf. 3.31667 (13) obj. -3 iterations 26
Pass 98: suminf. 4.11481 (23) obj. -3 iterations 19
Pass 99: suminf. 4.45926 (23) obj. -3 iterations 31
Pass 100: suminf. 4.00000 (17) obj. -3 iterations 20
Pass 101: suminf. 2.83333 (12) obj. -3 iterations 17
Pass 102: suminf. 3.53889 (14) obj. -3 iterations 37
Pass 103: suminf. 1.79286 (10) obj. -3 iterations 35
Pass 104: suminf. 2.33333 (8) obj. -3 iterations 34
Pass 105: suminf. 2.90000 (10) obj. -3 iterations 25
Pass 106: suminf. 3.50357 (24) obj. -3 iterations 15
Pass 107: suminf. 1.57143 (8) obj. -3 iterations 28
Pass 108: suminf. 4.59412 (18) obj. -3 iterations 24
Pass 109: suminf. 2.82222 (10) obj. -3 iterations 26
Pass 110: suminf. 2.82222 (10) obj. -3 iterations 10
Pass 111: suminf. 1.44444 (8) obj. -3 iterations 19
Pass 112: suminf. 1.08889 (6) obj. -3 iterations 6
Pass 113: suminf. 0.25000 (2) obj. -3 iterations 6
Pass 114: suminf. 0.20000 (2) obj. -3 iterations 6
Pass 115: suminf. 15.31847 (51) obj. -5.9442 iterations 47
Pass 116: suminf. 6.00730 (32) obj. -6.94921 iterations 46
Pass 117: suminf. 5.00079 (23) obj. -6.89286 iterations 21
Pass 118: suminf. 5.13251 (27) obj. -6.6646 iterations 13
Pass 119: suminf. 4.77857 (17) obj. -4 iterations 34
Pass 120: suminf. 3.06837 (17) obj. -4 iterations 13
Pass 121: suminf. 1.77143 (10) obj. -3.85714 iterations 18
Pass 122: suminf. 0.45000 (4) obj. -3 iterations 20
Pass 123: suminf. 0.45000 (4) obj. -3 iterations 13
Pass 124: suminf. 14.03409 (60) obj. -4.75735 iterations 61
Pass 125: suminf. 12.71061 (51) obj. -4.69475 iterations 37
Pass 126: suminf. 12.51916 (52) obj. -4.78052 iterations 5
Pass 127: suminf. 7.88600 (45) obj. -4.90703 iterations 31
Pass 128: suminf. 7.02184 (38) obj. -4.87546 iterations 23
Pass 129: suminf. 7.67581 (35) obj. -4.92627 iterations 11
Pass 130: suminf. 9.77917 (34) obj. -4 iterations 39
Pass 131: suminf. 6.59702 (25) obj. -4 iterations 16
Pass 132: suminf. 5.27729 (24) obj. -4 iterations 13
Pass 133: suminf. 5.15635 (24) obj. -4 iterations 28
Pass 134: suminf. 3.35476 (16) obj. -4 iterations 24
Pass 135: suminf. 3.35476 (16) obj. -4 iterations 1
Pass 136: suminf. 4.06667 (16) obj. -4 iterations 21
Pass 137: suminf. 3.27710 (18) obj. -4 iterations 18
Pass 138: suminf. 3.94286 (24) obj. -3.91429 iterations 19
Pass 139: suminf. 4.00119 (24) obj. -4 iterations 28
Pass 140: suminf. 2.55952 (17) obj. -3.85714 iterations 19
Pass 141: suminf. 2.36032 (15) obj. -3 iterations 20
Pass 142: suminf. 2.36032 (15) obj. -3 iterations 21
Pass 143: suminf. 4.62698 (23) obj. -3 iterations 30
Pass 144: suminf. 1.98810 (13) obj. -3 iterations 18
Pass 145: suminf. 1.98810 (13) obj. -3 iterations 18
Pass 146: suminf. 1.86032 (13) obj. -3 iterations 15
Pass 147: suminf. 2.09286 (10) obj. -2.71429 iterations 29
Pass 148: suminf. 2.23996 (11) obj. -2.59991 iterations 44
Pass 149: suminf. 1.14286 (4) obj. -4.71429 iterations 34
Pass 150: suminf. 1.14286 (4) obj. -4.71429 iterations 3
Pass 151: suminf. 0.75000 (2) obj. -4 iterations 7
Solution found of -4
event(heuristicSolution) CbcModel.cpp:13363 % OBJ VAL RAW: -4 OBJ VAL ORIG(?): 4 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196 objVAR: 8
Positions: [3, 4, 3, 1, 3, 5, 6, 6, 5]
Preferences satisfied: 8
----------
% MIP Status: feasible from a callback
% obj, bound, CPU_time, nodes (left): 4, 8, 0.048, 0 ( -1 )
Cleaned solution of -4
Before mini branch and bound, 14 integers at bound fixed and 0 continuous
Full problem 247 rows 196 columns, reduced to 220 rows 175 columns - 24 fixed gives 172, 103 - still too large
Full problem 247 rows 196 columns, reduced to 155 rows 96 columns - too large
Mini branch and bound did not improve solution (0.05 seconds)
Round again with cutoff of -5.59992
Pass 152: suminf. 18.52650 (76) obj. -5.62745 iterations 0
Pass 153: suminf. 17.02540 (72) obj. -5.71726 iterations 16
Pass 154: suminf. 12.36221 (55) obj. -6 iterations 31
Pass 155: suminf. 9.42730 (38) obj. -6 iterations 22
Pass 156: suminf. 8.61406 (40) obj. -6 iterations 5
Pass 157: suminf. 8.50159 (33) obj. -6 iterations 20
Pass 158: suminf. 8.23338 (39) obj. -5.95964 iterations 9
Pass 159: suminf. 7.30030 (29) obj. -5.59992 iterations 31
Pass 160: suminf. 6.35085 (29) obj. -5.59992 iterations 17
Pass 161: suminf. 6.41738 (34) obj. -5.59992 iterations 11
Pass 162: suminf. 8.03943 (40) obj. -5.59992 iterations 53
Pass 163: suminf. 8.91582 (40) obj. -5.59992 iterations 13
Pass 164: suminf. 4.67778 (23) obj. -6.125 iterations 42
Pass 165: suminf. 4.32671 (38) obj. -6 iterations 20
Pass 166: suminf. 5.36905 (21) obj. -6 iterations 32
Pass 167: suminf. 4.58492 (34) obj. -6 iterations 31
Pass 168: suminf. 4.61905 (21) obj. -6 iterations 27
Pass 169: suminf. 4.22837 (34) obj. -6 iterations 26
Pass 170: suminf. 5.88517 (35) obj. -6 iterations 26
Pass 171: suminf. 4.60837 (28) obj. -6 iterations 19
Pass 172: suminf. 4.60476 (25) obj. -5.88889 iterations 35
Pass 173: suminf. 4.24970 (36) obj. -6 iterations 17
Pass 174: suminf. 6.01276 (30) obj. -6 iterations 36
Pass 175: suminf. 4.48889 (27) obj. -5.95238 iterations 27
Pass 176: suminf. 5.18399 (30) obj. -5.98148 iterations 23
Pass 177: suminf. 2.99524 (17) obj. -5.85714 iterations 22
Pass 178: suminf. 2.99524 (17) obj. -5.85714 iterations 11
Pass 179: suminf. 5.99884 (38) obj. -5.59992 iterations 42
Pass 180: suminf. 3.43794 (14) obj. -5.59992 iterations 19
Pass 181: suminf. 3.43794 (14) obj. -5.59992 iterations 14
Pass 182: suminf. 3.27213 (29) obj. -5.77361 iterations 40
Pass 183: suminf. 2.77143 (13) obj. -5.66667 iterations 25
Pass 184: suminf. 6.34868 (41) obj. -5.59992 iterations 50
Pass 185: suminf. 3.43794 (14) obj. -5.59992 iterations 28
Pass 186: suminf. 3.43794 (14) obj. -5.59992 iterations 5
Pass 187: suminf. 3.01587 (15) obj. -6.66667 iterations 45
Pass 188: suminf. 2.57143 (11) obj. -6.66667 iterations 26
Pass 189: suminf. 1.68254 (11) obj. -6 iterations 28
Pass 190: suminf. 1.23810 (7) obj. -6 iterations 24
Pass 191: suminf. 12.80658 (57) obj. -5.59992 iterations 63
Pass 192: suminf. 5.75655 (29) obj. -5.84524 iterations 37
Pass 193: suminf. 5.26617 (30) obj. -5.85871 iterations 9
Pass 194: suminf. 2.66488 (21) obj. -5.98592 iterations 28
Pass 195: suminf. 2.36429 (14) obj. -5.85714 iterations 31
Pass 196: suminf. 3.45927 (18) obj. -5.59992 iterations 63
Pass 197: suminf. 3.45927 (18) obj. -5.59992 iterations 15
Pass 198: suminf. 2.00000 (10) obj. -8 iterations 53
Pass 199: suminf. 1.96429 (10) obj. -7.85714 iterations 27
Pass 200: suminf. 1.91429 (8) obj. -7 iterations 21
Pass 201: suminf. 1.91429 (8) obj. -7 iterations 26
Pass 202: suminf. 1.39286 (6) obj. -7 iterations 27
Pass 203: suminf. 1.39286 (6) obj. -7 iterations 25
Pass 204: suminf. 1.34286 (6) obj. -7 iterations 23
Pass 205: suminf. 1.34286 (6) obj. -7 iterations 22
Pass 206: suminf. 12.06849 (65) obj. -5.59992 iterations 61
Pass 207: suminf. 6.29206 (26) obj. -5.59992 iterations 39
Pass 208: suminf. 3.57460 (19) obj. -5.71429 iterations 24
Pass 209: suminf. 3.57460 (19) obj. -5.71429 iterations 15
Pass 210: suminf. 6.12524 (26) obj. -5.59992 iterations 37
Pass 211: suminf. 3.55032 (21) obj. -5.59992 iterations 23
Pass 212: suminf. 4.33333 (13) obj. -8 iterations 53
Pass 213: suminf. 3.52381 (13) obj. -8 iterations 36
Pass 214: suminf. 2.47619 (8) obj. -8 iterations 11
Pass 215: suminf. 2.47619 (8) obj. -8 iterations 5
Pass 216: suminf. 1.71429 (6) obj. -8 iterations 27
Pass 217: suminf. 1.71429 (6) obj. -8 iterations 15
Pass 218: suminf. 1.14286 (4) obj. -8 iterations 11
Pass 219: suminf. 1.14286 (4) obj. -8 iterations 16
Pass 220: suminf. 13.55125 (60) obj. -7.30217 iterations 55
Pass 221: suminf. 6.28950 (35) obj. -6.74178 iterations 49
Pass 222: suminf. 5.78950 (33) obj. -6.74178 iterations 1
Pass 223: suminf. 6.04270 (23) obj. -5.59992 iterations 51
Pass 224: suminf. 4.86663 (29) obj. -5.59992 iterations 39
Pass 225: suminf. 4.80801 (31) obj. -8 iterations 72
Pass 226: suminf. 3.14286 (21) obj. -7.71825 iterations 40
Pass 227: suminf. 3.38889 (17) obj. -5.96032 iterations 28
Pass 228: suminf. 3.38889 (17) obj. -5.96032 iterations 25
Pass 229: suminf. 2.25664 (20) obj. -5.98592 iterations 23
Pass 230: suminf. 2.87817 (21) obj. -5.98592 iterations 18
Pass 231: suminf. 5.79354 (24) obj. -5.59992 iterations 53
Pass 232: suminf. 5.11441 (25) obj. -5.59992 iterations 24
Pass 233: suminf. 4.03538 (27) obj. -5.59992 iterations 17
Pass 234: suminf. 6.64220 (31) obj. -8 iterations 69
Pass 235: suminf. 2.94286 (13) obj. -7.85714 iterations 39
Pass 236: suminf. 1.91429 (10) obj. -7.85714 iterations 11
Pass 237: suminf. 1.39286 (6) obj. -7 iterations 23
Pass 238: suminf. 1.39286 (6) obj. -7 iterations 14
Pass 239: suminf. 1.34286 (6) obj. -7 iterations 16
Pass 240: suminf. 1.34286 (6) obj. -7 iterations 16
Pass 241: suminf. 5.21032 (26) obj. -5.77778 iterations 43
Pass 242: suminf. 3.09286 (12) obj. -6 iterations 29
Pass 243: suminf. 1.64286 (8) obj. -6 iterations 30
Pass 244: suminf. 1.64286 (8) obj. -6 iterations 18
Pass 245: suminf. 1.54286 (8) obj. -6 iterations 21
Pass 246: suminf. 1.54286 (8) obj. -6 iterations 17
Pass 247: suminf. 16.59291 (76) obj. -5.59992 iterations 100
Pass 248: suminf. 10.27601 (56) obj. -5.59992 iterations 47
Pass 249: suminf. 8.83590 (51) obj. -5.59992 iterations 59
Pass 250: suminf. 7.38966 (39) obj. -5.59992 iterations 20
Pass 251: suminf. 10.63389 (60) obj. -5.59992 iterations 66
No solution found this major pass
Before mini branch and bound, 6 integers at bound fixed and 0 continuous
Full problem 247 rows 196 columns, reduced to 243 rows 188 columns - 24 fixed gives 199, 114 - still too large
Full problem 247 rows 196 columns, reduced to 188 rows 112 columns - too large
Mini branch and bound did not improve solution (0.10 seconds)
After 0.10 seconds - Feasibility pump exiting with objective of -4 - took 0.08 seconds
Integer solution of -4 found by feasibility pump after 0 iterations and 0 nodes (0.10 seconds)
event(heuristicSolution) CbcModel.cpp:13363 % OBJ VAL RAW: -4 OBJ VAL ORIG(?): 4 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196 objVAR: 8
Positions: [2, 3, 4, 2, 3, 5, 7, 7, 4]
Preferences satisfied: 8
----------
% MIP Status: feasible from a callback
% obj, bound, CPU_time, nodes (left): 4, 8, 0.100, 0 ( -1 )
event(heuristicSolution) CbcModel.cpp:15660 % OBJ VAL RAW: -4 OBJ VAL ORIG(?): 4 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196 objVAR: 8
% MIP Status: feasible from a callback
% obj, bound, CPU_time, nodes (left): 4, 8, 0.104, 0 ( -1 )
Full problem 247 rows 196 columns, reduced to 172 rows 92 columns - 19 fixed gives 110, 50 - ok now
event(solution) CbcModel.cpp:15719 % OBJ VAL RAW: -4 OBJ VAL ORIG(?): 4 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196 objVAR: 8
Positions: [2, 3, 4, 1, 3, 5, 7, 7, 3]
Preferences satisfied: 8
----------
% MIP Status: feasible from a callback
% obj, bound, CPU_time, nodes (left): 4, 8, 0.112, 0 ( -1 )
18 added rows had average density of 90.111111
At root node, 18 cuts changed objective from -8 to -8 in 97 passes
Cut generator 0 (Probing) - 423 row cuts average 2.3 elements, 0 column cuts (0 active) in 0.048 seconds - new frequency is -100
Cut generator 1 (Gomory) - 1558 row cuts average 168.8 elements, 0 column cuts (0 active) in 0.440 seconds - new frequency is -100
Cut generator 2 (Knapsack) - 6 row cuts average 3.3 elements, 0 column cuts (0 active) in 0.084 seconds - new frequency is -100
Cut generator 3 (Clique) - 0 row cuts average 0.0 elements, 0 column cuts (0 active) in 0.028 seconds - new frequency is -100
Cut generator 4 (MixedIntegerRounding2) - 17 row cuts average 7.5 elements, 0 column cuts (0 active) in 0.000 seconds - new frequency is -100
Cut generator 5 (FlowCover) - 0 row cuts average 0.0 elements, 0 column cuts (0 active) in 0.012 seconds - new frequency is -100
Cut generator 6 (TwoMirCuts) - 204 row cuts average 123.1 elements, 0 column cuts (0 active) in 0.036 seconds - new frequency is -100
event(solution) CbcModel.cpp:4568 % OBJ VAL RAW: -4 OBJ VAL ORIG(?): 4 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196 objVAR: 8
Positions: [9, 10, 11, 11, 12, 9, 7, 8, 7]
Preferences satisfied: 8
----------
% MIP Status: feasible from a callback
% obj, bound, CPU_time, nodes (left): 4, 8, 1.124, 0 ( -1 )
After 0 nodes, 1 on tree, -4 best solution, best possible -8 (1.12 seconds)
Full problem 247 rows 196 columns, reduced to 59 rows 31 columns
After 0 nodes, 1 on tree, 1e+50 best solution, best possible -7 (1.38 seconds)
Integer solution of -6 found by rounding after 82 iterations and 4 nodes (1.38 seconds)
event(heuristicSolution) CbcModel.cpp:13363 event(solution) CbcModel.cpp:4568 Search completed - best objective -6, took 82 iterations and 4 nodes (1.38 seconds)
Strong branching done 28 times (130 iterations), fathomed 1 nodes and fixed 3 variables
Maximum depth 2, 0 variables fixed on reduced cost
Integer solution of -6 found by RINS after 6647 iterations and 42 nodes (1.38 seconds)
event(heuristicSolution) CbcModel.cpp:13363 % OBJ VAL RAW: -6 OBJ VAL ORIG(?): 6 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196 objVAR: 8
Positions: [2, 8, 5, 6, 3, 7, 0, 1, 4]
Preferences satisfied: 8
----------
% MIP Status: feasible from a callback
% obj, bound, CPU_time, nodes (left): 6, 8, 1.380, 42 ( -1 )
event(solution) CbcModel.cpp:4568 % OBJ VAL RAW: -6 OBJ VAL ORIG(?): 6 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196 objVAR: 8
% MIP Status: feasible from a callback
% obj, bound, CPU_time, nodes (left): 6, 8, 1.380, 42 ( -1 )
Integer solution of -8 found by strong branching after 6843 iterations and 54 nodes (1.40 seconds)
event(solution) CbcModel.cpp:4568 % OBJ VAL RAW: -8 OBJ VAL ORIG(?): 8 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196 objVAR: 8
Positions: [2, 8, 5, 4, 3, 7, 0, 1, 6]
Preferences satisfied: 8
----------
% MIP Status: feasible from a callback
% obj, bound, CPU_time, nodes (left): 8, 8, 1.412, 54 ( -1 )
Search completed - best objective -8, took 6843 iterations and 54 nodes (1.41 seconds)
Strong branching done 910 times (9539 iterations), fathomed 14 nodes and fixed 24 variables
Maximum depth 24, 0 variables fixed on reduced cost
% MIP Status: Optimal
% obj, bound, CPU_time, nodes (left): 8, 8, 1.845, 54 ( -1 )
==========
Done (overall time 1.84 s).
-------------- next part --------------
/* $Id: CbcModel.cpp 2267 2016-02-21 11:26:51Z forrest $ */
// Copyright (C) 2002, International Business Machines
// Corporation and others. All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).
#if defined(_MSC_VER)
// Turn off compiler warning about long names
# pragma warning(disable:4786)
#endif
#include "CbcConfig.h"
#include <string>
//#define CBC_DEBUG 1
//#define CHECK_CUT_COUNTS
//#define CHECK_NODE
//#define CHECK_NODE_FULL
//#define NODE_LOG
//#define GLOBAL_CUTS_JUST_POINTERS
#ifdef CGL_DEBUG_GOMORY
extern int gomory_try;
#endif
#include <cassert>
#include <cmath>
#include <cfloat>
#ifdef COIN_HAS_CLP
// include Presolve from Clp
#include "ClpPresolve.hpp"
#include "OsiClpSolverInterface.hpp"
#include "ClpNode.hpp"
#include "ClpDualRowDantzig.hpp"
#include "ClpSimplexPrimal.hpp"
#endif
#include "CbcEventHandler.hpp"
#include "OsiSolverInterface.hpp"
#include "OsiAuxInfo.hpp"
#include "OsiSolverBranch.hpp"
#include "OsiChooseVariable.hpp"
#include "CoinWarmStartBasis.hpp"
#include "CoinPackedMatrix.hpp"
#include "CoinHelperFunctions.hpp"
#include "CbcBranchActual.hpp"
#include "CbcBranchDynamic.hpp"
#include "CbcHeuristic.hpp"
#include "CbcHeuristicFPump.hpp"
#include "CbcHeuristicRINS.hpp"
#include "CbcHeuristicDive.hpp"
#include "CbcModel.hpp"
#include "CbcTreeLocal.hpp"
#include "CbcStatistics.hpp"
#include "CbcStrategy.hpp"
#include "CbcMessage.hpp"
#include "OsiRowCut.hpp"
#include "OsiColCut.hpp"
#include "OsiRowCutDebugger.hpp"
#include "OsiCuts.hpp"
#include "CbcCountRowCut.hpp"
#include "CbcCutGenerator.hpp"
#include "CbcFeasibilityBase.hpp"
#include "CbcFathom.hpp"
#include "CbcFullNodeInfo.hpp"
#ifdef COIN_HAS_NTY
#include "CbcSymmetry.hpp"
#endif
// include Probing
#include "CglProbing.hpp"
#include "CglGomory.hpp"
#include "CglTwomir.hpp"
// include preprocessing
#include "CglPreProcess.hpp"
#include "CglDuplicateRow.hpp"
#include "CglStored.hpp"
#include "CglClique.hpp"
#include "CglKnapsackCover.hpp"
#include "CoinTime.hpp"
#include "CoinMpsIO.hpp"
#include "CbcCompareActual.hpp"
#include "CbcTree.hpp"
// This may be dummy
#include "CbcThread.hpp"
/* Various functions local to CbcModel.cpp */
static void * doRootCbcThread(void * voidInfo);
namespace {
//-------------------------------------------------------------------
// Returns the greatest common denominator of two
// positive integers, a and b, found using Euclid's algorithm
//-------------------------------------------------------------------
static int gcd(int a, int b)
{
int remainder = -1;
// make sure a<=b (will always remain so)
if (a > b) {
// Swap a and b
int temp = a;
a = b;
b = temp;
}
// if zero then gcd is nonzero (zero may occur in rhs of packed)
if (!a) {
if (b) {
return b;
} else {
printf("**** gcd given two zeros!!\n");
abort();
}
}
while (remainder) {
remainder = b % a;
b = a;
a = remainder;
}
return b;
}
#ifdef CHECK_NODE_FULL
/*
Routine to verify that tree linkage is correct. The invariant that is tested
is
reference count = (number of actual references) + (number of branches left)
The routine builds a set of paired arrays, info and count, by traversing the
tree. Each CbcNodeInfo is recorded in info, and the number of times it is
referenced (via the parent field) is recorded in count. Then a final check is
made to see if the numberPointingToThis_ field agrees.
*/
void verifyTreeNodes (const CbcTree * branchingTree, const CbcModel &model)
{
if (model.getNodeCount() == 661) return;
printf("*** CHECKING tree after %d nodes\n", model.getNodeCount()) ;
int j ;
int nNodes = branchingTree->size() ;
# define MAXINFO 1000
int *count = new int [MAXINFO] ;
CbcNodeInfo **info = new CbcNodeInfo*[MAXINFO] ;
int nInfo = 0 ;
/*
Collect all CbcNodeInfo objects in info, by starting from each live node and
traversing back to the root. Nodes in the live set should have unexplored
branches remaining.
TODO: The `while (nodeInfo)' loop could be made to break on reaching a
common ancester (nodeInfo is found in info[k]). Alternatively, the
check could change to signal an error if nodeInfo is not found above a
common ancestor.
*/
for (j = 0 ; j < nNodes ; j++) {
CbcNode *node = branchingTree->nodePointer(j) ;
if (!node)
continue;
CbcNodeInfo *nodeInfo = node->nodeInfo() ;
int change = node->nodeInfo()->numberBranchesLeft() ;
assert(change) ;
while (nodeInfo) {
int k ;
for (k = 0 ; k < nInfo ; k++) {
if (nodeInfo == info[k]) break ;
}
if (k == nInfo) {
assert(nInfo < MAXINFO) ;
nInfo++ ;
info[k] = nodeInfo ;
count[k] = 0 ;
}
nodeInfo = nodeInfo->parent() ;
}
}
/*
Walk the info array. For each nodeInfo, look up its parent in info and
increment the corresponding count.
*/
for (j = 0 ; j < nInfo ; j++) {
CbcNodeInfo *nodeInfo = info[j] ;
nodeInfo = nodeInfo->parent() ;
if (nodeInfo) {
int k ;
for (k = 0 ; k < nInfo ; k++) {
if (nodeInfo == info[k]) break ;
}
assert (k < nInfo) ;
count[k]++ ;
}
}
/*
Walk the info array one more time and check that the invariant holds. The
number of references (numberPointingToThis()) should equal the sum of the
number of actual references (held in count[]) plus the number of potential
references (unexplored branches, numberBranchesLeft()).
*/
for (j = 0; j < nInfo; j++) {
CbcNodeInfo * nodeInfo = info[j] ;
if (nodeInfo) {
int k ;
for (k = 0; k < nInfo; k++)
if (nodeInfo == info[k])
break ;
printf("Nodeinfo %x - %d left, %d count\n",
nodeInfo,
nodeInfo->numberBranchesLeft(),
nodeInfo->numberPointingToThis()) ;
assert(nodeInfo->numberPointingToThis() ==
count[k] + nodeInfo->numberBranchesLeft()) ;
}
}
delete [] count ;
delete [] info ;
return ;
}
#endif /* CHECK_NODE_FULL */
#ifdef CHECK_CUT_COUNTS
/*
Routine to verify that cut reference counts are correct.
*/
void verifyCutCounts (const CbcTree * branchingTree, CbcModel &model)
{
printf("*** CHECKING cuts after %d nodes\n", model.getNodeCount()) ;
int j ;
int nNodes = branchingTree->size() ;
/*
cut.tempNumber_ exists for the purpose of doing this verification. Clear it
in all cuts. We traverse the tree by starting from each live node and working
back to the root. At each CbcNodeInfo, check for cuts.
*/
for (j = 0 ; j < nNodes ; j++) {
CbcNode *node = branchingTree->nodePointer(j) ;
CbcNodeInfo * nodeInfo = node->nodeInfo() ;
assert (node->nodeInfo()->numberBranchesLeft()) ;
while (nodeInfo) {
int k ;
for (k = 0 ; k < nodeInfo->numberCuts() ; k++) {
CbcCountRowCut *cut = nodeInfo->cuts()[k] ;
if (cut) cut->tempNumber_ = 0;
}
nodeInfo = nodeInfo->parent() ;
}
}
/*
Walk the live set again, this time collecting the list of cuts in use at each
node. addCuts1 will collect the cuts in model.addedCuts_. Take into account
that when we recreate the basis for a node, we compress out the slack cuts.
*/
for (j = 0 ; j < nNodes ; j++) {
CoinWarmStartBasis *debugws = model.getEmptyBasis() ;
CbcNode *node = branchingTree->nodePointer(j) ;
CbcNodeInfo *nodeInfo = node->nodeInfo();
int change = node->nodeInfo()->numberBranchesLeft() ;
printf("Node %d %x (info %x) var %d way %d obj %g", j, node,
node->nodeInfo(), node->columnNumber(), node->way(),
node->objectiveValue()) ;
model.addCuts1(node, debugws) ;
int i ;
int numberRowsAtContinuous = model.numberRowsAtContinuous() ;
CbcCountRowCut **addedCuts = model.addedCuts() ;
for (i = 0 ; i < model.currentNumberCuts() ; i++) {
CoinWarmStartBasis::Status status =
debugws->getArtifStatus(i + numberRowsAtContinuous) ;
if (status != CoinWarmStartBasis::basic && addedCuts[i]) {
addedCuts[i]->tempNumber_ += change ;
}
}
while (nodeInfo) {
nodeInfo = nodeInfo->parent() ;
if (nodeInfo) printf(" -> %x", nodeInfo);
}
printf("\n") ;
delete debugws ;
}
/*
The moment of truth: We've tallied up the references by direct scan of the search tree. Check for agreement with the count in the cut.
TODO: Rewrite to check and print mismatch only when tempNumber_ == 0?
*/
for (j = 0 ; j < nNodes ; j++) {
CbcNode *node = branchingTree->nodePointer(j) ;
CbcNodeInfo *nodeInfo = node->nodeInfo();
while (nodeInfo) {
int k ;
for (k = 0 ; k < nodeInfo->numberCuts() ; k++) {
CbcCountRowCut *cut = nodeInfo->cuts()[k] ;
if (cut && cut->tempNumber_ >= 0) {
if (cut->tempNumber_ != cut->numberPointingToThis())
printf("mismatch %x %d %x %d %d\n", nodeInfo, k,
cut, cut->tempNumber_, cut->numberPointingToThis()) ;
else
printf(" match %x %d %x %d %d\n", nodeInfo, k,
cut, cut->tempNumber_, cut->numberPointingToThis()) ;
cut->tempNumber_ = -1 ;
}
}
nodeInfo = nodeInfo->parent() ;
}
}
return ;
}
#endif /* CHECK_CUT_COUNTS */
#ifdef CHECK_CUT_SIZE
/*
Routine to verify that cut reference counts are correct.
*/
void verifyCutSize (const CbcTree * branchingTree, CbcModel &model)
{
int j ;
int nNodes = branchingTree->size() ;
int totalCuts = 0;
/*
cut.tempNumber_ exists for the purpose of doing this verification. Clear it
in all cuts. We traverse the tree by starting from each live node and working
back to the root. At each CbcNodeInfo, check for cuts.
*/
for (j = 0 ; j < nNodes ; j++) {
CbcNode *node = branchingTree->nodePointer(j) ;
CbcNodeInfo * nodeInfo = node->nodeInfo() ;
assert (node->nodeInfo()->numberBranchesLeft()) ;
while (nodeInfo) {
totalCuts += nodeInfo->numberCuts();
nodeInfo = nodeInfo->parent() ;
}
}
printf("*** CHECKING cuts (size) after %d nodes - %d cuts\n", model.getNodeCount(), totalCuts) ;
return ;
}
#endif /* CHECK_CUT_SIZE */
}
/* End unnamed namespace for CbcModel.cpp */
void
CbcModel::analyzeObjective ()
/*
Try to find a minimum change in the objective function. The first scan
checks that there are no continuous variables with non-zero coefficients,
and grabs the largest objective coefficient associated with an unfixed
integer variable. The second scan attempts to scale up the objective
coefficients to a point where they are sufficiently close to integer that
we can pretend they are integer, and calculate a gcd over the coefficients
of interest. This will be the minimum increment for the scaled coefficients.
The final action is to scale the increment back for the original coefficients
and install it, if it's better than the existing value.
John's note: We could do better than this.
John's second note - apologies for changing s to z
*/
{
const double *objective = getObjCoefficients() ;
const double *lower = getColLower() ;
const double *upper = getColUpper() ;
/*
Scan continuous and integer variables to see if continuous
are cover or network with integral rhs.
*/
double continuousMultiplier = 1.0;
double * coeffMultiplier = NULL;
double largestObj = 0.0;
double smallestObj = COIN_DBL_MAX;
{
const double *rowLower = getRowLower() ;
const double *rowUpper = getRowUpper() ;
int numberRows = solver_->getNumRows() ;
double * rhs = new double [numberRows];
memset(rhs, 0, numberRows*sizeof(double));
int iColumn;
int numberColumns = solver_->getNumCols() ;
// Column copy of matrix
int problemType = -1;
const double * element = solver_->getMatrixByCol()->getElements();
const int * row = solver_->getMatrixByCol()->getIndices();
const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts();
const int * columnLength = solver_->getMatrixByCol()->getVectorLengths();
int numberInteger = 0;
int numberIntegerObj = 0;
int numberGeneralIntegerObj = 0;
int numberIntegerWeight = 0;
int numberContinuousObj = 0;
double cost = COIN_DBL_MAX;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if (upper[iColumn] == lower[iColumn]) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
rhs[iRow] += lower[iColumn] * element[j];
}
} else {
double objValue = objective[iColumn];
if (solver_->isInteger(iColumn))
numberInteger++;
if (objValue) {
if (!solver_->isInteger(iColumn)) {
numberContinuousObj++;
} else {
largestObj = CoinMax(largestObj, fabs(objValue));
smallestObj = CoinMin(smallestObj, fabs(objValue));
numberIntegerObj++;
if (cost == COIN_DBL_MAX)
cost = objValue;
else if (cost != objValue)
cost = -COIN_DBL_MAX;
int gap = static_cast<int> (upper[iColumn] - lower[iColumn]);
if (gap > 1) {
numberGeneralIntegerObj++;
numberIntegerWeight += gap;
}
}
}
}
}
int iType = 0;
if (!numberContinuousObj && numberIntegerObj <= 5 && numberIntegerWeight <= 100 &&
numberIntegerObj*3 < numberObjects_ && !parentModel_ && solver_->getNumRows() > 100)
iType = 1 + 4 + (((moreSpecialOptions_&536870912)==0) ? 2 : 0);
else if (!numberContinuousObj && numberIntegerObj <= 100 &&
numberIntegerObj*5 < numberObjects_ && numberIntegerWeight <= 100 &&
!parentModel_ &&
solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX)
iType = 4 + (((moreSpecialOptions_&536870912)==0) ? 2 : 0);
else if (!numberContinuousObj && numberIntegerObj <= 100 &&
numberIntegerObj*5 < numberObjects_ &&
!parentModel_ &&
solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX)
iType = 8;
int iTest = getMaximumNodes();
if (iTest >= 987654320 && iTest < 987654330 && numberObjects_ && !parentModel_) {
iType = iTest - 987654320;
printf("Testing %d integer variables out of %d objects (%d integer) have cost of %g - %d continuous\n",
numberIntegerObj, numberObjects_, numberInteger, cost, numberContinuousObj);
if (iType == 9)
exit(77);
if (numberContinuousObj)
iType = 0;
}
//if (!numberContinuousObj&&(numberIntegerObj<=5||cost!=-COIN_DBL_MAX)&&
//numberIntegerObj*3<numberObjects_&&!parentModel_&&solver_->getNumRows()>100) {
if (iType) {
/*
A) put high priority on (if none)
B) create artificial objective (if clp)
*/
int iPriority = -1;
for (int i = 0; i < numberObjects_; i++) {
int k = object_[i]->priority();
if (iPriority == -1)
iPriority = k;
else if (iPriority != k)
iPriority = -2;
}
bool branchOnSatisfied = ((iType & 1) != 0);
bool createFake = ((iType & 2) != 0);
bool randomCost = ((iType & 4) != 0);
if (iPriority >= 0) {
char general[200];
if (cost == -COIN_DBL_MAX) {
sprintf(general, "%d integer variables out of %d objects (%d integer) have costs - high priority",
numberIntegerObj, numberObjects_, numberInteger);
} else if (cost == COIN_DBL_MAX) {
sprintf(general, "No integer variables out of %d objects (%d integer) have costs",
numberObjects_, numberInteger);
branchOnSatisfied = false;
} else {
sprintf(general, "%d integer variables out of %d objects (%d integer) have cost of %g - high priority",
numberIntegerObj, numberObjects_, numberInteger, cost);
}
messageHandler()->message(CBC_GENERAL,
messages())
<< general << CoinMessageEol ;
sprintf(general, "branch on satisfied %c create fake objective %c random cost %c",
branchOnSatisfied ? 'Y' : 'N',
createFake ? 'Y' : 'N',
randomCost ? 'Y' : 'N');
messageHandler()->message(CBC_GENERAL,
messages())
<< general << CoinMessageEol ;
// switch off clp type branching
// no ? fastNodeDepth_ = -1;
int highPriority = (branchOnSatisfied) ? -999 : 100;
for (int i = 0; i < numberObjects_; i++) {
CbcSimpleInteger * thisOne = dynamic_cast <CbcSimpleInteger *> (object_[i]);
object_[i]->setPriority(1000);
if (thisOne) {
int iColumn = thisOne->columnNumber();
if (objective[iColumn])
thisOne->setPriority(highPriority);
}
}
}
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver && createFake) {
// Create artificial objective to be used when all else fixed
int numberColumns = clpSolver->getNumCols();
double * fakeObj = new double [numberColumns];
// Column copy
const CoinPackedMatrix * matrixByCol = clpSolver->getMatrixByCol();
//const double * element = matrixByCol.getElements();
//const int * row = matrixByCol.getIndices();
//const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
const int * columnLength = matrixByCol->getVectorLengths();
const double * solution = clpSolver->getColSolution();
#ifdef JJF_ZERO
int nAtBound = 0;
for (int i = 0; i < numberColumns; i++) {
double lowerValue = lower[i];
double upperValue = upper[i];
if (clpSolver->isInteger(i)) {
double lowerValue = lower[i];
double upperValue = upper[i];
double value = solution[i];
if (value < lowerValue + 1.0e-6 ||
value > upperValue - 1.0e-6)
nAtBound++;
}
}
#endif
/*
Generate a random objective function for problems where the given objective
function is not terribly useful. (Nearly feasible, single integer variable,
that sort of thing.
*/
CoinDrand48(true, 1234567);
for (int i = 0; i < numberColumns; i++) {
double lowerValue = lower[i];
double upperValue = upper[i];
double value = (randomCost) ? ceil((CoinDrand48() + 0.5) * 1000)
: i + 1 + columnLength[i] * 1000;
value *= 0.001;
//value += columnLength[i];
if (lowerValue > -1.0e5 || upperValue < 1.0e5) {
if (fabs(lowerValue) > fabs(upperValue))
value = - value;
if (clpSolver->isInteger(i)) {
double solValue = solution[i];
// Better to add in 0.5 or 1.0??
if (solValue < lowerValue + 1.0e-6)
value = fabs(value) + 0.5; //fabs(value*1.5);
else if (solValue > upperValue - 1.0e-6)
value = -fabs(value) - 0.5; //-fabs(value*1.5);
}
} else {
value = 0.0;
}
fakeObj[i] = value;
}
// pass to solver
clpSolver->setFakeObjective(fakeObj);
delete [] fakeObj;
}
#endif
} else if (largestObj < smallestObj*5.0 && !parentModel_ &&
!numberContinuousObj &&
!numberGeneralIntegerObj &&
numberIntegerObj*2 < CoinMin(numberColumns,20)) {
// up priorities on costed
int iPriority = -1;
for (int i = 0; i < numberObjects_; i++) {
int k = object_[i]->priority();
if (iPriority == -1)
iPriority = k;
else if (iPriority != k)
iPriority = -2;
}
if (iPriority >= 100) {
#if CBC_USEFUL_PRINTING>1
printf("Setting variables with obj to high priority\n");
#endif
for (int i = 0; i < numberObjects_; i++) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(object_[i]) ;
if (obj) {
int iColumn = obj->columnNumber();
if (objective[iColumn])
object_[i]->setPriority(iPriority - 1);
}
}
}
}
int iRow;
for (iRow = 0; iRow < numberRows; iRow++) {
if (rowLower[iRow] > -1.0e20 &&
fabs(rowLower[iRow] - rhs[iRow] - floor(rowLower[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) {
continuousMultiplier = 0.0;
break;
}
if (rowUpper[iRow] < 1.0e20 &&
fabs(rowUpper[iRow] - rhs[iRow] - floor(rowUpper[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) {
continuousMultiplier = 0.0;
break;
}
// set rhs to limiting value
if (rowLower[iRow] != rowUpper[iRow]) {
if (rowLower[iRow] > -1.0e20) {
if (rowUpper[iRow] < 1.0e20) {
// no good
continuousMultiplier = 0.0;
break;
} else {
rhs[iRow] = rowLower[iRow] - rhs[iRow];
if (problemType < 0)
problemType = 3; // set cover
else if (problemType != 3)
problemType = 4;
}
} else {
rhs[iRow] = rowUpper[iRow] - rhs[iRow];
if (problemType < 0)
problemType = 1; // set partitioning <=
else if (problemType != 1)
problemType = 4;
}
} else {
rhs[iRow] = rowUpper[iRow] - rhs[iRow];
if (problemType < 0)
problemType = 3; // set partitioning ==
else if (problemType != 2)
problemType = 2;
}
if (fabs(rhs[iRow] - 1.0) > 1.0e-12)
problemType = 4;
}
if (continuousMultiplier) {
// 1 network, 2 cover, 4 negative cover
int possible = 7;
bool unitRhs = true;
// See which rows could be set cover
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
for (CoinBigIndex j = start; j < end; j++) {
double value = element[j];
if (value == 1.0) {
} else if (value == -1.0) {
rhs[row[j]] = -0.5;
} else {
rhs[row[j]] = -COIN_DBL_MAX;
}
}
}
}
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
if (!isInteger(iColumn)) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
double rhsValue = 0.0;
// 1 all ones, -1 all -1s, 2 all +- 1, 3 no good
int type = 0;
for (CoinBigIndex j = start; j < end; j++) {
double value = element[j];
if (fabs(value) != 1.0) {
type = 3;
break;
} else if (value == 1.0) {
if (!type)
type = 1;
else if (type != 1)
type = 2;
} else {
if (!type)
type = -1;
else if (type != -1)
type = 2;
}
int iRow = row[j];
if (rhs[iRow] == -COIN_DBL_MAX) {
type = 3;
break;
} else if (rhs[iRow] == -0.5) {
// different values
unitRhs = false;
} else if (rhsValue) {
if (rhsValue != rhs[iRow])
unitRhs = false;
} else {
rhsValue = rhs[iRow];
}
}
// if no elements OK
if (type == 3) {
// no good
possible = 0;
break;
} else if (type == 2) {
if (end - start > 2) {
// no good
possible = 0;
break;
} else {
// only network
possible &= 1;
if (!possible)
break;
}
} else if (type == 1) {
// only cover
possible &= 2;
if (!possible)
break;
} else if (type == -1) {
// only negative cover
possible &= 4;
if (!possible)
break;
}
}
}
}
if ((possible == 2 || possible == 4) && !unitRhs) {
#if COIN_DEVELOP>1
printf("XXXXXX Continuous all +1 but different rhs\n");
#endif
possible = 0;
}
// may be all integer
if (possible != 7) {
if (!possible)
continuousMultiplier = 0.0;
else if (possible == 1)
continuousMultiplier = 1.0;
else
continuousMultiplier = 0.0; // 0.5 was incorrect;
#if COIN_DEVELOP>1
if (continuousMultiplier)
printf("XXXXXX multiplier of %g\n", continuousMultiplier);
#endif
if (continuousMultiplier == 0.5) {
coeffMultiplier = new double [numberColumns];
bool allOne = true;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
coeffMultiplier[iColumn] = 1.0;
if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
if (!isInteger(iColumn)) {
CoinBigIndex start = columnStart[iColumn];
int iRow = row[start];
double value = rhs[iRow];
assert (value >= 0.0);
if (value != 0.0 && value != 1.0)
allOne = false;
coeffMultiplier[iColumn] = 0.5 * value;
}
}
}
if (allOne) {
// back to old way
delete [] coeffMultiplier;
coeffMultiplier = NULL;
}
}
} else {
// all integer
problemType_ = problemType;
#if COIN_DEVELOP>1
printf("Problem type is %d\n", problemType_);
#endif
}
}
// But try again
if (continuousMultiplier < 1.0) {
memset(rhs, 0, numberRows*sizeof(double));
int * count = new int [numberRows];
memset(count, 0, numberRows*sizeof(int));
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
if (upper[iColumn] == lower[iColumn]) {
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
rhs[iRow] += lower[iColumn] * element[j];
}
} else if (solver_->isInteger(iColumn)) {
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
if (fabs(element[j] - floor(element[j] + 0.5)) > 1.0e-10)
rhs[iRow] = COIN_DBL_MAX;
}
} else {
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
count[iRow]++;
if (fabs(element[j]) != 1.0)
rhs[iRow] = COIN_DBL_MAX;
}
}
}
// now look at continuous
bool allGood = true;
double direction = solver_->getObjSense() ;
int numberObj = 0;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if (upper[iColumn] > lower[iColumn]) {
double objValue = objective[iColumn] * direction;
if (objValue && !solver_->isInteger(iColumn)) {
numberObj++;
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
if (objValue > 0.0) {
// wants to be as low as possible
if (lower[iColumn] < -1.0e10 || fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) {
allGood = false;
break;
} else if (upper[iColumn] < 1.0e10 && fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) {
allGood = false;
break;
}
bool singletonRow = true;
bool equality = false;
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
if (count[iRow] > 1)
singletonRow = false;
else if (rowLower[iRow] == rowUpper[iRow])
equality = true;
double rhsValue = rhs[iRow];
double lowerValue = rowLower[iRow];
double upperValue = rowUpper[iRow];
if (rhsValue < 1.0e20) {
if (lowerValue > -1.0e20)
lowerValue -= rhsValue;
if (upperValue < 1.0e20)
upperValue -= rhsValue;
}
if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10
|| fabs(element[j]) != 1.0) {
// no good
allGood = false;
break;
}
if (element[j] > 0.0) {
if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) {
// no good
allGood = false;
break;
}
} else {
if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) {
// no good
allGood = false;
break;
}
}
}
if (!singletonRow && end > start + 1 && !equality)
allGood = false;
if (!allGood)
break;
} else {
// wants to be as high as possible
if (upper[iColumn] > 1.0e10 || fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) {
allGood = false;
break;
} else if (lower[iColumn] > -1.0e10 && fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) {
allGood = false;
break;
}
bool singletonRow = true;
bool equality = false;
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
if (count[iRow] > 1)
singletonRow = false;
else if (rowLower[iRow] == rowUpper[iRow])
equality = true;
double rhsValue = rhs[iRow];
double lowerValue = rowLower[iRow];
double upperValue = rowUpper[iRow];
if (rhsValue < 1.0e20) {
if (lowerValue > -1.0e20)
lowerValue -= rhsValue;
if (upperValue < 1.0e20)
upperValue -= rhsValue;
}
if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10
|| fabs(element[j]) != 1.0) {
// no good
allGood = false;
break;
}
if (element[j] < 0.0) {
if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) {
// no good
allGood = false;
break;
}
} else {
if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) {
// no good
allGood = false;
break;
}
}
}
if (!singletonRow && end > start + 1 && !equality)
allGood = false;
if (!allGood)
break;
}
}
}
}
delete [] count;
if (allGood) {
#if COIN_DEVELOP>1
if (numberObj)
printf("YYYY analysis says all continuous with costs will be integer\n");
#endif
continuousMultiplier = 1.0;
}
}
delete [] rhs;
}
/*
Take a first scan to see if there are unfixed continuous variables in the
objective. If so, the minimum objective change could be arbitrarily small.
Also pick off the maximum coefficient of an unfixed integer variable.
If the objective is found to contain only integer variables, set the
fathoming discipline to strict.
*/
double maximumCost = 0.0 ;
//double trueIncrement=0.0;
int iColumn ;
int numberColumns = getNumCols() ;
double scaleFactor = 1.0; // due to rhs etc
/*
Original model did not have integer bounds.
*/
if ((specialOptions_&65536) == 0) {
/* be on safe side (later look carefully as may be able to
to get 0.5 say if bounds are multiples of 0.5 */
for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
double value;
value = fabs(lower[iColumn]);
if (floor(value + 0.5) != value) {
scaleFactor = CoinMin(scaleFactor, 0.5);
if (floor(2.0*value + 0.5) != 2.0*value) {
scaleFactor = CoinMin(scaleFactor, 0.25);
if (floor(4.0*value + 0.5) != 4.0*value) {
scaleFactor = 0.0;
}
}
}
value = fabs(upper[iColumn]);
if (floor(value + 0.5) != value) {
scaleFactor = CoinMin(scaleFactor, 0.5);
if (floor(2.0*value + 0.5) != 2.0*value) {
scaleFactor = CoinMin(scaleFactor, 0.25);
if (floor(4.0*value + 0.5) != 4.0*value) {
scaleFactor = 0.0;
}
}
}
}
}
}
bool possibleMultiple = continuousMultiplier != 0.0 && scaleFactor != 0.0 ;
if (possibleMultiple) {
for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
maximumCost = CoinMax(maximumCost, fabs(objective[iColumn])) ;
}
}
}
setIntParam(CbcModel::CbcFathomDiscipline, possibleMultiple) ;
/*
If a nontrivial increment is possible, try and figure it out. We're looking
for gcd(c<j>) for all c<j> that are coefficients of unfixed integer
variables. Since the c<j> might not be integers, try and inflate them
sufficiently that they look like integers (and we'll deflate the gcd
later).
2520.0 is used as it is a nice multiple of 2,3,5,7
*/
if (possibleMultiple && maximumCost) {
int increment = 0 ;
double multiplier = 2520.0 ;
while (10.0*multiplier*maximumCost < 1.0e8)
multiplier *= 10.0 ;
int bigIntegers = 0; // Count of large costs which are integer
for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
double objValue = fabs(objective[iColumn]);
if (!isInteger(iColumn)) {
if (!coeffMultiplier)
objValue *= continuousMultiplier;
else
objValue *= coeffMultiplier[iColumn];
}
if (objValue) {
double value = objValue * multiplier ;
if (value < 2.1e9) {
int nearest = static_cast<int> (floor(value + 0.5)) ;
if (fabs(value - floor(value + 0.5)) > 1.0e-8) {
increment = 0 ;
break ;
} else if (!increment) {
increment = nearest ;
} else {
increment = gcd(increment, nearest) ;
}
} else {
// large value - may still be multiple of 1.0
if (fabs(objValue - floor(objValue + 0.5)) > 1.0e-8) {
increment = 0;
break;
} else {
bigIntegers++;
}
}
}
}
}
delete [] coeffMultiplier;
/*
If the increment beats the current value for objective change, install it.
*/
if (increment) {
double value = increment ;
double cutoff = getDblParam(CbcModel::CbcCutoffIncrement) ;
if (bigIntegers) {
// allow for 1.0
increment = gcd(increment, static_cast<int> (multiplier));
value = increment;
}
value /= multiplier ;
value *= scaleFactor;
//trueIncrement=CoinMax(cutoff,value);;
if (value*0.999 > cutoff) {
messageHandler()->message(CBC_INTEGERINCREMENT,
messages())
<< value << CoinMessageEol ;
setDblParam(CbcModel::CbcCutoffIncrement, CoinMax(value*0.999,value-1.0e-4)) ;
}
}
}
return ;
}
/*
saveModel called (carved out of) BranchandBound
*/
void CbcModel::saveModel(OsiSolverInterface * saveSolver, double * checkCutoffForRestart, bool * feasible)
{
if (saveSolver && (specialOptions_&32768) != 0) {
// See if worth trying reduction
*checkCutoffForRestart = getCutoff();
bool tryNewSearch = solverCharacteristics_->reducedCostsAccurate() &&
(*checkCutoffForRestart < 1.0e20);
int numberColumns = getNumCols();
if (tryNewSearch) {
#if CBC_USEFUL_PRINTING>1
printf("after %d nodes, cutoff %g - looking\n",
numberNodes_, getCutoff());
#endif
saveSolver->resolve();
double direction = saveSolver->getObjSense() ;
double gap = *checkCutoffForRestart - saveSolver->getObjValue() * direction ;
double tolerance;
saveSolver->getDblParam(OsiDualTolerance, tolerance) ;
if (gap <= 0.0)
gap = tolerance;
gap += 100.0 * tolerance;
double integerTolerance = getDblParam(CbcIntegerTolerance) ;
const double *lower = saveSolver->getColLower() ;
const double *upper = saveSolver->getColUpper() ;
const double *solution = saveSolver->getColSolution() ;
const double *reducedCost = saveSolver->getReducedCost() ;
int numberFixed = 0 ;
int numberFixed2 = 0;
for (int i = 0 ; i < numberIntegers_ ; i++) {
int iColumn = integerVariable_[i] ;
double djValue = direction * reducedCost[iColumn] ;
if (upper[iColumn] - lower[iColumn] > integerTolerance) {
if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) {
saveSolver->setColUpper(iColumn, lower[iColumn]) ;
numberFixed++ ;
} else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) {
saveSolver->setColLower(iColumn, upper[iColumn]) ;
numberFixed++ ;
}
} else {
numberFixed2++;
}
}
#ifdef COIN_DEVELOP
/*
We're debugging. (specialOptions 1)
*/
if ((specialOptions_&1) != 0) {
const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger() ;
if (debugger) {
printf("Contains optimal\n") ;
OsiSolverInterface * temp = saveSolver->clone();
const double * solution = debugger->optimalSolution();
const double *lower = temp->getColLower() ;
const double *upper = temp->getColUpper() ;
int n = temp->getNumCols();
for (int i = 0; i < n; i++) {
if (temp->isInteger(i)) {
double value = floor(solution[i] + 0.5);
assert (value >= lower[i] && value <= upper[i]);
temp->setColLower(i, value);
temp->setColUpper(i, value);
}
}
temp->writeMps("reduced_fix");
delete temp;
saveSolver->writeMps("reduced");
} else {
abort();
}
}
printf("Restart could fix %d integers (%d already fixed)\n",
numberFixed + numberFixed2, numberFixed2);
#endif
numberFixed += numberFixed2;
if (numberFixed*20 < numberColumns)
tryNewSearch = false;
}
if (tryNewSearch) {
// back to solver without cuts?
OsiSolverInterface * solver2 = continuousSolver_->clone();
const double *lower = saveSolver->getColLower() ;
const double *upper = saveSolver->getColUpper() ;
for (int i = 0 ; i < numberIntegers_ ; i++) {
int iColumn = integerVariable_[i] ;
solver2->setColLower(iColumn, lower[iColumn]);
solver2->setColUpper(iColumn, upper[iColumn]);
}
// swap
delete saveSolver;
saveSolver = solver2;
double * newSolution = new double[numberColumns];
double objectiveValue = *checkCutoffForRestart;
CbcSerendipity heuristic(*this);
if (bestSolution_)
heuristic.setInputSolution(bestSolution_, bestObjective_);
heuristic.setFractionSmall(0.9);
heuristic.setFeasibilityPumpOptions(1008013);
// Use numberNodes to say how many are original rows
heuristic.setNumberNodes(continuousSolver_->getNumRows());
#ifdef COIN_DEVELOP
if (continuousSolver_->getNumRows() <
saveSolver->getNumRows())
printf("%d rows added ZZZZZ\n",
solver_->getNumRows() - continuousSolver_->getNumRows());
#endif
int returnCode = heuristic.smallBranchAndBound(saveSolver,
-1, newSolution,
objectiveValue,
*checkCutoffForRestart, "Reduce");
if (returnCode < 0) {
#ifdef COIN_DEVELOP
printf("Restart - not small enough to do search after fixing\n");
#endif
delete [] newSolution;
} else {
if ((returnCode&1) != 0) {
// increment number of solutions so other heuristics can test
numberSolutions_++;
numberHeuristicSolutions_++;
lastHeuristic_ = NULL;
setBestSolution(CBC_ROUNDING, objectiveValue, newSolution) ;
}
delete [] newSolution;
*feasible = false; // stop search
}
#if 0 // probably not needed def CBC_THREAD
if (master_) {
lockThread();
if (parallelMode() > 0) {
while (master_->waitForThreadsInTree(0)) {
lockThread();
double dummyBest;
tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
//unlockThread();
}
}
master_->waitForThreadsInTree(2);
delete master_;
master_ = NULL;
masterThread_ = NULL;
}
#endif
}
}
}
/*
Adds integers, called from BranchandBound()
*/
void CbcModel::AddIntegers()
{
int numberColumns = continuousSolver_->getNumCols();
int numberRows = continuousSolver_->getNumRows();
int numberOriginalIntegers = numberIntegers_;
int * del = new int [CoinMax(numberColumns, numberRows)];
int * original = new int [numberColumns];
char * possibleRow = new char [numberRows];
{
const CoinPackedMatrix * rowCopy = continuousSolver_->getMatrixByRow();
const int * column = rowCopy->getIndices();
const int * rowLength = rowCopy->getVectorLengths();
const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
const double * rowLower = continuousSolver_->getRowLower();
const double * rowUpper = continuousSolver_->getRowUpper();
const double * element = rowCopy->getElements();
for (int i = 0; i < numberRows; i++) {
int nLeft = 0;
bool possible = false;
if (rowLower[i] < -1.0e20) {
double value = rowUpper[i];
if (fabs(value - floor(value + 0.5)) < 1.0e-8)
possible = true;
} else if (rowUpper[i] > 1.0e20) {
double value = rowLower[i];
if (fabs(value - floor(value + 0.5)) < 1.0e-8)
possible = true;
} else {
double value = rowUpper[i];
if (rowLower[i] == rowUpper[i] &&
fabs(value - floor(value + 0.5)) < 1.0e-8)
possible = true;
}
double allSame = (possible) ? 0.0 : -1.0;
for (CoinBigIndex j = rowStart[i];
j < rowStart[i] + rowLength[i]; j++) {
int iColumn = column[j];
if (continuousSolver_->isInteger(iColumn)) {
if (fabs(element[j]) != 1.0)
possible = false;
} else {
nLeft++;
if (!allSame) {
allSame = fabs(element[j]);
} else if (allSame>0.0) {
if (allSame!=fabs(element[j]))
allSame = -1.0;
}
}
}
if (nLeft == rowLength[i] && allSame > 0.0)
possibleRow[i] = 2;
else if (possible || !nLeft)
possibleRow[i] = 1;
else
possibleRow[i] = 0;
}
}
int nDel = 0;
for (int i = 0; i < numberColumns; i++) {
original[i] = i;
if (continuousSolver_->isInteger(i))
del[nDel++] = i;
}
{
// we must not exclude current best solution (rounding errors)
// also not if large values
const int * row = continuousSolver_->getMatrixByCol()->getIndices();
const CoinBigIndex * columnStart = continuousSolver_->getMatrixByCol()->getVectorStarts();
const int * columnLength = continuousSolver_->getMatrixByCol()->getVectorLengths();
const double * solution = continuousSolver_->getColSolution();
for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
if (!continuousSolver_->isInteger(iColumn)) {
double value = bestSolution_ ? bestSolution_[iColumn] : 0.0;
double value2 = solution[iColumn];
if (fabs(value-floor(value+0.5))>1.0e-8 ||
fabs(value2)>1.0e3) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
possibleRow[iRow]=0;
}
}
}
}
}
int nExtra = 0;
OsiSolverInterface * copy1 = continuousSolver_->clone();
int nPass = 0;
while (nDel && nPass < 10) {
nPass++;
OsiSolverInterface * copy2 = copy1->clone();
int nLeft = 0;
for (int i = 0; i < nDel; i++)
original[del[i]] = -1;
for (int i = 0; i < numberColumns; i++) {
int kOrig = original[i];
if (kOrig >= 0)
original[nLeft++] = kOrig;
}
assert (nLeft == numberColumns - nDel);
copy2->deleteCols(nDel, del);
numberColumns = copy2->getNumCols();
const CoinPackedMatrix * rowCopy = copy2->getMatrixByRow();
numberRows = rowCopy->getNumRows();
const int * column = rowCopy->getIndices();
const int * rowLength = rowCopy->getVectorLengths();
const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
const double * rowLower = copy2->getRowLower();
const double * rowUpper = copy2->getRowUpper();
const double * element = rowCopy->getElements();
const CoinPackedMatrix * columnCopy = copy2->getMatrixByCol();
const int * columnLength = columnCopy->getVectorLengths();
nDel = 0;
// Could do gcd stuff on ones with costs
for (int i = 0; i < numberRows; i++) {
if (!rowLength[i]) {
del[nDel++] = i;
} else if (possibleRow[i]) {
if (rowLength[i] == 1) {
int k = rowStart[i];
int iColumn = column[k];
if (!copy2->isInteger(iColumn)) {
double mult = 1.0 / fabs(element[k]);
if (rowLower[i] < -1.0e20) {
// treat rhs as multiple of 1 unless elements all same
double value = ((possibleRow[i]==2) ? rowUpper[i] : 1.0) * mult;
if (fabs(value - floor(value + 0.5)) < 1.0e-8) {
del[nDel++] = i;
if (columnLength[iColumn] == 1) {
copy2->setInteger(iColumn);
int kOrig = original[iColumn];
setOptionalInteger(kOrig);
}
}
} else if (rowUpper[i] > 1.0e20) {
// treat rhs as multiple of 1 unless elements all same
double value = ((possibleRow[i]==2) ? rowLower[i] : 1.0) * mult;
if (fabs(value - floor(value + 0.5)) < 1.0e-8) {
del[nDel++] = i;
if (columnLength[iColumn] == 1) {
copy2->setInteger(iColumn);
int kOrig = original[iColumn];
setOptionalInteger(kOrig);
}
}
} else {
// treat rhs as multiple of 1 unless elements all same
double value = ((possibleRow[i]==2) ? rowUpper[i] : 1.0) * mult;
if (rowLower[i] == rowUpper[i] &&
fabs(value - floor(value + 0.5)) < 1.0e-8) {
del[nDel++] = i;
copy2->setInteger(iColumn);
int kOrig = original[iColumn];
setOptionalInteger(kOrig);
}
}
}
} else {
// only if all singletons
bool possible = false;
if (rowLower[i] < -1.0e20) {
double value = rowUpper[i];
if (fabs(value - floor(value + 0.5)) < 1.0e-8)
possible = true;
} else if (rowUpper[i] > 1.0e20) {
double value = rowLower[i];
if (fabs(value - floor(value + 0.5)) < 1.0e-8)
possible = true;
} else {
double value = rowUpper[i];
if (rowLower[i] == rowUpper[i] &&
fabs(value - floor(value + 0.5)) < 1.0e-8)
possible = true;
}
if (possible) {
for (CoinBigIndex j = rowStart[i];
j < rowStart[i] + rowLength[i]; j++) {
int iColumn = column[j];
if (columnLength[iColumn] != 1 || fabs(element[j]) != 1.0) {
possible = false;
break;
}
}
if (possible) {
for (CoinBigIndex j = rowStart[i];
j < rowStart[i] + rowLength[i]; j++) {
int iColumn = column[j];
if (!copy2->isInteger(iColumn)) {
copy2->setInteger(iColumn);
int kOrig = original[iColumn];
setOptionalInteger(kOrig);
}
}
del[nDel++] = i;
}
}
}
}
}
if (nDel) {
copy2->deleteRows(nDel, del);
// pack down possible
int n=0;
for (int i=0;i<nDel;i++)
possibleRow[del[i]]=-1;
for (int i=0;i<numberRows;i++) {
if (possibleRow[i]>=0)
possibleRow[n++]=possibleRow[i];
}
}
if (nDel != numberRows) {
nDel = 0;
for (int i = 0; i < numberColumns; i++) {
if (copy2->isInteger(i)) {
del[nDel++] = i;
nExtra++;
}
}
} else {
nDel = 0;
}
delete copy1;
copy1 = copy2->clone();
delete copy2;
}
// See if what's left is a network
bool couldBeNetwork = false;
if (copy1->getNumRows() && copy1->getNumCols()) {
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (copy1);
if (false && clpSolver) {
numberRows = clpSolver->getNumRows();
char * rotate = new char[numberRows];
int n = clpSolver->getModelPtr()->findNetwork(rotate, 1.0);
delete [] rotate;
#if CBC_USEFUL_PRINTING>1
printf("INTA network %d rows out of %d\n", n, numberRows);
#endif
if (CoinAbs(n) == numberRows) {
couldBeNetwork = true;
for (int i = 0; i < numberRows; i++) {
if (!possibleRow[i]) {
couldBeNetwork = false;
#if CBC_USEFUL_PRINTING>1
printf("but row %d is bad\n", i);
#endif
break;
}
}
}
} else
#endif
{
numberColumns = copy1->getNumCols();
numberRows = copy1->getNumRows();
const double * rowLower = copy1->getRowLower();
const double * rowUpper = copy1->getRowUpper();
couldBeNetwork = true;
for (int i = 0; i < numberRows; i++) {
if (rowLower[i] > -1.0e20 && fabs(rowLower[i] - floor(rowLower[i] + 0.5)) > 1.0e-12) {
couldBeNetwork = false;
break;
}
if (rowUpper[i] < 1.0e20 && fabs(rowUpper[i] - floor(rowUpper[i] + 0.5)) > 1.0e-12) {
couldBeNetwork = false;
break;
}
if (possibleRow[i]==0) {
couldBeNetwork = false;
break;
}
}
if (couldBeNetwork) {
const CoinPackedMatrix * matrixByCol = copy1->getMatrixByCol();
const double * element = matrixByCol->getElements();
//const int * row = matrixByCol->getIndices();
const CoinBigIndex * columnStart = matrixByCol->getVectorStarts();
const int * columnLength = matrixByCol->getVectorLengths();
for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
if (end > start + 2) {
couldBeNetwork = false;
break;
}
int type = 0;
for (CoinBigIndex j = start; j < end; j++) {
double value = element[j];
if (fabs(value) != 1.0) {
couldBeNetwork = false;
break;
} else if (value == 1.0) {
if ((type&1) == 0)
type |= 1;
else
type = 7;
} else if (value == -1.0) {
if ((type&2) == 0)
type |= 2;
else
type = 7;
}
}
if (type > 3) {
couldBeNetwork = false;
break;
}
}
}
}
}
if (couldBeNetwork) {
for (int i = 0; i < numberColumns; i++)
setOptionalInteger(original[i]);
}
if (nExtra || couldBeNetwork) {
numberColumns = copy1->getNumCols();
numberRows = copy1->getNumRows();
if (!numberColumns || !numberRows) {
int numberColumns = solver_->getNumCols();
for (int i = 0; i < numberColumns; i++)
assert(solver_->isInteger(i));
}
#if CBC_USEFUL_PRINTING>1
if (couldBeNetwork || nExtra)
printf("INTA %d extra integers, %d left%s\n", nExtra,
numberColumns,
couldBeNetwork ? ", all network" : "");
#endif
findIntegers(true, 2);
convertToDynamic();
}
#if CBC_USEFUL_PRINTING>1
if (!couldBeNetwork && copy1->getNumCols() &&
copy1->getNumRows()) {
printf("INTA %d rows and %d columns remain\n",
copy1->getNumRows(), copy1->getNumCols());
if (copy1->getNumCols() < 200) {
copy1->writeMps("moreint");
printf("INTA Written remainder to moreint.mps.gz %d rows %d cols\n",
copy1->getNumRows(), copy1->getNumCols());
}
}
#endif
delete copy1;
delete [] del;
delete [] original;
delete [] possibleRow;
// double check increment
analyzeObjective();
// If any changes - tell code
if(numberOriginalIntegers<numberIntegers_)
synchronizeModel();
}
/**
\todo
Normally, it looks like we enter here from command dispatch in the main
routine, after calling the solver for an initial solution
(CbcModel::initialSolve, which simply calls the solver's initialSolve
routine.) The first thing we do is call resolve. Presumably there are
circumstances where this is nontrivial? There's also a call from
CbcModel::originalModel (tied up with integer presolve), which should be
checked.
*/
#ifdef CONFLICT_CUTS
#if PRINT_CONFLICT==1
static int numberConflictCuts=0;
static int lastNumberConflictCuts=0;
static double lengthConflictCuts=0.0;
#endif
#endif
/*
The overall flow can be divided into three stages:
* Prep: Check that the lp relaxation remains feasible at the root. If so,
do all the setup for B&C.
* Process the root node: Generate cuts, apply heuristics, and in general do
the best we can to resolve the problem without B&C.
* Do B&C search until we hit a limit or exhaust the search tree.
Keep in mind that in general there is no node in the search tree that
corresponds to the active subproblem. The active subproblem is represented
by the current state of the model, of the solver, and of the constraint
system held by the solver.
*/
#ifdef COIN_HAS_CPX
#include "OsiCpxSolverInterface.hpp"
#include "cplex.h"
#endif
void CbcModel::branchAndBound(int doStatistics)
{
if (!parentModel_) {
/*
Capture a time stamp before we start (unless set).
*/
if (!dblParam_[CbcStartSeconds]) {
if (!useElapsedTime())
dblParam_[CbcStartSeconds] = CoinCpuTime();
else
dblParam_[CbcStartSeconds] = CoinGetTimeOfDay();
}
}
dblParam_[CbcSmallestChange] = COIN_DBL_MAX;
dblParam_[CbcSumChange] = 0.0;
dblParam_[CbcLargestChange] = 0.0;
intParam_[CbcNumberBranches] = 0;
double lastBestPossibleObjective=-COIN_DBL_MAX;
// when to check for restart
int nextCheckRestart=50;
// Force minimization !!!!
bool flipObjective = (solver_->getObjSense()<0.0);
if (flipObjective)
flipModel();
dblParam_[CbcOptimizationDirection] = 1.0; // was solver_->getObjSense();
strongInfo_[0] = 0;
strongInfo_[1] = 0;
strongInfo_[2] = 0;
strongInfo_[3] = 0;
strongInfo_[4] = 0;
strongInfo_[5] = 0;
strongInfo_[6] = 0;
numberStrongIterations_ = 0;
currentNode_ = NULL;
// See if should do cuts old way
if (parallelMode() < 0) {
specialOptions_ |= 4096 + 8192;
} else if (parallelMode() > 0) {
specialOptions_ |= 4096;
}
int saveMoreSpecialOptions = moreSpecialOptions_;
if (dynamic_cast<CbcTreeLocal *> (tree_))
specialOptions_ |= 4096 + 8192;
#ifdef COIN_HAS_CLP
{
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
// pass in disaster handler
CbcDisasterHandler handler(this);
clpSolver->passInDisasterHandler(&handler);
// Initialise solvers seed (unless users says not)
if ((specialOptions_&4194304)==0)
clpSolver->getModelPtr()->setRandomSeed(1234567);
#ifdef JJF_ZERO
// reduce factorization frequency
int frequency = clpSolver->getModelPtr()->factorizationFrequency();
clpSolver->getModelPtr()->setFactorizationFrequency(CoinMin(frequency, 120));
#endif
}
}
#endif
// original solver (only set if pre-processing)
OsiSolverInterface * originalSolver = NULL;
int numberOriginalObjects = numberObjects_;
OsiObject ** originalObject = NULL;
// Save whether there were any objects
bool noObjects = (numberObjects_ == 0);
// Set up strategies
/*
See if the user has supplied a strategy object and deal with it if present.
The call to setupOther will set numberStrong_ and numberBeforeTrust_, and
perform integer preprocessing, if requested.
We need to hang on to a pointer to solver_. setupOther will assign a
preprocessed solver to model, but will instruct assignSolver not to trash the
existing one.
*/
if (strategy_) {
// May do preprocessing
originalSolver = solver_;
strategy_->setupOther(*this);
if (strategy_->preProcessState()) {
// pre-processing done
if (strategy_->preProcessState() < 0) {
// infeasible (or unbounded)
status_ = 0 ;
if (!solver_->isProvenDualInfeasible()) {
handler_->message(CBC_INFEAS, messages_) << CoinMessageEol ;
secondaryStatus_ = 1;
} else {
handler_->message(CBC_UNBOUNDED,
messages_) << CoinMessageEol ;
secondaryStatus_ = 7;
}
originalContinuousObjective_ = COIN_DBL_MAX;
if (flipObjective)
flipModel();
return ;
} else if (numberObjects_ && object_) {
numberOriginalObjects = numberObjects_;
// redo sequence
numberIntegers_ = 0;
int numberColumns = getNumCols();
int nOrig = originalSolver->getNumCols();
CglPreProcess * process = strategy_->process();
assert (process);
const int * originalColumns = process->originalColumns();
// allow for cliques etc
nOrig = CoinMax(nOrig, originalColumns[numberColumns-1] + 1);
// try and redo debugger
OsiRowCutDebugger * debugger = const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
if (debugger) {
if (numberColumns<=debugger->numberColumns())
debugger->redoSolution(numberColumns, originalColumns);
else
debugger=NULL; // no idea how to handle (SOS?)
}
// User-provided solution might have been best. Synchronise.
if (bestSolution_) {
// need to redo - in case no better found in BAB
// just get integer part right
for (int i = 0; i < numberColumns; i++) {
int jColumn = originalColumns[i];
bestSolution_[i] = bestSolution_[jColumn];
}
}
originalObject = object_;
// object number or -1
int * temp = new int[nOrig];
int iColumn;
for (iColumn = 0; iColumn < nOrig; iColumn++)
temp[iColumn] = -1;
int iObject;
int nNonInt = 0;
for (iObject = 0; iObject < numberOriginalObjects; iObject++) {
iColumn = originalObject[iObject]->columnNumber();
if (iColumn < 0) {
nNonInt++;
} else {
temp[iColumn] = iObject;
}
}
int numberNewIntegers = 0;
int numberOldIntegers = 0;
int numberOldOther = 0;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
int jColumn = originalColumns[iColumn];
if (temp[jColumn] >= 0) {
int iObject = temp[jColumn];
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
if (obj)
numberOldIntegers++;
else
numberOldOther++;
} else if (isInteger(iColumn)) {
numberNewIntegers++;
}
}
/*
Allocate an array to hold the indices of the integer variables.
Make a large enough array for all objects
*/
numberObjects_ = numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt;
object_ = new OsiObject * [numberObjects_];
delete [] integerVariable_;
integerVariable_ = new int [numberNewIntegers+numberOldIntegers];
/*
Walk the variables again, filling in the indices and creating objects for
the integer variables. Initially, the objects hold the index and upper &
lower bounds.
*/
numberIntegers_ = 0;
int n = originalColumns[numberColumns-1] + 1;
int * backward = new int[n];
int i;
for ( i = 0; i < n; i++)
backward[i] = -1;
for (i = 0; i < numberColumns; i++)
backward[originalColumns[i]] = i;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
int jColumn = originalColumns[iColumn];
if (temp[jColumn] >= 0) {
int iObject = temp[jColumn];
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
if (obj) {
object_[numberIntegers_] = originalObject[iObject]->clone();
// redo ids etc
//object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns);
object_[numberIntegers_]->resetSequenceEtc(numberColumns, backward);
integerVariable_[numberIntegers_++] = iColumn;
}
} else if (isInteger(iColumn)) {
object_[numberIntegers_] =
new CbcSimpleInteger(this, iColumn);
integerVariable_[numberIntegers_++] = iColumn;
}
}
delete [] backward;
numberObjects_ = numberIntegers_;
// Now append other column stuff
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
int jColumn = originalColumns[iColumn];
if (temp[jColumn] >= 0) {
int iObject = temp[jColumn];
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
if (!obj) {
object_[numberObjects_] = originalObject[iObject]->clone();
// redo ids etc
CbcObject * obj =
dynamic_cast <CbcObject *>(object_[numberObjects_]) ;
assert (obj);
obj->redoSequenceEtc(this, numberColumns, originalColumns);
numberObjects_++;
}
}
}
// now append non column stuff
for (iObject = 0; iObject < numberOriginalObjects; iObject++) {
iColumn = originalObject[iObject]->columnNumber();
if (iColumn < 0) {
// already has column numbers changed
object_[numberObjects_] = originalObject[iObject]->clone();
#ifdef JJF_ZERO
// redo ids etc
CbcObject * obj =
dynamic_cast <CbcObject *>(object_[numberObjects_]) ;
assert (obj);
obj->redoSequenceEtc(this, numberColumns, originalColumns);
#endif
numberObjects_++;
}
}
delete [] temp;
if (!numberObjects_)
handler_->message(CBC_NOINT, messages_) << CoinMessageEol ;
} else {
int numberColumns = getNumCols();
CglPreProcess * process = strategy_->process();
assert (process);
const int * originalColumns = process->originalColumns();
// try and redo debugger
OsiRowCutDebugger * debugger = const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
if (debugger)
debugger->redoSolution(numberColumns, originalColumns);
}
} else {
//no preprocessing
originalSolver = NULL;
}
strategy_->setupCutGenerators(*this);
strategy_->setupHeuristics(*this);
// Set strategy print level to models
strategy_->setupPrinting(*this, handler_->logLevel());
}
eventHappened_ = false;
CbcEventHandler *eventHandler = getEventHandler() ;
if (eventHandler)
eventHandler->setModel(this);
#define CLIQUE_ANALYSIS
#ifdef CLIQUE_ANALYSIS
// set up for probing
// If we're doing clever stuff with cliques, additional info here.
if (!parentModel_)
probingInfo_ = new CglTreeProbingInfo(solver_);
else
probingInfo_ = NULL;
#else
probingInfo_ = NULL;
#endif
// Try for dominated columns
if ((specialOptions_&64) != 0) {
CglDuplicateRow dupcuts(solver_);
dupcuts.setMode(2);
CglStored * storedCuts = dupcuts.outDuplicates(solver_);
if (storedCuts) {
COIN_DETAIL_PRINT(printf("adding dup cuts\n"));
addCutGenerator(storedCuts, 1, "StoredCuts from dominated",
true, false, false, -200);
}
}
if (!nodeCompare_)
nodeCompare_ = new CbcCompareDefault();;
// See if hot start wanted
CbcCompareBase * saveCompare = NULL;
// User supplied hotstart. Adapt for preprocessing.
if (hotstartSolution_) {
if (strategy_ && strategy_->preProcessState() > 0) {
CglPreProcess * process = strategy_->process();
assert (process);
int n = solver_->getNumCols();
const int * originalColumns = process->originalColumns();
// columns should be in order ... but
double * tempS = new double[n];
for (int i = 0; i < n; i++) {
int iColumn = originalColumns[i];
tempS[i] = hotstartSolution_[iColumn];
}
delete [] hotstartSolution_;
hotstartSolution_ = tempS;
if (hotstartPriorities_) {
int * tempP = new int [n];
for (int i = 0; i < n; i++) {
int iColumn = originalColumns[i];
tempP[i] = hotstartPriorities_[iColumn];
}
delete [] hotstartPriorities_;
hotstartPriorities_ = tempP;
}
}
saveCompare = nodeCompare_;
// depth first
nodeCompare_ = new CbcCompareDepth();
}
if (!problemFeasibility_)
problemFeasibility_ = new CbcFeasibilityBase();
# ifdef CBC_DEBUG
std::string problemName ;
solver_->getStrParam(OsiProbName, problemName) ;
printf("Problem name - %s\n", problemName.c_str()) ;
solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0) ;
# endif
/*
Assume we're done, and see if we're proven wrong.
*/
status_ = 0 ;
secondaryStatus_ = 0;
phase_ = 0;
/*
Scan the variables, noting the integer variables. Create an
CbcSimpleInteger object for each integer variable.
*/
findIntegers(false) ;
// Say not dynamic pseudo costs
ownership_ &= ~0x40000000;
// If dynamic pseudo costs then do
if (numberBeforeTrust_)
convertToDynamic();
// Set up char array to say if integer (speed)
delete [] integerInfo_;
{
int n = solver_->getNumCols();
integerInfo_ = new char [n];
for (int i = 0; i < n; i++) {
if (solver_->isInteger(i))
integerInfo_[i] = 1;
else
integerInfo_[i] = 0;
}
}
if (preferredWay_) {
// set all unset ones
for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) {
CbcObject * obj =
dynamic_cast <CbcObject *>(object_[iObject]) ;
if (obj && !obj->preferredWay())
obj->setPreferredWay(preferredWay_);
}
}
/*
Ensure that objects on the lists of OsiObjects, heuristics, and cut
generators attached to this model all refer to this model.
*/
synchronizeModel() ;
if (!solverCharacteristics_) {
OsiBabSolver * solverCharacteristics = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
if (solverCharacteristics) {
solverCharacteristics_ = solverCharacteristics;
} else {
// replace in solver
OsiBabSolver defaultC;
solver_->setAuxiliaryInfo(&defaultC);
solverCharacteristics_ = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
}
}
solverCharacteristics_->setSolver(solver_);
// Set so we can tell we are in initial phase in resolve
continuousObjective_ = -COIN_DBL_MAX ;
/*
Solve the relaxation.
Apparently there are circumstances where this will be non-trivial --- i.e.,
we've done something since initialSolve that's trashed the solution to the
continuous relaxation.
*/
/* Tell solver we are in Branch and Cut
Could use last parameter for subtle differences */
solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
#ifdef COIN_HAS_CLP
{
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
ClpSimplex * clpSimplex = clpSolver->getModelPtr();
if ((specialOptions_&32) == 0) {
// take off names (unless going to be saving)
if (numberAnalyzeIterations_>=0||(-numberAnalyzeIterations_&64)==0)
clpSimplex->dropNames();
}
// no crunch if mostly continuous
if ((clpSolver->specialOptions()&(1 + 8)) != (1 + 8)) {
int numberColumns = solver_->getNumCols();
if (numberColumns > 1000 && numberIntegers_*4 < numberColumns)
clpSolver->setSpecialOptions(clpSolver->specialOptions()&(~1));
}
//#define NO_CRUNCH
#ifdef NO_CRUNCH
printf("TEMP switching off crunch\n");
int iOpt = clpSolver->specialOptions();
iOpt &= ~1;
iOpt |= 65536;
clpSolver->setSpecialOptions(iOpt);
#endif
}
}
#endif
bool feasible;
numberSolves_ = 0 ;
{
// check
int numberOdd = 0;
for (int i = 0; i < numberObjects_; i++) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(object_[i]) ;
if (!obj)
numberOdd++;
}
if (numberOdd)
moreSpecialOptions_ |= 1073741824;
}
// If NLP then we assume already solved outside branchAndbound
if (!solverCharacteristics_->solverType() || solverCharacteristics_->solverType() == 4) {
feasible = resolve(NULL, 0) != 0 ;
} else {
// pick up given status
feasible = (solver_->isProvenOptimal() &&
!solver_->isDualObjectiveLimitReached()) ;
}
if (problemFeasibility_->feasible(this, 0) < 0) {
feasible = false; // pretend infeasible
}
numberSavedSolutions_ = 0;
int saveNumberStrong = numberStrong_;
int saveNumberBeforeTrust = numberBeforeTrust_;
/*
If the linear relaxation of the root is infeasible, bail out now. Otherwise,
continue with processing the root node.
*/
if (!feasible) {
status_ = 0 ;
if (!solver_->isProvenDualInfeasible()) {
handler_->message(CBC_INFEAS, messages_) << CoinMessageEol ;
secondaryStatus_ = 1;
} else {
handler_->message(CBC_UNBOUNDED, messages_) << CoinMessageEol ;
secondaryStatus_ = 7;
}
originalContinuousObjective_ = COIN_DBL_MAX;
if (bestSolution_ &&
((specialOptions_&8388608)==0||(specialOptions_&2048)!=0)) {
// best solution found by various heuristics - set solution
char general[200];
sprintf(general,"Solution of %g already found by heuristic",
bestObjective_);
messageHandler()->message(CBC_GENERAL,
messages())
<< general << CoinMessageEol ;
setCutoff(1.0e50) ; // As best solution should be worse than cutoff
// change cutoff as constraint if wanted
if (cutoffRowNumber_>=0) {
if (solver_->getNumRows()>cutoffRowNumber_)
solver_->setRowUpper(cutoffRowNumber_,1.0e50);
}
// also in continuousSolver_
if (continuousSolver_) {
// Solvers know about direction
double direction = solver_->getObjSense();
continuousSolver_->setDblParam(OsiDualObjectiveLimit, 1.0e50*direction);
} else {
continuousSolver_ = solver_->clone();
}
phase_ = 5;
double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
if ((specialOptions_&4) == 0)
bestObjective_ += 100.0 * increment + 1.0e-3; // only set if we are going to solve
setBestSolution(CBC_END_SOLUTION, bestObjective_, bestSolution_, 1) ;
continuousSolver_->resolve() ;
if (!continuousSolver_->isProvenOptimal()) {
continuousSolver_->messageHandler()->setLogLevel(2) ;
continuousSolver_->initialSolve() ;
}
delete solver_ ;
solverCharacteristics_=NULL;
solver_ = continuousSolver_ ;
setPointers(solver_);
continuousSolver_ = NULL ;
}
solverCharacteristics_ = NULL;
if (flipObjective)
flipModel();
return ;
} else if (!numberObjects_) {
// nothing to do
// Undo preprocessing performed during BaB.
if (strategy_ && strategy_->preProcessState() > 0) {
// undo preprocessing
CglPreProcess * process = strategy_->process();
assert (process);
int n = originalSolver->getNumCols();
if (bestSolution_) {
delete [] bestSolution_;
bestSolution_ = new double [n];
process->postProcess(*solver_);
}
strategy_->deletePreProcess();
// Solution now back in originalSolver
delete solver_;
solver_ = originalSolver;
if (bestSolution_) {
bestObjective_ = solver_->getObjValue() * solver_->getObjSense();
memcpy(bestSolution_, solver_->getColSolution(), n*sizeof(double));
}
// put back original objects if there were any
if (originalObject) {
int iColumn;
assert (ownObjects_);
for (iColumn = 0; iColumn < numberObjects_; iColumn++)
delete object_[iColumn];
delete [] object_;
numberObjects_ = numberOriginalObjects;
object_ = originalObject;
delete [] integerVariable_;
numberIntegers_ = 0;
for (iColumn = 0; iColumn < n; iColumn++) {
if (solver_->isInteger(iColumn))
numberIntegers_++;
}
integerVariable_ = new int[numberIntegers_];
numberIntegers_ = 0;
for (iColumn = 0; iColumn < n; iColumn++) {
if (solver_->isInteger(iColumn))
integerVariable_[numberIntegers_++] = iColumn;
}
}
}
if (flipObjective)
flipModel();
solverCharacteristics_ = NULL;
bestObjective_ = solver_->getObjValue() * solver_->getObjSense();
int numberColumns = solver_->getNumCols();
delete [] bestSolution_;
bestSolution_ = new double[numberColumns];
CoinCopyN(solver_->getColSolution(), numberColumns, bestSolution_);
return ;
}
/*
See if we're using the Osi side of the branching hierarchy. If so, either
convert existing CbcObjects to OsiObjects, or generate them fresh. In the
first case, CbcModel owns the objects on the object_ list. In the second
case, the solver holds the objects and object_ simply points to the
solver's list.
080417 The conversion code here (the block protected by `if (obj)') cannot
possibly be correct. On the Osi side, descent is OsiObject -> OsiObject2 ->
all other Osi object classes. On the Cbc side, it's OsiObject -> CbcObject
-> all other Cbc object classes. It's structurally impossible for any Osi
object to descend from CbcObject. The only thing I can see is that this is
really dead code, and object detection is now handled from the Osi side.
*/
// Convert to Osi if wanted
//OsiBranchingInformation * persistentInfo = NULL;
if (branchingMethod_ && branchingMethod_->chooseMethod()) {
//persistentInfo = new OsiBranchingInformation(solver_);
if (numberOriginalObjects) {
for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) {
CbcObject * obj =
dynamic_cast <CbcObject *>(object_[iObject]) ;
if (obj) {
CbcSimpleInteger * obj2 =
dynamic_cast <CbcSimpleInteger *>(obj) ;
if (obj2) {
// back to Osi land
object_[iObject] = obj2->osiObject();
delete obj;
} else {
OsiSimpleInteger * obj3 =
dynamic_cast <OsiSimpleInteger *>(obj) ;
if (!obj3) {
OsiSOS * obj4 =
dynamic_cast <OsiSOS *>(obj) ;
if (!obj4) {
CbcSOS * obj5 =
dynamic_cast <CbcSOS *>(obj) ;
if (obj5) {
// back to Osi land
object_[iObject] = obj5->osiObject(solver_);
} else {
printf("Code up CbcObject type in Osi land\n");
abort();
}
}
}
}
}
}
// and add to solver
//if (!solver_->numberObjects()) {
solver_->addObjects(numberObjects_, object_);
//} else {
//if (solver_->numberObjects()!=numberOriginalObjects) {
//printf("should have trapped that solver has objects before\n");
//abort();
//}
//}
} else {
/*
As of 080104, findIntegersAndSOS is misleading --- the default OSI
implementation finds only integers.
*/
// do from solver
deleteObjects(false);
solver_->findIntegersAndSOS(false);
numberObjects_ = solver_->numberObjects();
object_ = solver_->objects();
ownObjects_ = false;
}
branchingMethod_->chooseMethod()->setSolver(solver_);
}
// take off heuristics if have to (some do not work with SOS, for example)
// object should know what's safe.
{
int numberOdd = 0;
int numberSOS = 0;
for (int i = 0; i < numberObjects_; i++) {
if (!object_[i]->canDoHeuristics())
numberOdd++;
CbcSOS * obj =
dynamic_cast <CbcSOS *>(object_[i]) ;
if (obj)
numberSOS++;
}
if (numberOdd) {
if (numberHeuristics_ && (specialOptions_&1024)==0 ) {
int k = 0;
for (int i = 0; i < numberHeuristics_; i++) {
if (!heuristic_[i]->canDealWithOdd())
delete heuristic_[i];
else
heuristic_[k++] = heuristic_[i];
}
if (!k) {
delete [] heuristic_;
heuristic_ = NULL;
}
numberHeuristics_ = k;
handler_->message(CBC_HEURISTICS_OFF, messages_) << numberOdd << CoinMessageEol ;
}
// If odd switch off AddIntegers
specialOptions_ &= ~65536;
// switch off fast nodes for now
fastNodeDepth_ = -1;
moreSpecialOptions_ &= ~33554432; // no diving
} else if (numberSOS) {
specialOptions_ |= 128; // say can do SOS in dynamic mode
// switch off fast nodes for now
fastNodeDepth_ = -1;
moreSpecialOptions_ &= ~33554432; // no diving
}
if (numberThreads_ > 0) {
// switch off fast nodes for now
//fastNodeDepth_ = -1;
}
}
// Save objective (just so user can access it)
originalContinuousObjective_ = solver_->getObjValue()* solver_->getObjSense();
bestPossibleObjective_ = originalContinuousObjective_;
sumChangeObjective1_ = 0.0;
sumChangeObjective2_ = 0.0;
/*
OsiRowCutDebugger knows an optimal answer for a subset of MIP problems.
Assuming it recognises the problem, when called upon it will check a cut to
see if it cuts off the optimal answer.
*/
// If debugger exists set specialOptions_ bit
if (solver_->getRowCutDebuggerAlways()) {
specialOptions_ |= 1;
}
# ifdef CBC_DEBUG
if ((specialOptions_&1) == 0)
solver_->activateRowCutDebugger(problemName.c_str()) ;
if (solver_->getRowCutDebuggerAlways())
specialOptions_ |= 1;
# endif
/*
Begin setup to process a feasible root node.
*/
bestObjective_ = CoinMin(bestObjective_, 1.0e50) ;
if (!bestSolution_) {
numberSolutions_ = 0 ;
numberHeuristicSolutions_ = 0 ;
}
stateOfSearch_ = 0;
// Everything is minimization
{
// needed to sync cutoffs
double value ;
solver_->getDblParam(OsiDualObjectiveLimit, value) ;
dblParam_[CbcCurrentCutoff] = value * solver_->getObjSense();
}
double cutoff = getCutoff() ;
double direction = solver_->getObjSense() ;
dblParam_[CbcOptimizationDirection] = direction;
if (cutoff < 1.0e20 && direction < 0.0)
messageHandler()->message(CBC_CUTOFF_WARNING1,
messages())
<< cutoff << -cutoff << CoinMessageEol ;
if (cutoff > bestObjective_)
cutoff = bestObjective_ ;
setCutoff(cutoff) ;
/*
We probably already have a current solution, but just in case ...
*/
int numberColumns = getNumCols() ;
if (!currentSolution_)
currentSolution_ = new double[numberColumns] ;
testSolution_ = currentSolution_;
/*
Create a copy of the solver, thus capturing the original (root node)
constraint system (aka the continuous system).
*/
delete continuousSolver_;
continuousSolver_ = solver_->clone() ;
#ifdef COIN_HAS_NTY
// maybe allow on fix and restart later
if ((moreSpecialOptions2_&(128|256))!=0&&!parentModel_) {
symmetryInfo_ = new CbcSymmetry();
symmetryInfo_->setupSymmetry(*continuousSolver_);
int numberGenerators = symmetryInfo_->statsOrbits(this,0);
if (!symmetryInfo_->numberUsefulOrbits()&&(moreSpecialOptions2_&(128|256))!=(128|256)) {
delete symmetryInfo_;
symmetryInfo_=NULL;
moreSpecialOptions2_ &= ~(128|256);
}
if ((moreSpecialOptions2_&(128|256))==(128|256)) {
//moreSpecialOptions2_ &= ~256;
}
}
#endif
// add cutoff as constraint if wanted
if (cutoffRowNumber_==-2) {
if (!parentModel_) {
int numberColumns=solver_->getNumCols();
double * obj = CoinCopyOfArray(solver_->getObjCoefficients(),numberColumns);
int * indices = new int [numberColumns];
int n=0;
for (int i=0;i<numberColumns;i++) {
if (obj[i]) {
indices[n]=i;
obj[n++]=obj[i];
}
}
if (n) {
double cutoff=getCutoff();
// relax a little bit
cutoff += 1.0e-4;
double offset;
solver_->getDblParam(OsiObjOffset, offset);
cutoffRowNumber_ = solver_->getNumRows();
solver_->addRow(n,indices,obj,-COIN_DBL_MAX,CoinMin(cutoff,1.0e25)+offset);
} else {
// no objective!
cutoffRowNumber_ = -1;
}
delete [] indices;
delete [] obj;
} else {
// switch off
cutoffRowNumber_ = -1;
}
}
numberRowsAtContinuous_ = getNumRows() ;
solver_->saveBaseModel();
/*
Check the objective to see if we can deduce a nontrivial increment. If
it's better than the current value for CbcCutoffIncrement, it'll be
installed.
*/
if (solverCharacteristics_->reducedCostsAccurate())
analyzeObjective() ;
{
// may be able to change cutoff now
double cutoff = getCutoff();
double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
if (cutoff > bestObjective_ - increment) {
cutoff = bestObjective_ - increment ;
setCutoff(cutoff) ;
}
}
#ifdef COIN_HAS_CLP
// Possible save of pivot method
ClpDualRowPivot * savePivotMethod = NULL;
{
// pass tolerance and increment to solver
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver)
clpSolver->setStuff(getIntegerTolerance(), getCutoffIncrement());
#ifdef CLP_RESOLVE
if ((moreSpecialOptions_&1048576)!=0&&!parentModel_&&clpSolver) {
resolveClp(clpSolver,0);
}
#endif
}
#endif
/*
Set up for cut generation. addedCuts_ holds the cuts which are relevant for
the active subproblem. whichGenerator will be used to record the generator
that produced a given cut.
*/
#define INITIAL_MAXIMUM_WHICH 1000
maximumWhich_ = INITIAL_MAXIMUM_WHICH ;
delete [] whichGenerator_;
whichGenerator_ = new int[maximumWhich_] ;
memset(whichGenerator_, 0, maximumWhich_*sizeof(int));
maximumNumberCuts_ = 0 ;
currentNumberCuts_ = 0 ;
delete [] addedCuts_ ;
addedCuts_ = NULL ;
OsiObject ** saveObjects = NULL;
maximumRows_ = numberRowsAtContinuous_;
currentDepth_ = 0;
workingBasis_.resize(maximumRows_, numberColumns);
/*
Set up an empty heap and associated data structures to hold the live set
(problems which require further exploration).
*/
CbcCompareDefault * compareActual
= dynamic_cast<CbcCompareDefault *> (nodeCompare_);
if (compareActual) {
compareActual->setBestPossible(direction*solver_->getObjValue());
compareActual->setCutoff(getCutoff());
#ifdef JJF_ZERO
if (false && !numberThreads_ && !parentModel_) {
printf("CbcTreeArray ? threads ? parentArray\n");
// Setup new style tree
delete tree_;
tree_ = new CbcTreeArray();
}
#endif
}
tree_->setComparison(*nodeCompare_) ;
/*
Used to record the path from a node to the root of the search tree, so that
we can then traverse from the root to the node when restoring a subproblem.
*/
maximumDepth_ = 10 ;
delete [] walkback_ ;
walkback_ = new CbcNodeInfo * [maximumDepth_] ;
lastDepth_ = 0;
delete [] lastNodeInfo_ ;
lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ;
delete [] lastNumberCuts_ ;
lastNumberCuts_ = new int [maximumDepth_] ;
maximumCuts_ = 100;
lastNumberCuts2_ = 0;
delete [] lastCut_;
lastCut_ = new const OsiRowCut * [maximumCuts_];
/*
Used to generate bound edits for CbcPartialNodeInfo.
*/
double * lowerBefore = new double [numberColumns] ;
double * upperBefore = new double [numberColumns] ;
/*
Set up to run heuristics and generate cuts at the root node. The heavy
lifting is hidden inside the calls to doHeuristicsAtRoot and solveWithCuts.
To start, tell cut generators they can be a bit more aggressive at the
root node.
QUESTION: phase_ = 0 is documented as `initial solve', phase = 1 as `solve
with cuts at root'. Is phase_ = 1 the correct indication when
doHeurisiticsAtRoot is called to run heuristics outside of the main
cut / heurisitc / reoptimise loop in solveWithCuts?
Generate cuts at the root node and reoptimise. solveWithCuts does the heavy
lifting. It will iterate a generate/reoptimise loop (including reduced cost
fixing) until no cuts are generated, the change in objective falls off, or
the limit on the number of rounds of cut generation is exceeded.
At the end of all this, any cuts will be recorded in cuts and also
installed in the solver's constraint system. We'll have reoptimised, and
removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
adjusted accordingly).
Tell cut generators they can be a bit more aggressive at root node
TODO: Why don't we make a copy of the solution after solveWithCuts?
TODO: If numberUnsatisfied == 0, don't we have a solution?
*/
phase_ = 1;
int iCutGenerator;
for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
// If parallel switch off global cuts
if (numberThreads_) {
generator_[iCutGenerator]->setGlobalCuts(false);
generator_[iCutGenerator]->setGlobalCutsAtRoot(false);
}
CglCutGenerator * generator = generator_[iCutGenerator]->generator();
generator->setAggressiveness(generator->getAggressiveness() + 100);
if (!generator->canDoGlobalCuts())
generator->setGlobalCuts(false);
}
OsiCuts cuts ;
int anyAction = -1 ;
numberOldActiveCuts_ = 0 ;
numberNewCuts_ = 0 ;
// Array to mark solution
delete [] usedInSolution_;
usedInSolution_ = new int[numberColumns];
CoinZeroN(usedInSolution_, numberColumns);
/*
For printing totals and for CbcNode (numberNodes_)
*/
numberIterations_ = 0 ;
numberNodes_ = 0 ;
numberNodes2_ = 0 ;
maximumStatistics_ = 0;
maximumDepthActual_ = 0;
numberDJFixed_ = 0.0;
if (!parentModel_) {
if ((specialOptions_&262144) != 0) {
// create empty stored cuts
//storedRowCuts_ = new CglStored(solver_->getNumCols());
} else if ((specialOptions_&524288) != 0 && storedRowCuts_) {
// tighten and set best solution
// A) tight bounds on integer variables
/*
storedRowCuts_ are coming in from outside, probably for nonlinear.
John was unsure about origin.
*/
const double * lower = solver_->getColLower();
const double * upper = solver_->getColUpper();
const double * tightLower = storedRowCuts_->tightLower();
const double * tightUpper = storedRowCuts_->tightUpper();
int nTightened = 0;
for (int i = 0; i < numberIntegers_; i++) {
int iColumn = integerVariable_[i];
if (tightLower[iColumn] > lower[iColumn]) {
nTightened++;
solver_->setColLower(iColumn, tightLower[iColumn]);
}
if (tightUpper[iColumn] < upper[iColumn]) {
nTightened++;
solver_->setColUpper(iColumn, tightUpper[iColumn]);
}
}
if (nTightened)
COIN_DETAIL_PRINT(printf("%d tightened by alternate cuts\n", nTightened));
if (storedRowCuts_->bestObjective() < bestObjective_) {
// B) best solution
double objValue = storedRowCuts_->bestObjective();
setBestSolution(CBC_SOLUTION, objValue,
storedRowCuts_->bestSolution()) ;
// Do heuristics
// Allow RINS
for (int i = 0; i < numberHeuristics_; i++) {
CbcHeuristicRINS * rins
= dynamic_cast<CbcHeuristicRINS *> (heuristic_[i]);
if (rins) {
rins->setLastNode(-100);
}
}
}
}
}
#ifdef SWITCH_VARIABLES
// see if any switching variables
if (numberIntegers_<solver_->getNumCols())
findSwitching();
#endif
/*
Run heuristics at the root. This is the only opportunity to run FPump; it
will be removed from the heuristics list by doHeuristicsAtRoot.
*/
// See if multiple runs wanted
CbcModel ** rootModels=NULL;
if (!parentModel_&&multipleRootTries_%100) {
double rootTimeCpu=CoinCpuTime();
double startTimeRoot=CoinGetTimeOfDay();
int numberRootThreads=1;
/* undocumented fine tuning
aabbcc where cc is number of tries
bb if nonzero is number of threads
aa if nonzero just do heuristics
*/
int numberModels = multipleRootTries_%100;
#ifdef CBC_THREAD
numberRootThreads = (multipleRootTries_/100)%100;
if (!numberRootThreads)
numberRootThreads=numberModels;
#endif
int otherOptions = (multipleRootTries_/10000)%100;
rootModels = new CbcModel * [numberModels];
unsigned int newSeed = randomSeed_;
if (newSeed==0) {
double time = fabs(CoinGetTimeOfDay());
while (time>=COIN_INT_MAX)
time *= 0.5;
newSeed = static_cast<unsigned int>(time);
} else if (newSeed<0) {
newSeed = 123456789;
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
newSeed += clpSolver->getModelPtr()->randomNumberGenerator()->getSeed();
}
#endif
}
CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *> (solver_->getEmptyWarmStart());
for (int i=0;i<numberModels;i++) {
rootModels[i]=new CbcModel(*this);
rootModels[i]->setNumberThreads(0);
rootModels[i]->setMaximumNodes(otherOptions ? -1 : 0);
rootModels[i]->setRandomSeed(newSeed+10000000*i);
rootModels[i]->randomNumberGenerator()->setSeed(newSeed+50000000*i);
rootModels[i]->setMultipleRootTries(0);
// use seed
rootModels[i]->setSpecialOptions(specialOptions_ |(4194304|8388608));
rootModels[i]->setMoreSpecialOptions(moreSpecialOptions_ &
(~(134217728|4194304)));
rootModels[i]->setMoreSpecialOptions2(moreSpecialOptions2_ &
(~(128|256)));
rootModels[i]->solver_->setWarmStart(basis);
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (rootModels[i]->solver_);
#define NEW_RANDOM_BASIS
#ifdef NEW_RANDOM_BASIS
if (i==0)
continue;
#endif
if (clpSolver) {
ClpSimplex * simplex = clpSolver->getModelPtr();
if (defaultHandler_)
simplex->setDefaultMessageHandler();
simplex->setRandomSeed(newSeed+20000000*i);
simplex->allSlackBasis();
int logLevel=simplex->logLevel();
if (logLevel==1)
simplex->setLogLevel(0);
if (i!=0) {
#ifdef NEW_RANDOM_BASIS
int numberRows = simplex->numberRows();
int throwOut=20;//2+numberRows/100;
for (int iThrow=0;iThrow<throwOut;iThrow++) {
double random = simplex->randomNumberGenerator()->randomDouble();
int iStart=static_cast<int>(random*numberRows);
for (int j=iStart;j<numberRows;j++) {
if (simplex->getRowStatus(j)!=ClpSimplex::basic) {
simplex->setRowStatus(j,ClpSimplex::basic);
break;
}
}
}
clpSolver->setWarmStart(NULL);
#else
double random = simplex->randomNumberGenerator()->randomDouble();
int bias = static_cast<int>(random*(numberIterations/4));
simplex->setMaximumIterations(numberIterations/2+bias);
simplex->primal();
simplex->setMaximumIterations(COIN_INT_MAX);
simplex->dual();
#endif
} else {
#ifndef NEW_RANDOM_BASIS
simplex->primal();
#endif
#endif
}
#ifdef NEW_RANDOM_BASIS
simplex->setLogLevel(logLevel);
clpSolver->setWarmStart(NULL);
#endif
}
for (int j=0;j<numberHeuristics_;j++)
rootModels[i]->heuristic_[j]->setSeed(rootModels[i]->heuristic_[j]->getSeed()+100000000*i);
for (int j=0;j<numberCutGenerators_;j++)
rootModels[i]->generator_[j]->generator()->refreshSolver(rootModels[i]->solver_);
}
delete basis;
#ifdef CBC_THREAD
if (numberRootThreads==1) {
#endif
for (int iModel=0;iModel<numberModels;iModel++) {
doRootCbcThread(rootModels[iModel]);
// see if solved at root node
if (rootModels[iModel]->getMaximumNodes()) {
feasible=false;
break;
}
}
#ifdef CBC_THREAD
} else {
Coin_pthread_t * threadId = new Coin_pthread_t [numberRootThreads];
for (int kModel=0;kModel<numberModels;kModel+=numberRootThreads) {
bool finished=false;
for (int iModel=kModel;iModel<CoinMin(numberModels,kModel+numberRootThreads);iModel++) {
pthread_create(&(threadId[iModel-kModel].thr), NULL,
doRootCbcThread,
rootModels[iModel]);
}
// wait
for (int iModel=kModel;iModel<CoinMin(numberModels,kModel+numberRootThreads);iModel++) {
pthread_join(threadId[iModel-kModel].thr, NULL);
}
// see if solved at root node
for (int iModel=kModel;iModel<CoinMin(numberModels,kModel+numberRootThreads);iModel++) {
if (rootModels[iModel]->getMaximumNodes())
finished=true;
}
if (finished) {
feasible=false;
break;
}
}
delete [] threadId;
}
#endif
// sort solutions
int * which = new int [numberModels];
double * value = new double [numberModels];
int numberSolutions=0;
for (int iModel=0;iModel<numberModels;iModel++) {
if (rootModels[iModel]->bestSolution()) {
which[numberSolutions]=iModel;
value[numberSolutions++]=
-rootModels[iModel]->getMinimizationObjValue();
}
}
char general[100];
rootTimeCpu=CoinCpuTime()-rootTimeCpu;
if (numberRootThreads==1)
sprintf(general,"Multiple root solvers took a total of %.2f seconds\n",
rootTimeCpu);
else
sprintf(general,"Multiple root solvers took a total of %.2f seconds (%.2f elapsed)\n",
rootTimeCpu,CoinGetTimeOfDay()-startTimeRoot);
messageHandler()->message(CBC_GENERAL,
messages())
<< general << CoinMessageEol ;
CoinSort_2(value,value+numberSolutions,which);
// to get name
CbcHeuristicRINS dummyHeuristic;
dummyHeuristic.setHeuristicName("Multiple root solvers");
lastHeuristic_=&dummyHeuristic;
for (int i=0;i<numberSolutions;i++) {
double objValue = - value[i];
if (objValue<getCutoff()) {
int iModel=which[i];
setBestSolution(CBC_ROUNDING,objValue,
rootModels[iModel]->bestSolution());
}
}
lastHeuristic_=NULL;
delete [] which;
delete [] value;
}
// Do heuristics
if (numberObjects_&&!rootModels)
doHeuristicsAtRoot();
if (solverCharacteristics_->solutionAddsCuts()) {
// With some heuristics solver needs a resolve here
solver_->resolve();
if(!isProvenOptimal()){
solver_->initialSolve();
}
}
/*
Grepping through the code, it would appear that this is a command line
debugging hook. There's no obvious place in the code where this is set to
a negative value.
User hook, says John.
*/
if ( intParam_[CbcMaxNumNode] < 0
||numberSolutions_>=getMaximumSolutions())
eventHappened_ = true; // stop as fast as possible
stoppedOnGap_ = false ;
// See if can stop on gap
bestPossibleObjective_ = solver_->getObjValue() * solver_->getObjSense();
if(canStopOnGap()) {
if (bestPossibleObjective_ < getCutoff())
stoppedOnGap_ = true ;
feasible = false;
//eventHappened_=true; // stop as fast as possible
}
/*
Set up for statistics collection, if requested. Standard values are
documented in CbcModel.hpp. The magic number 100 will trigger a dump of
CbcSimpleIntegerDynamicPseudoCost objects (no others). Looks like another
command line debugging hook.
*/
statistics_ = NULL;
// Do on switch
if (doStatistics > 0 && doStatistics <= 100) {
maximumStatistics_ = 10000;
statistics_ = new CbcStatistics * [maximumStatistics_];
memset(statistics_, 0, maximumStatistics_*sizeof(CbcStatistics *));
}
// See if we can add integers
if (noObjects && numberIntegers_ < solver_->getNumCols() && (specialOptions_&65536) != 0 && !parentModel_)
AddIntegers();
/*
Do an initial round of cut generation for the root node. Depending on the
type of underlying solver, we may want to do this even if the initial query
to the objects indicates they're satisfied.
solveWithCuts does the heavy lifting. It will iterate a generate/reoptimise
loop (including reduced cost fixing) until no cuts are generated, the
change in objective falls off, or the limit on the number of rounds of cut
generation is exceeded.
At the end of all this, any cuts will be recorded in cuts and also
installed in the solver's constraint system. We'll have reoptimised, and
removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
adjusted accordingly).
*/
int iObject ;
int numberUnsatisfied = 0 ;
delete [] currentSolution_;
currentSolution_ = new double [numberColumns];
testSolution_ = currentSolution_;
memcpy(currentSolution_, solver_->getColSolution(),
numberColumns*sizeof(double)) ;
// point to useful information
OsiBranchingInformation usefulInfo = usefulInformation();
for (iObject = 0 ; iObject < numberObjects_ ; iObject++) {
double infeasibility =
object_[iObject]->checkInfeasibility(&usefulInfo) ;
if (infeasibility ) numberUnsatisfied++ ;
}
// replace solverType
double * tightBounds = NULL;
if (solverCharacteristics_->tryCuts()) {
if (numberUnsatisfied) {
// User event
if (!eventHappened_ && feasible) {
if (rootModels) {
// for fixings
int numberColumns=solver_->getNumCols();
tightBounds = new double [2*numberColumns];
{
const double * lower = solver_->getColLower();
const double * upper = solver_->getColUpper();
for (int i=0;i<numberColumns;i++) {
tightBounds[2*i+0]=lower[i];
tightBounds[2*i+1]=upper[i];
}
}
int numberModels = multipleRootTries_%100;
const OsiSolverInterface ** solvers = new
const OsiSolverInterface * [numberModels];
int numberRows=continuousSolver_->getNumRows();
int maxCuts=0;
for (int i=0;i<numberModels;i++) {
solvers[i]=rootModels[i]->solver();
const double * lower = solvers[i]->getColLower();
const double * upper = solvers[i]->getColUpper();
for (int j=0;j<numberColumns;j++) {
tightBounds[2*j+0]=CoinMax(lower[j],tightBounds[2*j+0]);
tightBounds[2*j+1]=CoinMin(upper[j],tightBounds[2*j+1]);
}
int numberRows2=solvers[i]->getNumRows();
assert (numberRows2>=numberRows);
maxCuts += numberRows2-numberRows;
// accumulate statistics
for (int j=0;j<numberCutGenerators_;j++) {
generator_[j]->addStatistics(rootModels[i]->cutGenerator(j));
}
}
for (int j=0;j<numberCutGenerators_;j++) {
generator_[j]->scaleBackStatistics(numberModels);
}
//CbcRowCuts rowCut(maxCuts);
const OsiRowCutDebugger *debugger = NULL;
if ((specialOptions_&1) != 0)
debugger = solver_->getRowCutDebugger() ;
for (int iModel=0;iModel<numberModels;iModel++) {
int numberRows2=solvers[iModel]->getNumRows();
const CoinPackedMatrix * rowCopy = solvers[iModel]->getMatrixByRow();
const int * rowLength = rowCopy->getVectorLengths();
const double * elements = rowCopy->getElements();
const int * column = rowCopy->getIndices();
const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
const double * rowLower = solvers[iModel]->getRowLower();
const double * rowUpper = solvers[iModel]->getRowUpper();
for (int iRow=numberRows;iRow<numberRows2;iRow++) {
OsiRowCut rc;
rc.setLb(rowLower[iRow]);
rc.setUb(rowUpper[iRow]);
CoinBigIndex start = rowStart[iRow];
rc.setRow(rowLength[iRow],column+start,elements+start,false);
if (debugger)
CoinAssert (!debugger->invalidCut(rc));
globalCuts_.addCutIfNotDuplicate(rc);
}
//int cutsAdded=globalCuts_.numberCuts()-numberCuts;
//numberCuts += cutsAdded;
//printf("Model %d gave %d cuts (out of %d possible)\n",
// iModel,cutsAdded,numberRows2-numberRows);
}
// normally replace global cuts
//if (!globalCuts_.())
//globalCuts_=rowCutrowCut.addCuts(globalCuts_);
//rowCut.addCuts(globalCuts_);
int nTightened=0;
assert(feasible);
{
double tolerance=1.0e-5;
const double * lower = solver_->getColLower();
const double * upper = solver_->getColUpper();
for (int i=0;i<numberColumns;i++) {
if (tightBounds[2*i+0]>tightBounds[2*i+1]+1.0e-9) {
feasible=false;
char general[200];
sprintf(general,"Solvers give infeasible bounds on %d %g,%g was %g,%g - search finished\n",
i,tightBounds[2*i+0],tightBounds[2*i+1],lower[i],upper[i]);
messageHandler()->message(CBC_GENERAL,messages())
<< general << CoinMessageEol ;
break;
}
double oldLower=lower[i];
double oldUpper=upper[i];
if (tightBounds[2*i+0]>oldLower+tolerance) {
nTightened++;
solver_->setColLower(i,tightBounds[2*i+0]);
}
if (tightBounds[2*i+1]<oldUpper-tolerance) {
nTightened++;
solver_->setColUpper(i,tightBounds[2*i+1]);
}
}
}
delete [] tightBounds;
tightBounds=NULL;
char printBuffer[200];
sprintf(printBuffer,"%d solvers added %d different cuts out of pool of %d",
numberModels,globalCuts_.sizeRowCuts(),maxCuts);
messageHandler()->message(CBC_GENERAL, messages())
<< printBuffer << CoinMessageEol ;
if (nTightened) {
sprintf(printBuffer,"%d bounds were tightened",
nTightened);
messageHandler()->message(CBC_GENERAL, messages())
<< printBuffer << CoinMessageEol ;
}
delete [] solvers;
}
if (!parentModel_&&(moreSpecialOptions_&67108864) != 0) {
// load cuts from file
FILE * fp = fopen("global.cuts","rb");
if (fp) {
size_t nRead;
int numberColumns=solver_->getNumCols();
int numCols;
nRead = fread(&numCols, sizeof(int), 1, fp);
if (nRead != 1)
throw("Error in fread");
if (numberColumns!=numCols) {
printf("Mismatch on columns %d %d\n",numberColumns,numCols);
fclose(fp);
} else {
// If rootModel just do some
double threshold=-1.0;
if (!multipleRootTries_)
threshold=0.5;
int initialCuts=0;
int initialGlobal = globalCuts_.sizeRowCuts();
double * elements = new double [numberColumns+2];
int * indices = new int [numberColumns];
int numberEntries=1;
while (numberEntries>0) {
nRead = fread(&numberEntries, sizeof(int), 1, fp);
if (nRead != 1)
throw("Error in fread");
double randomNumber=randomNumberGenerator_.randomDouble();
if (numberEntries>0) {
initialCuts++;
nRead = fread(elements, sizeof(double), numberEntries+2, fp);
if (nRead != static_cast<size_t>(numberEntries+2))
throw("Error in fread");
nRead = fread(indices, sizeof(int), numberEntries, fp);
if (nRead != static_cast<size_t>(numberEntries))
throw("Error in fread");
if (randomNumber>threshold) {
OsiRowCut rc;
rc.setLb(elements[numberEntries]);
rc.setUb(elements[numberEntries+1]);
rc.setRow(numberEntries,indices,elements,
false);
rc.setGloballyValidAsInteger(2);
globalCuts_.addCutIfNotDuplicate(rc) ;
}
}
}
fclose(fp);
// fixes
int nTightened=0;
fp = fopen("global.fix","rb");
if (fp) {
nRead = fread(indices, sizeof(int), 2, fp);
if (nRead != 2)
throw("Error in fread");
if (numberColumns!=indices[0]) {
printf("Mismatch on columns %d %d\n",numberColumns,
indices[0]);
} else {
indices[0]=1;
while (indices[0]>=0) {
nRead = fread(indices, sizeof(int), 2, fp);
if (nRead != 2)
throw("Error in fread");
int iColumn=indices[0];
if (iColumn>=0) {
nTightened++;
nRead = fread(elements, sizeof(double), 4, fp);
if (nRead != 4)
throw("Error in fread");
solver_->setColLower(iColumn,elements[0]);
solver_->setColUpper(iColumn,elements[1]);
}
}
}
}
if (fp)
fclose(fp);
char printBuffer[200];
sprintf(printBuffer,"%d cuts read in of which %d were unique, %d bounds tightened",
initialCuts,
globalCuts_.sizeRowCuts()-initialGlobal,nTightened);
messageHandler()->message(CBC_GENERAL, messages())
<< printBuffer << CoinMessageEol ;
delete [] elements;
delete [] indices;
}
}
}
if (feasible)
feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_,
NULL);
if (multipleRootTries_&&
(moreSpecialOptions_&134217728)!=0) {
FILE * fp=NULL;
size_t nRead;
int numberColumns=solver_->getNumCols();
int initialCuts=0;
if ((moreSpecialOptions_&134217728)!=0) {
// append so go down to end
fp = fopen("global.cuts","r+b");
if (fp) {
int numCols;
nRead = fread(&numCols, sizeof(int), 1, fp);
if (nRead != 1)
throw("Error in fread");
if (numberColumns!=numCols) {
printf("Mismatch on columns %d %d\n",numberColumns,numCols);
fclose(fp);
fp=NULL;
}
}
}
double * elements = new double [numberColumns+2];
int * indices = new int [numberColumns];
if (fp) {
int numberEntries=1;
while (numberEntries>0) {
fpos_t position;
fgetpos(fp, &position);
nRead = fread(&numberEntries, sizeof(int), 1, fp);
if (nRead != 1)
throw("Error in fread");
if (numberEntries>0) {
initialCuts++;
nRead = fread(elements, sizeof(double), numberEntries+2, fp);
if (nRead != static_cast<size_t>(numberEntries+2))
throw("Error in fread");
nRead = fread(indices, sizeof(int), numberEntries, fp);
if (nRead != static_cast<size_t>(numberEntries))
throw("Error in fread");
} else {
// end
fsetpos(fp, &position);
}
}
} else {
fp = fopen("global.cuts","wb");
size_t nWrite;
nWrite=fwrite(&numberColumns,sizeof(int),1,fp);
if (nWrite != 1)
throw("Error in fwrite");
}
size_t nWrite;
// now append binding cuts
int numberC=continuousSolver_->getNumRows();
int numberRows=solver_->getNumRows();
printf("Saving %d cuts (up from %d)\n",
initialCuts+numberRows-numberC,initialCuts);
const double * rowLower = solver_->getRowLower();
const double * rowUpper = solver_->getRowUpper();
// Row copy
CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow());
const double * elementByRow = matrixByRow.getElements();
const int * column = matrixByRow.getIndices();
const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
const int * rowLength = matrixByRow.getVectorLengths();
for (int iRow=numberC;iRow<numberRows;iRow++) {
int n=rowLength[iRow];
assert (n);
CoinBigIndex start=rowStart[iRow];
memcpy(elements,elementByRow+start,n*sizeof(double));
memcpy(indices,column+start,n*sizeof(int));
elements[n]=rowLower[iRow];
elements[n+1]=rowUpper[iRow];
nWrite=fwrite(&n,sizeof(int),1,fp);
if (nWrite != 1)
throw("Error in fwrite");
nWrite=fwrite(elements,sizeof(double),n+2,fp);
if (nWrite != static_cast<size_t>(n+2))
throw("Error in fwrite");
nWrite=fwrite(indices,sizeof(int),n,fp);
if (nWrite != static_cast<size_t>(n))
throw("Error in fwrite");
}
// eof marker
int eofMarker=-1;
nWrite=fwrite(&eofMarker,sizeof(int),1,fp);
if (nWrite != 1)
throw("Error in fwrite");
fclose(fp);
// do tighter bounds (? later extra to original columns)
int nTightened=0;
const double * lower = solver_->getColLower();
const double * upper = solver_->getColUpper();
const double * originalLower = continuousSolver_->getColLower();
const double * originalUpper = continuousSolver_->getColUpper();
double tolerance=1.0e-5;
for (int i=0;i<numberColumns;i++) {
if (lower[i]>originalLower[i]+tolerance) {
nTightened++;
}
if (upper[i]<originalUpper[i]-tolerance) {
nTightened++;
}
}
if (nTightened) {
fp = fopen("global.fix","wb");
size_t nWrite;
indices[0]=numberColumns;
if (originalColumns_)
indices[1]=COIN_INT_MAX;
else
indices[1]=-1;
nWrite=fwrite(indices,sizeof(int),2,fp);
if (nWrite != 2)
throw("Error in fwrite");
for (int i=0;i<numberColumns;i++) {
int nTightened=0;
if (lower[i]>originalLower[i]+tolerance) {
nTightened++;
}
if (upper[i]<originalUpper[i]-tolerance) {
nTightened++;
}
if (nTightened) {
indices[0]=i;
if (originalColumns_)
indices[1]=originalColumns_[i];
elements[0]=lower[i];
elements[1]=upper[i];
elements[2]=originalLower[i];
elements[3]=originalUpper[i];
nWrite=fwrite(indices,sizeof(int),2,fp);
if (nWrite != 2)
throw("Error in fwrite");
nWrite=fwrite(elements,sizeof(double),4,fp);
if (nWrite != 4)
throw("Error in fwrite");
}
}
// eof marker
indices[0]=-1;
nWrite=fwrite(indices,sizeof(int),2,fp);
if (nWrite != 2)
throw("Error in fwrite");
fclose(fp);
}
delete [] elements;
delete [] indices;
}
if ((specialOptions_&524288) != 0 && !parentModel_
&& storedRowCuts_) {
if (feasible) {
/* pick up stuff and try again
add cuts, maybe keep around
do best solution and if so new heuristics
obviously tighten bounds
*/
// A and B probably done on entry
// A) tight bounds on integer variables
const double * lower = solver_->getColLower();
const double * upper = solver_->getColUpper();
const double * tightLower = storedRowCuts_->tightLower();
const double * tightUpper = storedRowCuts_->tightUpper();
int nTightened = 0;
for (int i = 0; i < numberIntegers_; i++) {
int iColumn = integerVariable_[i];
if (tightLower[iColumn] > lower[iColumn]) {
nTightened++;
solver_->setColLower(iColumn, tightLower[iColumn]);
}
if (tightUpper[iColumn] < upper[iColumn]) {
nTightened++;
solver_->setColUpper(iColumn, tightUpper[iColumn]);
}
}
if (nTightened)
COIN_DETAIL_PRINT(printf("%d tightened by alternate cuts\n", nTightened));
if (storedRowCuts_->bestObjective() < bestObjective_) {
// B) best solution
double objValue = storedRowCuts_->bestObjective();
setBestSolution(CBC_SOLUTION, objValue,
storedRowCuts_->bestSolution()) ;
// Do heuristics
// Allow RINS
for (int i = 0; i < numberHeuristics_; i++) {
CbcHeuristicRINS * rins
= dynamic_cast<CbcHeuristicRINS *> (heuristic_[i]);
if (rins) {
rins->setLastNode(-100);
}
}
doHeuristicsAtRoot();
}
#ifdef JJF_ZERO
int nCuts = storedRowCuts_->sizeRowCuts();
// add to global list
for (int i = 0; i < nCuts; i++) {
OsiRowCut newCut(*storedRowCuts_->rowCutPointer(i));
newCut.setGloballyValidAsInteger(2);
newCut.mutableRow().setTestForDuplicateIndex(false);
globalCuts_.insert(newCut) ;
}
#else
addCutGenerator(storedRowCuts_, -99, "Stored from previous run",
true, false, false, -200);
#endif
// Set cuts as active
delete [] addedCuts_ ;
maximumNumberCuts_ = cuts.sizeRowCuts();
if (maximumNumberCuts_) {
addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
} else {
addedCuts_ = NULL;
}
for (int i = 0; i < maximumNumberCuts_; i++)
addedCuts_[i] = new CbcCountRowCut(*cuts.rowCutPtr(i),
NULL, -1, -1, 2);
COIN_DETAIL_PRINT(printf("size %d\n", cuts.sizeRowCuts()));
cuts = OsiCuts();
currentNumberCuts_ = maximumNumberCuts_;
feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_,
NULL);
for (int i = 0; i < maximumNumberCuts_; i++)
delete addedCuts_[i];
}
delete storedRowCuts_;
storedRowCuts_ = NULL;
}
} else {
feasible = false;
}
} else if (solverCharacteristics_->solutionAddsCuts() ||
solverCharacteristics_->alwaysTryCutsAtRootNode()) {
// may generate cuts and turn the solution
//to an infeasible one
feasible = solveWithCuts(cuts, 2,
NULL);
}
}
if (rootModels) {
int numberModels = multipleRootTries_%100;
for (int i=0;i<numberModels;i++)
delete rootModels[i];
delete [] rootModels;
}
// check extra info on feasibility
if (!solverCharacteristics_->mipFeasible())
feasible = false;
// If max nodes==0 - don't do strong branching
if (!getMaximumNodes()) {
if (feasible)
feasible=false;
else
setMaximumNodes(1); //allow to stop on success
}
topOfTree_=NULL;
#ifdef CLP_RESOLVE
if ((moreSpecialOptions_&2097152)!=0&&!parentModel_&&feasible) {
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver)
resolveClp(clpSolver,0);
}
#endif
// make cut generators less aggressive
for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
CglCutGenerator * generator = generator_[iCutGenerator]->generator();
generator->setAggressiveness(generator->getAggressiveness() - 100);
}
currentNumberCuts_ = numberNewCuts_ ;
if (solverCharacteristics_->solutionAddsCuts()) {
// With some heuristics solver needs a resolve here (don't know if this is bug in heuristics)
solver_->resolve();
if(!isProvenOptimal()){
solver_->initialSolve();
}
}
// See if can stop on gap
bestPossibleObjective_ = solver_->getObjValue() * solver_->getObjSense();
if(canStopOnGap()) {
if (bestPossibleObjective_ < getCutoff())
stoppedOnGap_ = true ;
feasible = false;
}
// User event
if (eventHappened_)
feasible = false;
#if defined(COIN_HAS_CLP)&&defined(COIN_HAS_CPX)
/*
This is the notion of using Cbc stuff to get going, then calling cplex to
finish off.
*/
if (feasible && (specialOptions_&16384) != 0 && fastNodeDepth_ == -2 && !parentModel_) {
// Use Cplex to do search!
double time1 = CoinCpuTime();
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
OsiCpxSolverInterface cpxSolver;
double direction = clpSolver->getObjSense();
cpxSolver.setObjSense(direction);
// load up cplex
const CoinPackedMatrix * matrix = continuousSolver_->getMatrixByCol();
const double * rowLower = continuousSolver_->getRowLower();
const double * rowUpper = continuousSolver_->getRowUpper();
const double * columnLower = continuousSolver_->getColLower();
const double * columnUpper = continuousSolver_->getColUpper();
const double * objective = continuousSolver_->getObjCoefficients();
cpxSolver.loadProblem(*matrix, columnLower, columnUpper,
objective, rowLower, rowUpper);
double * setSol = new double [numberIntegers_];
int * setVar = new int [numberIntegers_];
// cplex doesn't know about objective offset
double offset = clpSolver->getModelPtr()->objectiveOffset();
for (int i = 0; i < numberIntegers_; i++) {
int iColumn = integerVariable_[i];
cpxSolver.setInteger(iColumn);
if (bestSolution_) {
setSol[i] = bestSolution_[iColumn];
setVar[i] = iColumn;
}
}
CPXENVptr env = cpxSolver.getEnvironmentPtr();
CPXLPptr lpPtr = cpxSolver.getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
cpxSolver.switchToMIP();
if (bestSolution_) {
CPXcopymipstart(env, lpPtr, numberIntegers_, setVar, setSol);
}
if (clpSolver->getNumRows() > continuousSolver_->getNumRows() && false) {
// add cuts
const CoinPackedMatrix * matrix = clpSolver->getMatrixByRow();
const double * rhs = clpSolver->getRightHandSide();
const char * rowSense = clpSolver->getRowSense();
const double * elementByRow = matrix->getElements();
const int * column = matrix->getIndices();
const CoinBigIndex * rowStart = matrix->getVectorStarts();
const int * rowLength = matrix->getVectorLengths();
int nStart = continuousSolver_->getNumRows();
int nRows = clpSolver->getNumRows();
int size = rowStart[nRows-1] + rowLength[nRows-1] -
rowStart[nStart];
int nAdd = 0;
double * rmatval = new double [size];
int * rmatind = new int [size];
int * rmatbeg = new int [nRows-nStart+1];
size = 0;
rmatbeg[0] = 0;
for (int i = nStart; i < nRows; i++) {
for (int k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) {
rmatind[size] = column[k];
rmatval[size++] = elementByRow[k];
}
nAdd++;
rmatbeg[nAdd] = size;
}
CPXaddlazyconstraints(env, lpPtr, nAdd, size,
rhs, rowSense, rmatbeg,
rmatind, rmatval, NULL);
CPXsetintparam( env, CPX_PARAM_REDUCE,
// CPX_PREREDUCE_NOPRIMALORDUAL (0)
CPX_PREREDUCE_PRIMALONLY);
}
if (getCutoff() < 1.0e50) {
double useCutoff = getCutoff() + offset;
if (bestObjective_ < 1.0e50)
useCutoff = bestObjective_ + offset + 1.0e-7;
cpxSolver.setDblParam(OsiDualObjectiveLimit, useCutoff*
direction);
if ( direction > 0.0 )
CPXsetdblparam( env, CPX_PARAM_CUTUP, useCutoff ) ; // min
else
CPXsetdblparam( env, CPX_PARAM_CUTLO, useCutoff ) ; // max
}
CPXsetdblparam(env, CPX_PARAM_EPGAP, dblParam_[CbcAllowableFractionGap]);
delete [] setSol;
delete [] setVar;
char printBuffer[200];
if (offset) {
sprintf(printBuffer, "Add %g to all Cplex messages for true objective",
-offset);
messageHandler()->message(CBC_GENERAL, messages())
<< printBuffer << CoinMessageEol ;
cpxSolver.setDblParam(OsiObjOffset, offset);
}
cpxSolver.branchAndBound();
double timeTaken = CoinCpuTime() - time1;
sprintf(printBuffer, "Cplex took %g seconds",
timeTaken);
messageHandler()->message(CBC_GENERAL, messages())
<< printBuffer << CoinMessageEol ;
numberExtraNodes_ = CPXgetnodecnt(env, lpPtr);
numberExtraIterations_ = CPXgetmipitcnt(env, lpPtr);
double value = cpxSolver.getObjValue() * direction;
if (cpxSolver.isProvenOptimal() && value <= getCutoff()) {
feasible = true;
clpSolver->setWarmStart(NULL);
// try and do solution
double * newSolution =
CoinCopyOfArray(cpxSolver.getColSolution(),
getNumCols());
setBestSolution(CBC_STRONGSOL, value, newSolution) ;
delete [] newSolution;
}
feasible = false;
}
#endif
if (!parentModel_&&(moreSpecialOptions_&268435456) != 0) {
// try idiotic idea
CbcObject * obj = new CbcIdiotBranch(this);
obj->setPriority(1); // temp
addObjects(1, &obj);
delete obj;
}
/*
A hook to use clp to quickly explore some part of the tree.
*/
if (fastNodeDepth_ == 1000 &&/*!parentModel_*/(specialOptions_&2048) == 0) {
fastNodeDepth_ = -1;
CbcObject * obj =
new CbcFollowOn(this);
obj->setPriority(1);
addObjects(1, &obj);
delete obj;
}
int saveNumberSolves = numberSolves_;
int saveNumberIterations = numberIterations_;
if ((fastNodeDepth_ >= 0||(moreSpecialOptions_&33554432)!=0)
&&/*!parentModel_*/(specialOptions_&2048) == 0) {
// add in a general depth object doClp
int type = (fastNodeDepth_ <= 100) ? fastNodeDepth_ : -(fastNodeDepth_ - 100);
if ((moreSpecialOptions_&33554432)!=0)
type=12;
else
fastNodeDepth_ += 1000000; // mark as done
CbcObject * obj =
new CbcGeneralDepth(this, type);
addObjects(1, &obj);
delete obj;
// fake number of objects
numberObjects_--;
if (parallelMode() < -1) {
// But make sure position is correct
OsiObject * obj2 = object_[numberObjects_];
obj = dynamic_cast<CbcObject *> (obj2);
assert (obj);
obj->setPosition(numberObjects_);
}
}
#ifdef COIN_HAS_CLP
#ifdef NO_CRUNCH
if (true) {
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver && !parentModel_) {
ClpSimplex * clpSimplex = clpSolver->getModelPtr();
clpSimplex->setSpecialOptions(clpSimplex->specialOptions() | 131072);
//clpSimplex->startPermanentArrays();
clpSimplex->setPersistenceFlag(2);
}
}
#endif
#endif
// Save copy of solver
OsiSolverInterface * saveSolver = NULL;
if (!parentModel_ && (specialOptions_&(512 + 32768)) != 0)
saveSolver = solver_->clone();
double checkCutoffForRestart = 1.0e100;
saveModel(saveSolver, &checkCutoffForRestart, &feasible);
if ((specialOptions_&262144) != 0 && !parentModel_) {
// Save stuff and return!
storedRowCuts_->saveStuff(bestObjective_, bestSolution_,
solver_->getColLower(),
solver_->getColUpper());
delete [] lowerBefore;
delete [] upperBefore;
delete saveSolver;
if (flipObjective)
flipModel();
return;
}
/*
We've taken the continuous relaxation as far as we can. Time to branch.
The first order of business is to actually create a node. chooseBranch
currently uses strong branching to evaluate branch object candidates,
unless forced back to simple branching. If chooseBranch concludes that a
branching candidate is monotone (anyAction == -1) or infeasible (anyAction
== -2) when forced to integer values, it returns here immediately.
Monotone variables trigger a call to resolve(). If the problem remains
feasible, try again to choose a branching variable. At the end of the loop,
resolved == true indicates that some variables were fixed.
Loss of feasibility will result in the deletion of newNode.
*/
bool resolved = false ;
CbcNode *newNode = NULL ;
numberFixedAtRoot_ = 0;
numberFixedNow_ = 0;
if (!parentModel_&&(moreSpecialOptions2_&2)!=0) {
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
if (getCutoff()>1.0e20) {
printf("Zapping costs\n");
int numberColumns=solver_->getNumCols();
double * zeroCost = new double [numberColumns];
// could make small random
memset(zeroCost,0,numberColumns*sizeof(double));
solver_->setObjective(zeroCost);
double objValue = solver_->getObjValue();
solver_->setDblParam(OsiObjOffset,-objValue);
clpSolver->getModelPtr()->setObjectiveValue(objValue);
delete [] zeroCost;
} else {
moreSpecialOptions2_ &= ~2;
}
} else {
#endif
moreSpecialOptions2_ &= ~2;
#ifdef COIN_HAS_CLP
}
#endif
}
int numberIterationsAtContinuous = numberIterations_;
//solverCharacteristics_->setSolver(solver_);
if (feasible) {
// mark all cuts as globally valid
int numberCuts=cuts.sizeRowCuts();
resizeWhichGenerator(0,numberCuts);
for (int i=0;i<numberCuts;i++) {
cuts.rowCutPtr(i)->setGloballyValid();
whichGenerator_[i]=20000+(whichGenerator_[i]%10000);
}
#define HOTSTART -1
#if HOTSTART<0
if (bestSolution_ && !parentModel_ && !hotstartSolution_ &&
(moreSpecialOptions_&1024) != 0) {
// Set priorities so only branch on ones we need to
// use djs and see if only few branches needed
#ifndef NDEBUG
double integerTolerance = getIntegerTolerance() ;
#endif
bool possible = true;
const double * saveLower = continuousSolver_->getColLower();
const double * saveUpper = continuousSolver_->getColUpper();
for (int i = 0; i < numberObjects_; i++) {
const CbcSimpleInteger * thisOne = dynamic_cast <const CbcSimpleInteger *> (object_[i]);
if (thisOne) {
int iColumn = thisOne->columnNumber();
if (saveUpper[iColumn] > saveLower[iColumn] + 1.5) {
possible = false;
break;
}
} else {
possible = false;
break;
}
}
if (possible) {
OsiSolverInterface * solver = continuousSolver_->clone();
int numberColumns = solver->getNumCols();
for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
double value = bestSolution_[iColumn] ;
value = CoinMax(value, saveLower[iColumn]) ;
value = CoinMin(value, saveUpper[iColumn]) ;
value = floor(value + 0.5);
if (solver->isInteger(iColumn)) {
solver->setColLower(iColumn, value);
solver->setColUpper(iColumn, value);
}
}
solver->setHintParam(OsiDoDualInResolve, false, OsiHintTry);
// objlim and all slack
double direction = solver->getObjSense();
solver->setDblParam(OsiDualObjectiveLimit, 1.0e50*direction);
CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *> (solver->getEmptyWarmStart());
solver->setWarmStart(basis);
delete basis;
bool changed = true;
hotstartPriorities_ = new int [numberColumns];
for (int iColumn = 0; iColumn < numberColumns; iColumn++)
hotstartPriorities_[iColumn] = 1;
while (changed) {
changed = false;
solver->resolve();
if (!solver->isProvenOptimal()) {
possible = false;
break;
}
const double * dj = solver->getReducedCost();
const double * colLower = solver->getColLower();
const double * colUpper = solver->getColUpper();
const double * solution = solver->getColSolution();
int nAtLbNatural = 0;
int nAtUbNatural = 0;
int nZeroDj = 0;
int nForced = 0;
for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
double value = solution[iColumn] ;
value = CoinMax(value, saveLower[iColumn]) ;
value = CoinMin(value, saveUpper[iColumn]) ;
if (solver->isInteger(iColumn)) {
assert(fabs(value - solution[iColumn]) <= integerTolerance) ;
if (hotstartPriorities_[iColumn] == 1) {
if (dj[iColumn] < -1.0e-6) {
// negative dj
if (saveUpper[iColumn] == colUpper[iColumn]) {
nAtUbNatural++;
hotstartPriorities_[iColumn] = 2;
solver->setColLower(iColumn, saveLower[iColumn]);
solver->setColUpper(iColumn, saveUpper[iColumn]);
} else {
nForced++;
}
} else if (dj[iColumn] > 1.0e-6) {
// positive dj
if (saveLower[iColumn] == colLower[iColumn]) {
nAtLbNatural++;
hotstartPriorities_[iColumn] = 2;
solver->setColLower(iColumn, saveLower[iColumn]);
solver->setColUpper(iColumn, saveUpper[iColumn]);
} else {
nForced++;
}
} else {
// zero dj
nZeroDj++;
}
}
}
}
#if CBC_USEFUL_PRINTING>1
printf("%d forced, %d naturally at lower, %d at upper - %d zero dj\n",
nForced, nAtLbNatural, nAtUbNatural, nZeroDj);
#endif
if (nAtLbNatural || nAtUbNatural) {
changed = true;
} else {
if (nForced + nZeroDj > 5000 ||
(nForced + nZeroDj)*2 > numberIntegers_)
possible = false;
}
}
delete solver;
}
if (possible) {
setHotstartSolution(bestSolution_);
if (!saveCompare) {
// create depth first comparison
saveCompare = nodeCompare_;
// depth first
nodeCompare_ = new CbcCompareDepth();
tree_->setComparison(*nodeCompare_) ;
}
} else {
delete [] hotstartPriorities_;
hotstartPriorities_ = NULL;
}
}
#endif
#if HOTSTART>0
if (hotstartSolution_ && !hotstartPriorities_) {
// Set up hot start
OsiSolverInterface * solver = solver_->clone();
double direction = solver_->getObjSense() ;
int numberColumns = solver->getNumCols();
double * saveLower = CoinCopyOfArray(solver->getColLower(), numberColumns);
double * saveUpper = CoinCopyOfArray(solver->getColUpper(), numberColumns);
// move solution
solver->setColSolution(hotstartSolution_);
// point to useful information
const double * saveSolution = testSolution_;
testSolution_ = solver->getColSolution();
OsiBranchingInformation usefulInfo = usefulInformation();
testSolution_ = saveSolution;
/*
Run through the objects and use feasibleRegion() to set variable bounds
so as to fix the variables specified in the objects at their value in this
solution. Since the object list contains (at least) one object for every
integer variable, this has the effect of fixing all integer variables.
*/
for (int i = 0; i < numberObjects_; i++)
object_[i]->feasibleRegion(solver, &usefulInfo);
solver->resolve();
assert (solver->isProvenOptimal());
double gap = CoinMax((solver->getObjValue() - solver_->getObjValue()) * direction, 0.0) ;
const double * dj = solver->getReducedCost();
const double * colLower = solver->getColLower();
const double * colUpper = solver->getColUpper();
const double * solution = solver->getColSolution();
int nAtLbNatural = 0;
int nAtUbNatural = 0;
int nAtLbNaturalZero = 0;
int nAtUbNaturalZero = 0;
int nAtLbFixed = 0;
int nAtUbFixed = 0;
int nAtOther = 0;
int nAtOtherNatural = 0;
int nNotNeeded = 0;
delete [] hotstartSolution_;
hotstartSolution_ = new double [numberColumns];
delete [] hotstartPriorities_;
hotstartPriorities_ = new int [numberColumns];
int * order = (int *) saveUpper;
int nFix = 0;
double bestRatio = COIN_DBL_MAX;
for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
double value = solution[iColumn] ;
value = CoinMax(value, saveLower[iColumn]) ;
value = CoinMin(value, saveUpper[iColumn]) ;
double sortValue = COIN_DBL_MAX;
if (solver->isInteger(iColumn)) {
assert(fabs(value - solution[iColumn]) <= 1.0e-5) ;
double value2 = floor(value + 0.5);
if (dj[iColumn] < -1.0e-6) {
// negative dj
//assert (value2==colUpper[iColumn]);
if (saveUpper[iColumn] == colUpper[iColumn]) {
nAtUbNatural++;
sortValue = 0.0;
double value = -dj[iColumn];
if (value > gap)
nFix++;
else if (gap < value*bestRatio)
bestRatio = gap / value;
if (saveLower[iColumn] != colLower[iColumn]) {
nNotNeeded++;
sortValue = 1.0e20;
}
} else if (saveLower[iColumn] == colUpper[iColumn]) {
nAtLbFixed++;
sortValue = dj[iColumn];
} else {
nAtOther++;
sortValue = 0.0;
if (saveLower[iColumn] != colLower[iColumn] &&
saveUpper[iColumn] != colUpper[iColumn]) {
nNotNeeded++;
sortValue = 1.0e20;
}
}
} else if (dj[iColumn] > 1.0e-6) {
// positive dj
//assert (value2==colLower[iColumn]);
if (saveLower[iColumn] == colLower[iColumn]) {
nAtLbNatural++;
sortValue = 0.0;
double value = dj[iColumn];
if (value > gap)
nFix++;
else if (gap < value*bestRatio)
bestRatio = gap / value;
if (saveUpper[iColumn] != colUpper[iColumn]) {
nNotNeeded++;
sortValue = 1.0e20;
}
} else if (saveUpper[iColumn] == colLower[iColumn]) {
nAtUbFixed++;
sortValue = -dj[iColumn];
} else {
nAtOther++;
sortValue = 0.0;
if (saveLower[iColumn] != colLower[iColumn] &&
saveUpper[iColumn] != colUpper[iColumn]) {
nNotNeeded++;
sortValue = 1.0e20;
}
}
} else {
// zero dj
if (value2 == saveUpper[iColumn]) {
nAtUbNaturalZero++;
sortValue = 0.0;
if (saveLower[iColumn] != colLower[iColumn]) {
nNotNeeded++;
sortValue = 1.0e20;
}
} else if (value2 == saveLower[iColumn]) {
nAtLbNaturalZero++;
sortValue = 0.0;
} else {
nAtOtherNatural++;
sortValue = 0.0;
if (saveLower[iColumn] != colLower[iColumn] &&
saveUpper[iColumn] != colUpper[iColumn]) {
nNotNeeded++;
sortValue = 1.0e20;
}
}
}
#if HOTSTART==3
sortValue = -fabs(dj[iColumn]);
#endif
}
hotstartSolution_[iColumn] = value ;
saveLower[iColumn] = sortValue;
order[iColumn] = iColumn;
}
COIN_DETAIL_PRINT(printf("** can fix %d columns - best ratio for others is %g on gap of %g\n",
nFix, bestRatio, gap));
int nNeg = 0;
CoinSort_2(saveLower, saveLower + numberColumns, order);
for (int i = 0; i < numberColumns; i++) {
if (saveLower[i] < 0.0) {
nNeg++;
#if HOTSTART==2||HOTSTART==3
// swap sign ?
saveLower[i] = -saveLower[i];
#endif
}
}
CoinSort_2(saveLower, saveLower + nNeg, order);
for (int i = 0; i < numberColumns; i++) {
#if HOTSTART==1
hotstartPriorities_[order[i]] = 100;
#else
hotstartPriorities_[order[i]] = -(i + 1);
#endif
}
COIN_DETAIL_PRINT(printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d %d\n",
nAtLbNatural,
nAtUbNatural,
nAtLbNaturalZero,
nAtUbNaturalZero,
nAtLbFixed,
nAtUbFixed,
nAtOther,
nAtOtherNatural, nNotNeeded, nNeg));
delete [] saveLower;
delete [] saveUpper;
if (!saveCompare) {
// create depth first comparison
saveCompare = nodeCompare_;
// depth first
nodeCompare_ = new CbcCompareDepth();
tree_->setComparison(*nodeCompare_) ;
}
}
#endif
newNode = new CbcNode ;
// Set objective value (not so obvious if NLP etc)
setObjectiveValue(newNode, NULL);
anyAction = -1 ;
// To make depth available we may need a fake node
CbcNode fakeNode;
if (!currentNode_) {
// Not true if sub trees assert (!numberNodes_);
currentNode_ = &fakeNode;
}
phase_ = 3;
// only allow 1000 passes
int numberPassesLeft = 1000;
// This is first crude step
if (numberAnalyzeIterations_ && !parentModel_) {
delete [] analyzeResults_;
//int numberColumns = solver_->getNumCols();
analyzeResults_ = new double [5*numberIntegers_];
numberFixedAtRoot_ = newNode->analyze(this, analyzeResults_);
if (numberFixedAtRoot_ > 0) {
COIN_DETAIL_PRINT(printf("%d fixed by analysis\n", numberFixedAtRoot_));
setPointers(solver_);
numberFixedNow_ = numberFixedAtRoot_;
} else if (numberFixedAtRoot_ < 0) {
COIN_DETAIL_PRINT(printf("analysis found to be infeasible\n"));
anyAction = -2;
delete newNode ;
newNode = NULL ;
feasible = false ;
}
}
OsiSolverBranch * branches = NULL;
if (feasible)
anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts, resolved,
NULL, NULL, NULL, branches);
if (anyAction == -2 || newNode->objectiveValue() >= cutoff) {
if (anyAction != -2) {
// zap parent nodeInfo
#ifdef COIN_DEVELOP
printf("zapping CbcNodeInfo %x\n", newNode->nodeInfo()->parent());
#endif
if (newNode->nodeInfo())
newNode->nodeInfo()->nullParent();
}
delete newNode ;
newNode = NULL ;
feasible = false ;
}
}
if (newNode && probingInfo_) {
int number01 = probingInfo_->numberIntegers();
//const fixEntry * entry = probingInfo_->fixEntries();
const int * toZero = probingInfo_->toZero();
//const int * toOne = probingInfo_->toOne();
//const int * integerVariable = probingInfo_->integerVariable();
if (toZero[number01]) {
CglTreeProbingInfo info(*probingInfo_);
if ((moreSpecialOptions2_&64)!=0&&!parentModel_) {
/*
Marginal idea. Further exploration probably good. Build some extra
cliques from probing info. Not quite worth the effort?
*/
CglProbing generator1;
generator1.setUsingObjective(false);
generator1.setMaxPass(1);
generator1.setMaxPassRoot(1);
generator1.setMaxLook(100);
generator1.setRowCuts(3);
generator1.setMaxElements(300);
generator1.setMaxProbeRoot(solver_->getNumCols());
CoinThreadRandom randomGenerator;
//CglTreeProbingInfo info(solver_);
info.level = 0;
info.formulation_rows = solver_->getNumRows();
info.inTree = false;
info.randomNumberGenerator=&randomGenerator;
info.pass=4;
generator1.setMode(8);
OsiCuts cs;
generator1.generateCutsAndModify(*solver_,cs,&info);
// very clunky
OsiSolverInterface * temp = generator1.cliqueModel(solver_,2);
CglPreProcess dummy;
OsiSolverInterface * newSolver=dummy.cliqueIt(*temp,0.0001);
delete temp;
OsiSolverInterface * fake = NULL;
if (newSolver) {
#if 0
int numberCliques = generator1.numberCliques();
cliqueEntry * entry = generator1.cliqueEntry();
cliqueType * type = new cliqueType [numberCliques];
int * start = new int [numberCliques+1];
start[numberCliques]=2*numberCliques;
int n=0;
for (int i=0;i<numberCliques;i++) {
start[i]=2*i;
setOneFixesInCliqueEntry(entry[2*i],true);
setOneFixesInCliqueEntry(entry[2*i+1],true);
type[i]=0;
}
fake = info.analyze(*solver_, 1,numberCliques,start,
entry,type);
delete [] type;
delete [] entry;
#else
fake = info.analyze(*newSolver, 1,-1);
#endif
delete newSolver;
} else {
fake = info.analyze(*solver_, 1);
}
if (fake) {
//fake->writeMps("fake");
CglFakeClique cliqueGen(fake);
cliqueGen.setStarCliqueReport(false);
cliqueGen.setRowCliqueReport(false);
cliqueGen.setMinViolation(0.1);
addCutGenerator(&cliqueGen, 1, "Fake cliques", true, false, false, -200);
generator_[numberCutGenerators_-1]->setTiming(true);
for (int i = 0; i < numberCutGenerators_; i++) {
CglKnapsackCover * cutGen =
dynamic_cast<CglKnapsackCover *>(generator_[i]->generator());
if (cutGen) {
cutGen->createCliques(*fake,2,200,false);
}
}
}
}
if (probingInfo_->packDown()) {
#if CBC_USEFUL_PRINTING>1
printf("%d implications on %d 0-1\n", toZero[number01], number01);
#endif
// Create a cut generator that remembers implications discovered at root.
CglImplication implication(probingInfo_);
addCutGenerator(&implication, 1, "ImplicationCuts", true, false, false, -200);
generator_[numberCutGenerators_-1]->setGlobalCuts(true);
generator_[numberCutGenerators_-1]->setTiming(true);
} else {
delete probingInfo_;
probingInfo_ = NULL;
}
} else {
delete probingInfo_;
probingInfo_ = NULL;
}
}
/*
At this point, the root subproblem is infeasible or fathomed by bound
(newNode == NULL), or we're live with an objective value that satisfies the
current objective cutoff.
*/
assert (!newNode || newNode->objectiveValue() <= cutoff) ;
// Save address of root node as we don't want to delete it
/*
The common case is that the lp relaxation is feasible but doesn't satisfy
integrality (i.e., newNode->branchingObject(), indicating we've been able to
select a branching variable). Remove any cuts that have gone slack due to
forcing monotone variables. Then tack on an CbcFullNodeInfo object and full
basis (via createInfo()) and stash the new cuts in the nodeInfo (via
addCuts()). If, by some miracle, we have an integral solution at the root
(newNode->branchingObject() is NULL), takeOffCuts() will ensure that the solver holds
a valid solution for use by setBestSolution().
*/
CoinWarmStartBasis *lastws = NULL ;
if (feasible && newNode->branchingObject()) {
if (resolved) {
takeOffCuts(cuts, false, NULL) ;
# ifdef CHECK_CUT_COUNTS
{ printf("Number of rows after chooseBranch fix (root)"
"(active only) %d\n",
numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_) ;
const CoinWarmStartBasis* debugws =
dynamic_cast <const CoinWarmStartBasis*>(solver_->getWarmStart()) ;
debugws->print() ;
delete debugws ;
}
# endif
}
//newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ;
//newNode->nodeInfo()->addCuts(cuts,
// newNode->numberBranches(),whichGenerator_) ;
if (lastws) delete lastws ;
lastws = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
}
/*
Continuous data to be used later
*/
continuousObjective_ = solver_->getObjValue() * solver_->getObjSense();
continuousInfeasibilities_ = 0 ;
if (newNode) {
continuousObjective_ = newNode->objectiveValue() ;
delete [] continuousSolution_;
continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
numberColumns);
continuousInfeasibilities_ = newNode->numberUnsatisfied() ;
}
/*
Bound may have changed so reset in objects
*/
{
int i ;
for (i = 0; i < numberObjects_; i++)
object_[i]->resetBounds(solver_) ;
}
/*
Feasible? Then we should have either a live node prepped for future
expansion (indicated by variable() >= 0), or (miracle of miracles) an
integral solution at the root node.
initializeInfo sets the reference counts in the nodeInfo object. Since
this node is still live, push it onto the heap that holds the live set.
*/
if (newNode) {
if (newNode->branchingObject()) {
newNode->initializeInfo() ;
tree_->push(newNode) ;
// save pointer to root node - so can pick up bounds
if (!topOfTree_)
topOfTree_ = dynamic_cast<CbcFullNodeInfo *>(newNode->nodeInfo()) ;
if (statistics_) {
if (numberNodes2_ == maximumStatistics_) {
maximumStatistics_ = 2 * maximumStatistics_;
CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
memset(temp, 0, maximumStatistics_*sizeof(CbcStatistics *));
memcpy(temp, statistics_, numberNodes2_*sizeof(CbcStatistics *));
delete [] statistics_;
statistics_ = temp;
}
assert (!statistics_[numberNodes2_]);
statistics_[numberNodes2_] = new CbcStatistics(newNode, this);
}
numberNodes2_++;
# ifdef CHECK_NODE
printf("Node %x on tree\n", newNode) ;
# endif
} else {
// continuous is integer
double objectiveValue = newNode->objectiveValue();
setBestSolution(CBC_SOLUTION, objectiveValue,
solver_->getColSolution()) ;
if (eventHandler) {
// we are stopping anyway so no need to test return code
std::cerr << " event(solution) " << __FILE__ << ":" << __LINE__ << " " << std::flush; eventHandler->event(CbcEventHandler::solution);
}
delete newNode ;
newNode = NULL ;
}
}
if (printFrequency_ <= 0) {
printFrequency_ = 1000 ;
if (getNumCols() > 2000)
printFrequency_ = 100 ;
}
/*
It is possible that strong branching fixes one variable and then the code goes round
again and again. This can take too long. So we need to warn user - just once.
*/
numberLongStrong_ = 0;
CbcNode * createdNode = NULL;
#ifdef CBC_THREAD
if ((specialOptions_&2048) != 0)
numberThreads_ = 0;
if (numberThreads_ ) {
nodeCompare_->sayThreaded(); // need to use addresses
master_ = new CbcBaseModel(*this,
(parallelMode() < -1) ? 1 : 0);
masterThread_ = master_->masterThread();
}
#endif
#ifdef COIN_HAS_CLP
{
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver && !parentModel_) {
clpSolver->computeLargestAway();
}
}
#endif
/*
At last, the actual branch-and-cut search loop, which will iterate until
the live set is empty or we hit some limit (integrality gap, time, node
count, etc.). The overall flow is to rebuild a subproblem, reoptimise using
solveWithCuts(), choose a branching pattern with chooseBranch(), and finally
add the node to the live set.
The first action is to winnow the live set to remove nodes which are worse
than the current objective cutoff.
*/
if (solver_->getRowCutDebuggerAlways()) {
OsiRowCutDebugger * debuggerX = const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
if (!debugger) {
// infeasible!!
printf("before search\n");
const double * lower = solver_->getColLower();
const double * upper = solver_->getColUpper();
const double * solution = debuggerX->optimalSolution();
int numberColumns = solver_->getNumCols();
for (int i = 0; i < numberColumns; i++) {
if (solver_->isInteger(i)) {
if (solution[i] < lower[i] - 1.0e-6 || solution[i] > upper[i] + 1.0e-6)
printf("**** ");
printf("%d %g <= %g <= %g\n",
i, lower[i], solution[i], upper[i]);
}
}
//abort();
}
}
{
// may be able to change cutoff now
double cutoff = getCutoff();
double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
if (cutoff > bestObjective_ - increment) {
cutoff = bestObjective_ - increment ;
setCutoff(cutoff) ;
}
}
#ifdef CBC_THREAD
bool goneParallel = false;
#endif
#define MAX_DEL_NODE 1
CbcNode * delNode[MAX_DEL_NODE+1];
int nDeleteNode = 0;
// For Printing etc when parallel
int lastEvery1000 = 0;
int lastPrintEvery = 0;
int numberConsecutiveInfeasible = 0;
#define PERTURB_IN_FATHOM
#ifdef PERTURB_IN_FATHOM
// allow in fathom
if ((moreSpecialOptions_& 262144) != 0)
specialOptions_ |= 131072;
#endif
while (true) {
lockThread();
#ifdef COIN_HAS_CLP
// See if we want dantzig row choice
goToDantzig(100, savePivotMethod);
#endif
if (tree_->empty()) {
#ifdef CBC_THREAD
if (parallelMode() > 0 && master_) {
int anyLeft = master_->waitForThreadsInTree(0);
if (!anyLeft) {
master_->stopThreads(-1);
break;
}
} else {
break;
}
#else
break;
#endif
} else {
unlockThread();
}
// If done 50/100 nodes see if worth trying reduction
if (numberNodes_ >= nextCheckRestart) {
if (nextCheckRestart<100)
nextCheckRestart=100;
else
nextCheckRestart=COIN_INT_MAX;
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver && ((specialOptions_&131072) == 0) && true) {
ClpSimplex * simplex = clpSolver->getModelPtr();
int perturbation = simplex->perturbation();
#if CBC_USEFUL_PRINTING>1
printf("Testing its n,s %d %d solves n,s %d %d - pert %d\n",
numberIterations_, saveNumberIterations,
numberSolves_, saveNumberSolves, perturbation);
#endif
if (perturbation == 50 && (numberIterations_ - saveNumberIterations) <
8*(numberSolves_ - saveNumberSolves)) {
// switch off perturbation
simplex->setPerturbation(100);
#if CBC_USEFUL_PRINTING>1
printf("Perturbation switched off\n");
#endif
}
}
#endif
/*
Decide if we want to do a restart.
*/
if (saveSolver && (specialOptions_&(512 + 32768)) != 0) {
bool tryNewSearch = solverCharacteristics_->reducedCostsAccurate() &&
(getCutoff() < 1.0e20 && getCutoff() < checkCutoffForRestart);
int numberColumns = getNumCols();
if (tryNewSearch) {
// adding increment back allows current best - tiny bit weaker
checkCutoffForRestart = getCutoff() + getCutoffIncrement() ;
#if CBC_USEFUL_PRINTING>1
printf("after %d nodes, cutoff %g - looking\n",
numberNodes_, getCutoff());
#endif
saveSolver->resolve();
double direction = saveSolver->getObjSense() ;
double gap = checkCutoffForRestart - saveSolver->getObjValue() * direction ;
double tolerance;
saveSolver->getDblParam(OsiDualTolerance, tolerance) ;
if (gap <= 0.0)
gap = tolerance;
gap += 100.0 * tolerance;
double integerTolerance = getDblParam(CbcIntegerTolerance) ;
const double *lower = saveSolver->getColLower() ;
const double *upper = saveSolver->getColUpper() ;
const double *solution = saveSolver->getColSolution() ;
const double *reducedCost = saveSolver->getReducedCost() ;
int numberFixed = 0 ;
int numberFixed2 = 0;
#ifdef COIN_DEVELOP
printf("gap %g\n", gap);
#endif
for (int i = 0 ; i < numberIntegers_ ; i++) {
int iColumn = integerVariable_[i] ;
double djValue = direction * reducedCost[iColumn] ;
if (upper[iColumn] - lower[iColumn] > integerTolerance) {
if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) {
//printf("%d to lb on dj of %g - bounds %g %g\n",
// iColumn,djValue,lower[iColumn],upper[iColumn]);
saveSolver->setColUpper(iColumn, lower[iColumn]) ;
numberFixed++ ;
} else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) {
//printf("%d to ub on dj of %g - bounds %g %g\n",
// iColumn,djValue,lower[iColumn],upper[iColumn]);
saveSolver->setColLower(iColumn, upper[iColumn]) ;
numberFixed++ ;
}
} else {
//printf("%d has dj of %g - already fixed to %g\n",
// iColumn,djValue,lower[iColumn]);
numberFixed2++;
}
}
#ifdef COIN_DEVELOP
if ((specialOptions_&1) != 0) {
const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger() ;
if (debugger) {
printf("Contains optimal\n") ;
OsiSolverInterface * temp = saveSolver->clone();
const double * solution = debugger->optimalSolution();
const double *lower = temp->getColLower() ;
const double *upper = temp->getColUpper() ;
int n = temp->getNumCols();
for (int i = 0; i < n; i++) {
if (temp->isInteger(i)) {
double value = floor(solution[i] + 0.5);
assert (value >= lower[i] && value <= upper[i]);
temp->setColLower(i, value);
temp->setColUpper(i, value);
}
}
temp->writeMps("reduced_fix");
delete temp;
saveSolver->writeMps("reduced");
} else {
abort();
}
}
printf("Restart could fix %d integers (%d already fixed)\n",
numberFixed + numberFixed2, numberFixed2);
#endif
numberFixed += numberFixed2;
if (numberFixed*10 < numberColumns && numberFixed*4 < numberIntegers_)
tryNewSearch = false;
}
#ifdef CONFLICT_CUTS
// temporary
if ((moreSpecialOptions_&4194304)!=0)
tryNewSearch=false;
#endif
if (tryNewSearch) {
// back to solver without cuts?
OsiSolverInterface * solver2 = saveSolver->clone();
const double *lower = saveSolver->getColLower() ;
const double *upper = saveSolver->getColUpper() ;
for (int i = 0 ; i < numberIntegers_ ; i++) {
int iColumn = integerVariable_[i] ;
solver2->setColLower(iColumn, lower[iColumn]);
solver2->setColUpper(iColumn, upper[iColumn]);
}
// swap
delete saveSolver;
saveSolver = solver2;
double * newSolution = new double[numberColumns];
double objectiveValue = checkCutoffForRestart;
// Save the best solution so far.
CbcSerendipity heuristic(*this);
if (bestSolution_)
heuristic.setInputSolution(bestSolution_, bestObjective_);
// Magic number
heuristic.setFractionSmall(0.8);
// `pumpTune' to stand-alone solver for explanations.
heuristic.setFeasibilityPumpOptions(1008013);
// Use numberNodes to say how many are original rows
heuristic.setNumberNodes(continuousSolver_->getNumRows());
#ifdef COIN_DEVELOP
if (continuousSolver_->getNumRows() <
solver_->getNumRows())
printf("%d rows added ZZZZZ\n",
solver_->getNumRows() - continuousSolver_->getNumRows());
#endif
int returnCode = heuristic.smallBranchAndBound(saveSolver,
-1, newSolution,
objectiveValue,
checkCutoffForRestart, "Reduce");
if (returnCode < 0) {
#ifdef COIN_DEVELOP
printf("Restart - not small enough to do search after fixing\n");
#endif
delete [] newSolution;
} else {
// 1 for sol'n, 2 for finished, 3 for both
if ((returnCode&1) != 0) {
// increment number of solutions so other heuristics can test
numberSolutions_++;
numberHeuristicSolutions_++;
lastHeuristic_ = NULL;
setBestSolution(CBC_ROUNDING, objectiveValue, newSolution) ;
}
delete [] newSolution;
#ifdef CBC_THREAD
if (master_) {
lockThread();
if (parallelMode() > 0) {
while (master_->waitForThreadsInTree(0)) {
lockThread();
double dummyBest;
tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
//unlockThread();
}
} else {
double dummyBest;
tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
}
master_->waitForThreadsInTree(2);
delete master_;
master_ = NULL;
masterThread_ = NULL;
}
#endif
if (tree_->size()) {
double dummyBest;
tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
}
break;
}
}
delete saveSolver;
saveSolver = NULL;
}
}
/*
Check for abort on limits: node count, solution count, time, integrality gap.
*/
if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
numberSolutions_ < intParam_[CbcMaxNumSol] &&
!maximumSecondsReached() &&
!stoppedOnGap_ && !eventHappened_ && (maximumNumberIterations_ < 0 ||
numberIterations_ < maximumNumberIterations_))) {
// out of loop
break;
}
#ifdef BONMIN
assert(!solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->mipFeasible());
#endif
// Sets percentage of time when we try diving. Diving requires a bit of heap reorganisation, because
// we need to replace the comparison function to dive, and that requires reordering to retain the
// heap property.
#define DIVE_WHEN 1000
#define DIVE_STOP 2000
int kNode = numberNodes_ % 4000;
if (numberNodes_<100000 && kNode>DIVE_WHEN && kNode <= DIVE_STOP) {
if (!parallelMode()) {
if (kNode == DIVE_WHEN + 1 || numberConsecutiveInfeasible > 1) {
CbcCompareDefault * compare = dynamic_cast<CbcCompareDefault *>
(nodeCompare_);
// Don't interfere if user has replaced the compare function.
if (compare) {
//printf("Redoing tree\n");
compare->startDive(this);
numberConsecutiveInfeasible = 0;
}
}
}
}
// replace current cutoff?
if (cutoff > getCutoff()) {
double newCutoff = getCutoff();
if (analyzeResults_) {
// see if we could fix any (more)
int n = 0;
double * newLower = analyzeResults_;
double * objLower = newLower + numberIntegers_;
double * newUpper = objLower + numberIntegers_;
double * objUpper = newUpper + numberIntegers_;
for (int i = 0; i < numberIntegers_; i++) {
if (objLower[i] > newCutoff) {
n++;
if (objUpper[i] > newCutoff) {
newCutoff = -COIN_DBL_MAX;
break;
}
// add as global cut
objLower[i]=-COIN_DBL_MAX;
OsiRowCut rc;
rc.setLb(newLower[i]);
rc.setUb(COIN_DBL_MAX);
double one=1.0;
rc.setRow(1,integerVariable_+i,&one,false);
rc.setGloballyValidAsInteger(2);
globalCuts_.addCutIfNotDuplicate(rc) ;
} else if (objUpper[i] > newCutoff) {
n++;
// add as global cut
objUpper[i]=-COIN_DBL_MAX;
OsiRowCut rc;
rc.setLb(-COIN_DBL_MAX);
rc.setUb(newUpper[i]);
double one=1.0;
rc.setRow(1,integerVariable_+i,&one,false);
rc.setGloballyValidAsInteger(2);
globalCuts_.addCutIfNotDuplicate(rc) ;
}
}
if (newCutoff == -COIN_DBL_MAX) {
COIN_DETAIL_PRINT(printf("Root analysis says finished\n"));
} else if (n > numberFixedNow_) {
COIN_DETAIL_PRINT(printf("%d more fixed by analysis - now %d\n", n - numberFixedNow_, n));
numberFixedNow_ = n;
}
}
if (eventHandler) {
std::cerr << " event(solution) " << __FILE__ << ":" << __LINE__ << " " << std::flush; if (!eventHandler->event(CbcEventHandler::solution)) {
eventHappened_ = true; // exit
}
newCutoff = getCutoff();
}
lockThread();
/*
Clean the tree to reflect the new solution, then see if the
node comparison predicate wants to make any changes. If so,
call setComparison for the side effect of rebuilding the heap.
*/
tree_->cleanTree(this,newCutoff,bestPossibleObjective_) ;
if (nodeCompare_->newSolution(this) ||
nodeCompare_->newSolution(this,continuousObjective_,
continuousInfeasibilities_)) {
tree_->setComparison(*nodeCompare_) ;
}
if (tree_->empty()) {
continue;
}
unlockThread();
}
cutoff = getCutoff() ;
/*
Periodic activities: Opportunities to
+ tweak the nodeCompare criteria,
+ check if we've closed the integrality gap enough to quit,
+ print a summary line to let the user know we're working
*/
if (numberNodes_ >= lastEvery1000) {
lockThread();
#ifdef COIN_HAS_CLP
// See if we want dantzig row choice
goToDantzig(1000, savePivotMethod);
#endif
lastEvery1000 = numberNodes_ + 1000;
bool redoTree = nodeCompare_->every1000Nodes(this, numberNodes_) ;
#ifdef CHECK_CUT_SIZE
verifyCutSize (tree_, *this);
#endif
// redo tree if requested
if (redoTree)
tree_->setComparison(*nodeCompare_) ;
unlockThread();
}
// Had hotstart before, now switched off
if (saveCompare && !hotstartSolution_) {
// hotstart switched off
delete nodeCompare_; // off depth first
nodeCompare_ = saveCompare;
saveCompare = NULL;
// redo tree
lockThread();
tree_->setComparison(*nodeCompare_) ;
unlockThread();
}
if (numberNodes_ >= lastPrintEvery) {
lastPrintEvery = numberNodes_ + printFrequency_;
lockThread();
int nNodes = tree_->size() ;
//MODIF PIERRE
bestPossibleObjective_ = tree_->getBestPossibleObjective();
#ifdef CBC_THREAD
if (parallelMode() > 0 && master_) {
// need to adjust for ones not on tree
int numberThreads = master_->numberThreads();
for (int i=0;i<numberThreads;i++) {
CbcThread * child = master_->child(i);
if (child->node()) {
// adjust
double value = child->node()->objectiveValue();
bestPossibleObjective_ = CoinMin(bestPossibleObjective_, value);
}
}
}
#endif
unlockThread();
#if CBC_USEFUL_PRINTING>1
if (getCutoff() < 1.0e20) {
if (fabs(getCutoff() - (bestObjective_ - getCutoffIncrement())) > 1.0e-6 &&
!parentModel_)
printf("model cutoff in status %g, best %g, increment %g\n",
getCutoff(), bestObjective_, getCutoffIncrement());
assert (getCutoff() < bestObjective_ - getCutoffIncrement() +
1.0e-6 + 1.0e-10*fabs(bestObjective_));
}
#endif
if (!intParam_[CbcPrinting]) {
// Parallel may not have any nodes
if (!nNodes)
bestPossibleObjective_ = lastBestPossibleObjective;
else
lastBestPossibleObjective = bestPossibleObjective_;
messageHandler()->message(CBC_STATUS, messages())
<< numberNodes_ << CoinMax(nNodes,1) << bestObjective_ << bestPossibleObjective_
<< getCurrentSeconds()
<< CoinMessageEol ;
} else if (intParam_[CbcPrinting] == 1) {
messageHandler()->message(CBC_STATUS2, messages())
<< numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
<< tree_->lastDepth() << tree_->lastUnsatisfied()
<< tree_->lastObjective() << numberIterations_
<< getCurrentSeconds()
<< CoinMessageEol ;
} else if (!numberExtraIterations_) {
messageHandler()->message(CBC_STATUS2, messages())
<< numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
<< tree_->lastDepth() << tree_->lastUnsatisfied() << numberIterations_
<< getCurrentSeconds()
<< CoinMessageEol ;
} else {
messageHandler()->message(CBC_STATUS3, messages())
<< numberNodes_ << numberFathoms_ << numberExtraNodes_ << nNodes
<< bestObjective_ << bestPossibleObjective_
<< tree_->lastDepth() << tree_->lastUnsatisfied() << numberIterations_ << numberExtraIterations_
<< getCurrentSeconds()
<< CoinMessageEol ;
}
#ifdef COIN_HAS_NTY
if (symmetryInfo_)
symmetryInfo_->statsOrbits(this,1);
#endif
#if PRINT_CONFLICT==1
if (numberConflictCuts>lastNumberConflictCuts) {
double length = lengthConflictCuts/numberConflictCuts;
printf("%d new conflict cuts - total %d - average length %g\n",
numberConflictCuts-lastNumberConflictCuts,
numberConflictCuts,length);
lastNumberConflictCuts = numberConflictCuts;
}
#endif
if (eventHandler && !eventHandler->event(CbcEventHandler::treeStatus)) {
eventHappened_ = true; // exit
}
}
// See if can stop on gap
if(canStopOnGap()) {
stoppedOnGap_ = true ;
}
#ifdef CHECK_NODE_FULL
verifyTreeNodes(tree_, *this) ;
# endif
# ifdef CHECK_CUT_COUNTS
verifyCutCounts(tree_, *this) ;
# endif
/*
Now we come to the meat of the loop. To create the active subproblem, we'll
pop the most promising node in the live set, rebuild the subproblem it
represents, and then execute the current arm of the branch to create the
active subproblem.
*/
CbcNode * node = NULL;
#ifdef CBC_THREAD
if (!parallelMode() || parallelMode() == -1) {
#endif
node = tree_->bestNode(cutoff) ;
// Possible one on tree worse than cutoff
// Weird comparison function can leave ineligible nodes on tree
if (!node || node->objectiveValue() > cutoff)
continue;
// Do main work of solving node here
doOneNode(this, node, createdNode);
#ifdef JJF_ZERO
if (node) {
if (createdNode) {
printf("Node %d depth %d, created %d depth %d\n",
node->nodeNumber(), node->depth(),
createdNode->nodeNumber(), createdNode->depth());
} else {
printf("Node %d depth %d, no created node\n",
node->nodeNumber(), node->depth());
}
} else if (createdNode) {
printf("Node exhausted, created %d depth %d\n",
createdNode->nodeNumber(), createdNode->depth());
} else {
printf("Node exhausted, no created node\n");
numberConsecutiveInfeasible = 2;
}
#endif
//if (createdNode)
//numberConsecutiveInfeasible=0;
//else
//numberConsecutiveInfeasible++;
#ifdef CBC_THREAD
} else if (parallelMode() > 0) {
//lockThread();
//node = tree_->bestNode(cutoff) ;
// Possible one on tree worse than cutoff
if (true || !node || node->objectiveValue() > cutoff) {
assert (master_);
if (master_) {
int anyLeft = master_->waitForThreadsInTree(1);
// may need to go round again
if (anyLeft) {
continue;
} else {
master_->stopThreads(-1);
}
}
}
//unlockThread();
} else {
// Deterministic parallel
if ((tree_->size() < CoinMax(numberThreads_, 8)||
hotstartSolution_) && !goneParallel) {
node = tree_->bestNode(cutoff) ;
// Possible one on tree worse than cutoff
if (!node || node->objectiveValue() > cutoff)
continue;
// Do main work of solving node here
doOneNode(this, node, createdNode);
assert (createdNode);
if (!createdNode->active()) {
delete createdNode;
createdNode = NULL;
} else {
// Say one more pointing to this
node->nodeInfo()->increment() ;
tree_->push(createdNode) ;
}
if (node->active()) {
assert (node->nodeInfo());
if (node->nodeInfo()->numberBranchesLeft()) {
tree_->push(node) ;
} else {
node->setActive(false);
}
} else {
if (node->nodeInfo()) {
if (!node->nodeInfo()->numberBranchesLeft())
node->nodeInfo()->allBranchesGone(); // can clean up
// So will delete underlying stuff
node->setActive(true);
}
delNode[nDeleteNode++] = node;
node = NULL;
}
if (nDeleteNode >= MAX_DEL_NODE) {
for (int i = 0; i < nDeleteNode; i++) {
//printf("trying to del %d %x\n",i,delNode[i]);
delete delNode[i];
//printf("done to del %d %x\n",i,delNode[i]);
}
nDeleteNode = 0;
}
} else {
// Split and solve
master_->deterministicParallel();
goneParallel = true;
}
}
#endif
}
if (nDeleteNode) {
for (int i = 0; i < nDeleteNode; i++) {
delete delNode[i];
}
nDeleteNode = 0;
}
#ifdef CBC_THREAD
if (master_) {
master_->stopThreads(-1);
master_->waitForThreadsInTree(2);
// adjust time to allow for children on some systems
//dblParam_[CbcStartSeconds] -= CoinCpuTimeJustChildren();
}
#endif
/*
End of the non-abort actions. The next block of code is executed if we've
aborted because we hit one of the limits. Clean up by deleting the live set
and break out of the node processing loop. Note that on an abort, node may
have been pushed back onto the tree for further processing, in which case
it'll be deleted in cleanTree. We need to check.
*/
if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
numberSolutions_ < intParam_[CbcMaxNumSol] &&
!maximumSecondsReached() &&
!stoppedOnGap_ &&
!eventHappened_ &&
(maximumNumberIterations_ < 0 || numberIterations_ < maximumNumberIterations_))
) {
if (tree_->size()) {
double dummyBest;
tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
#if 0 // Does not seem to be needed def CBC_THREAD
if (parallelMode() > 0 && master_) {
// see if any dangling nodes
int numberThreads = master_->numberThreads();
for (int i=0;i<numberThreads;i++) {
CbcThread * child = master_->child(i);
//if (child->createdNode())
//printf("CHILD_NODE %p\n",child->createdNode());
delete child->createdNode();
}
}
#endif
}
delete nextRowCut_;
/* order is important here:
* maximumSecondsReached() should be checked before eventHappened_ and
* isNodeLimitReached() should be checked after eventHappened_
* reason is, that at timelimit, eventHappened_ is set to true to make Cbc stop fast
* and if Ctrl+C is hit, then the nodelimit is set to -1 to make Cbc stop
*/
if (stoppedOnGap_) {
messageHandler()->message(CBC_GAP, messages())
<< bestObjective_ - bestPossibleObjective_
<< dblParam_[CbcAllowableGap]
<< dblParam_[CbcAllowableFractionGap]*100.0
<< CoinMessageEol ;
secondaryStatus_ = 2;
status_ = 0 ;
} else if (maximumSecondsReached()) {
handler_->message(CBC_MAXTIME, messages_) << CoinMessageEol ;
secondaryStatus_ = 4;
status_ = 1 ;
} else if (numberSolutions_ >= intParam_[CbcMaxNumSol]) {
handler_->message(CBC_MAXSOLS, messages_) << CoinMessageEol ;
secondaryStatus_ = 6;
status_ = 1 ;
} else if (isNodeLimitReached()) {
handler_->message(CBC_MAXNODES, messages_) << CoinMessageEol ;
secondaryStatus_ = 3;
status_ = 1 ;
} else if (maximumNumberIterations_ >= 0 && numberIterations_ >= maximumNumberIterations_) {
handler_->message(CBC_MAXITERS, messages_) << CoinMessageEol ;
secondaryStatus_ = 8;
status_ = 1 ;
} else {
handler_->message(CBC_EVENT, messages_) << CoinMessageEol ;
secondaryStatus_ = 5;
status_ = 5 ;
}
}
#ifdef CBC_THREAD
if (master_) {
delete master_;
master_ = NULL;
masterThread_ = NULL;
}
#endif
/*
That's it, we've exhausted the search tree, or broken out of the loop because
we hit some limit on evaluation.
We may have got an intelligent tree so give it one more chance
*/
// Tell solver we are not in Branch and Cut
solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo, NULL) ;
tree_->endSearch();
// If we did any sub trees - did we give up on any?
if ( numberStoppedSubTrees_)
status_ = 1;
numberNodes_ += numberExtraNodes_;
numberIterations_ += numberExtraIterations_;
if (eventHandler) {
eventHandler->event(CbcEventHandler::endSearch);
}
if (!status_) {
// Set best possible unless stopped on gap
if (secondaryStatus_ != 2)
bestPossibleObjective_ = bestObjective_;
handler_->message(CBC_END_GOOD, messages_)
<< bestObjective_ << numberIterations_ << numberNodes_ << getCurrentSeconds()
<< CoinMessageEol ;
} else {
handler_->message(CBC_END, messages_)
<< bestObjective_ << bestPossibleObjective_
<< numberIterations_ << numberNodes_ << getCurrentSeconds()
<< CoinMessageEol ;
}
if ((moreSpecialOptions_&4194304)!=0) {
// Conflict cuts
int numberCuts = globalCuts_.sizeRowCuts();
int nConflict=0;
double sizeConflict = 0.0;
for (int i=0;i<numberCuts;i++) {
OsiRowCut2 * cut = globalCuts_.cut(i);
if (cut->whichRow()==1) {
nConflict++;
sizeConflict += cut->row().getNumElements();
}
}
if (nConflict) {
sizeConflict /= nConflict;
char general[200];
sprintf(general, "%d conflict cuts generated - average length %g",
nConflict,sizeConflict);
messageHandler()->message(CBC_GENERAL,
messages())
<< general << CoinMessageEol ;
}
}
if (numberStrongIterations_)
handler_->message(CBC_STRONG_STATS, messages_)
<< strongInfo_[0] << numberStrongIterations_ << strongInfo_[2]
<< strongInfo_[1] << CoinMessageEol ;
if (!numberExtraNodes_)
handler_->message(CBC_OTHER_STATS, messages_)
<< maximumDepthActual_
<< numberDJFixed_ << CoinMessageEol ;
else
handler_->message(CBC_OTHER_STATS2, messages_)
<< maximumDepthActual_
<< numberDJFixed_ << numberFathoms_ << numberExtraNodes_ << numberExtraIterations_
<< CoinMessageEol ;
#ifdef COIN_HAS_NTY
if (symmetryInfo_)
symmetryInfo_->statsOrbits(this,1);
#endif
if (doStatistics == 100) {
for (int i = 0; i < numberObjects_; i++) {
CbcSimpleIntegerDynamicPseudoCost * obj =
dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[i]) ;
if (obj)
obj->print();
}
}
if (statistics_) {
// report in some way
int * lookup = new int[numberObjects_];
int i;
for (i = 0; i < numberObjects_; i++)
lookup[i] = -1;
bool goodIds = false; //true;
for (i = 0; i < numberObjects_; i++) {
int iColumn = object_[i]->columnNumber();
if (iColumn >= 0 && iColumn < numberColumns) {
if (lookup[i] == -1) {
lookup[i] = iColumn;
} else {
goodIds = false;
break;
}
} else {
goodIds = false;
break;
}
}
if (!goodIds) {
delete [] lookup;
lookup = NULL;
}
if (doStatistics >= 3) {
printf(" node parent depth column value obj inf\n");
for ( i = 0; i < numberNodes2_; i++) {
statistics_[i]->print(lookup);
}
}
if (doStatistics > 1) {
// Find last solution
int k;
for (k = numberNodes2_ - 1; k >= 0; k--) {
if (statistics_[k]->endingObjective() != COIN_DBL_MAX &&
!statistics_[k]->endingInfeasibility())
break;
}
if (k >= 0) {
int depth = statistics_[k]->depth();
int * which = new int[depth+1];
for (i = depth; i >= 0; i--) {
which[i] = k;
k = statistics_[k]->parentNode();
}
printf(" node parent depth column value obj inf\n");
for (i = 0; i <= depth; i++) {
statistics_[which[i]]->print(lookup);
}
delete [] which;
}
}
// now summary
int maxDepth = 0;
double averageSolutionDepth = 0.0;
int numberSolutions = 0;
double averageCutoffDepth = 0.0;
double averageSolvedDepth = 0.0;
int numberCutoff = 0;
int numberDown = 0;
int numberFirstDown = 0;
double averageInfDown = 0.0;
double averageObjDown = 0.0;
int numberCutoffDown = 0;
int numberUp = 0;
int numberFirstUp = 0;
double averageInfUp = 0.0;
double averageObjUp = 0.0;
int numberCutoffUp = 0;
double averageNumberIterations1 = 0.0;
double averageValue = 0.0;
for ( i = 0; i < numberNodes2_; i++) {
int depth = statistics_[i]->depth();
int way = statistics_[i]->way();
double value = statistics_[i]->value();
double startingObjective = statistics_[i]->startingObjective();
int startingInfeasibility = statistics_[i]->startingInfeasibility();
double endingObjective = statistics_[i]->endingObjective();
int endingInfeasibility = statistics_[i]->endingInfeasibility();
maxDepth = CoinMax(depth, maxDepth);
// Only for completed
averageNumberIterations1 += statistics_[i]->numberIterations();
averageValue += value;
if (endingObjective != COIN_DBL_MAX && !endingInfeasibility) {
numberSolutions++;
averageSolutionDepth += depth;
}
if (endingObjective == COIN_DBL_MAX) {
numberCutoff++;
averageCutoffDepth += depth;
if (way < 0) {
numberDown++;
numberCutoffDown++;
if (way == -1)
numberFirstDown++;
} else {
numberUp++;
numberCutoffUp++;
if (way == 1)
numberFirstUp++;
}
} else {
averageSolvedDepth += depth;
if (way < 0) {
numberDown++;
averageInfDown += startingInfeasibility - endingInfeasibility;
averageObjDown += endingObjective - startingObjective;
if (way == -1)
numberFirstDown++;
} else {
numberUp++;
averageInfUp += startingInfeasibility - endingInfeasibility;
averageObjUp += endingObjective - startingObjective;
if (way == 1)
numberFirstUp++;
}
}
}
// Now print
if (numberSolutions)
averageSolutionDepth /= static_cast<double> (numberSolutions);
int numberSolved = numberNodes2_ - numberCutoff;
double averageNumberIterations2 = numberIterations_ - averageNumberIterations1
- numberIterationsAtContinuous;
if (numberCutoff) {
averageCutoffDepth /= static_cast<double> (numberCutoff);
averageNumberIterations2 /= static_cast<double> (numberCutoff);
}
if (numberNodes2_)
averageValue /= static_cast<double> (numberNodes2_);
if (numberSolved) {
averageNumberIterations1 /= static_cast<double> (numberSolved);
averageSolvedDepth /= static_cast<double> (numberSolved);
}
printf("%d solution(s) were found (by branching) at an average depth of %g\n",
numberSolutions, averageSolutionDepth);
printf("average value of variable being branched on was %g\n",
averageValue);
printf("%d nodes were cutoff at an average depth of %g with iteration count of %g\n",
numberCutoff, averageCutoffDepth, averageNumberIterations2);
printf("%d nodes were solved at an average depth of %g with iteration count of %g\n",
numberSolved, averageSolvedDepth, averageNumberIterations1);
if (numberDown) {
averageInfDown /= static_cast<double> (numberDown);
averageObjDown /= static_cast<double> (numberDown);
}
printf("Down %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
numberDown, numberFirstDown, numberDown - numberFirstDown, numberCutoffDown,
averageInfDown, averageObjDown);
if (numberUp) {
averageInfUp /= static_cast<double> (numberUp);
averageObjUp /= static_cast<double> (numberUp);
}
printf("Up %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
numberUp, numberFirstUp, numberUp - numberFirstUp, numberCutoffUp,
averageInfUp, averageObjUp);
for ( i = 0; i < numberNodes2_; i++)
delete statistics_[i];
delete [] statistics_;
statistics_ = NULL;
maximumStatistics_ = 0;
delete [] lookup;
}
/*
If we think we have a solution, restore and confirm it with a call to
setBestSolution(). We need to reset the cutoff value so as not to fathom
the solution on bounds. Note that calling setBestSolution( ..., true)
leaves the continuousSolver_ bounds vectors fixed at the solution value.
Running resolve() here is a failsafe --- setBestSolution has already
reoptimised using the continuousSolver_. If for some reason we fail to
prove optimality, run the problem again after instructing the solver to
tell us more.
If all looks good, replace solver_ with continuousSolver_, so that the
outside world will be able to obtain information about the solution using
public methods.
Don't replace if we are trying to save cuts
*/
if (bestSolution_ && (solverCharacteristics_->solverType() < 2 || solverCharacteristics_->solverType() == 4) &&
((specialOptions_&8388608)==0||(specialOptions_&2048)!=0)) {
setCutoff(1.0e50) ; // As best solution should be worse than cutoff
// change cutoff as constraint if wanted
if (cutoffRowNumber_>=0) {
if (solver_->getNumRows()>cutoffRowNumber_)
solver_->setRowUpper(cutoffRowNumber_,1.0e50);
}
// also in continuousSolver_
if (continuousSolver_) {
// Solvers know about direction
double direction = solver_->getObjSense();
continuousSolver_->setDblParam(OsiDualObjectiveLimit, 1.0e50*direction);
}
phase_ = 5;
double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
if ((specialOptions_&4) == 0)
bestObjective_ += 100.0 * increment + 1.0e-3; // only set if we are going to solve
setBestSolution(CBC_END_SOLUTION, bestObjective_, bestSolution_, 1) ;
continuousSolver_->resolve() ;
if (!continuousSolver_->isProvenOptimal()) {
continuousSolver_->messageHandler()->setLogLevel(2) ;
continuousSolver_->initialSolve() ;
}
delete solver_ ;
// above deletes solverCharacteristics_
solverCharacteristics_ = NULL;
solver_ = continuousSolver_ ;
setPointers(solver_);
continuousSolver_ = NULL ;
}
/*
Clean up dangling objects. continuousSolver_ may already be toast.
*/
delete lastws ;
if (saveObjects) {
for (int i = 0; i < numberObjects_; i++)
delete saveObjects[i];
delete [] saveObjects;
}
numberStrong_ = saveNumberStrong;
numberBeforeTrust_ = saveNumberBeforeTrust;
delete [] whichGenerator_ ;
whichGenerator_ = NULL;
delete [] lowerBefore ;
delete [] upperBefore ;
delete [] walkback_ ;
walkback_ = NULL ;
delete [] lastNodeInfo_ ;
lastNodeInfo_ = NULL;
delete [] lastNumberCuts_ ;
lastNumberCuts_ = NULL;
delete [] lastCut_;
lastCut_ = NULL;
delete [] addedCuts_ ;
addedCuts_ = NULL ;
//delete persistentInfo;
// Get rid of characteristics
solverCharacteristics_ = NULL;
if (continuousSolver_) {
delete continuousSolver_ ;
continuousSolver_ = NULL ;
}
/*
Destroy global cuts by replacing with an empty OsiCuts object.
*/
globalCuts_ = CbcRowCuts() ;
delete globalConflictCuts_;
globalConflictCuts_=NULL;
if (!bestSolution_ && (specialOptions_&8388608)==0) {
// make sure lp solver is infeasible
int numberColumns = solver_->getNumCols();
const double * columnLower = solver_->getColLower();
int iColumn;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if (solver_->isInteger(iColumn))
solver_->setColUpper(iColumn, columnLower[iColumn]);
}
solver_->initialSolve();
}
#ifdef COIN_HAS_CLP
{
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
// Possible restore of pivot method
if (savePivotMethod) {
// model may have changed
savePivotMethod->setModel(NULL);
clpSolver->getModelPtr()->setDualRowPivotAlgorithm(*savePivotMethod);
delete savePivotMethod;
}
clpSolver->setLargestAway(-1.0);
}
}
#endif
if ((fastNodeDepth_ >= 1000000 || (moreSpecialOptions_&33554432)!=0)
&& !parentModel_) {
// delete object off end
delete object_[numberObjects_];
if ((moreSpecialOptions_&33554432)==0)
fastNodeDepth_ -= 1000000;
}
delete saveSolver;
// Undo preprocessing performed during BaB.
if (strategy_ && strategy_->preProcessState() > 0) {
// undo preprocessing
CglPreProcess * process = strategy_->process();
assert (process);
int n = originalSolver->getNumCols();
if (bestSolution_) {
delete [] bestSolution_;
bestSolution_ = new double [n];
process->postProcess(*solver_);
}
strategy_->deletePreProcess();
// Solution now back in originalSolver
delete solver_;
solver_ = originalSolver;
if (bestSolution_) {
bestObjective_ = solver_->getObjValue() * solver_->getObjSense();
memcpy(bestSolution_, solver_->getColSolution(), n*sizeof(double));
}
// put back original objects if there were any
if (originalObject) {
int iColumn;
assert (ownObjects_);
for (iColumn = 0; iColumn < numberObjects_; iColumn++)
delete object_[iColumn];
delete [] object_;
numberObjects_ = numberOriginalObjects;
object_ = originalObject;
delete [] integerVariable_;
numberIntegers_ = 0;
for (iColumn = 0; iColumn < n; iColumn++) {
if (solver_->isInteger(iColumn))
numberIntegers_++;
}
integerVariable_ = new int[numberIntegers_];
numberIntegers_ = 0;
for (iColumn = 0; iColumn < n; iColumn++) {
if (solver_->isInteger(iColumn))
integerVariable_[numberIntegers_++] = iColumn;
}
}
}
if (flipObjective)
flipModel();
#ifdef COIN_HAS_CLP
{
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver)
clpSolver->setFakeObjective(reinterpret_cast<double *> (NULL));
}
#endif
moreSpecialOptions_ = saveMoreSpecialOptions;
return ;
}
// Solve the initial LP relaxation
void
CbcModel::initialSolve()
{
assert (solver_);
// Double check optimization directions line up
dblParam_[CbcOptimizationDirection] = solver_->getObjSense();
// Check if bounds are all integral (as may get messed up later)
checkModel();
if (!solverCharacteristics_) {
OsiBabSolver * solverCharacteristics = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
if (solverCharacteristics) {
solverCharacteristics_ = solverCharacteristics;
} else {
// replace in solver
OsiBabSolver defaultC;
solver_->setAuxiliaryInfo(&defaultC);
solverCharacteristics_ = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
}
}
solverCharacteristics_->setSolver(solver_);
solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
solver_->initialSolve();
solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo, NULL) ;
if (!solver_->isProvenOptimal())
solver_->resolve();
// But set up so Jon Lee will be happy
status_ = -1;
secondaryStatus_ = -1;
originalContinuousObjective_ = solver_->getObjValue() * solver_->getObjSense();
bestPossibleObjective_ = originalContinuousObjective_;
if (solver_->isProvenDualInfeasible())
originalContinuousObjective_ = -COIN_DBL_MAX;
delete [] continuousSolution_;
continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
solver_->getNumCols());
setPointers(solver_);
solverCharacteristics_ = NULL;
}
/*! \brief Get an empty basis object
Return an empty CoinWarmStartBasis object with the requested capacity,
appropriate for the current solver. The object is cloned from the object
cached as emptyWarmStart_. If there is no cached object, the routine
queries the solver for a warm start object, empties it, and caches the
result.
*/
CoinWarmStartBasis *CbcModel::getEmptyBasis (int ns, int na) const
{
CoinWarmStartBasis *emptyBasis ;
/*
Acquire an empty basis object, if we don't yet have one.
*/
if (emptyWarmStart_ == 0) {
if (solver_ == 0) {
throw CoinError("Cannot construct basis without solver!",
"getEmptyBasis", "CbcModel") ;
}
emptyBasis =
dynamic_cast<CoinWarmStartBasis *>(solver_->getEmptyWarmStart()) ;
if (emptyBasis == 0) {
throw CoinError(
"Solver does not appear to use a basis-oriented warm start.",
"getEmptyBasis", "CbcModel") ;
}
emptyBasis->setSize(0, 0) ;
emptyWarmStart_ = dynamic_cast<CoinWarmStart *>(emptyBasis) ;
}
/*
Clone the empty basis object, resize it as requested, and return.
*/
emptyBasis = dynamic_cast<CoinWarmStartBasis *>(emptyWarmStart_->clone()) ;
assert(emptyBasis) ;
if (ns != 0 || na != 0) emptyBasis->setSize(ns, na) ;
return (emptyBasis) ;
}
/** Default Constructor
Creates an empty model without an associated solver.
*/
CbcModel::CbcModel()
:
solver_(NULL),
ownership_(0x80000000),
continuousSolver_(NULL),
referenceSolver_(NULL),
defaultHandler_(true),
emptyWarmStart_(NULL),
bestObjective_(COIN_DBL_MAX),
bestPossibleObjective_(COIN_DBL_MAX),
sumChangeObjective1_(0.0),
sumChangeObjective2_(0.0),
bestSolution_(NULL),
savedSolutions_(NULL),
currentSolution_(NULL),
testSolution_(NULL),
globalConflictCuts_(NULL),
minimumDrop_(1.0e-4),
numberSolutions_(0),
numberSavedSolutions_(0),
maximumSavedSolutions_(0),
stateOfSearch_(0),
whenCuts_(-1),
hotstartSolution_(NULL),
hotstartPriorities_(NULL),
numberHeuristicSolutions_(0),
numberNodes_(0),
numberNodes2_(0),
numberIterations_(0),
numberSolves_(0),
status_(-1),
secondaryStatus_(-1),
numberIntegers_(0),
numberRowsAtContinuous_(0),
cutoffRowNumber_(-1),
maximumNumberCuts_(0),
phase_(0),
currentNumberCuts_(0),
maximumDepth_(0),
walkback_(NULL),
lastNodeInfo_(NULL),
lastCut_(NULL),
lastDepth_(0),
lastNumberCuts2_(0),
maximumCuts_(0),
lastNumberCuts_(NULL),
addedCuts_(NULL),
nextRowCut_(NULL),
currentNode_(NULL),
integerVariable_(NULL),
integerInfo_(NULL),
continuousSolution_(NULL),
usedInSolution_(NULL),
specialOptions_(0),
moreSpecialOptions_(0),
moreSpecialOptions2_(0),
topOfTree_(NULL),
subTreeModel_(NULL),
heuristicModel_(NULL),
numberStoppedSubTrees_(0),
presolve_(0),
numberStrong_(5),
numberBeforeTrust_(10),
numberPenalties_(20),
stopNumberIterations_(-1),
penaltyScaleFactor_(3.0),
numberAnalyzeIterations_(0),
analyzeResults_(NULL),
numberInfeasibleNodes_(0),
problemType_(0),
printFrequency_(0),
numberCutGenerators_(0),
generator_(NULL),
virginGenerator_(NULL),
numberHeuristics_(0),
heuristic_(NULL),
lastHeuristic_(NULL),
fastNodeDepth_(-1),
eventHandler_(NULL),
#ifdef COIN_HAS_NTY
symmetryInfo_(NULL),
#endif
numberObjects_(0),
object_(NULL),
ownObjects_(true),
originalColumns_(NULL),
howOftenGlobalScan_(3),
numberGlobalViolations_(0),
numberExtraIterations_(0),
numberExtraNodes_(0),
numberFathoms_(0),
continuousObjective_(COIN_DBL_MAX),
originalContinuousObjective_(COIN_DBL_MAX),
continuousInfeasibilities_(COIN_INT_MAX),
maximumCutPassesAtRoot_(20),
maximumCutPasses_(10),
preferredWay_(0),
currentPassNumber_(0),
maximumWhich_(INITIAL_MAXIMUM_WHICH),
maximumRows_(0),
randomSeed_(-1),
multipleRootTries_(0),
currentDepth_(0),
whichGenerator_(NULL),
maximumStatistics_(0),
statistics_(NULL),
maximumDepthActual_(0),
numberDJFixed_(0.0),
probingInfo_(NULL),
numberFixedAtRoot_(0),
numberFixedNow_(0),
stoppedOnGap_(false),
eventHappened_(false),
numberLongStrong_(0),
numberOldActiveCuts_(0),
numberNewCuts_(0),
searchStrategy_(-1),
strongStrategy_(0),
numberStrongIterations_(0),
resolveAfterTakeOffCuts_(true),
maximumNumberIterations_(-1),
continuousPriority_(COIN_INT_MAX),
numberUpdateItems_(0),
maximumNumberUpdateItems_(0),
updateItems_(NULL),
storedRowCuts_(NULL),
numberThreads_(0),
threadMode_(0),
numberGlobalCutsIn_(0),
master_(NULL),
masterThread_(NULL)
{
memset(intParam_, 0, sizeof(intParam_));
intParam_[CbcMaxNumNode] = 2147483647;
intParam_[CbcMaxNumSol] = 9999999;
memset(dblParam_, 0, sizeof(dblParam_));
dblParam_[CbcIntegerTolerance] = 1e-6;
dblParam_[CbcCutoffIncrement] = 1e-5;
dblParam_[CbcAllowableGap] = 1.0e-10;
dblParam_[CbcMaximumSeconds] = 1.0e100;
dblParam_[CbcCurrentCutoff] = 1.0e100;
dblParam_[CbcOptimizationDirection] = 1.0;
dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
strongInfo_[0] = 0;
strongInfo_[1] = 0;
strongInfo_[2] = 0;
strongInfo_[3] = 0;
strongInfo_[4] = 0;
strongInfo_[5] = 0;
strongInfo_[6] = 0;
solverCharacteristics_ = NULL;
nodeCompare_ = new CbcCompareDefault();;
problemFeasibility_ = new CbcFeasibilityBase();
tree_ = new CbcTree();
branchingMethod_ = NULL;
cutModifier_ = NULL;
strategy_ = NULL;
parentModel_ = NULL;
cbcColLower_ = NULL;
cbcColUpper_ = NULL;
cbcRowLower_ = NULL;
cbcRowUpper_ = NULL;
cbcColSolution_ = NULL;
cbcRowPrice_ = NULL;
cbcReducedCost_ = NULL;
cbcRowActivity_ = NULL;
appData_ = NULL;
handler_ = new CoinMessageHandler();
handler_->setLogLevel(2);
messages_ = CbcMessage();
//eventHandler_ = new CbcEventHandler() ;
}
/** Constructor from solver.
Creates a model complete with a clone of the solver passed as a parameter.
*/
CbcModel::CbcModel(const OsiSolverInterface &rhs)
:
continuousSolver_(NULL),
referenceSolver_(NULL),
defaultHandler_(true),
emptyWarmStart_(NULL),
bestObjective_(COIN_DBL_MAX),
bestPossibleObjective_(COIN_DBL_MAX),
sumChangeObjective1_(0.0),
sumChangeObjective2_(0.0),
globalConflictCuts_(NULL),
minimumDrop_(1.0e-4),
numberSolutions_(0),
numberSavedSolutions_(0),
maximumSavedSolutions_(0),
stateOfSearch_(0),
whenCuts_(-1),
hotstartSolution_(NULL),
hotstartPriorities_(NULL),
numberHeuristicSolutions_(0),
numberNodes_(0),
numberNodes2_(0),
numberIterations_(0),
numberSolves_(0),
status_(-1),
secondaryStatus_(-1),
numberRowsAtContinuous_(0),
cutoffRowNumber_(-1),
maximumNumberCuts_(0),
phase_(0),
currentNumberCuts_(0),
maximumDepth_(0),
walkback_(NULL),
lastNodeInfo_(NULL),
lastCut_(NULL),
lastDepth_(0),
lastNumberCuts2_(0),
maximumCuts_(0),
lastNumberCuts_(NULL),
addedCuts_(NULL),
nextRowCut_(NULL),
currentNode_(NULL),
integerInfo_(NULL),
specialOptions_(0),
moreSpecialOptions_(0),
moreSpecialOptions2_(0),
topOfTree_(NULL),
subTreeModel_(NULL),
heuristicModel_(NULL),
numberStoppedSubTrees_(0),
presolve_(0),
numberStrong_(5),
numberBeforeTrust_(10),
numberPenalties_(20),
stopNumberIterations_(-1),
penaltyScaleFactor_(3.0),
numberAnalyzeIterations_(0),
analyzeResults_(NULL),
numberInfeasibleNodes_(0),
problemType_(0),
printFrequency_(0),
numberCutGenerators_(0),
generator_(NULL),
virginGenerator_(NULL),
numberHeuristics_(0),
heuristic_(NULL),
lastHeuristic_(NULL),
fastNodeDepth_(-1),
eventHandler_(NULL),
#ifdef COIN_HAS_NTY
symmetryInfo_(NULL),
#endif
numberObjects_(0),
object_(NULL),
ownObjects_(true),
originalColumns_(NULL),
howOftenGlobalScan_(3),
numberGlobalViolations_(0),
numberExtraIterations_(0),
numberExtraNodes_(0),
numberFathoms_(0),
continuousObjective_(COIN_DBL_MAX),
originalContinuousObjective_(COIN_DBL_MAX),
continuousInfeasibilities_(COIN_INT_MAX),
maximumCutPassesAtRoot_(20),
maximumCutPasses_(10),
preferredWay_(0),
currentPassNumber_(0),
maximumWhich_(INITIAL_MAXIMUM_WHICH),
maximumRows_(0),
randomSeed_(-1),
multipleRootTries_(0),
currentDepth_(0),
whichGenerator_(NULL),
maximumStatistics_(0),
statistics_(NULL),
maximumDepthActual_(0),
numberDJFixed_(0.0),
probingInfo_(NULL),
numberFixedAtRoot_(0),
numberFixedNow_(0),
stoppedOnGap_(false),
eventHappened_(false),
numberLongStrong_(0),
numberOldActiveCuts_(0),
numberNewCuts_(0),
searchStrategy_(-1),
strongStrategy_(0),
numberStrongIterations_(0),
resolveAfterTakeOffCuts_(true),
maximumNumberIterations_(-1),
continuousPriority_(COIN_INT_MAX),
numberUpdateItems_(0),
maximumNumberUpdateItems_(0),
updateItems_(NULL),
storedRowCuts_(NULL),
numberThreads_(0),
threadMode_(0),
numberGlobalCutsIn_(0),
master_(NULL),
masterThread_(NULL)
{
memset(intParam_, 0, sizeof(intParam_));
intParam_[CbcMaxNumNode] = 2147483647;
intParam_[CbcMaxNumSol] = 9999999;
memset(dblParam_, 0, sizeof(dblParam_));
dblParam_[CbcIntegerTolerance] = 1e-6;
dblParam_[CbcCutoffIncrement] = 1e-5;
dblParam_[CbcAllowableGap] = 1.0e-10;
dblParam_[CbcMaximumSeconds] = 1.0e100;
dblParam_[CbcCurrentCutoff] = 1.0e100;
dblParam_[CbcOptimizationDirection] = 1.0;
dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
strongInfo_[0] = 0;
strongInfo_[1] = 0;
strongInfo_[2] = 0;
strongInfo_[3] = 0;
strongInfo_[4] = 0;
strongInfo_[5] = 0;
strongInfo_[6] = 0;
solverCharacteristics_ = NULL;
nodeCompare_ = new CbcCompareDefault();;
problemFeasibility_ = new CbcFeasibilityBase();
tree_ = new CbcTree();
branchingMethod_ = NULL;
cutModifier_ = NULL;
strategy_ = NULL;
parentModel_ = NULL;
appData_ = NULL;
solver_ = rhs.clone();
handler_ = new CoinMessageHandler();
if (!solver_->defaultHandler()&&
solver_->messageHandler()->logLevel(0)!=-1000)
passInMessageHandler(solver_->messageHandler());
handler_->setLogLevel(2);
messages_ = CbcMessage();
//eventHandler_ = new CbcEventHandler() ;
referenceSolver_ = solver_->clone();
ownership_ = 0x80000000;
cbcColLower_ = NULL;
cbcColUpper_ = NULL;
cbcRowLower_ = NULL;
cbcRowUpper_ = NULL;
cbcColSolution_ = NULL;
cbcRowPrice_ = NULL;
cbcReducedCost_ = NULL;
cbcRowActivity_ = NULL;
// Initialize solution and integer variable vectors
bestSolution_ = NULL; // to say no solution found
savedSolutions_ = NULL;
numberIntegers_ = 0;
int numberColumns = solver_->getNumCols();
int iColumn;
if (numberColumns) {
// Space for current solution
currentSolution_ = new double[numberColumns];
continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),numberColumns);
usedInSolution_ = new int[numberColumns];
CoinZeroN(usedInSolution_, numberColumns);
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if ( solver_->isInteger(iColumn))
numberIntegers_++;
}
} else {
// empty model
currentSolution_ = NULL;
continuousSolution_ = NULL;
usedInSolution_ = NULL;
}
testSolution_ = currentSolution_;
if (numberIntegers_) {
integerVariable_ = new int [numberIntegers_];
numberIntegers_ = 0;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if ( solver_->isInteger(iColumn))
integerVariable_[numberIntegers_++] = iColumn;
}
} else {
integerVariable_ = NULL;
}
}
static int * resizeInt(int * array,int oldLength, int newLength)
{
if (!array)
return NULL;
assert (newLength>oldLength);
int * newArray = new int [newLength];
memcpy(newArray,array,oldLength*sizeof(int));
delete [] array;
memset(newArray+oldLength,0,(newLength-oldLength)*sizeof(int));
return newArray;
}
static double * resizeDouble(double * array,int oldLength, int newLength)
{
if (!array)
return NULL;
assert (newLength>oldLength);
double * newArray = new double [newLength];
memcpy(newArray,array,oldLength*sizeof(double));
delete [] array;
memset(newArray+oldLength,0,(newLength-oldLength)*sizeof(double));
return newArray;
}
/*
Assign a solver to the model (model assumes ownership)
The integer variable vector is initialized if it's not already present.
If deleteSolver then current solver deleted (if model owned)
Assuming ownership matches usage in OsiSolverInterface
(cf. assignProblem, loadProblem).
TODO: What to do about solver parameters? A simple copy likely won't do it,
because the SI must push the settings into the underlying solver. In
the context of switching solvers in cbc, this means that command line
settings will get lost. Stash the command line somewhere and reread it
here, maybe?
TODO: More generally, how much state should be transferred from the old
solver to the new solver? Best perhaps to see how usage develops.
What's done here mimics the CbcModel(OsiSolverInterface) constructor.
*/
void
CbcModel::assignSolver(OsiSolverInterface *&solver, bool deleteSolver)
{
// resize stuff if exists
if (solver && solver_) {
int nOld = solver_->getNumCols();
int nNew = solver->getNumCols();
if (nNew > nOld) {
originalColumns_ = resizeInt(originalColumns_,nOld,nNew);
usedInSolution_ = resizeInt(usedInSolution_,nOld,nNew);
continuousSolution_ = resizeDouble(continuousSolution_,nOld,nNew);
hotstartSolution_ = resizeDouble(hotstartSolution_,nOld,nNew);
bestSolution_ = resizeDouble(bestSolution_,nOld,nNew);
currentSolution_ = resizeDouble(currentSolution_,nOld,nNew);
if (savedSolutions_) {
for (int i = 0; i < maximumSavedSolutions_; i++)
savedSolutions_[i] = resizeDouble(savedSolutions_[i],nOld,nNew);
}
}
}
// Keep the current message level for solver (if solver exists)
if (solver_)
solver->messageHandler()->setLogLevel(solver_->messageHandler()->logLevel()) ;
if (modelOwnsSolver() && deleteSolver) {
solverCharacteristics_ = NULL;
delete solver_ ;
}
solver_ = solver;
solver = NULL ;
setModelOwnsSolver(true) ;
/*
Basis information is solver-specific.
*/
if (emptyWarmStart_) {
delete emptyWarmStart_ ;
emptyWarmStart_ = 0 ;
}
bestSolutionBasis_ = CoinWarmStartBasis();
/*
Initialize integer variable vector.
*/
numberIntegers_ = 0;
int numberColumns = solver_->getNumCols();
int iColumn;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if ( solver_->isInteger(iColumn))
numberIntegers_++;
}
delete [] integerVariable_;
if (numberIntegers_) {
integerVariable_ = new int [numberIntegers_];
numberIntegers_ = 0;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if ( solver_->isInteger(iColumn))
integerVariable_[numberIntegers_++] = iColumn;
}
} else {
integerVariable_ = NULL;
}
return ;
}
// Cloning method
CbcModel *CbcModel::clone (bool cloneHandler) {
return new CbcModel (*this, cloneHandler);
}
// Copy constructor.
CbcModel::CbcModel(const CbcModel & rhs, bool cloneHandler)
:
continuousSolver_(NULL),
referenceSolver_(NULL),
defaultHandler_(rhs.defaultHandler_),
emptyWarmStart_(NULL),
bestObjective_(rhs.bestObjective_),
bestPossibleObjective_(rhs.bestPossibleObjective_),
sumChangeObjective1_(rhs.sumChangeObjective1_),
sumChangeObjective2_(rhs.sumChangeObjective2_),
globalConflictCuts_(NULL),
minimumDrop_(rhs.minimumDrop_),
numberSolutions_(rhs.numberSolutions_),
numberSavedSolutions_(rhs.numberSavedSolutions_),
maximumSavedSolutions_(rhs.maximumSavedSolutions_),
stateOfSearch_(rhs.stateOfSearch_),
whenCuts_(rhs.whenCuts_),
numberHeuristicSolutions_(rhs.numberHeuristicSolutions_),
numberNodes_(rhs.numberNodes_),
numberNodes2_(rhs.numberNodes2_),
numberIterations_(rhs.numberIterations_),
numberSolves_(rhs.numberSolves_),
status_(rhs.status_),
secondaryStatus_(rhs.secondaryStatus_),
specialOptions_(rhs.specialOptions_),
moreSpecialOptions_(rhs.moreSpecialOptions_),
moreSpecialOptions2_(rhs.moreSpecialOptions2_),
topOfTree_(NULL),
subTreeModel_(rhs.subTreeModel_),
heuristicModel_(NULL),
numberStoppedSubTrees_(rhs.numberStoppedSubTrees_),
presolve_(rhs.presolve_),
numberStrong_(rhs.numberStrong_),
numberBeforeTrust_(rhs.numberBeforeTrust_),
numberPenalties_(rhs.numberPenalties_),
stopNumberIterations_(rhs.stopNumberIterations_),
penaltyScaleFactor_(rhs.penaltyScaleFactor_),
numberAnalyzeIterations_(rhs.numberAnalyzeIterations_),
analyzeResults_(NULL),
numberInfeasibleNodes_(rhs.numberInfeasibleNodes_),
problemType_(rhs.problemType_),
printFrequency_(rhs.printFrequency_),
fastNodeDepth_(rhs.fastNodeDepth_),
howOftenGlobalScan_(rhs.howOftenGlobalScan_),
numberGlobalViolations_(rhs.numberGlobalViolations_),
numberExtraIterations_(rhs.numberExtraIterations_),
numberExtraNodes_(rhs.numberExtraNodes_),
numberFathoms_(rhs.numberFathoms_),
continuousObjective_(rhs.continuousObjective_),
originalContinuousObjective_(rhs.originalContinuousObjective_),
continuousInfeasibilities_(rhs.continuousInfeasibilities_),
maximumCutPassesAtRoot_(rhs.maximumCutPassesAtRoot_),
maximumCutPasses_( rhs.maximumCutPasses_),
preferredWay_(rhs.preferredWay_),
currentPassNumber_(rhs.currentPassNumber_),
maximumWhich_(rhs.maximumWhich_),
maximumRows_(0),
randomSeed_(rhs.randomSeed_),
multipleRootTries_(rhs.multipleRootTries_),
currentDepth_(0),
whichGenerator_(NULL),
maximumStatistics_(0),
statistics_(NULL),
maximumDepthActual_(0),
numberDJFixed_(0.0),
probingInfo_(NULL),
numberFixedAtRoot_(rhs.numberFixedAtRoot_),
numberFixedNow_(rhs.numberFixedNow_),
stoppedOnGap_(rhs.stoppedOnGap_),
eventHappened_(rhs.eventHappened_),
numberLongStrong_(rhs.numberLongStrong_),
numberOldActiveCuts_(rhs.numberOldActiveCuts_),
numberNewCuts_(rhs.numberNewCuts_),
searchStrategy_(rhs.searchStrategy_),
strongStrategy_(rhs.strongStrategy_),
numberStrongIterations_(rhs.numberStrongIterations_),
resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_),
maximumNumberIterations_(rhs.maximumNumberIterations_),
continuousPriority_(rhs.continuousPriority_),
numberUpdateItems_(rhs.numberUpdateItems_),
maximumNumberUpdateItems_(rhs.maximumNumberUpdateItems_),
updateItems_(NULL),
storedRowCuts_(NULL),
numberThreads_(rhs.numberThreads_),
threadMode_(rhs.threadMode_),
numberGlobalCutsIn_(rhs.numberGlobalCutsIn_),
master_(NULL),
masterThread_(NULL)
{
memcpy(intParam_, rhs.intParam_, sizeof(intParam_));
memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_));
strongInfo_[0] = rhs.strongInfo_[0];
strongInfo_[1] = rhs.strongInfo_[1];
strongInfo_[2] = rhs.strongInfo_[2];
strongInfo_[3] = rhs.strongInfo_[3];
strongInfo_[4] = rhs.strongInfo_[4];
strongInfo_[5] = rhs.strongInfo_[5];
strongInfo_[6] = rhs.strongInfo_[6];
solverCharacteristics_ = NULL;
if (rhs.emptyWarmStart_) emptyWarmStart_ = rhs.emptyWarmStart_->clone() ;
if (defaultHandler_ || cloneHandler) {
handler_ = new CoinMessageHandler();
handler_->setLogLevel(2);
} else {
handler_ = rhs.handler_;
}
messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
numberCutGenerators_ = rhs.numberCutGenerators_;
if (numberCutGenerators_) {
generator_ = new CbcCutGenerator * [numberCutGenerators_];
virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_];
int i;
for (i = 0; i < numberCutGenerators_; i++) {
generator_[i] = new CbcCutGenerator(*rhs.generator_[i]);
virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]);
}
} else {
generator_ = NULL;
virginGenerator_ = NULL;
}
globalCuts_ = rhs.globalCuts_;
numberHeuristics_ = rhs.numberHeuristics_;
if (numberHeuristics_) {
heuristic_ = new CbcHeuristic * [numberHeuristics_];
int i;
for (i = 0; i < numberHeuristics_; i++) {
heuristic_[i] = rhs.heuristic_[i]->clone();
}
} else {
heuristic_ = NULL;
}
lastHeuristic_ = NULL;
if (rhs.eventHandler_) {
eventHandler_ = rhs.eventHandler_->clone() ;
} else {
eventHandler_ = NULL ;
}
ownObjects_ = rhs.ownObjects_;
if (ownObjects_) {
numberObjects_ = rhs.numberObjects_;
if (numberObjects_) {
object_ = new OsiObject * [numberObjects_];
int i;
for (i = 0; i < numberObjects_; i++) {
object_[i] = (rhs.object_[i])->clone();
CbcObject * obj = dynamic_cast <CbcObject *>(object_[i]) ;
// Could be OsiObjects
if (obj)
obj->setModel(this);
}
} else {
object_ = NULL;
}
} else {
// assume will be redone
numberObjects_ = 0;
object_ = NULL;
}
if (rhs.continuousSolver_) {
continuousSolver_ = rhs.continuousSolver_->clone() ;
} else {
continuousSolver_ = NULL ;
}
if (rhs.referenceSolver_)
referenceSolver_ = rhs.referenceSolver_->clone();
else
referenceSolver_ = NULL;
solver_ = rhs.solver_->clone();
if (rhs.originalColumns_) {
int numberColumns = solver_->getNumCols();
originalColumns_ = new int [numberColumns];
memcpy(originalColumns_, rhs.originalColumns_, numberColumns*sizeof(int));
} else {
originalColumns_ = NULL;
}
if (maximumNumberUpdateItems_) {
updateItems_ = new CbcObjectUpdateData [maximumNumberUpdateItems_];
for (int i = 0; i < maximumNumberUpdateItems_; i++)
updateItems_[i] = rhs.updateItems_[i];
}
if (maximumWhich_ && rhs.whichGenerator_)
whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_, maximumWhich_);
nodeCompare_ = rhs.nodeCompare_->clone();
problemFeasibility_ = rhs.problemFeasibility_->clone();
tree_ = rhs.tree_->clone();
if (rhs.branchingMethod_)
branchingMethod_ = rhs.branchingMethod_->clone();
else
branchingMethod_ = NULL;
if (rhs.cutModifier_)
cutModifier_ = rhs.cutModifier_->clone();
else
cutModifier_ = NULL;
cbcColLower_ = NULL;
cbcColUpper_ = NULL;
cbcRowLower_ = NULL;
cbcRowUpper_ = NULL;
cbcColSolution_ = NULL;
cbcRowPrice_ = NULL;
cbcReducedCost_ = NULL;
cbcRowActivity_ = NULL;
if (rhs.strategy_)
strategy_ = rhs.strategy_->clone();
else
strategy_ = NULL;
parentModel_ = rhs.parentModel_;
appData_ = rhs.appData_;
messages_ = rhs.messages_;
ownership_ = rhs.ownership_ | 0x80000000;
messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
numberIntegers_ = rhs.numberIntegers_;
randomNumberGenerator_ = rhs.randomNumberGenerator_;
if (numberIntegers_) {
integerVariable_ = new int [numberIntegers_];
memcpy(integerVariable_, rhs.integerVariable_, numberIntegers_*sizeof(int));
integerInfo_ = CoinCopyOfArray(rhs.integerInfo_, solver_->getNumCols());
} else {
integerVariable_ = NULL;
integerInfo_ = NULL;
}
if (rhs.hotstartSolution_) {
int numberColumns = solver_->getNumCols();
hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_, numberColumns);
hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns);
} else {
hotstartSolution_ = NULL;
hotstartPriorities_ = NULL;
}
if (rhs.bestSolution_) {
int numberColumns = solver_->getNumCols();
bestSolution_ = new double[numberColumns];
memcpy(bestSolution_, rhs.bestSolution_, numberColumns*sizeof(double));
} else {
bestSolution_ = NULL;
}
int numberColumns = solver_->getNumCols();
if (maximumSavedSolutions_ && rhs.savedSolutions_) {
savedSolutions_ = new double * [maximumSavedSolutions_];
for (int i = 0; i < maximumSavedSolutions_; i++)
savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2);
} else {
savedSolutions_ = NULL;
}
// Space for current solution
if (numberColumns) {
currentSolution_ = new double[numberColumns];
continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),numberColumns);
usedInSolution_ = new int[numberColumns];
CoinZeroN(usedInSolution_, numberColumns);
} else {
currentSolution_ = NULL;
continuousSolution_ = NULL;
usedInSolution_ = NULL;
}
testSolution_ = currentSolution_;
numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_;
cutoffRowNumber_ = rhs.cutoffRowNumber_;
maximumNumberCuts_ = rhs.maximumNumberCuts_;
phase_ = rhs.phase_;
currentNumberCuts_ = rhs.currentNumberCuts_;
maximumDepth_ = rhs.maximumDepth_;
// These are only used as temporary arrays so need not be filled
if (maximumNumberCuts_) {
addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
} else {
addedCuts_ = NULL;
}
bestSolutionBasis_ = rhs.bestSolutionBasis_;
nextRowCut_ = NULL;
currentNode_ = NULL;
if (maximumDepth_) {
walkback_ = new CbcNodeInfo * [maximumDepth_];
lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ;
lastNumberCuts_ = new int [maximumDepth_] ;
} else {
walkback_ = NULL;
lastNodeInfo_ = NULL;
lastNumberCuts_ = NULL;
}
maximumCuts_ = rhs.maximumCuts_;
if (maximumCuts_) {
lastCut_ = new const OsiRowCut * [maximumCuts_] ;
} else {
lastCut_ = NULL;
}
#ifdef COIN_HAS_NTY
if (rhs.symmetryInfo_)
symmetryInfo_ = new CbcSymmetry(*rhs.symmetryInfo_);
else
symmetryInfo_ = NULL;
#endif
synchronizeModel();
if (cloneHandler && !defaultHandler_) {
delete handler_;
CoinMessageHandler * handler = rhs.handler_->clone();
passInMessageHandler(handler);
}
}
// Assignment operator
CbcModel &
CbcModel::operator=(const CbcModel & rhs)
{
if (this != &rhs) {
if (modelOwnsSolver()) {
solverCharacteristics_ = NULL;
delete solver_;
solver_ = NULL;
}
gutsOfDestructor();
if (defaultHandler_) {
delete handler_;
handler_ = NULL;
}
defaultHandler_ = rhs.defaultHandler_;
if (defaultHandler_) {
handler_ = new CoinMessageHandler();
handler_->setLogLevel(2);
} else {
handler_ = rhs.handler_;
}
messages_ = rhs.messages_;
messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
if (rhs.solver_) {
solver_ = rhs.solver_->clone() ;
} else {
solver_ = 0 ;
}
ownership_ = 0x80000000;
delete continuousSolver_ ;
if (rhs.continuousSolver_) {
continuousSolver_ = rhs.continuousSolver_->clone() ;
} else {
continuousSolver_ = 0 ;
}
delete referenceSolver_;
if (rhs.referenceSolver_) {
referenceSolver_ = rhs.referenceSolver_->clone() ;
} else {
referenceSolver_ = NULL ;
}
delete emptyWarmStart_ ;
if (rhs.emptyWarmStart_) {
emptyWarmStart_ = rhs.emptyWarmStart_->clone() ;
} else {
emptyWarmStart_ = 0 ;
}
bestObjective_ = rhs.bestObjective_;
bestPossibleObjective_ = rhs.bestPossibleObjective_;
sumChangeObjective1_ = rhs.sumChangeObjective1_;
sumChangeObjective2_ = rhs.sumChangeObjective2_;
delete [] bestSolution_;
if (rhs.bestSolution_) {
int numberColumns = rhs.getNumCols();
bestSolution_ = new double[numberColumns];
memcpy(bestSolution_, rhs.bestSolution_, numberColumns*sizeof(double));
} else {
bestSolution_ = NULL;
}
for (int i = 0; i < maximumSavedSolutions_; i++)
delete [] savedSolutions_[i];
delete [] savedSolutions_;
savedSolutions_ = NULL;
int numberColumns = rhs.getNumCols();
if (numberColumns) {
// Space for current solution
currentSolution_ = new double[numberColumns];
continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),numberColumns);
usedInSolution_ = new int[numberColumns];
CoinZeroN(usedInSolution_, numberColumns);
} else {
currentSolution_ = NULL;
continuousSolution_ = NULL;
usedInSolution_ = NULL;
}
if (maximumSavedSolutions_) {
savedSolutions_ = new double * [maximumSavedSolutions_];
for (int i = 0; i < maximumSavedSolutions_; i++)
savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2);
} else {
savedSolutions_ = NULL;
}
testSolution_ = currentSolution_;
minimumDrop_ = rhs.minimumDrop_;
numberSolutions_ = rhs.numberSolutions_;
numberSavedSolutions_ = rhs.numberSavedSolutions_;
maximumSavedSolutions_ = rhs.maximumSavedSolutions_;
stateOfSearch_ = rhs.stateOfSearch_;
whenCuts_ = rhs.whenCuts_;
numberHeuristicSolutions_ = rhs.numberHeuristicSolutions_;
numberNodes_ = rhs.numberNodes_;
numberNodes2_ = rhs.numberNodes2_;
numberIterations_ = rhs.numberIterations_;
numberSolves_ = rhs.numberSolves_;
status_ = rhs.status_;
secondaryStatus_ = rhs.secondaryStatus_;
specialOptions_ = rhs.specialOptions_;
moreSpecialOptions_ = rhs.moreSpecialOptions_;
moreSpecialOptions2_ = rhs.moreSpecialOptions2_;
subTreeModel_ = rhs.subTreeModel_;
heuristicModel_ = NULL;
numberStoppedSubTrees_ = rhs.numberStoppedSubTrees_;
presolve_ = rhs.presolve_;
numberStrong_ = rhs.numberStrong_;
numberBeforeTrust_ = rhs.numberBeforeTrust_;
numberPenalties_ = rhs.numberPenalties_;
stopNumberIterations_ = rhs.stopNumberIterations_;
penaltyScaleFactor_ = rhs.penaltyScaleFactor_;
numberAnalyzeIterations_ = rhs.numberAnalyzeIterations_;
delete [] analyzeResults_;
analyzeResults_ = NULL;
numberInfeasibleNodes_ = rhs.numberInfeasibleNodes_;
problemType_ = rhs.problemType_;
printFrequency_ = rhs.printFrequency_;
howOftenGlobalScan_ = rhs.howOftenGlobalScan_;
numberGlobalViolations_ = rhs.numberGlobalViolations_;
numberExtraIterations_ = rhs.numberExtraIterations_;
numberExtraNodes_ = rhs.numberExtraNodes_;
numberFathoms_ = rhs.numberFathoms_;
continuousObjective_ = rhs.continuousObjective_;
originalContinuousObjective_ = rhs.originalContinuousObjective_;
continuousInfeasibilities_ = rhs.continuousInfeasibilities_;
maximumCutPassesAtRoot_ = rhs.maximumCutPassesAtRoot_;
maximumCutPasses_ = rhs.maximumCutPasses_;
randomSeed_ = rhs.randomSeed_;
multipleRootTries_ = rhs.multipleRootTries_;
preferredWay_ = rhs.preferredWay_;
currentPassNumber_ = rhs.currentPassNumber_;
memcpy(intParam_, rhs.intParam_, sizeof(intParam_));
memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_));
globalCuts_ = rhs.globalCuts_;
delete globalConflictCuts_;
globalConflictCuts_=NULL;
int i;
for (i = 0; i < numberCutGenerators_; i++) {
delete generator_[i];
delete virginGenerator_[i];
}
delete [] generator_;
delete [] virginGenerator_;
delete [] heuristic_;
maximumWhich_ = rhs.maximumWhich_;
delete [] whichGenerator_;
whichGenerator_ = NULL;
if (maximumWhich_ && rhs.whichGenerator_)
whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_, maximumWhich_);
maximumRows_ = 0;
currentDepth_ = 0;
randomNumberGenerator_ = rhs.randomNumberGenerator_;
workingBasis_ = CoinWarmStartBasis();
for (i = 0; i < maximumStatistics_; i++)
delete statistics_[i];
delete [] statistics_;
maximumStatistics_ = 0;
statistics_ = NULL;
delete probingInfo_;
probingInfo_ = NULL;
numberFixedAtRoot_ = rhs.numberFixedAtRoot_;
numberFixedNow_ = rhs.numberFixedNow_;
stoppedOnGap_ = rhs.stoppedOnGap_;
eventHappened_ = rhs.eventHappened_;
numberLongStrong_ = rhs.numberLongStrong_;
numberOldActiveCuts_ = rhs.numberOldActiveCuts_;
numberNewCuts_ = rhs.numberNewCuts_;
resolveAfterTakeOffCuts_ = rhs.resolveAfterTakeOffCuts_;
maximumNumberIterations_ = rhs.maximumNumberIterations_;
continuousPriority_ = rhs.continuousPriority_;
numberUpdateItems_ = rhs.numberUpdateItems_;
maximumNumberUpdateItems_ = rhs.maximumNumberUpdateItems_;
delete [] updateItems_;
if (maximumNumberUpdateItems_) {
updateItems_ = new CbcObjectUpdateData [maximumNumberUpdateItems_];
for (i = 0; i < maximumNumberUpdateItems_; i++)
updateItems_[i] = rhs.updateItems_[i];
} else {
updateItems_ = NULL;
}
numberThreads_ = rhs.numberThreads_;
threadMode_ = rhs.threadMode_;
numberGlobalCutsIn_ = rhs.numberGlobalCutsIn_;
delete master_;
master_ = NULL;
masterThread_ = NULL;
searchStrategy_ = rhs.searchStrategy_;
strongStrategy_ = rhs.strongStrategy_;
numberStrongIterations_ = rhs.numberStrongIterations_;
strongInfo_[0] = rhs.strongInfo_[0];
strongInfo_[1] = rhs.strongInfo_[1];
strongInfo_[2] = rhs.strongInfo_[2];
strongInfo_[3] = rhs.strongInfo_[3];
strongInfo_[4] = rhs.strongInfo_[4];
strongInfo_[5] = rhs.strongInfo_[5];
strongInfo_[6] = rhs.strongInfo_[6];
solverCharacteristics_ = NULL;
lastHeuristic_ = NULL;
numberCutGenerators_ = rhs.numberCutGenerators_;
if (numberCutGenerators_) {
generator_ = new CbcCutGenerator * [numberCutGenerators_];
virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_];
int i;
for (i = 0; i < numberCutGenerators_; i++) {
generator_[i] = new CbcCutGenerator(*rhs.generator_[i]);
virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]);
}
} else {
generator_ = NULL;
virginGenerator_ = NULL;
}
numberHeuristics_ = rhs.numberHeuristics_;
if (numberHeuristics_) {
heuristic_ = new CbcHeuristic * [numberHeuristics_];
memcpy(heuristic_, rhs.heuristic_,
numberHeuristics_*sizeof(CbcHeuristic *));
} else {
heuristic_ = NULL;
}
lastHeuristic_ = NULL;
if (eventHandler_)
delete eventHandler_ ;
if (rhs.eventHandler_) {
eventHandler_ = rhs.eventHandler_->clone() ;
} else {
eventHandler_ = NULL ;
}
fastNodeDepth_ = rhs.fastNodeDepth_;
if (ownObjects_) {
for (i = 0; i < numberObjects_; i++)
delete object_[i];
delete [] object_;
numberObjects_ = rhs.numberObjects_;
if (numberObjects_) {
object_ = new OsiObject * [numberObjects_];
int i;
for (i = 0; i < numberObjects_; i++)
object_[i] = (rhs.object_[i])->clone();
} else {
object_ = NULL;
}
} else {
// assume will be redone
numberObjects_ = 0;
object_ = NULL;
}
delete [] originalColumns_;
if (rhs.originalColumns_) {
int numberColumns = rhs.getNumCols();
originalColumns_ = new int [numberColumns];
memcpy(originalColumns_, rhs.originalColumns_, numberColumns*sizeof(int));
} else {
originalColumns_ = NULL;
}
nodeCompare_ = rhs.nodeCompare_->clone();
problemFeasibility_ = rhs.problemFeasibility_->clone();
delete tree_;
tree_ = rhs.tree_->clone();
if (rhs.branchingMethod_)
branchingMethod_ = rhs.branchingMethod_->clone();
else
branchingMethod_ = NULL;
if (rhs.cutModifier_)
cutModifier_ = rhs.cutModifier_->clone();
else
cutModifier_ = NULL;
delete strategy_;
if (rhs.strategy_)
strategy_ = rhs.strategy_->clone();
else
strategy_ = NULL;
parentModel_ = rhs.parentModel_;
appData_ = rhs.appData_;
delete [] integerVariable_;
numberIntegers_ = rhs.numberIntegers_;
if (numberIntegers_) {
integerVariable_ = new int [numberIntegers_];
memcpy(integerVariable_, rhs.integerVariable_,
numberIntegers_*sizeof(int));
integerInfo_ = CoinCopyOfArray(rhs.integerInfo_, rhs.getNumCols());
} else {
integerVariable_ = NULL;
integerInfo_ = NULL;
}
if (rhs.hotstartSolution_) {
int numberColumns = solver_->getNumCols();
hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_, numberColumns);
hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns);
} else {
hotstartSolution_ = NULL;
hotstartPriorities_ = NULL;
}
numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_;
cutoffRowNumber_ = rhs.cutoffRowNumber_;
maximumNumberCuts_ = rhs.maximumNumberCuts_;
phase_ = rhs.phase_;
currentNumberCuts_ = rhs.currentNumberCuts_;
maximumDepth_ = rhs.maximumDepth_;
delete [] addedCuts_;
delete [] walkback_;
// These are only used as temporary arrays so need not be filled
if (maximumNumberCuts_) {
addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
} else {
addedCuts_ = NULL;
}
delete [] lastNodeInfo_ ;
delete [] lastNumberCuts_ ;
delete [] lastCut_;
bestSolutionBasis_ = rhs.bestSolutionBasis_;
nextRowCut_ = NULL;
currentNode_ = NULL;
if (maximumDepth_) {
walkback_ = new CbcNodeInfo * [maximumDepth_];
lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ;
lastNumberCuts_ = new int [maximumDepth_] ;
} else {
walkback_ = NULL;
lastNodeInfo_ = NULL;
lastNumberCuts_ = NULL;
}
maximumCuts_ = rhs.maximumCuts_;
if (maximumCuts_) {
lastCut_ = new const OsiRowCut * [maximumCuts_] ;
} else {
lastCut_ = NULL;
}
#ifdef COIN_HAS_NTY
if (rhs.symmetryInfo_)
symmetryInfo_ = new CbcSymmetry(*rhs.symmetryInfo_);
else
symmetryInfo_ = NULL;
#endif
synchronizeModel();
cbcColLower_ = NULL;
cbcColUpper_ = NULL;
cbcRowLower_ = NULL;
cbcRowUpper_ = NULL;
cbcColSolution_ = NULL;
cbcRowPrice_ = NULL;
cbcReducedCost_ = NULL;
cbcRowActivity_ = NULL;
}
return *this;
}
// Destructor
CbcModel::~CbcModel ()
{
if (defaultHandler_) {
delete handler_;
handler_ = NULL;
}
delete tree_;
tree_ = NULL;
if (modelOwnsSolver()) {
delete solver_;
solver_ = NULL;
}
gutsOfDestructor();
delete eventHandler_ ;
eventHandler_ = NULL ;
#ifdef CBC_THREAD
// Get rid of all threaded stuff
delete master_;
#endif
}
// Clears out as much as possible (except solver)
void
CbcModel::gutsOfDestructor()
{
delete referenceSolver_;
referenceSolver_ = NULL;
int i;
for (i = 0; i < numberCutGenerators_; i++) {
delete generator_[i];
delete virginGenerator_[i];
}
delete [] generator_;
delete [] virginGenerator_;
generator_ = NULL;
virginGenerator_ = NULL;
for (i = 0; i < numberHeuristics_; i++)
delete heuristic_[i];
delete [] heuristic_;
heuristic_ = NULL;
delete nodeCompare_;
nodeCompare_ = NULL;
delete problemFeasibility_;
problemFeasibility_ = NULL;
delete [] originalColumns_;
originalColumns_ = NULL;
delete strategy_;
delete [] updateItems_;
updateItems_ = NULL;
numberUpdateItems_ = 0;
maximumNumberUpdateItems_ = 0;
gutsOfDestructor2();
}
// Clears out enough to reset CbcModel
void
CbcModel::gutsOfDestructor2()
{
delete [] integerInfo_;
integerInfo_ = NULL;
delete [] integerVariable_;
integerVariable_ = NULL;
int i;
if (ownObjects_) {
for (i = 0; i < numberObjects_; i++)
delete object_[i];
delete [] object_;
}
ownObjects_ = true;
object_ = NULL;
numberIntegers_ = 0;
numberObjects_ = 0;
// Below here is whatever consensus is
ownership_ = 0x80000000;
delete branchingMethod_;
branchingMethod_ = NULL;
delete cutModifier_;
cutModifier_ = NULL;
topOfTree_ = NULL;
resetModel();
#ifdef COIN_HAS_NTY
delete symmetryInfo_;
symmetryInfo_ = NULL;
#endif
}
// Clears out enough to reset CbcModel
void
CbcModel::resetModel()
{
delete emptyWarmStart_ ;
emptyWarmStart_ = NULL;
delete continuousSolver_;
continuousSolver_ = NULL;
numberSavedSolutions_ = 0;
delete [] bestSolution_;
bestSolution_ = NULL;
if (savedSolutions_) {
for (int i = 0; i < maximumSavedSolutions_; i++)
delete [] savedSolutions_[i];
delete [] savedSolutions_;
savedSolutions_ = NULL;
}
delete [] currentSolution_;
currentSolution_ = NULL;
delete [] continuousSolution_;
continuousSolution_ = NULL;
solverCharacteristics_ = NULL;
delete [] usedInSolution_;
usedInSolution_ = NULL;
testSolution_ = NULL;
lastHeuristic_ = NULL;
delete [] addedCuts_;
addedCuts_ = NULL;
nextRowCut_ = NULL;
currentNode_ = NULL;
delete [] walkback_;
walkback_ = NULL;
delete [] lastNodeInfo_ ;
lastNodeInfo_ = NULL;
delete [] lastNumberCuts_ ;
lastNumberCuts_ = NULL;
delete [] lastCut_;
lastCut_ = NULL;
delete [] whichGenerator_;
whichGenerator_ = NULL;
for (int i = 0; i < maximumStatistics_; i++)
delete statistics_[i];
delete [] statistics_;
statistics_ = NULL;
maximumDepthActual_ = 0;
numberDJFixed_ = 0.0;
if (probingInfo_) {
delete probingInfo_;
probingInfo_ = NULL;
if (!generator_)
numberCutGenerators_=0;
// also get rid of cut generator
int n=0;
for (int i = 0; i < numberCutGenerators_; i++) {
CglImplication * cutGen;
cutGen = dynamic_cast<CglImplication *>(generator_[i]->generator());
if (!cutGen) {
generator_[n]=generator_[i];
virginGenerator_[n]=virginGenerator_[i];
n++;
} else {
cutGen->setProbingInfo(NULL);
delete generator_[i];
cutGen = dynamic_cast<CglImplication *>(virginGenerator_[i]->generator());
assert (cutGen);
cutGen->setProbingInfo(NULL);
delete virginGenerator_[i];
}
}
numberCutGenerators_=n;
}
maximumStatistics_ = 0;
delete [] analyzeResults_;
analyzeResults_ = NULL;
bestObjective_ = COIN_DBL_MAX;
bestPossibleObjective_ = COIN_DBL_MAX;
sumChangeObjective1_ = 0.0;
sumChangeObjective2_ = 0.0;
numberSolutions_ = 0;
stateOfSearch_ = 0;
delete [] hotstartSolution_;
hotstartSolution_ = NULL;
delete [] hotstartPriorities_;
hotstartPriorities_ = NULL;
numberHeuristicSolutions_ = 0;
numberNodes_ = 0;
numberNodes2_ = 0;
numberIterations_ = 0;
numberSolves_ = 0;
status_ = -1;
secondaryStatus_ = -1;
maximumNumberCuts_ = 0;
phase_ = 0;
currentNumberCuts_ = 0;
maximumDepth_ = 0;
nextRowCut_ = NULL;
currentNode_ = NULL;
// clear out tree
if (tree_ && tree_->size())
tree_->cleanTree(this, -1.0e100, bestPossibleObjective_) ;
subTreeModel_ = NULL;
heuristicModel_ = NULL;
numberStoppedSubTrees_ = 0;
numberInfeasibleNodes_ = 0;
numberGlobalViolations_ = 0;
numberExtraIterations_ = 0;
numberExtraNodes_ = 0;
numberFathoms_ = 0;
continuousObjective_ = 0.0;
originalContinuousObjective_ = 0.0;
continuousInfeasibilities_ = 0;
numberFixedAtRoot_ = 0;
numberFixedNow_ = 0;
stoppedOnGap_ = false;
eventHappened_ = false;
numberLongStrong_ = 0;
numberOldActiveCuts_ = 0;
numberNewCuts_ = 0;
searchStrategy_ = -1;
strongStrategy_ = 0;
numberStrongIterations_ = 0;
// Parameters which need to be reset
setCutoff(COIN_DBL_MAX);
dblParam_[CbcCutoffIncrement] = 1e-5;
dblParam_[CbcCurrentCutoff] = 1.0e100;
dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
delete globalConflictCuts_;
globalConflictCuts_=NULL;
}
/* Most of copy constructor
mode - 0 copy but don't delete before
1 copy and delete before
2 copy and delete before (but use virgin generators)
*/
void
CbcModel::gutsOfCopy(const CbcModel & rhs, int mode)
{
minimumDrop_ = rhs.minimumDrop_;
specialOptions_ = rhs.specialOptions_;
moreSpecialOptions_ = rhs.moreSpecialOptions_;
moreSpecialOptions2_ = rhs.moreSpecialOptions2_;
numberStrong_ = rhs.numberStrong_;
numberBeforeTrust_ = rhs.numberBeforeTrust_;
numberPenalties_ = rhs.numberPenalties_;
printFrequency_ = rhs.printFrequency_;
fastNodeDepth_ = rhs.fastNodeDepth_;
howOftenGlobalScan_ = rhs.howOftenGlobalScan_;
maximumCutPassesAtRoot_ = rhs.maximumCutPassesAtRoot_;
maximumCutPasses_ = rhs.maximumCutPasses_;
randomSeed_ = rhs.randomSeed_;
multipleRootTries_ = rhs.multipleRootTries_;
preferredWay_ = rhs.preferredWay_;
resolveAfterTakeOffCuts_ = rhs.resolveAfterTakeOffCuts_;
maximumNumberIterations_ = rhs.maximumNumberIterations_;
numberSavedSolutions_ = rhs.numberSavedSolutions_;
maximumSavedSolutions_ = rhs.maximumSavedSolutions_;
if (maximumSavedSolutions_) {
int n = solver_->getNumCols();
savedSolutions_ = new double * [maximumSavedSolutions_];
for (int i = 0; i < maximumSavedSolutions_; i++)
savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], n + 2);
}
continuousPriority_ = rhs.continuousPriority_;
numberThreads_ = rhs.numberThreads_;
threadMode_ = rhs.threadMode_;
numberGlobalCutsIn_ = rhs.numberGlobalCutsIn_;
delete master_;
master_ = NULL;
masterThread_ = NULL;
memcpy(intParam_, rhs.intParam_, sizeof(intParam_));
memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_));
int i;
if (mode) {
for (i = 0; i < numberCutGenerators_; i++) {
delete generator_[i];
delete virginGenerator_[i];
}
delete [] generator_;
delete [] virginGenerator_;
for (i = 0; i < numberHeuristics_; i++) {
delete heuristic_[i];
}
delete [] heuristic_;
delete eventHandler_;
delete branchingMethod_;
}
numberCutGenerators_ = rhs.numberCutGenerators_;
if (numberCutGenerators_) {
generator_ = new CbcCutGenerator * [numberCutGenerators_];
virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_];
int i;
for (i = 0; i < numberCutGenerators_; i++) {
if (mode < 2) {
generator_[i] = new CbcCutGenerator(*rhs.generator_[i]);
} else {
generator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]);
// But copy across maximumTries and switches
generator_[i]->setMaximumTries(rhs.generator_[i]->maximumTries());
generator_[i]->setSwitches(rhs.generator_[i]->switches());
}
virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]);
}
} else {
generator_ = NULL;
virginGenerator_ = NULL;
}
numberHeuristics_ = rhs.numberHeuristics_;
if (numberHeuristics_) {
heuristic_ = new CbcHeuristic * [numberHeuristics_];
int i;
for (i = 0; i < numberHeuristics_; i++) {
heuristic_[i] = rhs.heuristic_[i]->clone();
}
} else {
heuristic_ = NULL;
}
if (rhs.eventHandler_)
eventHandler_ = rhs.eventHandler_->clone() ;
else
eventHandler_ = NULL ;
if (rhs.branchingMethod_)
branchingMethod_ = rhs.branchingMethod_->clone();
else
branchingMethod_ = NULL;
messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
whenCuts_ = rhs.whenCuts_;
#ifdef COIN_HAS_NTY
if (rhs.symmetryInfo_)
symmetryInfo_ = new CbcSymmetry (*rhs.symmetryInfo_);
else
symmetryInfo_ = NULL;
#endif
synchronizeModel();
}
// Move status, nodes etc etc across
void
CbcModel::moveInfo(const CbcModel & rhs)
{
bestObjective_ = rhs.bestObjective_;
bestPossibleObjective_ = rhs.bestPossibleObjective_;
numberSolutions_ = rhs.numberSolutions_;
numberHeuristicSolutions_ = rhs.numberHeuristicSolutions_;
numberNodes_ = rhs.numberNodes_;
numberNodes2_ = rhs.numberNodes2_;
numberIterations_ = rhs.numberIterations_;
numberSolves_ = rhs.numberSolves_;
status_ = rhs.status_;
secondaryStatus_ = rhs.secondaryStatus_;
numberStoppedSubTrees_ = rhs.numberStoppedSubTrees_;
numberInfeasibleNodes_ = rhs.numberInfeasibleNodes_;
continuousObjective_ = rhs.continuousObjective_;
originalContinuousObjective_ = rhs.originalContinuousObjective_;
continuousInfeasibilities_ = rhs.continuousInfeasibilities_;
numberFixedAtRoot_ = rhs.numberFixedAtRoot_;
numberFixedNow_ = rhs.numberFixedNow_;
stoppedOnGap_ = rhs.stoppedOnGap_;
eventHappened_ = rhs.eventHappened_;
numberLongStrong_ = rhs.numberLongStrong_;
numberStrongIterations_ = rhs.numberStrongIterations_;
strongInfo_[0] = rhs.strongInfo_[0];
strongInfo_[1] = rhs.strongInfo_[1];
strongInfo_[2] = rhs.strongInfo_[2];
strongInfo_[3] = rhs.strongInfo_[3];
strongInfo_[4] = rhs.strongInfo_[4];
strongInfo_[5] = rhs.strongInfo_[5];
strongInfo_[6] = rhs.strongInfo_[6];
numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_;
cutoffRowNumber_ = rhs.cutoffRowNumber_;
maximumDepth_ = rhs.maximumDepth_;
}
// Save a copy of the current solver so can be reset to
void
CbcModel::saveReferenceSolver()
{
delete referenceSolver_;
referenceSolver_ = solver_->clone();
}
// Uses a copy of reference solver to be current solver
void
CbcModel::resetToReferenceSolver()
{
delete solver_;
solver_ = referenceSolver_->clone();
// clear many things
gutsOfDestructor2();
// Reset cutoff
// Solvers know about direction
double direction = solver_->getObjSense();
double value;
solver_->getDblParam(OsiDualObjectiveLimit, value);
setCutoff(value*direction);
}
// Are there a numerical difficulties?
bool
CbcModel::isAbandoned() const
{
return status_ == 2;
}
// Is optimality proven?
bool
CbcModel::isProvenOptimal() const
{
if (!status_ && bestObjective_ < 1.0e30)
return true;
else
return false;
}
// Is infeasiblity proven (or none better than cutoff)?
bool
CbcModel::isProvenInfeasible() const
{
if (!status_ && (bestObjective_ >= 1.0e30
&& (secondaryStatus_==0||secondaryStatus_==1)))
return true;
else
return false;
}
// Was continuous solution unbounded
bool
CbcModel::isContinuousUnbounded() const
{
if (!status_ && secondaryStatus_ == 7)
return true;
else
return false;
}
// Was continuous solution unbounded
bool
CbcModel::isProvenDualInfeasible() const
{
if (!status_ && secondaryStatus_ == 7)
return true;
else
return false;
}
// Node limit reached?
bool
CbcModel::isNodeLimitReached() const
{
return numberNodes_ >= intParam_[CbcMaxNumNode];
}
// Time limit reached?
bool
CbcModel::isSecondsLimitReached() const
{
if (status_ == 1 && secondaryStatus_ == 4)
return true;
else
return false;
}
// Solution limit reached?
bool
CbcModel::isSolutionLimitReached() const
{
return numberSolutions_ >= intParam_[CbcMaxNumSol];
}
// Set language
void
CbcModel::newLanguage(CoinMessages::Language language)
{
messages_ = CbcMessage(language);
}
void
CbcModel::setNumberStrong(int number)
{
if (number < 0)
numberStrong_ = 0;
else
numberStrong_ = number;
}
void
CbcModel::setNumberBeforeTrust(int number)
{
if (number < -3) {
numberBeforeTrust_ = 0;
} else {
numberBeforeTrust_ = number;
//numberStrong_ = CoinMax(numberStrong_,1);
}
}
void
CbcModel::setNumberPenalties(int number)
{
if (number <= 0) {
numberPenalties_ = 0;
} else {
numberPenalties_ = number;
}
}
void
CbcModel::setPenaltyScaleFactor(double value)
{
if (value <= 0) {
penaltyScaleFactor_ = 3.0;
} else {
penaltyScaleFactor_ = value;
}
}
void
CbcModel::setHowOftenGlobalScan(int number)
{
if (number < -1)
howOftenGlobalScan_ = 0;
else
howOftenGlobalScan_ = number;
}
// Add one generator
void
CbcModel::addCutGenerator(CglCutGenerator * generator,
int howOften, const char * name,
bool normal, bool atSolution,
bool whenInfeasible, int howOftenInSub,
int whatDepth, int whatDepthInSub)
{
CbcCutGenerator ** temp = generator_;
generator_ = new CbcCutGenerator * [numberCutGenerators_+1];
memcpy(generator_, temp, numberCutGenerators_*sizeof(CbcCutGenerator *));
delete[] temp ;
generator_[numberCutGenerators_] =
new CbcCutGenerator(this, generator, howOften, name,
normal, atSolution, whenInfeasible, howOftenInSub,
whatDepth, whatDepthInSub);
// and before any changes
temp = virginGenerator_;
virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_+1];
memcpy(virginGenerator_, temp, numberCutGenerators_*sizeof(CbcCutGenerator *));
delete[] temp ;
virginGenerator_[numberCutGenerators_++] =
new CbcCutGenerator(this, generator, howOften, name,
normal, atSolution, whenInfeasible, howOftenInSub,
whatDepth, whatDepthInSub);
}
// Add one heuristic
void
CbcModel::addHeuristic(CbcHeuristic * generator, const char *name,
int before)
{
CbcHeuristic ** temp = heuristic_;
heuristic_ = new CbcHeuristic * [numberHeuristics_+1];
memcpy(heuristic_, temp, numberHeuristics_*sizeof(CbcHeuristic *));
delete [] temp;
int where;
if (before < 0 || before >= numberHeuristics_) {
where = numberHeuristics_;
} else {
// move up
for (int i = numberHeuristics_; i > before; i--)
heuristic_[i] = heuristic_[i-1];
where = before;
}
heuristic_[where] = generator->clone();
if (name)
heuristic_[where]->setHeuristicName(name) ;
#ifndef SAME_HEURISTIC_SEED
heuristic_[where]->setSeed(987654321 + where);
#else
heuristic_[where]->setSeed(987654321);
#endif
numberHeuristics_++ ;
}
/*
The last subproblem handled by the solver is not necessarily related to the
one being recreated, so the first action is to remove all cuts from the
constraint system. Next, traverse the tree from node to the root to
determine the basis size required for this subproblem and create an empty
basis with the right capacity. Finally, traverse the tree from root to
node, adjusting bounds in the constraint system, adjusting the basis, and
collecting the cuts that must be added to the constraint system.
applyToModel does the heavy lifting.
addCuts1 is used in contexts where all that's desired is the list of cuts:
the node is already fathomed, and we're collecting cuts so that we can
adjust reference counts as we prune nodes. Arguably the two functions
should be separated. The culprit is applyToModel, which performs cut
collection and model adjustment.
Certainly in the contexts where all we need is a list of cuts, there's no
point in passing in a valid basis --- an empty basis will do just fine.
*/
bool CbcModel::addCuts1 (CbcNode * node, CoinWarmStartBasis *&lastws)
{
int nNode = 0;
CbcNodeInfo * nodeInfo = node->nodeInfo();
int numberColumns = getNumCols();
/*
Accumulate the path from node to the root in walkback_, and accumulate a
cut count in currentNumberCuts.
original comment: when working then just unwind until where new node joins
old node (for cuts?)
*/
int currentNumberCuts = 0;
while (nodeInfo) {
//printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo);
walkback_[nNode++] = nodeInfo;
currentNumberCuts += nodeInfo->numberCuts() ;
nodeInfo = nodeInfo->parent() ;
if (nNode == maximumDepth_) {
redoWalkBack();
}
}
resizeWhichGenerator(currentNumberCuts_,currentNumberCuts);
currentNumberCuts_ = currentNumberCuts;
if (currentNumberCuts > maximumNumberCuts_) {
maximumNumberCuts_ = currentNumberCuts;
delete [] addedCuts_;
addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
}
/*
This last bit of code traverses the path collected in walkback_ from the
root back to node. At the end of the loop,
* lastws will be an appropriate basis for node;
* variable bounds in the constraint system will be set to be correct for
node; and
* addedCuts_ will be set to a list of cuts that need to be added to the
constraint system at node.
applyToModel does all the heavy lifting.
*/
bool sameProblem = false;
if ((specialOptions_&4096) == 0) {
#if 0
{
int n1 = numberRowsAtContinuous_;
for (int i = 0; i < lastDepth_; i++)
n1 += lastNumberCuts_[i];
int n2 = numberRowsAtContinuous_;
for (int i = 0; i < nNode; i++)
n2 += walkback_[i]->numberCuts();
//printf("ROWS a %d - old thinks %d new %d\n",solver_->getNumRows(),n1,n2);
}
#endif
int nDel = 0;
int nAdd = 0;
int n = CoinMin(lastDepth_, nNode);
int i;
int difference = lastDepth_ - nNode;
int iZ = lastDepth_;
int iN = 0;
// Last is reversed to minimize copying
if (difference > 0) {
for (i = 0; i < difference; i++) {
// delete rows
nDel += lastNumberCuts_[--iZ];
}
} else if (difference < 0) {
for (i = 0; i < -difference; i++) {
// add rows
nAdd += walkback_[i]->numberCuts();
}
iN = -difference;
}
for (i = 0; i < n; i++) {
iZ--;
if (lastNodeInfo_[iZ] == walkback_[iN]) {
break;
} else {
// delete rows
nDel += lastNumberCuts_[iZ];
// add rows
nAdd += walkback_[iN++]->numberCuts();
}
}
assert (i < n || lastDepth_ == 0);
//printf("lastDepth %d thisDepth %d match at %d, rows+-= %d %d\n",
// lastDepth_,nNode,n-i,nAdd,nDel);
sameProblem = (!nAdd) && (!nDel);
if (lastDepth_) {
while (iN >= 0) {
lastNumberCuts_[iZ] = walkback_[iN]->numberCuts();
lastNodeInfo_[iZ++] = walkback_[iN--];
}
} else {
lastNumberCuts_[0] = walkback_[0]->numberCuts();
lastNodeInfo_[0] = walkback_[0];
}
lastDepth_ = nNode;
}
currentDepth_ = nNode;
/*
Remove all cuts from the constraint system.
(original comment includes ``see note below for later efficiency'', but
the reference isn't clear to me).
*/
/*
Create an empty basis with sufficient capacity for the constraint system
we'll construct: original system plus cuts. Make sure we have capacity to
record those cuts in addedCuts_.
The method of adjusting the basis at a FullNodeInfo object (the root, for
example) is to use a copy constructor to duplicate the basis held in the
nodeInfo, then resize it and return the new basis object. Guaranteed,
lastws will point to a different basis when it returns. We pass in a basis
because we need the parameter to return the allocated basis, and it's an
easy way to pass in the size. But we take a hit for memory allocation.
*/
if (lastws)
lastws->setSize(numberColumns, numberRowsAtContinuous_ + currentNumberCuts);
currentNumberCuts = 0;
while (nNode) {
--nNode;
walkback_[nNode]->applyToModel(this, lastws,
addedCuts_, currentNumberCuts);
}
#ifndef NDEBUG
if (lastws&&!lastws->fullBasis()) {
#ifdef COIN_DEVELOP
printf("******* bad basis\n");
#endif
int numberRows = lastws->getNumArtificial();
int i;
for (i = 0; i < numberRows; i++)
lastws->setArtifStatus(i, CoinWarmStartBasis::basic);
int numberColumns = lastws->getNumStructural();
for (i = 0; i < numberColumns; i++) {
if (lastws->getStructStatus(i) == CoinWarmStartBasis::basic)
lastws->setStructStatus(i, CoinWarmStartBasis::atLowerBound);
}
}
#endif
return sameProblem;
}
/*
adjustCuts might be a better name: If the node is feasible, we sift through
the cuts collected by addCuts1, add the ones that are tight and omit the
ones that are loose. If the node is infeasible, we just adjust the
reference counts to reflect that we're about to prune this node and its
descendants.
*/
int CbcModel::addCuts (CbcNode *node, CoinWarmStartBasis *&lastws)
{
/*
addCuts1 performs step 1 of restoring the subproblem at this node; see the
comments there.
*/
bool sameProblem =
addCuts1(node, lastws);
int i;
int numberColumns = getNumCols();
if (solver_->getNumRows() > maximumRows_) {
maximumRows_ = solver_->getNumRows();
workingBasis_.resize(maximumRows_, numberColumns);
}
CbcNodeInfo * nodeInfo = node->nodeInfo();
double cutoff = getCutoff() ;
int currentNumberCuts = currentNumberCuts_;
/*
If the node can't be fathomed by bound, reinstall tight cuts in the
constraint system. Even if there are no cuts, we'll want to set the
reconstructed basis in the solver.
*/
if (node->objectiveValue() < cutoff || numberThreads_) {
//# define CBC_CHECK_BASIS
# ifdef CBC_CHECK_BASIS
printf("addCuts: expanded basis; rows %d+%d\n",
numberRowsAtContinuous_, currentNumberCuts);
lastws->print();
# endif
/*
Adjust the basis and constraint system so that we retain only active cuts.
There are three steps:
1) Scan the basis. Sort the cuts into effective cuts to be kept and
loose cuts to be dropped.
2) Drop the loose cuts and resize the basis to fit.
3) Install the tight cuts in the constraint system (applyRowCuts) and
and install the basis (setWarmStart).
Use of compressRows conveys we're compressing the basis and not just
tweaking the artificialStatus_ array.
*/
if (currentNumberCuts > 0) {
int numberToAdd = 0;
const OsiRowCut **addCuts;
int numberToDrop = 0 ;
int *cutsToDrop ;
addCuts = new const OsiRowCut* [currentNumberCuts];
cutsToDrop = new int[currentNumberCuts] ;
assert (currentNumberCuts + numberRowsAtContinuous_ <= lastws->getNumArtificial());
assert (currentNumberCuts <= maximumWhich_); // we will read from whichGenerator_[0..currentNumberCuts-1] below, so should have all these entries
// the above assert fails in certain situations, which indicates a bug in the code below
// as a workaround, resize whichGenerator_ to make sure we can read all entries without an invalid read from valgrind (and subsequent crash somewhere, seems so)
resizeWhichGenerator(maximumWhich_, currentNumberCuts);
for (i = 0; i < currentNumberCuts; i++) {
CoinWarmStartBasis::Status status =
lastws->getArtifStatus(i + numberRowsAtContinuous_);
if (addedCuts_[i] &&
(status != CoinWarmStartBasis::basic ||
(addedCuts_[i]->effectiveness() > 1.0e10 &&
!addedCuts_[i]->canDropCut(solver_, i + numberRowsAtContinuous_)))) {
# ifdef CHECK_CUT_COUNTS
printf("Using cut %d %x as row %d\n", i, addedCuts_[i],
numberRowsAtContinuous_ + numberToAdd);
# endif
assert (i<maximumWhich_);
whichGenerator_[numberToAdd] = whichGenerator_[i];
addCuts[numberToAdd++] = addedCuts_[i];
#if 1
if ((specialOptions_&1) != 0) {
const OsiRowCutDebugger * debugger = solver_->getRowCutDebugger() ;
if (debugger)
CoinAssert (!debugger->invalidCut(*addedCuts_[i]));
}
#endif
} else {
# ifdef CHECK_CUT_COUNTS
printf("Dropping cut %d %x\n", i, addedCuts_[i]);
# endif
addedCuts_[i] = NULL;
cutsToDrop[numberToDrop++] = numberRowsAtContinuous_ + i ;
}
}
assert (lastws->fullBasis());
int numberRowsNow = numberRowsAtContinuous_ + numberToAdd;
lastws->compressRows(numberToDrop, cutsToDrop) ;
lastws->resize(numberRowsNow, numberColumns);
// Take out as local search can give bad basisassert (lastws->fullBasis());
bool canMissStuff = false;
if ((specialOptions_&4096) == 0) {
bool redoCuts = true;
if (CoinAbs(lastNumberCuts2_ - numberToAdd) < 5) {
int numberToCheck = CoinMin(lastNumberCuts2_, numberToAdd);
int i1 = 0;
int i2 = 0;
int nDiff = 0;
int nSame = 0;
if (lastNumberCuts2_ == numberToAdd) {
for (int i = 0; i < numberToCheck; i++) {
if (lastCut_[i1++] != addCuts[i2++]) {
nDiff++;
} else {
nSame++;
}
}
} else if (lastNumberCuts2_ > numberToAdd) {
int nDiff2 = lastNumberCuts2_ - numberToAdd;
for (int i = 0; i < numberToCheck; i++) {
if (lastCut_[i1] != addCuts[i2]) {
nDiff++;
while (nDiff2) {
i1++;
nDiff2--;
if (lastCut_[i1] == addCuts[i2]) {
nSame++;
break;
} else {
nDiff++;
}
}
} else {
nSame++;
}
}
nDiff += nDiff2;
} else {
int nDiff2 = numberToAdd - lastNumberCuts2_;
for (int i = 0; i < numberToCheck; i++) {
if (lastCut_[i1] != addCuts[i2]) {
nDiff++;
while (nDiff2) {
i2++;
nDiff2--;
if (lastCut_[i1] == addCuts[i2]) {
nSame++;
break;
} else {
nDiff++;
}
}
} else {
nSame++;
}
}
nDiff += nDiff2;
}
canMissStuff = !nDiff && sameProblem;
// But only if number of rows looks OK
if (numberRowsAtContinuous_ + numberToAdd != solver_->getNumRows())
canMissStuff = false;
} else {
//printf("add now %d add last %d NO2\n",numberToAdd,lastNumberCuts2_);
}
assert (lastws->fullBasis() &&
numberRowsAtContinuous_ + numberToAdd == numberRowsNow);
if (redoCuts) {
if (numberToAdd > maximumCuts_) {
delete [] lastCut_;
maximumCuts_ = 2 * numberToAdd + 10;
lastCut_ = new const OsiRowCut * [maximumCuts_];
}
lastNumberCuts2_ = numberToAdd;
for (int i = 0; i < numberToAdd; i++)
lastCut_[i] = addCuts[i];
}
}
if (!canMissStuff) {
//if (canMissStuff)
//solver_->writeMps("before");
//printf("Not Skipped\n");
//int n1=solver_->getNumRows();
if ((specialOptions_&4096) == 0) {
solver_->restoreBaseModel(numberRowsAtContinuous_);
} else {
// *** Fix later
int numberCuts = solver_->getNumRows() - numberRowsAtContinuous_;
int *which = new int[numberCuts];
for (i = 0 ; i < numberCuts ; i++)
which[i] = i + numberRowsAtContinuous_;
solver_->deleteRows(numberCuts, which);
delete [] which;
}
//#define CHECK_DEBUGGER
#ifdef CHECK_DEBUGGER
if ((specialOptions_&1) != 0 ) {
const OsiRowCutDebugger * debugger =
solver_->getRowCutDebugger();
if (debugger) {
for (int j=0;j<numberToAdd;j++)
CoinAssert (!debugger->invalidCut(*addCuts[j]));
//addCuts[j]->print();
}
}
#endif
solver_->applyRowCuts(numberToAdd, addCuts);
}
# ifdef CBC_CHECK_BASIS
printf("addCuts: stripped basis; rows %d + %d\n",
numberRowsAtContinuous_, numberToAdd);
lastws->print();
# endif
delete [] addCuts;
delete [] cutsToDrop ;
}
/*
Set the basis in the solver.
*/
solver_->setWarmStart(lastws);
/*
Clean up and we're out of here.
*/
numberNodes_++;
return 0;
}
/*
This node has been fathomed by bound as we try to revive it out of the live
set. Adjust the cut reference counts to reflect that we no longer need to
explore the remaining branch arms, hence they will no longer reference any
cuts. Cuts whose reference count falls to zero are deleted.
*/
else {
int i;
if (currentNumberCuts) {
lockThread();
int numberLeft = nodeInfo->numberBranchesLeft();
for (i = 0 ; i < currentNumberCuts ; i++) {
if (addedCuts_[i]) {
if (!addedCuts_[i]->decrement(numberLeft)) {
delete addedCuts_[i];
addedCuts_[i] = NULL;
}
}
}
unlockThread();
}
return 1 ;
}
}
/* Makes all handlers same. If makeDefault 1 then makes top level
default and rest point to that. If 2 then each is copy
*/
void
CbcModel::synchronizeHandlers(int /*makeDefault*/)
{
bool defaultHandler = defaultHandler_;
if (!defaultHandler_) {
// Must have clone
handler_ = handler_->clone();
defaultHandler_ = true;
}
#ifdef COIN_HAS_CLP
if (!defaultHandler) {
OsiClpSolverInterface * solver;
solver = dynamic_cast<OsiClpSolverInterface *>(solver_) ;
if (solver) {
solver->passInMessageHandler(handler_);
solver->getModelPtr()->passInMessageHandler(handler_);
}
solver = dynamic_cast<OsiClpSolverInterface *>(continuousSolver_) ;
if (solver) {
solver->passInMessageHandler(handler_);
solver->getModelPtr()->passInMessageHandler(handler_);
}
}
#endif
}
/*
Perform reduced cost fixing on integer variables.
The variables in question are already nonbasic at bound. We're just nailing
down the current situation.
*/
int CbcModel::reducedCostFix ()
{
if (!solverCharacteristics_->reducedCostsAccurate())
return 0; //NLP
double cutoff = getCutoff() ;
double direction = solver_->getObjSense() ;
double gap = cutoff - solver_->getObjValue() * direction ;
double tolerance;
solver_->getDblParam(OsiDualTolerance, tolerance) ;
if (gap <= 0.0)
gap = tolerance; //return 0;
gap += 100.0 * tolerance;
double integerTolerance = getDblParam(CbcIntegerTolerance) ;
const double *lower = solver_->getColLower() ;
const double *upper = solver_->getColUpper() ;
const double *solution = solver_->getColSolution() ;
const double *reducedCost = solver_->getReducedCost() ;
int numberFixed = 0 ;
int numberTightened = 0 ;
# ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
ClpSimplex * clpSimplex = NULL;
if (clpSolver)
clpSimplex = clpSolver->getModelPtr();
# endif
for (int i = 0 ; i < numberIntegers_ ; i++) {
int iColumn = integerVariable_[i] ;
double djValue = direction * reducedCost[iColumn] ;
double boundGap = upper[iColumn] - lower[iColumn];
if (boundGap > integerTolerance) {
if (solution[iColumn] < lower[iColumn] + integerTolerance
&& djValue*boundGap > gap) {
#ifdef COIN_HAS_CLP
// may just have been fixed before
if (clpSimplex) {
if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) {
#ifdef COIN_DEVELOP
printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n",
iColumn, clpSimplex->getColumnStatus(iColumn),
djValue, gap, lower[iColumn], upper[iColumn]);
#endif
} else {
assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atLowerBound ||
clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed);
}
}
#endif
double newBound = lower[iColumn];
if (boundGap > 1.99) {
boundGap = gap / djValue + 1.0e-4 * boundGap;
newBound = lower[iColumn] + floor(boundGap);
numberTightened++;
//if (newBound)
//printf("tighter - gap %g dj %g newBound %g\n",
// gap,djValue,newBound);
}
solver_->setColUpper(iColumn, newBound) ;
numberFixed++ ;
} else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > boundGap*gap) {
#ifdef COIN_HAS_CLP
// may just have been fixed before
if (clpSimplex) {
if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) {
#ifdef COIN_DEVELOP
printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n",
iColumn, clpSimplex->getColumnStatus(iColumn),
djValue, gap, lower[iColumn], upper[iColumn]);
#endif
} else {
assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atUpperBound ||
clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed);
}
}
#endif
double newBound = upper[iColumn];
if (boundGap > 1.99) {
boundGap = -gap / djValue + 1.0e-4 * boundGap;
newBound = upper[iColumn] - floor(boundGap);
//if (newBound)
//printf("tighter - gap %g dj %g newBound %g\n",
// gap,djValue,newBound);
numberTightened++;
}
solver_->setColLower(iColumn, newBound) ;
numberFixed++ ;
}
}
}
numberDJFixed_ += numberFixed - numberTightened;
#ifdef SWITCH_VARIABLES
if (numberFixed)
fixAssociated(NULL,0);
#endif
return numberFixed;
}
// Collect coding to replace whichGenerator
void
CbcModel::resizeWhichGenerator(int numberNow, int numberAfter)
{
if (numberAfter > maximumWhich_) {
#define MAXIMUM_WHICH_INCREMENT 100
#define MAXIMUM_WHICH_MULTIPLIER 2
//printf("maximumWhich from %d to %d (%d needed)\n",maximumWhich_,
// CoinMax(maximumWhich_ * MAXIMUM_WHICH_MULTIPLIER + MAXIMUM_WHICH_INCREMENT, numberAfter),
// numberAfter);
maximumWhich_ = CoinMax(maximumWhich_ * MAXIMUM_WHICH_MULTIPLIER + MAXIMUM_WHICH_INCREMENT, numberAfter) ;
//maximumWhich_ = numberAfter ;
int * temp = new int[2*maximumWhich_] ;
memcpy(temp, whichGenerator_, numberNow*sizeof(int)) ;
delete [] whichGenerator_ ;
whichGenerator_ = temp ;
memset(whichGenerator_ + numberNow, 0, (maximumWhich_ - numberNow)*sizeof(int));
}
}
/** Solve the model using cuts
This version takes off redundant cuts from node.
Returns true if feasible.
\todo
Why do I need to resolve the problem? What has been done between the last
relaxation and calling solveWithCuts?
If numberTries == 0 then user did not want any cuts.
*/
bool
CbcModel::solveWithCuts (OsiCuts &cuts, int numberTries, CbcNode *node)
/*
Parameters:
numberTries: (i) the maximum number of iterations for this round of cut
generation; if negative then we don't mind if drop is tiny.
cuts: (o) all cuts generated in this round of cut generation
node: (i) So we can update dynamic pseudo costs
*/
{
#ifdef JJF_ZERO
if (node && numberTries > 1) {
if (currentDepth_ < 5)
numberTries *= 4; // boost
else if (currentDepth_ < 10)
numberTries *= 2; // boost
}
#endif
#define CUT_HISTORY 7
double cut_obj[CUT_HISTORY];
for (int j = 0; j < CUT_HISTORY; j++)
cut_obj[j] = -COIN_DBL_MAX;
# ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
int saveClpOptions = 0;
if (clpSolver)
saveClpOptions = clpSolver->specialOptions();
# endif
//solver_->writeMps("saved");
#ifdef CBC_THREAD
/*
Thread mode makes a difference here only when it specifies using separate
threads to generate cuts at the root (bit 2^1 set in threadMode_). In which
case we'll create an array of empty CbcModels (!). Solvers will be cloned
later.
Don't start up threads here if we're already threaded.
*/
CbcBaseModel * master = NULL;
if (numberThreads_ && (threadMode_&2) != 0 && !numberNodes_) {
master = new CbcBaseModel(*this, -1);
}
#endif
bool feasible = true ;
int violated = 0 ;
int numberRowsAtStart = solver_->getNumRows() ;
//printf("solver had %d rows\n",numberRowsAtStart);
int numberColumns = solver_->getNumCols() ;
CoinBigIndex numberElementsAtStart = solver_->getNumElements();
numberOldActiveCuts_ = numberRowsAtStart - numberRowsAtContinuous_ ;
numberNewCuts_ = cuts.sizeRowCuts();
int lastNumberCuts = numberNewCuts_ ;
if (numberNewCuts_) {
// from multiple root passes
const OsiRowCut **addCuts = new const OsiRowCut* [numberNewCuts_];
for (int i = 0; i < numberNewCuts_; i++) {
addCuts[i] = cuts.rowCutPtr(i);
}
solver_->applyRowCuts(numberNewCuts_, addCuts);
delete [] addCuts;
}
bool onOptimalPath = false ;
const OsiRowCutDebugger *debugger = NULL;
if ((specialOptions_&1) != 0) {
/*
See OsiRowCutDebugger for details. In a nutshell, make sure that current
variable values do not conflict with a known optimal solution. (Obviously
this can be fooled when there are multiple solutions.)
*/
debugger = solver_->getRowCutDebugger() ;
if (debugger)
onOptimalPath = (debugger->onOptimalPath(*solver_)) ;
}
/*
As the final action in each round of cut generation (the numberTries loop),
we'll call takeOffCuts to remove slack cuts. These are saved into slackCuts
and rechecked immediately after the cut generation phase of the loop.
*/
OsiCuts slackCuts;
/*
lh:
Resolve the problem
The resolve will also refresh cached copies of the solver solution
(cbcColLower_, ...) held by CbcModel.
This resolve looks like the best point to capture a warm start for use in
the case where cut generation proves ineffective and we need to back out
a few tight cuts.
I've always maintained that this resolve is unnecessary. Let's put in a hook
to report if it's every nontrivial. -lh
Resolve the problem. If we've lost feasibility, might as well bail out right
after the debug stuff. The resolve will also refresh cached copies of the
solver solution (cbcColLower_, ...) held by CbcModel.
*/
double objectiveValue = solver_->getObjValue() * solver_->getObjSense();
if (node) {
objectiveValue = node->objectiveValue();
}
int save = moreSpecialOptions_;
if ((moreSpecialOptions_&4194304)!=0)
moreSpecialOptions_ |= 8388608;
int returnCode = resolve(node ? node->nodeInfo() : NULL, 1);
moreSpecialOptions_=save;
#ifdef CONFLICT_CUTS
#ifdef COIN_HAS_CLP
// if infeasible conflict analysis
if (solver_->isProvenPrimalInfeasible()&&!parentModel_&&
(moreSpecialOptions_&4194304)!=0&&clpSolver) {
if (!topOfTree_ && masterThread_)
topOfTree_ = masterThread_->master_->baseModel_->topOfTree_;
assert (topOfTree_);
int iType=0;
OsiRowCut * cut = clpSolver->modelCut(topOfTree_->lower(),
topOfTree_->upper(),
numberRowsAtContinuous_,whichGenerator_,iType);
if (cut) {
//cut->print();
if (!iType) {
int badCut = makeGlobalCut(cut) ;
if (!badCut) {
#if PRINT_CONFLICT==1
numberConflictCuts++;
lengthConflictCuts += cut->row().getNumElements();
#endif
#if PRINT_CONFLICT<2
if (handler_->logLevel() > 1) {
#endif
printf("Conflict cut at depth %d (%d elements)\n",
currentDepth_,cut->row().getNumElements());
if (cut->row().getNumElements()<3)
cut->print();
#if PRINT_CONFLICT<2
}
#endif
}
if ((specialOptions_&1) != 0) {
debugger = continuousSolver_->getRowCutDebugger() ;
if (debugger) {
if (debugger->invalidCut(*cut)) {
continuousSolver_->applyRowCuts(1,cut);
continuousSolver_->writeMps("bad");
}
CoinAssert (!debugger->invalidCut(*cut));
}
}
} else {
makePartialCut(cut);
}
delete cut;
}
}
if ((moreSpecialOptions_&4194304)!=0&&solver_->isProvenPrimalInfeasible()
&&clpSolver&&clpSolver->lastAlgorithm()==2&&
clpSolver->getModelPtr()->infeasibilityRay()&&
!parentModel_) {
printf("ray exists\n");
}
#endif
#endif
double lastObjective = solver_->getObjValue() * solver_->getObjSense();
cut_obj[CUT_HISTORY-1] = lastObjective;
//double firstObjective = lastObjective+1.0e-8+1.0e-12*fabs(lastObjective);
/*
Contemplate the result of the resolve.
- CbcModel::resolve() has a hook that calls CbcStrategy::status to look
over the solution. The net result is that resolve can return
0 (infeasible), 1 (feasible), or -1 (feasible, but do no further work).
- CbcFeasbililityBase::feasible() can return 0 (no comment),
1 (pretend this is an integer solution), or -1 (pretend this is
infeasible). As of 080104, this seems to be a stub to allow overrides,
with a default implementation that always returns 0.
Setting numberTries = 0 for `do no more work' is problematic. The main cut
generation loop will still execute once, so we do not observe the `no
further work' semantics.
As best I can see, allBranchesGone is a null function as of 071220.
*/
if (node && node->nodeInfo() && !node->nodeInfo()->numberBranchesLeft())
node->nodeInfo()->allBranchesGone(); // can clean up
feasible = returnCode != 0 ;
if (returnCode < 0)
numberTries = 0;
if (problemFeasibility_->feasible(this, 0) < 0) {
feasible = false; // pretend infeasible
}
//#define CHECK_KNOWN_SOLUTION
#ifdef CHECK_KNOWN_SOLUTION
if (onOptimalPath && (solver_->isDualObjectiveLimitReached()||
!feasible)) {
printf("help 1\n");
}
#endif
/*
NEW_UPDATE_OBJECT is defined to 0 when unthreaded (CBC_THREAD undefined), 2
when threaded. No sign of 1 as of 071220.
At present, there are two sets of hierarchies for branching classes. Call
them CbcHier and OsiHier. For example, we have OsiBranchingObject, with
children CbcBranchingObject and OsiTwoWayBranchingObject. All
specialisations descend from one of these two children. Similarly, there is
OsiObject, with children CbcObject and OsiObject2.
In the original setup, there's a single CbcBranchDecision object attached
to CbcModel (branchingMethod_). It has a field to hold the current CbcHier
branching object, and the updateInformation routine reaches through the
branching object to update the underlying CbcHier object.
NEW_UPDATE_OBJECT = 0 would seem to assume the original setup. But,
if we're using the OSI hierarchy for objects and branching, a call to a
nontrivial branchingMethod_->updateInformation would have no effect (it
would expect a CbcObject to work on) or perhaps crash. For the
default CbcBranchDefaultDecision, updateInformation is a noop (actually
defined in the base CbcBranchDecision class).
NEW_UPDATE_OBJECT = 2 looks like it's prepared to cope with either CbcHier or
OsiHier, but it'll be executed only when threads are activated. See the
comments below. The setup is scary.
But ... if the OsiHier update actually reaches right through to the object
list in the solver, it should work just fine in unthreaded mode. It would
seem that the appropriate thing to do in unthreaded mode would be to choose
between the existing code for NEW_UPDATE_OBJECT = 0 and the OsiHier code for
NEW_UPDATE_OBJECT = 2. But I'm going to let John hash that out. The worst
that can happen is inefficiency because I'm not properly updating an object.
*/
// Update branching information if wanted
if (node && branchingMethod_) {
OsiBranchingObject * bobj = node->modifiableBranchingObject();
CbcBranchingObject * cbcobj = dynamic_cast<CbcBranchingObject *> (bobj);
if (cbcobj && cbcobj->object()) {
CbcObject * object = cbcobj->object();
CbcObjectUpdateData update = object->createUpdateInformation(solver_, node, cbcobj);
// have to compute object number as not saved
CbcSimpleInteger * simpleObject =
static_cast <CbcSimpleInteger *>(object) ;
int iObject = simpleObject->position();
#ifndef NDEBUG
int iColumn = simpleObject->columnNumber();
int jObject;
for (jObject = 0 ; jObject < numberObjects_ ; jObject++) {
simpleObject =
static_cast <CbcSimpleInteger *>(object_[jObject]) ;
if (simpleObject->columnNumber() == iColumn)
break;
}
assert (jObject < numberObjects_ && iObject == jObject);
#else
#ifdef CBCMODEL_TIGHTEN_BOUNDS
int iColumn = simpleObject->columnNumber();
#endif
#endif
update.objectNumber_ = iObject;
// Care! We must be careful not to update the same variable in parallel threads.
addUpdateInformation(update);
//#define CBCMODEL_TIGHTEN_BOUNDS
#ifdef CBCMODEL_TIGHTEN_BOUNDS
double cutoff = getCutoff() ;
if (feasible && cutoff < 1.0e20) {
int way = cbcobj->way();
// way is what will be taken next
way = -way;
double value = cbcobj->value();
//const double * lower = solver_->getColLower();
//const double * upper = solver_->getColUpper();
double objectiveChange = lastObjective - objectiveValue;
if (objectiveChange > 1.0e-5) {
CbcIntegerBranchingObject * branch = dynamic_cast <CbcIntegerBranchingObject *>(cbcobj) ;
assert (branch);
if (way < 0) {
double down = value - floor(value);
double changePer = objectiveChange / (down + 1.0e-7);
double distance = (cutoff - objectiveValue) / changePer;
distance += 1.0e-3;
if (distance < 5.0) {
double newLower = ceil(value - distance);
const double * downBounds = branch->downBounds();
if (newLower > downBounds[0]) {
//printf("%d way %d bounds %g %g value %g\n",
// iColumn,way,lower[iColumn],upper[iColumn],value);
//printf("B Could increase lower bound on %d from %g to %g\n",
// iColumn,downBounds[0],newLower);
solver_->setColLower(iColumn, newLower);
}
}
} else {
double up = ceil(value) - value;
double changePer = objectiveChange / (up + 1.0e-7);
double distance = (cutoff - objectiveValue) / changePer;
distance += 1.0e-3;
if (distance < 5.0) {
double newUpper = floor(value + distance);
const double * upBounds = branch->upBounds();
if (newUpper < upBounds[1]) {
//printf("%d way %d bounds %g %g value %g\n",
// iColumn,way,lower[iColumn],upper[iColumn],value);
//printf("B Could decrease upper bound on %d from %g to %g\n",
// iColumn,upBounds[1],newUpper);
solver_->setColUpper(iColumn, newUpper);
}
}
}
}
}
#endif
} else {
OsiIntegerBranchingObject * obj = dynamic_cast<OsiIntegerBranchingObject *> (bobj);
if (obj) {
const OsiObject * object = obj->originalObject();
// have to compute object number as not saved
int iObject;
int iColumn = object->columnNumber();
for (iObject = 0 ; iObject < numberObjects_ ; iObject++) {
if (object_[iObject]->columnNumber() == iColumn)
break;
}
assert (iObject < numberObjects_);
int branch = obj->firstBranch();
if (obj->branchIndex() == 2)
branch = 1 - branch;
assert (branch == 0 || branch == 1);
double originalValue = node->objectiveValue();
double objectiveValue = solver_->getObjValue() * solver_->getObjSense();
double changeInObjective = CoinMax(0.0, objectiveValue - originalValue);
double value = obj->value();
double movement;
if (branch)
movement = ceil(value) - value;
else
movement = value - floor(value);
branchingMethod_->chooseMethod()->updateInformation(iObject, branch, changeInObjective,
movement, 0 /*(feasible) ? 0 : 1; */);
}
}
}
#ifdef CBC_DEBUG
if (feasible) {
printf("Obj value %g (%s) %d rows\n", solver_->getObjValue(),
(solver_->isProvenOptimal()) ? "proven" : "unproven",
solver_->getNumRows()) ;
}
else {
printf("Infeasible %d rows\n", solver_->getNumRows()) ;
}
#endif
if ((specialOptions_&1) != 0) {
/*
If the RowCutDebugger said we were compatible with the optimal solution,
and now we're suddenly infeasible, we might be confused. Then again, we
may have fathomed by bound, heading for a rediscovery of an optimal solution.
*/
if (onOptimalPath && !solver_->isDualObjectiveLimitReached()) {
if (!feasible) {
solver_->writeMpsNative("infeas.mps", NULL, NULL, 2);
solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
CoinWarmStartBasis *slack =
dynamic_cast<CoinWarmStartBasis *>(solver_->getEmptyWarmStart()) ;
solver_->setWarmStart(slack);
delete slack ;
solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0) ;
solver_->initialSolve();
}
assert(feasible) ;
}
}
if (!feasible) {
numberInfeasibleNodes_++;
# ifdef COIN_HAS_CLP
if (clpSolver)
clpSolver->setSpecialOptions(saveClpOptions);
# endif
return (false) ;
}
double change = lastObjective - objectiveValue;
if (change > 1.0e-10) {
dblParam_[CbcSmallestChange] = CoinMin(dblParam_[CbcSmallestChange], change);
dblParam_[CbcSumChange] += change;
dblParam_[CbcLargestChange] = CoinMax(dblParam_[CbcLargestChange], change);
intParam_[CbcNumberBranches]++;
}
sumChangeObjective1_ += solver_->getObjValue() * solver_->getObjSense()
- objectiveValue ;
if ( maximumSecondsReached() )
numberTries = 0; // exit
if ((moreSpecialOptions2_&(2048|4096))!=0 && currentDepth_>5) {
// howOftenGlobalScan_ = 10;
int type = (moreSpecialOptions2_&(2048|4096))>>11;
if (type==1) {
int n=0;
int k=currentDepth_;
while (k) {
if ((k&1)!=0)
n++;
k = k >>1;
}
if (n>1)
numberTries=0;
} else if (type==2) {
if ((currentDepth_%4)!=0)
numberTries=0;
} else {
if ((currentDepth_%8)!=0)
numberTries=0;
}
}
//if ((numberNodes_%100)==0)
//printf("XXa sum obj changed by %g\n",sumChangeObjective1_);
objectiveValue = solver_->getObjValue() * solver_->getObjSense();
// Return at once if numberTries zero
if (!numberTries) {
cuts = OsiCuts();
numberNewCuts_ = 0;
# ifdef COIN_HAS_CLP
if (clpSolver)
clpSolver->setSpecialOptions(saveClpOptions);
# endif
setPointers(solver_);
return true;
}
/*
Do reduced cost fixing.
*/
int xxxxxx = 0;
if (xxxxxx)
solver_->resolve();
reducedCostFix() ;
/*
Set up for at most numberTries rounds of cut generation. If numberTries is
negative, we'll ignore the minimumDrop_ cutoff and keep generating cuts for
the specified number of rounds.
*/
double minimumDrop = minimumDrop_ ;
bool allowZeroIterations = false;
int maximumBadPasses = 0;
if (numberTries < 0) {
numberTries = -numberTries ;
// minimumDrop *= 1.0e-5 ;
// if (numberTries >= -1000000) {
//numberTries=100;
minimumDrop = -1.0;
// }
//numberTries=CoinMax(numberTries,100);
allowZeroIterations = true;
}
int saveNumberTries=numberTries;
/*
Is it time to scan the cuts in order to remove redundant cuts? If so, set
up to do it.
*/
int fullScan = 0 ;
if ((numberNodes_ % SCANCUTS) == 0 || (specialOptions_&256) != 0) {
fullScan = 1 ;
if (!numberNodes_ || (specialOptions_&256) != 0)
fullScan = 2;
specialOptions_ &= ~256; // mark as full scan done
}
double direction = solver_->getObjSense() ;
double startObjective = solver_->getObjValue() * direction ;
currentPassNumber_ = 0 ;
// Really primalIntegerTolerance; relates to an illposed problem with various
// integer solutions depending on integer tolerance.
//double primalTolerance = 1.0e-7 ;
// We may need to keep going on
bool keepGoing = false;
// Say we have not tried one last time
int numberLastAttempts = 0;
/* Get experimental option as to when to stop adding cuts
0 - old style
1 - new style
2 - new style plus don't break if zero cuts first time
3 - as 2 but last drop has to be >0.1*min to say OK
*/
int experimentBreak = (moreSpecialOptions_ >> 11) & 3;
// Whether to increase minimum drop
bool increaseDrop = (moreSpecialOptions_ & 8192) != 0;
for (int i = 0; i < numberCutGenerators_; i++)
generator_[i]->setWhetherInMustCallAgainMode(false);
/*
Begin cut generation loop. Cuts generated during each iteration are
collected in theseCuts. The loop can be divided into four phases:
1) Prep: Fix variables using reduced cost. In the first iteration only,
consider scanning globalCuts_ and activating any applicable cuts.
2) Cut Generation: Call each generator and heuristic registered in the
generator_ and heuristic_ arrays. Newly generated global cuts are
copied to globalCuts_ at this time.
3) Cut Installation and Reoptimisation: Install column and row cuts in
the solver. Copy row cuts to cuts (parameter). Reoptimise.
4) Cut Purging: takeOffCuts() removes inactive cuts from the solver, and
does the necessary bookkeeping in the model.
*/
do {
currentPassNumber_++ ;
numberTries-- ;
if (numberTries < 0 && keepGoing) {
// switch off all normal generators (by the generator's opinion of normal)
// Intended for situations where the primal problem really isn't complete,
// and there are `not normal' cut generators that will augment.
for (int i = 0; i < numberCutGenerators_; i++) {
if (!generator_[i]->mustCallAgain())
generator_[i]->setSwitchedOff(true);
else
generator_[i]->setWhetherInMustCallAgainMode(true);
}
}
keepGoing = false;
OsiCuts theseCuts ;
/*
Scan previously generated global column and row cuts to see if any are
useful.
*/
int numberViolated = 0;
if ((currentPassNumber_ == 1 ||!numberNodes_) && howOftenGlobalScan_ > 0 &&
(numberNodes_ % howOftenGlobalScan_) == 0 &&
(doCutsNow(1) || true)) {
// global column cuts now done in node at top of tree
int numberCuts = numberCutGenerators_ ? globalCuts_.sizeRowCuts() : 0;
if (numberCuts) {
// possibly extend whichGenerator
resizeWhichGenerator(numberViolated, numberViolated + numberCuts);
// only add new cuts up to 10% of current elements
int numberElements = solver_->getNumElements();
int numberColumns = solver_->getNumCols();
int maximumAdd = CoinMax(numberElements/10,2*numberColumns)+100;
double * violations = new double[numberCuts];
int * which = new int[numberCuts];
int numberPossible=0;
for (int i = 0; i < numberCuts; i++) {
OsiRowCut * thisCut = globalCuts_.rowCutPtr(i) ;
double violation = thisCut->violated(cbcColSolution_);
if(thisCut->effectiveness() == COIN_DBL_MAX) {
// see if already there
int j;
for (j = 0; j < currentNumberCuts_; j++) {
if (addedCuts_[j]==thisCut)
break;
}
if (j==currentNumberCuts_)
violation = COIN_DBL_MAX;
//else
//printf("already done??\n");
}
if (violation > 0.005) {
violations[numberPossible]=-violation;
which[numberPossible++]=i;
}
}
CoinSort_2(violations,violations+numberPossible,which);
for (int i = 0; i < numberPossible; i++) {
int k=which[i];
OsiRowCut * thisCut = globalCuts_.rowCutPtr(k) ;
assert (thisCut->violated(cbcColSolution_) > 0.005/*primalTolerance*/ ||
thisCut->effectiveness() == COIN_DBL_MAX);
#define CHECK_DEBUGGER
#ifdef CHECK_DEBUGGER
if ((specialOptions_&1) != 0 && ! parentModel_) {
CoinAssert (!solver_->getRowCutDebuggerAlways()->invalidCut(*thisCut));
}
#endif
#if 0 //ndef NDEBUG
printf("Global cut added - violation %g\n",
thisCut->violated(cbcColSolution_)) ;
#endif
whichGenerator_[numberViolated++] = 20099;
#ifndef GLOBAL_CUTS_JUST_POINTERS
theseCuts.insert(*thisCut) ;
#else
theseCuts.insert(thisCut) ;
#endif
if (violations[i]!=-COIN_DBL_MAX)
maximumAdd -= thisCut->row().getNumElements();
if (maximumAdd<0)
break;
}
delete [] which;
delete [] violations;
numberGlobalViolations_ += numberViolated;
}
}
/*
Generate new cuts (global and/or local) and/or apply heuristics. If
CglProbing is used, then it should be first as it can fix continuous
variables.
At present, CglProbing is the only case where generateCuts will return
true. generateCuts actually modifies variable bounds in the solver when
CglProbing indicates that it can fix a variable. Reoptimisation is required
to take full advantage.
The need to resolve here should only happen after a heuristic solution.
optimalBasisIsAvailable resolves to basisIsAvailable, which seems to be part
of the old OsiSimplex API. Doc'n says `Returns true if a basis is available
and the problem is optimal. Should be used to see if the BinvARow type
operations are possible and meaningful.' Which means any solver other the clp
is probably doing a lot of unnecessary resolves right here.
(Note default OSI implementation of optimalBasisIsAvailable always returns
false.)
*/
if (solverCharacteristics_->warmStart() &&
!solver_->optimalBasisIsAvailable()) {
//printf("XXXXYY no opt basis\n");
#ifdef JJF_ZERO//def COIN_HAS_CLP
//OsiClpSolverInterface * clpSolver
//= dynamic_cast<OsiClpSolverInterface *> (solver_);
int save = 0;
if (clpSolver) {
save = clpSolver->specialOptions();
clpSolver->setSpecialOptions(save | 2048/*4096*/); // Bonmin <something>
}
#endif
resolve(node ? node->nodeInfo() : NULL, 3);
#ifdef JJF_ZERO//def COIN_HAS_CLP
if (clpSolver)
clpSolver->setSpecialOptions(save);
#if CBC_USEFUL_PRINTING>1
if (clpSolver->getModelPtr()->numberIterations())
printf("ITS %d pass %d\n",
clpSolver->getModelPtr()->numberIterations(),
currentPassNumber_);
#endif
#endif
}
if (nextRowCut_) {
// branch was a cut - add it
theseCuts.insert(*nextRowCut_);
if (handler_->logLevel() > 1)
nextRowCut_->print();
const OsiRowCut * cut = nextRowCut_;
double lb = cut->lb();
double ub = cut->ub();
int n = cut->row().getNumElements();
const int * column = cut->row().getIndices();
const double * element = cut->row().getElements();
double sum = 0.0;
for (int i = 0; i < n; i++) {
int iColumn = column[i];
double value = element[i];
//if (cbcColSolution_[iColumn]>1.0e-7)
//printf("value of %d is %g\n",iColumn,cbcColSolution_[iColumn]);
sum += value * cbcColSolution_[iColumn];
}
delete nextRowCut_;
nextRowCut_ = NULL;
if (handler_->logLevel() > 1)
printf("applying branch cut, sum is %g, bounds %g %g\n", sum, lb, ub);
// possibly extend whichGenerator
resizeWhichGenerator(numberViolated, numberViolated + 1);
// set whichgenerator (also serves as marker to say don't delete0
whichGenerator_[numberViolated++] = 20098;
}
// reset probing info
//if (probingInfo_)
//probingInfo_->initializeFixing();
int i;
// If necessary make cut generators work harder
bool strongCuts = (!node && cut_obj[CUT_HISTORY-1] != -COIN_DBL_MAX &&
fabs(cut_obj[CUT_HISTORY-1] - cut_obj[CUT_HISTORY-2]) < 1.0e-7 +
1.0e-6 * fabs(cut_obj[CUT_HISTORY-1]));
for (i = 0; i < numberCutGenerators_; i++)
generator_[i]->setIneffectualCuts(strongCuts);
// Print details
if (!node) {
handler_->message(CBC_ROOT_DETAIL, messages_)
<< currentPassNumber_
<< solver_->getNumRows()
<< solver_->getNumRows() - numberRowsAtContinuous_
<< solver_->getObjValue()
<< CoinMessageEol ;
}
//Is Necessary for Bonmin? Always keepGoing if cuts have been generated in last iteration (taken from similar code in Cbc-2.4)
if (solverCharacteristics_->solutionAddsCuts()&&numberViolated) {
for (i = 0;i<numberCutGenerators_;i++) {
if (generator_[i]->mustCallAgain()) {
keepGoing=true; // say must go round
break;
}
}
}
if(!keepGoing){
// Status for single pass of cut generation
int status = 0;
/*
threadMode with bit 2^1 set indicates we should use threads for root cut
generation.
*/
if ((threadMode_&2) == 0 || numberNodes_) {
status = serialCuts(theseCuts, node, slackCuts, lastNumberCuts);
} else {
// do cuts independently
#ifdef CBC_THREAD
status = parallelCuts(master, theseCuts, node, slackCuts, lastNumberCuts);
#endif
}
// Do we need feasible and violated?
feasible = (status >= 0);
if (status == 1)
keepGoing = true;
else if (status == 2)
numberTries = 0;
if (!feasible)
violated = -2;
}
//if (!feasible)
//break;
/*
End of the loop to exercise each generator - try heuristics
- unless at root node and first pass
*/
if ((numberNodes_ || currentPassNumber_ != 1) && true) {
double * newSolution = new double [numberColumns] ;
double heuristicValue = getCutoff() ;
int found = -1; // no solution found
int whereFrom = numberNodes_ ? 4 : 1;
for (i = 0; i < numberHeuristics_; i++) {
// skip if can't run here
if (!heuristic_[i]->shouldHeurRun(whereFrom))
continue;
// see if heuristic will do anything
double saveValue = heuristicValue ;
int ifSol =
heuristic_[i]->solution(heuristicValue,
newSolution);
//theseCuts) ;
if (ifSol > 0) {
// better solution found
heuristic_[i]->incrementNumberSolutionsFound();
found = i ;
incrementUsed(newSolution);
lastHeuristic_ = heuristic_[found];
#ifdef HEURISTIC_INFORM
printf("HEUR %s where %d A\n",
lastHeuristic_->heuristicName(), whereFrom);
#endif
// CBC_ROUNDING is symbolic; just says found by heuristic
setBestSolution(CBC_ROUNDING, heuristicValue, newSolution) ;
whereFrom |= 8; // say solution found
} else if (ifSol < 0) {
heuristicValue = saveValue ;
}
}
/*
Did any of the heuristics turn up a new solution? Record it before we free
the vector.
*/
if (found >= 0) {
phase_ = 4;
CbcTreeLocal * tree
= dynamic_cast<CbcTreeLocal *> (tree_);
if (tree)
tree->passInSolution(bestSolution_, heuristicValue);
}
delete [] newSolution ;
}
#ifdef JJF_ZERO
// switch on to get all cuts printed
theseCuts.printCuts() ;
#endif
int numberColumnCuts = theseCuts.sizeColCuts() ;
int numberRowCuts = theseCuts.sizeRowCuts() ;
if (violated >= 0)
violated = numberRowCuts + numberColumnCuts ;
/*
Apply column cuts (aka bound tightening). This may be partially redundant
for column cuts returned by CglProbing, as generateCuts installs bounds
from CglProbing when it determines it can fix a variable.
TODO: Looks like the use of violated has evolved. The value set above is
completely ignored. All that's left is violated == -1 indicates some
cut is violated, violated == -2 indicates infeasibility. Only
infeasibility warrants exceptional action.
TODO: Strikes me that this code will fail to detect infeasibility, because
the breaks escape the inner loops but the outer loop keeps going.
Infeasibility in an early cut will be overwritten if a later cut is
merely violated.
*/
if (numberColumnCuts) {
#ifdef CBC_DEBUG
double * oldLower = new double [numberColumns] ;
double * oldUpper = new double [numberColumns] ;
memcpy(oldLower, cbcColLower_, numberColumns*sizeof(double)) ;
memcpy(oldUpper, cbcColUpper_, numberColumns*sizeof(double)) ;
#endif
double integerTolerance = getDblParam(CbcIntegerTolerance) ;
for (int i = 0; i < numberColumnCuts; i++) {
const OsiColCut * thisCut = theseCuts.colCutPtr(i) ;
const CoinPackedVector & lbs = thisCut->lbs() ;
const CoinPackedVector & ubs = thisCut->ubs() ;
int j ;
int n ;
const int * which ;
const double * values ;
n = lbs.getNumElements() ;
which = lbs.getIndices() ;
values = lbs.getElements() ;
for (j = 0; j < n; j++) {
int iColumn = which[j] ;
double value = cbcColSolution_[iColumn] ;
#if CBC_DEBUG>1
printf("%d %g %g %g %g\n", iColumn, oldLower[iColumn],
cbcColSolution_[iColumn], oldUpper[iColumn], values[j]) ;
#endif
solver_->setColLower(iColumn, values[j]) ;
if (value < values[j] - integerTolerance)
violated = -1 ;
if (values[j] > cbcColUpper_[iColumn] + integerTolerance) {
// infeasible
violated = -2 ;
break ;
}
}
n = ubs.getNumElements() ;
which = ubs.getIndices() ;
values = ubs.getElements() ;
for (j = 0; j < n; j++) {
int iColumn = which[j] ;
double value = cbcColSolution_[iColumn] ;
#if CBC_DEBUG>1
printf("%d %g %g %g %g\n", iColumn, oldLower[iColumn],
cbcColSolution_[iColumn], oldUpper[iColumn], values[j]) ;
#endif
solver_->setColUpper(iColumn, values[j]) ;
if (value > values[j] + integerTolerance)
violated = -1 ;
if (values[j] < cbcColLower_[iColumn] - integerTolerance) {
// infeasible
violated = -2 ;
break ;
}
}
}
#ifdef CBC_DEBUG
delete [] oldLower ;
delete [] oldUpper ;
#endif
}
/*
End installation of column cuts. The break here escapes the numberTries
loop.
*/
if (violated == -2 || !feasible) {
// infeasible
feasible = false ;
violated = -2;
if (!numberNodes_)
messageHandler()->message(CBC_INFEAS,
messages())
<< CoinMessageEol ;
break ;
}
/*
Now apply the row (constraint) cuts. This is a bit more work because we need
to obtain and augment the current basis.
TODO: Why do this work, if there are no row cuts? The current basis will do
just fine.
*/
int numberRowsNow = solver_->getNumRows() ;
#ifndef NDEBUG
assert(numberRowsNow == numberRowsAtStart + lastNumberCuts) ;
#else
// ? maybe clue to threaded problems
if (numberRowsNow != numberRowsAtStart + lastNumberCuts) {
fprintf(stderr, "*** threaded error - numberRowsNow(%d) != numberRowsAtStart(%d)+lastNumberCuts(%d)\n",
numberRowsNow, numberRowsAtStart, lastNumberCuts);
fprintf(stdout, "*** threaded error - numberRowsNow(%d) != numberRowsAtStart(%d)+lastNumberCuts(%d)\n",
numberRowsNow, numberRowsAtStart, lastNumberCuts);
abort();
}
#endif
int numberToAdd = theseCuts.sizeRowCuts() ;
numberNewCuts_ = lastNumberCuts + numberToAdd ;
// resize whichGenerator
resizeWhichGenerator(lastNumberCuts,numberNewCuts_);
/*
Now actually add the row cuts and reoptimise.
Install the cuts in the solver using applyRowCuts and
augment the basis with the corresponding slack. We also add each row cut to
the set of row cuts (cuts.insert()) supplied as a parameter. The new basis
must be set with setWarmStart().
TODO: Seems to me the original code could allocate addCuts with size 0, if
numberRowCuts was 0 and numberColumnCuts was nonzero. That might
explain the memory fault noted in the comment by AJK. Unfortunately,
just commenting out the delete[] results in massive memory leaks. Try
a revision to separate the row cut case. Why do we need addCuts at
all? A typing issue, apparently: OsiCut vs. OsiRowCut.
TODO: It looks to me as if numberToAdd and numberRowCuts are identical at
this point. Confirm & get rid of one of them.
TODO: Any reason why the three loops can't be consolidated?
*/
const OsiRowCut ** addCuts = NULL;
if (numberRowCuts > 0 || numberColumnCuts > 0) {
if (numberToAdd > 0) {
int i ;
int * whichGenerator = whichGenerator_ + lastNumberCuts;
// Faster to add all at once
addCuts = new const OsiRowCut * [numberToAdd] ;
for (i = 0 ; i < numberToAdd ; i++) {
addCuts[i] = &theseCuts.rowCut(i) ;
whichGenerator[i]=90;
}
if ((specialOptions_&262144) != 0 && !parentModel_) {
//save
for (i = 0 ; i < numberToAdd ; i++)
storedRowCuts_->addCut(*addCuts[i]);
}
solver_->applyRowCuts(numberToAdd, addCuts) ;
CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
assert(basis != NULL); // make sure not volume
/* dylp bug
Consistent size used by OsiDylp as sanity check. Implicit resize seen
as an error. Hence this call to resize is necessary.
*/
basis->resize(numberRowsAtStart + numberNewCuts_, numberColumns) ;
for (i = 0 ; i < numberToAdd ; i++) {
basis->setArtifStatus(numberRowsNow + i,
CoinWarmStartBasis::basic) ;
}
if (solver_->setWarmStart(basis) == false) {
throw CoinError("Fail setWarmStart() after cut installation.",
"solveWithCuts", "CbcModel") ;
}
delete basis;
}
//solver_->setHintParam(OsiDoDualInResolve,false,OsiHintTry);
feasible = ( resolve(node ? node->nodeInfo() : NULL, 2) != 0) ;
//solver_->setHintParam(OsiDoDualInResolve,true,OsiHintTry);
if ( maximumSecondsReached() ) {
numberTries = -1000; // exit
feasible = false;
delete [] addCuts ;
break;
}
# ifdef CBC_DEBUG
printf("Obj value after cuts %g %d rows\n", solver_->getObjValue(),
solver_->getNumRows()) ;
if (onOptimalPath && !solver_->isDualObjectiveLimitReached())
assert(feasible) ;
# endif
}
/*
No cuts. Cut short the cut generation (numberTries) loop.
*/
else if (numberLastAttempts > 2 || experimentBreak < 2) {
numberTries = 0 ;
}
/*
If the problem is still feasible, first, call takeOffCuts() to remove cuts
that are now slack. takeOffCuts() will call the solver to reoptimise if
that's needed to restore a valid solution.
Next, see if we should quit due to diminishing returns:
* we've tried three rounds of cut generation and we're getting
insufficient improvement in the objective; or
* we generated no cuts; or
* the solver declared optimality with 0 iterations after we added the
cuts generated in this round.
If we decide to keep going, prep for the next iteration.
It just seems more safe to tell takeOffCuts() to call resolve(), even if
we're not continuing cut generation. Otherwise code executed between here
and final disposition of the node will need to be careful not to access the
lp solution. It can happen that we lose feasibility in takeOffCuts ---
numerical jitters when the cutoff bound is epsilon less than the current
best, and we're evaluating an alternative optimum.
TODO: After successive rounds of code motion, there seems no need to
distinguish between the two checks for aborting the cut generation
loop. Confirm and clean up.
*/
if (feasible) {
int cutIterations = solver_->getIterationCount() ;
if (numberOldActiveCuts_ + numberNewCuts_
&& (numberNewCuts_ || doCutsNow(1))
) {
OsiCuts * saveCuts = node ? NULL : &slackCuts;
int nDel = takeOffCuts(cuts, resolveAfterTakeOffCuts_, saveCuts, numberToAdd, addCuts) ;
if (nDel)
lastNumberCuts2_ = 0;
if (solver_->isDualObjectiveLimitReached() && resolveAfterTakeOffCuts_) {
feasible = false ;
# ifdef CBC_DEBUG
double z = solver_->getObjValue() ;
double cut = getCutoff() ;
printf("Lost feasibility by %g in takeOffCuts; z = %g, cutoff = %g\n",
z - cut, z, cut) ;
# endif
}
}
delete [] addCuts ;
if (feasible) {
numberRowsAtStart = numberOldActiveCuts_ + numberRowsAtContinuous_ ;
lastNumberCuts = numberNewCuts_ ;
double thisObj = direction * solver_->getObjValue();
bool badObj = (allowZeroIterations) ? thisObj < cut_obj[0] + minimumDrop
: thisObj < cut_obj[CUT_HISTORY-1] + minimumDrop;
#ifdef JJF_ZERO // probably not a good idea
if (!badObj)
numberLastAttempts = CoinMax(0, numberLastAttempts - 1);
#endif
// Compute maximum number of bad passes
if (minimumDrop > 0.0) {
if (increaseDrop) {
// slowly increase minimumDrop; breakpoints are rule-of-thumb
if (currentPassNumber_ == 13)
minimumDrop = CoinMax(1.5 * minimumDrop, 1.0e-5 * fabs(thisObj));
else if (currentPassNumber_ > 20 && (currentPassNumber_ % 5) == 0)
minimumDrop = CoinMax(1.1 * minimumDrop, 1.0e-5 * fabs(thisObj));
else if (currentPassNumber_ > 50)
minimumDrop = CoinMax(1.1 * minimumDrop, 1.0e-5 * fabs(thisObj));
}
int nBadPasses = 0;
// The standard way of determining escape
if (!experimentBreak) {
double test = 0.01 * minimumDrop;
double goodDrop = COIN_DBL_MAX;
for (int j = CUT_HISTORY - 1; j >= 0; j--) {
if (thisObj - cut_obj[j] < test) {
nBadPasses++;
} else {
goodDrop = (thisObj - cut_obj[j]) / static_cast<double>(nBadPasses + 1);
break;
}
}
maximumBadPasses = CoinMax(maximumBadPasses, nBadPasses);
if (nBadPasses < maximumBadPasses &&
goodDrop > minimumDrop)
badObj = false; // carry on
} else {
// Experimental escape calculations
//if (currentPassNumber_==13||currentPassNumber_>50)
//minimumDrop = CoinMax(1.5*minimumDrop,1.0e-5*fabs(thisObj));
double test = 0.1 * minimumDrop;
double goodDrop = (thisObj - cut_obj[0]) / static_cast<double>(CUT_HISTORY);
double objValue = thisObj;
for (int j = CUT_HISTORY - 1; j >= 0; j--) {
if (objValue - cut_obj[j] < test) {
nBadPasses++;
objValue = cut_obj[j];
} else {
break;
}
}
#if CBC_USEFUL_PRINTING>12
if (!parentModel_ && !numberNodes_)
printf("badObj %s nBad %d maxBad %d goodDrop %g minDrop %g thisDrop %g obj %g\n",
badObj ? "true" : "false",
nBadPasses, maximumBadPasses, goodDrop, minimumDrop,
thisObj - cut_obj[CUT_HISTORY-1],
solver_->getObjValue());
#endif
maximumBadPasses = CoinMax(maximumBadPasses, nBadPasses);
if (nBadPasses < 2 || goodDrop > 2.0*minimumDrop) {
if (experimentBreak <= 2 || goodDrop > 0.1*minimumDrop)
badObj = false; // carry on
}
if (experimentBreak > 1 && goodDrop < minimumDrop)
numberLastAttempts++;
}
}
// magic numbers, they seemed reasonable; there's a possibility here of going more than
// nominal number of passes if we're doing really well.
if (numberTries == 1 && currentDepth_ < 12 && currentPassNumber_ < 10) {
double drop[12] = {1.0, 2.0, 3.0, 10.0, 10.0, 10.0, 10.0, 20.0, 100.0, 100.0, 1000.0, 1000.0};
if (thisObj - lastObjective > drop[currentDepth_]*minimumDrop) {
numberTries++;
#if CBC_USEFUL_PRINTING>1
//printf("drop %g %g %d\n",thisObj,lastObjective,currentPassNumber_);
#endif
}
}
for (int j = 0; j < CUT_HISTORY - 1; j++)
cut_obj[j] = cut_obj[j+1];
cut_obj[CUT_HISTORY-1] = thisObj;
bool allowEarlyTermination = currentPassNumber_ >= 10;
if (currentDepth_ > 10 || (currentDepth_ > 5 && numberColumns > 200))
allowEarlyTermination = true;
//if (badObj && (currentPassNumber_ >= 10 || (currentDepth_>10))
if (badObj && allowEarlyTermination
//&&(currentPassNumber_>=10||lastObjective>firstObjective)
&& !keepGoing) {
numberTries = 0 ;
}
if (numberRowCuts + numberColumnCuts == 0 ||
(cutIterations == 0 && !allowZeroIterations) ) {
// maybe give it one more try
if (numberLastAttempts > 2 || currentDepth_ || experimentBreak < 2)
numberTries=0 ;
else
numberLastAttempts++;
}
if (numberTries > 0) {
reducedCostFix() ;
lastObjective = direction * solver_->getObjValue() ;
}
}
} else {
// not feasible
delete [] addCuts ;
}
/*
We've lost feasibility --- this node won't be referencing the cuts we've
been collecting, so decrement the reference counts.
*/
if (!feasible) {
int i ;
if (currentNumberCuts_) {
lockThread();
for (i = 0; i < currentNumberCuts_; i++) {
// take off node
if (addedCuts_[i]) {
if (!addedCuts_[i]->decrement())
delete addedCuts_[i] ;
addedCuts_[i] = NULL ;
}
}
unlockThread();
}
numberTries = 0 ;
keepGoing=false;
}
if (numberTries ==0 && feasible && !keepGoing && !parentModel_ && !numberNodes_) {
for (int i = 0; i < numberCutGenerators_; i++) {
if (generator_[i]->whetherCallAtEnd()
&&!generator_[i]->whetherInMustCallAgainMode()) {
// give it some goes and switch off
numberTries=(saveNumberTries+4)/5;
generator_[i]->setWhetherCallAtEnd(false);
}
}
}
} while (numberTries > 0 || keepGoing) ;
/*
End cut generation loop.
*/
{
// switch on
for (int i = 0; i < numberCutGenerators_; i++)
generator_[i]->setSwitchedOff(false);
}
//check feasibility.
//If solution seems to be integer feasible calling setBestSolution
//will eventually add extra global cuts which we need to install at
//the nodes
if (feasible && solverCharacteristics_->solutionAddsCuts()) { //check integer feasibility
bool integerFeasible = true;
const double * save = testSolution_;
testSolution_ = solver_->getColSolution();
// point to useful information
OsiBranchingInformation usefulInfo = usefulInformation();
for (int i = 0; i < numberObjects_ && integerFeasible; i++) {
double infeasibility = object_[i]->checkInfeasibility(&usefulInfo);
if (infeasibility)
integerFeasible = false;
}
testSolution_ = save;
// Consider the possibility that some alternatives here only make sense in context
// of bonmin.
if (integerFeasible) { //update
double objValue = solver_->getObjValue();
int numberGlobalBefore = globalCuts_.sizeRowCuts();
// SOLUTION2 so won't up cutoff or print message
setBestSolution(CBC_SOLUTION2, objValue,
solver_->getColSolution(), 0);
int numberGlobalAfter = globalCuts_.sizeRowCuts();
int numberToAdd = numberGlobalAfter - numberGlobalBefore;
if (numberToAdd > 0)
//We have added some cuts say they are tight at that node
//Basis and lp should already have been updated
{
feasible = (solver_->isProvenOptimal() &&
!solver_->isDualObjectiveLimitReached()) ;
if (feasible) {
int numberCuts = numberNewCuts_ = cuts.sizeRowCuts();
// possibly extend whichGenerator
resizeWhichGenerator(numberCuts, numberToAdd + numberCuts);
for (int i = numberGlobalBefore ; i < numberGlobalAfter ; i++) {
whichGenerator_[numberNewCuts_++] = 20099;
#ifndef GLOBAL_CUTS_JUST_POINTERS
cuts.insert(*globalCuts_.rowCutPtr(i)) ;
#else
OsiRowCut * rowCutPointer = globalCuts_.rowCutPtr(i);
cuts.insert(rowCutPointer) ;
#endif
}
numberNewCuts_ = lastNumberCuts + numberToAdd;
//now take off the cuts which are not tight anymore
takeOffCuts(cuts, resolveAfterTakeOffCuts_, NULL) ;
if (solver_->isDualObjectiveLimitReached() && resolveAfterTakeOffCuts_) {
feasible = false ;
}
}
if (!feasible) { //node will be fathomed
lockThread();
for (int i = 0; i < currentNumberCuts_; i++) {
// take off node
if (addedCuts_[i]) {
if (!addedCuts_[i]->decrement())
delete addedCuts_[i] ;
addedCuts_[i] = NULL ;
}
}
unlockThread();
}
}
}
}
/*
End of code block to check for a solution, when cuts may be added as a result
of a feasible solution.
Reduced cost fix at end. Must also check feasible, in case we've popped out
because a generator indicated we're infeasible.
*/
if (feasible && solver_->isProvenOptimal())
reducedCostFix() ;
// If at root node do heuristics
if (!numberNodes_ && !maximumSecondsReached()) {
// First see if any cuts are slack
int numberRows = solver_->getNumRows();
int numberAdded = numberRows - numberRowsAtContinuous_;
if (numberAdded) {
CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
assert(basis != NULL);
int * added = new int[numberAdded];
int nDelete = 0;
for (int j = numberRowsAtContinuous_; j < numberRows; j++) {
if (basis->getArtifStatus(j) == CoinWarmStartBasis::basic) {
//printf("%d slack!\n",j);
added[nDelete++] = j;
}
}
if (nDelete) {
solver_->deleteRows(nDelete, added);
}
delete [] added;
delete basis ;
}
// mark so heuristics can tell
int savePass = currentPassNumber_;
currentPassNumber_ = 999999;
double * newSolution = new double [numberColumns] ;
double heuristicValue = getCutoff() ;
int found = -1; // no solution found
if (feasible) {
int whereFrom = node ? 3 : 2;
for (int i = 0; i < numberHeuristics_; i++) {
// skip if can't run here
if (!heuristic_[i]->shouldHeurRun(whereFrom))
continue;
// see if heuristic will do anything
double saveValue = heuristicValue ;
int ifSol = heuristic_[i]->solution(heuristicValue,
newSolution);
if (ifSol > 0) {
// better solution found
heuristic_[i]->incrementNumberSolutionsFound();
found = i ;
incrementUsed(newSolution);
lastHeuristic_ = heuristic_[found];
#ifdef HEURISTIC_INFORM
printf("HEUR %s where %d B\n",
lastHeuristic_->heuristicName(), whereFrom);
#endif
setBestSolution(CBC_ROUNDING, heuristicValue, newSolution) ;
whereFrom |= 8; // say solution found
} else {
heuristicValue = saveValue ;
}
}
}
currentPassNumber_ = savePass;
if (found >= 0) {
phase_ = 4;
}
delete [] newSolution ;
}
// Up change due to cuts
if (feasible)
sumChangeObjective2_ += solver_->getObjValue() * solver_->getObjSense()
- objectiveValue ;
//if ((numberNodes_%100)==0)
//printf("XXb sum obj changed by %g\n",sumChangeObjective2_);
/*
End of cut generation loop.
Now, consider if we want to disable or adjust the frequency of use for any
of the cut generators. If the client specified a positive number for
howOften, it will never change. If the original value was negative, it'll
be converted to 1000000+|howOften|, and this value will be adjusted each
time fullScan is true. Actual cut generation is performed every
howOften%1000000 nodes; the 1000000 offset is just a convenient way to
specify that the frequency is adjustable.
During cut generation, we recorded the number of cuts produced by each
generator for this node. For all cuts, whichGenerator records the generator
that produced a cut.
TODO: All this should probably be hidden in a method of the CbcCutGenerator
class.
lh:
TODO: Can the loop that scans over whichGenerator to accumulate per
generator counts be replaced by values in countRowCuts and
countColumnCuts?
<< I think the answer is yes, but not the other way 'round. Row and
column cuts are block interleaved in whichGenerator. >>
The root is automatically a full scan interval. At the root, decide if
we're going to do cuts in the tree, and whether we should keep the cuts we
have.
Codes for willBeCutsInTree:
-1: no cuts in tree and currently active cuts seem ineffective; delete
them
0: no cuts in tree but currently active cuts seem effective; make them
into architecturals (faster than treating them as cuts)
1: cuts will be generated in the tree; currently active cuts remain as
cuts
-lh
*/
#ifdef NODE_LOG
int fatherNum = (node == NULL) ? -1 : node->nodeNumber();
double value = (node == NULL) ? -1 : node->branchingObject()->value();
string bigOne = (solver_->getIterationCount() > 30) ? "*******" : "";
string way = (node == NULL) ? "" : (node->branchingObject()->way()) == 1 ? "Down" : "Up";
std::cout << "Node " << numberNodes_ << ", father " << fatherNum << ", #iterations " << solver_->getIterationCount() << ", sol value : " << solver_->getObjValue() << std::endl;
#endif
if (fullScan && numberCutGenerators_) {
/* If cuts just at root node then it will probably be faster to
update matrix and leave all in */
int willBeCutsInTree = 0;
double thisObjective = solver_->getObjValue() * direction ;
// get sizes
int numberRowsAdded = solver_->getNumRows() - numberRowsAtStart;
CoinBigIndex numberElementsAdded = solver_->getNumElements() - numberElementsAtStart ;
double densityOld = static_cast<double> (numberElementsAtStart) / static_cast<double> (numberRowsAtStart);
double densityNew = numberRowsAdded ? (static_cast<double> (numberElementsAdded)) / static_cast<double> (numberRowsAdded)
: 0.0;
/*
If we're at the root, and we added cuts, and the cuts haven't changed the
objective, and the cuts resulted in a significant increase (> 20%) in nonzero
coefficients, do no cuts in the tree and ditch the current cuts. They're not
cost-effective.
*/
if (!numberNodes_) {
if (!parentModel_) {
//printf("%d global cuts\n",globalCuts_.sizeRowCuts()) ;
if ((specialOptions_&1) != 0) {
//specialOptions_ &= ~1;
int numberCuts = globalCuts_.sizeRowCuts();
const OsiRowCutDebugger *debugger =
continuousSolver_->getRowCutDebugger() ;
if (debugger) {
for (int i = 0; i < numberCuts; i++) {
OsiRowCut * cut = globalCuts_.rowCutPtr(i) ;
if (debugger->invalidCut(*cut)) {
continuousSolver_->applyRowCuts(1,cut);
continuousSolver_->writeMps("bad");
printf("BAD cut\n");
}
//CoinAssert (!debugger->invalidCut(*cut));
}
}
}
}
//solver_->writeMps("second");
if (numberRowsAdded)
handler_->message(CBC_CUTS_STATS, messages_)
<< numberRowsAdded
<< densityNew
<< CoinMessageEol ;
if (thisObjective - startObjective < 1.0e-5 && numberElementsAdded > 0.2*numberElementsAtStart)
willBeCutsInTree = -1;
int whenC = whenCuts_;
if (whenC == 999999 || whenC == 999998) {
int size = continuousSolver_->getNumRows() + continuousSolver_->getNumCols();
bool smallProblem = size <= 550;
smallProblem = false;
#if CBC_USEFUL_PRINTING>1
int maxPass = maximumCutPasses_;
#endif
if (thisObjective - startObjective < 1.0e-5) {
// No change in objective function
if (numberElementsAdded > 0.2*numberElementsAtStart) {
if (whenCuts_ == 999999) {
whenCuts_ = 5000010;
if (!smallProblem)
maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
} else if (whenCuts_ == 999998) {
whenCuts_ = 5000010;
if (!smallProblem)
maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
}
#ifdef JJF_ZERO
} else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 8)) {
if (whenCuts_ == 999999) {
whenCuts_ = 8000008;
maximumCutPasses_ = 1;
} else if (whenCuts_ == 999998) {
whenCuts_ = 10000008;
maximumCutPasses_ = 1;
}
} else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 50)) {
if (whenCuts_ == 999999) {
whenCuts_ = 8000008;
maximumCutPasses_ = 1;
} else if (whenCuts_ == 999998) {
whenCuts_ = 10000006;
maximumCutPasses_ = 1;
}
} else if (currentPassNumber_ < CoinAbs(maximumCutPassesAtRoot_)) {
if (whenCuts_ == 999999) {
whenCuts_ = 8000008;
maximumCutPasses_ = 1;
} else if (whenCuts_ == 999998) {
whenCuts_ = 10000004;
maximumCutPasses_ = 1;
}
#endif
} else {
if (whenCuts_ == 999999) {
whenCuts_ = 8000008;
if (!smallProblem)
maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
} else if (whenCuts_ == 999998) {
whenCuts_ = 10000004;
if (!smallProblem)
maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
}
}
} else {
// Objective changed
#ifdef JJF_ZERO
if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 8)) {
if (whenCuts_ == 999999) {
whenCuts_ = 8000008;
maximumCutPasses_ = 1;
} else if (whenCuts_ == 999998) {
whenCuts_ = 10000008;
maximumCutPasses_ = 1;
}
} else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 50)) {
if (whenCuts_ == 999999) {
whenCuts_ = 8000008;
maximumCutPasses_ = 1;
} else if (whenCuts_ == 999998) {
whenCuts_ = 10000004;
maximumCutPasses_ = 1;
}
} else
#endif
if (currentPassNumber_ < CoinAbs(maximumCutPassesAtRoot_)) {
if (whenCuts_ == 999999) {
whenCuts_ = 8000008;
if (!smallProblem)
maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
} else if (whenCuts_ == 999998) {
whenCuts_ = 10000004;
if (!smallProblem)
maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
}
} else {
if (whenCuts_ == 999999) {
whenCuts_ = 10000004;
maximumCutPasses_ = CoinMax(maximumCutPasses_, 2);
} else if (whenCuts_ == 999998) {
whenCuts_ = 11000002;
maximumCutPasses_ = CoinMax(maximumCutPasses_, 2);
}
}
}
// Set bit to say don't try too hard if seems reasonable
if (maximumCutPasses_ <= 5)
whenCuts_ += 100000;
//// end
#if CBC_USEFUL_PRINTING>1
printf("changing whenCuts from %d to %d and cutPasses from %d to %d objchange %g\n",
whenC, whenCuts_, maxPass, maximumCutPasses_, thisObjective - startObjective);
#endif
}
}
/*
Noop block 071219.
*/
if ((numberRowsAdded > 100 + 0.5*numberRowsAtStart
|| numberElementsAdded > 0.5*numberElementsAtStart)
&& (densityNew > 200.0 && numberRowsAdded > 100 && densityNew > 2.0*densityOld)) {
// much bigger
//if (thisObjective-startObjective<0.1*fabs(startObjective)+1.0e-5)
//willBeCutsInTree=-1;
//printf("Cuts will be taken off , %d rows added with density %g\n",
// numberRowsAdded,densityNew);
}
/*
Noop block 071219.
*/
if (densityNew > 100.0 && numberRowsAdded > 2 && densityNew > 2.0*densityOld) {
//if (thisObjective-startObjective<0.1*fabs(startObjective)+1.0e-5)
//willBeCutsInTree=-2;
//printf("Density says no cuts ? , %d rows added with density %g\n",
// numberRowsAdded,densityNew);
}
// Root node or every so often - see what to turn off
/*
Hmmm ... > -90 for any generator will overrule previous decision to do no
cuts in tree and delete existing cuts.
*/
int i ;
for (i = 0; i < numberCutGenerators_; i++) {
int howOften = generator_[i]->howOften() ;
if (howOften > -90)
willBeCutsInTree = 0;
}
if (!numberNodes_) {
handler_->message(CBC_ROOT, messages_)
<< numberNewCuts_
<< startObjective << thisObjective
<< currentPassNumber_
<< CoinMessageEol ;
}
/*
Count the number of cuts produced by each cut generator on this call. Not
clear to me that the accounting is equivalent here. whichGenerator_ records
the generator for column and row cuts. So unless numberNewCuts is row cuts
only, we're double counting for JUST_ACTIVE. Note too the multiplier applied
to column cuts.
*/
if (!numberNodes_) {
double value = CoinMax(minimumDrop_, 0.005 * (thisObjective - startObjective) /
static_cast<double> (currentPassNumber_));
if (numberColumns < 200)
value = CoinMax(minimumDrop_, 0.1 * value);
#if CBC_USEFUL_PRINTING>1
printf("Minimum drop for cuts was %g, now is %g\n", minimumDrop_, value);
#endif
minimumDrop_ = value;
}
int * count = new int[numberCutGenerators_] ;
memset(count, 0, numberCutGenerators_*sizeof(int)) ;
int numberActiveGenerators = 0;
for (i = 0; i < numberNewCuts_; i++) {
int iGenerator = whichGenerator_[i];
//assert (iGenerator>=0);
if (iGenerator>=0)
iGenerator=iGenerator%10000;
if (iGenerator >= 0 && iGenerator < numberCutGenerators_)
count[iGenerator]++ ;
}
// add in any active cuts if at root node (for multiple solvers)
#ifdef CHECK_KNOWN_SOLUTION
if (onOptimalPath && (solver_->isDualObjectiveLimitReached()||
!feasible)) {
printf("help 2\n");
}
#endif
if (!numberNodes_) {
for (i = 0; i < numberCutGenerators_; i++)
count[i] += generator_[i]->numberCutsActive();
}
double totalCuts = 0.0 ;
//#define JUST_ACTIVE
for (i = 0; i < numberCutGenerators_; i++) {
if (generator_[i]->numberCutsInTotal() || generator_[i]->numberColumnCuts())
numberActiveGenerators++;
#ifdef JUST_ACTIVE
double value = count[i] ;
#else
double value = generator_[i]->numberCutsInTotal() ;
#endif
totalCuts += value;
}
/*
Open up a loop to step through the cut generators and decide what (if any)
adjustment should be made for calling frequency.
*/
int iProbing = -1;
double smallProblem = (0.2 * totalCuts) /
static_cast<double> (numberActiveGenerators) ;
for (i = 0; i < numberCutGenerators_; i++) {
int howOften = generator_[i]->howOften() ;
/* Probing can be set to just do column cuts in treee.
But if doing good then leave as on
Ok, let me try to explain this. rowCuts = 3 says do disaggregation (1<<0) and
coefficient (1<<1) cuts. But if the value is negative, there's code at the
entry to generateCuts, and generateCutsAndModify, that temporarily changes
the value to 4 (1<<2) if we're in a search tree.
Which does nothing to explain this next bit. We set a boolean, convert
howOften to the code for `generate while objective is improving', and change
over to `do everywhere'. Hmmm ... now I write it out, this makes sense in the
context of the original comment. If we're doing well (objective improving)
we'll keep probing fully active.
*/
bool probingWasOnBut = false;
CglProbing * probing = dynamic_cast<CglProbing*>(generator_[i]->generator());
if (probing && !numberNodes_) {
if (generator_[i]->numberCutsInTotal()) {
// If large number of probing - can be biased
smallProblem = (0.2 * (totalCuts - generator_[i]->numberCutsInTotal())) /
static_cast<double> (numberActiveGenerators - 1) ;
}
iProbing = i;
if (probing->rowCuts() == -3) {
probingWasOnBut = true;
howOften = -98;
probing->setRowCuts(3);
}
}
/*
Convert `as long as objective is improving' into `only at root' if we've
decided cuts just aren't worth it.
*/
if (willBeCutsInTree < 0 && howOften == -98)
howOften = -99;
/*
And check to see if the objective is improving. But don't do the check if
the user has specified some minimum number of cuts.
This exclusion seems bogus, or at least counterintuitive. Why would a user
suspect that setting a minimum cut limit would invalidate the objective
check? Nor do I see the point in comparing the number of rows and columns
in the second test.
*/
if (!probing && howOften == -98 && !generator_[i]->numberShortCutsAtRoot() &&
generator_[i]->numberCutsInTotal()) {
// switch off as no short cuts generated
//printf("Switch off %s?\n",generator_[i]->cutGeneratorName());
howOften = -99;
}
if (howOften == -98 && generator_[i]->switchOffIfLessThan() > 0) {
if (thisObjective - startObjective < 0.005*fabs(startObjective) + 1.0e-5)
howOften = -99; // switch off
if (thisObjective - startObjective < 0.1*fabs(startObjective) + 1.0e-5
&& 5*solver_->getNumRows() < solver_->getNumCols())
howOften = -99; // switch off
}
if (generator_[i]->maximumTries()!=-1)
howOften = CoinMin(howOften,-99); // switch off
/*
Below -99, this generator is switched off. There's no need to consider
further. Then again, there was no point in persisting this far!
*/
if (howOften < -99) {
// may have been switched off - report
if (!numberNodes_) {
int n = generator_[i]->numberCutsInTotal();
if (n) {
double average = 0.0;
average = generator_[i]->numberElementsInTotal();
average /= n;
handler_->message(CBC_GENERATOR, messages_)
<< i
<< generator_[i]->cutGeneratorName()
<< n
<< average
<< generator_[i]->numberColumnCuts()
<< generator_[i]->numberCutsActive()
+ generator_[i]->numberColumnCuts();
handler_->printing(generator_[i]->timing())
<< generator_[i]->timeInCutGenerator();
handler_->message()
<< -100
<< CoinMessageEol ;
}
}
continue ;
}
/*
Adjust, if howOften is adjustable.
*/
if (howOften < 0 || howOften >= 1000000) {
if ( !numberNodes_) {
/*
If root only, or objective improvement but no cuts generated, switch off. If
it's just that the generator found no cuts at the root, give it one more
chance.
*/
// If small number switch mostly off
#ifdef JUST_ACTIVE
double thisCuts = count[i] + 5.0 * generator_[i]->numberColumnCuts() ;
#else
double thisCuts = generator_[i]->numberCutsInTotal() + 5.0 * generator_[i]->numberColumnCuts() ;
#endif
// Allow on smaller number if <-1
if (generator_[i]->switchOffIfLessThan() < 0) {
double multiplier[] = {2.0, 5.0};
int iSwitch = -generator_[i]->switchOffIfLessThan() - 1;
assert (iSwitch >= 0 && iSwitch < 2);
thisCuts *= multiplier[iSwitch];
}
if (!thisCuts || howOften == -99) {
if (howOften == -99 || howOften == -98) {
howOften = -100 ;
} else {
howOften = 1000000 + SCANCUTS; // wait until next time
if (probing) {
// not quite so drastic
howOften = 1000000 + 1;
probing->setMaxLook(1);
probing->setMaxProbe(123);
}
}
/*
Not productive, but not zero either.
*/
} else if ((thisCuts + generator_[i]->numberColumnCuts() < smallProblem)
&& !generator_[i] ->whetherToUse()) {
/*
Not unadjustable every node, and not strong probing.
*/
if (howOften != 1 && !probingWasOnBut) {
/*
No depth spec, or not adjustable every node.
*/
if (generator_[i]->whatDepth() < 0 || howOften != -1) {
int k = static_cast<int> (sqrt(smallProblem / thisCuts)) ;
/*
Not objective improvement, set to new frequency, otherwise turn off.
*/
if (howOften != -98)
howOften = k + 1000000 ;
else
howOften = -100;
/*
Depth spec, or adjustable every node. Force to unadjustable every node.
*/
} else {
howOften = 1;
}
/*
Unadjustable every node, or strong probing. Force unadjustable every node and
force not strong probing? I don't understand.
*/
} else {
howOften = 1;
// allow cuts
probingWasOnBut = false;
}
/*
Productive cut generator. Say we'll do it every node, adjustable. But if the
objective isn't improving, restrict that to every fifth depth level
(whatDepth overrides howOften in generateCuts).
*/
} else {
if (thisObjective - startObjective < 0.1*fabs(startObjective) + 1.0e-5 && generator_[i]->whatDepth() < 0)
generator_[i]->setWhatDepth(5);
howOften = 1 + 1000000 ;
}
}
/*
End root actions.
sumChangeObjective2_ is the objective change due to cuts. If we're getting
much better results from branching over a large number of nodes, switch off
cuts.
Except it doesn't, really --- it just puts off the decision 'til the
next full scan, when it'll put it off again unless cuts look better.
*/
// If cuts useless switch off
if (numberNodes_ >= 100000 && sumChangeObjective1_ > 2.0e2*(sumChangeObjective2_ + 1.0e-12)) {
howOften = 1000000 + SCANCUTS; // wait until next time
//printf("switch off cut %d due to lack of use\n",i);
}
}
/*
Ok, that's the frequency adjustment bit.
Now, if we're at the root, force probing back on at every node, for column
cuts at least, even if it looks useless for row cuts. Notice that if it
looked useful, the values set above mean we'll be doing strong probing in
the tree subject to objective improvement.
*/
if (!numberNodes_) {
if (probingWasOnBut && howOften == -100) {
probing->setRowCuts(-3);
howOften = 1;
}
if (howOften == 1)
generator_[i]->setWhatDepth(1);
if (howOften >= 0 && generator_[i]->generator()->mayGenerateRowCutsInTree())
willBeCutsInTree = 1;
}
/*
Set the new frequency in the generator. If this is an adjustable frequency,
use the value to set whatDepth.
Hey! Seems like this could override the user's depth setting.
*/
generator_[i]->setHowOften(howOften) ;
if (howOften >= 1000000 && howOften < 2000000 && 0) {
// Go to depth
int bias = 1;
if (howOften == 1 + 1000000)
generator_[i]->setWhatDepth(bias + 1);
else if (howOften <= 10 + 1000000)
generator_[i]->setWhatDepth(bias + 2);
else
generator_[i]->setWhatDepth(bias + 1000);
}
int newFrequency = generator_[i]->howOften() % 1000000 ;
// increment cut counts
generator_[i]->incrementNumberCutsActive(count[i]);
CglStored * stored = dynamic_cast<CglStored*>(generator_[i]->generator());
if (stored && !generator_[i]->numberCutsInTotal())
continue;
double average = 0.0;
int n = generator_[i]->numberCutsInTotal();
if (n) {
average = generator_[i]->numberElementsInTotal();
average /= n;
}
if (handler_->logLevel() > 1 || !numberNodes_) {
handler_->message(CBC_GENERATOR, messages_)
<< i
<< generator_[i]->cutGeneratorName()
//<<generator_[i]->numberCutsInTotal()<<count[i]
<< n
<< average
<< generator_[i]->numberColumnCuts()
<< generator_[i]->numberCutsActive()
+ generator_[i]->numberColumnCuts();
handler_->printing(!numberNodes_ && generator_[i]->timing())
<< generator_[i]->timeInCutGenerator();
handler_->message()
<< newFrequency
<< CoinMessageEol ;
}
}
/*
End loop to adjust cut generator frequency of use.
*/
delete [] count ;
if ( !numberNodes_) {
// save statistics
for (i = 0; i < numberCutGenerators_; i++) {
generator_[i]->setNumberCutsAtRoot(generator_[i]->numberCutsInTotal());
generator_[i]->setNumberActiveCutsAtRoot(generator_[i]->numberCutsActive());
}
/*
Garbage code 071219
*/
// decide on pseudo cost strategy
int howOften = iProbing >= 0 ? generator_[iProbing]->howOften() : 0;
if ((howOften % 1000000) != 1)
howOften = 0;
//if (howOften) {
//CglProbing * probing = dynamic_cast<CglProbing*>(generator_[iProbing]->generator());
//}
howOften = 0;
if (howOften) {
COIN_DETAIL_PRINT(printf("** method 1\n"));
//CglProbing * probing = dynamic_cast<CglProbing*>(generator_[iProbing]->generator());
generator_[iProbing]->setWhatDepth(1);
// could set no row cuts
//if (thisObjective-startObjective<0.001*fabs(startObjective)+1.0e-5)
// probing->setRowCuts(0);
for (int i = 0; i < numberObjects_; i++) {
CbcSimpleIntegerDynamicPseudoCost * obj =
dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[i]) ;
if (obj)
obj->setMethod(1);
}
}
if (willBeCutsInTree == -2)
willBeCutsInTree = 0;
/*
End garbage code.
Now I've reached the problem area. This is a problem only at the root node,
so that should simplify the issue of finding a workable basis? Or maybe not.
*/
if ( willBeCutsInTree <= 0) {
// Take off cuts
cuts = OsiCuts();
numberNewCuts_ = 0;
if (!willBeCutsInTree) {
// update size of problem
numberRowsAtContinuous_ = solver_->getNumRows() ;
} else {
// take off cuts
int numberRows = solver_->getNumRows();
int numberAdded = numberRows - numberRowsAtContinuous_;
if (numberAdded) {
int * added = new int[numberAdded];
for (int i = 0; i < numberAdded; i++)
added[i] = i + numberRowsAtContinuous_;
solver_->deleteRows(numberAdded, added);
delete [] added;
// resolve so optimal
resolve(solver_);
}
}
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
// Maybe solver might like to know only column bounds will change
//int options = clpSolver->specialOptions();
//clpSolver->setSpecialOptions(options|128);
clpSolver->synchronizeModel();
}
#endif
} else {
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
// make sure factorization can't carry over
int options = clpSolver->specialOptions();
clpSolver->setSpecialOptions(options&(~8));
}
#endif
}
}
} else {
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
// Maybe solver might like to know only column bounds will change
//int options = clpSolver->specialOptions();
//clpSolver->setSpecialOptions(options|128);
clpSolver->synchronizeModel();
}
#endif
if (numberCutGenerators_) {
int i;
// What if not feasible as cuts may have helped
if (feasible) {
for (i = 0; i < numberNewCuts_; i++) {
int iGenerator = whichGenerator_[i];
#ifdef CONFLICT_CUTS
assert (iGenerator>=0);
#endif
if (iGenerator>=0)
iGenerator=iGenerator%10000;
if (iGenerator >= 0 && iGenerator < numberCutGenerators_)
generator_[iGenerator]->incrementNumberCutsActive();
}
}
}
}
#ifdef CHECK_CUT_COUNTS
if (feasible) {
CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
printf("solveWithCuts: Number of rows at end (only active cuts) %d\n",
numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_) ;
basis->print() ;
delete basis;
}
#endif
#ifdef CHECK_KNOWN_SOLUTION
if (onOptimalPath && (solver_->isDualObjectiveLimitReached()||
!feasible)) {
printf("help\n");
}
#endif
#ifdef CBC_DEBUG
if (onOptimalPath && !solver_->isDualObjectiveLimitReached())
assert(feasible) ;
#endif
# ifdef COIN_HAS_CLP
if (clpSolver)
clpSolver->setSpecialOptions(saveClpOptions);
# endif
#ifdef CBC_THREAD
// Get rid of all threaded stuff
if (master) {
master->stopThreads(0);
delete master;
}
#endif
// make sure pointers are up to date
setPointers(solver_);
return feasible ;
}
// Generate one round of cuts - serial mode
int
CbcModel::serialCuts(OsiCuts & theseCuts, CbcNode * node, OsiCuts & slackCuts, int lastNumberCuts)
{
/*
Is it time to scan the cuts in order to remove redundant cuts? If so, set
up to do it.
*/
int fullScan = 0 ;
if ((numberNodes_ % SCANCUTS) == 0 || (specialOptions_&256) != 0) {
fullScan = 1 ;
if (!numberNodes_ || (specialOptions_&256) != 0)
fullScan = 2;
specialOptions_ &= ~256; // mark as full scan done
}
# if 0 //def COIN_HAS_CLP
// check basis
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
ClpSimplex * simplex = clpSolver->getModelPtr();
int numberTotal=simplex->numberRows()+simplex->numberColumns();
int superbasic=0;
for (int i=0;i<numberTotal;i++) {
if (simplex->getStatus(i)==ClpSimplex::superBasic)
superbasic++;
}
if (superbasic) {
printf("%d superbasic!\n",superbasic);
clpSolver->resolve();
superbasic=0;
for (int i=0;i<numberTotal;i++) {
if (simplex->getStatus(i)==ClpSimplex::superBasic)
superbasic++;
}
assert (!superbasic);
}
}
# endif
int switchOff = (!doCutsNow(1) && !fullScan) ? 1 : 0;
int status = 0;
int i;
for (i = 0; i < numberCutGenerators_; i++) {
int numberRowCutsBefore = theseCuts.sizeRowCuts() ;
int numberColumnCutsBefore = theseCuts.sizeColCuts() ;
int numberRowCutsAfter = numberRowCutsBefore;
int numberColumnCutsAfter = numberColumnCutsBefore;
/*printf("GEN %d %s switches %d\n",
i,generator_[i]->cutGeneratorName(),
generator_[i]->switches());*/
bool generate = generator_[i]->normal();
// skip if not optimal and should be (maybe a cut generator has fixed variables)
if (generator_[i]->howOften() == -100 ||
(generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable())
|| generator_[i]->switchedOff())
generate = false;
if (switchOff&&!generator_[i]->mustCallAgain()) {
// switch off if default
if (generator_[i]->howOften() == 1 && generator_[i]->whatDepth() < 0) {
generate = false;
} else if (currentDepth_ > -10 && switchOff == 2) {
generate = false;
}
}
if (generator_[i]->whetherCallAtEnd())
generate=false;
const OsiRowCutDebugger * debugger = NULL;
bool onOptimalPath = false;
if (generate) {
bool mustResolve =
generator_[i]->generateCuts(theseCuts, fullScan, solver_, node) ;
numberRowCutsAfter = theseCuts.sizeRowCuts() ;
if (fullScan && generator_[i]->howOften() == 1000000 + SCANCUTS_PROBING) {
CglProbing * probing =
dynamic_cast<CglProbing*>(generator_[i]->generator());
if (probing && (numberRowCutsBefore < numberRowCutsAfter ||
numberColumnCutsBefore < theseCuts.sizeColCuts())) {
// switch on
generator_[i]->setHowOften(1);
}
}
if (numberRowCutsBefore < numberRowCutsAfter &&
generator_[i]->mustCallAgain() && status >= 0)
/*printf("%s before %d after %d must %c atend %c off %c endmode %c\n",
generator_[i]->cutGeneratorName(),
numberRowCutsBefore,numberRowCutsAfter,
generator_[i]->mustCallAgain() ? 'Y': 'N',
generator_[i]->whetherCallAtEnd() ? 'Y': 'N',
generator_[i]->switchedOff() ? 'Y': 'N',
generator_[i]->whetherInMustCallAgainMode() ? 'Y': 'N');*/
if (numberRowCutsBefore < numberRowCutsAfter &&
generator_[i]->mustCallAgain() && status >= 0)
status = 1 ; // say must go round
// Check last cut to see if infeasible
/*
The convention is that if the generator proves infeasibility, it should
return as its last cut something with lb > ub.
*/
if (numberRowCutsBefore < numberRowCutsAfter) {
const OsiRowCut * thisCut = theseCuts.rowCutPtr(numberRowCutsAfter - 1) ;
if (thisCut->lb() > thisCut->ub()) {
status = -1; // sub-problem is infeasible
break;
}
}
#ifdef CBC_DEBUG
{
int k ;
for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
OsiRowCut thisCut = theseCuts.rowCut(k) ;
/* check size of elements.
We can allow smaller but this helps debug generators as it
is unsafe to have small elements */
int n = thisCut.row().getNumElements();
const int * column = thisCut.row().getIndices();
const double * element = thisCut.row().getElements();
//assert (n);
for (int i = 0; i < n; i++) {
double value = element[i];
assert(fabs(value) > 1.0e-12 && fabs(value) < 1.0e20);
}
}
}
#endif
if (mustResolve /*|| (specialOptions_&1) != 0*/) {
int returnCode = resolve(node ? node->nodeInfo() : NULL, 2);
if (returnCode == 0)
status = -1;
if (returnCode < 0 && !status)
status = 2;
if ((specialOptions_&1) != 0) {
debugger = solver_->getRowCutDebugger() ;
if (debugger)
onOptimalPath = (debugger->onOptimalPath(*solver_)) ;
else
onOptimalPath = false;
if (onOptimalPath && !solver_->isDualObjectiveLimitReached())
assert(status >= 0) ;
}
if (status < 0)
break ;
}
}
numberRowCutsAfter = theseCuts.sizeRowCuts() ;
numberColumnCutsAfter = theseCuts.sizeColCuts() ;
if ((specialOptions_&1) != 0) {
if (onOptimalPath) {
int k ;
for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
OsiRowCut thisCut = theseCuts.rowCut(k) ;
if (debugger->invalidCut(thisCut)) {
solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
solver_->writeMpsNative("badCut.mps", NULL, NULL, 2);
printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n",
i, generator_[i]->cutGeneratorName(), k - numberRowCutsBefore);
const double *lower = getColLower() ;
const double *upper = getColUpper() ;
int numberColumns = solver_->getNumCols();
if (numberColumns < 200) {
for (int i = 0; i < numberColumns; i++)
printf("%d bounds %g,%g\n", i, lower[i], upper[i]);
}
abort();
}
assert(!debugger->invalidCut(thisCut)) ;
}
}
}
/*
The cut generator has done its thing, and maybe it generated some
cuts. Do a bit of bookkeeping: load
whichGenerator[i] with the index of the generator responsible for a cut,
and place cuts flagged as global in the global cut pool for the model.
lastNumberCuts is the sum of cuts added in previous iterations; it's the
offset to the proper starting position in whichGenerator.
*/
int numberBefore =
numberRowCutsBefore + lastNumberCuts ;
int numberAfter =
numberRowCutsAfter + lastNumberCuts ;
// possibly extend whichGenerator
resizeWhichGenerator(numberBefore, numberAfter);
int j ;
/*
Look for numerically unacceptable cuts.
*/
bool dodgyCuts = false;
for (j = numberRowCutsBefore; j < numberRowCutsAfter; j++) {
const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ;
if (thisCut->lb() > 1.0e10 || thisCut->ub() < -1.0e10) {
dodgyCuts = true;
break;
}
whichGenerator_[numberBefore++] = i+20000 ;
if (!numberNodes_||generator_[i]->globalCuts())
whichGenerator_[numberBefore-1]=i+10000;
if (thisCut->lb() > thisCut->ub())
status = -1; // sub-problem is infeasible
if (thisCut->globallyValid()||!numberNodes_) {
// add to global list
OsiRowCut newCut(*thisCut);
newCut.setGloballyValid(true);
newCut.mutableRow().setTestForDuplicateIndex(false);
globalCuts_.addCutIfNotDuplicate(newCut) ;
whichGenerator_[numberBefore-1] = i+10000 ;
}
}
if (dodgyCuts) {
for (int k = numberRowCutsAfter - 1; k >= j; k--) {
const OsiRowCut * thisCut = theseCuts.rowCutPtr(k) ;
if (thisCut->lb() > thisCut->ub())
status = -1; // sub-problem is infeasible
if (thisCut->lb() > 1.0e10 || thisCut->ub() < -1.0e10)
theseCuts.eraseRowCut(k);
}
numberRowCutsAfter = theseCuts.sizeRowCuts() ;
for (; j < numberRowCutsAfter; j++) {
const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ;
whichGenerator_[numberBefore++] = i+20000 ;
if (!numberNodes_||generator_[i]->globalCuts())
whichGenerator_[numberBefore-1]=i+10000;
if (thisCut->globallyValid()) {
// add to global list
OsiRowCut newCut(*thisCut);
newCut.setGloballyValid(true);
newCut.mutableRow().setTestForDuplicateIndex(false);
globalCuts_.addCutIfNotDuplicate(newCut) ;
whichGenerator_[numberBefore-1]=i+10000;
}
}
}
for (j = numberColumnCutsBefore; j < numberColumnCutsAfter; j++) {
//whichGenerator_[numberBefore++] = i ;
const OsiColCut * thisCut = theseCuts.colCutPtr(j) ;
if (thisCut->globallyValid()) {
// fix
makeGlobalCut(thisCut);
}
}
}
/*
End of loop to run each cut generator.
*/
if (status >= 0) {
// delete null cuts
int nCuts = theseCuts.sizeRowCuts() ;
int k ;
for (k = nCuts - 1; k >= 0; k--) {
const OsiRowCut * thisCut = theseCuts.rowCutPtr(k) ;
int n = thisCut->row().getNumElements();
if (!n)
theseCuts.eraseRowCut(k);
}
}
// Add in any violated saved cuts
if (!theseCuts.sizeRowCuts() && !theseCuts.sizeColCuts()) {
int numberOld = theseCuts.sizeRowCuts() + lastNumberCuts;
int numberCuts = slackCuts.sizeRowCuts() ;
int i;
// possibly extend whichGenerator
resizeWhichGenerator(numberOld, numberOld + numberCuts);
double primalTolerance;
solver_->getDblParam(OsiPrimalTolerance, primalTolerance) ;
for ( i = 0; i < numberCuts; i++) {
const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ;
if (thisCut->violated(cbcColSolution_) > 100.0*primalTolerance) {
if (messageHandler()->logLevel() > 2)
printf("Old cut added - violation %g\n",
thisCut->violated(cbcColSolution_)) ;
whichGenerator_[numberOld++] = 20097;
theseCuts.insert(*thisCut) ;
}
}
}
return status;
}
/*
Remove slack cuts. We obtain a basis and scan it. Cuts with basic slacks
are purged. If any cuts are purged, resolve() is called to restore the
solution held in the solver. If resolve() pivots, there's the possibility
that a slack may be pivoted in (trust me :-), so the process iterates.
Setting allowResolve to false will suppress reoptimisation (but see note
below).
At the level of the solver's constraint system, loose cuts are really
deleted. There's an implicit assumption that deleteRows will also update
the active basis in the solver.
At the level of nodes and models, it's more complicated.
New cuts exist only in the collection of cuts passed as a parameter. They
are deleted from the collection and that's the end of them.
Older cuts have made it into addedCuts_. Two separate actions are needed.
The reference count for the CbcCountRowCut object is decremented. If this
count falls to 0, the node which owns the cut is located, the reference to
the cut is removed, and then the cut object is destroyed (courtesy of the
CbcCountRowCut destructor). We also need to set the addedCuts_ entry to
NULL. This is important so that when it comes time to generate basis edits
we can tell this cut was dropped from the basis during processing of the
node.
NOTE: In general, it's necessary to call resolve() after purging slack
cuts. Deleting constraints constitutes a change in the problem, and
an OSI is not required to maintain a valid solution when the problem
is changed. But ... it's really useful to maintain the active basis,
and the OSI is supposed to do that. (Yes, it's splitting hairs.) In
some places, it's possible to know that the solution will never be
consulted after this call, only the basis. (E.g., this routine is
called as a last act before generating info to place the node in the
live set.) For such use, set allowResolve to false.
TODO: No real harm would be done if we just ignored the rare occasion when
the call to resolve() pivoted a slack back into the basis. It's a
minor inefficiency, at worst. But it does break assertions which
check that there are no loose cuts in the basis. It might be better
to remove the assertions.
*/
int
CbcModel::takeOffCuts (OsiCuts &newCuts,
bool allowResolve, OsiCuts * saveCuts,
int numberNewCuts, const OsiRowCut ** addedCuts)
{ // int resolveIterations = 0 ;
int numberDropped = 0;
int firstOldCut = numberRowsAtContinuous_ ;
int totalNumberCuts = numberNewCuts_ + numberOldActiveCuts_ ;
assert (numberRowsAtContinuous_+totalNumberCuts==
solver_->getNumRows());
int *solverCutIndices = new int[totalNumberCuts] ;
int *newCutIndices = new int[numberNewCuts_] ;
const CoinWarmStartBasis* ws ;
CoinWarmStartBasis::Status status ;
//#define COIN_HAS_CLP_KEEP_STATUS
#ifdef COIN_HAS_CLP_KEEP_STATUS
int problemStatus=-1;
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver)
problemStatus=clpSolver->getModelPtr()->status();
#endif
bool needPurge = true ;
/*
The outer loop allows repetition of purge in the event that reoptimisation
changes the basis. To start an iteration, clear the deletion counts and grab
the current basis.
*/
while (needPurge) {
int numberNewToDelete = 0 ;
int numberOldToDelete = 0 ;
int i ;
int kCut=0;
ws = dynamic_cast<const CoinWarmStartBasis*>(solver_->getWarmStart()) ;
/*
Scan the basis entries of the old cuts generated prior to this round of cut
generation. Loose cuts are `removed' by decrementing their reference count
and setting the addedCuts_ entry to NULL. (If the reference count falls to
0, they're really deleted. See CbcModel and CbcCountRowCut doc'n for
principles of cut handling.)
*/
int oldCutIndex = 0 ;
if (numberOldActiveCuts_) {
lockThread();
for (i = 0 ; i < numberOldActiveCuts_ ; i++) {
status = ws->getArtifStatus(i + firstOldCut) ;
while (!addedCuts_[oldCutIndex]) oldCutIndex++ ;
assert(oldCutIndex < currentNumberCuts_) ;
// always leave if from nextRowCut_
if (status == CoinWarmStartBasis::basic &&
(addedCuts_[oldCutIndex]->effectiveness() <= 1.0e10 ||
addedCuts_[oldCutIndex]->canDropCut(solver_, i + firstOldCut))) {
solverCutIndices[numberOldToDelete++] = i + firstOldCut ;
if (saveCuts) {
// send to cut pool
OsiRowCut * slackCut = addedCuts_[oldCutIndex];
if (slackCut->effectiveness() != -1.234) {
slackCut->setEffectiveness(-1.234);
slackCut->setGloballyValid();
saveCuts->insert(*slackCut);
}
}
if (addedCuts_[oldCutIndex]->decrement() == 0)
delete addedCuts_[oldCutIndex] ;
addedCuts_[oldCutIndex] = NULL ;
oldCutIndex++ ;
} else {
int iGenerator = addedCuts_[oldCutIndex]->whichCutGenerator();
if (iGenerator==-1)
iGenerator=100;
whichGenerator_[kCut++] = iGenerator ;
oldCutIndex++;
}
}
unlockThread();
}
/*
Scan the basis entries of the new cuts generated with this round of cut
generation. At this point, newCuts is the only record of the new cuts, so
when we delete loose cuts from newCuts, they're really gone. newCuts is a
vector, so it's most efficient to compress it (eraseRowCut) from back to
front.
*/
int firstNewCut = firstOldCut + numberOldActiveCuts_ ;
int nCuts = newCuts.sizeRowCuts();
for (i = 0 ; i < nCuts ; i++) {
status = ws->getArtifStatus(i + firstNewCut) ;
if (status == CoinWarmStartBasis::basic &&
/*whichGenerator_[i]!=-2*/newCuts.rowCutPtr(i)->effectiveness() < 1.0e20) {
solverCutIndices[numberNewToDelete+numberOldToDelete] = i + firstNewCut ;
newCutIndices[numberNewToDelete++] = i ;
} else { // save which generator did it
// 20098 means branch cut! assert (whichGenerator_[i]!=20098); // ?? what if it is - memory leak?
whichGenerator_[kCut++] = whichGenerator_[i] ;
}
}
int baseRow = firstNewCut + nCuts;
//OsiRowCut ** mutableAdded = const_cast<OsiRowCut **>(addedCuts);
int numberTotalToDelete = numberNewToDelete + numberOldToDelete;
for (i = 0 ; i < numberNewCuts ; i++) {
status = ws->getArtifStatus(i + baseRow) ;
if (status != CoinWarmStartBasis::basic ||
/*whichGenerator_[i+nCuts]==-2*/addedCuts[i]->effectiveness() >= 1.0e20) {
newCuts.insert(*addedCuts[i]) ;
//newCuts.insert(mutableAdded[i]) ;
//mutableAdded[i]=NULL;
//if (status == CoinWarmStartBasis::basic&&whichGenerator_[i]!=-2) {
// save which generator did it
//whichGenerator_[k++] = whichGenerator_[i+nCuts] ;
//}
} else {
solverCutIndices[numberTotalToDelete++] = i + baseRow ;
}
}
numberNewCuts = 0;
numberNewCuts_ = newCuts.sizeRowCuts();
delete ws ;
for (i = numberNewToDelete - 1 ; i >= 0 ; i--) {
int iCut = newCutIndices[i] ;
if (saveCuts) {
// send to cut pool
OsiRowCut * slackCut = newCuts.rowCutPtrAndZap(iCut);
if (slackCut->effectiveness() != -1.234) {
slackCut->setEffectiveness(-1.234);
slackCut->setGloballyValid();
saveCuts->insert(slackCut);
} else {
delete slackCut;
}
} else {
newCuts.eraseRowCut(iCut) ;
}
}
/*
Did we delete anything? If so, delete the cuts from the constraint system
held in the solver and reoptimise unless we're forbidden to do so. If the
call to resolve() results in pivots, there's the possibility we again have
basic slacks. Repeat the purging loop.
*/
if (numberTotalToDelete > 0 ) {
solver_->deleteRows(numberTotalToDelete,
solverCutIndices) ;
numberDropped += numberTotalToDelete;
numberNewCuts_ -= numberNewToDelete ;
assert (numberNewCuts_ == newCuts.sizeRowCuts());
numberOldActiveCuts_ -= numberOldToDelete ;
# ifdef CBC_DEBUG
printf("takeOffCuts: purged %d+%d cuts\n", numberOldToDelete,
numberNewToDelete );
# endif
if (allowResolve) {
phase_ = 3;
// can do quick optimality check
int easy = 2;
solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ;
resolve(solver_) ;
setPointers(solver_);
solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
if (solver_->getIterationCount() == 0) {
needPurge = false ;
}
# ifdef CBC_DEBUG
else {
printf( "Repeating purging loop. %d iters.\n",
solver_->getIterationCount());
}
# endif
} else {
needPurge = false ;
}
} else {
needPurge = false ;
}
}
#ifdef COIN_HAS_CLP_KEEP_STATUS
// need to check further that only zero duals dropped
if (clpSolver) // status may have got to -1
clpSolver->getModelPtr()->setProblemStatus(problemStatus);
#endif
/*
Clean up and return.
*/
delete [] solverCutIndices ;
delete [] newCutIndices ;
return numberDropped;
}
/*
Return values:
1: feasible
0: infeasible
-1: feasible and finished (do no more work on this subproblem)
*/
int
CbcModel::resolve(CbcNodeInfo * parent, int whereFrom,
double * saveSolution,
double * saveLower,
double * saveUpper)
{
#ifdef CBC_STATISTICS
void cbc_resolve_check(const OsiSolverInterface * solver);
cbc_resolve_check(solver_);
#endif
bool onOptimalPath = false;
if ((specialOptions_&1) != 0) {
const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
if (debugger) {
onOptimalPath = true;
printf("On optimal path d\n") ;
}
}
// We may have deliberately added in violated cuts - check to avoid message
int iRow;
int numberRows = solver_->getNumRows();
const double * rowLower = solver_->getRowLower();
const double * rowUpper = solver_->getRowUpper();
bool feasible = true;
for (iRow = numberRowsAtContinuous_; iRow < numberRows; iRow++) {
if (rowLower[iRow] > rowUpper[iRow] + 1.0e-8)
feasible = false;
}
// Can't happen if strong branching as would have been found before
if ((!numberStrong_||(moreSpecialOptions_&1073741824)!=0)
&& numberObjects_ > numberIntegers_) {
int iColumn;
int numberColumns = solver_->getNumCols();
const double * columnLower = solver_->getColLower();
const double * columnUpper = solver_->getColUpper();
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if (columnLower[iColumn] > columnUpper[iColumn] + 1.0e-5)
feasible = false;
}
}
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
#endif
/*
Reoptimize. Consider the possibility that we should fathom on bounds. But be
careful --- where the objective takes on integral values, we may want to keep
a solution where the objective is right on the cutoff.
*/
if (feasible) {
int nTightened = 0;
#ifdef COIN_HAS_CLP
// Pierre pointed out that this is not valid for all solvers
// so just do if Clp
if ((specialOptions_&1) != 0 && onOptimalPath) {
solver_->writeMpsNative("before-tighten.mps", NULL, NULL, 2);
}
if (clpSolver && (!currentNode_ || (currentNode_->depth()&2) != 0) &&
!solverCharacteristics_->solutionAddsCuts() &&
(moreSpecialOptions_&1073741824)==0)
nTightened = clpSolver->tightenBounds();
if (nTightened) {
//printf("%d bounds tightened\n",nTightened);
if ((specialOptions_&1) != 0 && onOptimalPath) {
const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
if (!debugger) {
// tighten did something???
solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
solver_->writeMpsNative("infeas4.mps", NULL, NULL, 2);
printf("Not on optimalpath aaaa\n");
//abort();
onOptimalPath = false;
}
}
}
#endif
if (nTightened >= 0) {
resolve(solver_) ;
numberIterations_ += solver_->getIterationCount() ;
feasible = (solver_->isProvenOptimal() &&
!solver_->isDualObjectiveLimitReached()) ;
if (feasible) {
// double check
double testValue = solver_->getObjSense() *
solver_->getObjValue();
//double cutoff = getCutoff();
if (bestObjective_ - getCutoffIncrement() < testValue) {
#if CBC_USEFUL_PRINTING>1
double value ;
solver_->getDblParam(OsiDualObjectiveLimit, value) ;
printf("Should cutoff as obj %.18g, best %.18g, inc %.18g - solver cutoff %.18g model cutoff %.18g\n",
testValue, bestObjective_, getCutoffIncrement(),
value, getCutoff());
#endif
feasible = false;
}
} else if (solver_->isAbandoned()) {
setMaximumSeconds(-COIN_DBL_MAX);
}
#ifdef COIN_HAS_CLP
if (clpSolver && feasible && !numberNodes_ && false) {
double direction = solver_->getObjSense() ;
double tolerance;
solver_->getDblParam(OsiDualTolerance, tolerance) ;
double primalTolerance;
solver_->getDblParam(OsiPrimalTolerance, primalTolerance) ;
const double *lower = solver_->getColLower() ;
const double *upper = solver_->getColUpper() ;
const double *solution = solver_->getColSolution() ;
const double *reducedCost = solver_->getReducedCost() ;
ClpSimplex * clpSimplex = clpSolver->getModelPtr();
double * rowLower = clpSimplex->rowLower();
double * rowUpper = clpSimplex->rowUpper();
int numberRows = clpSimplex->numberRows();
double * saveRowLower = CoinCopyOfArray(rowLower, numberRows);
double * saveRowUpper = CoinCopyOfArray(rowUpper, numberRows);
{
const double * dual = clpSimplex->dualRowSolution();
const double * rowActivity = clpSimplex->primalRowSolution();
for (int iRow = 0 ; iRow < numberRows ; iRow++) {
double djValue = direction * dual[iRow] ;
double lowerValue = rowLower[iRow];
double upperValue = rowUpper[iRow];
if (rowActivity[iRow] < lowerValue + primalTolerance && djValue > tolerance) {
rowUpper[iRow] = lowerValue;
assert (clpSimplex->getRowStatus(iRow) != ClpSimplex::basic);
} else if (rowActivity[iRow] > upperValue - primalTolerance && djValue < -tolerance) {
rowLower[iRow] = upperValue;
assert (clpSimplex->getRowStatus(iRow) != ClpSimplex::basic);
}
}
}
int numberColumns = solver_->getNumCols();
double * objective = clpSimplex->objective();
double * saveObj = CoinCopyOfArray(objective, numberColumns);
double objValue = 0.01;
bool someFree = false;
for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
double djValue = direction * reducedCost[iColumn] ;
double lowerValue = lower[iColumn];
double upperValue = upper[iColumn];
if (solution[iColumn] < lowerValue + primalTolerance && djValue > tolerance) {
objective[iColumn] = 1.0e8 * direction;
assert (clpSimplex->getColumnStatus(iColumn) != ClpSimplex::basic);
} else if (solution[iColumn] > upperValue - primalTolerance && djValue < -tolerance) {
objective[iColumn] = -1.0e8 * direction;
assert (clpSimplex->getColumnStatus(iColumn) != ClpSimplex::basic);
} else if (lowerValue > -1.0e20 || upperValue < 1.0e20) {
assert (fabs(djValue) <= tolerance);
if (fabs(lowerValue) < fabs(upperValue))
objective[iColumn] = objValue * direction;
else
objective[iColumn] = -objValue * direction;
objValue += 0.01;
} else {
objective[iColumn] = 0.0;
someFree = true;
}
}
if (!someFree)
clpSimplex->primal(1);
memcpy(objective, saveObj, numberColumns*sizeof(double));
delete [] saveObj;
memcpy(rowLower, saveRowLower, numberRows*sizeof(double));
delete [] saveRowLower;
memcpy(rowUpper, saveRowUpper, numberRows*sizeof(double));
delete [] saveRowUpper;
if (!someFree) {
clpSimplex->primal(1);
//assert (clpSimplex->numberIterations()<10);
}
//clpSimplex->writeMps("xx");
//clpSimplex->primal(1);
clpSolver->setWarmStart(NULL);
}
#endif
if ((specialOptions_&1) != 0 && onOptimalPath) {
if (!solver_->getRowCutDebugger()) {
// tighten did something???
solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
solver_->writeMpsNative("infeas4.mps", NULL, NULL, 2);
//assert (solver_->getRowCutDebugger()) ;
printf("Not on optimalpath e\n");
//abort();
}
}
} else {
feasible = false;
}
}
if (0 && feasible) {
const double * lb = solver_->getColLower();
const double * ub = solver_->getColUpper();
const double * x = solver_->getColSolution();
const double * dj = solver_->getReducedCost();
int numberColumns = solver_->getNumCols();
for (int i = 0; i < numberColumns; i++) {
if (dj[i] > 1.0e-4 && ub[i] - lb[i] > 1.0e-4 && x[i] > lb[i] + 1.0e-4)
printf("error %d %g %g %g %g\n", i, dj[i], lb[i], x[i], ub[i]);
if (dj[i] < -1.0e-4 && ub[i] - lb[i] > 1.0e-4 && x[i] < ub[i] - 1.0e-4)
printf("error %d %g %g %g %g\n", i, dj[i], lb[i], x[i], ub[i]);
}
}
if (false && !feasible && continuousObjective_ < -1.0e30) {
// at root node - double double check
bool saveTakeHint;
OsiHintStrength saveStrength;
solver_->getHintParam(OsiDoDualInResolve, saveTakeHint, saveStrength);
if (saveTakeHint || saveStrength == OsiHintIgnore) {
solver_->setHintParam(OsiDoDualInResolve, false, OsiHintDo) ;
resolve(solver_);
solver_->setHintParam(OsiDoDualInResolve, saveTakeHint, saveStrength);
numberIterations_ += solver_->getIterationCount() ;
feasible = solver_->isProvenOptimal();
// solver_->writeMps("infeas");
}
}
#ifdef JJF_ZERO
if (cutModifier_ && feasible && !solverCharacteristics_->solutionAddsCuts()) {
//double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
double cutoff ;
solver_->getDblParam(OsiDualObjectiveLimit, cutoff) ;
double distance = fabs(cutoff - solver_->getObjValue());
if (distance < 10.0*trueIncrement) {
double offset;
solver_->getDblParam(OsiObjOffset, offset);
double objFixedValue = -offset;
double objValue = 0.0;
double direction = solver_->getObjSense();
const double * solution = solver_->getColSolution();
const double * objective = solver_->getObjCoefficients();
const double * columnLower = solver_->getColLower();
const double * columnUpper = solver_->getColUpper();
int numberColumns = solver_->getNumCols();
int increment = 0 ;
double multiplier = 1.0 / trueIncrement;
int bigIntegers = 0; // Count of large costs which are integer
for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
double value = solution[iColumn];
// make sure clean
value = CoinMin(value, columnUpper[iColumn]);
value = CoinMax(value, columnLower[iColumn]);
double cost = direction * objective[iColumn];
if (cost) {
if (columnLower[iColumn] < columnUpper[iColumn]) {
objValue += value * cost;
value = fabs(cost) * multiplier ;
if (value < 2.1e9) {
int nearest = static_cast<int> (floor(value + 0.5)) ;
assert (fabs(value - floor(value + 0.5)) < 1.0e-8);
if (!increment)
increment = nearest ;
else
increment = gcd(increment, nearest) ;
} else {
// large value - may still be multiple of 1.0
value = fabs(objective[iColumn]);
assert(fabs(value - floor(value + 0.5)) < 1.0e-8);
bigIntegers++;
}
} else {
// fixed
objFixedValue += value * cost;
}
}
}
if (increment) {
double value = increment ;
value /= multiplier ;
if (value > trueIncrement) {
double x = objValue / value;
x = ceil(x - 1.0e-5);
x *= value;
//printf("fixed %g, variable %g -> %g, sum %g - cutoff %g\n",
// objFixedValue,objValue,x,x+objFixedValue,cutoff);
x += objFixedValue;
if (x > cutoff + 1.0e-5*fabs(cutoff) + 1.0e-5) {
//printf("Node cutoff\n");
feasible = false;
}
} else {
value = trueIncrement;
double x = objValue / value;
x = ceil(x - 1.0e-5);
x *= value;
x += objFixedValue;
if (x > cutoff + 1.0e-5*fabs(cutoff) + 1.0e-5) {
//printf("Node cutoff\n");
feasible = false;
}
}
}
}
}
#endif
setPointers(solver_);
if (feasible && saveSolution) {
// called from CbcNode
assert (saveLower);
assert (saveUpper);
int numberColumns = solver_->getNumCols();
memcpy(saveSolution, solver_->getColSolution(), numberColumns*sizeof(double));
reserveCurrentSolution(saveSolution);
memcpy(saveLower, solver_->getColLower(), numberColumns*sizeof(double));
memcpy(saveUpper, solver_->getColUpper(), numberColumns*sizeof(double));
}
#ifdef COIN_HAS_CLP
if (clpSolver && !feasible) {
// make sure marked infeasible
if (!clpSolver->isProvenDualInfeasible())
clpSolver->getModelPtr()->setProblemStatus(1);
}
#endif
int returnStatus = feasible ? 1 : 0;
if (strategy_) {
/*
Possible returns from status:
-1: no recommendation
0: treat as optimal
1: treat as optimal and finished (no more resolves, cuts, etc.)
2: treat as infeasible.
*/
// user can play clever tricks here
int status = strategy_->status(this, parent, whereFrom);
if (status >= 0) {
if (status == 0)
returnStatus = 1;
else if (status == 1)
returnStatus = -1;
else
returnStatus = 0;
}
}
#if 0
if ((specialOptions_&1) != 0 && onOptimalPath) {
const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
if (!debugger) {
// tighten did something???
solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
solver_->writeMpsNative("infeas4.mps", NULL, NULL, 2);
printf("Not on optimalpath aaaa\n");
//abort();
} else {
printf("Still on optimal path\n");
}
}
#endif
return returnStatus ;
}
/* Set up objects. Only do ones whose length is in range.
If makeEquality true then a new model may be returned if
modifications had to be made, otherwise "this" is returned.
Could use Probing at continuous to extend objects
*/
CbcModel *
CbcModel::findCliques(bool makeEquality,
int atLeastThisMany, int lessThanThis,
int /*defaultValue*/)
{
// No objects are allowed to exist
assert(numberObjects_ == numberIntegers_ || !numberObjects_);
CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow());
int numberRows = solver_->getNumRows();
int numberColumns = solver_->getNumCols();
// We may want to add columns
int numberSlacks = 0;
int * rows = new int[numberRows];
double * element = new double[numberRows];
int iRow;
findIntegers(true);
numberObjects_ = numberIntegers_;
int numberCliques = 0;
OsiObject ** object = new OsiObject * [numberRows];
int * which = new int[numberIntegers_];
char * type = new char[numberIntegers_];
int * lookup = new int[numberColumns];
int i;
for (i = 0; i < numberColumns; i++)
lookup[i] = -1;
for (i = 0; i < numberIntegers_; i++)
lookup[integerVariable_[i]] = i;
// Statistics
int totalP1 = 0, totalM1 = 0;
int numberBig = 0, totalBig = 0;
int numberFixed = 0;
// Row copy
const double * elementByRow = matrixByRow.getElements();
const int * column = matrixByRow.getIndices();
const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
const int * rowLength = matrixByRow.getVectorLengths();
// Column lengths for slacks
const int * columnLength = solver_->getMatrixByCol()->getVectorLengths();
const double * lower = getColLower();
const double * upper = getColUpper();
const double * rowLower = getRowLower();
const double * rowUpper = getRowUpper();
/*
Scan the rows, looking for individual rows that are clique constraints.
*/
for (iRow = 0; iRow < numberRows; iRow++) {
int numberP1 = 0, numberM1 = 0;
int j;
double upperValue = rowUpper[iRow];
double lowerValue = rowLower[iRow];
bool good = true;
int slack = -1;
/*
Does this row qualify? All variables must be binary and all coefficients
+/- 1.0. Variables with positive coefficients are recorded at the low end of
which, variables with negative coefficients the high end.
*/
for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
int iColumn = column[j];
int iInteger = lookup[iColumn];
if (upper[iColumn] - lower[iColumn] < 1.0e-8) {
// fixed
upperValue -= lower[iColumn] * elementByRow[j];
lowerValue -= lower[iColumn] * elementByRow[j];
continue;
} else if (upper[iColumn] != 1.0 || lower[iColumn] != 0.0) {
good = false;
break;
} else if (iInteger < 0) {
good = false;
break;
} else {
if (columnLength[iColumn] == 1)
slack = iInteger;
}
if (fabs(elementByRow[j]) != 1.0) {
good = false;
break;
} else if (elementByRow[j] > 0.0) {
which[numberP1++] = iInteger;
} else {
numberM1++;
which[numberIntegers_-numberM1] = iInteger;
}
}
int iUpper = static_cast<int> (floor(upperValue + 1.0e-5));
int iLower = static_cast<int> (ceil(lowerValue - 1.0e-5));
/*
What do we have? If the row upper bound is greater than 1-numberM1, this
isn't a clique. If the row upper bound is 1-numberM1, we have the classic
clique (an SOS1 on binary variables, if numberM1 = 0). If the upper bound
equals numberM1, we can fix all variables. If the upper bound is less than
numberM1, we're infeasible.
A similar analysis applies using numberP1 against the lower bound.
*/
int state = 0;
if (upperValue < 1.0e6) {
if (iUpper == 1 - numberM1)
state = 1;
else if (iUpper == -numberM1)
state = 2;
else if (iUpper < -numberM1)
state = 3;
}
if (!state && lowerValue > -1.0e6) {
if (-iLower == 1 - numberP1)
state = -1;
else if (-iLower == -numberP1)
state = -2;
else if (-iLower < -numberP1)
state = -3;
}
/*
What to do? If we learned nothing, move on to the next iteration. If we're
infeasible, we're outta here. If we decided we can fix variables, do it.
*/
if (good && state) {
if (abs(state) == 3) {
// infeasible
numberObjects_ = -1;
break;
} else if (abs(state) == 2) {
// we can fix all
numberFixed += numberP1 + numberM1;
if (state > 0) {
// fix all +1 at 0, -1 at 1
for (i = 0; i < numberP1; i++)
solver_->setColUpper(integerVariable_[which[i]], 0.0);
for (i = 0; i < numberM1; i++)
solver_->setColLower(integerVariable_[which[numberIntegers_-i-1]],
1.0);
} else {
// fix all +1 at 1, -1 at 0
for (i = 0; i < numberP1; i++)
solver_->setColLower(integerVariable_[which[i]], 1.0);
for (i = 0; i < numberM1; i++)
solver_->setColUpper(integerVariable_[which[numberIntegers_-i-1]],
0.0);
}
} else {
/*
And the final case: we have a clique constraint. If it's within the allowed
size range, make a clique object.
*/
int length = numberP1 + numberM1;
if (length >= atLeastThisMany && length < lessThanThis) {
// create object
bool addOne = false;
int objectType;
/*
Choose equality (type 1) or inequality (type 0). If we're forcing equalities,
add a slack.
*/
if (iLower == iUpper) {
objectType = 1;
} else {
if (makeEquality) {
objectType = 1;
element[numberSlacks] = state;
rows[numberSlacks++] = iRow;
addOne = true;
} else {
objectType = 0;
}
}
/*
Record the strong values for the variables. Variables with positive
coefficients force all others when set to 1; variables with negative
coefficients force when set to 0. If the clique is formed against the row
lower bound, convert to the canonical form of a clique against the row
upper bound.
*/
if (state > 0) {
totalP1 += numberP1;
totalM1 += numberM1;
for (i = 0; i < numberP1; i++)
type[i] = 1;
for (i = 0; i < numberM1; i++) {
which[numberP1] = which[numberIntegers_-i-1];
type[numberP1++] = 0;
}
} else {
totalP1 += numberM1;
totalM1 += numberP1;
for (i = 0; i < numberP1; i++)
type[i] = 0;
for (i = 0; i < numberM1; i++) {
which[numberP1] = which[numberIntegers_-i-1];
type[numberP1++] = 1;
}
}
if (addOne) {
// add in slack
which[numberP1] = numberIntegers_ + numberSlacks - 1;
slack = numberP1;
type[numberP1++] = 1;
} else if (slack >= 0) {
for (i = 0; i < numberP1; i++) {
if (which[i] == slack) {
slack = i;
}
}
}
object[numberCliques] = new CbcClique(this, objectType, numberP1,
which, type,
1000000 + numberCliques, slack);
numberCliques++;
} else if (numberP1 + numberM1 >= lessThanThis) {
// too big
numberBig++;
totalBig += numberP1 + numberM1;
}
}
}
}
delete [] which;
delete [] type;
delete [] lookup;
#if COIN_DEVELOP>1
if (numberCliques < 0) {
printf("*** Problem infeasible\n");
} else {
if (numberCliques)
printf("%d cliques of average size %g found, %d P1, %d M1\n",
numberCliques,
(static_cast<double>(totalP1 + totalM1)) / (static_cast<double> (numberCliques)),
totalP1, totalM1);
else
printf("No cliques found\n");
if (numberBig)
printf("%d large cliques ( >= %d) found, total %d\n",
numberBig, lessThanThis, totalBig);
if (numberFixed)
printf("%d variables fixed\n", numberFixed);
}
#endif
/*
If required, augment the constraint matrix with clique slacks. Seems like we
should be able to add the necessary integer objects without a complete
rebuild of existing integer objects, but I'd need to look further to confirm
that (lh, 071219). Finally, add the clique objects.
*/
if (numberCliques > 0 && numberSlacks && makeEquality) {
COIN_DETAIL_PRINT(printf("adding %d integer slacks\n", numberSlacks));
// add variables to make equality rows
int * temp = new int[numberIntegers_+numberSlacks];
memcpy(temp, integerVariable_, numberIntegers_*sizeof(int));
// Get new model
CbcModel * newModel = new CbcModel(*this);
OsiSolverInterface * newSolver = newModel->solver();
for (i = 0; i < numberSlacks; i++) {
temp[i+numberIntegers_] = i + numberColumns;
int iRow = rows[i];
double value = element[i];
double lowerValue = 0.0;
double upperValue = 1.0;
double objValue = 0.0;
CoinPackedVector column(1, &iRow, &value);
newSolver->addCol(column, lowerValue, upperValue, objValue);
// set integer
newSolver->setInteger(numberColumns + i);
if (value > 0)
newSolver->setRowLower(iRow, rowUpper[iRow]);
else
newSolver->setRowUpper(iRow, rowLower[iRow]);
}
// replace list of integers
for (i = 0; i < newModel->numberObjects_; i++)
delete newModel->object_[i];
newModel->numberObjects_ = 0;
delete [] newModel->object_;
newModel->object_ = NULL;
newModel->findIntegers(true); //Set up all integer objects
for (i = 0; i < numberIntegers_; i++) {
newModel->modifiableObject(i)->setPriority(object_[i]->priority());
}
if (originalColumns_) {
// old model had originalColumns
delete [] newModel->originalColumns_;
newModel->originalColumns_ = new int[numberColumns+numberSlacks];
memcpy(newModel->originalColumns_, originalColumns_, numberColumns*sizeof(int));
// mark as not in previous model
for (i = numberColumns; i < numberColumns + numberSlacks; i++)
newModel->originalColumns_[i] = -1;
}
delete [] rows;
delete [] element;
newModel->addObjects(numberCliques, object);
assert (ownObjects_);
for (; i < numberCliques; i++)
delete object[i];
delete [] object;
newModel->synchronizeModel();
return newModel;
} else {
assert (ownObjects_);
if (numberCliques > 0) {
addObjects(numberCliques, object);
for (; i < numberCliques; i++)
delete object[i];
synchronizeModel();
}
delete [] object;
delete [] rows;
delete [] element;
return this;
}
}
// Fill in useful estimates
void
CbcModel::pseudoShadow(int iActive)
{
assert (iActive<2*8*32 && iActive> -3);
if (iActive == -1) {
if (numberNodes_) {
// zero out
for (int i = 0; i < numberObjects_; i++) {
CbcSimpleIntegerDynamicPseudoCost * obj1 =
dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[i]) ;
if (obj1) {
//assert (obj1->downShadowPrice()>0.0);
#define P_FACTOR 1.0
#ifndef JJF_ONE
obj1->setDownShadowPrice(-P_FACTOR*obj1->downShadowPrice());
obj1->setUpShadowPrice(-P_FACTOR*obj1->upShadowPrice());
#else
double pCost;
double sCost;
pCost = obj1->downDynamicPseudoCost();
sCost = P_FACTOR * obj1->downShadowPrice();
if (!obj1->numberTimesDown() || sCost > pCost)
obj1->updateDownDynamicPseudoCost(sCost);
obj1->setDownShadowPrice(0.0);
pCost = obj1->upDynamicPseudoCost();
sCost = P_FACTOR * obj1->upShadowPrice();
if (!obj1->numberTimesUp() || sCost > pCost)
obj1->updateUpDynamicPseudoCost(sCost);
obj1->setUpShadowPrice(0.0);
#endif
}
}
}
return;
}
bool doShadow = false;
if (!iActive || iActive >= 32) {
doShadow = true;
if (iActive >= 32)
iActive -= 32;
}
double * rowWeight = NULL;
double * columnWeight = NULL;
int numberColumns = solver_->getNumCols() ;
int numberRows = solver_->getNumRows() ;
// Column copy of matrix
const double * element = solver_->getMatrixByCol()->getElements();
const int * row = solver_->getMatrixByCol()->getIndices();
const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts();
const int * columnLength = solver_->getMatrixByCol()->getVectorLengths();
const double * dual = solver_->getRowPrice();
const double * solution = solver_->getColSolution();
const double * dj = solver_->getReducedCost();
bool useMax = false;
bool useAlpha = false;
if (iActive) {
// Use Patel and Chinneck ideas
rowWeight = new double [numberRows];
columnWeight = new double [numberColumns];
// add in active constraints
double tolerance = 1.0e-5;
const double *rowLower = getRowLower() ;
const double *rowUpper = getRowUpper() ;
const double *rowActivity = solver_->getRowActivity();
const double * lower = getColLower();
const double * upper = getColUpper();
CoinZeroN(rowWeight, numberRows);
/* 1 A weight 1
2 B weight 1/sum alpha
3 L weight 1/number integer
4 M weight 1/number active integer
7 O weight 1/number integer and use alpha
8 P weight 1/number active integer and use alpha
9 up subtract 8 and use maximum
*/
if (iActive > 8) {
iActive -= 8;
useMax = true;
}
if (iActive > 4) {
iActive -= 4;
useAlpha = true;
}
switch (iActive) {
// A
case 1:
for (int iRow = 0; iRow < numberRows; iRow++) {
if (rowActivity[iRow] > rowUpper[iRow] - tolerance ||
rowActivity[iRow] < rowLower[iRow] + tolerance) {
rowWeight[iRow] = 1.0;
}
}
break;
// B
case 2:
for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
if (upper[iColumn] > lower[iColumn]) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
rowWeight[iRow] += fabs(element[j]);
}
}
}
for (int iRow = 0; iRow < numberRows; iRow++) {
if (rowWeight[iRow])
rowWeight[iRow] = 1.0 / rowWeight[iRow];
}
break;
// L
case 3:
for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) {
int iColumn = integerVariable_[jColumn];
if (upper[iColumn] > lower[iColumn]) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
rowWeight[iRow]++;
}
}
}
for (int iRow = 0; iRow < numberRows; iRow++) {
if (rowWeight[iRow])
rowWeight[iRow] = 1.0 / rowWeight[iRow];
}
break;
// M
case 4:
for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) {
int iColumn = integerVariable_[jColumn];
double value = solution[iColumn];
if (fabs(value - floor(value + 0.5)) > 1.0e-5) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
rowWeight[iRow]++;
}
}
}
for (int iRow = 0; iRow < numberRows; iRow++) {
if (rowWeight[iRow])
rowWeight[iRow] = 1.0 / rowWeight[iRow];
}
break;
}
if (doShadow) {
for (int iRow = 0; iRow < numberRows; iRow++) {
rowWeight[iRow] *= dual[iRow];
}
}
dual = rowWeight;
}
const double *objective = solver_->getObjCoefficients() ;
double direction = solver_->getObjSense();
double * down = new double[numberColumns];
double * up = new double[numberColumns];
double upSum = 1.0e-20;
double downSum = 1.0e-20;
int numberIntegers = 0;
if (doShadow) {
// shadow prices
if (!useMax) {
for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) {
int iColumn = integerVariable_[jColumn];
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
double upValue = 0.0;
double downValue = 0.0;
double value = direction * objective[iColumn];
if (value) {
if (value > 0.0)
upValue += value;
else
downValue -= value;
}
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
value = -dual[iRow];
assert (fabs(dual[iRow]) < 1.0e50);
if (value) {
value *= element[j];
if (value > 0.0)
upValue += value;
else
downValue -= value;
}
}
up[iColumn] = upValue;
down[iColumn] = downValue;
if (solver_->isInteger(iColumn)) {
if (!numberNodes_ && handler_->logLevel() > 1)
printf("%d - up %g down %g cost %g\n",
iColumn, upValue, downValue, objective[iColumn]);
upSum += upValue;
downSum += downValue;
numberIntegers++;
}
}
} else {
for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) {
int iColumn = integerVariable_[jColumn];
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
double upValue = 0.0;
double downValue = 0.0;
double value = direction * objective[iColumn];
if (value) {
if (value > 0.0)
upValue += value;
else
downValue -= value;
}
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
value = -dual[iRow];
if (value) {
value *= element[j];
if (value > 0.0)
upValue = CoinMax(upValue, value);
else
downValue = CoinMax(downValue, -value);
}
}
up[iColumn] = upValue;
down[iColumn] = downValue;
if (solver_->isInteger(iColumn)) {
if (!numberNodes_ && handler_->logLevel() > 1)
printf("%d - up %g down %g cost %g\n",
iColumn, upValue, downValue, objective[iColumn]);
upSum += upValue;
downSum += downValue;
numberIntegers++;
}
}
}
} else {
for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) {
int iColumn = integerVariable_[jColumn];
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
double upValue = 0.0;
double downValue = 0.0;
double value = direction * objective[iColumn];
if (value) {
if (value > 0.0)
upValue += value;
else
downValue -= value;
}
double weight = 0.0;
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
value = -dual[iRow];
double thisWeight = rowWeight[iRow];
if (useAlpha)
thisWeight *= fabs(element[j]);
if (!useMax)
weight += thisWeight;
else
weight = CoinMax(weight, thisWeight);
if (value) {
value *= element[j];
if (value > 0.0)
upValue += value;
else
downValue -= value;
}
}
columnWeight[iColumn] = weight;
// use dj if bigger
double djValue = dj[iColumn];
upValue = CoinMax(upValue, djValue);
downValue = CoinMax(downValue, -djValue);
up[iColumn] = upValue;
down[iColumn] = downValue;
if (solver_->isInteger(iColumn)) {
if (!numberNodes_ && handler_->logLevel() > 1)
printf("%d - dj %g up %g down %g cost %g\n",
iColumn, djValue, upValue, downValue, objective[iColumn]);
upSum += upValue;
downSum += downValue;
numberIntegers++;
}
}
if (numberIntegers) {
double averagePrice = (0.5 * (upSum + downSum)) / static_cast<double>(numberIntegers);
//averagePrice *= 0.1;
averagePrice *= 100.0;
for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
double weight = columnWeight[iColumn];
up[iColumn] += averagePrice * weight;
down[iColumn] += averagePrice * weight;
}
}
}
delete [] rowWeight;
delete [] columnWeight;
if (numberIntegers) {
double smallDown = 0.0001 * (downSum / static_cast<double> (numberIntegers));
double smallUp = 0.0001 * (upSum / static_cast<double> (numberIntegers));
#define PSEUDO_FACTOR 5.0e-1
double pseudoFactor = PSEUDO_FACTOR;
//if (!numberNodes_)
//pseudoFactor=0.0;
for (int i = 0; i < numberObjects_; i++) {
CbcSimpleIntegerDynamicPseudoCost * obj1 =
dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[i]) ;
if (obj1 && obj1->upShadowPrice() >= 0.0) {
int iColumn = obj1->columnNumber();
double upPseudoCost = obj1->upDynamicPseudoCost();
double saveUp = upPseudoCost;
upPseudoCost = CoinMax(pseudoFactor * upPseudoCost, smallUp);
upPseudoCost = CoinMax(upPseudoCost, up[iColumn]);
upPseudoCost = CoinMax(upPseudoCost, 0.001 * down[iColumn]);
obj1->setUpShadowPrice(upPseudoCost);
if (upPseudoCost > saveUp && !numberNodes_ && handler_->logLevel() > 1)
printf("For %d up went from %g to %g\n",
iColumn, saveUp, upPseudoCost);
double downPseudoCost = obj1->downDynamicPseudoCost();
double saveDown = downPseudoCost;
downPseudoCost = CoinMax(pseudoFactor * downPseudoCost, smallDown);
downPseudoCost = CoinMax(downPseudoCost, down[iColumn]);
downPseudoCost = CoinMax(downPseudoCost, 0.001 * up[iColumn]);
obj1->setDownShadowPrice(downPseudoCost);
if (downPseudoCost > saveDown && !numberNodes_ && handler_->logLevel() > 1)
printf("For %d down went from %g to %g\n",
iColumn, saveDown, downPseudoCost);
}
}
}
delete [] down;
delete [] up;
}
/*
Set branching priorities.
Setting integer priorities looks pretty robust; the call to findIntegers
makes sure that SimpleInteger objects are in place. Setting priorities for
other objects is entirely dependent on their existence, and the routine may
quietly fail in several directions.
*/
void
CbcModel::passInPriorities (const int * priorities,
bool ifObject)
{
findIntegers(false);
int i;
if (priorities) {
int i0 = 0;
int i1 = numberObjects_ - 1;
if (ifObject) {
for (i = numberIntegers_; i < numberObjects_; i++) {
object_[i]->setPriority(priorities[i-numberIntegers_]);
}
i0 = numberIntegers_;
} else {
for (i = 0; i < numberIntegers_; i++) {
object_[i]->setPriority(priorities[i]);
}
i1 = numberIntegers_ - 1;
}
messageHandler()->message(CBC_PRIORITY,
messages())
<< i0 << i1 << numberObjects_ << CoinMessageEol ;
}
}
// Delete all object information
void
CbcModel::deleteObjects(bool getIntegers)
{
if (ownObjects_) {
int i;
for (i = 0; i < numberObjects_; i++)
delete object_[i];
delete [] object_;
}
object_ = NULL;
numberObjects_ = 0;
if (getIntegers && ownObjects_)
findIntegers(true);
}
/*!
Ensure all attached objects (OsiObjects, heuristics, and cut
generators) point to this model.
*/
void CbcModel::synchronizeModel()
{
if (!numberObjects_)
return;
int i;
for (i = 0; i < numberHeuristics_; i++)
heuristic_[i]->setModel(this);
for (i = 0; i < numberObjects_; i++) {
CbcObject * obj =
dynamic_cast <CbcObject *>(object_[i]) ;
if (obj) {
obj->setModel(this);
obj->setPosition(i);
}
}
for (i = 0; i < numberCutGenerators_; i++)
generator_[i]->refreshModel(this);
if (!solverCharacteristics_) {
OsiBabSolver * solverCharacteristics = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
if (solverCharacteristics) {
solverCharacteristics_ = solverCharacteristics;
} else {
// replace in solver
OsiBabSolver defaultC;
solver_->setAuxiliaryInfo(&defaultC);
solverCharacteristics_ = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
}
}
solverCharacteristics_->setSolver(solver_);
}
// Fill in integers and create objects
/**
The routine first does a scan to count the number of integer variables.
It then creates an array, integerVariable_, to store the indices of the
integer variables, and an array of `objects', one for each variable.
The scan is repeated, this time recording the index of each integer
variable in integerVariable_, and creating an CbcSimpleInteger object that
contains information about the integer variable. Initially, this is just
the index and upper & lower bounds.
\todo
Note the assumption in cbc that the first numberIntegers_ objects are
CbcSimpleInteger. In particular, the code which handles the startAgain
case assumes that if the object_ array exists it can simply replace the first
numberInteger_ objects. This is arguably unsafe.
I am going to re-order if necessary
*/
void
CbcModel::findIntegers(bool startAgain, int type)
{
assert(solver_);
/*
No need to do this if we have previous information, unless forced to start
over.
*/
if (numberIntegers_ && !startAgain && object_)
return;
/*
Clear out the old integer variable list, then count the number of integer
variables.
*/
delete [] integerVariable_;
integerVariable_ = NULL;
numberIntegers_ = 0;
int numberColumns = getNumCols();
int iColumn;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if (isInteger(iColumn))
numberIntegers_++;
}
// Find out how many old non-integer objects there are
int nObjects = 0;
OsiObject ** oldObject = object_;
int iObject;
// also see where old ones were
char * mark = new char[numberColumns];
CoinZeroN(mark, numberColumns);
int iPriority = -100000;
for (iObject = 0; iObject < numberObjects_; iObject++) {
iPriority = CoinMax(iPriority, object_[iObject]->priority());
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(oldObject[iObject]) ;
if (obj) {
int iColumn = obj->columnNumber();
if (iColumn >= 0 && iColumn < numberColumns)
mark[iColumn] = 1;
delete oldObject[iObject];
} else {
oldObject[nObjects++] = oldObject[iObject];
}
}
// See if there any SOS
#ifdef COIN_HAS_CLP
if (!nObjects) {
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver && (clpSolver->numberSOS() || clpSolver->numberObjects())) {
// deal with sos
const CoinSet * setInfo = clpSolver->setInfo();
int numberSOS = clpSolver->numberSOS();
if (numberSOS) {
nObjects = 0;
delete [] oldObject;
oldObject = new OsiObject * [numberSOS];
for (int i = 0; i < numberSOS; i++) {
int type = setInfo[i].setType();
int n = setInfo[i].numberEntries();
const int * which = setInfo[i].which();
const double * weights = setInfo[i].weights();
oldObject[nObjects++] = new CbcSOS(this, n, which, weights, i, type);
}
} else {
// objects - only works with SOS at present
int numberObjects = clpSolver->numberObjects();
nObjects = 0;
delete [] oldObject;
oldObject = new OsiObject * [numberObjects];
OsiObject ** osiObjects = clpSolver->objects();
for (int i = 0; i < numberObjects; i++) {
OsiSOS * obj =
dynamic_cast <OsiSOS *>(osiObjects[i]) ;
if (obj) {
int type = obj->setType();
int n = obj->numberMembers();
const int * which = obj->members();
const double * weights = obj->weights();
oldObject[nObjects++] = new CbcSOS(this, n, which, weights, i, type);
}
}
}
}
}
#endif
/*
Found any? Allocate an array to hold the indices of the integer variables.
Make a large enough array for all objects
*/
delete [] integerVariable_;
object_ = new OsiObject * [numberIntegers_+nObjects];
numberObjects_ = numberIntegers_ + nObjects;
integerVariable_ = new int [numberIntegers_];
/*
Walk the variables again, filling in the indices and creating objects for
the integer variables. Initially, the objects hold the index and upper &
lower bounds.
*/
numberIntegers_ = 0;
if (type == 2)
continuousPriority_ = iPriority + 1;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
if (isInteger(iColumn)) {
if (!type) {
object_[numberIntegers_] =
new CbcSimpleInteger(this, iColumn);
} else if (type == 1) {
object_[numberIntegers_] =
new CbcSimpleIntegerPseudoCost(this, iColumn, 0.3);
} else if (type == 2) {
object_[numberIntegers_] =
new CbcSimpleInteger(this, iColumn);
if (mark[iColumn]) {
// could up priority on costs if all costs same??
} else {
object_[numberIntegers_]->setPriority(iPriority + 1);
}
}
integerVariable_[numberIntegers_++] = iColumn;
}
}
delete [] mark;
// Now append other objects
memcpy(object_ + numberIntegers_, oldObject, nObjects*sizeof(OsiObject *));
// Delete old array (just array)
delete [] oldObject;
if (!numberObjects_)
handler_->message(CBC_NOINT, messages_) << CoinMessageEol ;
}
/* If numberBeforeTrust >0 then we are going to use CbcBranchDynamic.
Scan and convert CbcSimpleInteger objects
*/
void
CbcModel::convertToDynamic()
{
int iObject;
const double * cost = solver_->getObjCoefficients();
bool allDynamic = true;
for (iObject = 0; iObject < numberObjects_; iObject++) {
CbcSimpleInteger * obj1 =
dynamic_cast <CbcSimpleInteger *>(object_[iObject]) ;
CbcSimpleIntegerPseudoCost * obj1a =
dynamic_cast <CbcSimpleIntegerPseudoCost *>(object_[iObject]) ;
CbcSimpleIntegerDynamicPseudoCost * obj2 =
dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[iObject]) ;
if (obj1 && !obj2) {
// replace
int iColumn = obj1->columnNumber();
int priority = obj1->priority();
int preferredWay = obj1->preferredWay();
double costValue = CoinMax(1.0e-5, fabs(cost[iColumn]));
// treat as if will cost what it says up
double upCost = costValue;
#ifndef BRANCH_BREAKEVEN
#define BRANCH_BREAKEVEN 0.3
#else
preferredWay=1;
#endif
// and balance at breakeven of 0.3
double downCost = ((1.0-BRANCH_BREAKEVEN) * upCost) / BRANCH_BREAKEVEN;
if (obj1a) {
upCost = obj1a->upPseudoCost();
downCost = obj1a->downPseudoCost();
}
delete object_[iObject];
CbcSimpleIntegerDynamicPseudoCost * newObject =
new CbcSimpleIntegerDynamicPseudoCost(this, iColumn, 1.0e0*downCost, 1.0e0*upCost);
//newObject->setNumberBeforeTrust(numberBeforeTrust_);
newObject->setPriority(priority);
newObject->setPosition(iObject);
newObject->setPreferredWay(preferredWay);
object_[iObject] = newObject;
} else if (!obj2) {
CbcObject * obj3 =
dynamic_cast <CbcObject *>(object_[iObject]) ;
if (!obj3 || !obj3->optionalObject())
allDynamic = false;
} else {
// synchronize trust
//obj2->setNumberBeforeTrust(numberBeforeTrust_);
}
}
if (branchingMethod_) {
if ((branchingMethod_->whichMethod()&1) == 0 && !branchingMethod_->chooseMethod()) {
// Need a method which can do better
delete branchingMethod_;
branchingMethod_ = NULL;
}
}
if (allDynamic)
ownership_ |= 0x40000000;
if (!branchingMethod_ && allDynamic) {
// create one
branchingMethod_ = new CbcBranchDynamicDecision();
}
#ifdef SWITCH_VARIABLES
// see if any switching variables
if (numberIntegers_<solver_->getNumCols())
findSwitching();
#endif
synchronizeNumberBeforeTrust();
}
#ifdef SWITCH_VARIABLES
// Convert Dynamic to Switching
int
CbcModel::findSwitching()
{
if ((moreSpecialOptions2_&1)==0)
return 0;
const CoinPackedMatrix * rowCopy = solver_->getMatrixByRow();
const int * column = rowCopy->getIndices();
const int * rowLength = rowCopy->getVectorLengths();
const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
const double * rowLower = solver_->getRowLower();
const double * rowUpper = solver_->getRowUpper();
const double * columnLower = solver_->getColLower();
const double * columnUpper = solver_->getColUpper();
const double * element = rowCopy->getElements();
//const double * element = solver_->getMatrixByCol()->getElements();
const int * row = solver_->getMatrixByCol()->getIndices();
const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts();
const int * columnLength = solver_->getMatrixByCol()->getVectorLengths();
int numberRows = solver_->getNumRows();
int numberColumns = solver_->getNumCols();
int * sort = new int[2*numberRows+2+numberColumns];
int * whichRow = sort+numberRows+1;
int * marked = whichRow+numberRows+1;
memset(marked,0,numberColumns*sizeof(int));
int nnSwitch=0;
int nnSwitchTotal=0;
int n2Switch=0;
double largeRatio1=1000.0;
double largeRatio2=100.0;
for (int i=0;i<numberIntegers_;i++) {
int iColumn = integerVariable_[i];
if (columnLower[iColumn]||columnUpper[iColumn]!=1.0)
continue;
if (!dynamic_cast <CbcSimpleInteger *> (object_[i]))
continue;
int nAdd=0;
bool takeThis=false;
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
if (rowLength[iRow]!=2) {
continue;
}
// for now just 0.0 in rhs
if (!rowLower[iRow]) {
if (rowUpper[iRow]!=COIN_DBL_MAX)
continue;
} else if (rowLower[iRow]!=-COIN_DBL_MAX) {
continue;
} else if (rowUpper[iRow]) {
continue;
}
CoinBigIndex k = rowStart[iRow];
double bValue, cValue;
int cColumn;
if (column[k]==iColumn) {
bValue=element[k];
cValue=element[k+1];
cColumn=column[k+1];
} else {
bValue=element[k+1];
cValue=element[k];
cColumn=column[k];
}
if (solver_->isInteger(cColumn))
continue;
if (columnLower[cColumn]<0.0)
continue;
if (bValue*cValue>0.0)
continue;
if (fabs(bValue)>largeRatio1*fabs(cValue))
takeThis=true;
// add to list
whichRow[nAdd]=iRow;
sort[nAdd++]=cColumn;
}
if (nAdd) {
n2Switch++;
CoinSort_2(sort,sort+nAdd,whichRow);
int last=sort[0];
for (int k=1;k<nAdd;k++) {
if (sort[k]==last)
takeThis=true;
else
last=sort[k];
}
if (takeThis) {
int last=sort[0];
marked[last]++;
for (int k=1;k<nAdd;k++) {
if (sort[k]!=last) {
last=sort[k];
marked[last]++;
}
}
//printf("Column %d has %d other columns\n",iColumn,nAdd);
sort[nAdd]=COIN_INT_MAX;
whichRow[nAdd]=COIN_INT_MAX;
CbcSimpleIntegerDynamicPseudoCost * thisOne =
dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *> (object_[i]);
if (thisOne) {
assert(iColumn == thisOne->columnNumber());
object_[i]=new CbcSwitchingBinary(thisOne,nAdd,sort,whichRow);
delete thisOne;
} else {
CbcSimpleInteger * thisOne =
dynamic_cast <CbcSimpleInteger *> (object_[i]);
assert (thisOne);
assert(iColumn == thisOne->columnNumber());
CbcSimpleIntegerDynamicPseudoCost tempObj(this,iColumn,0.1);
object_[i]=new CbcSwitchingBinary(&tempObj,nAdd,sort,whichRow);
delete thisOne;
}
}
}
// see if there is an interesting row
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
// for now just 0.0 in rhs
if (!rowLower[iRow]) {
if (rowUpper[iRow]!=COIN_DBL_MAX)
continue;
} else if (rowLower[iRow]!=-COIN_DBL_MAX) {
continue;
} else if (rowUpper[iRow]) {
continue;
}
int nOther=0;
double bEl=0.0;
double cMax=-COIN_DBL_MAX;
double cMin=COIN_DBL_MAX;
for (CoinBigIndex k = rowStart[iRow];
k<rowStart[iRow]+rowLength[iRow];k++) {
int jColumn = column[k];
if (jColumn==iColumn) {
bEl=element[k];
} else {
sort[nOther++]=jColumn;
if (solver_->isInteger(jColumn)) {
cMin=-1.0;
cMax=1.0;
break;
} else {
cMax=CoinMax(cMax,element[k]);
cMin=CoinMin(cMin,element[k]);
if (columnLower[jColumn]<0.0) {
cMin=-1.0;
cMax=1.0;
break;
}
}
}
}
double largestC = CoinMax(fabs(cMin),fabs(cMax));
if (((cMin>0.0&&bEl<0.0&&!rowUpper[iRow])||
(cMin<0.0&&bEl>0.0&&!rowLower[iRow]))&&cMin*cMax>0.0&&
fabs(bEl)>largeRatio2*largestC) {
// forces to zero
CbcSwitchingBinary * object =
dynamic_cast <CbcSwitchingBinary *> (object_[i]);
if (!object) {
// create empty one
CbcSimpleIntegerDynamicPseudoCost * thisOne =
dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *> (object_[i]);
if (thisOne) {
assert(iColumn == thisOne->columnNumber());
object=new CbcSwitchingBinary(thisOne,0,sort,whichRow);
delete thisOne;
} else {
CbcSimpleInteger * thisOne =
dynamic_cast <CbcSimpleInteger *> (object_[i]);
assert (thisOne);
assert(iColumn == thisOne->columnNumber());
CbcSimpleIntegerDynamicPseudoCost tempObj(this,iColumn,0.1);
object=new CbcSwitchingBinary(&tempObj,0,sort,whichRow);
delete thisOne;
}
object_[i]=object;
}
object->addZeroSwitches(nOther,sort);
nnSwitch++;
nnSwitchTotal+=nOther;
}
}
}
if (n2Switch+nnSwitch) {
if (handler_->logLevel()>2)
printf("%d two switch variables - %d multi (total multi %d)\n",
n2Switch,nnSwitch,nnSwitchTotal);
memset(whichRow,0,(numberRows+1)*sizeof(int));
for (int i=0;i<numberColumns;i++) {
whichRow[marked[i]]++;
}
if (handler_->logLevel()>2) {
for (int i=0;i<numberRows+1;i++) {
if (whichRow[i])
printf("%d variables have %d switches\n",whichRow[i],i);
}
}
}
delete [] sort;
// say switches exist
if (n2Switch+nnSwitch)
moreSpecialOptions2_|=4;
return n2Switch+nnSwitch;
}
// Fix associated variables
int
CbcModel::fixAssociated(OsiSolverInterface * solver,int cleanBasis)
{
int nChanged=0;
if ((moreSpecialOptions2_&4)!=0) {
int n=-1;
while (n) {
n=0;
for (int i=0;i<numberObjects_;i++) {
CbcSwitchingBinary * object = dynamic_cast<CbcSwitchingBinary *> (object_[i]);
if (object) {
n += object->setAssociatedBounds(solver,cleanBasis);
}
}
nChanged+=n;
}
}
return nChanged;
}
/* Debug associated variables
printLevel - 1 summary if bad on fixed
2 summary if bad on satisfied
3 for individuals
*/
int
CbcModel::checkAssociated(const OsiSolverInterface * solver,
const double * solution,int printLevel)
{
int nBad=0;
int nBadFixed=0;
if ((moreSpecialOptions2_&4)!=0) {
int nAt0=0;
int nAt1=0;
int nBetween=0;
for (int i=0;i<numberObjects_;i++) {
CbcSwitchingBinary * object = dynamic_cast<CbcSwitchingBinary *> (object_[i]);
if (object) {
int state[3];
nBad += object->checkAssociatedBounds(solver,solution,printLevel,state,
nBadFixed);
if (state[0]==0)
nBetween++;
else if (state[0]==-1)
nAt0++;
else
nAt1++;
}
}
if (handler_->logLevel()>2) {
if (printLevel>1||(printLevel==1&&nBadFixed)) {
printf("%d switches, %d at 0, %d at 1, %d between - %d bad values (%d when fixed)\n",
nBetween+nAt0+nAt1,nAt0,nAt1,nBetween,nBad,nBadFixed);
if (nBadFixed && printLevel!=3)
checkAssociated(solver,solution,3);
}
}
}
return nBad;
}
#endif
// Set numberBeforeTrust in all objects
void
CbcModel::synchronizeNumberBeforeTrust(int type)
{
int iObject;
for (iObject = 0; iObject < numberObjects_; iObject++) {
CbcSimpleIntegerDynamicPseudoCost * obj2 =
dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[iObject]) ;
if (obj2) {
// synchronize trust
if (!type) {
obj2->setNumberBeforeTrust(numberBeforeTrust_);
} else if (type == 1) {
int value = obj2->numberBeforeTrust();
value = (value * 11) / 10 + 1;
value = CoinMax(numberBeforeTrust_, value);
obj2->setNumberBeforeTrust(value);
} else {
assert (type == 2);
int value = obj2->numberBeforeTrust();
int n = CoinMax(obj2->numberTimesDown(),
obj2->numberTimesUp());
if (n >= value) {
value = CoinMin(CoinMin(n+1,3*(value+1)/2),5*numberBeforeTrust_);
obj2->setNumberBeforeTrust(value);
}
}
}
}
}
/* Add in any object information (objects are cloned - owner can delete
originals */
void
CbcModel::addObjects(int numberObjects, CbcObject ** objects)
{
// If integers but not enough objects fudge
if (numberIntegers_ > numberObjects_ || !numberObjects_)
findIntegers(true);
/* But if incoming objects inherit from simple integer we just want
to replace */
int numberColumns = solver_->getNumCols();
/** mark is -1 if not integer, >=0 if using existing simple integer and
>=numberColumns if using new integer */
int * mark = new int[numberColumns];
int i;
for (i = 0; i < numberColumns; i++)
mark[i] = -1;
int newNumberObjects = numberObjects;
int newIntegers = 0;
for (i = 0; i < numberObjects; i++) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(objects[i]) ;
if (obj) {
int iColumn = obj->columnNumber();
assert (iColumn >= 0);
mark[iColumn] = i + numberColumns;
newIntegers++;
}
}
// and existing
for (i = 0; i < numberObjects_; i++) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(object_[i]) ;
if (obj) {
int iColumn = obj->columnNumber();
if (mark[iColumn] < 0) {
newIntegers++;
newNumberObjects++;
mark[iColumn] = i;
}
} else {
// some other object - keep
newNumberObjects++;
}
}
delete [] integerVariable_;
integerVariable_ = NULL;
#if COIN_DEVELOP>1
if (newIntegers != numberIntegers_)
printf("changing number of integers from %d to %d\n",
numberIntegers_, newIntegers);
#endif
numberIntegers_ = newIntegers;
integerVariable_ = new int [numberIntegers_];
OsiObject ** temp = new OsiObject * [newNumberObjects];
// Put integers first
newIntegers = 0;
numberIntegers_ = 0;
for (i = 0; i < numberColumns; i++) {
int which = mark[i];
if (which >= 0) {
if (!isInteger(i)) {
newIntegers++;
solver_->setInteger(i);
}
if (which < numberColumns) {
temp[numberIntegers_] = object_[which];
object_[which] = NULL;
} else {
temp[numberIntegers_] = objects[which-numberColumns]->clone();
}
integerVariable_[numberIntegers_++] = i;
}
}
#if COIN_DEVELOP>1
if (newIntegers)
printf("%d variables were declared integer\n", newIntegers);
#endif
int n = numberIntegers_;
// Now rest of old
for (i = 0; i < numberObjects_; i++) {
if (object_[i]) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(object_[i]) ;
if (obj) {
delete object_[i];
} else {
temp[n++] = object_[i];
}
}
}
// and rest of new
for (i = 0; i < numberObjects; i++) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(objects[i]) ;
if (!obj) {
temp[n] = objects[i]->clone();
CbcObject * obj =
dynamic_cast <CbcObject *>(temp[n]) ;
if (obj)
obj->setModel(this);
n++;
}
}
delete [] mark;
assert (ownObjects_);
delete [] object_;
object_ = temp;
assert (n == newNumberObjects);
numberObjects_ = newNumberObjects;
}
/* Add in any object information (objects are cloned - owner can delete
originals */
void
CbcModel::addObjects(int numberObjects, OsiObject ** objects)
{
// If integers but not enough objects fudge
if (numberIntegers_ > numberObjects_)
findIntegers(true);
/* But if incoming objects inherit from simple integer we just want
to replace */
int numberColumns = solver_->getNumCols();
/** mark is -1 if not integer, >=0 if using existing simple integer and
>=numberColumns if using new integer */
int * mark = new int[numberColumns];
int i;
for (i = 0; i < numberColumns; i++)
mark[i] = -1;
int newNumberObjects = numberObjects;
int newIntegers = 0;
for (i = 0; i < numberObjects; i++) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(objects[i]) ;
if (obj) {
int iColumn = obj->columnNumber();
mark[iColumn] = i + numberColumns;
newIntegers++;
} else {
OsiSimpleInteger * obj2 =
dynamic_cast <OsiSimpleInteger *>(objects[i]) ;
if (obj2) {
// Osi takes precedence
int iColumn = obj2->columnNumber();
mark[iColumn] = i + numberColumns;
newIntegers++;
}
}
}
// and existing
for (i = 0; i < numberObjects_; i++) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(object_[i]) ;
if (obj) {
int iColumn = obj->columnNumber();
if (mark[iColumn] < 0) {
newIntegers++;
newNumberObjects++;
mark[iColumn] = i;
}
}
}
delete [] integerVariable_;
integerVariable_ = NULL;
#if COIN_DEVELOP>1
if (newIntegers != numberIntegers_)
printf("changing number of integers from %d to %d\n",
numberIntegers_, newIntegers);
#endif
numberIntegers_ = newIntegers;
integerVariable_ = new int [numberIntegers_];
OsiObject ** temp = new OsiObject * [newNumberObjects];
// Put integers first
newIntegers = 0;
numberIntegers_ = 0;
for (i = 0; i < numberColumns; i++) {
int which = mark[i];
if (which >= 0) {
if (!isInteger(i)) {
newIntegers++;
solver_->setInteger(i);
}
if (which < numberColumns) {
temp[numberIntegers_] = object_[which];
object_[which] = NULL;
} else {
temp[numberIntegers_] = objects[which-numberColumns]->clone();
}
integerVariable_[numberIntegers_++] = i;
}
}
#if COIN_DEVELOP>1
if (newIntegers)
printf("%d variables were declared integer\n", newIntegers);
#endif
int n = numberIntegers_;
// Now rest of old
for (i = 0; i < numberObjects_; i++) {
if (object_[i]) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(object_[i]) ;
if (obj) {
delete object_[i];
} else {
temp[n++] = object_[i];
}
}
}
// and rest of new
for (i = 0; i < numberObjects; i++) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(objects[i]) ;
OsiSimpleInteger * obj2 =
dynamic_cast <OsiSimpleInteger *>(objects[i]) ;
if (!obj && !obj2) {
temp[n] = objects[i]->clone();
CbcObject * obj =
dynamic_cast <CbcObject *>(temp[n]) ;
if (obj)
obj->setModel(this);
n++;
}
}
delete [] mark;
assert (ownObjects_);
delete [] object_;
object_ = temp;
assert (n == newNumberObjects);
numberObjects_ = newNumberObjects;
}
/**
This routine sets the objective cutoff value used for fathoming and
determining monotonic variables.
If the fathoming discipline is strict, a small tolerance is added to the
new cutoff. This avoids problems due to roundoff when the target value
is exact. The common example would be an IP with only integer variables in
the objective. If the target is set to the exact value z of the optimum,
it's possible to end up fathoming an ancestor of the solution because the
solver returns z+epsilon.
Determining if strict fathoming is needed is best done by analysis.
In cbc, that's analyseObjective. The default is false.
In cbc we always minimize so add epsilon
*/
void CbcModel::setCutoff (double value)
{
#ifdef JJF_ZERO
double tol = 0 ;
int fathomStrict = getIntParam(CbcFathomDiscipline) ;
if (fathomStrict == 1) {
solver_->getDblParam(OsiDualTolerance, tol) ;
tol = tol * (1 + fabs(value)) ;
value += tol ;
}
#endif
dblParam_[CbcCurrentCutoff] = value;
if (solver_) {
// Solvers know about direction
double direction = solver_->getObjSense();
solver_->setDblParam(OsiDualObjectiveLimit, value*direction);
}
}
/*
Call this to really test if a valid solution can be feasible. The cutoff is
passed in as a parameter so that we don't need to worry here after swapping
solvers. The solution is assumed to be numberColumns in size. If
fixVariables is true then the bounds of the continuous solver are updated.
The routine returns the objective value determined by reoptimizing from
scratch. If the solution is rejected, this will be worse than the cutoff.
TODO: There's an issue with getting the correct cutoff value: We update the
cutoff in the regular solver, but not in continuousSolver_. But our only
use for continuousSolver_ is verifying candidate solutions. Would it
make sense to update the cutoff? Then we wouldn't need to step around
isDualObjectiveLimitReached().
*/
double
CbcModel::checkSolution (double cutoff, double *solution,
int fixVariables, double objectiveValue)
{
int numberContinuousColumns=continuousSolver_->getNumCols();
if (!solverCharacteristics_->solutionAddsCuts()) {
// Can trust solution
int numberColumns = solver_->getNumCols();
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpContinuousSolver
= dynamic_cast<OsiClpSolverInterface *> (continuousSolver_);
int modifiedTolerances=0;
#ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
int savePerturbation=-1;
#endif
#ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
double savePrimalTolerance=0.0;
#endif
#ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
int saveScaling=-1;
#endif
if (clpContinuousSolver ) {
// be more accurate if possible
ClpSimplex * clp = clpContinuousSolver->getModelPtr();
#ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
savePerturbation=clp->perturbation();
#endif
#ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
savePrimalTolerance=clp->primalTolerance();
#endif
#ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
saveScaling=clp->scalingFlag();
#endif
#ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
if (savePrimalTolerance>0.9999999e-7) {
modifiedTolerances |= 1;
clp->setPrimalTolerance(1.0e-8);
}
#endif
#ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
if (savePerturbation<100) {
modifiedTolerances |= 2;
clp->setPerturbation(100);
}
#endif
#ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
if (saveScaling) {
modifiedTolerances |= 4;
clp->scaling(0);
}
#endif
}
#endif
/*
Grab the continuous solver (the pristine copy of the problem, made before
starting to work on the root node). Save the bounds on the variables.
Install the solution passed as a parameter, and copy it to the model's
currentSolution_.
TODO: This is a belt-and-suspenders approach. Once the code has settled
a bit, we can cast a critical eye here.
*/
OsiSolverInterface * saveSolver = solver_;
if (continuousSolver_)
solver_ = continuousSolver_;
// save basis and solution
CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
assert(basis != NULL);
double * saveSolution = CoinCopyOfArray(solver_->getColSolution(),
solver_->getNumCols());
// move solution to continuous copy
solver_->setColSolution(solution);
// Put current solution in safe place
// Point to current solution
const double * save = testSolution_;
// Safe as will be const inside infeasibility()
testSolution_ = solver_->getColSolution();
//memcpy(currentSolution_,solver_->getColSolution(),
// numberColumns*sizeof(double));
//solver_->messageHandler()->setLogLevel(4);
// save original bounds
double * saveUpper = new double[numberColumns];
double * saveLower = new double[numberColumns];
memcpy(saveUpper, getColUpper(), numberColumns*sizeof(double));
memcpy(saveLower, getColLower(), numberColumns*sizeof(double));
//#define CLP_INVESTIGATE4
#if CBC_USEFUL_PRINTING>14
{
int nBad=checkAssociated(solver_,solver_->getColSolution(),1);
if (nBad)
checkAssociated(solver_,solver_->getColSolution(),3);
double largestInfeasibility = 0.0;
double primalTolerance ;
double offset;
solver_->getDblParam(OsiObjOffset, offset);
solver_->getDblParam(OsiPrimalTolerance, primalTolerance) ;
const double *objective = getObjCoefficients() ;
const double * rowLower = solver_->getRowLower() ;
const double * rowUpper = solver_->getRowUpper() ;
const double * columnLower = solver_->getColLower() ;
const double * columnUpper = solver_->getColUpper() ;
int numberRows = solver_->getNumRows() ;
double *rowActivity = new double[numberRows] ;
memset(rowActivity, 0, numberRows*sizeof(double)) ;
double *rowSum = new double[numberRows] ;
memset(rowSum, 0, numberRows*sizeof(double)) ;
int * marked = new int [numberColumns];
for (int i=0;i<numberColumns;i++)
marked[i]=-1;
for (int i=0;i<numberIntegers_;i++)
marked[integerVariable_[i]]=-2;
if ((moreSpecialOptions2_&4)!=0) {
for (int i=0;i<numberObjects_;i++) {
CbcSwitchingBinary * object = dynamic_cast<CbcSwitchingBinary *> (object_[i]);
if (object) {
int iColumn = object->columnNumber();
const int * other = object->otherVariable();
marked[iColumn]=-3-other[0];
int n=object->numberOther();
for (int k=0;k<n;k++)
marked[other[k]]=iColumn;
}
}
}
const double * element = solver_->getMatrixByCol()->getElements();
const int * row = solver_->getMatrixByCol()->getIndices();
const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts();
const int * columnLength = solver_->getMatrixByCol()->getVectorLengths();
const CoinPackedMatrix * rowCopy = solver_->getMatrixByRow();
const int * column = rowCopy->getIndices();
const int * rowLength = rowCopy->getVectorLengths();
const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
const double * elementByRow = rowCopy->getElements();
double objValue=-offset;
for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
double value = solution[iColumn];
objValue += value*objective[iColumn];
if (value>columnUpper[iColumn]) {
if (value-columnUpper[iColumn]>1.0e-8)
printf("column %d has value %.12g above %.12g\n",iColumn,value,columnUpper[iColumn]);
value=columnUpper[iColumn];
} else if (value<columnLower[iColumn]) {
if (value-columnLower[iColumn]<-1.0e-8)
printf("column %d has value %.12g below %.12g\n",iColumn,value,columnLower[iColumn]);
value=columnLower[iColumn];
}
if (value) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
rowActivity[iRow] += value * element[j];
rowSum[iRow] += fabs(value * element[j]);
}
}
}
for (int i = 0 ; i < numberRows ; i++) {
#if 0 //def CLP_INVESTIGATE
double inf;
inf = rowLower[i] - rowActivity[i];
if (inf > primalTolerance)
printf("Row %d inf %g sum %g %g <= %g <= %g\n",
i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
inf = rowActivity[i] - rowUpper[i];
if (inf > primalTolerance)
printf("Row %d inf %g sum %g %g <= %g <= %g\n",
i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
#endif
double infeasibility = CoinMax(rowActivity[i]-rowUpper[i],
rowLower[i]-rowActivity[i]);
// but allow for errors
double factor = CoinMax(1.0,rowSum[i]*1.0e-3);
if (infeasibility>largestInfeasibility*factor) {
largestInfeasibility = infeasibility/factor;
printf("Ainf of %g on row %d sum %g scaled %g\n",
infeasibility,i,rowSum[i],largestInfeasibility);
if (infeasibility>1.0e10) {
for (CoinBigIndex j=rowStart[i];
j<rowStart[i]+rowLength[i];j++) {
printf("col %d element %g marked %d\n",
column[j],elementByRow[j],marked[column[j]]);
}
}
}
}
delete [] rowActivity ;
delete [] rowSum;
delete [] marked;
if (largestInfeasibility > 10.0*primalTolerance)
printf("Alargest infeasibility is %g - obj %g\n", largestInfeasibility,objValue);
else
printf("Afeasible (%g) - obj %g\n", largestInfeasibility,objValue);
}
#endif
// point to useful information
OsiBranchingInformation usefulInfo = usefulInformation();
/*
Run through the objects and use feasibleRegion() to set variable bounds
so as to fix the variables specified in the objects at their value in this
solution. Since the object list contains (at least) one object for every
integer variable, this has the effect of fixing all integer variables.
*/
int i;
for (i = 0; i < numberObjects_; i++)
object_[i]->feasibleRegion(solver_, &usefulInfo);
#if CBC_USEFUL_PRINTING>14
{
int nBad=checkAssociated(solver_,solver_->getColSolution(),1);
if (nBad)
checkAssociated(solver_,solver_->getColSolution(),3);
double largestInfeasibility = 0.0;
double primalTolerance ;
double offset;
solver_->getDblParam(OsiObjOffset, offset);
solver_->getDblParam(OsiPrimalTolerance, primalTolerance) ;
const double *objective = getObjCoefficients() ;
const double * rowLower = solver_->getRowLower() ;
const double * rowUpper = solver_->getRowUpper() ;
const double * columnLower = solver_->getColLower() ;
const double * columnUpper = solver_->getColUpper() ;
int numberRows = solver_->getNumRows() ;
double *rowActivity = new double[numberRows] ;
memset(rowActivity, 0, numberRows*sizeof(double)) ;
double *rowSum = new double[numberRows] ;
memset(rowSum, 0, numberRows*sizeof(double)) ;
int * marked = new int [numberColumns];
for (int i=0;i<numberColumns;i++)
marked[i]=-1;
for (int i=0;i<numberIntegers_;i++)
marked[integerVariable_[i]]=-2;
if ((moreSpecialOptions2_&4)!=0) {
for (int i=0;i<numberObjects_;i++) {
CbcSwitchingBinary * object = dynamic_cast<CbcSwitchingBinary *> (object_[i]);
if (object) {
int iColumn = object->columnNumber();
const int * other = object->otherVariable();
marked[iColumn]=-3-other[0];
int n=object->numberOther();
for (int k=0;k<n;k++)
marked[other[k]]=iColumn;
}
}
}
const double * element = solver_->getMatrixByCol()->getElements();
const int * row = solver_->getMatrixByCol()->getIndices();
const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts();
const int * columnLength = solver_->getMatrixByCol()->getVectorLengths();
const CoinPackedMatrix * rowCopy = solver_->getMatrixByRow();
const int * column = rowCopy->getIndices();
const int * rowLength = rowCopy->getVectorLengths();
const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
const double * elementByRow = rowCopy->getElements();
double objValue=-offset;
for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
double value = solution[iColumn];
objValue += value*objective[iColumn];
if (value>columnUpper[iColumn]) {
if (value-columnUpper[iColumn]>1.0e-8)
printf("column %d has value %.12g above %.12g\n",iColumn,value,columnUpper[iColumn]);
value=columnUpper[iColumn];
} else if (value<columnLower[iColumn]) {
if (value-columnLower[iColumn]<-1.0e-8)
printf("column %d has value %.12g below %.12g\n",iColumn,value,columnLower[iColumn]);
value=columnLower[iColumn];
}
if (value) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
rowActivity[iRow] += value * element[j];
rowSum[iRow] += fabs(value * element[j]);
}
}
}
for (int i = 0 ; i < numberRows ; i++) {
#if 0 //def CLP_INVESTIGATE
double inf;
inf = rowLower[i] - rowActivity[i];
if (inf > primalTolerance)
printf("Row %d inf %g sum %g %g <= %g <= %g\n",
i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
inf = rowActivity[i] - rowUpper[i];
if (inf > primalTolerance)
printf("Row %d inf %g sum %g %g <= %g <= %g\n",
i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
#endif
double infeasibility = CoinMax(rowActivity[i]-rowUpper[i],
rowLower[i]-rowActivity[i]);
// but allow for errors
double factor = CoinMax(1.0,rowSum[i]*1.0e-3);
if (infeasibility>largestInfeasibility*factor) {
largestInfeasibility = infeasibility/factor;
printf("inf of %g on row %d sum %g scaled %g\n",
infeasibility,i,rowSum[i],largestInfeasibility);
if (infeasibility>1.0e10) {
for (CoinBigIndex j=rowStart[i];
j<rowStart[i]+rowLength[i];j++) {
printf("col %d element %g marked %d\n",
column[j],elementByRow[j],marked[column[j]]);
}
}
}
}
delete [] rowActivity ;
delete [] rowSum;
delete [] marked;
if (largestInfeasibility > 10.0*primalTolerance)
printf("Largest infeasibility is %g - obj %g\n", largestInfeasibility,objValue);
else
printf("Feasible (%g) - obj %g\n", largestInfeasibility,objValue);
}
#endif
// If relaxed then leave bounds on basic variables
if (fixVariables == -1 && (specialOptions_&16) == 0) {
CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis*>(saveSolver->getWarmStart()) ;
assert(basis != NULL);
#ifdef JJF_ZERO //ndef CBC_OTHER_SOLVER
for (i = 0; i < numberObjects_; i++) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(object_[i]) ;
if (obj) {
int iColumn = obj->columnNumber();
if (basis->getStructStatus(iColumn) == CoinWarmStartBasis::basic) {
solver_->setColLower(iColumn, saveLower[iColumn]);
solver_->setColUpper(iColumn, saveUpper[iColumn]);
}
}
}
#endif
delete basis;
}
// We can switch off check
if ((specialOptions_&4) == 0 && (moreSpecialOptions2_&10) != 8) {
// Be on safe side - unless very few integers and large
bool allSlack = (specialOptions_&2) == 0 && solverCharacteristics_->warmStart();
if (numberIntegers_*4>solver_->getNumCols()||solver_->getNumCols()<10000)
allSlack = true;
if (allSlack) {
/*
Remove any existing warm start information to be sure there is no
residual influence on initialSolve().
*/
CoinWarmStartBasis *slack =
dynamic_cast<CoinWarmStartBasis *>(solver_->getEmptyWarmStart()) ;
solver_->setWarmStart(slack);
delete slack ;
} else {
if (bestSolutionBasis_.getNumStructural() == solver_->getNumCols() &&
bestSolutionBasis_.getNumArtificial() == solver_->getNumRows())
solver_->setWarmStart(&bestSolutionBasis_);
}
// Give a hint to do dual
bool saveTakeHint;
OsiHintStrength saveStrength;
#ifndef NDEBUG
bool gotHint = (solver_->getHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength));
assert (gotHint);
#else
(solver_->getHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength));
#endif
solver_->setHintParam(OsiDoDualInInitial, true, OsiHintTry);
solver_->initialSolve();
#ifdef SWITCH_VARIABLES
if (solver_->isProvenOptimal()) {
int nBad=checkAssociated(solver_,solver_->getColSolution(),1);
if (nBad)
checkAssociated(solver_,solver_->getColSolution(),3);
}
#endif
#ifdef JJF_ZERO
if (solver_->isProvenOptimal()) {
solver_->writeMpsNative("feasible.mps",NULL,NULL,2);
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver ) {
clpSolver->getModelPtr()->writeBasis("feasible.bas",true);
}
#endif
printf("XXXXXXXXXXXX - saving feasible\n");
}
#endif
if (!solver_->isProvenOptimal()) {
#if CBC_FEASIBILITY_INVESTIGATE
printf("checkSolution infeas! Retrying with primal.\n");
#endif
//bool saveTakeHint;
//OsiHintStrength saveStrength;
//bool savePrintHint;
//solver_->writeMpsNative("infeas.mps", NULL, NULL, 2);
//bool gotHint = (solver_->getHintParam(OsiDoReducePrint,savePrintHint,saveStrength));
//gotHint = (solver_->getHintParam(OsiDoScale,saveTakeHint,saveStrength));
//solver_->setHintParam(OsiDoScale,false,OsiHintTry);
//solver_->setHintParam(OsiDoReducePrint,false,OsiHintTry) ;
solver_->setHintParam(OsiDoDualInInitial, false, OsiHintTry);
solver_->initialSolve();
//solver_->setHintParam(OsiDoScale,saveTakeHint,saveStrength);
//solver_->setHintParam(OsiDoReducePrint,savePrintHint,OsiHintTry) ;
// go from all slack now
specialOptions_ &= ~2;
if (!solver_->isProvenOptimal()) {
CoinWarmStartBasis *slack =
dynamic_cast<CoinWarmStartBasis *>(solver_->getEmptyWarmStart()) ;
solver_->setWarmStart(slack);
delete slack ;
#if CBC_FEASIBILITY_INVESTIGATE
printf("checkSolution infeas! Retrying wihout basis and with primal.\n");
#endif
solver_->initialSolve();
//solver_->writeMps("bad");
#ifdef COIN_HAS_CLP
if (!solver_->isProvenOptimal()&&modifiedTolerances) {
// Restore
ClpSimplex * clp = clpContinuousSolver->getModelPtr();
#ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
clp->setPrimalTolerance(savePrimalTolerance);
#endif
#ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
clp->setPerturbation(savePerturbation);
#endif
#ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
clp->scaling(saveScaling);
#endif
solver_->resolve();
}
#endif
#if CBC_FEASIBILITY_INVESTIGATE
if (!solver_->isProvenOptimal()) {
printf("checkSolution still infeas!\n");
}
#endif
}
}
//assert(solver_->isProvenOptimal());
solver_->setHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength);
objectiveValue = solver_->getObjValue() * solver_->getObjSense();
}
bestSolutionBasis_ = CoinWarmStartBasis();
/*
Check that the solution still beats the objective cutoff.
If it passes, make a copy of the primal variable values and do some
cleanup and checks:
+ Values of all variables are are within original bounds and values of
all integer variables are within tolerance of integral.
+ There are no constraint violations.
There really should be no need for the check against original bounds.
Perhaps an opportunity for a sanity check?
*/
if (objectiveValue > cutoff && objectiveValue < cutoff + 1.0e-8 + 1.0e-8*fabs(cutoff))
cutoff = objectiveValue; // relax
if ((solver_->isProvenOptimal() || (specialOptions_&4) != 0) && objectiveValue <= cutoff) {
memcpy(solution , solver_->getColSolution(), numberColumns*sizeof(double)) ;
int iColumn;
#ifndef NDEBUG
double integerTolerance = getIntegerTolerance() ;
#endif
#if CBC_FEASIBILITY_INVESTIGATE
const double * dj = solver_->getReducedCost();
const double * colLower = saveSolver->getColLower();
const double * colUpper = saveSolver->getColUpper();
int nAtLbNatural = 0;
int nAtUbNatural = 0;
int nAtLbNaturalZero = 0;
int nAtUbNaturalZero = 0;
int nAtLbFixed = 0;
int nAtUbFixed = 0;
int nAtOther = 0;
int nAtOtherNatural = 0;
int nNotNeeded = 0;
#endif
for (iColumn = 0 ; iColumn < numberContinuousColumns ; iColumn++) {
double value = solution[iColumn] ;
value = CoinMax(value, saveLower[iColumn]) ;
value = CoinMin(value, saveUpper[iColumn]) ;
if (solver_->isInteger(iColumn)) {
assert(fabs(value - solution[iColumn]) <= 100.0*integerTolerance) ;
#if CBC_FEASIBILITY_INVESTIGATE
double value2 = floor(value + 0.5);
if (dj[iColumn] < -1.0e-6) {
// negative dj
//assert (value2==colUpper[iColumn]);
if (saveUpper[iColumn] == colUpper[iColumn]) {
nAtUbNatural++;
if (saveLower[iColumn] != colLower[iColumn])
nNotNeeded++;
} else if (saveLower[iColumn] == colUpper[iColumn]) {
nAtLbFixed++;
} else {
nAtOther++;
if (saveLower[iColumn] != colLower[iColumn] &&
saveUpper[iColumn] != colUpper[iColumn])
nNotNeeded++;
}
} else if (dj[iColumn] > 1.0e-6) {
// positive dj
//assert (value2==colLower[iColumn]);
if (saveLower[iColumn] == colLower[iColumn]) {
nAtLbNatural++;
if (saveUpper[iColumn] != colUpper[iColumn])
nNotNeeded++;
} else if (saveUpper[iColumn] == colLower[iColumn]) {
nAtUbFixed++;
} else {
nAtOther++;
if (saveLower[iColumn] != colLower[iColumn] &&
saveUpper[iColumn] != colUpper[iColumn])
nNotNeeded++;
}
} else {
// zero dj
if (value2 == saveUpper[iColumn]) {
nAtUbNaturalZero++;
if (saveLower[iColumn] != colLower[iColumn])
nNotNeeded++;
} else if (value2 == saveLower[iColumn]) {
nAtLbNaturalZero++;
} else {
nAtOtherNatural++;
if (saveLower[iColumn] != colLower[iColumn] &&
saveUpper[iColumn] != colUpper[iColumn])
nNotNeeded++;
}
}
#endif
}
solution[iColumn] = value ;
}
#if CBC_FEASIBILITY_INVESTIGATE
printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d\n",
nAtLbNatural,
nAtUbNatural,
nAtLbNaturalZero,
nAtUbNaturalZero,
nAtLbFixed,
nAtUbFixed,
nAtOther,
nAtOtherNatural, nNotNeeded);
//if (currentNode_)
//printf(" SOL at depth %d\n",currentNode_->depth());
//else
//printf(" SOL at unknown depth\n");
#endif
if ((specialOptions_&16) == 0) {
#ifdef JJF_ZERO
// check without scaling
bool saveTakeHint;
OsiHintStrength saveStrength;
solver_->getHintParam(OsiDoScale, saveTakeHint, saveStrength);
solver_->setHintParam(OsiDoScale, false, OsiHintTry);
solver_->resolve();
solver_->setHintParam(OsiDoScale, saveTakeHint, saveStrength);
#endif
double largestInfeasibility = 0.0;
double primalTolerance ;
solver_->getDblParam(OsiPrimalTolerance, primalTolerance) ;
const double * rowLower = solver_->getRowLower() ;
const double * rowUpper = solver_->getRowUpper() ;
int numberRows = solver_->getNumRows() ;
double *rowActivity = new double[numberRows] ;
memset(rowActivity, 0, numberRows*sizeof(double)) ;
double *rowSum = new double[numberRows] ;
memset(rowSum, 0, numberRows*sizeof(double)) ;
const double * element = solver_->getMatrixByCol()->getElements();
const int * row = solver_->getMatrixByCol()->getIndices();
const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts();
const int * columnLength = solver_->getMatrixByCol()->getVectorLengths();
double offset;
solver_->getDblParam(OsiObjOffset, offset);
double objValue=-offset;
const double *objective = getObjCoefficients() ;
for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
double value = solution[iColumn];
objValue += value*objective[iColumn];
if (value) {
CoinBigIndex start = columnStart[iColumn];
CoinBigIndex end = start + columnLength[iColumn];
for (CoinBigIndex j = start; j < end; j++) {
int iRow = row[j];
rowActivity[iRow] += value * element[j];
rowSum[iRow] += fabs(value * element[j]);
}
}
}
for (i = 0 ; i < numberRows ; i++) {
#if CBC_FEASIBILITY_INVESTIGATE>1
double inf;
inf = rowLower[i] - rowActivity[i];
if (inf > primalTolerance)
printf("Row %d inf %g sum %g %g <= %g <= %g\n",
i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
inf = rowActivity[i] - rowUpper[i];
if (inf > primalTolerance)
printf("Row %d inf %g sum %g %g <= %g <= %g\n",
i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
#endif
double infeasibility = CoinMax(rowActivity[i]-rowUpper[i],
rowLower[i]-rowActivity[i]);
// but allow for errors
double factor = CoinMax(1.0,rowSum[i]*1.0e-3);
if (infeasibility>largestInfeasibility*factor) {
largestInfeasibility = infeasibility/factor;
//printf("inf of %g on row %d sum %g scaled %g\n",
// infeasibility,i,rowSum[i],largestInfeasibility);
}
}
delete [] rowActivity ;
delete [] rowSum;
#if CBC_FEASIBILITY_INVESTIGATE==0
if (handler_->logLevel()>2) {
#endif
if (largestInfeasibility > 10.0*primalTolerance)
printf("BLargest infeasibility is %g - obj %g (%g)\n", largestInfeasibility,objValue,objectiveValue);
else
printf("BFeasible (%g) - obj %g %g\n", largestInfeasibility,objValue,objectiveValue);
#if CBC_FEASIBILITY_INVESTIGATE==0
}
#else
solver_->writeMpsNative("BFeasible.mps",NULL,NULL,2);
#endif
//if (fabs(objValue-objectiveValue)>1.0e-7*fabs(objectiveValue)) {
//printf("Bad obj values\n");
objectiveValue = objValue;
//}
#if CBC_FEASIBILITY_INVESTIGATE
if (largestInfeasibility > 10.0*primalTolerance)
printf("XX largest infeasibility is %g\n", largestInfeasibility);
#endif
if (largestInfeasibility > 200.0*primalTolerance) {
handler_->message(CBC_NOTFEAS3, messages_)
<< largestInfeasibility << CoinMessageEol ;
objectiveValue = 1.0e50 ;
}
}
} else {
objectiveValue = 1.0e50 ;
}
/*
Regardless of what we think of the solution, we may need to restore the
original bounds of the continuous solver. Unfortunately, const'ness
prevents us from simply reversing the memcpy used to make these snapshots.
*/
if (fixVariables <= 0) {
for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
solver_->setColLower(iColumn, saveLower[iColumn]) ;
solver_->setColUpper(iColumn, saveUpper[iColumn]) ;
}
}
delete [] saveLower;
delete [] saveUpper;
solver_->setColSolution(saveSolution);
delete [] saveSolution;
solver_->setWarmStart(basis);
delete basis ;
/*
Restore the usual solver.
*/
solver_ = saveSolver;
testSolution_ = save;
#ifdef COIN_HAS_CLP
if (modifiedTolerances) {
// Restore
ClpSimplex * clp = clpContinuousSolver->getModelPtr();
#ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
clp->setPrimalTolerance(savePrimalTolerance);
#endif
#ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
clp->setPerturbation(savePerturbation);
#endif
#ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
clp->scaling(saveScaling);
#endif
}
#endif
return objectiveValue;
} else {
// Outer approximation or similar
//If this is true then the solution comes from the nlp we don't need to resolve the same nlp with ipopt
//solverCharacteristics_->setSolver(solver_);
bool solutionComesFromNlp = solverCharacteristics_->bestObjectiveValue() < cutoff;
double objectiveValue;
int numberColumns = solver_->getNumCols();
double *saveLower = NULL;
double * saveUpper = NULL;
if (! solutionComesFromNlp) { //Otherwise solution already comes from ipopt and cuts are known
if (fixVariables > 0) { //Will temporarily fix all integer valued var
// save original bounds
saveUpper = new double[numberColumns];
saveLower = new double[numberColumns];
memcpy(saveUpper, solver_->getColUpper(), numberColumns*sizeof(double));
memcpy(saveLower, solver_->getColLower(), numberColumns*sizeof(double));
//in any case solution should be already loaded into solver_
/*
Run through the objects and use feasibleRegion() to set variable bounds
so as to fix the variables specified in the objects at their value in this
solution. Since the object list contains (at least) one object for every
integer variable, this has the effect of fixing all integer variables.
*/
const double * save = testSolution_;
testSolution_ = solution;
// point to useful information
OsiBranchingInformation usefulInfo = usefulInformation();
for (int i = 0; i < numberObjects_; i++)
object_[i]->feasibleRegion(solver_, &usefulInfo);
testSolution_ = save;
resolve(solver_);
}
/*
Now step through the cut generators and see if any of them are flagged to
run when a new solution is discovered. Only global cuts are useful.
(The solution being evaluated may not correspond to the current location in the
search tree --- discovered by heuristic, for example.)
*/
OsiCuts theseCuts;
int i;
int lastNumberCuts = 0;
// reset probing info
//if (probingInfo_)
//probingInfo_->initializeFixing();
for (i = 0; i < numberCutGenerators_; i++) {
if (generator_[i]->atSolution()) {
generator_[i]->generateCuts(theseCuts, 1, solver_, NULL);
int numberCuts = theseCuts.sizeRowCuts();
for (int j = lastNumberCuts; j < numberCuts; j++) {
const OsiRowCut * thisCut = theseCuts.rowCutPtr(j);
if (thisCut->globallyValid()) {
// if ((specialOptions_&1)!=0)
// {
// /* As these are global cuts -
// a) Always get debugger object
// b) Not fatal error to cutoff optimal (if we have just got optimal)
// */
// const OsiRowCutDebugger *debugger = solver_->getRowCutDebuggerAlways() ;
// if (debugger)
// {
// if(debugger->invalidCut(*thisCut))
// printf("ZZZZ Global cut - cuts off optimal solution!\n");
// }
// }
// add to global list
OsiRowCut newCut(*thisCut);
newCut.setGloballyValid(true);
newCut.mutableRow().setTestForDuplicateIndex(false);
globalCuts_.addCutIfNotDuplicate(newCut) ;
} else {
// obviously wrong
if (handler_->logLevel() > 1)
printf("Cut generator %s set to run on new solution but NOT globally valid!!\n",
generator_[i]->cutGeneratorName());
}
}
}
}
// int numberCuts = theseCuts.sizeColCuts();
// for (i=0;i<numberCuts;i++) {
// const OsiColCut * thisCut = theseCuts.colCutPtr(i);
// if (thisCut->globallyValid()) {
// // add to global list
// globalCuts_.insert(*thisCut);
// }
// }
//have to retrieve the solution and its value from the nlp
}
double newObjectiveValue = cutoff;
if (solverCharacteristics_->solution(newObjectiveValue,
const_cast<double *> (solution),
numberColumns)) {
objectiveValue = newObjectiveValue;
} else {
objectiveValue = 2e50;
}
if (!solutionComesFromNlp && fixVariables > 0) {
for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
solver_->setColLower(iColumn, saveLower[iColumn]) ;
solver_->setColUpper(iColumn, saveUpper[iColumn]) ;
}
delete [] saveLower;
delete [] saveUpper;
solver_->resolve();
}
//If the variables were fixed the cutting plane procedure may have believed that the node could be fathomed
//re-establish truth.- should do no harm for non nlp
if (!solutionComesFromNlp && fixVariables > 0)
solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
return objectiveValue;
}
}
/*
Call this routine from anywhere when a solution is found. The solution
vector is assumed to contain one value for each structural variable.
The first action is to run checkSolution() to confirm the objective and
feasibility. If this check causes the solution to be rejected, we're done.
If fixVariables = true, the variable bounds held by the continuous solver
will be left fixed to the values in the solution; otherwise they are
restored to the original values.
If the solution is accepted, install it as the best solution.
The routine also contains a hook to run any cut generators that are flagged
to run when a new solution is discovered. There's a potential hazard because
the cut generators see the continuous solver >after< possible restoration of
original bounds (which may well invalidate the solution).
*/
void
CbcModel::setBestSolution (CBC_Message how,
double & objectiveValue, const double *solutionIn,
int fixVariables)
{
double * solution = CoinCopyOfArray(solutionIn, solver_->getNumCols());
#ifdef JJF_ZERO
{
double saveOffset;
solver_->getDblParam(OsiObjOffset, saveOffset);
const double * obj = solver_->getObjCoefficients();
double newTrueSolutionValue = -saveOffset;
double newSumInfeas = 0.0;
int numberColumns = solver_->getNumCols();
for (int i = 0 ; i < numberColumns ; i++ ) {
if (solver_->isInteger(i)) {
double value = solution[i];
double nearest = floor(value + 0.5);
newSumInfeas += fabs(value - nearest);
}
if (solution[i])
printf("%d obj %g val %g - total %g true\n", i, obj[i], solution[i],
newTrueSolutionValue);
newTrueSolutionValue += obj[i] * solution[i];
}
printf("obj %g\n", newTrueSolutionValue);
}
#endif
if (!solverCharacteristics_->solutionAddsCuts()) {
// Can trust solution
double cutoff = getCutoff();
if (cutoff < 1.0e30)
cutoff = CoinMin(cutoff, bestObjective_) ;
/*
Double check the solution to catch pretenders.
*/
double saveObjectiveValue = objectiveValue;
// save basis
CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
assert(basis != NULL);
objectiveValue = checkSolution(cutoff, solution, fixVariables, objectiveValue);
if (cutoff>1.0e40&&objectiveValue<1.0e10)
saveObjectiveValue = objectiveValue; // take anyway
if (saveObjectiveValue + 1.0e-3 +1.0e-7*fabs(saveObjectiveValue)
< objectiveValue) {
#if CBC_FEASIBILITY_INVESTIGATE
printf("First try at solution had objective %.16g, rechecked as %.16g\n",
saveObjectiveValue, objectiveValue);
#endif
// try again with basic variables with original bounds
// save basis
CoinWarmStartBasis * basis2 =
dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
assert(basis2 != NULL);
solver_->setWarmStart(basis);
int numberColumns = solver_->getNumCols();
double * solution2 = CoinCopyOfArray(solutionIn, numberColumns);
double objectiveValue2 = saveObjectiveValue;
objectiveValue2 = checkSolution(cutoff, solution2, -1, objectiveValue2);
#if CBC_FEASIBILITY_INVESTIGATE
printf("Relaxed second try had objective of %.16g\n",
objectiveValue2);
#endif
if (objectiveValue2 + 1.0e-7 < objectiveValue) {
// Now check tolerances
double integerTolerance = dblParam_[CbcIntegerTolerance];
double tolerance;
solver_->getDblParam(OsiPrimalTolerance, tolerance) ;
double largestAway = 0.0;
int iAway = -1;
double largestInfeasibility = tolerance;
#if CBC_FEASIBILITY_INVESTIGATE
int iInfeas = -1;
#endif
const double * columnLower = continuousSolver_->getColLower();
const double * columnUpper = continuousSolver_->getColUpper();
int i;
for (i = 0; i < numberColumns; i++) {
double value = solution2[i];
if (value > columnUpper[i] + largestInfeasibility) {
#if CBC_FEASIBILITY_INVESTIGATE
iInfeas = i;
#endif
largestInfeasibility = value - columnUpper[i];
} else if (value < columnLower[i] - largestInfeasibility) {
#if CBC_FEASIBILITY_INVESTIGATE
iInfeas = i;
#endif
largestInfeasibility = columnLower[i] - value;
}
}
for (i = 0; i < numberObjects_; i++) {
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(object_[i]) ;
if (obj) {
int iColumn = obj->columnNumber();
double value = solution2[iColumn];
value = fabs(floor(value + 0.5) - value);
if (value > largestAway) {
iAway = iColumn;
largestAway = value;
}
}
}
#if CBC_FEASIBILITY_INVESTIGATE
if (iInfeas >= 0)
printf("Largest infeasibility of %g on column %d - tolerance %g\n",
largestInfeasibility, iInfeas, tolerance);
#endif
if (largestAway > integerTolerance) {
handler_->message(CBC_RELAXED1, messages_)
<< objectiveValue2
<< iAway
<< largestAway
<< integerTolerance
<< CoinMessageEol ;
} else {
handler_->message(CBC_RELAXED2, messages_)
<< objectiveValue2
<< integerTolerance
<< CoinMessageEol ;
// take
CoinCopyN(solution2, numberColumns, solution);
objectiveValue = objectiveValue2;
}
} else if (!parentModel_) {
// not good
messageHandler()->message(CBC_FPUMP2, messages())
<< "On closer inspection - solution discarded"
<< CoinMessageEol ;
}
delete [] solution2;
solver_->setWarmStart(basis2);
delete basis2 ;
}
delete basis ;
if (objectiveValue > cutoff && objectiveValue < cutoff + 1.0e-8 + 1.0e-8*fabs(cutoff))
cutoff = objectiveValue; // relax
CbcEventHandler::CbcAction action =
dealWithEventHandler(CbcEventHandler::beforeSolution2,
objectiveValue, solution);
if (action == CbcEventHandler::killSolution) {
// Pretend solution never happened
objectiveValue = cutoff + 1.0e30;
}
if (objectiveValue > cutoff || objectiveValue > 1.0e30) {
if (objectiveValue > 1.0e30)
handler_->message(CBC_NOTFEAS1, messages_) << CoinMessageEol ;
else
handler_->message(CBC_NOTFEAS2, messages_)
<< objectiveValue << cutoff << CoinMessageEol ;
} else if (objectiveValue < bestObjective_) {
/*
We have a winner. Install it as the new incumbent.
Bump the objective cutoff value and solution counts. Give the user the
good news.
*/
specialOptions_ |= 256; // mark as full cut scan should be done
saveBestSolution(solution, objectiveValue);
//bestObjective_ = objectiveValue;
//int numberColumns = solver_->getNumCols();
//if (!bestSolution_)
//bestSolution_ = new double[numberColumns];
//CoinCopyN(solution,numberColumns,bestSolution_);
cutoff = bestObjective_ - dblParam_[CbcCutoffIncrement];
// But allow for rounding errors
if (dblParam_[CbcCutoffIncrement] == 1e-5) {
#if CBC_FEASIBILITY_INVESTIGATE
if (saveObjectiveValue + 1.0e-7 < bestObjective_)
printf("First try at solution had objective %.16g, rechecked as %.16g\n",
saveObjectiveValue, bestObjective_);
#endif
saveObjectiveValue = CoinMax(saveObjectiveValue, bestObjective_ - 0.0000001 * fabs(bestObjective_));
cutoff = CoinMin(bestObjective_, saveObjectiveValue) - 1.0e-5;
if (fabs(cutoff + 1.0e-5 - floor(cutoff + 0.5)) < 1.0e-8)
cutoff -= 2.0e-5;
}
if (!parentModel_&&(moreSpecialOptions2_&2)!=0) {
// put back objective
solver_->setObjective(continuousSolver_->getObjCoefficients());
double offset;
continuousSolver_->getDblParam(OsiObjOffset,offset);
solver_->setDblParam(OsiObjOffset,offset);
moreSpecialOptions2_ &= ~2;
}
// This is not correct - that way cutoff can go up if maximization
//double direction = solver_->getObjSense();
//setCutoff(cutoff*direction);
setCutoff(cutoff);
// change cutoff as constraint if wanted
if (cutoffRowNumber_>=0) {
if (solver_->getNumRows()>cutoffRowNumber_) {
double offset;
solver_->getDblParam(OsiObjOffset, offset);
solver_->setRowUpper(cutoffRowNumber_,cutoff+offset);
}
}
if (how == CBC_ROUNDING)
numberHeuristicSolutions_++;
numberSolutions_++;
if (how != CBC_ROUNDING) {
handler_->message(how, messages_)
<< bestObjective_ << numberIterations_
<< numberNodes_ << getCurrentSeconds()
<< CoinMessageEol;
} else {
const char * name ;
if (lastHeuristic_)
name = lastHeuristic_->heuristicName();
else
name = "Reduced search";
handler_->message(CBC_ROUNDING, messages_)
<< bestObjective_
<< name
<< numberIterations_
<< numberNodes_ << getCurrentSeconds()
<< CoinMessageEol;
dealWithEventHandler(CbcEventHandler::heuristicSolution,
objectiveValue, solution);
}
/*
Now step through the cut generators and see if any of them are flagged to
run when a new solution is discovered. Only global cuts are useful. (The
solution being evaluated may not correspond to the current location in the
search tree --- discovered by heuristic, for example.)
*/
OsiCuts theseCuts;
int i;
int lastNumberCuts = 0;
// reset probing info
//if (probingInfo_)
//probingInfo_->initializeFixing();
for (i = 0; i < numberCutGenerators_; i++) {
bool generate = generator_[i]->atSolution();
// skip if not optimal and should be (maybe a cut generator has fixed variables)
if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable())
generate = false;
if (generate) {
generator_[i]->generateCuts(theseCuts, 1, solver_, NULL);
int numberCuts = theseCuts.sizeRowCuts();
for (int j = lastNumberCuts; j < numberCuts; j++) {
const OsiRowCut * thisCut = theseCuts.rowCutPtr(j);
if (thisCut->globallyValid()) {
if ((specialOptions_&1) != 0) {
/* As these are global cuts -
a) Always get debugger object
b) Not fatal error to cutoff optimal (if we have just got optimal)
*/
const OsiRowCutDebugger *debugger = solver_->getRowCutDebuggerAlways() ;
if (debugger) {
if (debugger->invalidCut(*thisCut))
printf("ZZZZ Global cut - cuts off optimal solution!\n");
}
}
// add to global list
OsiRowCut newCut(*thisCut);
newCut.setGloballyValid(true);
newCut.mutableRow().setTestForDuplicateIndex(false);
globalCuts_.addCutIfNotDuplicate(newCut) ;
generator_[i]->incrementNumberCutsInTotal();
}
}
}
}
int numberCuts = theseCuts.sizeColCuts();
for (i = 0; i < numberCuts; i++) {
const OsiColCut * thisCut = theseCuts.colCutPtr(i);
if (thisCut->globallyValid()) {
// fix
makeGlobalCut(thisCut);
}
}
}
} else {
// Outer approximation or similar
double cutoff = getCutoff() ;
/*
Double check the solution to catch pretenders.
*/
int numberRowBefore = solver_->getNumRows();
int numberColBefore = solver_->getNumCols();
double *saveColSol = NULL;
CoinWarmStart * saveWs = NULL;
// if(how!=CBC_SOLUTION) return;
if (how == CBC_ROUNDING)//We don't want to make any change to solver_
//take a snapshot of current state
{
//save solution
saveColSol = new double[numberColBefore];
CoinCopyN(solver_->getColSolution(), numberColBefore, saveColSol);
//save warm start
saveWs = solver_->getWarmStart();
}
//run check solution this will eventually generate cuts
//if in strongBranching or heuristic will do only one cut generation iteration
// by fixing variables.
if (!fixVariables && ((how == CBC_ROUNDING) || (how == CBC_STRONGSOL)))
fixVariables = 1;
double * candidate = new double[numberColBefore];
CoinCopyN(solution, numberColBefore, candidate);
objectiveValue = checkSolution(cutoff, candidate, fixVariables, objectiveValue);
//If it was an heuristic solution we have to clean up the solver
if (how == CBC_ROUNDING) {
//delete the cuts
int currentNumberRowCuts = solver_->getNumRows() - numberRowBefore;
int currentNumberColCuts = solver_->getNumCols() - numberColBefore;
if (CoinMax(currentNumberColCuts, currentNumberRowCuts) > 0) {
int *which = new int[CoinMax(currentNumberColCuts, currentNumberRowCuts)];
if (currentNumberRowCuts) {
for (int i = 0 ; i < currentNumberRowCuts ; i++)
which[i] = i + numberRowBefore;
solver_->deleteRows(currentNumberRowCuts, which);
}
if (currentNumberColCuts) {
for (int i = 0 ; i < currentNumberColCuts ; i++)
which[i] = i + numberColBefore;
solver_->deleteCols(currentNumberColCuts, which);
}
delete [] which;
}
// Reset solution and warm start info
solver_->setColSolution(saveColSol);
solver_->setWarmStart(saveWs);
delete [] saveColSol;
delete saveWs;
}
if (objectiveValue > cutoff) {
// message only for solution
if (how == CBC_SOLUTION) {
if (!solverCharacteristics_->solutionAddsCuts()) {
if (objectiveValue > 1.0e30)
handler_->message(CBC_NOTFEAS1, messages_) << CoinMessageEol ;
else
handler_->message(CBC_NOTFEAS2, messages_)
<< objectiveValue << cutoff << CoinMessageEol ;
}
}
} else {
/*
We have a winner. Install it as the new incumbent.
Bump the objective cutoff value and solution counts. Give the user the
good news.
NB - Not all of this if from solve with cuts
*/
saveBestSolution(candidate, objectiveValue);
//bestObjective_ = objectiveValue;
//int numberColumns = solver_->getNumCols();
//if (!bestSolution_)
//bestSolution_ = new double[numberColumns];
//CoinCopyN(candidate,numberColumns,bestSolution_);
// don't update if from solveWithCuts
if (how != CBC_SOLUTION2) {
if (how == CBC_ROUNDING)
numberHeuristicSolutions_++;
cutoff = bestObjective_ - dblParam_[CbcCutoffIncrement];
// This is not correct - that way cutoff can go up if maximization
//double direction = solver_->getObjSense();
//setCutoff(cutoff*direction);
setCutoff(cutoff);
// change cutoff as constraint if wanted
if (cutoffRowNumber_>=0) {
if (solver_->getNumRows()>cutoffRowNumber_) {
double offset;
solver_->getDblParam(OsiObjOffset, offset);
solver_->setRowUpper(cutoffRowNumber_,cutoff+offset);
}
}
numberSolutions_++;
if (how != CBC_ROUNDING) {
handler_->message(how, messages_)
<< bestObjective_ << numberIterations_
<< numberNodes_ << getCurrentSeconds()
<< CoinMessageEol;
} else {
assert (lastHeuristic_);
const char * name = lastHeuristic_->heuristicName();
handler_->message(CBC_ROUNDING, messages_)
<< bestObjective_
<< name
<< numberIterations_
<< numberNodes_ << getCurrentSeconds()
<< CoinMessageEol;
}
}
}
delete [] candidate;
}
delete [] solution;
return ;
}
// Deals with event handler and solution
CbcEventHandler::CbcAction
CbcModel::dealWithEventHandler(CbcEventHandler::CbcEvent event,
double objValue,
const double * solution)
{
CbcEventHandler *eventHandler = getEventHandler() ;
if (eventHandler) {
// Temporarily put in best
double saveObj = bestObjective_;
int numberColumns = solver_->getNumCols();
double * saveSol = CoinCopyOfArray(bestSolution_, numberColumns);
if (!saveSol)
bestSolution_ = new double [numberColumns];
bestObjective_ = objValue;
memcpy(bestSolution_, solution, numberColumns*sizeof(double));
if (CbcEventHandler::solution==event) std::cerr << " event(solution) " << __FILE__ << ":" << __LINE__ << " " << std::flush; else if ( CbcEventHandler::heuristicSolution==event) std::cerr << " event(heuristicSolution) " << __FILE__ << ":" << __LINE__ << " " << std::flush; CbcEventHandler::CbcAction action =
eventHandler->event(event);
bestObjective_ = saveObj;
if (saveSol) {
memcpy(bestSolution_, saveSol, numberColumns*sizeof(double));
delete [] saveSol;
} else {
delete [] bestSolution_;
bestSolution_ = NULL;
}
return action;
} else {
return CbcEventHandler::noAction;
}
}
/* Test the current solution for feasibility.
Calculate the number of standard integer infeasibilities, then scan the
remaining objects to see if any of them report infeasibilities.
Currently (2003.08) the only object besides SimpleInteger is Clique, hence
the comments about `odd ones' infeasibilities.
*/
bool
CbcModel::feasibleSolution(int & numberIntegerInfeasibilities,
int & numberObjectInfeasibilities) const
{
int numberUnsatisfied = 0;
//double sumUnsatisfied=0.0;
int j;
// Point to current solution
const double * save = testSolution_;
// Safe as will be const inside infeasibility()
testSolution_ = solver_->getColSolution();
// Put current solution in safe place
//memcpy(currentSolution_,solver_->getColSolution(),
// solver_->getNumCols()*sizeof(double));
// point to useful information
OsiBranchingInformation usefulInfo = usefulInformation();
#define SIMPLE_INTEGER
#ifdef SIMPLE_INTEGER
const double * solution = usefulInfo.solution_;
const double * lower = usefulInfo.lower_;
const double * upper = usefulInfo.upper_;
double tolerance = usefulInfo.integerTolerance_;
#endif
for (j = 0; j < numberIntegers_; j++) {
#ifndef SIMPLE_INTEGER
const OsiObject * object = object_[j];
double infeasibility = object->checkInfeasibility(&usefulInfo);
if (infeasibility) {
assert (infeasibility > 0);
numberUnsatisfied++;
//sumUnsatisfied += infeasibility;
}
#else
int iColumn = integerVariable_[j];
double value = solution[iColumn];
value = CoinMax(value, lower[iColumn]);
value = CoinMin(value, upper[iColumn]);
double nearest = floor(value + 0.5);
if (fabs(value - nearest) > tolerance) {
numberUnsatisfied++;
}
#endif
}
numberIntegerInfeasibilities = numberUnsatisfied;
for (; j < numberObjects_; j++) {
const OsiObject * object = object_[j];
double infeasibility = object->checkInfeasibility(&usefulInfo);
if (infeasibility) {
assert (infeasibility > 0);
numberUnsatisfied++;
//sumUnsatisfied += infeasibility;
}
}
// and restore
testSolution_ = save;
numberObjectInfeasibilities = numberUnsatisfied - numberIntegerInfeasibilities;
return (!numberUnsatisfied);
}
/* For all vubs see if we can tighten bounds by solving Lp's
type - 0 just vubs
1 all (could be very slow)
-1 just vubs where variable away from bound
Returns false if not feasible
*/
bool
CbcModel::tightenVubs(int type, bool allowMultipleBinary, double useCutoff)
{
CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow());
int numberRows = solver_->getNumRows();
int numberColumns = solver_->getNumCols();
int iRow, iColumn;
// Row copy
//const double * elementByRow = matrixByRow.getElements();
const int * column = matrixByRow.getIndices();
const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
const int * rowLength = matrixByRow.getVectorLengths();
const double * colUpper = solver_->getColUpper();
const double * colLower = solver_->getColLower();
//const double * rowUpper = solver_->getRowUpper();
//const double * rowLower = solver_->getRowLower();
const double * objective = solver_->getObjCoefficients();
//double direction = solver_->getObjSense();
const double * colsol = solver_->getColSolution();
int numberVub = 0;
int * continuous = new int[numberColumns];
if (type >= 0) {
double * sort = new double[numberColumns];
for (iRow = 0; iRow < numberRows; iRow++) {
int j;
int numberBinary = 0;
int numberUnsatisfiedBinary = 0;
int numberContinuous = 0;
int iCont = -1;
double weight = 1.0e30;
for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
int iColumn = column[j];
if (colUpper[iColumn] - colLower[iColumn] > 1.0e-8) {
if (solver_->isFreeBinary(iColumn)) {
numberBinary++;
/* For sort I make naive assumption:
x - a * delta <=0 or
-x + a * delta >= 0
*/
if (colsol[iColumn] > colLower[iColumn] + 1.0e-6 &&
colsol[iColumn] < colUpper[iColumn] - 1.0e-6) {
numberUnsatisfiedBinary++;
weight = CoinMin(weight, fabs(objective[iColumn]));
}
} else {
numberContinuous++;
iCont = iColumn;
}
}
}
if (numberContinuous == 1 && numberBinary) {
if (numberBinary == 1 || allowMultipleBinary) {
// treat as vub
if (!numberUnsatisfiedBinary)
weight = -1.0; // at end
sort[numberVub] = -weight;
continuous[numberVub++] = iCont;
}
}
}
if (type > 0) {
// take so many
CoinSort_2(sort, sort + numberVub, continuous);
numberVub = CoinMin(numberVub, type);
}
delete [] sort;
} else {
for (iColumn = 0; iColumn < numberColumns; iColumn++)
continuous[iColumn] = iColumn;
numberVub = numberColumns;
}
bool feasible = tightenVubs(numberVub, continuous, useCutoff);
delete [] continuous;
return feasible;
}
// This version is just handed a list of variables
bool
CbcModel::tightenVubs(int numberSolves, const int * which,
double useCutoff)
{
int numberColumns = solver_->getNumCols();
int iColumn;
OsiSolverInterface * solver = solver_;
double saveCutoff = getCutoff() ;
double * objective = new double[numberColumns];
memcpy(objective, solver_->getObjCoefficients(), numberColumns*sizeof(double));
double direction = solver_->getObjSense();
// add in objective if there is a cutoff
if (useCutoff < 1.0e30) {
// get new version of model
solver = solver_->clone();
CoinPackedVector newRow;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
solver->setObjCoeff(iColumn, 0.0); // zero out in new model
if (objective[iColumn])
newRow.insert(iColumn, direction * objective[iColumn]);
}
solver->addRow(newRow, -COIN_DBL_MAX, useCutoff);
// signal no objective
delete [] objective;
objective = NULL;
}
setCutoff(COIN_DBL_MAX);
bool * vub = new bool [numberColumns];
int iVub;
// mark vub columns
for (iColumn = 0; iColumn < numberColumns; iColumn++)
vub[iColumn] = false;
for (iVub = 0; iVub < numberSolves; iVub++)
vub[which[iVub]] = true;
OsiCuts cuts;
// First tighten bounds anyway if CglProbing there
CglProbing* generator = NULL;
int iGen;
// reset probing info
//if (probingInfo_)
//probingInfo_->initializeFixing();
for (iGen = 0; iGen < numberCutGenerators_; iGen++) {
generator = dynamic_cast<CglProbing*>(generator_[iGen]->generator());
if (generator)
break;
}
int numberFixed = 0;
int numberTightened = 0;
int numberFixedByProbing = 0;
int numberTightenedByProbing = 0;
int printFrequency = (numberSolves + 19) / 20; // up to 20 messages
int save[4] = {0, 0, 0, 0};
if (generator) {
// set to cheaper and then restore at end
save[0] = generator->getMaxPass();
save[1] = generator->getMaxProbe();
save[2] = generator->getMaxLook();
save[3] = generator->rowCuts();
generator->setMaxPass(1);
generator->setMaxProbe(10);
generator->setMaxLook(50);
generator->setRowCuts(0);
// Probing - return tight column bounds
CglTreeInfo info;
generator->generateCutsAndModify(*solver, cuts, &info);
const double * tightLower = generator->tightLower();
const double * lower = solver->getColLower();
const double * tightUpper = generator->tightUpper();
const double * upper = solver->getColUpper();
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
double newUpper = tightUpper[iColumn];
double newLower = tightLower[iColumn];
if (newUpper < upper[iColumn] - 1.0e-8*(fabs(upper[iColumn]) + 1) ||
newLower > lower[iColumn] + 1.0e-8*(fabs(lower[iColumn]) + 1)) {
if (newUpper < newLower) {
fprintf(stderr, "Problem is infeasible\n");
return false;
}
if (newUpper == newLower) {
numberFixed++;
numberFixedByProbing++;
solver->setColLower(iColumn, newLower);
solver->setColUpper(iColumn, newUpper);
COIN_DETAIL_PRINT(printf("Column %d, new bounds %g %g\n", iColumn,
newLower, newUpper));
} else if (vub[iColumn]) {
numberTightened++;
numberTightenedByProbing++;
if (!solver->isInteger(iColumn)) {
// relax
newLower = CoinMax(lower[iColumn],
newLower
- 1.0e-5 * (fabs(lower[iColumn]) + 1));
newUpper = CoinMin(upper[iColumn],
newUpper
+ 1.0e-5 * (fabs(upper[iColumn]) + 1));
}
solver->setColLower(iColumn, newLower);
solver->setColUpper(iColumn, newUpper);
}
}
}
}
CoinWarmStart * ws = solver->getWarmStart();
double * solution = new double [numberColumns];
memcpy(solution, solver->getColSolution(), numberColumns*sizeof(double));
for (iColumn = 0; iColumn < numberColumns; iColumn++)
solver->setObjCoeff(iColumn, 0.0);
//solver->messageHandler()->setLogLevel(2);
for (iVub = 0; iVub < numberSolves; iVub++) {
iColumn = which[iVub];
int iTry;
for (iTry = 0; iTry < 2; iTry++) {
double saveUpper = solver->getColUpper()[iColumn];
double saveLower = solver->getColLower()[iColumn];
double value;
if (iTry == 1) {
// try all way up
solver->setObjCoeff(iColumn, -1.0);
} else {
// try all way down
solver->setObjCoeff(iColumn, 1.0);
}
solver->initialSolve();
setPointers(continuousSolver_);
value = solver->getColSolution()[iColumn];
bool change = false;
if (iTry == 1) {
if (value < saveUpper - 1.0e-4) {
if (solver->isInteger(iColumn)) {
value = floor(value + 0.00001);
} else {
// relax a bit
value = CoinMin(saveUpper, value + 1.0e-8 * (fabs(saveUpper) + 1));
}
if (value - saveLower < 1.0e-7)
value = saveLower; // make sure exactly same
solver->setColUpper(iColumn, value);
saveUpper = value;
change = true;
}
} else {
if (value > saveLower + 1.0e-4) {
if (solver->isInteger(iColumn)) {
value = ceil(value - 0.00001);
} else {
// relax a bit
value = CoinMax(saveLower, value - 1.0e-8 * (fabs(saveLower) + 1));
}
if (saveUpper - value < 1.0e-7)
value = saveUpper; // make sure exactly same
solver->setColLower(iColumn, value);
saveLower = value;
change = true;
}
}
solver->setObjCoeff(iColumn, 0.0);
if (change) {
if (saveUpper == saveLower)
numberFixed++;
else
numberTightened++;
int saveFixed = numberFixed;
int jColumn;
if (generator) {
// Probing - return tight column bounds
cuts = OsiCuts();
CglTreeInfo info;
generator->generateCutsAndModify(*solver, cuts, &info);
const double * tightLower = generator->tightLower();
const double * lower = solver->getColLower();
const double * tightUpper = generator->tightUpper();
const double * upper = solver->getColUpper();
for (jColumn = 0; jColumn < numberColumns; jColumn++) {
double newUpper = tightUpper[jColumn];
double newLower = tightLower[jColumn];
if (newUpper < upper[jColumn] - 1.0e-8*(fabs(upper[jColumn]) + 1) ||
newLower > lower[jColumn] + 1.0e-8*(fabs(lower[jColumn]) + 1)) {
if (newUpper < newLower) {
fprintf(stderr, "Problem is infeasible\n");
return false;
}
if (newUpper == newLower) {
numberFixed++;
numberFixedByProbing++;
solver->setColLower(jColumn, newLower);
solver->setColUpper(jColumn, newUpper);
} else if (vub[jColumn]) {
numberTightened++;
numberTightenedByProbing++;
if (!solver->isInteger(jColumn)) {
// relax
newLower = CoinMax(lower[jColumn],
newLower
- 1.0e-8 * (fabs(lower[jColumn]) + 1));
newUpper = CoinMin(upper[jColumn],
newUpper
+ 1.0e-8 * (fabs(upper[jColumn]) + 1));
}
solver->setColLower(jColumn, newLower);
solver->setColUpper(jColumn, newUpper);
}
}
}
}
if (numberFixed > saveFixed) {
// original solution may not be feasible
// go back to true costs to solve if exists
if (objective) {
for (jColumn = 0; jColumn < numberColumns; jColumn++)
solver->setObjCoeff(jColumn, objective[jColumn]);
}
solver->setColSolution(solution);
solver->setWarmStart(ws);
solver->resolve();
if (!solver->isProvenOptimal()) {
fprintf(stderr, "Problem is infeasible\n");
return false;
}
delete ws;
ws = solver->getWarmStart();
memcpy(solution, solver->getColSolution(),
numberColumns*sizeof(double));
for (jColumn = 0; jColumn < numberColumns; jColumn++)
solver->setObjCoeff(jColumn, 0.0);
}
}
solver->setColSolution(solution);
solver->setWarmStart(ws);
}
if (iVub % printFrequency == 0)
handler_->message(CBC_VUB_PASS, messages_)
<< iVub + 1 << numberFixed << numberTightened
<< CoinMessageEol;
}
handler_->message(CBC_VUB_END, messages_)
<< numberFixed << numberTightened
<< CoinMessageEol;
delete ws;
delete [] solution;
// go back to true costs to solve if exists
if (objective) {
for (iColumn = 0; iColumn < numberColumns; iColumn++)
solver_->setObjCoeff(iColumn, objective[iColumn]);
delete [] objective;
}
delete [] vub;
if (generator) {
/*printf("Probing fixed %d and tightened %d\n",
numberFixedByProbing,
numberTightenedByProbing);*/
if (generator_[iGen]->howOften() == -1 &&
(numberFixedByProbing + numberTightenedByProbing)*5 >
(numberFixed + numberTightened))
generator_[iGen]->setHowOften(1000000 + 1);
generator->setMaxPass(save[0]);
generator->setMaxProbe(save[1]);
generator->setMaxLook(save[2]);
generator->setRowCuts(save[3]);
}
if (solver != solver_) {
// move bounds across
const double * lower = solver->getColLower();
const double * upper = solver->getColUpper();
const double * lowerOrig = solver_->getColLower();
const double * upperOrig = solver_->getColUpper();
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
solver_->setColLower(iColumn, CoinMax(lower[iColumn], lowerOrig[iColumn]));
solver_->setColUpper(iColumn, CoinMin(upper[iColumn], upperOrig[iColumn]));
}
delete solver;
}
setCutoff(saveCutoff);
return true;
}
// Pass in Message handler (not deleted at end)
void
CbcModel::passInMessageHandler(CoinMessageHandler * handler)
{
if (defaultHandler_) {
delete handler_;
handler_ = NULL;
}
defaultHandler_ = false;
handler_ = handler;
if (solver_)
solver_->passInMessageHandler(handler);
if (continuousSolver_)
continuousSolver_->passInMessageHandler(handler);
if (referenceSolver_)
referenceSolver_->passInMessageHandler(handler);
}
void
CbcModel::passInTreeHandler(CbcTree & tree)
{
delete tree_;
tree_ = tree.clone();
}
// Make sure region there
void
CbcModel::reserveCurrentSolution(const double * solution)
{
int numberColumns = getNumCols() ;
if (!currentSolution_)
currentSolution_ = new double[numberColumns] ;
testSolution_ = currentSolution_;
if (solution)
memcpy(currentSolution_, solution, numberColumns*sizeof(double));
}
/* For passing in an CbcModel to do a sub Tree (with derived tree handlers).
Passed in model must exist for duration of branch and bound
*/
void
CbcModel::passInSubTreeModel(CbcModel & model)
{
subTreeModel_ = &model;
}
// For retrieving a copy of subtree model with given OsiSolver or NULL
CbcModel *
CbcModel::subTreeModel(OsiSolverInterface * solver) const
{
const CbcModel * subModel = subTreeModel_;
if (!subModel)
subModel = this;
// Get new copy
CbcModel * newModel = new CbcModel(*subModel);
if (solver)
newModel->assignSolver(solver);
return newModel;
}
//#############################################################################
// Set/Get Application Data
// This is a pointer that the application can store into and retrieve
// from the solverInterface.
// This field is the application to optionally define and use.
//#############################################################################
void CbcModel::setApplicationData(void * appData)
{
appData_ = appData;
}
//-----------------------------------------------------------------------------
void * CbcModel::getApplicationData() const
{
return appData_;
}
// Set a pointer to a row cut which will be added instead of normal branching.
void
CbcModel::setNextRowCut(const OsiRowCut & cut)
{
nextRowCut_ = new OsiRowCut(cut);
nextRowCut_->setEffectiveness(COIN_DBL_MAX); // mark so will always stay
}
// Just update objectiveValue
void CbcModel::setBestObjectiveValue( double objectiveValue)
{
bestObjective_ = objectiveValue;
}
double
CbcModel::getBestPossibleObjValue() const
{
return CoinMin(bestPossibleObjective_, bestObjective_) * solver_->getObjSense() ;
}
// Make given rows (L or G) into global cuts and remove from lp
void
CbcModel::makeGlobalCuts(int number, const int * which)
{
const double * rowLower = solver_->getRowLower();
const double * rowUpper = solver_->getRowUpper();
int numberRows = solver_->getNumRows();
// Row copy
const double * elementByRow = solver_->getMatrixByRow()->getElements();
const int * column = solver_->getMatrixByRow()->getIndices();
const CoinBigIndex * rowStart = solver_->getMatrixByRow()->getVectorStarts();
const int * rowLength = solver_->getMatrixByRow()->getVectorLengths();
// Not all rows may be good so we need new array
int * whichDelete = new int[numberRows];
int nDelete = 0;
for (int i = 0; i < number; i++) {
int iRow = which[i];
if (iRow >= 0 && iRow < numberRows) {
if (rowLower[iRow] < -1.0e20 || rowUpper[iRow] > 1.0e20) {
whichDelete[nDelete++] = iRow;
OsiRowCut thisCut;
thisCut.setLb(rowLower[iRow]);
thisCut.setUb(rowUpper[iRow]);
int start = rowStart[iRow];
thisCut.setRow(rowLength[iRow], column + start, elementByRow + start, false);
thisCut.setGloballyValid(true);
globalCuts_.addCutIfNotDuplicate(thisCut) ;
}
}
}
if (nDelete)
solver_->deleteRows(nDelete, whichDelete);
delete [] whichDelete;
}
// Make given cut into a global cut
int
CbcModel::makeGlobalCut(const OsiRowCut * cut)
{
if (cut->row().getNumElements()>1-1) {
OsiRowCut newCut(*cut);
newCut.setGloballyValidAsInteger(2);
newCut.mutableRow().setTestForDuplicateIndex(false);
return globalCuts_.addCutIfNotDuplicate(newCut,1) ;
} else {
assert (cut->row().getNumElements()==1);
int iColumn = cut->row().getIndices()[0];
double value = cut->row().getElements()[0];
double lb = cut->lb();
double ub = cut->ub();
if (value>0) {
if (lb>-COIN_DBL_MAX)
lb /= value;
if (ub<COIN_DBL_MAX)
ub /= value;
} else {
double saveUb=ub;
if (lb>-COIN_DBL_MAX)
ub = lb/value;
else
ub = COIN_DBL_MAX;
if (saveUb<COIN_DBL_MAX)
lb = saveUb/value;
else
lb =- COIN_DBL_MAX;
}
#if PRINT_CONFLICT==0
if (handler_->logLevel() > 1) {
#endif
printf("Conflict cut at depth %d (%d elements)\n",
currentDepth_,cut->row().getNumElements());
cut->print();
#if PRINT_CONFLICT==0
}
#endif
const double * lower;
const double * upper;
if (topOfTree_) {
lower = topOfTree_->lower();
upper = topOfTree_->upper();
lb = CoinMax(lb,lower[iColumn]);
topOfTree_->setColLower(iColumn,lb);
ub = CoinMin(ub,upper[iColumn]);
topOfTree_->setColUpper(iColumn,ub);
} else {
lower = solver_->getColLower();
upper = solver_->getColUpper();
lb = CoinMax(lb,lower[iColumn]);
solver_->setColLower(iColumn,lb);
ub = CoinMin(ub,upper[iColumn]);
solver_->setColUpper(iColumn,ub);
}
return 1;
}
}
// Make given cut into a global cut
int
CbcModel::makeGlobalCut(const OsiRowCut & cut)
{
OsiRowCut newCut(cut);
newCut.setGloballyValid(true);
newCut.mutableRow().setTestForDuplicateIndex(false);
return globalCuts_.addCutIfNotDuplicate(newCut) ;
}
// Make given column cut into a global cut
void
CbcModel::makeGlobalCut(const OsiColCut * cut)
{
const double * lower;
const double * upper;
if (topOfTree_) {
lower = topOfTree_->lower();
upper = topOfTree_->upper();
} else {
lower = solver_->getColLower();
upper = solver_->getColUpper();
}
int nLower=cut->lbs().getNumElements();
const int * indexLower=cut->lbs().getIndices();
const double * boundLower=cut->lbs().getElements();
for (int i=0;i<nLower;i++) {
int iColumn=indexLower[i];
double newValue=CoinMax(lower[iColumn],boundLower[iColumn]);
if (topOfTree_)
topOfTree_->setColLower(iColumn,newValue);
else
solver_->setColLower(iColumn,newValue);
}
int nUpper=cut->ubs().getNumElements();
const int * indexUpper=cut->ubs().getIndices();
const double * boundUpper=cut->ubs().getElements();
for (int i=0;i<nUpper;i++) {
int iColumn=indexUpper[i];
double newValue=CoinMin(upper[iColumn],boundUpper[iColumn]);
if (topOfTree_)
topOfTree_->setColUpper(iColumn,newValue);
else
solver_->setColUpper(iColumn,newValue);
}
}
// Make given column cut into a global cut
void
CbcModel::makeGlobalCut(const OsiColCut & cut)
{
const double * lower;
const double * upper;
if (topOfTree_) {
lower = topOfTree_->lower();
upper = topOfTree_->upper();
} else {
lower = solver_->getColLower();
upper = solver_->getColUpper();
}
int nLower=cut.lbs().getNumElements();
const int * indexLower=cut.lbs().getIndices();
const double * boundLower=cut.lbs().getElements();
for (int i=0;i<nLower;i++) {
int iColumn=indexLower[i];
double newValue=CoinMax(lower[iColumn],boundLower[iColumn]);
if (topOfTree_)
topOfTree_->setColLower(iColumn,newValue);
else
solver_->setColLower(iColumn,newValue);
}
int nUpper=cut.ubs().getNumElements();
const int * indexUpper=cut.ubs().getIndices();
const double * boundUpper=cut.ubs().getElements();
for (int i=0;i<nUpper;i++) {
int iColumn=indexUpper[i];
double newValue=CoinMin(upper[iColumn],boundUpper[iColumn]);
if (topOfTree_)
topOfTree_->setColUpper(iColumn,newValue);
else
solver_->setColUpper(iColumn,newValue);
}
}
// Make partial cut into a global cut and save
void
CbcModel::makePartialCut(const OsiRowCut * partialCut,
const OsiSolverInterface * solver)
{
// get greedy cut
double bSum = partialCut->lb();
assert (bSum<0.0);
if (!solver)
solver=solver_;
int nConflict = partialCut->row().getNumElements();
const int * column = partialCut->row().getIndices();
const double * element = partialCut->row().getElements();
double * originalLower = topOfTree_->mutableLower();
const double * columnLower = solver->getColLower();
double * originalUpper = topOfTree_->mutableUpper();
const double * columnUpper = solver->getColUpper();
int nC=nConflict;
while (nConflict) {
int iColumn = column[nConflict-1];
double farkasValue = element[nConflict-1];
double change;
if (farkasValue>0.0) {
change=farkasValue*(originalUpper[iColumn]-columnUpper[iColumn]);
} else {
change=farkasValue*(originalLower[iColumn]-columnLower[iColumn]);
}
if (bSum+change>-1.0e-4)
break;
nConflict--;
bSum += change;
}
OsiRowCut newCut;
newCut.setUb(COIN_DBL_MAX);
double lo=1.0;
double * values = new double[nConflict];
for (int i=0;i<nConflict;i++) {
int iColumn = column[i];
if (originalLower[iColumn]==columnLower[iColumn]) {
// must be at least one higher
values[i]=1.0;
lo += originalLower[iColumn];
} else {
// must be at least one lower
values[i]=-1.0;
lo -= originalUpper[iColumn];
}
}
newCut.setLb(lo);
newCut.setRow(nConflict,column,values);
printf("CUTa has %d (started at %d) - final bSum %g - depth %d\n",nConflict,nC,bSum,currentDepth_);
if (nConflict>1) {
if ((specialOptions_&1) != 0) {
const OsiRowCutDebugger *debugger = continuousSolver_->getRowCutDebugger() ;
if (debugger) {
if (debugger->invalidCut(newCut)) {
continuousSolver_->applyRowCuts(1,&newCut);
continuousSolver_->writeMps("bad");
}
CoinAssert (!debugger->invalidCut(newCut));
}
}
newCut.setGloballyValidAsInteger(2);
newCut.mutableRow().setTestForDuplicateIndex(false);
globalCuts_.addCutIfNotDuplicate(newCut) ;
} else {
// change bounds
int iColumn=column[0];
if (values[0]<0.0) {
// change upper bound
double newUpper = -lo;
assert (newUpper<originalUpper[iColumn]);
printf("Changing upper bound on %d from %g to %g\n",
iColumn,originalUpper[iColumn],newUpper);
originalUpper[iColumn]=newUpper;
} else {
// change lower bound
double newLower = lo;
assert (newLower>originalLower[iColumn]);
printf("Changing lower bound on %d from %g to %g\n",
iColumn,originalLower[iColumn],newLower);
originalLower[iColumn]=newLower;
}
}
// add to partial cuts
if (globalConflictCuts_) {
globalConflictCuts_->addCutIfNotDuplicateWhenGreedy(*partialCut,2);
}
delete [] values;
}
// Make partial cuts into global cuts
void
CbcModel::makeGlobalCuts()
{
}
void
CbcModel::setNodeComparison(CbcCompareBase * compare)
{
delete nodeCompare_;
nodeCompare_ = compare->clone();
}
void
CbcModel::setNodeComparison(CbcCompareBase & compare)
{
delete nodeCompare_;
nodeCompare_ = compare.clone();
}
void
CbcModel::setProblemFeasibility(CbcFeasibilityBase * feasibility)
{
delete problemFeasibility_;
problemFeasibility_ = feasibility->clone();
}
void
CbcModel::setProblemFeasibility(CbcFeasibilityBase & feasibility)
{
delete problemFeasibility_;
problemFeasibility_ = feasibility.clone();
}
// Set the strategy. Clones
void
CbcModel::setStrategy(CbcStrategy & strategy)
{
delete strategy_;
strategy_ = strategy.clone();
}
// Increases usedInSolution for nonzeros
void
CbcModel::incrementUsed(const double * solution)
{
if(usedInSolution_) {
// might as well mark all including continuous
int numberColumns = solver_->getNumCols();
for (int i = 0; i < numberColumns; i++) {
if (solution[i])
usedInSolution_[i]++;
}
}
}
// Are there numerical difficulties (for initialSolve) ?
bool
CbcModel::isInitialSolveAbandoned() const
{
if (status_ != -1) {
return false;
} else {
return solver_->isAbandoned();
}
}
// Is optimality proven (for initialSolve) ?
bool
CbcModel::isInitialSolveProvenOptimal() const
{
if (status_ != -1) {
return fabs(originalContinuousObjective_) < 1.0e50;
} else {
return solver_->isProvenOptimal();
}
}
// Is primal infeasiblity proven (for initialSolve) ?
bool
CbcModel::isInitialSolveProvenPrimalInfeasible() const
{
if (status_ != -1) {
if (status_ == 0 && secondaryStatus_ == 7)
return false;
else
return originalContinuousObjective_ >= 1.0e50;
} else {
return solver_->isProvenPrimalInfeasible();
}
}
// Is dual infeasiblity proven (for initialSolve) ?
bool
CbcModel::isInitialSolveProvenDualInfeasible() const
{
if (status_ != -1) {
if (status_ == 0 && secondaryStatus_ == 7)
return true;
else
return false;
} else {
return solver_->isProvenDualInfeasible();
}
}
// Set pointers for speed
void
CbcModel::setPointers(const OsiSolverInterface * solver)
{
/// Pointer to array[getNumCols()] (for speed) of column lower bounds
cbcColLower_ = solver_->getColLower();
/// Pointer to array[getNumCols()] (for speed) of column upper bounds
cbcColUpper_ = solver_->getColUpper();
/// Pointer to array[getNumRows()] (for speed) of row lower bounds
cbcRowLower_ = solver_->getRowLower();
/// Pointer to array[getNumRows()] (for speed) of row upper bounds
cbcRowUpper_ = solver_->getRowUpper();
/// Pointer to array[getNumCols()] (for speed) of primal solution vector
cbcColSolution_ = solver_->getColSolution();
/// Pointer to array[getNumRows()] (for speed) of dual prices
cbcRowPrice_ = solver_->getRowPrice();
/// Get a pointer to array[getNumCols()] (for speed) of reduced costs
if (solverCharacteristics_ && solverCharacteristics_->reducedCostsAccurate())
cbcReducedCost_ = solver_->getReducedCost();
else
cbcReducedCost_ = NULL;
/// Pointer to array[getNumRows()] (for speed) of row activity levels.
cbcRowActivity_ = solver_->getRowActivity();
dblParam_[CbcCurrentObjectiveValue] = solver->getObjValue();
dblParam_[CbcCurrentMinimizationObjectiveValue] =
dblParam_[CbcCurrentObjectiveValue] *
dblParam_[CbcOptimizationDirection];
}
/*
Delete any existing handler and create a clone of the one supplied.
*/
void CbcModel::passInEventHandler (const CbcEventHandler *eventHandler)
{
delete eventHandler_;
eventHandler_ = NULL ;
if (eventHandler) {
eventHandler_ = eventHandler->clone();
eventHandler_->setModel(this);
}
}
/*
CbcEventHandler* CbcModel::eventHandler is inlined in CbcModel.hpp.
*/
// Encapsulates solver resolve
int
CbcModel::resolve(OsiSolverInterface * solver)
{
numberSolves_++;
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver);
#endif
#ifdef CLIQUE_ANALYSIS
if (probingInfo_ && currentDepth_ > 0) {
int nFix = probingInfo_->fixColumns(*solver);
#ifdef SWITCH_VARIABLES
if (nFix>0)
fixAssociated(solver_,0);
#endif
if (nFix < 0) {
#ifdef COIN_HAS_CLP
if (clpSolver)
clpSolver->getModelPtr()->setProblemStatus(1);
#endif
return 0;
}
}
#endif
#ifdef COIN_HAS_CLP
if (clpSolver) {
/*bool takeHint;
OsiHintStrength strength;
bool gotHint = (clpSolver->getHintParam(OsiDoDualInResolve,takeHint,strength));
assert (gotHint);
int algorithm=-1;
if (strength!=OsiHintIgnore)
algorithm = takeHint ? -1 : 1;
assert (algorithm==-1);*/
//clpSolver->setHintParam(OsiDoDualInResolve,true,OsiHintTry);
ClpSimplex * clpSimplex = clpSolver->getModelPtr();
int save = clpSimplex->specialOptions();
if ((moreSpecialOptions_&8388608)==0)
clpSimplex->setSpecialOptions(save | 0x11000000); // say is Cbc (and in branch and bound)
else
clpSimplex->setSpecialOptions(save | 0x11200000); // say is Cbc (and in branch and bound - but save ray)
int save2 = clpSolver->specialOptions();
if (false && (save2&2048) == 0) {
// see if worthwhile crunching
int nFixed = 0;
const double * columnLower = clpSimplex->columnLower();
const double * columnUpper = clpSimplex->columnUpper();
for (int i = 0; i < numberIntegers_; i++) {
int iColumn = integerVariable_[i];
if (columnLower[iColumn] == columnUpper[iColumn])
nFixed++;
}
if (nFixed*20 < clpSimplex->numberColumns()) {
double d = nFixed;
printf("%d fixed out of %d - ratio %g\n",
nFixed,
clpSimplex->numberColumns(),
d / clpSimplex->numberColumns());
clpSolver->setSpecialOptions(save2 | 2048);
}
}
#ifdef CHECK_KNOWN_SOLUTION
bool onOptimalPath = false;
if ((specialOptions_&1) != 0) {
const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
if (debugger) {
onOptimalPath = true;
printf("On optimal path before resolve\n") ;
}
}
#endif
clpSolver->resolve();
#ifdef CHECK_KNOWN_SOLUTION
if ((specialOptions_&1) != 0&&onOptimalPath) {
const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
if (debugger) {
printf("On optimal path after resolve\n") ;
} else {
solver_->writeMpsNative("badSolve.mps", NULL, NULL, 2);
printf("NOT on optimal path after resolve\n") ;
}
}
#endif
if (!numberNodes_) {
double error = CoinMax(clpSimplex->largestDualError(),
clpSimplex->largestPrimalError());
if (error > 1.0e-2 || !clpSolver->isProvenOptimal()) {
#if CBC_USEFUL_PRINTING>1
printf("Problem was %s largest dual error %g largest primal %g - safer cuts\n",
clpSolver->isProvenOptimal() ? "optimal" : "!infeasible",
clpSimplex->largestDualError(),
clpSimplex->largestPrimalError());
#endif
if (!clpSolver->isProvenOptimal()) {
clpSolver->setSpecialOptions(save2 | 2048);
clpSimplex->allSlackBasis(true);
clpSolver->resolve();
if (!clpSolver->isProvenOptimal()) {
bool takeHint;
OsiHintStrength strength;
clpSolver->getHintParam(OsiDoDualInResolve, takeHint, strength);
clpSolver->setHintParam(OsiDoDualInResolve, false, OsiHintDo);
clpSolver->resolve();
clpSolver->setHintParam(OsiDoDualInResolve, takeHint, strength);
}
}
// make cuts safer
for (int iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
CglCutGenerator * generator = generator_[iCutGenerator]->generator();
CglGomory * cgl1 = dynamic_cast<CglGomory *>(generator);
if (cgl1) {
cgl1->setLimitAtRoot(cgl1->getLimit());
}
CglTwomir * cgl2 = dynamic_cast<CglTwomir *>(generator);
if (cgl2) {
generator_[iCutGenerator]->setHowOften(-100);
}
}
}
}
clpSolver->setSpecialOptions(save2);
#if CBC_USEFUL_PRINTING>1
if (clpSimplex->numberIterations() > 1000)
printf("node %d took %d iterations\n", numberNodes_, clpSimplex->numberIterations());
#endif
clpSimplex->setSpecialOptions(save);
if (clpSimplex->status()==4)
clpSimplex->setProblemStatus(1);
} else {
solver->resolve();
}
#else
solver->resolve();
#endif
#ifdef SWITCH_VARIABLES
if (solver_->isProvenOptimal()) {
int nBad=checkAssociated(solver_,solver_->getColSolution(),0);
if (nBad)
checkAssociated(solver_,solver_->getColSolution(),1);
}
#endif
return solver->isProvenOptimal() ? 1 : 0;
}
#ifdef CLP_RESOLVE
// Special purpose resolve
int
CbcModel::resolveClp(OsiClpSolverInterface * clpSolver, int type)
{
numberSolves_++;
ClpSimplex * clpSimplex = clpSolver->getModelPtr();
int save = clpSimplex->specialOptions();
clpSimplex->setSpecialOptions(save | 0x11000000); // say is Cbc (and in branch and bound)
int save2 = clpSolver->specialOptions();
clpSolver->resolve();
if (!numberNodes_) {
double error = CoinMax(clpSimplex->largestDualError(),
clpSimplex->largestPrimalError());
if (error > 1.0e-2 || !clpSolver->isProvenOptimal()) {
#if CBC_USEFUL_PRINTING>1
printf("Problem was %s largest dual error %g largest primal %g - safer cuts\n",
clpSolver->isProvenOptimal() ? "optimal" : "!infeasible",
clpSimplex->largestDualError(),
clpSimplex->largestPrimalError());
#endif
if (!clpSolver->isProvenOptimal()) {
clpSolver->setSpecialOptions(save2 | 2048);
clpSimplex->allSlackBasis(true);
clpSolver->resolve();
if (!clpSolver->isProvenOptimal()) {
bool takeHint;
OsiHintStrength strength;
clpSolver->getHintParam(OsiDoDualInResolve, takeHint, strength);
clpSolver->setHintParam(OsiDoDualInResolve, false, OsiHintDo);
clpSolver->resolve();
clpSolver->setHintParam(OsiDoDualInResolve, takeHint, strength);
}
}
// make cuts safer
for (int iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
CglCutGenerator * generator = generator_[iCutGenerator]->generator();
CglGomory * cgl1 = dynamic_cast<CglGomory *>(generator);
if (cgl1) {
cgl1->setLimitAtRoot(cgl1->getLimit());
}
CglTwomir * cgl2 = dynamic_cast<CglTwomir *>(generator);
if (cgl2) {
generator_[iCutGenerator]->setHowOften(-100);
}
}
}
}
clpSolver->setSpecialOptions(save2);
#if CBC_USEFUL_PRINTING>1
if (clpSimplex->numberIterations() > 1000)
printf("node %d took %d iterations\n", numberNodes_, clpSimplex->numberIterations());
#endif
if (type==0 && clpSolver->isProvenOptimal()) {
ClpSimplex newModel(*clpSimplex);
newModel.primal();
int numberColumns = newModel.numberColumns();
int numberRows = newModel.numberRows();
double * obj = new double [numberColumns];
int * which = new int [numberColumns];
const double * solution = clpSimplex->primalColumnSolution();
double rhs=1.0e-8;
int numberObj=0;
double integerTolerance = getDblParam(CbcIntegerTolerance) ;
double * objective = newModel.objective();
for (int i=0;i<numberColumns;i++) {
if (objective[i]) {
rhs += objective[i]*solution[i];
obj[numberObj]=objective[i];
which[numberObj++]=i;
objective[i]=0.0;
}
}
if (numberObj) {
newModel.addRow(numberObj,which,obj,-COIN_DBL_MAX,rhs);
}
delete [] obj;
delete [] which;
double * lower = newModel.columnLower();
double * upper = newModel.columnUpper();
int numberInf = 0;
int numberLb = 0;
int numberUb = 0;
int numberInt = 0;
double sumInf=0.0;
for (int i=0;i<numberIntegers_;i++) {
int iSequence = integerVariable_[i];
double value = solution[iSequence];
value = CoinMax(value, lower[iSequence]);
value = CoinMin(value, upper[iSequence]);
double nearest = floor(value + 0.5);
if (value<lower[iSequence]+integerTolerance) {
objective[iSequence]=1.0;
numberLb++;
} else if (value>upper[iSequence]-integerTolerance) {
objective[iSequence]=-1.0;
numberUb++;
} else if (fabs(value - nearest) <= integerTolerance) {
// fix??
lower[iSequence]=nearest;
upper[iSequence]=nearest;
numberInt++;
} else {
lower[iSequence]=floor(value);
upper[iSequence]=ceil(value);
if (value>nearest) {
objective[iSequence]=1.0;
sumInf += value-nearest;
} else {
objective[iSequence]=-1.0;
sumInf -= value-nearest;
}
numberInf++;
}
}
printf("XX %d inf (sum %g), %d at lb %d at ub %d other integer\n",
numberInf,sumInf,numberLb,numberUb,numberInt);
if (numberInf) {
newModel.primal(1);
if (!newModel.isProvenOptimal()) {
printf("not optimal - scaling issue - switch off\n");
clpSimplex->setSpecialOptions(save);
if (clpSimplex->status()==4)
clpSimplex->setProblemStatus(1);
return clpSolver->isProvenOptimal() ? 1 : 0;
}
//newModel.writeMps("bad.mps");
//assert (newModel.isProvenOptimal());
printf("%d iterations\n",newModel.numberIterations());
int numberInf2 = 0;
int numberLb2 = 0;
int numberUb2 = 0;
int numberInt2 = 0;
double sumInf2=0.0;
const double * solution = newModel.primalColumnSolution();
const double * lower = clpSimplex->columnLower();
const double * upper = clpSimplex->columnUpper();
for (int i=0;i<numberIntegers_;i++) {
int iSequence = integerVariable_[i];
double value = solution[iSequence];
value = CoinMax(value, lower[iSequence]);
value = CoinMin(value, upper[iSequence]);
double nearest = floor(value + 0.5);
if (value<lower[iSequence]+integerTolerance) {
numberLb2++;
} else if (value>upper[iSequence]-integerTolerance) {
numberUb2++;
} else if (fabs(value - nearest) <= integerTolerance) {
numberInt2++;
} else {
if (value>nearest) {
sumInf2 += value-nearest;
} else {
sumInf2 -= value-nearest;
}
numberInf2++;
}
}
printf("XXX %d inf (sum %g), %d at lb %d at ub %d other integer\n",
numberInf2,sumInf2,numberLb2,numberUb2,numberInt2);
if (sumInf2<sumInf*0.95) {
printf("XXXX suminf reduced from %g (%d) to %g (%d)\n",
sumInf,numberInf,sumInf2,numberInf2);
if (numberObj) {
newModel.deleteRows(1,&numberRows);
}
memcpy(newModel.objective(),
clpSimplex->objective(),
numberColumns*sizeof(double));
memcpy(newModel.columnLower(),
clpSimplex->columnLower(),
numberColumns*sizeof(double));
memcpy(newModel.columnUpper(),
clpSimplex->columnUpper(),
numberColumns*sizeof(double));
newModel.setClpScaledMatrix(NULL);
newModel.primal(1);
printf("%d iterations\n",newModel.numberIterations());
int numberInf3 = 0;
int numberLb3 = 0;
int numberUb3 = 0;
int numberInt3 = 0;
double sumInf3=0.0;
const double * solution = newModel.primalColumnSolution();
const double * lower = clpSimplex->columnLower();
const double * upper = clpSimplex->columnUpper();
for (int i=0;i<numberIntegers_;i++) {
int iSequence = integerVariable_[i];
double value = solution[iSequence];
value = CoinMax(value, lower[iSequence]);
value = CoinMin(value, upper[iSequence]);
double nearest = floor(value + 0.5);
if (value<lower[iSequence]+integerTolerance) {
numberLb3++;
} else if (value>upper[iSequence]-integerTolerance) {
numberUb3++;
} else if (fabs(value - nearest) <= integerTolerance) {
numberInt3++;
} else {
if (value>nearest) {
sumInf3 += value-nearest;
} else {
sumInf3 -= value-nearest;
}
numberInf3++;
}
}
printf("XXXXX %d inf (sum %g), %d at lb %d at ub %d other integer\n",
numberInf3,sumInf3,numberLb3,numberUb3,numberInt3);
if (sumInf3<sumInf*0.95) {
memcpy(clpSimplex->primalColumnSolution(),
newModel.primalColumnSolution(),
numberColumns*sizeof(double));
memcpy(clpSimplex->dualColumnSolution(),
newModel.dualColumnSolution(),
numberColumns*sizeof(double));
memcpy(clpSimplex->primalRowSolution(),
newModel.primalRowSolution(),
numberRows*sizeof(double));
memcpy(clpSimplex->dualRowSolution(),
newModel.dualRowSolution(),
numberRows*sizeof(double));
memcpy(clpSimplex->statusArray(),
newModel.statusArray(),
(numberColumns+numberRows)*sizeof(unsigned char));
clpSolver->setWarmStart(NULL);
}
}
}
}
clpSimplex->setSpecialOptions(save);
if (clpSimplex->status()==4)
clpSimplex->setProblemStatus(1);
return clpSolver->isProvenOptimal() ? 1 : 0;
}
#endif
/*!
\todo It'd be really nice if there were an overload for this method that
allowed a separate value for the underlying solver's log level. The
overload could be coded to allow an increase in the log level of the
underlying solver.
It's worth contemplating whether OSI should have a setLogLevel method
that's more specific than the hint mechanism.
*/
// Set log level
void
CbcModel::setLogLevel(int value)
{
handler_->setLogLevel(value);
// Reduce print out in Osi
if (solver_) {
int oldLevel = solver_->messageHandler()->logLevel();
if (value < oldLevel)
solver_->messageHandler()->setLogLevel(value);
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
ClpSimplex * clpSimplex = clpSolver->getModelPtr();
oldLevel = clpSimplex->logLevel();
if (value < oldLevel)
clpSimplex->setLogLevel(value);
}
#else // COIN_HAS_CLP
/*
For generic OSI solvers, if the new log level is 0, try the
DoReducePrint hint for emphasis.
*/
if (value == 0) {
solver_->setHintParam(OsiDoReducePrint, true, OsiHintDo) ;
}
#endif // COIN_HAS_CLP
}
}
/* Pass in target solution and optional priorities.
If priorities then >0 means only branch if incorrect
while <0 means branch even if correct. +1 or -1 are
highest priority */
void
CbcModel::setHotstartSolution(const double * solution, const int * priorities)
{
if (solution == NULL) {
delete [] hotstartSolution_;
hotstartSolution_ = NULL;
delete [] hotstartPriorities_;
hotstartPriorities_ = NULL;
} else {
int numberColumns = solver_->getNumCols();
hotstartSolution_ = CoinCopyOfArray(solution, numberColumns);
hotstartPriorities_ = CoinCopyOfArray(priorities, numberColumns);
for (int i = 0; i < numberColumns; i++) {
if (hotstartSolution_[i] == -COIN_DBL_MAX) {
hotstartSolution_[i] = 0.0;
hotstartPriorities_[i] += 10000;
}
if (solver_->isInteger(i))
hotstartSolution_[i] = floor(hotstartSolution_[i] + 0.5);
}
}
}
// Increment strong info
void
CbcModel::incrementStrongInfo(int numberTimes, int numberIterations,
int numberFixed, bool ifInfeasible)
{
strongInfo_[0] += numberTimes;
numberStrongIterations_ += numberIterations;
strongInfo_[1] += numberFixed;
if (ifInfeasible)
strongInfo_[2] ++;
}
/* Set objective value in a node. This is separated out so that
odd solvers can use. It may look at extra information in
solverCharacteriscs_ and will also use bound from parent node
*/
void
CbcModel::setObjectiveValue(CbcNode * thisNode, const CbcNode * parentNode) const
{
double newObjValue = solver_->getObjSense() * solver_->getObjValue();
// If odd solver take its bound
if (solverCharacteristics_) {
newObjValue = CoinMax(newObjValue, solverCharacteristics_->mipBound());
// Reset bound anyway (no harm if not odd)
solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
}
// If not root then use max of this and parent
if (parentNode)
newObjValue = CoinMax(newObjValue, parentNode->objectiveValue());
thisNode->setObjectiveValue(newObjValue);
}
// Current time since start of branchAndbound
double
CbcModel::getCurrentSeconds() const
{
if (!useElapsedTime())
return CoinCpuTime() - getDblParam(CbcStartSeconds);
else
return CoinGetTimeOfDay() - getDblParam(CbcStartSeconds);
}
/* Encapsulates choosing a variable -
anyAction: -2 infeasible
-1 round again
0 done
At the point where chooseBranch is called, we've decided that this problem
will need to be placed in the live set and we need to choose a branching
variable.
Parameters:
newNode: the node just created for the active subproblem.
oldNode: newNode's parent.
lastws: oldNode's basis
lowerBefore, upperBefore: column bound arrays for oldNode
cuts: list of cuts added to newNode.
resolved: (o) set to true if newNode is resolved during processing
branches: (o) will be filled in with ... ? Null on entry
*/
int
CbcModel::chooseBranch(CbcNode * &newNode, int numberPassesLeft,
CbcNode * oldNode, OsiCuts & cuts,
bool & resolved, CoinWarmStartBasis *lastws,
const double * lowerBefore, const double * upperBefore,
OsiSolverBranch * & branches)
{
// Set state of search
/*
0 - outside CbcNode
1 - no solutions
2 - all heuristic solutions
3 - a solution reached by branching (could be strong)
4 - no solution but many nodes
add 10 if depth >= K
K is currently hardcoded to 8, a few lines below.
CBCMODEL_DEBUG: Seems like stateOfSearch_ should be 2 if
numberHeuristicSolutions_ == numberSolutions_.
*/
stateOfSearch_ = 1;
if (numberSolutions_ > 0) {
if (numberHeuristicSolutions_ == numberSolutions_)
stateOfSearch_ = 3;
else
stateOfSearch_ = 3;
}
if (numberNodes_ > 2*numberObjects_ + 1000) {
stateOfSearch_ = 4;
}
//stateOfSearch_=3;
if (currentNode_ && currentNode_->depth() >= 8)
stateOfSearch_ += 10;
//printf("STate %d, %d nodes - parent %c - sol %d %d\n",
// stateOfSearch_,numberNodes_,parentModel_ ? 'Y' :'N',
// numberSolutions_,numberHeuristicSolutions_);
int anyAction = -1 ;
resolved = false ;
if (newNode->objectiveValue() >= getCutoff())
anyAction = -2;
branches = NULL;
bool feasible = true;
int branchingState = -1;
// Compute "small" change in branch
int nBranches = intParam_[CbcNumberBranches];
if (nBranches) {
double average = dblParam_[CbcSumChange] / static_cast<double>(nBranches);
dblParam_[CbcSmallChange] =
CoinMax(average * 1.0e-5, dblParam_[CbcSmallestChange]);
dblParam_[CbcSmallChange] = CoinMax(dblParam_[CbcSmallChange], 1.0e-8);
} else {
dblParam_[CbcSmallChange] = 1.0e-8;
}
#ifdef JJF_ZERO
// Say not on optimal path
bool onOptimalPath = false;
if ((specialOptions_&1) != 0) {
/*
This doesn't work as intended --- getRowCutDebugger will return null
unless the current feasible solution region includes the optimal solution
that RowCutDebugger knows. There's no way to tell inactive from off the
optimal path.
*/
const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
if (debugger) {
onOptimalPath = true;
printf("On optimal path - choose\n") ;
}
}
#endif
currentNode_ = newNode; // so can be used elsewhere
// Remember number of rows to restore at the end of the loop
int saveNumberRows=solver_->getNumRows();
/*
Enough preparation. Get down to the business of choosing a branching
variable.
*/
while (anyAction == -1) {
// Set objective value (not so obvious if NLP etc)
setObjectiveValue(newNode, oldNode);
//if (numberPassesLeft<=0)
//branchingState=1;
/*
Is there a CbcBranchDecision object installed? Does it specify a
chooseVariable method? If not, we're using the old (Cbc) side of the branch
decision hierarchy. In quick summary, CbcNode::chooseBranch uses strong
branching on any objects, while CbcNode::chooseDynamicBranch uses dynamic
branching, but only on simple integers (-3 is the code for punt due to
complex objects). Serious bugs remain on the Cbc side, particularly in
chooseDynamicBranch.
*/
if (!branchingMethod_ || !branchingMethod_->chooseMethod()) {
#ifdef COIN_HAS_CLP
bool doClp = oldNode && (oldNode->depth() % 2) == 1;
if (!doCutsNow(1))
doClp = true;
//doClp = true;
int testDepth = 5;
// Don't do if many iterations per node
int totalNodes = numberNodes_ + numberExtraNodes_;
int totalIterations = numberIterations_ + numberExtraIterations_;
bool diving=false;
if ((moreSpecialOptions_&33554432)!=0) {
testDepth=COIN_INT_MAX;
if (oldNode&&(oldNode->depth()==-2||oldNode->depth()==4))
diving=true;
}
if (totalNodes*40 < totalIterations || numberNodes_ < 1000) {
doClp = false;
//} else if (oldNode&&fastNodeDepth_>=0&&oldNode->depth()>=testDepth&&(specialOptions_&2048)==0) {
//printf("size %d %d - cuts %d - nodes %d its %d %c\n",solver_->getNumRows(),
// solver_->getNumCols(),cuts.sizeRowCuts(),
// totalNodes,totalIterations,doClp ? 'Y' : 'N');
}
if (oldNode &&
((fastNodeDepth_ >= 0 && oldNode->depth() >= testDepth && doClp)||diving) &&/*!parentModel_*/(specialOptions_&2048) == 0
&& !cuts.sizeRowCuts()) {
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver) {
anyAction = newNode->chooseClpBranch(this, oldNode) ;
if (anyAction != -1)
break;
}
}
#endif
#ifdef COIN_HAS_CLP
int save=0;
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver&&(moreSpecialOptions_&4194304)!=0) {
ClpSimplex * clpSimplex = clpSolver->getModelPtr();
save=clpSimplex->specialOptions();
clpSimplex->setSpecialOptions(save | 0x11200000); // say is Cbc (and in branch and bound - but save ray)
}
#endif
#ifdef COIN_HAS_NTY
if (symmetryInfo_) {
CbcNodeInfo * infoX = oldNode ? oldNode->nodeInfo() : NULL;
bool worthTrying = false;
if (infoX) {
CbcNodeInfo * info = infoX;
for (int i=0;i<NTY_BAD_DEPTH;i++) {
if (!info->parent()) {
worthTrying = true;
break;
}
info = info->parent();
if (info->symmetryWorked()) {
worthTrying = true;
break;
}
}
} else {
worthTrying=true;
}
if ((moreSpecialOptions2_&(128|256))==(128|256)&¤tDepth_>5)
worthTrying=false;
if (worthTrying) {
int n=symmetryInfo_->orbitalFixing(solver_);
if (n) {
#if PRINT_MORE==0
if (logLevel()>1)
printf("%d orbital fixes\n",n);
#endif
solver_->resolve();
if(!isProvenOptimal()) {
if (logLevel()>1)
printf("infeasible after orbital fixing\n");
}
}
}
}
#endif
if (numberBeforeTrust_ == 0 ) {
anyAction = newNode->chooseBranch(this, oldNode, numberPassesLeft) ;
} else {
anyAction = newNode->chooseDynamicBranch(this, oldNode, branches, numberPassesLeft) ;
if (anyAction == -3)
anyAction = newNode->chooseBranch(this, oldNode, numberPassesLeft) ; // dynamic did nothing
}
#ifdef COIN_HAS_CLP
if (clpSolver&&(moreSpecialOptions_&4194304)!=0) {
ClpSimplex * clpSimplex = clpSolver->getModelPtr();
clpSimplex->setSpecialOptions(save);
}
#endif
/*
We're on the new (Osi) side of the branching hierarchy.
*/
} else {
OsiBranchingInformation usefulInfo = usefulInformation();
anyAction = newNode->chooseOsiBranch(this, oldNode, &usefulInfo, branchingState) ;; // Osi method
//branchingState=0;
}
if (!oldNode) {
if (numberUpdateItems_) {
for (int i = 0; i < numberUpdateItems_; i++) {
CbcObjectUpdateData * update = updateItems_ + i;
CbcObject * object = dynamic_cast<CbcObject *> (update->object_);
#ifndef NDEBUG
bool found = false;
for (int j = 0; j < numberObjects_; j++) {
if (update->object_ == object_[j]) {
found = true;
break;
}
}
assert (found);
#endif
//if (object)
//assert (object==object_[update->objectNumber_]);
if (object)
object->updateInformation(*update);
}
numberUpdateItems_ = 0;
}
}
if (solverCharacteristics_ &&
solverCharacteristics_->solutionAddsCuts() && // we are in some OA based bab
feasible && (newNode->numberUnsatisfied() == 0) //solution has become integer feasible during strong branching
) {
//in the present case we need to check here integer infeasibility if the node is not fathomed we will have to do the loop
// again
//std::cout<<solver_<<std::endl;
OsiCuts feasCuts;
for (int i = 0; i < numberCutGenerators_ && (feasCuts.sizeRowCuts () == 0); i++) {
if (generator_ [i] -> normal () &&
(!generator_ [i] -> needsOptimalBasis () || solver_ -> basisIsAvailable ()))
generator_ [i] -> generateCuts (feasCuts, 1 /* = fullscan */, solver_, NULL);
}
solver_ -> applyCuts (feasCuts);
resolve(solver_);
double objval = solver_->getObjValue();
lastHeuristic_ = NULL;
setBestSolution(CBC_SOLUTION, objval,
solver_->getColSolution()) ;
int easy = 2;
if (!solverCharacteristics_->mipFeasible())//did we prove that the node could be pruned?
feasible = false;
// Reset the bound now
solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ;
feasible &= resolve(oldNode ? oldNode->nodeInfo() : NULL, 11) != 0 ;
solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
resolved = true ;
if (problemFeasibility_->feasible(this, 0) < 0) {
feasible = false; // pretend infeasible
}
if (feasible)
anyAction = -1;
else
anyAction = -2;
}
/*
Yep, false positives for sure. And no easy way to distinguish honest
infeasibility from `found a solution and tightened objective target.'
if (onOptimalPath)
assert (anyAction!=-2); // can be useful but gives false positives on strong
*/
numberPassesLeft--;
if (numberPassesLeft <= -1) {
if (!numberLongStrong_ && !numberThreads_)
messageHandler()->message(CBC_WARNING_STRONG,
messages()) << CoinMessageEol ;
numberLongStrong_++;
}
if (anyAction == -1) {
// can do quick optimality check
int easy = 2;
solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ;
feasible = resolve(oldNode ? oldNode->nodeInfo() : NULL, 11) != 0 ;
solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
resolved = true ;
if (problemFeasibility_->feasible(this, 0) < 0) {
feasible = false; // pretend infeasible
}
if (feasible) {
// Set objective value (not so obvious if NLP etc)
setObjectiveValue(newNode, oldNode);
reducedCostFix() ;
if (newNode->objectiveValue() >= getCutoff())
anyAction = -2;
} else {
anyAction = -2 ;
}
}
}
//A candidate has been found; restore the subproblem.
if( saveNumberRows<solver_->getNumRows()) {
// delete rows - but leave solution
int n = solver_->getNumRows();
int * del = new int [n-saveNumberRows];
for (int i=saveNumberRows;i<n;i++)
del[i-saveNumberRows]=i;
solver_->deleteRows(n-saveNumberRows,del);
delete [] del;
}
/*
End main loop to choose a branching variable.
*/
if (anyAction >= 0) {
if (resolved) {
/*
Used to be that when the node was not fathomed (branching object present)
the solution was not needed. But that's no longer the case --- heuristics
are applied, and they may want the solution.
*/
// bool needValidSolution = (newNode->branchingObject() == NULL) ;
bool needValidSolution = true ;
takeOffCuts(cuts, needValidSolution , NULL) ;
# ifdef CHECK_CUT_COUNTS
{
printf("Number of rows after chooseBranch fix (node)"
"(active only) %d\n",
numberRowsAtContinuous_ + numberNewCuts_ +
numberOldActiveCuts_) ;
const CoinWarmStartBasis* debugws =
dynamic_cast<const CoinWarmStartBasis*>
(solver_->getWarmStart()) ;
debugws->print() ;
delete debugws ;
}
# endif
}
{
OsiBranchingObject * branchingObject =
newNode->modifiableBranchingObject();
CbcGeneralBranchingObject * generalBranch =
dynamic_cast <CbcGeneralBranchingObject *> (branchingObject);
if (generalBranch && false) {
int numberProblems = generalBranch->numberSubProblems();
for (int i = 0; i < numberProblems; i++) {
double objectiveValue;
double sumInfeasibilities;
int numberUnsatisfied;
generalBranch->state(objectiveValue, sumInfeasibilities,
numberUnsatisfied, i);
printf("node %d obj %g sumI %g numI %i rel depth %d\n",
i, objectiveValue, sumInfeasibilities, numberUnsatisfied,
generalBranch->subProblem(i)->depth_);
}
}
if (generalBranch) {
int numberProblems = generalBranch->numberSubProblems();
newNode->setBranchingObject(NULL);
CbcNode * newNode2 = NULL;
assert (numberProblems);
int nProbMinus1 = numberProblems - 1;
lockThread();
for (int i = 0; i < currentNumberCuts_; i++) {
if (addedCuts_[i])
addedCuts_[i]->increment(nProbMinus1) ;
}
unlockThread();
for (int i = 0; i < numberProblems; i++) {
double objectiveValue;
double sumInfeasibilities;
int numberUnsatisfied;
generalBranch->state(objectiveValue, sumInfeasibilities,
numberUnsatisfied, i);
//printf("node %d obj %g sumI %g numI %i rel depth %d\n",
// i,objectiveValue,sumInfeasibilities,numberUnsatisfied,
// generalBranch->subProblem(i)->depth_);
newNode2 = new CbcNode();
newNode2->setDepth(generalBranch->subProblem(i)->depth_ + currentDepth_);
generalBranch->subProblem(i)->apply(solver_, 8); // basis
newNode2->setNumberUnsatisfied(numberUnsatisfied);
newNode2->setSumInfeasibilities(sumInfeasibilities);
newNode2->setGuessedObjectiveValue(objectiveValue);
newNode2->setObjectiveValue(objectiveValue);
CbcOneGeneralBranchingObject * object =
new CbcOneGeneralBranchingObject(this, generalBranch, i);
newNode2->setBranchingObject(object);
assert (lastws->fullBasis());
newNode2->createInfo(this, oldNode, lastws,
lowerBefore, upperBefore,
numberOldActiveCuts_, numberNewCuts_) ;
newNode2->nodeInfo()->setNumberBranchesLeft(1);
//newNode2->nodeInfo()->unsetParentBasedData();
if (i < nProbMinus1) {
//OsiBranchingObject * object = oldNode->modifiableBranchingObject();
CbcNodeInfo * nodeInfo = oldNode->nodeInfo();
//object->incrementNumberBranchesLeft();
nodeInfo->incrementNumberPointingToThis();
newNode2->nodeInfo()->setNodeNumber(numberNodes2_);
//newNode2->nodeInfo()->setNumberBranchesLeft(1);
newNode2->initializeInfo();
numberNodes2_++;
tree_->push(newNode2);
}
}
delete newNode;
newNode = newNode2;
} else {
if (lastws) {
if (parallelMode() < -1) {
lastws->fixFullBasis();
} else {
if ((specialOptions_&8192) == 0)
assert (lastws->fullBasis());
else
lastws->fixFullBasis();
}
}
newNode->createInfo(this, oldNode, lastws, lowerBefore, upperBefore,
numberOldActiveCuts_, numberNewCuts_) ;
}
}
if (newNode->numberUnsatisfied()) {
maximumDepthActual_ = CoinMax(maximumDepthActual_, newNode->depth());
// Number of branches is in oldNode!
newNode->initializeInfo() ;
if (cuts.sizeRowCuts()) {
int initialNumber = ((threadMode_ & 1) == 0) ? 0 : 1000000000;
lockThread();
newNode->nodeInfo()->addCuts(cuts, newNode->numberBranches(),
//whichGenerator_,
initialNumber) ;
unlockThread();
}
}
} else {
anyAction = -2 ;
// Reset bound anyway (no harm if not odd)
solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
}
// May have slipped through i.e. anyAction == 0 and objective above cutoff
// I think this will screw up cut reference counts if executed.
// We executed addCuts just above. (lh)
if ( anyAction >= 0 ) {
assert (newNode);
if (newNode->objectiveValue() >= getCutoff()) {
anyAction = -2; // say bad after all
// zap parent nodeInfo
#ifdef COIN_DEVELOP
printf("zapping3 CbcNodeInfo %x\n", newNode->nodeInfo()->parent());
#endif
if (newNode->nodeInfo())
newNode->nodeInfo()->nullParent();
}
}
stateOfSearch_ = 0; // outside chooseBranch
#ifdef JJF_ZERO
if (onOptimalPath) {
const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
if (!debugger) {
printf("NOT On optimal path - choose\n") ;
abort();
} else {
printf("Still On optimal path - choose\n") ;
if (anyAction == -2) {
printf("anyAction 2!!\n");
abort();
}
}
}
#endif
return anyAction;
}
/*
For advanced applications you may wish to modify the behavior of Cbc
e.g. if the solver is a NLP solver then you may not have an exact
optimum solution at each step. Information could be built into
OsiSolverInterface but this is an alternative so that that interface
does not have to be changed. If something similar is useful to
enough solvers then it could be migrated.
You can also pass in by using solver->setAuxiliaryInfo.
You should do that if solver is odd - if solver is normal simplex
then use this
*/
void
CbcModel::passInSolverCharacteristics(OsiBabSolver * solverCharacteristics)
{
solverCharacteristics_ = solverCharacteristics;
}
// Generate an OsiBranchingInformation object
OsiBranchingInformation
CbcModel::usefulInformation() const
{
OsiBranchingInformation usefulInfo(solver_, normalSolver(), false);
// and modify
usefulInfo.solution_ = testSolution_;
usefulInfo.integerTolerance_ = dblParam_[CbcIntegerTolerance] ;
usefulInfo.hotstartSolution_ = hotstartSolution_;
usefulInfo.numberSolutions_ = numberSolutions_;
usefulInfo.numberBranchingSolutions_ = numberSolutions_ - numberHeuristicSolutions_;
usefulInfo.depth_ = -1;
return usefulInfo;
}
void
CbcModel::setBestSolution(const double * solution, int numberColumns,
double objectiveValue, bool checkSolution)
{
// May be odd discontinuities - so only check if asked
if (checkSolution) {
assert (numberColumns == solver_->getNumCols());
double * saveLower = CoinCopyOfArray(solver_->getColLower(), numberColumns);
double * saveUpper = CoinCopyOfArray(solver_->getColUpper(), numberColumns);
// Fix integers
int numberAway = 0;
for (int i = 0; i < numberColumns; i++) {
if (solver_->isInteger(i)) {
double value = solution[i];
double intValue = floor(value + 0.5);
if (fabs(value - intValue) > 1.0e-4)
numberAway++;
solver_->setColLower(i, intValue);
solver_->setColUpper(i, intValue);
}
}
// Save basis
CoinWarmStart * saveBasis = solver_->getWarmStart();
// Solve
solver_->initialSolve();
char printBuffer[200];
if (numberAway) {
sprintf(printBuffer, "Warning %d integer variables were more than 1.0e-4 away from integer", numberAway);
messageHandler()->message(CBC_GENERAL, messages())
<< printBuffer << CoinMessageEol ;
}
bool looksGood = solver_->isProvenOptimal();
if (looksGood) {
double direction = solver_->getObjSense() ;
double objValue = direction * solver_->getObjValue();
if (objValue > objectiveValue + 1.0e-8*(1.0 + fabs(objectiveValue))) {
sprintf(printBuffer, "Given objective value %g, computed %g",
objectiveValue, objValue);
messageHandler()->message(CBC_GENERAL, messages())
<< printBuffer << CoinMessageEol ;
}
// Use this as objective value and solution
objectiveValue = objValue;
solution = solver_->getColSolution();
// Save current basis
CoinWarmStartBasis* ws =
dynamic_cast <CoinWarmStartBasis*>(solver_->getWarmStart()) ;
assert(ws);
setBestSolutionBasis(*ws);
delete ws;
}
// Restore basis
solver_->setWarmStart(saveBasis);
delete saveBasis;
// Restore bounds
solver_->setColLower(saveLower);
delete [] saveLower;
solver_->setColUpper(saveUpper);
delete [] saveUpper;
// Return if no good
if (!looksGood) {
messageHandler()->message(CBC_GENERAL, messages())
<< "Error solution not saved as not feasible" << CoinMessageEol ;
return;
} else {
// message
sprintf(printBuffer, "Solution with objective value %g saved",
objectiveValue);
messageHandler()->message(CBC_GENERAL, messages())
<< printBuffer << CoinMessageEol ;
}
}
if (bestSolution_)
saveExtraSolution(bestSolution_, bestObjective_);
bestObjective_ = objectiveValue;
// may be able to change cutoff now
double cutoff = getCutoff();
double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
if (cutoff > objectiveValue - increment) {
cutoff = objectiveValue - increment ;
setCutoff(cutoff) ;
// change cutoff as constraint if wanted
if (cutoffRowNumber_>=0) {
if (solver_->getNumRows()>cutoffRowNumber_) {
double offset;
solver_->getDblParam(OsiObjOffset, offset);
solver_->setRowUpper(cutoffRowNumber_,cutoff+offset);
if (continuousSolver_&&solver_->getNumCols()>continuousSolver_->getNumCols()) {
solver_->setRowUpper(cutoffRowNumber_,floor(cutoff)+offset);
solver_->setRowLower(cutoffRowNumber_,floor(cutoff)+offset);
}
}
}
}
int n = CoinMax(numberColumns, solver_->getNumCols());
delete [] bestSolution_;
bestSolution_ = new double [n];
memset(bestSolution_, 0, n*sizeof(double));
memcpy(bestSolution_, solution, numberColumns*sizeof(double));
}
/* Do heuristics at root.
0 - don't delete
1 - delete
2 - just delete - don't even use
Parameter of 2 means what it says --- the routine will do nothing except
delete the existing heuristics. A feasibility pump is always deleted,
independent of the parameter value, as it's only useful at the root.
The routine is called from branchAndBound to process the root node. But it
will also be called when we've recursed into branchAndBound via smallBaB.
*/
void
CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards)
{
int numberColumns = getNumCols() ;
double * newSolution = new double [numberColumns] ;
int i;
if (deleteHeuristicsAfterwards != 2) {
/*
If mode == 1, we delete and recreate here, then delete at the bottom. The
create/delete part makes sense, but why delete the existing array? Seems like
it should be preserved and restored.
*/
if (deleteHeuristicsAfterwards) {
delete [] usedInSolution_;
usedInSolution_ = new int [numberColumns];
CoinZeroN(usedInSolution_, numberColumns);
}
double heuristicValue = getCutoff() ;
int found = -1; // no solution found
CbcEventHandler *eventHandler = getEventHandler() ;
if (eventHandler)
eventHandler->setModel(this);
/*
currentPassNumber_ is described as `cut pass number'. Again, seems a bit
cavalier to just change it.
Whether this has any effect is determined by individual heuristics. Typically
there will be a check at the front of the solution() routine that determines
whether it will run or simply return. Root heuristics are characterised by
node count of 0. In addition, currentPassNumber_ can be checked to to limit
execution in terms of passes through cut generation / heuristic execution in
solveWithCuts.
*/
currentPassNumber_ = 1; // so root heuristics will run
/*
A loop to run the heuristics. incrementUsed will mark entries in
usedInSolution corresponding to variables that are nonzero in the solution.
CBC_ROUNDING just identifies a message template, not the heuristic.
*/
// Modify based on size etc
adjustHeuristics();
// See if already within allowable gap
bool exitNow = false;
for (i = 0; i < numberHeuristics_; i++) {
if (heuristic_[i]->exitNow(bestObjective_))
exitNow = true;
}
if (!exitNow) {
/** -1 first time otherwise number of solutions last time */
int lastSolutionCount = -1;
while (lastSolutionCount) {
int thisSolutionCount=0;
#ifdef CBC_THREAD
if ((threadMode_&4) != 0) {
typedef struct {
double solutionValue;
CbcModel * model;
double * solution;
int foundSol;
} argBundle;
int chunk;
if (!numberThreads_)
chunk = numberHeuristics_;
else
chunk = numberThreads_;
for (int iChunk = 0; iChunk < numberHeuristics_; iChunk += chunk) {
argBundle * parameters = new argBundle [chunk];
for (int i = 0; i < chunk; i++)
parameters[i].model = NULL;
int nThisTime = CoinMin(numberHeuristics_ - iChunk, chunk);
for (int i = iChunk; i < iChunk + nThisTime; i++) {
// skip if can't run here
if (!heuristic_[i]->shouldHeurRun(0))
continue;
if (lastSolutionCount>0&&
(heuristic_[i]->switches()&16)==0)
continue; // no point
parameters[i-iChunk].solutionValue = heuristicValue;
// Don't want a strategy object
CbcStrategy * saveStrategy = strategy_;
strategy_ = NULL;
CbcModel * newModel = new CbcModel(*this);
strategy_ = saveStrategy;
assert (!newModel->continuousSolver_);
if (continuousSolver_)
newModel->continuousSolver_ = continuousSolver_->clone();
else
newModel->continuousSolver_ = solver_->clone();
parameters[i-iChunk].model = newModel;
parameters[i-iChunk].solution = new double [numberColumns];;
parameters[i-iChunk].foundSol = 0;
//newModel->gutsOfCopy(*this,-1);
for (int j = 0; j < numberHeuristics_; j++)
delete newModel->heuristic_[j];
//newModel->heuristic_ = new CbcHeuristic * [1];
newModel->heuristic_[0] = heuristic_[i]->clone();
newModel->heuristic_[0]->setModel(newModel);
newModel->heuristic_[0]->resetModel(newModel);
newModel->numberHeuristics_ = 1;
}
void
parallelHeuristics (int numberThreads,
int sizeOfData,
void * argBundle);
parallelHeuristics(nThisTime,
static_cast<int>(sizeof(argBundle)),
parameters);
double cutoff = heuristicValue;
for (int i = 0; i < chunk; i++) {
if (parameters[i].model) {
if (parameters[i].foundSol > 0 &&
parameters[i].solutionValue < heuristicValue) {
memcpy(newSolution, parameters[i].solution,
numberColumns*sizeof(double));
lastHeuristic_ = heuristic_[i+iChunk];
double value = parameters[i].solutionValue;
setBestSolution(CBC_ROUNDING, value, newSolution) ;
// Double check valid
if (getCutoff() < cutoff) {
cutoff = getCutoff();
heuristicValue = value;
heuristic_[i+iChunk]->incrementNumberSolutionsFound();
incrementUsed(newSolution);
// increment number of solutions so other heuristics can test
thisSolutionCount++;
numberHeuristicSolutions_++;
found = i + iChunk ;
}
}
if (heuristic_[i+iChunk]->exitNow(bestObjective_) ||
(parameters[i].model->heuristic(0)->switches()&(1024 + 2048))
== (1024 + 2048))
exitNow = true;
delete [] parameters[i].solution;
delete parameters[i].model;
}
}
delete [] parameters;
if (exitNow)
break;
}
} else {
#endif
int whereFrom = 0;
for (i = 0; i < numberHeuristics_; i++) {
// skip if can't run here
if (!heuristic_[i]->shouldHeurRun(whereFrom))
continue;
if (lastSolutionCount>0&&
(heuristic_[i]->switches()&16)==0)
continue; // no point
if (maximumSecondsReached()) {
thisSolutionCount=-1000000;
break;
}
// see if heuristic will do anything
double saveValue = heuristicValue ;
double before = getCurrentSeconds();
int ifSol = heuristic_[i]->solution(heuristicValue,
newSolution);
if (handler_->logLevel()>1) {
char line[100];
sprintf(line,"Heuristic %s took %g seconds (%s)",
heuristic_[i]->heuristicName(),
getCurrentSeconds()-before,
ifSol ? "good" : "no good");
handler_->message(CBC_GENERAL, messages_) <<
line << CoinMessageEol ;
}
//#define DEBUG_BEST
#ifdef DEBUG_BEST
FILE * fp = fopen("solution.data","rb");
if (!fp&&ifSol>0) {
int numberColumns=getNumCols();
fp = fopen("solution.data","wb");
printf("Solution data on file solution.data\n");
size_t numberWritten;
numberWritten=fwrite(&numberColumns,sizeof(int),1,fp);
assert (numberWritten==1);
numberWritten=fwrite(&heuristicValue,sizeof(double),1,fp);
assert (numberWritten==1);
numberWritten=fwrite(newSolution,sizeof(double),numberColumns,fp);
assert (numberWritten==numberColumns);
fclose(fp);
} else if (fp) {
int numberColumns=getNumCols();
int numberColumnsX;
size_t numberRead;
numberRead=fread(&numberColumnsX,sizeof(int),1,fp);
assert (numberRead==1);
if (numberColumns==numberColumnsX) {
numberRead=fread(&heuristicValue,sizeof(double),1,fp);
assert (numberRead==1);
numberRead=fread(newSolution,sizeof(double),numberColumns,fp);
assert (numberRead==numberColumns);
ifSol=1;
}
fclose(fp);
}
#endif
if (ifSol > 0) {
// better solution found
double currentObjective = bestObjective_;
CbcHeuristic * saveHeuristic = lastHeuristic_;
lastHeuristic_ = heuristic_[i];
setBestSolution(CBC_ROUNDING, heuristicValue, newSolution) ;
if (bestObjective_ < currentObjective) {
thisSolutionCount++;
heuristic_[i]->incrementNumberSolutionsFound();
found = i ;
incrementUsed(newSolution);
// increment number of solutions so other heuristics can test
// numberSolutions_++;
numberHeuristicSolutions_++;
#ifdef HEURISTIC_INFORM
printf("HEUR %s where %d C\n",
lastHeuristic_->heuristicName(), whereFrom);
#endif
whereFrom |= 8; // say solution found
if (heuristic_[i]->exitNow(bestObjective_)
||numberSolutions_>=getMaximumSolutions()) {
thisSolutionCount=-1000000;
break;
}
if (eventHandler) {
std::cerr << " event(heuristicSolution) " << __FILE__ << ":" << __LINE__ << " " << std::flush; if (!eventHandler->event(CbcEventHandler::heuristicSolution)) {
eventHappened_ = true; // exit
thisSolutionCount=-1000000;
break;
}
}
double testGap = CoinMax(dblParam_[CbcAllowableGap],
CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_))
* dblParam_[CbcAllowableFractionGap]);
if (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0 &&bestPossibleObjective_ < 1.0e30) {
if (bestPossibleObjective_ < getCutoff())
stoppedOnGap_ = true ;
//eventHappened_=true; // stop as fast as possible
thisSolutionCount=-1000000;
break;
}
reducedCostFix();
} else {
// NOT better solution
#if CBC_USEFUL_PRINTING>1
printf("HEUR %s where %d REJECTED i==%d\n",
heuristic_[i]->heuristicName(), whereFrom, i);
#endif
lastHeuristic_ = saveHeuristic;
heuristicValue = saveValue ;
}
} else {
heuristicValue = saveValue ;
}
if (eventHandler) {
if (!eventHandler->event(CbcEventHandler::afterHeuristic)) {
eventHappened_ = true; // exit
thisSolutionCount=-1000000;
break;
}
}
}
#ifdef CBC_THREAD
}
#endif
if (thisSolutionCount<=0)
break;
lastSolutionCount=thisSolutionCount;
}
}
currentPassNumber_ = 0;
/*
Did any of the heuristics turn up a new solution? Record it before we free
the vector. tree_ will not necessarily be a CbcTreeLocal; the main model gets
a CbcTree by default. CbcTreeLocal actually implements a k-neighbourhood
search heuristic. This initialises it with a solution and creates the
k-neighbourhood cut.
*/
if (found >= 0) {
CbcTreeLocal * tree
= dynamic_cast<CbcTreeLocal *> (tree_);
if (tree)
tree->passInSolution(bestSolution_, heuristicValue);
if (eventHandler) {
std::cerr << " event(solution) " << __FILE__ << ":" << __LINE__ << " " << std::flush; if (!eventHandler->event(CbcEventHandler::solution)) {
eventHappened_ = true; // exit
}
}
}
}
/*
Cleanup. The feasibility pump heuristic is a root heuristic to look for an
initial feasible solution. It's had its chance; remove it.
For modes 1 and 2, all the heuristics are deleted.
*/
if (!deleteHeuristicsAfterwards) {
for (i = 0; i < numberHeuristics_; i++) {
// delete FPump
CbcHeuristicFPump * pump
= dynamic_cast<CbcHeuristicFPump *> (heuristic_[i]);
if (pump && pump->feasibilityPumpOptions() < 1000000) {
delete pump;
numberHeuristics_ --;
for (int j = i; j < numberHeuristics_; j++)
heuristic_[j] = heuristic_[j+1];
}
}
} else {
// delete all
for (i = 0; i < numberHeuristics_; i++)
delete heuristic_[i];
numberHeuristics_ = 0;
delete [] heuristic_;
heuristic_ = NULL;
delete [] usedInSolution_;
usedInSolution_ = NULL;
}
delete [] newSolution ;
}
// Zap integer information in problem (may leave object info)
void
CbcModel::zapIntegerInformation(bool leaveObjects)
{
numberIntegers_ = 0;
delete [] integerVariable_;
integerVariable_ = NULL;
if (!leaveObjects && ownObjects_) {
int i;
for (i = 0; i < numberObjects_; i++)
delete object_[i];
delete [] object_;
numberObjects_ = 0;
object_ = NULL;
}
}
// Create C++ lines to get to current state
void
CbcModel::generateCpp( FILE * fp, int /*options*/)
{
// Do cut generators
int i;
for (i = 0; i < numberCutGenerators_; i++) {
CglCutGenerator * generator = generator_[i]->generator();
std::string name = generator->generateCpp(fp);
int howOften = generator_[i]->howOften();
int howOftenInSub = generator_[i]->howOftenInSub();
int whatDepth = generator_[i]->whatDepth();
int whatDepthInSub = generator_[i]->whatDepthInSub();
bool normal = generator_[i]->normal();
bool atSolution = generator_[i]->atSolution();
bool whenInfeasible = generator_[i]->whenInfeasible();
bool timing = generator_[i]->timing();
fprintf(fp, "3 cbcModel->addCutGenerator(&%s,%d,",
name.c_str(), howOften);
// change name
name[0] = static_cast<char>(toupper(name[0]));
fprintf(fp, "\"%s\",%s,%s,%s,%d,%d,%d);\n",
name.c_str(), normal ? "true" : "false",
atSolution ? "true" : "false",
whenInfeasible ? "true" : "false",
howOftenInSub, whatDepth, whatDepthInSub);
fprintf(fp, "3 cbcModel->cutGenerator(%d)->setTiming(%s);\n",
i, timing ? "true" : "false");
fprintf(fp, "3 \n");
}
for (i = 0; i < numberHeuristics_; i++) {
CbcHeuristic * heuristic = heuristic_[i];
heuristic->generateCpp(fp);
fprintf(fp, "3 \n");
}
if (nodeCompare_)
nodeCompare_->generateCpp(fp);
tree_->generateCpp(fp);
CbcModel defaultModel;
CbcModel * other = &defaultModel;
int iValue1, iValue2;
double dValue1, dValue2;
iValue1 = this->getMaximumNodes();
iValue2 = other->getMaximumNodes();
fprintf(fp, "%d int save_getMaximumNodes = cbcModel->getMaximumNodes();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setMaximumNodes(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setMaximumNodes(save_getMaximumNodes);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->getMaximumSolutions();
iValue2 = other->getMaximumSolutions();
fprintf(fp, "%d int save_getMaximumSolutions = cbcModel->getMaximumSolutions();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setMaximumSolutions(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setMaximumSolutions(save_getMaximumSolutions);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->numberStrong();
iValue2 = other->numberStrong();
fprintf(fp, "%d int save_numberStrong = cbcModel->numberStrong();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setNumberStrong(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setNumberStrong(save_numberStrong);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->numberBeforeTrust();
iValue2 = other->numberBeforeTrust();
fprintf(fp, "%d int save_numberBeforeTrust = cbcModel->numberBeforeTrust();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setNumberBeforeTrust(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setNumberBeforeTrust(save_numberBeforeTrust);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->numberPenalties();
iValue2 = other->numberPenalties();
fprintf(fp, "%d int save_numberPenalties = cbcModel->numberPenalties();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setNumberPenalties(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setNumberPenalties(save_numberPenalties);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->howOftenGlobalScan();
iValue2 = other->howOftenGlobalScan();
fprintf(fp, "%d int save_howOftenGlobalScan = cbcModel->howOftenGlobalScan();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setHowOftenGlobalScan(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setHowOftenGlobalScan(save_howOftenGlobalScan);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->printFrequency();
iValue2 = other->printFrequency();
fprintf(fp, "%d int save_printFrequency = cbcModel->printFrequency();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setPrintFrequency(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setPrintFrequency(save_printFrequency);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->getPrintingMode();
iValue2 = other->getPrintingMode();
fprintf(fp, "%d int save_printingMode = cbcModel->getPrintingMode();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setPrintingMode(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setPrintingMode(save_printingMode);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->searchStrategy();
iValue2 = other->searchStrategy();
fprintf(fp, "%d int save_searchStrategy = cbcModel->searchStrategy();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setSearchStrategy(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setSearchStrategy(save_searchStrategy);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->specialOptions();
iValue2 = other->specialOptions();
fprintf(fp, "%d int save_cbcSpecialOptions = cbcModel->specialOptions();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setSpecialOptions(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setSpecialOptions(save_cbcSpecialOptions);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->messageHandler()->logLevel();
iValue2 = other->messageHandler()->logLevel();
fprintf(fp, "%d int save_cbcMessageLevel = cbcModel->messageHandler()->logLevel();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->messageHandler()->setLogLevel(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->messageHandler()->setLogLevel(save_cbcMessageLevel);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->getMaximumCutPassesAtRoot();
iValue2 = other->getMaximumCutPassesAtRoot();
fprintf(fp, "%d int save_getMaximumCutPassesAtRoot = cbcModel->getMaximumCutPassesAtRoot();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setMaximumCutPassesAtRoot(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setMaximumCutPassesAtRoot(save_getMaximumCutPassesAtRoot);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->getMaximumCutPasses();
iValue2 = other->getMaximumCutPasses();
fprintf(fp, "%d int save_getMaximumCutPasses = cbcModel->getMaximumCutPasses();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setMaximumCutPasses(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setMaximumCutPasses(save_getMaximumCutPasses);\n", iValue1 == iValue2 ? 7 : 6);
iValue1 = this->getPreferredWay();
iValue2 = other->getPreferredWay();
fprintf(fp, "%d int save_getPreferredWay = cbcModel->getPreferredWay();\n", iValue1 == iValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setPreferredWay(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
fprintf(fp, "%d cbcModel->setPreferredWay(save_getPreferredWay);\n", iValue1 == iValue2 ? 7 : 6);
dValue1 = this->getMinimumDrop();
dValue2 = other->getMinimumDrop();
fprintf(fp, "%d double save_getMinimumDrop = cbcModel->getMinimumDrop();\n", dValue1 == dValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setMinimumDrop(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
fprintf(fp, "%d cbcModel->setMinimumDrop(save_getMinimumDrop);\n", dValue1 == dValue2 ? 7 : 6);
dValue1 = this->getIntegerTolerance();
dValue2 = other->getIntegerTolerance();
fprintf(fp, "%d double save_getIntegerTolerance = cbcModel->getIntegerTolerance();\n", dValue1 == dValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setIntegerTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
fprintf(fp, "%d cbcModel->setIntegerTolerance(save_getIntegerTolerance);\n", dValue1 == dValue2 ? 7 : 6);
dValue1 = this->getInfeasibilityWeight();
dValue2 = other->getInfeasibilityWeight();
fprintf(fp, "%d double save_getInfeasibilityWeight = cbcModel->getInfeasibilityWeight();\n", dValue1 == dValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setInfeasibilityWeight(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
fprintf(fp, "%d cbcModel->setInfeasibilityWeight(save_getInfeasibilityWeight);\n", dValue1 == dValue2 ? 7 : 6);
dValue1 = this->getCutoffIncrement();
dValue2 = other->getCutoffIncrement();
fprintf(fp, "%d double save_getCutoffIncrement = cbcModel->getCutoffIncrement();\n", dValue1 == dValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setCutoffIncrement(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
fprintf(fp, "%d cbcModel->setCutoffIncrement(save_getCutoffIncrement);\n", dValue1 == dValue2 ? 7 : 6);
dValue1 = this->getAllowableGap();
dValue2 = other->getAllowableGap();
fprintf(fp, "%d double save_getAllowableGap = cbcModel->getAllowableGap();\n", dValue1 == dValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setAllowableGap(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
fprintf(fp, "%d cbcModel->setAllowableGap(save_getAllowableGap);\n", dValue1 == dValue2 ? 7 : 6);
dValue1 = this->getAllowableFractionGap();
dValue2 = other->getAllowableFractionGap();
fprintf(fp, "%d double save_getAllowableFractionGap = cbcModel->getAllowableFractionGap();\n", dValue1 == dValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setAllowableFractionGap(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
fprintf(fp, "%d cbcModel->setAllowableFractionGap(save_getAllowableFractionGap);\n", dValue1 == dValue2 ? 7 : 6);
dValue1 = this->getMaximumSeconds();
dValue2 = other->getMaximumSeconds();
fprintf(fp, "%d double save_cbcMaximumSeconds = cbcModel->getMaximumSeconds();\n", dValue1 == dValue2 ? 2 : 1);
fprintf(fp, "%d cbcModel->setMaximumSeconds(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
fprintf(fp, "%d cbcModel->setMaximumSeconds(save_cbcMaximumSeconds);\n", dValue1 == dValue2 ? 7 : 6);
}
// So we can use osiObject or CbcObject during transition
void getIntegerInformation(const OsiObject * object, double & originalLower,
double & originalUpper)
{
const CbcSimpleInteger * integerObject =
dynamic_cast<const CbcSimpleInteger *> (object);
if (integerObject) {
// get original bounds
originalLower = integerObject->originalLowerBound();
originalUpper = integerObject->originalUpperBound();
} else {
const OsiSimpleInteger * integerObject =
dynamic_cast<const OsiSimpleInteger *> (object);
assert (integerObject);
// get original bounds
originalLower = integerObject->originalLowerBound();
originalUpper = integerObject->originalUpperBound();
}
}
// Set original columns as created by preprocessing
void
CbcModel::setOriginalColumns(const int * originalColumns,int numberGood)
{
int numberColumns = getNumCols();
delete [] originalColumns_;
originalColumns_ = new int [numberColumns];
int numberCopy=CoinMin(numberColumns,numberGood);
memcpy(originalColumns_,originalColumns,numberCopy*sizeof(int));
for (int i=numberCopy;i<numberColumns;i++)
originalColumns_[i]=-1;
}
// Set the cut modifier method
void
CbcModel::setCutModifier(CbcCutModifier * modifier)
{
delete cutModifier_;
cutModifier_ = modifier->clone();
}
/* Set the cut modifier method
*/
void
CbcModel::setCutModifier(CbcCutModifier & modifier)
{
delete cutModifier_;
cutModifier_ = modifier.clone();
}
/* Do one node - broken out for clarity?
also for parallel (when baseModel!=this)
Returns 1 if solution found
node NULL on return if no branches left
newNode NULL if no new node created
*/
int
CbcModel::doOneNode(CbcModel * baseModel, CbcNode * & node, CbcNode * & newNode)
{
int foundSolution = 0;
int saveNumberCutGenerators=numberCutGenerators_;
if ((moreSpecialOptions_&33554432)!=0 && (specialOptions_&2048)==0) {
if (node&&(node->depth()==-2||node->depth()==4))
numberCutGenerators_=0; // so can dive and branch
}
currentNode_ = node; // so can be accessed elsewhere
double bestObjective = bestObjective_;
numberUpdateItems_ = 0;
// Say not on optimal path
bool onOptimalPath = false;
# ifdef CHECK_NODE
printf("Node %x popped from tree - %d left, %d count\n", node,
node->nodeInfo()->numberBranchesLeft(),
node->nodeInfo()->numberPointingToThis()) ;
printf("\tdepth = %d, z = %g, unsat = %d\n", //var = %d.\n",
node->depth(), node->objectiveValue(),
node->numberUnsatisfied());
//node->columnNumber()) ;
# endif
/*
Rebuild the subproblem for this node: Call addCuts() to adjust the model
to recreate the subproblem for this node (set proper variable bounds, add
cuts, create a basis). This may result in the problem being fathomed by
bound or infeasibility. Returns 1 if node is fathomed.
Execute the current arm of the branch: If the problem survives, save the
resulting variable bounds and call branch() to modify variable bounds
according to the current arm of the branching object. If we're processing
the final arm of the branching object, flag the node for removal from the
live set.
*/
/*
Used to generate bound edits for CbcPartialNodeInfo.
*/
int numberColumns = getNumCols() ;
double * lowerBefore = new double [numberColumns] ;
double * upperBefore = new double [numberColumns] ;
if (parallelMode() >= 0)
newNode = NULL ;
else
newNode = new CbcNode();
bool feasible = true;
CoinWarmStartBasis *lastws = new CoinWarmStartBasis();
lockThread();
// point to genuine ones
//int save1 = maximumNumberCuts_;
//maximumNumberCuts_ = baseModel->maximumNumberCuts_;
//addedCuts_ = baseModel->addedCuts_;
if (parallelMode() >= 0) {
maximumDepth_ = baseModel->maximumDepth_;
walkback_ = baseModel->walkback_;
lastNodeInfo_ = baseModel->lastNodeInfo_;
lastNumberCuts_ = baseModel->lastNumberCuts_;
lastCut_ = baseModel->lastCut_;
lastNumberCuts2_ = baseModel->lastNumberCuts2_;
}
int save2 = maximumDepth_;
int retCode = addCuts(node, lastws);
#ifdef SWITCH_VARIABLES
fixAssociated(solver_,0);
#endif
//if (save1<maximumNumberCuts_) {
// increased
//baseModel->maximumNumberCuts_ = maximumNumberCuts_;
//baseModel->addedCuts_ = addedCuts_;
//}
if (parallelMode() >= 0 && save2 < maximumDepth_) {
// increased
baseModel->maximumDepth_ = maximumDepth_;
baseModel->walkback_ = walkback_;
baseModel->lastNodeInfo_ = lastNodeInfo_;
baseModel->lastNumberCuts_ = lastNumberCuts_;
baseModel->lastCut_ = lastCut_;
baseModel->lastNumberCuts2_ = lastNumberCuts2_;
}
int branchesLeft = 0;
if (!retCode) {
unlockThread();
int i ;
const double * lower = getColLower() ;
const double * upper = getColUpper() ;
for (i = 0 ; i < numberColumns ; i++) {
lowerBefore[i] = lower[i] ;
upperBefore[i] = upper[i] ;
}
if ((solverCharacteristics_->extraCharacteristics()&2) != 0) {
solverCharacteristics_->setBeforeLower(lowerBefore);
solverCharacteristics_->setBeforeUpper(upperBefore);
}
lockThread();
assert (node->objectiveValue() < 1.0e200);
if (messageHandler()->logLevel() > 2)
node->modifiableBranchingObject()->print();
if (branchingMethod_ && branchingMethod_->chooseMethod()) {
branchesLeft = node->branch(solver_); // new way
} else {
// old way so need to cheat
OsiBranchingObject * branch2 = node->modifiableBranchingObject();
#ifndef NDEBUG
CbcBranchingObject * branch = dynamic_cast <CbcBranchingObject *>(branch2) ;
assert (branch);
#else
CbcBranchingObject * branch = static_cast <CbcBranchingObject *>(branch2) ;
#endif
#if 1
branch->setModel(this);
branchesLeft = node->branch(NULL); // old way
#else
branchesLeft = node->branch(solver_);
#endif
if (parallelMode() >= 0)
branch->setModel(baseModel);
}
assert (branchesLeft == node->nodeInfo()->numberBranchesLeft());
if (parallelMode() > 0) {
assert(masterThread_);
assert (node->nodeInfo());
node->nodeInfo()->increment() ;
unlockThread();
}
if ((specialOptions_&1) != 0) {
/*
This doesn't work as intended --- getRowCutDebugger will return null
unless the current feasible solution region includes the optimal solution
that RowCutDebugger knows. There's no way to tell inactive from off the
optimal path.
*/
const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
if (debugger) {
onOptimalPath = true;
printf("On optimal path\n") ;
}
}
/*
Reoptimize, possibly generating cuts and/or using heuristics to find
solutions. Cut reference counts are unaffected unless we lose feasibility,
in which case solveWithCuts() will make the adjustment.
*/
phase_ = 2;
OsiCuts cuts ;
int saveNumber = numberIterations_;
if (solverCharacteristics_->solutionAddsCuts()) {
int returnCode = resolve(node ? node->nodeInfo() : NULL, 1);
feasible = returnCode != 0;
if (feasible) {
int iObject ;
int numberUnsatisfied = 0 ;
memcpy(currentSolution_, solver_->getColSolution(),
numberColumns*sizeof(double)) ;
// point to useful information
OsiBranchingInformation usefulInfo = usefulInformation();
for (iObject = 0 ; iObject < numberObjects_ ; iObject++) {
double infeasibility =
object_[iObject]->checkInfeasibility(&usefulInfo) ;
if (infeasibility ) numberUnsatisfied++ ;
}
if (returnCode > 0) {
if (numberUnsatisfied) {
feasible = solveWithCuts(cuts, maximumCutPasses_, node);
} else {
// may generate cuts and turn the solution
//to an infeasible one
feasible = solveWithCuts(cuts, 1,
node);
}
}
// check extra info on feasibility
if (!solverCharacteristics_->mipFeasible()) {
feasible = false;
solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
}
}
} else {
// normal
if (false) {
const double * lower = solver_->getColLower();
const double * upper = solver_->getColUpper();
printf("STATE before solve\n");
for (int i = 0; i < 100; i++)
if (lower[i] || !upper[i])
printf("%d fixed to %g\n", i, lower[i]);
}
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if ((clpSolver || (specialOptions_&16384) != 0) && fastNodeDepth_ < -1
&& (specialOptions_&2048) == 0) {
#define FATHOM_BIAS -2
if (numberNodes_ == 1) {
int numberNodesBeforeFathom = 500;
if (fastNodeDepth_ < -1000001) {
numberNodesBeforeFathom = (-fastNodeDepth_) / 1000000;
numberNodesBeforeFathom = 250 * numberNodesBeforeFathom;
}
#ifdef COIN_DEVELOP
int fastNodeDepth1 = -fastNodeDepth_ % 1000000;
printf("initial depth %d after %d nodes\n",
FATHOM_BIAS + fastNodeDepth1, numberNodesBeforeFathom);
#endif
}
//#endif
ClpNodeStuff stuff;
ClpNodeStuff * info = &stuff;
/*
Used to generate bound edits for CbcPartialNodeInfo.
*/
//double * lowerBefore = NULL;
//double * upperBefore = NULL;
int fastNodeDepth1 = -fastNodeDepth_ % 1000000;
int numberNodesBeforeFathom = 500;
if (fastNodeDepth_ < -1000001) {
numberNodesBeforeFathom = (-fastNodeDepth_) / 1000000;
numberNodesBeforeFathom = 100 * numberNodesBeforeFathom;
}
int go_fathom = FATHOM_BIAS + fastNodeDepth1;
if ((specialOptions_&16384) != 0)
numberNodesBeforeFathom = 0;
if (node->depth() >= go_fathom && (specialOptions_&2048) == 0
//if (node->depth()>=FATHOM_BIAS-fastNodeDepth_&&!parentModel_
&& numberNodes_ >= numberNodesBeforeFathom && !hotstartSolution_) {
#ifndef COIN_HAS_CPX
specialOptions_ &= ~16384;
#endif
if ((specialOptions_&16384) == 0) {
info->integerTolerance_ = getIntegerTolerance();
info->integerIncrement_ = getCutoffIncrement();
info->numberBeforeTrust_ = numberBeforeTrust_;
info->stateOfSearch_ = 1;
if (numberSolutions_ > 0) {
info->stateOfSearch_ = 3;
}
if (numberNodes_ > 2*numberObjects_ + 1000) {
info->stateOfSearch_ = 4;
}
// Compute "small" change in branch
int nBranches = intParam_[CbcNumberBranches];
if (nBranches) {
double average = dblParam_[CbcSumChange] / static_cast<double>(nBranches);
info->smallChange_ =
CoinMax(average * 1.0e-5, dblParam_[CbcSmallestChange]);
info->smallChange_ = CoinMax(info->smallChange_, 1.0e-8);
} else {
info->smallChange_ = 1.0e-8;
}
double * down = new double[numberIntegers_];
double * up = new double[numberIntegers_];
int * priority = new int[numberIntegers_];
int * numberDown = new int[numberIntegers_];
int * numberUp = new int[numberIntegers_];
int * numberDownInfeasible = new int[numberIntegers_];
int * numberUpInfeasible = new int[numberIntegers_];
fillPseudoCosts(down, up, priority, numberDown, numberUp,
numberDownInfeasible, numberUpInfeasible);
// See if all priorities same
bool allSame = true;
int kPriority = priority[0];
for (int i = 1; i < numberIntegers_; i++) {
if (kPriority != priority[i]) {
allSame = false;
break;
}
}
ClpSimplex * simplex = clpSolver->getModelPtr();
if (allSame && false) {
// change priorities on general
const double * lower = simplex->columnLower();
const double * upper = simplex->columnUpper();
for (int i = 0; i < numberIntegers_; i++) {
int iColumn = integerVariable_[i];
if (upper[iColumn] > lower[iColumn] + 1.1)
priority[i] = kPriority + 1;
}
}
info->fillPseudoCosts(down, up, priority, numberDown, numberUp,
numberDownInfeasible,
numberUpInfeasible, numberIntegers_);
info->presolveType_ = 1;
// for reduced costs and duals
info->solverOptions_ |= 7;
delete [] down;
delete [] up;
delete [] numberDown;
delete [] priority;
delete [] numberUp;
delete [] numberDownInfeasible;
delete [] numberUpInfeasible;
bool takeHint;
OsiHintStrength strength;
solver_->getHintParam(OsiDoReducePrint, takeHint, strength);
//printf("mod cutoff %g solver %g offset %g\n",
// getCutoff(),simplex->dualObjectiveLimit(),simplex->objectiveOffset());
int saveLevel = simplex->logLevel();
if (strength != OsiHintIgnore && takeHint && saveLevel == 1)
simplex->setLogLevel(0);
clpSolver->setBasis();
int perturbation = simplex->perturbation();
if ((specialOptions_&131072) != 0) {
//assert (perturbation == 100);
simplex->setPerturbation(50);
}
int saveMoreOptions = simplex->moreSpecialOptions();
int flags = (moreSpecialOptions_>>18)&3;
simplex->setMoreSpecialOptions(saveMoreOptions|flags<<11);
#ifndef NO_FATHOM_PRINT
info->startingDepth_ = node->depth();
info->nodeCalled_ = numberNodes_;
info->handler_ = handler_;
#endif
feasible = simplex->fathom(info) != 0;
simplex->setMoreSpecialOptions(saveMoreOptions);
simplex->setPerturbation(perturbation);
incrementExtra(info->numberNodesExplored_,
info->numberIterations_);
char general[200];
int fathomStatus=info->nNodes_;
if (feasible)
fathomStatus=1;
sprintf(general, "fathom took %d nodes, %d iterations - status %d",
info->numberNodesExplored_,
info->numberIterations_,fathomStatus);
messageHandler()->message(CBC_FPUMP2,
messages())
<< general << CoinMessageEol ;
if (info->numberNodesExplored_ > 10000 /* && !feasible */
&& (moreSpecialOptions_&524288) == 0 && info->nNodes_>=0) {
fastNodeDepth_ --;
#ifndef NO_FATHOM_PRINT
if ((moreSpecialOptions_&262144) != 0)
handler_->message(CBC_FATHOM_CHANGE, messages_) <<
FATHOM_BIAS - fastNodeDepth_ << CoinMessageEol ;
#endif
#if CBC_USEFUL_PRINTING>0
printf(">10000 - depth now %d so at depth >= %d\n",
fastNodeDepth_, FATHOM_BIAS - fastNodeDepth_);
#endif
}
if (info->nNodes_ < 0) {
// we gave up
//abort();
fastNodeDepth_ -= (info->nNodes_==-10) ? 5 : 2;
#ifndef NO_FATHOM_PRINT
if ((moreSpecialOptions_&262144) != 0)
handler_->message(CBC_FATHOM_CHANGE, messages_) <<
FATHOM_BIAS - fastNodeDepth_ << CoinMessageEol ;
#endif
#if CBC_USEFUL_PRINTING>0
printf("gave up fastNodeDepth now %d - so at depth >= %d\n",
fastNodeDepth_, FATHOM_BIAS - fastNodeDepth_);
#endif
if (feasible) {
// Save bounds round bestSolution
//double * saveLower = CoinCopyOfArray(solver_->getColLower(),
// numberColumns);
//double * saveUpper = CoinCopyOfArray(solver_->getColUpper(),
// numberColumns);
clpSolver->setWarmStart(NULL);
// try and do solution
double value = simplex->objectiveValue();
double * newSolution =
CoinCopyOfArray(simplex->primalColumnSolution(),
numberColumns);
setBestSolution(CBC_STRONGSOL, value, newSolution) ;
delete [] newSolution;
//solver_->setColLower(saveLower);
//solver_->setColUpper(saveUpper);
//delete [] saveLower;
//delete [] saveUpper;
}
// say feasible so will redo node
feasible = true;
} else {
if (feasible) {
clpSolver->setWarmStart(NULL);
// try and do solution
double value = simplex->objectiveValue();
double * newSolution =
CoinCopyOfArray(simplex->primalColumnSolution(),
numberColumns);
setBestSolution(CBC_STRONGSOL, value, newSolution) ;
// in case of inaccuracy
simplex->setObjectiveValue(CoinMax(bestObjective_,
simplex->objectiveValue()));
delete [] newSolution;
}
// update pseudo costs
double smallest = 1.0e50;
double largest = -1.0;
for (int i = 0; i < numberIntegers_; i++) {
CbcSimpleIntegerDynamicPseudoCost * obj =
dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[i]) ;
if (!obj)
continue;
assert (obj->columnNumber() == integerVariable_[i]);
if (info->numberUp_[i] > 0) {
if (info->downPseudo_[i] > largest)
largest = info->downPseudo_[i];
if (info->downPseudo_[i] < smallest)
smallest = info->downPseudo_[i];
if (info->upPseudo_[i] > largest)
largest = info->upPseudo_[i];
if (info->upPseudo_[i] < smallest)
smallest = info->upPseudo_[i];
obj->updateAfterMini(info->numberDown_[i],
info->numberDownInfeasible_[i],
info->downPseudo_[i],
info->numberUp_[i],
info->numberUpInfeasible_[i],
info->upPseudo_[i]);
}
}
//printf("range of costs %g to %g\n",smallest,largest);
}
simplex->setLogLevel(saveLevel);
#ifdef COIN_HAS_CPX
} else {
// try cplex
OsiCpxSolverInterface cpxSolver;
double direction = clpSolver->getObjSense();
cpxSolver.setObjSense(direction);
// load up cplex
const CoinPackedMatrix * matrix = clpSolver->getMatrixByCol();
const double * rowLower = clpSolver->getRowLower();
const double * rowUpper = clpSolver->getRowUpper();
const double * columnLower = clpSolver->getColLower();
const double * columnUpper = clpSolver->getColUpper();
const double * objective = clpSolver->getObjCoefficients();
cpxSolver.loadProblem(*matrix, columnLower, columnUpper,
objective, rowLower, rowUpper);
double * setSol = new double [numberIntegers_];
int * setVar = new int [numberIntegers_];
// cplex doesn't know about objective offset
double offset = clpSolver->getModelPtr()->objectiveOffset();
for (int i = 0; i < numberIntegers_; i++) {
int iColumn = integerVariable_[i];
cpxSolver.setInteger(iColumn);
if (bestSolution_) {
setSol[i] = bestSolution_[iColumn];
setVar[i] = iColumn;
}
}
CPXENVptr env = cpxSolver.getEnvironmentPtr();
CPXLPptr lpPtr = cpxSolver.getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
cpxSolver.switchToMIP();
if (bestSolution_) {
CPXcopymipstart(env, lpPtr, numberIntegers_, setVar, setSol);
}
if (getCutoff() < 1.0e50) {
double useCutoff = getCutoff() + offset;
if (bestObjective_ < 1.0e50)
useCutoff = bestObjective_ + offset + 1.0e-7;
cpxSolver.setDblParam(OsiDualObjectiveLimit, useCutoff*
direction);
if ( direction > 0.0 )
CPXsetdblparam( env, CPX_PARAM_CUTUP, useCutoff ) ; // min
else
CPXsetdblparam( env, CPX_PARAM_CUTLO, useCutoff ) ; // max
}
CPXsetdblparam(env, CPX_PARAM_EPGAP, dblParam_[CbcAllowableFractionGap]);
delete [] setSol;
delete [] setVar;
if (offset) {
char printBuffer[200];
sprintf(printBuffer, "Add %g to all Cplex messages for true objective",
-offset);
messageHandler()->message(CBC_GENERAL, messages())
<< printBuffer << CoinMessageEol ;
cpxSolver.setDblParam(OsiObjOffset, offset);
}
cpxSolver.branchAndBound();
numberExtraNodes_ += CPXgetnodecnt(env, lpPtr);
numberExtraIterations_ += CPXgetmipitcnt(env, lpPtr);
double value = cpxSolver.getObjValue() * direction;
if (cpxSolver.isProvenOptimal() && value <= getCutoff()) {
feasible = true;
clpSolver->setWarmStart(NULL);
// try and do solution
double * newSolution =
CoinCopyOfArray(cpxSolver.getColSolution(),
getNumCols());
setBestSolution(CBC_STRONGSOL, value, newSolution) ;
delete [] newSolution;
}
#endif
}
}
}
if (feasible) {
//int numberPasses = doCutsNow(1) ? maximumCutPasses_ : 0;
int numberPasses = /*doCutsNow(1) ?*/ maximumCutPasses_ /*: 0*/;
feasible = solveWithCuts(cuts, numberPasses, node);
}
#else
feasible = solveWithCuts(cuts, maximumCutPasses_, node);
#endif
}
if ((specialOptions_&1) != 0 && onOptimalPath) {
if(solver_->getRowCutDebuggerAlways()->optimalValue()<getCutoff()) {
if (!solver_->getRowCutDebugger() || !feasible) {
// dj fix did something???
solver_->writeMpsNative("infeas2.mps", NULL, NULL, 2);
solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
#ifndef NDEBUG
const OsiRowCutDebugger * debugger = solver_->getRowCutDebugger() ;
#endif
assert (debugger) ;
int numberRows0=continuousSolver_->getNumRows();
int numberRows=solver_->getNumRows();
const CoinPackedMatrix * rowCopy = solver_->getMatrixByRow();
const int * rowLength = rowCopy->getVectorLengths();
const double * elements = rowCopy->getElements();
const int * column = rowCopy->getIndices();
const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
const double * rowLower = solver_->getRowLower();
const double * rowUpper = solver_->getRowUpper();
for (int iRow=numberRows0;iRow<numberRows;iRow++) {
OsiRowCut rc;
rc.setLb(rowLower[iRow]);
rc.setUb(rowUpper[iRow]);
CoinBigIndex start = rowStart[iRow];
rc.setRow(rowLength[iRow],column+start,elements+start,false);
CoinAssert (!debugger->invalidCut(rc));
}
assert (feasible);
}
}
}
if (statistics_) {
assert (numberNodes2_);
assert (statistics_[numberNodes2_-1]);
assert (statistics_[numberNodes2_-1]->node() == numberNodes2_ - 1);
statistics_[numberNodes2_-1]->endOfBranch(numberIterations_ - saveNumber,
feasible ? solver_->getObjValue()
: COIN_DBL_MAX);
}
/*
Are we still feasible? If so, create a node and do the work to attach a
branching object, reoptimising as needed if chooseBranch() identifies
monotone objects.
Finally, attach a partial nodeInfo object and store away any cuts that we
created back in solveWithCuts. addCuts() will initialise the reference
counts for these new cuts.
This next test can be problematic if we've discovered an
alternate equivalent answer and subsequently fathom the solution
known to the row cut debugger due to bounds.
*/
if (onOptimalPath) {
bool objLim = solver_->isDualObjectiveLimitReached() ;
if (!feasible && !objLim) {
if(solver_->getRowCutDebuggerAlways()->optimalValue()<getCutoff()) {
printf("infeas2\n");
solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
solver_->writeMpsNative("infeas.mps", NULL, NULL, 2);
CoinWarmStartBasis *slack =
dynamic_cast<CoinWarmStartBasis *>(solver_->getEmptyWarmStart()) ;
solver_->setWarmStart(slack);
delete slack ;
solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0) ;
solver_->initialSolve();
assert (!solver_->isProvenOptimal());
assert (feasible || objLim);
}
}
}
bool checkingNode = false;
if (feasible) {
#ifdef FUNNY_BRANCHING2
// Far too clever
if ((numberThreads_ == -10 || true) && node->numberBranches() == 2) {
// see if any parent branches redundant
// Look at state of "node"
CbcNodeInfo * nodeInfo = node->nodeInfo();
if (nodeInfo) {
// See if any branched variables off bounds
const double * dj = solver_->getReducedCost();
const double * lower = solver_->getColLower();
const double * upper = solver_->getColUpper();
const double * solution = solver_->getColSolution();
int numberColumns = solver_->getNumCols();
double * currentLower = CoinCopyOfArray(lower, numberColumns);
double * currentUpper = CoinCopyOfArray(upper, numberColumns);
char * touched = new char[numberColumns];
memset(touched, 0, numberColumns);
double direction = solver_->getObjSense() ;
bool canDelete = nodeInfo->numberBranchesLeft() > 0;
//int numberBounds = nodeInfo->numberChangedBounds();
//const int * which = nodeInfo->variables();
//const double * bounds = nodeInfo->newBounds();
const OsiBranchingObject * obj = node->branchingObject();
const CbcIntegerBranchingObject * objectI = dynamic_cast<const CbcIntegerBranchingObject *> (obj);
if (objectI) {
const CbcSimpleInteger * object1 = dynamic_cast<const CbcSimpleInteger *> (objectI->object());
int iColumn1 = -1;
int way1 = 0;
const double * bounds1 = NULL;
bool zeroOne1 = false;
if (object1) {
iColumn1 = object1->columnNumber();
double originalLower1 = object1->originalLowerBound();
double originalUpper1 = object1->originalUpperBound();
// Unset all bounds from parents
CbcPartialNodeInfo * partial =
dynamic_cast<CbcPartialNodeInfo *>(nodeInfo);
touched[iColumn1] = 1;
if (partial) {
/* maybe don't do if obj hasn't changed
as then you might get loop
at present just 0-1
as need to know original bound
*/
int n = partial->numberChangedBounds();
const int * which = partial->variables();
const double * values = partial->newBounds();
for (int i = 0; i < n; i++) {
int variable = which[i];
int k = variable & 0x3fffffff;
assert (k != iColumn1);
if (!touched[k]) {
if ((variable&0x80000000) == 0) {
// lower bound changing
assert (currentLower[k] == 1.0);
currentLower[k] = 0.0;
} else {
// upper bound changing
assert (currentUpper[k] == 0.0);
currentUpper[k] = 1.0;
}
}
}
}
zeroOne1 = originalLower1 == 0.0 && originalUpper1 == 1.0;
way1 = objectI->way();
assert (way1 == -1 || way1 == 1);
int kWay = way1;
//way1 = -way1; // what last branch did
// work out using bounds
if (objectI->downBounds()[1] >= upper[iColumn1] &&
objectI->downBounds()[0] <= lower[iColumn1])
way1 = -1;
else
way1 = 1;
assert (kWay == -way1);
if (way1 < 0) {
// must have been down branch
bounds1 = objectI->downBounds();
} else {
// must have been up branch
bounds1 = objectI->upBounds();
}
// double check bounds
assert (bounds1[0] <= lower[iColumn1] && bounds1[1] >= upper[iColumn1]);
}
bool inBetween = false;
#ifdef CBC_PRINT2
printf("%d (way %d) with down bounds %g, %g and up bounds %g, %g current bounds %g, %g solution %g dj %g (bleft %d)\n",
iColumn1, way1, objectI->downBounds()[0], objectI->downBounds()[1],
objectI->upBounds()[0], objectI->upBounds()[1],
lower[iColumn1], upper[iColumn1], solution[iColumn1],
dj[iColumn1], nodeInfo->numberBranchesLeft());
#endif
while (nodeInfo->parent()) {
nodeInfo = nodeInfo->parent();
CbcNode * nodeLook = nodeInfo->mutableOwner();
if (!nodeLook || nodeLook->objectiveValue() == 0.5*COIN_DBL_MAX)
continue;
OsiBranchingObject * obj = nodeLook->modifiableBranchingObject();
CbcIntegerBranchingObject * objectI = dynamic_cast<CbcIntegerBranchingObject *> (obj);
//const OsiObject * object2a = obj->originalObject();
//assert (object2a);
const CbcSimpleInteger * object2 = dynamic_cast<const CbcSimpleInteger *> (objectI->object());
if (nodeInfo->numberBranchesLeft() && object2) {
int iColumn2 = object2->columnNumber();
double originalLower = object2->originalLowerBound();
double originalUpper = object2->originalUpperBound();
bool zeroOne2 = originalLower == 0.0 && originalUpper == 1.0;
zeroOne1 = true; // temp
double newUpper = originalUpper;
double newLower = originalLower;
//double value = solution[iColumn2];
double djValue = dj[iColumn2] * direction;
int way = objectI->way();
assert (way == -1 || way == 1);
way = -way; // what last branch did
#ifdef CBC_PRINT2
printf("%d (way %d) with down bounds %g, %g and up bounds %g, %g current bounds %g, %g solution %g dj %g (bleft %d)\n",
iColumn2, way, objectI->downBounds()[0], objectI->downBounds()[1],
objectI->upBounds()[0], objectI->upBounds()[1],
lower[iColumn2], upper[iColumn2], solution[iColumn2],
djValue, nodeInfo->numberBranchesLeft());
#endif
/*if (objectI->downBounds()[0]==0&&objectI->downBounds()[1]==1&&
objectI->upBounds()[0]==0&&objectI->upBounds()[1]==1)
assert(lower[iColumn2]<upper[iColumn2]);*/
if (way < 0) {
// must have been down branch
const double * bounds = objectI->downBounds();
if (djValue > 1.0e-3 || solution[iColumn2] < upper[iColumn2] - 1.0e-5) {
if (canDelete) {
//nRedundantDown++;
#ifndef JJF_ONE
COIN_DETAIL_PRINT(printf("%d redundant branch down with bounds %g, %g current upper %g solution %g dj %g\n",
iColumn2, bounds[0], bounds[1], upper[iColumn2], solution[iColumn2], djValue));
#endif
if (bounds[0] == bounds[1] || zeroOne2 || (bounds[0] == lower[iColumn2] && false)) {
{
// get rid of node as far as branching
nodeLook->setObjectiveValue(0.5*COIN_DBL_MAX);
objectI->deactivate();
}
previousBounds(node, nodeInfo, iColumn2, newLower, newUpper, 2);
solver_->setColUpper(iColumn2, newUpper);
assert (newLower == lower[iColumn2]);
} else {
COIN_DETAIL_PRINT(printf("SKipping\n"));
}
} else if (iColumn1 >= 0 && iColumn1 != iColumn2 && (!inBetween || true) && zeroOne1 && zeroOne2 && false) {
#ifndef JJF_ONE
if (true) {
// add in bounds
newLower = bounds1[0];
newUpper = bounds1[1];
COIN_DETAIL_PRINT(printf("setting bounds of %g and %g (column %d) on other branch for column %d\n",
newLower, newUpper, iColumn1, iColumn2));
int infeasible = objectI->applyExtraBounds(iColumn1, newLower, newUpper, objectI->way());
if (infeasible) {
COIN_DETAIL_PRINT(printf("infeasa!\n"));
// get rid of node as far as branching
nodeLook->setObjectiveValue(0.5*COIN_DBL_MAX);
}
}
#endif
}
//break;
} else {
inBetween = true;
}
} else {
// must have been up branch
const double * bounds = objectI->upBounds();
if (djValue < -1.0e-3 || solution[iColumn2] > lower[iColumn2] + 1.0e-5) {
if (canDelete) {
//nRedundantUp++;
#ifndef JJF_ONE
COIN_DETAIL_PRINT(printf("%d redundant branch up with bounds %g, %g current lower %g solution %g dj %g\n",
iColumn2, bounds[0], bounds[1], lower[iColumn2], solution[iColumn2], djValue));
#endif
if (bounds[0] == bounds[1] || zeroOne2 || (bounds[1] == upper[iColumn2] && false)) {
{
// get rid of node as far as branching
nodeLook->setObjectiveValue(0.5*COIN_DBL_MAX);
objectI->deactivate();
}
previousBounds(node, nodeInfo, iColumn2, newLower, newUpper, 1);
solver_->setColLower(iColumn2, newLower);
assert (newUpper == upper[iColumn2]);
} else {
COIN_DETAIL_PRINT(printf("SKipping\n"));
}
} else if (iColumn1 >= 0 && iColumn1 != iColumn2 && (!inBetween || true) && zeroOne1 && zeroOne2 && false) {
#ifndef JJF_ONE
// add in bounds
newLower = bounds1[0];
newUpper = bounds1[1];
COIN_DETAIL_PRINT(printf("setting bounds of %g and %g (column %d) on other branch for column %d\n",
newLower, newUpper, iColumn1, iColumn2));
int infeasible = objectI->applyExtraBounds(iColumn1, newLower, newUpper, objectI->way());
if (infeasible) {
COIN_DETAIL_PRINT(printf("infeasb!\n"));
// get rid of node as far as branching
nodeLook->setObjectiveValue(0.5*COIN_DBL_MAX);
}
#endif
}
// break;
} else {
inBetween = true;
}
}
} else {
// odd
break;
}
}
}
delete [] currentLower;
delete [] currentUpper;
}
}
#endif
if (parallelMode() >= 0)
newNode = new CbcNode() ;
#if 0
// Try diving
if (parallelMode() >= 0 && (specialOptions_&2048) == 0) {
// See if any diving heuristics set to do dive+save
CbcHeuristicDive * dive=NULL;
for (int i = 0; i < numberHeuristics_; i++) {
CbcHeuristicDive * possible = dynamic_cast<CbcHeuristicDive *>(heuristic_[i]);
if (possible&&possible->maxSimplexIterations()==COIN_INT_MAX) {
// if more than one then rotate later?
//if (possible->canHeuristicRun()) {
if (node->depth()==0||node->depth()==5) {
dive=possible;
break;
}
}
}
if (dive) {
int numberNodes;
CbcSubProblem ** nodes=NULL;
int branchState=dive->fathom(this,numberNodes,nodes);
if (branchState) {
printf("new solution\n");
}
if (0) {
for (int iNode=0;iNode<numberNodes;iNode++) {
//tree_->push(nodes[iNode]) ;
}
assert (node->nodeInfo());
if (node->nodeInfo()->numberBranchesLeft()) {
tree_->push(node) ;
} else {
node->setActive(false);
}
}
delete [] nodes;
}
}
// end try diving
#endif
// Set objective value (not so obvious if NLP etc)
setObjectiveValue(newNode, node);
int anyAction = -1 ;
bool resolved = false ;
if (newNode->objectiveValue() >= getCutoff()) {
anyAction = -2;
} else {// only allow at most a few passes
int numberPassesLeft = 5;
checkingNode = true;
OsiSolverBranch * branches = NULL;
// point to useful information
anyAction = chooseBranch(newNode, numberPassesLeft, node, cuts, resolved,
lastws, lowerBefore, upperBefore, branches);
}
/*
If we end up infeasible, we can delete the new node immediately. Since this
node won't be needing the cuts we collected, decrement the reference counts.
If we are feasible, then we'll be placing this node into the live set, so
increment the reference count in the current (parent) nodeInfo.
*/
lockThread();
if (anyAction == -2) {
if (parallelMode() > 0) {
assert (masterThread_);
assert (node->nodeInfo());
node->nodeInfo()->decrement() ;
delete newNode ;
assert (node->nodeInfo());
node->nodeInfo()->increment() ;
newNode = NULL ;
} else if (parallelMode() == 0) {
delete newNode ;
newNode = NULL ;
} else {
//assert (newNode->active());
newNode->setActive(false);
}
// say strong doing well
if (checkingNode)
setSpecialOptions(specialOptions_ | 8);
for (i = 0 ; i < currentNumberCuts_ ; i++) {
if (addedCuts_[i]) {
if (!addedCuts_[i]->decrement(1)) {
delete addedCuts_[i] ;
}
addedCuts_[i] = NULL;
//}
}
}
} else {
assert (node->nodeInfo());
if (parallelMode() >= 0)
node->nodeInfo()->increment() ;
if ((numberNodes_ % 20) == 0) {
// say strong not doing as well
setSpecialOptions(specialOptions_&~8);
}
}
unlockThread();
}
/*
At this point, there are three possibilities:
* newNode is live and will require further branching to resolve
(variable() >= 0). Increment the cut reference counts by
numberBranches() to allow for use by children of this node, and
decrement by 1 because we've executed one arm of the branch of our
parent (consuming one reference). Before we push newNode onto the
search tree, try for a heuristic solution.
* We have a solution, in which case newNode is non-null but we have no
branching variable. Decrement the cut counts and save the solution.
* The node was found to be infeasible, in which case it's already been
deleted, and newNode is null.
*/
if (eventHandler_ && !eventHandler_->event(CbcEventHandler::node)) {
eventHappened_ = true; // exit
}
if (parallelMode() >= 0)
assert (!newNode || newNode->objectiveValue() <= getCutoff()) ;
else
assert (!newNode->active() || newNode->objectiveValue() <= getCutoff()) ;
if (statistics_) {
assert (numberNodes2_);
assert (statistics_[numberNodes2_-1]);
assert (statistics_[numberNodes2_-1]->node() == numberNodes2_ - 1);
if (newNode && newNode->active())
statistics_[numberNodes2_-1]->updateInfeasibility(newNode->numberUnsatisfied());
else
statistics_[numberNodes2_-1]->sayInfeasible();
}
lockThread();
bool locked = true;
if (parallelMode() <= 0) {
if (numberUpdateItems_) {
for (i = 0; i < numberUpdateItems_; i++) {
CbcObjectUpdateData * update = updateItems_ + i;
CbcObject * object = dynamic_cast<CbcObject *> (update->object_);
#ifndef NDEBUG
bool found = false;
for (int j = 0; j < numberObjects_; j++) {
if (update->object_ == object_[j]) {
found = true;
break;
}
}
assert (found);
#endif
//if (object)
//assert (object==object_[update->objectNumber_]);
if (object)
object->updateInformation(*update);
}
numberUpdateItems_ = 0;
}
}
if (newNode)
if (newNode && newNode->active()) {
if (newNode->branchingObject() == NULL) {
const double * solution = solver_->getColSolution();
CbcEventHandler::CbcAction action =
dealWithEventHandler(CbcEventHandler::beforeSolution1,
getSolverObjValue(), solution);
if (action == CbcEventHandler::addCuts ||
solverCharacteristics_->solverType() == 4) {
// need to check if any cuts would do anything
OsiCuts theseCuts;
// reset probing info
//if (probingInfo_)
//probingInfo_->initializeFixing(solver_);
for (int i = 0; i < numberCutGenerators_; i++) {
bool generate = generator_[i]->normal();
// skip if not optimal and should be (maybe a cut generator has fixed variables)
if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable())
generate = false;
if (!generator_[i]->mustCallAgain())
generate = false; // only special cuts
if (generate) {
generator_[i]->generateCuts(theseCuts, -1, solver_, NULL) ;
int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
if (numberRowCutsAfter)
break;
}
}
int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
if (numberRowCutsAfter ||
action == CbcEventHandler::addCuts) {
// need dummy branch
newNode->setBranchingObject(new CbcDummyBranchingObject(this));
newNode->nodeInfo()->initializeInfo(1);
}
}
}
if (newNode->branchingObject()) {
handler_->message(CBC_BRANCH, messages_)
<< numberNodes_ << newNode->objectiveValue()
<< newNode->numberUnsatisfied() << newNode->depth()
<< CoinMessageEol ;
// Increment cut counts (taking off current)
int numberLeft = newNode->numberBranches() ;
for (i = 0; i < currentNumberCuts_; i++) {
if (addedCuts_[i]) {
# ifdef CHECK_CUT_COUNTS
printf("Count on cut %x increased by %d\n", addedCuts_[i],
numberLeft - 1) ;
# endif
addedCuts_[i]->increment(numberLeft - 1) ;
}
}
unlockThread();
locked = false;
double estValue = newNode->guessedObjectiveValue() ;
int found = -1 ;
double * newSolution = new double [numberColumns] ;
double heurValue = getCutoff() ;
int iHeur ;
int whereFrom = 3;
// allow more heuristics
currentPassNumber_=0;
for (iHeur = 0 ; iHeur < numberHeuristics_ ; iHeur++) {
// skip if can't run here
if (!heuristic_[iHeur]->shouldHeurRun(whereFrom))
continue;
double saveValue = heurValue ;
int ifSol = heuristic_[iHeur]->solution(heurValue, newSolution) ;
if (ifSol > 0) {
// new solution found
heuristic_[iHeur]->incrementNumberSolutionsFound();
found = iHeur ;
if (parallelMode() > 0) {
lockThread();
baseModel->incrementUsed(newSolution);
unlockThread();
} else {
lastHeuristic_ = heuristic_[found];
#ifdef HEURISTIC_INFORM
printf("HEUR %s where %d D\n",
lastHeuristic_->heuristicName(), whereFrom);
#endif
setBestSolution(CBC_ROUNDING, heurValue, newSolution) ;
foundSolution = 1;
whereFrom |= 8; // say solution found
}
} else if (ifSol < 0) { // just returning an estimate
estValue = heurValue; //CoinMin(heurValue, estValue) ;
heurValue = saveValue ;
}
}
if (found >= 0 && parallelMode() > 0) {
lastHeuristic_ = heuristic_[found];
#if CBC_USEFUL_PRINTING>1
printf("HEUR %s where %d D\n",
lastHeuristic_->heuristicName(), whereFrom);
#endif
setBestSolution(CBC_ROUNDING, heurValue, newSolution) ;
foundSolution = 1;
}
delete [] newSolution ;
newNode->setGuessedObjectiveValue(estValue) ;
if (parallelMode() >= 0) {
if (!masterThread_) // only if serial
tree_->push(newNode) ;
}
if (statistics_) {
if (numberNodes2_ == maximumStatistics_) {
maximumStatistics_ = 2 * maximumStatistics_;
CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
memset(temp, 0, maximumStatistics_*sizeof(CbcStatistics *));
memcpy(temp, statistics_, numberNodes2_*sizeof(CbcStatistics *));
delete [] statistics_;
statistics_ = temp;
}
assert (!statistics_[numberNodes2_]);
statistics_[numberNodes2_] = new CbcStatistics(newNode, this);
}
numberNodes2_++;
# ifdef CHECK_NODE
printf("Node %x pushed on tree c\n", newNode) ;
# endif
} else {
if (solverCharacteristics_ && //we may be in a non standard bab
solverCharacteristics_->solutionAddsCuts()// we are in some kind of OA based bab.
) {
std::cerr << "You should never get here" << std::endl;
throw CoinError("Nodes should not be fathomed on integer infeasibility in this setting",
"branchAndBound", "CbcModel") ;
}
for (i = 0 ; i < currentNumberCuts_ ; i++) {
if (addedCuts_[i]) {
if (!addedCuts_[i]->decrement(1)) {
delete addedCuts_[i] ;
addedCuts_[i] = NULL;
}
}
}
double objectiveValue = newNode->objectiveValue();
lastHeuristic_ = NULL;
// Just possible solver did not know about a solution from another thread!
if (objectiveValue < getCutoff()) {
incrementUsed(solver_->getColSolution());
setBestSolution(CBC_SOLUTION, objectiveValue,
solver_->getColSolution()) ;
// Check if was found
if (bestObjective_ < getCutoff())
foundSolution = 1;
}
//assert(nodeInfo->numberPointingToThis() <= 2) ;
if (parallelMode() >= 0) {
// avoid accidental pruning, if newNode was final branch arm
node->nodeInfo()->increment();
delete newNode ;
newNode = NULL;
node->nodeInfo()->decrement() ;
} else {
newNode->setActive(false);
}
}
}
if (branchesLeft) {
// set nodenumber correctly
if (node->nodeInfo())
node->nodeInfo()->setNodeNumber(numberNodes2_);
if (parallelMode() >= 0) {
if (!masterThread_) // only if serial
tree_->push(node) ;
}
if (statistics_) {
if (numberNodes2_ == maximumStatistics_) {
maximumStatistics_ = 2 * maximumStatistics_;
CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
memset(temp, 0, maximumStatistics_*sizeof(CbcStatistics *));
memcpy(temp, statistics_, numberNodes2_*sizeof(CbcStatistics *));
delete [] statistics_;
statistics_ = temp;
}
assert (!statistics_[numberNodes2_]);
statistics_[numberNodes2_] = new CbcStatistics(node, this);
}
numberNodes2_++;
//nodeOnTree=true; // back on tree
//deleteNode = false ;
# ifdef CHECK_NODE
printf("Node %x pushed back on tree - %d left, %d count\n", node,
node->nodeInfo()->numberBranchesLeft(),
node->nodeInfo()->numberPointingToThis()) ;
# endif
if (parallelMode() > 0) {
assert (node->nodeInfo());
node->nodeInfo()->decrement() ;
}
} else {
/*
This node has been completely expanded and can be removed from the live
set.
*/
if (parallelMode() > 0) {
assert (masterThread_) ;
assert (node->nodeInfo());
node->nodeInfo()->decrement() ;
}
assert (node->nodeInfo());
if (parallelMode() >= 0) {
if (!node->nodeInfo()->numberBranchesLeft())
node->nodeInfo()->allBranchesGone(); // can clean up
delete node ;
node = NULL;
} else {
node->setActive(false);
}
}
if (locked)
unlockThread();
} else {
// add cuts found to be infeasible (on bound)!
COIN_DETAIL_PRINT(printf("found to be infeas! - branches left %d - cutoff %g\n", node->nodeInfo()->numberBranchesLeft(),
getCutoff()));
#ifdef COIN_DETAIL
node->print();
#endif
//abort();
assert (node->nodeInfo());
if (parallelMode() >= 0) {
if (!node->nodeInfo()->numberBranchesLeft())
node->nodeInfo()->allBranchesGone(); // can clean up
delete node;
node = NULL;
} else {
node->setActive(false);
}
}
/*
Delete cuts to get back to the original system.
I'm thinking this is redundant --- the call to addCuts that conditions entry
to this code block also performs this action.
*/
#ifndef JJF_ONE
//if (numberThreads_)
{
int numberToDelete = getNumRows() - numberRowsAtContinuous_ ;
if (numberToDelete) {
int * delRows = new int[numberToDelete] ;
int i ;
for (i = 0 ; i < numberToDelete ; i++)
delRows[i] = i + numberRowsAtContinuous_ ;
solver_->deleteRows(numberToDelete, delRows) ;
delete [] delRows ;
}
numberNewCuts_=0;
}
#endif
delete lastws ;
delete [] lowerBefore ;
delete [] upperBefore ;
if (bestObjective > bestObjective_)
foundSolution = 2;
if (parallelMode() > 0 && foundSolution) {
lockThread();
// might as well mark all including continuous
int numberColumns = solver_->getNumCols();
for (int i = 0; i < numberColumns; i++) {
baseModel->usedInSolution_[i] += usedInSolution_[i];
usedInSolution_[i] = 0;
}
if (bestObjective_ < baseModel->bestObjective_ && bestObjective_ < baseModel->getCutoff()) {
baseModel->bestObjective_ = bestObjective_ ;
int numberColumns = solver_->getNumCols();
if (!baseModel->bestSolution_)
baseModel->bestSolution_ = new double[numberColumns];
CoinCopyN(bestSolution_, numberColumns, baseModel->bestSolution_);
baseModel->setCutoff(getCutoff());
baseModel->handler_->message(CBC_ROUNDING, messages_)
<< bestObjective_
<< "heuristic"
<< baseModel->numberIterations_
<< baseModel->numberNodes_ << getCurrentSeconds()
<< CoinMessageEol;
}
baseModel->numberSolutions_++;
unlockThread();
}
numberCutGenerators_=saveNumberCutGenerators;
return foundSolution;
}
// Adds an update information object
void
CbcModel::addUpdateInformation(const CbcObjectUpdateData & data)
{
if (numberUpdateItems_ == maximumNumberUpdateItems_) {
maximumNumberUpdateItems_ += 10;
CbcObjectUpdateData * temp = new CbcObjectUpdateData [maximumNumberUpdateItems_];
for (int i = 0; i < maximumNumberUpdateItems_ - 10; i++)
temp[i] = updateItems_[i];
delete [] updateItems_;
updateItems_ = temp;
}
updateItems_[numberUpdateItems_++] = data;
}
// Returns bounds just before where - initially original bounds - also sets bounds
void CbcModel::previousBounds (CbcNode * node, CbcNodeInfo * where, int iColumn,
double & lower, double & upper, int force)
{
int i;
int nNode = 0;
CbcNodeInfo * nodeInfo = node->nodeInfo();
int nWhere = -1;
/*
Accumulate the path from node to the root in walkback_
*/
while (nodeInfo) {
//printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo);
walkback_[nNode++] = nodeInfo;
nodeInfo = nodeInfo->parent() ;
if (nNode == maximumDepth_) {
redoWalkBack();
}
if (nodeInfo == where)
nWhere = nNode;
}
assert (nWhere >= 0);
nWhere = nNode - nWhere;
for (i = 0; i < nWhere; i++) {
--nNode;
walkback_[nNode]->applyBounds(iColumn, lower, upper, 0);
}
// correct bounds
walkback_[nNode]->applyBounds(iColumn, lower, upper, 3);
CbcNode * nodeLook = walkback_[nNode]->mutableOwner();
if (nodeLook) {
OsiBranchingObject * obj = nodeLook->modifiableBranchingObject();
CbcIntegerBranchingObject * objectI = dynamic_cast<CbcIntegerBranchingObject *> (obj);
//const OsiObject * object2 = obj->orig
#ifndef NDEBUG
const CbcSimpleInteger * object2 = dynamic_cast<const CbcSimpleInteger *> (objectI->object());
assert (object2);
assert (iColumn == object2->columnNumber());
#endif
double bounds[2];
bounds[0] = lower;
bounds[1] = upper;
objectI->setDownBounds(bounds);
objectI->setUpBounds(bounds);
}
while (nNode) {
--nNode;
walkback_[nNode]->applyBounds(iColumn, lower, upper, force);
#ifdef JJF_ZERO
CbcNode * nodeLook = walkback_[nNode]->mutableOwner();
if (nodeLook) {
const OsiBranchingObject * obj = nodeLook->branchingObject();
const CbcIntegerBranchingObject * objectI = dynamic_cast<const CbcIntegerBranchingObject *> (obj);
//const OsiObject * object2 = obj->orig
const CbcSimpleInteger * object2 = dynamic_cast<const CbcSimpleInteger *> (objectI->object());
assert (object2);
int iColumn2 = object2->columnNumber();
assert (iColumn != iColumn2);
}
#endif
}
}
/* Return pseudo costs
If not all integers or not pseudo costs - returns all zero
Length of arrays are numberIntegers() and entries
correspond to integerVariable()[i]
User must allocate arrays before call
*/
void
CbcModel::fillPseudoCosts(double * downCosts, double * upCosts,
int * priority,
int * numberDown, int * numberUp,
int * numberDownInfeasible,
int * numberUpInfeasible) const
{
CoinFillN(downCosts, numberIntegers_, 1.0);
CoinFillN(upCosts, numberIntegers_, 1.0);
if (priority) {
CoinFillN(priority, numberIntegers_, 1000000);
}
if (numberDown) {
CoinFillN(numberDown, numberIntegers_, 1);
CoinFillN(numberUp, numberIntegers_, 1);
}
if (numberDownInfeasible) {
CoinZeroN(numberDownInfeasible, numberIntegers_);
CoinZeroN(numberUpInfeasible, numberIntegers_);
}
int numberColumns = getNumCols();
int * back = new int[numberColumns];
int i;
for (i = 0; i < numberColumns; i++)
back[i] = -1;
for (i = 0; i < numberIntegers_; i++)
back[integerVariable_[i]] = i;
#if CBC_USEFUL_PRINTING>1
int numberNot = 0;
#endif
for ( i = 0; i < numberObjects_; i++) {
CbcSimpleIntegerDynamicPseudoCost * obj =
dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[i]) ;
if (!obj)
continue;
#if CBC_USEFUL_PRINTING>1
if (obj->numberTimesDown() < numberBeforeTrust_ ||
obj->numberTimesUp() < numberBeforeTrust_)
numberNot++;
#endif
int iColumn = obj->columnNumber();
iColumn = back[iColumn];
assert (iColumn >= 0);
if (priority)
priority[iColumn] = obj->priority();
downCosts[iColumn] = obj->downDynamicPseudoCost();
upCosts[iColumn] = obj->upDynamicPseudoCost();
if (numberDown) {
numberDown[iColumn] = obj->numberTimesDown();
numberUp[iColumn] = obj->numberTimesUp();
}
if (numberDownInfeasible) {
numberDownInfeasible[iColumn] = obj->numberTimesDownInfeasible();
numberUpInfeasible[iColumn] = obj->numberTimesUpInfeasible();
}
}
#if CBC_USEFUL_PRINTING>5
if (priority)
printf("Before fathom %d not trusted out of %d\n",
numberNot, numberIntegers_);
#endif
delete [] back;
}
// Redo walkback arrays
void
CbcModel::redoWalkBack()
{
int nNode = maximumDepth_;
maximumDepth_ *= 2;
CbcNodeInfo ** temp = new CbcNodeInfo * [maximumDepth_];
CbcNodeInfo ** temp2 = new CbcNodeInfo * [maximumDepth_];
int * temp3 = new int [maximumDepth_];
for (int i = 0; i < nNode; i++) {
temp[i] = walkback_[i];
temp2[i] = lastNodeInfo_[i];
temp3[i] = lastNumberCuts_[i];
}
delete [] walkback_;
walkback_ = temp;
delete [] lastNodeInfo_ ;
lastNodeInfo_ = temp2;
delete [] lastNumberCuts_ ;
lastNumberCuts_ = temp3;
}
/* Return true if we want to do cuts
If allowForTopOfTree zero then just does on multiples of depth
if 1 then allows for doing at top of tree
if 2 then says if cuts allowed anywhere apart from root
if 3 then gives smallest valid depth >shallow
*/
bool
CbcModel::doCutsNow(int allowForTopOfTree) const
{
int whenCutsUse = whenCuts_;
int alwaysReturnAt10 = whenCutsUse % 100000;
if (whenCutsUse > 0 && alwaysReturnAt10) {
whenCutsUse -= alwaysReturnAt10;
if (currentDepth_ > 10)
return false;
}
//if (currentDepth_>10)
//return false;
#define TRY_IDEA1 2
int size = continuousSolver_->getNumRows() + continuousSolver_->getNumCols();
if (true && (whenCutsUse < 0 || (size <= 500 - 500*TRY_IDEA1 && allowForTopOfTree != 3))) {
int whenCuts = (size <= 500) ? -1 : 1;
//whenCuts = (size<=500) ? 1 :1;
if (parentModel_)
whenCuts = 1;
//int nodeDepth = currentDepth_-1;
bool doCuts2 = !(currentDepth_ > 11 && (currentDepth_ & 1) == whenCuts);
if (fastNodeDepth_ > 0 && currentDepth_ > 10)
doCuts2 = false;
//printf("when %d node %d depth %d size %d doing cuts %s\n",whenCutsUse,
// numberNodes_,currentDepth_,size,doCuts2 ? "yes" : "no");
return doCuts2;
}
//if (!parentModel_&¤tDepth_==7)
//printf("q\n");
int top = whenCutsUse / 1000000;
int shallow = top ? (top - 1) : 9;
int when = whenCutsUse - 1000000 * top;
#if TRY_IDEA1
if (when<15 && when>1 && size <= 500)
when /= 2;
#endif
if ((when > 15 || (top && top < 5)) && currentDepth_ > when)
when = 100000; // off
bool doCuts = when ? ((currentDepth_ % when) == 0) || (when == 1) : false;
if (allowForTopOfTree == 1 && currentDepth_ <= shallow) {
doCuts = true;
} else if (allowForTopOfTree == 2 && shallow >= 1) {
doCuts = true;
#if TRY_IDEA1<2
} else if (allowForTopOfTree == 3 && doCuts) {
// only if first
if (currentDepth_ <= shallow || currentDepth_ - when > shallow)
doCuts = false;
#else
} else if (allowForTopOfTree == 3) {
// only exactly at 10
doCuts = (currentDepth_ == 10);
#endif
}
//if (!doCuts&¤tDepth_&&!parentModel_)
//printf("zzz\n");
return doCuts;
}
// See if can stop on gap
bool
CbcModel::canStopOnGap() const
{
bool returnCode=false;
if (bestObjective_<1.0e50) {
double testGap = CoinMax(dblParam_[CbcAllowableGap],
CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_))
* dblParam_[CbcAllowableFractionGap]);
returnCode = (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0);
}
#if 0
if (returnCode) {
if (fabs(bestObjective_+1469650.0)<1.0) {
fprintf(stderr,"BAD - cr to continue\n");
fflush(stdout);
char xx;
xx=getc(stdin);
}
}
#endif
return returnCode;
}
// Adjust heuristics based on model
void
CbcModel::adjustHeuristics()
{
int numberRows = solver_->getNumRows();
int numberColumns = solver_->getNumCols();
int nTree = CoinMax(10000, 2 * numberRows + numberColumns);
int nRoot = CoinMax(40000, 8 * numberRows + 4 * numberColumns);
for (int i = 0; i < numberHeuristics_; i++) {
CbcHeuristicDive * heuristic = dynamic_cast<CbcHeuristicDive *> (heuristic_[i]);
if (heuristic && heuristic->maxSimplexIterations()!=COIN_INT_MAX) {
heuristic->setMaxSimplexIterations(nTree);
heuristic->setMaxSimplexIterationsAtRoot(nRoot);
}
}
}
// Number of saved solutions (including best)
int
CbcModel::numberSavedSolutions() const
{
if (!bestSolution_)
return 0;
else
return numberSavedSolutions_ + 1;
}
// Set maximum number of extra saved solutions
void
CbcModel::setMaximumSavedSolutions(int value)
{
if (value < maximumSavedSolutions_) {
for (int i = value; i < maximumSavedSolutions_; i++)
delete [] savedSolutions_[i];
maximumSavedSolutions_ = value;
numberSavedSolutions_ = CoinMin(numberSavedSolutions_,
maximumSavedSolutions_);
if (!maximumSavedSolutions_)
delete [] savedSolutions_;
} else if (value > maximumSavedSolutions_) {
double ** temp = new double * [value];
int i;
for ( i = 0; i < maximumSavedSolutions_; i++)
temp[i] = savedSolutions_[i];
for ( ; i < value; i++)
temp[i] = NULL;
delete [] savedSolutions_;
maximumSavedSolutions_ = value;
savedSolutions_ = temp;
}
}
// Return a saved solution objective (0==best) - COIN_DBL_MAX if off end
double
CbcModel::savedSolutionObjective(int which) const
{
if (which == 0) {
return bestObjective_;
} else if (which <= numberSavedSolutions_) {
double * sol = savedSolutions_[which-1];
assert (static_cast<int>(sol[0]) == solver_->getNumCols());
return sol[1];
} else {
return COIN_DBL_MAX;
}
}
// Return a saved solution (0==best) - NULL if off end
const double *
CbcModel::savedSolution(int which) const
{
if (which == 0) {
return bestSolution_;
} else if (which <= numberSavedSolutions_) {
double * sol = savedSolutions_[which-1];
assert (static_cast<int>(sol[0]) == solver_->getNumCols());
return sol + 2;
} else {
return NULL;
}
}
// Save a solution
void
CbcModel::saveExtraSolution(const double * solution, double objectiveValue)
{
double * save = NULL;
if (maximumSavedSolutions_) {
if (!savedSolutions_) {
savedSolutions_ = new double * [maximumSavedSolutions_];
for (int i = 0; i < maximumSavedSolutions_; i++)
savedSolutions_[i] = NULL;
}
int n = solver_->getNumCols();
int k;
for (k = numberSavedSolutions_ - 1; k >= 0; k--) {
double * sol = savedSolutions_[k];
assert (static_cast<int>(sol[0]) == n);
if (objectiveValue > sol[1])
break;
}
k++; // where to put
if (k < maximumSavedSolutions_) {
if (numberSavedSolutions_ == maximumSavedSolutions_) {
save = savedSolutions_[numberSavedSolutions_-1];
} else {
save = new double [n+2];
numberSavedSolutions_++;
}
// move up
for (int j = maximumSavedSolutions_ - 1; j > k; j--)
savedSolutions_[j] = savedSolutions_[j-1];
savedSolutions_[k] = save;
save[0] = n;
save[1] = objectiveValue;
memcpy(save + 2, solution, n*sizeof(double));
}
}
}
// Save a solution to best and move current to saved
void
CbcModel::saveBestSolution(const double * solution, double objectiveValue)
{
int n = solver_->getNumCols();
if (bestSolution_)
saveExtraSolution(bestSolution_, bestObjective_);
else
bestSolution_ = new double [n];
bestObjective_ = objectiveValue;
memcpy(bestSolution_, solution, n*sizeof(double));
}
// Delete best and saved solutions
void
CbcModel::deleteSolutions()
{
delete [] bestSolution_;
bestSolution_ = NULL;
for (int i = 0; i < maximumSavedSolutions_; i++) {
delete [] savedSolutions_[i];
savedSolutions_[i] = NULL;
}
numberSavedSolutions_ = 0;
}
// Delete a saved solution and move others up
void
CbcModel::deleteSavedSolution(int which)
{
if (which >0 && which <= numberSavedSolutions_) {
delete [] savedSolutions_[which-1];
// move up
numberSavedSolutions_--;
for (int j = which-1; j <numberSavedSolutions_; j++) {
savedSolutions_[j] = savedSolutions_[j+1];
}
savedSolutions_[numberSavedSolutions_]=NULL;
}
}
#ifdef COIN_HAS_CLP
void
CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *& savePivotMethod)
{
// Possible change of pivot method
if (!savePivotMethod && !parentModel_) {
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver && numberNodes_ >= numberNodes && numberNodes_ < 2*numberNodes && clpSolver->getNumRows() < 10000) {
if (numberIterations_ < (numberSolves_ + numberNodes_)*10) {
//if (numberIterations_<numberNodes_*20) {
ClpSimplex * simplex = clpSolver->getModelPtr();
ClpDualRowPivot * pivotMethod = simplex->dualRowPivot();
ClpDualRowDantzig * pivot =
dynamic_cast< ClpDualRowDantzig*>(pivotMethod);
if (!pivot) {
savePivotMethod = pivotMethod->clone(true);
ClpDualRowDantzig dantzig;
simplex->setDualRowPivotAlgorithm(dantzig);
#ifdef COIN_DEVELOP
printf("%d node, %d iterations ->Dantzig\n", numberNodes_,
numberIterations_);
#endif
#ifdef CBC_THREAD
if (master_)
master_->setDantzigState();
#endif
}
}
}
}
}
#else
CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *& savePivotMethod)
{
printf("Need Clp to go to Dantzig\n");
abort();
}
#endif
// Below this is deprecated or at least fairly deprecated
/*
Do Integer Presolve. Returns new model.
I have to work out cleanest way of getting solution to
original problem at end. So this is very preliminary.
*/
CbcModel *
CbcModel::integerPresolve(bool weak)
{
status_ = 0;
// solve LP
//solver_->writeMps("bad");
bool feasible = (resolve(NULL, 3) != 0);
CbcModel * newModel = NULL;
if (feasible) {
// get a new model
newModel = new CbcModel(*this);
newModel->messageHandler()->setLogLevel(messageHandler()->logLevel());
feasible = newModel->integerPresolveThisModel(solver_, weak);
}
if (!feasible) {
handler_->message(CBC_INFEAS, messages_)
<< CoinMessageEol;
status_ = 0;
secondaryStatus_ = 1;
delete newModel;
return NULL;
} else {
newModel->synchronizeModel(); // make sure everything that needs solver has it
return newModel;
}
}
/*
Do Integer Presolve - destroying current model
*/
bool
CbcModel::integerPresolveThisModel(OsiSolverInterface * originalSolver,
bool weak)
{
printf("DEPRECATED\n");
status_ = 0;
// solve LP
bool feasible = (resolve(NULL, 3) != 0);
bestObjective_ = 1.0e50;
numberSolutions_ = 0;
numberHeuristicSolutions_ = 0;
double cutoff = getCutoff() ;
double direction = solver_->getObjSense();
if (cutoff < 1.0e20 && direction < 0.0)
messageHandler()->message(CBC_CUTOFF_WARNING1,
messages())
<< cutoff << -cutoff << CoinMessageEol ;
if (cutoff > bestObjective_)
cutoff = bestObjective_ ;
setCutoff(cutoff) ;
int iColumn;
int numberColumns = getNumCols();
int originalNumberColumns = numberColumns;
currentPassNumber_ = 0;
synchronizeModel(); // make sure everything that needs solver has it
if (!solverCharacteristics_) {
OsiBabSolver * solverCharacteristics = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
if (solverCharacteristics) {
solverCharacteristics_ = solverCharacteristics;
} else {
// replace in solver
OsiBabSolver defaultC;
solver_->setAuxiliaryInfo(&defaultC);
solverCharacteristics_ = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
}
}
solverCharacteristics_->setSolver(solver_);
// just point to solver_
delete continuousSolver_;
continuousSolver_ = solver_;
// get a copy of original so we can fix bounds
OsiSolverInterface * cleanModel = originalSolver->clone();
#ifdef CBC_DEBUG
std::string problemName;
cleanModel->getStrParam(OsiProbName, problemName);
printf("Problem name - %s\n", problemName.c_str());
cleanModel->activateRowCutDebugger(problemName.c_str());
const OsiRowCutDebugger * debugger = cleanModel->getRowCutDebugger();
#endif
// array which points from original columns to presolved
int * original = new int[numberColumns];
// arrays giving bounds - only ones found by probing
// rest will be found by presolve
double * originalLower = new double[numberColumns];
double * originalUpper = new double[numberColumns];
{
const double * lower = getColLower();
const double * upper = getColUpper();
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
original[iColumn] = iColumn;
originalLower[iColumn] = lower[iColumn];
originalUpper[iColumn] = upper[iColumn];
}
}
findIntegers(true);
// save original integers
int * originalIntegers = new int[numberIntegers_];
int originalNumberIntegers = numberIntegers_;
memcpy(originalIntegers, integerVariable_, numberIntegers_*sizeof(int));
int todo = 20;
if (weak)
todo = 1;
while (currentPassNumber_ < todo) {
currentPassNumber_++;
numberSolutions_ = 0;
// this will be set false to break out of loop with presolved problem
bool doIntegerPresolve = (currentPassNumber_ != 20);
// Current number of free integer variables
// Get increment in solutions
{
const double * objective = cleanModel->getObjCoefficients();
const double * lower = cleanModel->getColLower();
const double * upper = cleanModel->getColUpper();
double maximumCost = 0.0;
bool possibleMultiple = true;
int numberChanged = 0;
for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) {
if (originalUpper[iColumn] > originalLower[iColumn]) {
if ( cleanModel->isInteger(iColumn)) {
maximumCost = CoinMax(maximumCost, fabs(objective[iColumn]));
} else if (objective[iColumn]) {
possibleMultiple = false;
}
}
if (originalUpper[iColumn] < upper[iColumn]) {
#ifdef CBC_DEBUG
printf("Changing upper bound on %d from %g to %g\n",
iColumn, upper[iColumn], originalUpper[iColumn]);
#endif
cleanModel->setColUpper(iColumn, originalUpper[iColumn]);
numberChanged++;
}
if (originalLower[iColumn] > lower[iColumn]) {
#ifdef CBC_DEBUG
printf("Changing lower bound on %d from %g to %g\n",
iColumn, lower[iColumn], originalLower[iColumn]);
#endif
cleanModel->setColLower(iColumn, originalLower[iColumn]);
numberChanged++;
}
}
// if first pass - always try
if (currentPassNumber_ == 1)
numberChanged += 1;
if (possibleMultiple && maximumCost) {
int increment = 0;
double multiplier = 2520.0;
while (10.0*multiplier*maximumCost < 1.0e8)
multiplier *= 10.0;
for (int j = 0; j < originalNumberIntegers; j++) {
iColumn = originalIntegers[j];
if (originalUpper[iColumn] > originalLower[iColumn]) {
if (objective[iColumn]) {
double value = fabs(objective[iColumn]) * multiplier;
int nearest = static_cast<int> (floor(value + 0.5));
if (fabs(value - floor(value + 0.5)) > 1.0e-8 || value > 2.1e9) {
increment = 0;
break; // no good
} else if (!increment) {
// first
increment = nearest;
} else {
increment = gcd(increment, nearest);
}
}
}
}
if (increment) {
double value = increment;
value /= multiplier;
if (value*0.999 > dblParam_[CbcCutoffIncrement]) {
messageHandler()->message(CBC_INTEGERINCREMENT, messages())
<< value
<< CoinMessageEol;
dblParam_[CbcCutoffIncrement] = value * 0.999;
}
}
}
if (!numberChanged) {
doIntegerPresolve = false; // not doing any better
}
}
#ifdef CBC_DEBUG
if (debugger)
assert(debugger->onOptimalPath(*cleanModel));
#endif
#ifdef COIN_HAS_CLP
// do presolve - for now just clp but easy to get osi interface
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (cleanModel);
if (clpSolver) {
ClpSimplex * clp = clpSolver->getModelPtr();
clp->messageHandler()->setLogLevel(cleanModel->messageHandler()->logLevel());
ClpPresolve pinfo;
//printf("integerPresolve - temp switch off doubletons\n");
//pinfo.setPresolveActions(4);
ClpSimplex * model2 = pinfo.presolvedModel(*clp, 1.0e-8);
if (!model2) {
// presolve found to be infeasible
feasible = false;
} else {
// update original array
const int * originalColumns = pinfo.originalColumns();
// just slot in new solver
OsiClpSolverInterface * temp = new OsiClpSolverInterface(model2, true);
numberColumns = temp->getNumCols();
for (iColumn = 0; iColumn < originalNumberColumns; iColumn++)
original[iColumn] = -1;
for (iColumn = 0; iColumn < numberColumns; iColumn++)
original[originalColumns[iColumn]] = iColumn;
// copy parameters
temp->copyParameters(*solver_);
// and specialized ones
temp->setSpecialOptions(clpSolver->specialOptions());
delete solver_;
solver_ = temp;
setCutoff(cutoff);
deleteObjects();
if (!numberObjects_) {
// Nothing left
doIntegerPresolve = false;
weak = true;
break;
}
synchronizeModel(); // make sure everything that needs solver has it
// just point to solver_
continuousSolver_ = solver_;
feasible = (resolve(NULL, 3) != 0);
if (!feasible || !doIntegerPresolve || weak) break;
// see if we can get solution by heuristics
int found = -1;
int iHeuristic;
double * newSolution = new double [numberColumns];
double heuristicValue = getCutoff();
int whereFrom = 0;
for (iHeuristic = 0; iHeuristic < numberHeuristics_; iHeuristic++) {
// skip if can't run here
if (!heuristic_[iHeuristic]->shouldHeurRun(whereFrom))
continue;
double saveValue = heuristicValue;
int ifSol = heuristic_[iHeuristic]->solution(heuristicValue,
newSolution);
if (ifSol > 0) {
// better solution found
heuristic_[iHeuristic]->incrementNumberSolutionsFound();
found = iHeuristic;
incrementUsed(newSolution);
whereFrom |= 8; // say solution found
} else if (ifSol < 0) {
heuristicValue = saveValue;
}
}
if (found >= 0) {
// We probably already have a current solution, but just in case ...
int numberColumns = getNumCols() ;
if (!currentSolution_)
currentSolution_ = new double[numberColumns] ;
testSolution_ = currentSolution_;
// better solution save
lastHeuristic_ = heuristic_[found];
#ifdef HEURISTIC_INFORM
printf("HEUR %s where %d oddE\n",
lastHeuristic_->heuristicName(), whereFrom);
#endif
setBestSolution(CBC_ROUNDING, heuristicValue,
newSolution);
// update cutoff
cutoff = getCutoff();
}
delete [] newSolution;
// Space for type of cuts
maximumWhich_ = INITIAL_MAXIMUM_WHICH;
delete [] whichGenerator_ ;
whichGenerator_ = new int[maximumWhich_];
// save number of rows
numberRowsAtContinuous_ = getNumRows();
maximumNumberCuts_ = 0;
currentNumberCuts_ = 0;
delete [] addedCuts_;
addedCuts_ = NULL;
// maximum depth for tree walkback
maximumDepth_ = 10;
delete [] walkback_;
walkback_ = new CbcNodeInfo * [maximumDepth_];
lastDepth_ = 0;
delete [] lastNodeInfo_ ;
lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ;
delete [] lastNumberCuts_ ;
lastNumberCuts_ = new int [maximumDepth_] ;
maximumCuts_ = 100;
delete [] lastCut_;
lastCut_ = new const OsiRowCut * [maximumCuts_];
OsiCuts cuts;
numberOldActiveCuts_ = 0;
numberNewCuts_ = 0;
feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, NULL);
currentNumberCuts_ = numberNewCuts_;
delete [] whichGenerator_;
whichGenerator_ = NULL;
delete [] walkback_;
walkback_ = NULL;
delete [] addedCuts_;
addedCuts_ = NULL;
if (feasible) {
// fix anything in original which integer presolve fixed
// for now just integers
const double * lower = solver_->getColLower();
const double * upper = solver_->getColUpper();
int i;
for (i = 0; i < originalNumberIntegers; i++) {
iColumn = originalIntegers[i];
int jColumn = original[iColumn];
if (jColumn >= 0) {
if (upper[jColumn] < originalUpper[iColumn])
originalUpper[iColumn] = upper[jColumn];
if (lower[jColumn] > originalLower[iColumn])
originalLower[iColumn] = lower[jColumn];
}
}
}
}
}
#endif
if (!feasible || !doIntegerPresolve) {
break;
}
}
//solver_->writeMps("xx");
delete cleanModel;
delete [] originalIntegers;
numberColumns = getNumCols();
delete [] originalColumns_;
originalColumns_ = new int[numberColumns];
numberColumns = 0;
for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) {
int jColumn = original[iColumn];
if (jColumn >= 0)
originalColumns_[numberColumns++] = iColumn;
}
delete [] original;
delete [] originalLower;
delete [] originalUpper;
deleteObjects();
synchronizeModel(); // make sure everything that needs solver has it
continuousSolver_ = NULL;
currentNumberCuts_ = 0;
return feasible;
}
// Put back information into original model - after integerpresolve
void
CbcModel::originalModel(CbcModel * presolvedModel, bool weak)
{
solver_->copyParameters(*(presolvedModel->solver_));
bestObjective_ = presolvedModel->bestObjective_;
delete [] bestSolution_;
findIntegers(true);
if (presolvedModel->bestSolution_) {
int numberColumns = getNumCols();
int numberOtherColumns = presolvedModel->getNumCols();
//bestSolution_ = new double[numberColumns];
// set up map
int * back = new int[numberColumns];
int i;
for (i = 0; i < numberColumns; i++)
back[i] = -1;
for (i = 0; i < numberOtherColumns; i++)
back[presolvedModel->originalColumns_[i]] = i;
int iColumn;
// set ones in presolved model to values
double * otherSolution = presolvedModel->bestSolution_;
//const double * lower = getColLower();
for (i = 0; i < numberIntegers_; i++) {
iColumn = integerVariable_[i];
int jColumn = back[iColumn];
//bestSolution_[iColumn]=lower[iColumn];
if (jColumn >= 0) {
double value = floor(otherSolution[jColumn] + 0.5);
solver_->setColLower(iColumn, value);
solver_->setColUpper(iColumn, value);
//bestSolution_[iColumn]=value;
}
}
delete [] back;
#ifdef JJF_ZERO
// ** looks as if presolve needs more intelligence
// do presolve - for now just clp but easy to get osi interface
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
assert (clpSolver);
ClpSimplex * clp = clpSolver->getModelPtr();
Presolve pinfo;
ClpSimplex * model2 = pinfo.presolvedModel(*clp, 1.0e-8);
model2->primal(1);
pinfo.postsolve(true);
const double * solution = solver_->getColSolution();
for (i = 0; i < numberIntegers_; i++) {
iColumn = integerVariable_[i];
double value = floor(solution[iColumn] + 0.5);
solver_->setColLower(iColumn, value);
solver_->setColUpper(iColumn, value);
}
#else
if (!weak) {
// for now give up
int save = numberCutGenerators_;
numberCutGenerators_ = 0;
bestObjective_ = 1.0e100;
branchAndBound();
numberCutGenerators_ = save;
}
#endif
if (bestSolution_) {
// solve problem
resolve(NULL, 3);
// should be feasible
if (!currentSolution_)
currentSolution_ = new double[numberColumns] ;
testSolution_ = currentSolution_;
#ifndef NDEBUG
int numberIntegerInfeasibilities;
int numberObjectInfeasibilities;
assert(feasibleSolution(numberIntegerInfeasibilities,
numberObjectInfeasibilities));
#endif
}
} else {
bestSolution_ = NULL;
}
numberSolutions_ = presolvedModel->numberSolutions_;
numberHeuristicSolutions_ = presolvedModel->numberHeuristicSolutions_;
numberNodes_ = presolvedModel->numberNodes_;
numberIterations_ = presolvedModel->numberIterations_;
status_ = presolvedModel->status_;
secondaryStatus_ = presolvedModel->secondaryStatus_;
synchronizeModel();
}
void
CbcModel::setOptionalInteger(int index)
{
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver_);
if (clpSolver)
clpSolver->setOptionalInteger(index);
else
#endif
solver_->setInteger(index);
}
// Return true if maximum time reached
bool
CbcModel::maximumSecondsReached() const
{
double totalTime = getCurrentSeconds() ;
double maxSeconds = getMaximumSeconds();
bool hitMaxTime = (totalTime >= maxSeconds);
if (parentModel_ && !hitMaxTime) {
// In a sub tree
assert (parentModel_);
maxSeconds = parentModel_->getMaximumSeconds();
hitMaxTime = (totalTime >= maxSeconds);
}
if (hitMaxTime) {
// Set eventHappened_ so will by-pass as much stuff as possible
eventHappened_ = true;
}
return hitMaxTime;
}
// Check original model before it gets messed up
void
CbcModel::checkModel()
{
int iColumn ;
int numberColumns = getNumCols() ;
const double *lower = getColLower() ;
const double *upper = getColUpper() ;
int setFlag = 65536;
for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
double value;
value = fabs(lower[iColumn]);
if (floor(value + 0.5) != value) {
setFlag = 0;
break;
}
value = fabs(upper[iColumn]);
if (floor(value + 0.5) != value) {
setFlag = 0;
break;
}
}
}
specialOptions_ |= setFlag;
}
static void flipSolver(OsiSolverInterface * solver, double newCutoff)
{
if (solver) {
double objValue = solver->getObjValue();
double objectiveOffset;
solver->setObjSense(-solver->getObjSense());
solver->getDblParam(OsiObjOffset,objectiveOffset);
solver->setDblParam(OsiObjOffset,-objectiveOffset);
int numberColumns = solver->getNumCols();
double * array = CoinCopyOfArray(solver->getObjCoefficients(),numberColumns);
for (int i=0;i<numberColumns;i++)
array[i] = - array[i];
solver->setObjective(array);
delete [] array;
solver->setDblParam(OsiDualObjectiveLimit,newCutoff);
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (solver);
if (clpSolver) {
double * dj = clpSolver->getModelPtr()->dualColumnSolution();
for (int i=0;i<numberColumns;i++)
dj[i] = - dj[i];
int numberRows=clpSolver->getNumRows();
double * pi = clpSolver->getModelPtr()->dualRowSolution();
for (int i=0;i<numberRows;i++)
pi[i] = - pi[i];
clpSolver->getModelPtr()->setObjectiveValue(-objValue);
} else {
#endif
// update values
solver->resolve();
#ifdef COIN_HAS_CLP
}
#endif
}
}
/*
Flip direction of optimization on all models
*/
void
CbcModel::flipModel()
{
if (parentModel_)
return;
// I think cutoff is always minimization
double cutoff=getCutoff();
flipSolver(referenceSolver_,cutoff);
flipSolver(continuousSolver_,cutoff);
flipSolver(solver_,cutoff);
}
#ifdef CBC_KEEP_DEPRECATED
/* preProcess problem - replacing solver
If makeEquality true then <= cliques converted to ==.
Presolve will be done numberPasses times.
Returns NULL if infeasible
If makeEquality is 1 add slacks to get cliques,
if 2 add slacks to get sos (but only if looks plausible) and keep sos info
*/
CglPreProcess *
CbcModel::preProcess( int makeEquality, int numberPasses, int tuning)
{
CglPreProcess * process = new CglPreProcess();
// Default set of cut generators
CglProbing generator1;
generator1.setUsingObjective(true);
generator1.setMaxPass(3);
generator1.setMaxProbeRoot(solver_->getNumCols());
generator1.setMaxElements(100);
generator1.setMaxLookRoot(50);
generator1.setRowCuts(3);
// Add in generators
process->addCutGenerator(&generator1);
process->messageHandler()->setLogLevel(this->logLevel());
/* model may not have created objects
If none then create
*/
if (!numberIntegers_ || !numberObjects_) {
this->findIntegers(true, 1);
}
// Do SOS
int i;
int numberSOS2 = 0;
for (i = 0; i < numberObjects_; i++) {
CbcSOS * objSOS =
dynamic_cast <CbcSOS *>(object_[i]) ;
if (objSOS) {
int type = objSOS->sosType();
if (type == 2)
numberSOS2++;
}
}
if (numberSOS2) {
// SOS
int numberColumns = solver_->getNumCols();
char * prohibited = new char[numberColumns];
memset(prohibited, 0, numberColumns);
for (i = 0; i < numberObjects_; i++) {
CbcSOS * objSOS =
dynamic_cast <CbcSOS *>(object_[i]) ;
if (objSOS) {
int type = objSOS->sosType();
if (type == 2) {
int n = objSOS->numberMembers();
const int * which = objSOS->members();
for (int j = 0; j < n; j++) {
int iColumn = which[j];
prohibited[iColumn] = 1;
}
}
}
}
process->passInProhibited(prohibited, numberColumns);
delete [] prohibited;
}
// Tell solver we are not in Branch and Cut
solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ;
OsiSolverInterface * newSolver = process->preProcessNonDefault(*solver_, makeEquality,
numberPasses, tuning);
// Tell solver we are not in Branch and Cut
solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;
if (newSolver) {
int numberOriginalObjects = numberObjects_;
OsiSolverInterface * originalSolver = solver_;
solver_ = newSolver->clone(); // clone as process owns solver
// redo sequence
numberIntegers_ = 0;
int numberColumns = solver_->getNumCols();
int nOrig = originalSolver->getNumCols();
const int * originalColumns = process->originalColumns();
// allow for cliques etc
nOrig = CoinMax(nOrig, originalColumns[numberColumns-1] + 1);
OsiObject ** originalObject = object_;
// object number or -1
int * temp = new int[nOrig];
int iColumn;
for (iColumn = 0; iColumn < nOrig; iColumn++)
temp[iColumn] = -1;
int iObject;
numberObjects_ = 0;
int nNonInt = 0;
for (iObject = 0; iObject < numberOriginalObjects; iObject++) {
iColumn = originalObject[iObject]->columnNumber();
if (iColumn < 0) {
nNonInt++;
} else {
temp[iColumn] = iObject;
}
}
int numberNewIntegers = 0;
int numberOldIntegers = 0;
int numberOldOther = 0;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
int jColumn = originalColumns[iColumn];
if (temp[jColumn] >= 0) {
int iObject = temp[jColumn];
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
if (obj)
numberOldIntegers++;
else
numberOldOther++;
} else if (isInteger(iColumn)) {
numberNewIntegers++;
}
}
/*
Allocate an array to hold the indices of the integer variables.
Make a large enough array for all objects
*/
numberObjects_ = numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt;
object_ = new OsiObject * [numberObjects_];
delete [] integerVariable_;
integerVariable_ = new int [numberNewIntegers+numberOldIntegers];
/*
Walk the variables again, filling in the indices and creating objects for
the integer variables. Initially, the objects hold the index and upper &
lower bounds.
*/
numberIntegers_ = 0;
int n = originalColumns[numberColumns-1] + 1;
int * backward = new int[n];
int i;
for ( i = 0; i < n; i++)
backward[i] = -1;
for (i = 0; i < numberColumns; i++)
backward[originalColumns[i]] = i;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
int jColumn = originalColumns[iColumn];
if (temp[jColumn] >= 0) {
int iObject = temp[jColumn];
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
if (obj) {
object_[numberIntegers_] = originalObject[iObject]->clone();
// redo ids etc
//object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns);
object_[numberIntegers_]->resetSequenceEtc(numberColumns, backward);
integerVariable_[numberIntegers_++] = iColumn;
}
} else if (isInteger(iColumn)) {
object_[numberIntegers_] =
new CbcSimpleInteger(this, iColumn);
integerVariable_[numberIntegers_++] = iColumn;
}
}
delete [] backward;
numberObjects_ = numberIntegers_;
// Now append other column stuff
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
int jColumn = originalColumns[iColumn];
if (temp[jColumn] >= 0) {
int iObject = temp[jColumn];
CbcSimpleInteger * obj =
dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
if (!obj) {
object_[numberObjects_] = originalObject[iObject]->clone();
// redo ids etc
CbcObject * obj =
dynamic_cast <CbcObject *>(object_[numberObjects_]) ;
assert (obj);
obj->redoSequenceEtc(this, numberColumns, originalColumns);
numberObjects_++;
}
}
}
// now append non column stuff
for (iObject = 0; iObject < numberOriginalObjects; iObject++) {
iColumn = originalObject[iObject]->columnNumber();
if (iColumn < 0) {
object_[numberObjects_] = originalObject[iObject]->clone();
// redo ids etc
CbcObject * obj =
static_cast <CbcObject *>(object_[numberObjects_]) ;
assert (obj);
obj->redoSequenceEtc(this, numberColumns, originalColumns);
numberObjects_++;
}
delete originalObject[iObject];
}
delete [] originalObject;
delete [] temp;
if (!numberObjects_)
handler_->message(CBC_NOINT, messages_) << CoinMessageEol ;
return process;
} else {
// infeasible
delete process;
return NULL;
}
}
/* Does postprocessing - original solver back.
User has to delete process */
void
CbcModel::postProcess(CglPreProcess * process)
{
process->postProcess(*solver_);
delete solver_;
solver_ = process->originalModel();
}
/* Process root node and return a strengthened model
The method assumes that initialSolve() has been called to solve the
LP relaxation. It processes the root node and then returns a pointer
to the strengthened model (or NULL if infeasible)
*/
OsiSolverInterface *
CbcModel::strengthenedModel()
{
/*
Switch off heuristics
*/
int saveNumberHeuristics = numberHeuristics_;
numberHeuristics_ = 0;
/*
Scan the variables, noting the integer variables. Create an
CbcSimpleInteger object for each integer variable.
*/
findIntegers(false) ;
/*
Ensure that objects on the lists of OsiObjects, heuristics, and cut
generators attached to this model all refer to this model.
*/
synchronizeModel() ;
// Set so we can tell we are in initial phase in resolve
continuousObjective_ = -COIN_DBL_MAX ;
/*
Solve the relaxation.
Apparently there are circumstances where this will be non-trivial --- i.e.,
we've done something since initialSolve that's trashed the solution to the
continuous relaxation.
*/
bool feasible = resolve(NULL, 0) != 0 ;
/*
If the linear relaxation of the root is infeasible, bail out now. Otherwise,
continue with processing the root node.
*/
if (!feasible) {
handler_->message(CBC_INFEAS, messages_) << CoinMessageEol ;
return NULL;
}
// Save objective (just so user can access it)
originalContinuousObjective_ = solver_->getObjValue();
/*
Begin setup to process a feasible root node.
*/
bestObjective_ = CoinMin(bestObjective_, 1.0e50) ;
numberSolutions_ = 0 ;
numberHeuristicSolutions_ = 0 ;
// Everything is minimization
double cutoff = getCutoff() ;
double direction = solver_->getObjSense() ;
if (cutoff < 1.0e20 && direction < 0.0)
messageHandler()->message(CBC_CUTOFF_WARNING1,
messages())
<< cutoff << -cutoff << CoinMessageEol ;
if (cutoff > bestObjective_)
cutoff = bestObjective_ ;
setCutoff(cutoff) ;
/*
We probably already have a current solution, but just in case ...
*/
int numberColumns = getNumCols() ;
if (!currentSolution_)
currentSolution_ = new double[numberColumns] ;
testSolution_ = currentSolution_;
/*
Create a copy of the solver, thus capturing the original (root node)
constraint system (aka the continuous system).
*/
continuousSolver_ = solver_->clone() ;
numberRowsAtContinuous_ = getNumRows() ;
/*
Check the objective to see if we can deduce a nontrivial increment. If
it's better than the current value for CbcCutoffIncrement, it'll be
installed.
*/
analyzeObjective() ;
/*
Set up for cut generation. addedCuts_ holds the cuts which are relevant for
the active subproblem. whichGenerator will be used to record the generator
that produced a given cut.
*/
maximumWhich_ = INITIAL_MAXIMUM_WHICH ;
delete [] whichGenerator_ ;
whichGenerator_ = new int[maximumWhich_] ;
maximumNumberCuts_ = 0 ;
currentNumberCuts_ = 0 ;
delete [] addedCuts_ ;
addedCuts_ = NULL ;
/*
Generate cuts at the root node and reoptimise. solveWithCuts does the heavy
lifting. It will iterate a generate/reoptimise loop (including reduced cost
fixing) until no cuts are generated, the change in objective falls off, or
the limit on the number of rounds of cut generation is exceeded.
At the end of all this, any cuts will be recorded in cuts and also
installed in the solver's constraint system. We'll have reoptimised, and
removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
adjusted accordingly).
Tell cut generators they can be a bit more aggressive at root node
*/
int iCutGenerator;
for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
CglCutGenerator * generator = generator_[iCutGenerator]->generator();
generator->setAggressiveness(generator->getAggressiveness() + 100);
}
OsiCuts cuts ;
numberOldActiveCuts_ = 0 ;
numberNewCuts_ = 0 ;
{
int iObject ;
int numberUnsatisfied = 0 ;
memcpy(currentSolution_, solver_->getColSolution(),
numberColumns*sizeof(double)) ;
// point to useful information
OsiBranchingInformation usefulInfo = usefulInformation();
for (iObject = 0 ; iObject < numberObjects_ ; iObject++) {
double infeasibility =
object_[iObject]->checkInfeasibility(&usefulInfo) ;
if (infeasibility) numberUnsatisfied++ ;
}
if (numberUnsatisfied) {
feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_,
NULL) ;
}
}
/*
We've taken the continuous relaxation as far as we can.
*/
OsiSolverInterface * newSolver = NULL;
if (feasible) {
// make copy of current solver
newSolver = solver_->clone();
}
/*
Clean up dangling objects. continuousSolver_ may already be toast.
*/
delete [] whichGenerator_ ;
whichGenerator_ = NULL;
delete [] walkback_ ;
walkback_ = NULL ;
delete [] lastNodeInfo_ ;
lastNodeInfo_ = NULL;
delete [] lastNumberCuts_ ;
lastNumberCuts_ = NULL;
delete [] lastCut_;
lastCut_ = NULL;
delete [] addedCuts_ ;
addedCuts_ = NULL ;
if (continuousSolver_) {
delete continuousSolver_ ;
continuousSolver_ = NULL ;
}
/*
Destroy global cuts by replacing with an empty OsiCuts object.
*/
globalCuts_ = OsiCuts() ;
delete globalConflictCuts_;
globalConflictCuts_=NULL;
numberHeuristics_ = saveNumberHeuristics;
return newSolver;
}
/* create a submodel from partially fixed problem
The method creates a new clean model with given bounds.
*/
CbcModel *
CbcModel::cleanModel(const double * lower, const double * upper)
{
OsiSolverInterface * solver = continuousSolver_->clone();
int numberIntegers = numberIntegers_;
const int * integerVariable = integerVariable_;
int i;
for (i = 0; i < numberIntegers; i++) {
int iColumn = integerVariable[i];
const OsiObject * object = object_[i];
#ifndef NDEBUG
const CbcSimpleInteger * integerObject =
dynamic_cast<const CbcSimpleInteger *> (object);
assert(integerObject);
#else
const CbcSimpleInteger * integerObject =
static_cast<const CbcSimpleInteger *> (object);
#endif
// get original bounds
double originalLower = integerObject->originalLowerBound();
double originalUpper = integerObject->originalUpperBound();
solver->setColLower(iColumn, CoinMax(lower[iColumn], originalLower));
solver->setColUpper(iColumn, CoinMin(upper[iColumn], originalUpper));
}
CbcModel * model = new CbcModel(*solver);
// off some messages
if (handler_->logLevel() <= 1) {
model->messagesPointer()->setDetailMessage(3, 9);
model->messagesPointer()->setDetailMessage(3, 6);
model->messagesPointer()->setDetailMessage(3, 4);
model->messagesPointer()->setDetailMessage(3, 1);
model->messagesPointer()->setDetailMessage(3, 13);
model->messagesPointer()->setDetailMessage(3, 14);
model->messagesPointer()->setDetailMessage(3, 3007);
}
// Cuts
for ( i = 0; i < numberCutGenerators_; i++) {
int howOften = generator_[i]->howOftenInSub();
if (howOften > -100) {
CbcCutGenerator * generator = virginGenerator_[i];
CglCutGenerator * cglGenerator = generator->generator();
model->addCutGenerator(cglGenerator, howOften,
generator->cutGeneratorName(),
generator->normal(),
generator->atSolution(),
generator->whenInfeasible(),
-100, generator->whatDepthInSub(), -1);
}
}
double cutoff = getCutoff();
model->setCutoff(cutoff);
return model;
}
/* Invoke the branch & cut algorithm on partially fixed problem
The method uses a subModel created by cleanModel. The search
ends when the tree is exhausted or maximum nodes is reached.
If better solution found then it is saved.
Returns 0 if search completed and solution, 1 if not completed and solution,
2 if completed and no solution, 3 if not completed and no solution.
Normally okay to do subModel immediately followed by subBranchandBound
(== other form of subBranchAndBound)
but may need to get at model for advanced features.
Deletes model
*/
int
CbcModel::subBranchAndBound(CbcModel * model,
CbcModel * presolvedModel,
int maximumNodes)
{
int i;
double cutoff = model->getCutoff();
CbcModel * model2;
if (presolvedModel)
model2 = presolvedModel;
else
model2 = model;
// Do complete search
for (i = 0; i < numberHeuristics_; i++) {
model2->addHeuristic(heuristic_[i]);
model2->heuristic(i)->resetModel(model2);
}
// Definition of node choice
model2->setNodeComparison(nodeCompare_->clone());
//model2->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
model2->messageHandler()->setLogLevel(CoinMax(0, handler_->logLevel() - 1));
//model2->solver()->messageHandler()->setLogLevel(2);
model2->setMaximumCutPassesAtRoot(maximumCutPassesAtRoot_);
model2->setPrintFrequency(50);
model2->setIntParam(CbcModel::CbcMaxNumNode, maximumNodes);
model2->branchAndBound();
delete model2->nodeComparison();
if (model2->getMinimizationObjValue() > cutoff) {
// no good
if (model != model2)
delete model2;
delete model;
return 2;
}
if (model != model2) {
// get back solution
model->originalModel(model2, false);
delete model2;
}
int status;
if (model->getMinimizationObjValue() < cutoff && model->bestSolution()) {
double objValue = model->getObjValue();
const double * solution = model->bestSolution();
setBestSolution(CBC_TREE_SOL, objValue, solution);
status = 0;
} else {
status = 2;
}
if (model->status())
status ++ ; // not finished search
delete model;
return status;
}
/* Invoke the branch & cut algorithm on partially fixed problem
The method creates a new model with given bounds, presolves it
then proceeds to explore the branch & cut search tree. The search
ends when the tree is exhausted or maximum nodes is reached.
Returns 0 if search completed and solution, 1 if not completed and solution,
2 if completed and no solution, 3 if not completed and no solution.
*/
int
CbcModel::subBranchAndBound(const double * lower, const double * upper,
int maximumNodes)
{
OsiSolverInterface * solver = continuousSolver_->clone();
int numberIntegers = numberIntegers_;
const int * integerVariable = integerVariable_;
int i;
for (i = 0; i < numberIntegers; i++) {
int iColumn = integerVariable[i];
const OsiObject * object = object_[i];
#ifndef NDEBUG
const CbcSimpleInteger * integerObject =
dynamic_cast<const CbcSimpleInteger *> (object);
assert(integerObject);
#else
const CbcSimpleInteger * integerObject =
static_cast<const CbcSimpleInteger *> (object);
#endif
// get original bounds
double originalLower = integerObject->originalLowerBound();
double originalUpper = integerObject->originalUpperBound();
solver->setColLower(iColumn, CoinMax(lower[iColumn], originalLower));
solver->setColUpper(iColumn, CoinMin(upper[iColumn], originalUpper));
}
CbcModel model(*solver);
// off some messages
if (handler_->logLevel() <= 1) {
model.messagesPointer()->setDetailMessage(3, 9);
model.messagesPointer()->setDetailMessage(3, 6);
model.messagesPointer()->setDetailMessage(3, 4);
model.messagesPointer()->setDetailMessage(3, 1);
model.messagesPointer()->setDetailMessage(3, 3007);
}
double cutoff = getCutoff();
model.setCutoff(cutoff);
// integer presolve
CbcModel * model2 = model.integerPresolve(false);
if (!model2 || !model2->getNumRows()) {
delete model2;
delete solver;
return 2;
}
if (handler_->logLevel() > 1)
printf("Reduced model has %d rows and %d columns\n",
model2->getNumRows(), model2->getNumCols());
// Do complete search
// Cuts
for ( i = 0; i < numberCutGenerators_; i++) {
int howOften = generator_[i]->howOftenInSub();
if (howOften > -100) {
CbcCutGenerator * generator = virginGenerator_[i];
CglCutGenerator * cglGenerator = generator->generator();
model2->addCutGenerator(cglGenerator, howOften,
generator->cutGeneratorName(),
generator->normal(),
generator->atSolution(),
generator->whenInfeasible(),
-100, generator->whatDepthInSub(), -1);
}
}
for (i = 0; i < numberHeuristics_; i++) {
model2->addHeuristic(heuristic_[i]);
model2->heuristic(i)->resetModel(model2);
}
// Definition of node choice
model2->setNodeComparison(nodeCompare_->clone());
//model2->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
model2->messageHandler()->setLogLevel(CoinMax(0, handler_->logLevel() - 1));
//model2->solver()->messageHandler()->setLogLevel(2);
model2->setMaximumCutPassesAtRoot(maximumCutPassesAtRoot_);
model2->setPrintFrequency(50);
model2->setIntParam(CbcModel::CbcMaxNumNode, maximumNodes);
model2->branchAndBound();
delete model2->nodeComparison();
if (model2->getMinimizationObjValue() > cutoff) {
// no good
delete model2;
delete solver;
return 2;
}
// get back solution
model.originalModel(model2, false);
delete model2;
int status;
if (model.getMinimizationObjValue() < cutoff && model.bestSolution()) {
double objValue = model.getObjValue();
const double * solution = model.bestSolution();
setBestSolution(CBC_TREE_SOL, objValue, solution);
status = 0;
} else {
status = 2;
}
if (model.status())
status ++ ; // not finished search
delete solver;
return status;
}
#endif
static void * doRootCbcThread(void * voidInfo)
{
CbcModel * model = reinterpret_cast<CbcModel *> (voidInfo);
#ifdef COIN_HAS_CLP
OsiClpSolverInterface * clpSolver
= dynamic_cast<OsiClpSolverInterface *> (model->solver());
char general[200];
if (clpSolver) {
sprintf(general,"Starting multiple root solver");
model->messageHandler()->message(CBC_GENERAL,
model->messages())
<< general << CoinMessageEol ;
clpSolver->setHintParam(OsiDoReducePrint, true, OsiHintTry);
ClpSimplex * simplex = clpSolver->getModelPtr();
int logLevel=simplex->logLevel();
if (logLevel<=1)
simplex->setLogLevel(0);
simplex->dual();
simplex->setLogLevel(logLevel);
clpSolver->setWarmStart(NULL);
} else {
model->initialSolve();
sprintf(general,"Solver did %d iterations in initialSolve\n",
model->solver()->getIterationCount());
model->messageHandler()->message(CBC_GENERAL,
model->messages())
<< general << CoinMessageEol ;
}
#endif
model->branchAndBound();
sprintf(general,"Ending multiple root solver");
model->messageHandler()->message(CBC_GENERAL,
model->messages())
<< general << CoinMessageEol ;
return NULL;
}
OsiRowCut *
CbcModel::conflictCut(const OsiSolverInterface * solver, bool & localCuts)
{
OsiRowCut * cut=NULL;
localCuts=false;
# ifdef COIN_HAS_CLP
const OsiClpSolverInterface * clpSolver
= dynamic_cast<const OsiClpSolverInterface *> (solver);
if (clpSolver&&topOfTree_) {
int debugMode=0;
const double * originalLower = topOfTree_->lower();
const double * originalUpper = topOfTree_->upper();
int typeCut = 1;
ClpSimplex * simplex = clpSolver->getModelPtr();
assert(simplex->status()==1);
if(simplex->ray()) {
{
int numberRows=simplex->numberRows();
double * saveRay=CoinCopyOfArray(simplex->ray(),numberRows);
#define SAFE_RAY
#ifdef SAFE_RAY
ClpSimplex & tempSimplex=*simplex;
#else
ClpSimplex tempSimplex=*simplex;
#endif
int logLevel=simplex->logLevel();
tempSimplex.setLogLevel(63);
tempSimplex.scaling(0);
tempSimplex.dual();
tempSimplex.setLogLevel(logLevel);
if (!tempSimplex.numberIterations()) {
double * ray = tempSimplex.ray();
int nBad=0;
for (int i=0;i<numberRows;i++) {
if (fabs(ray[i]-saveRay[i])>1.0e-3) {
if (debugMode)
printf("row %d true %g bad %g - diff %g\n",
i,ray[i],saveRay[i],ray[i]-saveRay[i]);
nBad++;
}
}
if (nBad)
printf("%d mismatch crunch ray values\n",nBad);
}
delete [] saveRay;
}
// make sure we use non-scaled versions
ClpPackedMatrix * saveMatrix = simplex->swapScaledMatrix(NULL);
double * saveScale = simplex->swapRowScale(NULL);
//printf("Could do normal cut\n");
// could use existing arrays
int numberRows=simplex->numberRows();
int numberColumns=simplex->numberColumns();
double * farkas = new double [2*numberColumns+numberRows];
double * bound = farkas + numberColumns;
double * effectiveRhs = bound + numberColumns;
// sign as internally for dual - so swap if primal
/*const*/ double * ray = simplex->ray();
// have to get rid of local cut rows
if (whichGenerator_) {
const int * whichGenerator = whichGenerator_ - numberRowsAtContinuous_;
int badRows=0;
for (int iRow=numberRowsAtContinuous_;iRow<numberRows;iRow++) {
int iType=whichGenerator[iRow];
if ((iType>=0&&iType<20000)) {
if (fabs(ray[iRow])>1.0e-10) {
badRows++;
} else {
ray[iRow]=0.0;
}
}
}
if (badRows) {
if ((debugMode&1)!=0)
printf("%d rows from local cuts\n",badRows);
localCuts=true;
}
}
// get farkas row
memset(farkas,0,(2*numberColumns+numberRows)*sizeof(double));
simplex->transposeTimes(-1.0,ray,farkas);
//const char * integerInformation = simplex->integerType_;
//assert (integerInformation);
int sequenceOut = simplex->sequenceOut();
// Put nonzero bounds in bound
const double * columnLower = simplex->columnLower();
const double * columnUpper = simplex->columnUpper();
int numberBad=0;
for (int i=0;i<numberColumns;i++) {
double value = farkas[i];
double boundValue=0.0;
if (simplex->getStatus(i)==ClpSimplex::basic) {
// treat as zero if small
if (fabs(value)<1.0e-8) {
value=0.0;
farkas[i]=0.0;
}
if (value) {
//printf("basic %d direction %d farkas %g\n",
// i,simplex->directionOut(),value);
if (value<0.0)
boundValue=columnLower[i];
else
boundValue=columnUpper[i];
}
} else if (fabs(value)>1.0e-10) {
if (value<0.0)
boundValue=columnLower[i];
else
boundValue=columnUpper[i];
}
bound[i]=boundValue;
if (fabs(boundValue)>1.0e10)
numberBad++;
}
const double * rowLower = simplex->rowLower();
const double * rowUpper = simplex->rowUpper();
//int pivotRow = simplex->spareIntArray_[3];
//bool badPivot=pivotRow<0;
for (int i=0;i<numberRows;i++) {
double value = ray[i];
double rhsValue=0.0;
if (simplex->getRowStatus(i)==ClpSimplex::basic) {
// treat as zero if small
if (fabs(value)<1.0e-8) {
value=0.0;
ray[i]=0.0;
}
if (value) {
//printf("row basic %d direction %d ray %g\n",
// i,simplex->directionOut(),value);
if (value<0.0)
rhsValue=rowLower[i];
else
rhsValue=rowUpper[i];
}
} else if (fabs(value)>1.0e-10) {
if (value<0.0)
rhsValue=rowLower[i];
else
rhsValue=rowUpper[i];
}
effectiveRhs[i]=rhsValue;
}
simplex->times(-1.0,bound,effectiveRhs);
simplex->swapRowScale(saveScale);
simplex->swapScaledMatrix(saveMatrix);
double bSum=0.0;
for (int i=0;i<numberRows;i++) {
bSum += effectiveRhs[i]*ray[i];
}
if (numberBad||bSum>-1.0e-4) {
#ifndef NDEBUG
printf("bad BOUND bSum %g - %d bad\n",
bSum,numberBad);
#endif
} else {
const char * integerInformation = simplex->integerInformation();
assert (integerInformation);
int * conflict = new int[numberColumns];
double * sort = new double [numberColumns];
double relax=0.0;
int nConflict=0;
int nOriginal=0;
int nFixed=0;
for (int iColumn=0;iColumn<numberColumns;iColumn++) {
if (integerInformation[iColumn]) {
if ((debugMode&1)!=0)
printf("%d status %d %g <= %g <=%g (orig %g, %g) farkas %g\n",
iColumn,simplex->getStatus(iColumn),columnLower[iColumn],
simplex->primalColumnSolution()[iColumn],columnUpper[iColumn],
originalLower[iColumn],originalUpper[iColumn],
farkas[iColumn]);
double gap = originalUpper[iColumn]-originalLower[iColumn];
if (!gap)
continue;
if (gap==columnUpper[iColumn]-columnLower[iColumn])
nOriginal++;
if (columnUpper[iColumn]==columnLower[iColumn])
nFixed++;
if (fabs(farkas[iColumn])<1.0e-15) {
farkas[iColumn]=0.0;
continue;
}
// temp
if (gap>=20000.0&&false) {
// can't use
if (farkas[iColumn]<0.0) {
assert(originalLower[iColumn]-columnLower[iColumn]<=0.0);
// farkas is negative - relax lower bound all way
relax +=
farkas[iColumn]*(originalLower[iColumn]-columnLower[iColumn]);
} else {
assert(originalUpper[iColumn]-columnUpper[iColumn]>=0.0);
// farkas is positive - relax upper bound all way
relax +=
farkas[iColumn]*(originalUpper[iColumn]-columnUpper[iColumn]);
}
continue;
}
if (originalLower[iColumn]==columnLower[iColumn]) {
if (farkas[iColumn]>0.0&&(simplex->getStatus(iColumn)==ClpSimplex::atUpperBound
||simplex->getStatus(iColumn)==ClpSimplex::isFixed
||iColumn==sequenceOut)) {
// farkas is positive - add to list
gap=originalUpper[iColumn]-columnUpper[iColumn];
if (gap) {
sort[nConflict]=-farkas[iColumn]*gap;
conflict[nConflict++]=iColumn;
}
//assert (gap>columnUpper[iColumn]-columnLower[iColumn]);
}
} else if (originalUpper[iColumn]==columnUpper[iColumn]) {
if (farkas[iColumn]<0.0&&(simplex->getStatus(iColumn)==ClpSimplex::atLowerBound
||simplex->getStatus(iColumn)==ClpSimplex::isFixed
||iColumn==sequenceOut)) {
// farkas is negative - add to list
gap=columnLower[iColumn]-originalLower[iColumn];
if (gap) {
sort[nConflict]=farkas[iColumn]*gap;
conflict[nConflict++]=iColumn;
}
//assert (gap>columnUpper[iColumn]-columnLower[iColumn]);
}
} else {
// can't use
if (farkas[iColumn]<0.0) {
assert(originalLower[iColumn]-columnLower[iColumn]<=0.0);
// farkas is negative - relax lower bound all way
relax +=
farkas[iColumn]*(originalLower[iColumn]-columnLower[iColumn]);
} else {
assert(originalUpper[iColumn]-columnUpper[iColumn]>=0.0);
// farkas is positive - relax upper bound all way
relax +=
farkas[iColumn]*(originalUpper[iColumn]-columnUpper[iColumn]);
}
}
assert(relax>=0.0);
} else {
// not integer - but may have been got at
double gap = originalUpper[iColumn]-originalLower[iColumn];
if (gap>columnUpper[iColumn]-columnLower[iColumn]) {
// can't use
if (farkas[iColumn]<0.0) {
assert(originalLower[iColumn]-columnLower[iColumn]<=0.0);
// farkas is negative - relax lower bound all way
relax +=
farkas[iColumn]*(originalLower[iColumn]-columnLower[iColumn]);
} else {
assert(originalUpper[iColumn]-columnUpper[iColumn]>=0.0);
// farkas is positive - relax upper bound all way
relax +=
farkas[iColumn]*(originalUpper[iColumn]-columnUpper[iColumn]);
}
}
}
}
if (relax+bSum>-1.0e-4||!nConflict) {
if (relax+bSum>-1.0e-4) {
#ifndef NDEBUG
printf("General integers relax bSum to %g\n",relax+bSum);
#endif
} else {
printf("All variables relaxed and still infeasible - what does this mean?\n");
int nR=0;
for (int i=0;i<numberRows;i++) {
if (fabs(ray[i])>1.0e-10)
nR++;
else
ray[i]=0.0;
}
int nC=0;
for (int i=0;i<numberColumns;i++) {
if (fabs(farkas[i])>1.0e-10)
nC++;
else
farkas[i]=0.0;
}
if (nR<3&&nC<5) {
printf("BAD %d nonzero rows, %d nonzero columns\n",nR,nC);
}
}
} else {
printf("BOUNDS violation bSum %g (relaxed %g) - %d at original bounds, %d fixed - %d in conflict\n",bSum,
relax+bSum,nOriginal,nFixed,nConflict);
CoinSort_2(sort,sort+nConflict,conflict);
int nC=nConflict;
bSum+=relax;
double saveBsum = bSum;
while (nConflict) {
//int iColumn=conflict[nConflict-1];
double change=-sort[nConflict-1];
if (bSum+change>-1.0e-4)
break;
nConflict--;
bSum += change;
}
if (!nConflict) {
int nR=0;
for (int i=0;i<numberRows;i++) {
if (fabs(ray[i])>1.0e-10)
nR++;
else
ray[i]=0.0;
}
int nC=0;
for (int i=0;i<numberColumns;i++) {
if (fabs(farkas[i])>1.0e-10)
nC++;
else
farkas[i]=0.0;
}
if (nR<3&&nC<5) {
printf("BAD2 %d nonzero rows, %d nonzero columns\n",nR,nC);
}
}
// no point doing if no reduction (or big?) ?
if (nConflict<nC+1&&nConflict<500) {
cut=new OsiRowCut();
cut->setUb(COIN_DBL_MAX);
if (!typeCut) {
double lo=1.0;
for (int i=0;i<nConflict;i++) {
int iColumn = conflict[i];
if (originalLower[iColumn]==columnLower[iColumn]) {
// must be at least one higher
sort[i]=1.0;
lo += originalLower[iColumn];
} else {
// must be at least one lower
sort[i]=-1.0;
lo -= originalUpper[iColumn];
}
}
cut->setLb(lo);
cut->setRow(nConflict,conflict,sort);
printf("CUT has %d (started at %d) - final bSum %g\n",nConflict,nC,bSum);
} else {
// just save for use later
// first take off small
int nC2=nC;
while (nC2) {
//int iColumn=conflict[nConflict-1];
double change=-sort[nC2-1];
if (saveBsum+change>-1.0e-4||change>1.0e-4)
break;
nC2--;
saveBsum += change;
}
cut->setLb(saveBsum);
for (int i=0;i<nC2;i++) {
int iColumn = conflict[i];
sort[i]=farkas[iColumn];
}
cut->setRow(nC2,conflict,sort);
printf("Stem CUT has %d (greedy %d - with small %d) - saved bSum %g final greedy bSum %g\n",
nC2,nConflict,nC,saveBsum,bSum);
}
}
}
delete [] conflict;
delete [] sort;
}
delete [] farkas;
} else {
printf("No dual ray\n");
}
}
#endif
return cut;
}
-------------- next part --------------
// $Id: interrupt.cpp 1899 2013-04-09 18:12:08Z stefan $
// Copyright (C) 2007, International Business Machines
// Corporation and others. All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).
#include <cassert>
#include <iomanip>
#include "CoinPragma.hpp"
#include "CbcModel.hpp"
#include "OsiClpSolverInterface.hpp"
#include "CbcSolver.hpp"
// Preprocessing
#include "CglPreProcess.hpp"
#include "CoinTime.hpp"
//#############################################################################
/************************************************************************
This main program shows how to take advantage of the standalone cbc in your program,
while still making major modifications.
This is very like driver4 but allows interrupts in clp for faster stopping
It would be up to user to clean up output as stopping in Clp seems to
give correct results but can think it is stopping in an odd way.
To make cleaner would need more events defined (in Cbc AND Clp)
First it reads in an integer model from an mps file
Then it initializes the integer model with cbc defaults
Then it calls CbcMain1 passing all parameters apart from first but with callBack to modify stuff
Finally it prints solution
************************************************************************/
/* Meaning of whereFrom:
1 after initial solve by dualsimplex etc
2 after preprocessing
3 just before branchAndBound (so user can override)
4 just after branchAndBound (before postprocessing)
5 after postprocessing
*/
/* Meaning of model status is as normal
status
-1 before branchAndBound
0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found
(or check value of best solution)
1 stopped - on maxnodes, maxsols, maxtime
2 difficulties so run was abandoned
(5 event user programmed event occurred)
cbc secondary status of problem
-1 unset (status_ will also be -1)
0 search completed with solution
1 linear relaxation not feasible (or worse than cutoff)
2 stopped on gap
3 stopped on nodes
4 stopped on time
5 stopped on user event
6 stopped on solutions
7 linear relaxation unbounded
but initially check if status is 0 and secondary status is 1 -> infeasible
or you can check solver status.
*/
/* Return non-zero to return quickly */
static int callBack(CbcModel * model, int whereFrom)
{
int returnCode=0;
switch (whereFrom) {
case 1:
case 2:
if (!model->status()&&model->secondaryStatus())
returnCode=1;
break;
case 3:
{
//CbcCompareUser compare;
//model->setNodeComparison(compare);
}
break;
case 4:
// If not good enough could skip postprocessing
break;
case 5:
break;
default:
abort();
}
return returnCode;
}
#include "CbcEventHandler.hpp"
static int cancelAsap=0;
/*
0 - not yet in Cbc
1 - in Cbc with new signal handler
2 - ending Cbc
*/
static int statusOfCbc=0;
#include "CoinSignal.hpp"
static CoinSighandler_t saveSignal = static_cast<CoinSighandler_t> (0);
extern "C" {
static void
#if defined(_MSC_VER)
__cdecl
#endif // _MSC_VER
signal_handler(int /*whichSignal*/)
{
cancelAsap=3;
return;
}
}
/** This is so user can trap events and do useful stuff.
CbcModel model_ is available as well as anything else you care
to pass in
*/
class MyEventHandler3 : public CbcEventHandler {
public:
/**@name Overrides */
//@{
virtual CbcAction event(CbcEvent whichEvent);
//@}
/**@name Constructors, destructor etc*/
//@{
/** Default constructor. */
MyEventHandler3();
/// Constructor with pointer to model (redundant as setEventHandler does)
MyEventHandler3(CbcModel * model);
/** Destructor */
virtual ~MyEventHandler3();
/** The copy constructor. */
MyEventHandler3(const MyEventHandler3 & rhs);
/// Assignment
MyEventHandler3& operator=(const MyEventHandler3 & rhs);
/// Clone
virtual CbcEventHandler * clone() const ;
//@}
protected:
// data goes here
};
//-------------------------------------------------------------------
// Default Constructor
//-------------------------------------------------------------------
MyEventHandler3::MyEventHandler3 ()
: CbcEventHandler()
{
}
//-------------------------------------------------------------------
// Copy constructor
//-------------------------------------------------------------------
MyEventHandler3::MyEventHandler3 (const MyEventHandler3 & rhs)
: CbcEventHandler(rhs)
{
}
// Constructor with pointer to model
MyEventHandler3::MyEventHandler3(CbcModel * model)
: CbcEventHandler(model)
{
}
//-------------------------------------------------------------------
// Destructor
//-------------------------------------------------------------------
MyEventHandler3::~MyEventHandler3 ()
{
}
//----------------------------------------------------------------
// Assignment operator
//-------------------------------------------------------------------
MyEventHandler3 &
MyEventHandler3::operator=(const MyEventHandler3& rhs)
{
if (this != &rhs) {
CbcEventHandler::operator=(rhs);
}
return *this;
}
//-------------------------------------------------------------------
// Clone
//-------------------------------------------------------------------
CbcEventHandler * MyEventHandler3::clone() const
{
return new MyEventHandler3(*this);
}
extern CglPreProcess* cbcPreProcessPointer;
CbcEventHandler::CbcAction
MyEventHandler3::event(CbcEvent whichEvent)
{
if(!statusOfCbc) {
// override signal handler
// register signal handler
saveSignal = signal(SIGINT, signal_handler);
statusOfCbc=1;
}
if ( (cancelAsap&2)!=0 ) {
printf("Cbc got cancel\n");
// switch off Clp cancel
cancelAsap &= 2;
return stop;
}
// If in sub tree carry on
if (!model_->parentModel()) {
if (whichEvent==endSearch&&statusOfCbc==1) {
// switch off cancel
cancelAsap=0;
// restore signal handler
signal(SIGINT, saveSignal);
statusOfCbc=2;
}
if (whichEvent==solution||whichEvent==heuristicSolution) {
#ifdef STOP_EARLY
return stop; // say finished
#else
#define WANT_SOLUTION
#ifdef WANT_SOLUTION
// If preprocessing was done solution will be to processed model
// int numberColumns = model_->getNumCols();
const double * bestSolution = model_->bestSolution();
assert (bestSolution);
// printf("value of solution is %g\n",model_->getObjValue());
// Trying to obtain solution for the original model:
assert( model_ && model_->solver() );
double objOffset=0;
model_->solver()->getDblParam(OsiObjOffset, objOffset);
const double objVal =
(model_->getObjValue() - objOffset)*
model_->getObjSense()* // ???
-1;
const double bestBnd =
(model_->getBestPossibleObjValue() - objOffset)*
model_->getObjSense()* // ???
-1;
OsiSolverInterface* origModel=0;
if ( 0!=cbcPreProcessPointer && 0!=model_->solver() ) {
cbcPreProcessPointer->postProcess( *model_->solver(), false );
origModel = cbcPreProcessPointer->originalModel();
} else {
origModel = model_->solver();
}
std::cout
<< " % OBJ VAL RAW: " << model_->getObjValue()
<< " OBJ VAL ORIG(?): " << objVal
<< " % BND RAW: " << model_->getBestPossibleObjValue()
<< " BND ORIG(?): " << bestBnd
<< " orig NCols: " << origModel->getNumCols()
<< " prepro NCols: " << model_->getNumCols()
<< std::endl;
printf(" Preprocessed sol: ");
for (int i=0;i<model_->getNumCols();i++) {
if (fabs(bestSolution[i])>1.0e-8)
printf("%d:%g ",i,bestSolution[i]);
}
printf("\n Postprocessed sol: ");
const int numberColumns = origModel->getNumCols();
const double* x = origModel->getColSolution();
for (int i=0;i<numberColumns;i++) {
if (fabs(x[i])>1.0e-8)
printf("%d:%g ",i,x[i]);
}
printf("\n");
#endif
return noAction; // carry on
#endif
} else {
return noAction; // carry on
}
} else {
return noAction; // carry on
}
}
/** This is so user can trap events and do useful stuff.
ClpSimplex model_ is available as well as anything else you care
to pass in
*/
class MyEventHandler4 : public ClpEventHandler {
public:
/**@name Overrides */
//@{
virtual int event(Event whichEvent);
//@}
/**@name Constructors, destructor etc*/
//@{
/** Default constructor. */
MyEventHandler4();
/// Constructor with pointer to model (redundant as setEventHandler does)
MyEventHandler4(ClpSimplex * model);
/** Destructor */
virtual ~MyEventHandler4();
/** The copy constructor. */
MyEventHandler4(const MyEventHandler4 & rhs);
/// Assignment
MyEventHandler4& operator=(const MyEventHandler4 & rhs);
/// Clone
virtual ClpEventHandler * clone() const ;
//@}
protected:
// data goes here
};
//-------------------------------------------------------------------
// Default Constructor
//-------------------------------------------------------------------
MyEventHandler4::MyEventHandler4 ()
: ClpEventHandler()
{
}
//-------------------------------------------------------------------
// Copy constructor
//-------------------------------------------------------------------
MyEventHandler4::MyEventHandler4 (const MyEventHandler4 & rhs)
: ClpEventHandler(rhs)
{
}
// Constructor with pointer to model
MyEventHandler4::MyEventHandler4(ClpSimplex * model)
: ClpEventHandler(model)
{
}
//-------------------------------------------------------------------
// Destructor
//-------------------------------------------------------------------
MyEventHandler4::~MyEventHandler4 ()
{
}
//----------------------------------------------------------------
// Assignment operator
//-------------------------------------------------------------------
MyEventHandler4 &
MyEventHandler4::operator=(const MyEventHandler4& rhs)
{
if (this != &rhs) {
ClpEventHandler::operator=(rhs);
}
return *this;
}
//-------------------------------------------------------------------
// Clone
//-------------------------------------------------------------------
ClpEventHandler * MyEventHandler4::clone() const
{
return new MyEventHandler4(*this);
}
int
MyEventHandler4::event(Event whichEvent)
{
if ( (cancelAsap&1)!=0 ) {
printf("Clp got cancel\n");
return 5;
} else {
return -1;
}
}
int main (int argc, const char *argv[])
{
OsiClpSolverInterface solver1;
//#define USE_OSI_NAMES
#ifdef USE_OSI_NAMES
// Say we are keeping names (a bit slower this way)
solver1.setIntParam(OsiNameDiscipline,1);
#endif
// Read in model using argv[1]
// and assert that it is a clean model
std::string mpsFileName;
#if defined(SAMPLEDIR)
mpsFileName = SAMPLEDIR "/p0033.mps";
#else
if (argc < 2) {
fprintf(stderr, "Do not know where to find sample MPS files.\n");
exit(1);
}
#endif
if (argc>=2) mpsFileName = argv[1];
int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
if( numMpsReadErrors != 0 )
{
printf("%d errors reading MPS file\n", numMpsReadErrors);
return numMpsReadErrors;
}
// Tell solver to return fast if presolve or initial solve infeasible
solver1.getModelPtr()->setMoreSpecialOptions(3);
// allow Clp to handle interrupts
MyEventHandler4 clpEventHandler;
solver1.getModelPtr()->passInEventHandler(&clpEventHandler);
/* Two ways of doing this depending on whether NEW_STYLE_SOLVER defined.
So we need pointer to model. Old way could use modelA. rather than model->
*/
// Messy code below copied from CbcSolver.cpp
#if NEW_STYLE_SOLVER==0
// Pass to Cbc initialize defaults
CbcModel modelA(solver1);
CbcModel * model = &modelA;
CbcMain0(modelA);
// Event handler
MyEventHandler3 eventHandler;
model->passInEventHandler(&eventHandler);
/* Now go into code for standalone solver
Could copy arguments and add -quit at end to be safe
but this will do
*/
if (argc>2) {
CbcMain1(argc-1,argv+1,modelA,callBack);
} else {
const char * argv2[]={"driver4","-solve","-quit"};
CbcMain1(3,argv2,modelA,callBack);
}
#else
CbcSolver control(solver1);
// initialize
control.fillValuesInSolver();
// Event handler
MyEventHandler3 eventHandler;
CbcModel * model = control.model();
model->passInEventHandler(&eventHandler);
control.solve (argc-1, argv+1, 1);
#endif
// Solver was cloned so get current copy
OsiSolverInterface * solver = model->solver();
// Print solution if finished (could get from model->bestSolution() as well
if (model->bestSolution()) {
const double * solution = solver->getColSolution();
int iColumn;
int numberColumns = solver->getNumCols();
std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
std::cout<<"--------------------------------------"<<std::endl;
#ifdef USE_OSI_NAMES
for (iColumn=0;iColumn<numberColumns;iColumn++) {
double value=solution[iColumn];
if (fabs(value)>1.0e-7&&solver->isInteger(iColumn))
std::cout<<std::setw(6)<<iColumn<<" "<<std::setw(8)<<setiosflags(std::ios::left)<<solver->getColName(iColumn)
<<resetiosflags(std::ios::adjustfield)<<std::setw(14)<<" "<<value<<std::endl;
}
#else
// names may not be in current solver - use original
for (iColumn=0;iColumn<numberColumns;iColumn++) {
double value=solution[iColumn];
if (fabs(value)>1.0e-7&&solver->isInteger(iColumn))
std::cout<<std::setw(6)<<iColumn<<" "<<std::setw(8)<<setiosflags(std::ios::left)<<solver1.getModelPtr()->columnName(iColumn)
<<resetiosflags(std::ios::adjustfield)<<std::setw(14)<<" "<<value<<std::endl;
}
#endif
std::cout<<"--------------------------------------"<<std::endl;
std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
} else {
std::cout<<" No solution!"<<std::endl;
}
return 0;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: photo.mps.gz
Type: application/x-gzip
Size: 5194 bytes
Desc: not available
URL: <http://list.coin-or.org/pipermail/cbc/attachments/20160226/c2534099/attachment-0002.bin>
-------------- next part --------------
Coin0008I BLANK read with 0 errors
Welcome to the CBC MILP Solver
Version: 2.9
Build Date: Feb 23 2016
Revision Number: 2274
command line - driver4 -solve -quit (default strategy 1)
Continuous objective value is -8 - 0.00 seconds
Cgl0003I 1 fixed, 0 tightened bounds, 97 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 33 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 6 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 1 strengthened rows, 0 substitutions
Cgl0004I processed model has 247 rows, 196 columns (196 integer (186 of which binary)) and 1049 elements
Cutoff increment increased from 1e-05 to 0.9999
Cbc0045I 1 integer variables out of 196 objects (196 integer) have cost of -1 - high priority
Cbc0045I branch on satisfied Y create fake objective Y random cost Y
Cbc0038I Initial state - 94 integers unsatisfied sum - 26.8016
Cbc0038I Pass 1: suminf. 18.52650 (76) obj. -5.62745 iterations 74
Cbc0038I Pass 2: suminf. 17.02540 (72) obj. -5.71726 iterations 13
Cbc0038I Pass 3: suminf. 11.61466 (49) obj. -6 iterations 21
Cbc0038I Pass 4: suminf. 11.26452 (49) obj. -6 iterations 20
Cbc0038I Pass 5: suminf. 5.50308 (30) obj. -6 iterations 32
Cbc0038I Pass 6: suminf. 5.31400 (34) obj. -6 iterations 15
Cbc0038I Pass 7: suminf. 3.36481 (31) obj. -5.98485 iterations 30
Cbc0038I Pass 8: suminf. 3.28579 (34) obj. -5.96248 iterations 13
Cbc0038I Pass 9: suminf. 6.04255 (34) obj. -5.88889 iterations 22
Cbc0038I Pass 10: suminf. 4.99869 (31) obj. -5.90523 iterations 15
Cbc0038I Pass 11: suminf. 1.94497 (15) obj. -6 iterations 23
Cbc0038I Pass 12: suminf. 4.54524 (25) obj. -5.88889 iterations 28
Cbc0038I Pass 13: suminf. 2.60476 (18) obj. -5.85714 iterations 22
Cbc0038I Pass 14: suminf. 5.97778 (30) obj. -4.77778 iterations 30
Cbc0038I Pass 15: suminf. 2.51905 (16) obj. -5 iterations 29
Cbc0038I Pass 16: suminf. 5.97778 (30) obj. -4.77778 iterations 31
Cbc0038I Pass 17: suminf. 2.11508 (13) obj. -4.71429 iterations 23
Cbc0038I Pass 18: suminf. 0.65000 (6) obj. -3 iterations 23
Cbc0038I Pass 19: suminf. 0.75794 (6) obj. -3 iterations 12
Cbc0038I Pass 20: suminf. 14.48742 (66) obj. -5.88383 iterations 72
Cbc0038I Pass 21: suminf. 11.17259 (47) obj. -4.50817 iterations 37
Cbc0038I Pass 22: suminf. 11.17259 (47) obj. -4.50817 iterations 2
Cbc0038I Pass 23: suminf. 7.82659 (29) obj. -4 iterations 37
Cbc0038I Pass 24: suminf. 6.83823 (35) obj. -3.51984 iterations 18
Cbc0038I Pass 25: suminf. 4.31201 (26) obj. -2.01344 iterations 31
Cbc0038I Pass 26: suminf. 4.21587 (17) obj. -1.88889 iterations 13
Cbc0038I Pass 27: suminf. 2.46984 (11) obj. -1 iterations 28
Cbc0038I Pass 28: suminf. 1.74286 (12) obj. -0.857143 iterations 13
Cbc0038I Pass 29: suminf. 2.88095 (14) obj. 0 iterations 24
Cbc0038I Pass 30: suminf. 1.25000 (8) obj. 0 iterations 22
Cbc0038I Pass 31: suminf. 0.84444 (6) obj. 0 iterations 15
Cbc0038I Pass 32: suminf. 0.75000 (6) obj. 0 iterations 16
Cbc0038I Pass 33: suminf. 5.91528 (29) obj. -0.444444 iterations 45
Cbc0038I Pass 34: suminf. 2.20000 (10) obj. 0 iterations 30
Cbc0038I Pass 35: suminf. 0.68571 (6) obj. 0 iterations 25
Cbc0038I Pass 36: suminf. 0.90000 (6) obj. 0 iterations 25
Cbc0038I Pass 37: suminf. 8.18333 (34) obj. -2.02778 iterations 76
Cbc0038I Pass 38: suminf. 5.34286 (20) obj. -1.93056 iterations 44
Cbc0038I Pass 39: suminf. 4.34286 (18) obj. -1.93056 iterations 6
Cbc0038I Pass 40: suminf. 4.85000 (22) obj. -1.80952 iterations 30
Cbc0038I Pass 41: suminf. 2.81735 (14) obj. -1.71429 iterations 15
Cbc0038I Pass 42: suminf. 2.01508 (10) obj. -1 iterations 26
Cbc0038I Pass 43: suminf. 1.86111 (12) obj. -0.902778 iterations 20
Cbc0038I Pass 44: suminf. 0.45000 (4) obj. -1 iterations 20
Cbc0038I Pass 45: suminf. 0.45000 (4) obj. -1 iterations 2
Cbc0038I Pass 46: suminf. 0.47222 (4) obj. -1 iterations 14
Cbc0038I Pass 47: suminf. 14.17176 (52) obj. -2.46838 iterations 51
Cbc0038I Pass 48: suminf. 7.41481 (31) obj. -1.92593 iterations 52
Cbc0038I Pass 49: suminf. 4.35476 (21) obj. -1.14286 iterations 38
Cbc0038I Pass 50: suminf. 3.44662 (26) obj. -1 iterations 55
Cbc0038I Pass 51: suminf. 0.67222 (6) obj. -1 iterations 24
Cbc0038I Pass 52: suminf. 0.67222 (6) obj. -1 iterations 3
Cbc0038I Pass 53: suminf. 0.73571 (6) obj. -1 iterations 25
Cbc0038I Pass 54: suminf. 7.86071 (28) obj. -1 iterations 57
Cbc0038I Pass 55: suminf. 7.30913 (30) obj. -1.14286 iterations 25
Cbc0038I Pass 56: suminf. 7.30913 (30) obj. -1.14286 iterations 3
Cbc0038I Pass 57: suminf. 4.18016 (18) obj. -0.888889 iterations 19
Cbc0038I Pass 58: suminf. 4.52857 (20) obj. -1 iterations 6
Cbc0038I Pass 59: suminf. 4.16111 (20) obj. -0.888889 iterations 25
Cbc0038I Pass 60: suminf. 3.01508 (19) obj. -0.857143 iterations 17
Cbc0038I Pass 61: suminf. 3.08651 (12) obj. -0.571429 iterations 10
Cbc0038I Pass 62: suminf. 0.78571 (6) obj. 0 iterations 31
Cbc0038I Pass 63: suminf. 0.62222 (6) obj. 0 iterations 8
Cbc0038I Pass 64: suminf. 9.21845 (33) obj. -1.66667 iterations 62
Cbc0038I Pass 65: suminf. 6.01944 (30) obj. -1.1746 iterations 26
Cbc0038I Pass 66: suminf. 2.96032 (12) obj. -0.888889 iterations 33
Cbc0038I Pass 67: suminf. 1.96032 (10) obj. -0.888889 iterations 8
Cbc0038I Pass 68: suminf. 0.00000 (0) obj. -1 iterations 17
Cbc0038I Solution found of -1
event(heuristicSolution) CbcModel.cpp:13363 % OBJ VAL RAW: -1 OBJ VAL ORIG(?): 1 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196
Preprocessed sol: 0:3 1:8 2:7 3:4 4:1 5:6 6:5 8:2 9:1 17:1 30:1 42:1 50:1 56:1 62:1 76:1 84:1 88:1 99:1 121:1 136:1 139:1 141:1 142:1 145:1 146:1 149:1 150:1 153:1 154:1 157:1 158:1 161:1 162:1 165:1 166:1 167:1 169:1 170:1 172:1 175:1 177:1 178:1 181:1 182:1 184:1 187:1 189:1 190:1 192:1 195:1
Postprocessed sol: 0:1.71721 1:2.71721 2:3.71721 3:1.71721 4:3 5:5 6:6.98037 7:6.55931 8:4.59149 9:8 11:1 15:0.666667 16:0.4 18:0.607018 19:0.4 20:1 22:0.4 23:0.526316 24:1 25:1 26:1 27:0.358604 28:0.426234 33:0.215162 37:0.570494 39:0.143442 42:0.286065 48:0.856558 53:0.143442 54:0.391396 56:0.358604 58:0.25 63:0.25 67:0.75 77:1 82:0.00327243 88:0.996728 92:0.0733115 96:0.498773 97:0.00327243 98:0.424643 101:0.568085 107:0.431915 110:0.253644 111:0.746356 118:0.666667 120:0.271721 121:0.128279 124:0.0717208 125:0.535297 127:0.4 130:0.240851 131:0.159149 132:0.526316 134:0.842105 135:0.157895 136:0.670242 137:0.329758 138:1 141:1 142:1 143:0.253644 144:1 145:0.746356 146:1 149:1 150:0.828279 151:0.171721 153:1 154:0.234286 155:0.765714 156:0.612572 157:0.387428 158:1 159:0.666667 160:1 162:1 163:0.271721 164:1 165:0.128279 166:0.8 167:0.2 169:1 170:1 171:0.0717208 172:1 173:0.535297 174:1 176:1 177:0.4 179:1 180:1 182:1 183:0.240851 184:1 185:0.159149 186:1 187:0.526316 188:1 190:1 191:0.842105 192:1 193:0.157895 194:1 195:0.670242 196:1 197:0.329758
Cbc0038I Cleaned solution of -1
Cbc0038I Before mini branch and bound, 17 integers at bound fixed and 0 continuous
Cbc0038I Full problem 247 rows 196 columns, reduced to 231 rows 173 columns - 13 fixed gives 205, 133 - still too large
Cbc0038I Mini branch and bound did not improve solution (0.05 seconds)
Cbc0038I Round again with cutoff of -2.59991
Cbc0038I Pass 69: suminf. 18.52650 (76) obj. -5.62745 iterations 0
Cbc0038I Pass 70: suminf. 17.02540 (72) obj. -5.71726 iterations 16
Cbc0038I Pass 71: suminf. 10.72577 (47) obj. -6 iterations 28
Cbc0038I Pass 72: suminf. 10.31419 (47) obj. -6 iterations 14
Cbc0038I Pass 73: suminf. 5.45079 (23) obj. -6 iterations 33
Cbc0038I Pass 74: suminf. 6.35895 (36) obj. -6 iterations 9
Cbc0038I Pass 75: suminf. 5.94410 (34) obj. -6 iterations 29
Cbc0038I Pass 76: suminf. 4.84966 (30) obj. -5.87302 iterations 24
Cbc0038I Pass 77: suminf. 5.17302 (24) obj. -4 iterations 42
Cbc0038I Pass 78: suminf. 5.73770 (24) obj. -4 iterations 18
Cbc0038I Pass 79: suminf. 5.69008 (24) obj. -4 iterations 13
Cbc0038I Pass 80: suminf. 3.79921 (18) obj. -3.88889 iterations 28
Cbc0038I Pass 81: suminf. 4.37917 (36) obj. -4 iterations 20
Cbc0038I Pass 82: suminf. 9.75556 (36) obj. -4 iterations 32
Cbc0038I Pass 83: suminf. 4.69008 (20) obj. -4 iterations 22
Cbc0038I Pass 84: suminf. 3.21587 (18) obj. -3.85714 iterations 12
Cbc0038I Pass 85: suminf. 3.97488 (28) obj. -3 iterations 34
Cbc0038I Pass 86: suminf. 3.97488 (28) obj. -3 iterations 5
Cbc0038I Pass 87: suminf. 4.81111 (21) obj. -3 iterations 49
Cbc0038I Pass 88: suminf. 4.03413 (20) obj. -3 iterations 25
Cbc0038I Pass 89: suminf. 2.86667 (13) obj. -3 iterations 7
Cbc0038I Pass 90: suminf. 3.31667 (13) obj. -3 iterations 42
Cbc0038I Pass 91: suminf. 2.81667 (13) obj. -3 iterations 11
Cbc0038I Pass 92: suminf. 2.81667 (13) obj. -3 iterations 6
Cbc0038I Pass 93: suminf. 4.03413 (20) obj. -3 iterations 30
Cbc0038I Pass 94: suminf. 3.98889 (19) obj. -3 iterations 13
Cbc0038I Pass 95: suminf. 4.75833 (19) obj. -3 iterations 21
Cbc0038I Pass 96: suminf. 4.75833 (19) obj. -3 iterations 15
Cbc0038I Pass 97: suminf. 3.31667 (13) obj. -3 iterations 26
Cbc0038I Pass 98: suminf. 4.11481 (23) obj. -3 iterations 19
Cbc0038I Pass 99: suminf. 4.45926 (23) obj. -3 iterations 31
Cbc0038I Pass 100: suminf. 4.00000 (17) obj. -3 iterations 20
Cbc0038I Pass 101: suminf. 2.83333 (12) obj. -3 iterations 17
Cbc0038I Pass 102: suminf. 3.53889 (14) obj. -3 iterations 37
Cbc0038I Pass 103: suminf. 1.79286 (10) obj. -3 iterations 35
Cbc0038I Pass 104: suminf. 2.33333 (8) obj. -3 iterations 34
Cbc0038I Pass 105: suminf. 2.90000 (10) obj. -3 iterations 25
Cbc0038I Pass 106: suminf. 3.50357 (24) obj. -3 iterations 15
Cbc0038I Pass 107: suminf. 1.57143 (8) obj. -3 iterations 28
Cbc0038I Pass 108: suminf. 4.59412 (18) obj. -3 iterations 24
Cbc0038I Pass 109: suminf. 2.82222 (10) obj. -3 iterations 26
Cbc0038I Pass 110: suminf. 2.82222 (10) obj. -3 iterations 10
Cbc0038I Pass 111: suminf. 1.44444 (8) obj. -3 iterations 19
Cbc0038I Pass 112: suminf. 1.08889 (6) obj. -3 iterations 6
Cbc0038I Pass 113: suminf. 0.25000 (2) obj. -3 iterations 6
Cbc0038I Pass 114: suminf. 0.20000 (2) obj. -3 iterations 6
Cbc0038I Pass 115: suminf. 15.31847 (51) obj. -5.9442 iterations 47
Cbc0038I Pass 116: suminf. 6.00730 (32) obj. -6.94921 iterations 46
Cbc0038I Pass 117: suminf. 5.00079 (23) obj. -6.89286 iterations 21
Cbc0038I Pass 118: suminf. 5.13251 (27) obj. -6.6646 iterations 13
Cbc0038I Pass 119: suminf. 4.77857 (17) obj. -4 iterations 34
Cbc0038I Pass 120: suminf. 3.06837 (17) obj. -4 iterations 13
Cbc0038I Pass 121: suminf. 1.77143 (10) obj. -3.85714 iterations 18
Cbc0038I Pass 122: suminf. 0.45000 (4) obj. -3 iterations 20
Cbc0038I Pass 123: suminf. 0.45000 (4) obj. -3 iterations 13
Cbc0038I Pass 124: suminf. 14.03409 (60) obj. -4.75735 iterations 61
Cbc0038I Pass 125: suminf. 12.71061 (51) obj. -4.69475 iterations 37
Cbc0038I Pass 126: suminf. 12.51916 (52) obj. -4.78052 iterations 5
Cbc0038I Pass 127: suminf. 7.88600 (45) obj. -4.90703 iterations 31
Cbc0038I Pass 128: suminf. 7.02184 (38) obj. -4.87546 iterations 23
Cbc0038I Pass 129: suminf. 7.67581 (35) obj. -4.92627 iterations 11
Cbc0038I Pass 130: suminf. 9.77917 (34) obj. -4 iterations 39
Cbc0038I Pass 131: suminf. 6.59702 (25) obj. -4 iterations 16
Cbc0038I Pass 132: suminf. 5.27729 (24) obj. -4 iterations 13
Cbc0038I Pass 133: suminf. 5.15635 (24) obj. -4 iterations 28
Cbc0038I Pass 134: suminf. 3.35476 (16) obj. -4 iterations 24
Cbc0038I Pass 135: suminf. 3.35476 (16) obj. -4 iterations 1
Cbc0038I Pass 136: suminf. 4.06667 (16) obj. -4 iterations 21
Cbc0038I Pass 137: suminf. 3.27710 (18) obj. -4 iterations 18
Cbc0038I Pass 138: suminf. 3.94286 (24) obj. -3.91429 iterations 19
Cbc0038I Pass 139: suminf. 4.00119 (24) obj. -4 iterations 28
Cbc0038I Pass 140: suminf. 2.55952 (17) obj. -3.85714 iterations 19
Cbc0038I Pass 141: suminf. 2.36032 (15) obj. -3 iterations 20
Cbc0038I Pass 142: suminf. 2.36032 (15) obj. -3 iterations 21
Cbc0038I Pass 143: suminf. 4.62698 (23) obj. -3 iterations 30
Cbc0038I Pass 144: suminf. 1.98810 (13) obj. -3 iterations 18
Cbc0038I Pass 145: suminf. 1.98810 (13) obj. -3 iterations 18
Cbc0038I Pass 146: suminf. 1.86032 (13) obj. -3 iterations 15
Cbc0038I Pass 147: suminf. 2.09286 (10) obj. -2.71429 iterations 29
Cbc0038I Pass 148: suminf. 2.23996 (11) obj. -2.59991 iterations 44
Cbc0038I Pass 149: suminf. 1.14286 (4) obj. -4.71429 iterations 34
Cbc0038I Pass 150: suminf. 1.14286 (4) obj. -4.71429 iterations 3
Cbc0038I Pass 151: suminf. 0.75000 (2) obj. -4 iterations 7
Cbc0038I Solution found of -4
event(heuristicSolution) CbcModel.cpp:13363 % OBJ VAL RAW: -4 OBJ VAL ORIG(?): 4 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196
Preprocessed sol: 1:6 2:8 3:2 4:1 5:3 6:5 7:7 8:4 9:4 11:1 18:1 20:1 22:1 27:1 40:1 51:1 54:1 62:1 73:1 84:1 95:1 101:1 108:1 123:1 128:1 136:1 139:1 140:1 141:1 143:1 144:1 147:1 149:1 150:1 153:1 154:1 157:1 158:1 161:1 162:1 165:1 166:1 169:1 170:1 171:1 172:1 175:1 177:1 178:1 180:1 181:1 183:1 184:1 187:1 188:1 191:1 193:1 194:1
Postprocessed sol: 0:2.99109 1:3.99109 2:3.17814 3:1.17814 4:3 5:5 6:6.25182 7:5.83077 8:4.57895 9:8 11:1 15:0.4 16:0.292632 18:0.4 19:0.4 20:1 22:1 23:0.507368 24:1 25:1 26:1 27:0.0890688 28:0.494899 33:0.416032 37:0.380405 39:0.0356275 42:0.583968 48:0.964372 53:0.0356275 54:0.660931 56:0.0890688 58:0.25 63:0.25 67:0.75 77:1 82:0.124696 88:0.875304 92:0.340756 97:0.124696 98:0.534548 101:0.570175 107:0.429825 110:0.199109 111:0.800891 118:0.4 120:0.217814 121:0.182186 124:0.0178138 125:0.382186 127:0.4 130:0.842105 131:0.157895 132:0.507368 134:0.842105 135:0.157895 136:0.325182 137:0.674818 138:0.818704 139:0.181296 141:1 142:1 143:0.199109 144:1 145:0.800891 146:1 149:1 150:0.700891 151:0.299109 152:0.123887 153:0.876113 154:0.0734818 155:0.926518 156:0.741215 157:0.258785 158:1 159:0.4 160:1 162:1 163:0.217814 164:1 165:0.182186 166:0.981296 167:0.0187045 169:1 170:1 171:0.0178138 172:1 173:0.382186 174:1 176:1 177:0.4 179:1 180:1 182:1 183:0.842105 184:1 185:0.157895 186:1 187:0.507368 188:1 190:1 191:0.842105 192:1 193:0.157895 194:1 195:0.325182 196:1 197:0.674818
Cbc0038I Cleaned solution of -4
Cbc0038I Before mini branch and bound, 14 integers at bound fixed and 0 continuous
Cbc0038I Full problem 247 rows 196 columns, reduced to 220 rows 175 columns - 24 fixed gives 172, 103 - still too large
Cbc0038I Full problem 247 rows 196 columns, reduced to 155 rows 96 columns - too large
Cbc0038I Mini branch and bound did not improve solution (0.11 seconds)
Cbc0038I Round again with cutoff of -5.59992
Cbc0038I Pass 152: suminf. 18.52650 (76) obj. -5.62745 iterations 0
Cbc0038I Pass 153: suminf. 17.02540 (72) obj. -5.71726 iterations 16
Cbc0038I Pass 154: suminf. 12.36221 (55) obj. -6 iterations 31
Cbc0038I Pass 155: suminf. 9.42730 (38) obj. -6 iterations 22
Cbc0038I Pass 156: suminf. 8.61406 (40) obj. -6 iterations 5
Cbc0038I Pass 157: suminf. 8.50159 (33) obj. -6 iterations 20
Cbc0038I Pass 158: suminf. 8.23338 (39) obj. -5.95964 iterations 9
Cbc0038I Pass 159: suminf. 7.30030 (29) obj. -5.59992 iterations 31
Cbc0038I Pass 160: suminf. 6.35085 (29) obj. -5.59992 iterations 17
Cbc0038I Pass 161: suminf. 6.41738 (34) obj. -5.59992 iterations 11
Cbc0038I Pass 162: suminf. 8.03943 (40) obj. -5.59992 iterations 53
Cbc0038I Pass 163: suminf. 8.91582 (40) obj. -5.59992 iterations 13
Cbc0038I Pass 164: suminf. 4.67778 (23) obj. -6.125 iterations 42
Cbc0038I Pass 165: suminf. 4.32671 (38) obj. -6 iterations 20
Cbc0038I Pass 166: suminf. 5.36905 (21) obj. -6 iterations 32
Cbc0038I Pass 167: suminf. 4.58492 (34) obj. -6 iterations 31
Cbc0038I Pass 168: suminf. 4.61905 (21) obj. -6 iterations 27
Cbc0038I Pass 169: suminf. 4.22837 (34) obj. -6 iterations 26
Cbc0038I Pass 170: suminf. 5.88517 (35) obj. -6 iterations 26
Cbc0038I Pass 171: suminf. 4.60837 (28) obj. -6 iterations 19
Cbc0038I Pass 172: suminf. 4.60476 (25) obj. -5.88889 iterations 35
Cbc0038I Pass 173: suminf. 4.24970 (36) obj. -6 iterations 17
Cbc0038I Pass 174: suminf. 6.01276 (30) obj. -6 iterations 36
Cbc0038I Pass 175: suminf. 4.48889 (27) obj. -5.95238 iterations 27
Cbc0038I Pass 176: suminf. 5.18399 (30) obj. -5.98148 iterations 23
Cbc0038I Pass 177: suminf. 2.99524 (17) obj. -5.85714 iterations 22
Cbc0038I Pass 178: suminf. 2.99524 (17) obj. -5.85714 iterations 11
Cbc0038I Pass 179: suminf. 5.99884 (38) obj. -5.59992 iterations 42
Cbc0038I Pass 180: suminf. 3.43794 (14) obj. -5.59992 iterations 19
Cbc0038I Pass 181: suminf. 3.43794 (14) obj. -5.59992 iterations 14
Cbc0038I Pass 182: suminf. 3.27213 (29) obj. -5.77361 iterations 40
Cbc0038I Pass 183: suminf. 2.77143 (13) obj. -5.66667 iterations 25
Cbc0038I Pass 184: suminf. 6.34868 (41) obj. -5.59992 iterations 50
Cbc0038I Pass 185: suminf. 3.43794 (14) obj. -5.59992 iterations 28
Cbc0038I Pass 186: suminf. 3.43794 (14) obj. -5.59992 iterations 5
Cbc0038I Pass 187: suminf. 3.01587 (15) obj. -6.66667 iterations 45
Cbc0038I Pass 188: suminf. 2.57143 (11) obj. -6.66667 iterations 26
Cbc0038I Pass 189: suminf. 1.68254 (11) obj. -6 iterations 28
Cbc0038I Pass 190: suminf. 1.23810 (7) obj. -6 iterations 24
Cbc0038I Pass 191: suminf. 12.80658 (57) obj. -5.59992 iterations 63
Cbc0038I Pass 192: suminf. 5.75655 (29) obj. -5.84524 iterations 37
Cbc0038I Pass 193: suminf. 5.26617 (30) obj. -5.85871 iterations 9
Cbc0038I Pass 194: suminf. 2.66488 (21) obj. -5.98592 iterations 28
Cbc0038I Pass 195: suminf. 2.36429 (14) obj. -5.85714 iterations 31
Cbc0038I Pass 196: suminf. 3.45927 (18) obj. -5.59992 iterations 63
Cbc0038I Pass 197: suminf. 3.45927 (18) obj. -5.59992 iterations 15
Cbc0038I Pass 198: suminf. 2.00000 (10) obj. -8 iterations 53
Cbc0038I Pass 199: suminf. 1.96429 (10) obj. -7.85714 iterations 27
Cbc0038I Pass 200: suminf. 1.91429 (8) obj. -7 iterations 21
Cbc0038I Pass 201: suminf. 1.91429 (8) obj. -7 iterations 26
Cbc0038I Pass 202: suminf. 1.39286 (6) obj. -7 iterations 27
Cbc0038I Pass 203: suminf. 1.39286 (6) obj. -7 iterations 25
Cbc0038I Pass 204: suminf. 1.34286 (6) obj. -7 iterations 23
Cbc0038I Pass 205: suminf. 1.34286 (6) obj. -7 iterations 22
Cbc0038I Pass 206: suminf. 12.06849 (65) obj. -5.59992 iterations 61
Cbc0038I Pass 207: suminf. 6.29206 (26) obj. -5.59992 iterations 39
Cbc0038I Pass 208: suminf. 3.57460 (19) obj. -5.71429 iterations 24
Cbc0038I Pass 209: suminf. 3.57460 (19) obj. -5.71429 iterations 15
Cbc0038I Pass 210: suminf. 6.12524 (26) obj. -5.59992 iterations 37
Cbc0038I Pass 211: suminf. 3.55032 (21) obj. -5.59992 iterations 23
Cbc0038I Pass 212: suminf. 4.33333 (13) obj. -8 iterations 53
Cbc0038I Pass 213: suminf. 3.52381 (13) obj. -8 iterations 36
Cbc0038I Pass 214: suminf. 2.47619 (8) obj. -8 iterations 11
Cbc0038I Pass 215: suminf. 2.47619 (8) obj. -8 iterations 5
Cbc0038I Pass 216: suminf. 1.71429 (6) obj. -8 iterations 27
Cbc0038I Pass 217: suminf. 1.71429 (6) obj. -8 iterations 15
Cbc0038I Pass 218: suminf. 1.14286 (4) obj. -8 iterations 11
Cbc0038I Pass 219: suminf. 1.14286 (4) obj. -8 iterations 16
Cbc0038I Pass 220: suminf. 13.55125 (60) obj. -7.30217 iterations 55
Cbc0038I Pass 221: suminf. 6.28950 (35) obj. -6.74178 iterations 49
Cbc0038I Pass 222: suminf. 5.78950 (33) obj. -6.74178 iterations 1
Cbc0038I Pass 223: suminf. 6.04270 (23) obj. -5.59992 iterations 51
Cbc0038I Pass 224: suminf. 4.86663 (29) obj. -5.59992 iterations 39
Cbc0038I Pass 225: suminf. 4.80801 (31) obj. -8 iterations 72
Cbc0038I Pass 226: suminf. 3.14286 (21) obj. -7.71825 iterations 40
Cbc0038I Pass 227: suminf. 3.38889 (17) obj. -5.96032 iterations 28
Cbc0038I Pass 228: suminf. 3.38889 (17) obj. -5.96032 iterations 25
Cbc0038I Pass 229: suminf. 2.25664 (20) obj. -5.98592 iterations 23
Cbc0038I Pass 230: suminf. 2.87817 (21) obj. -5.98592 iterations 18
Cbc0038I Pass 231: suminf. 5.79354 (24) obj. -5.59992 iterations 53
Cbc0038I Pass 232: suminf. 5.11441 (25) obj. -5.59992 iterations 24
Cbc0038I Pass 233: suminf. 4.03538 (27) obj. -5.59992 iterations 17
Cbc0038I Pass 234: suminf. 6.64220 (31) obj. -8 iterations 69
Cbc0038I Pass 235: suminf. 2.94286 (13) obj. -7.85714 iterations 39
Cbc0038I Pass 236: suminf. 1.91429 (10) obj. -7.85714 iterations 11
Cbc0038I Pass 237: suminf. 1.39286 (6) obj. -7 iterations 23
Cbc0038I Pass 238: suminf. 1.39286 (6) obj. -7 iterations 14
Cbc0038I Pass 239: suminf. 1.34286 (6) obj. -7 iterations 16
Cbc0038I Pass 240: suminf. 1.34286 (6) obj. -7 iterations 16
Cbc0038I Pass 241: suminf. 5.21032 (26) obj. -5.77778 iterations 43
Cbc0038I Pass 242: suminf. 3.09286 (12) obj. -6 iterations 29
Cbc0038I Pass 243: suminf. 1.64286 (8) obj. -6 iterations 30
Cbc0038I Pass 244: suminf. 1.64286 (8) obj. -6 iterations 18
Cbc0038I Pass 245: suminf. 1.54286 (8) obj. -6 iterations 21
Cbc0038I Pass 246: suminf. 1.54286 (8) obj. -6 iterations 17
Cbc0038I Pass 247: suminf. 16.59291 (76) obj. -5.59992 iterations 100
Cbc0038I Pass 248: suminf. 10.27601 (56) obj. -5.59992 iterations 47
Cbc0038I Pass 249: suminf. 8.83590 (51) obj. -5.59992 iterations 59
Cbc0038I Pass 250: suminf. 7.38966 (39) obj. -5.59992 iterations 20
Cbc0038I Pass 251: suminf. 10.63389 (60) obj. -5.59992 iterations 66
Cbc0038I No solution found this major pass
Cbc0038I Before mini branch and bound, 6 integers at bound fixed and 0 continuous
Cbc0038I Full problem 247 rows 196 columns, reduced to 243 rows 188 columns - 24 fixed gives 199, 114 - still too large
Cbc0038I Full problem 247 rows 196 columns, reduced to 188 rows 112 columns - too large
Cbc0038I Mini branch and bound did not improve solution (0.20 seconds)
Cbc0038I After 0.20 seconds - Feasibility pump exiting with objective of -4 - took 0.20 seconds
Cbc0012I Integer solution of -4 found by feasibility pump after 0 iterations and 0 nodes (0.20 seconds)
event(heuristicSolution) CbcModel.cpp:13363 % OBJ VAL RAW: -4 OBJ VAL ORIG(?): 4 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196
Preprocessed sol: 1:6 2:8 3:2 4:1 5:3 6:5 7:7 8:4 9:4 11:1 18:1 20:1 22:1 27:1 40:1 51:1 54:1 62:1 73:1 84:1 95:1 101:1 108:1 123:1 128:1 136:1 139:1 140:1 141:1 143:1 144:1 147:1 149:1 150:1 153:1 154:1 157:1 158:1 161:1 162:1 165:1 166:1 169:1 170:1 171:1 172:1 175:1 177:1 178:1 180:1 181:1 183:1 184:1 187:1 188:1 191:1 193:1 194:1
Postprocessed sol: 0:1.73684 1:2.73684 2:3.73684 3:1.69474 4:3 5:5 6:7 7:7.01053 8:4.08421 9:8 11:1 15:0.404211 16:0.45614 18:0.813333 19:0.4 20:1 22:0.4 23:0.526316 24:1 25:1 26:1 27:0.347368 28:0.435789 33:0.216842 37:0.564211 39:0.147368 42:0.288421 48:0.852632 53:0.147368 54:0.402632 56:0.347368 58:0.25 63:0.25 67:0.75 77:1 88:1 96:0.494737 98:0.505263 101:0.652632 107:0.347368 110:0.251462 111:0.748538 118:0.404211 120:0.329825 121:0.126316 124:0.0694737 125:0.74386 127:0.4 130:0.291579 131:0.108421 132:0.526316 134:0.798947 135:0.201053 136:0.492632 137:0.507368 138:1 141:1 142:1 143:0.251462 144:1 145:0.748538 146:1 149:1 150:0.826316 151:0.173684 153:1 154:0.168421 155:0.831579 156:0.665263 157:0.334737 158:1 159:0.404211 160:1 162:1 163:0.329825 164:1 165:0.126316 166:0.804211 167:0.195789 169:1 170:1 171:0.0694737 172:1 173:0.74386 174:1 176:1 177:0.4 179:1 180:1 182:1 183:0.291579 184:1 185:0.108421 186:1 187:0.526316 188:1 190:1 191:0.798947 192:1 193:0.201053 194:1 195:0.492632 196:1 197:0.507368
event(heuristicSolution) CbcModel.cpp:15660 % OBJ VAL RAW: -4 OBJ VAL ORIG(?): 4 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196
Preprocessed sol: 1:6 2:8 3:2 4:1 5:3 6:5 7:7 8:4 9:4 11:1 18:1 20:1 22:1 27:1 40:1 51:1 54:1 62:1 73:1 84:1 95:1 101:1 108:1 123:1 128:1 136:1 139:1 140:1 141:1 143:1 144:1 147:1 149:1 150:1 153:1 154:1 157:1 158:1 161:1 162:1 165:1 166:1 169:1 170:1 171:1 172:1 175:1 177:1 178:1 180:1 181:1 183:1 184:1 187:1 188:1 191:1 193:1 194:1
Postprocessed sol: 0:2 1:3 2:3.73684 3:1.5193 4:3 5:5 6:7 7:7.00351 8:3.74035 9:8 11:1 15:0.642495 16:0.4 18:0.631189 19:0.4 20:1 22:0.4 23:0.526316 24:1 25:1 26:1 27:0.259649 28:0.488421 33:0.25193 37:0.511579 39:0.147368 42:0.341053 48:0.852632 53:0.147368 54:0.490351 56:0.259649 58:0.25 63:0.25 67:0.75 77:1 88:1 92:0.0304094 96:0.407018 98:0.562573 101:0.709942 107:0.290058 110:0.222222 111:0.777778 118:0.642495 120:0.273684 121:0.126316 124:0.0519298 125:0.683119 127:0.4 130:0.325965 131:0.0740351 132:0.526316 134:0.799649 135:0.200351 136:0.526316 137:0.473684 138:0.973684 139:0.0263158 141:1 142:1 143:0.222222 144:1 145:0.777778 146:1 149:1 150:0.8 151:0.2 153:1 154:0.0925439 155:0.907456 156:0.725965 157:0.274035 158:1 159:0.642495 160:1 162:1 163:0.273684 164:1 165:0.126316 166:0.84807 167:0.15193 169:1 170:1 171:0.0519298 172:1 173:0.683119 174:1 176:1 177:0.4 179:1 180:1 182:1 183:0.325965 184:1 185:0.0740351 186:1 187:0.526316 188:1 190:1 191:0.799649 192:1 193:0.200351 194:1 195:0.526316 196:1 197:0.473684
Cbc0038I Full problem 247 rows 196 columns, reduced to 172 rows 92 columns - 19 fixed gives 110, 50 - ok now
event(solution) CbcModel.cpp:15719 % OBJ VAL RAW: -4 OBJ VAL ORIG(?): 4 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196
Preprocessed sol: 1:6 2:8 3:2 4:1 5:3 6:5 7:7 8:4 9:4 11:1 18:1 20:1 22:1 27:1 40:1 51:1 54:1 62:1 73:1 84:1 95:1 101:1 108:1 123:1 128:1 136:1 139:1 140:1 141:1 143:1 144:1 147:1 149:1 150:1 153:1 154:1 157:1 158:1 161:1 162:1 165:1 166:1 169:1 170:1 171:1 172:1 175:1 177:1 178:1 180:1 181:1 183:1 184:1 187:1 188:1 191:1 193:1 194:1
Postprocessed sol: 0:2.44421 1:3.44421 2:3.73684 3:1.22316 4:3 5:5 6:7 7:6.70737 8:3.44421 9:8 11:1 15:0.609591 16:0.350316 18:0.713778 19:0.4 20:1 22:0.4 23:0.526316 24:1 25:1 26:1 27:0.111579 28:0.577263 33:0.311158 37:0.422737 39:0.147368 42:0.429895 48:0.852632 53:0.147368 54:0.638421 56:0.111579 58:0.25 63:0.25 67:0.75 77:1 88:1 92:0.129123 96:0.258947 98:0.61193 101:0.759298 107:0.240702 110:0.172865 111:0.827135 118:0.609591 120:0.273684 121:0.126316 124:0.0223158 125:0.691462 127:0.4 130:0.355579 131:0.0444211 132:0.526316 134:0.829263 135:0.170737 136:0.526316 137:0.473684 138:0.929263 139:0.0707368 141:1 142:1 143:0.172865 144:1 145:0.827135 146:1 149:1 150:0.755579 151:0.244421 152:0.0555263 153:0.944474 155:1 156:0.8 157:0.2 158:1 159:0.609591 160:1 162:1 163:0.273684 164:1 165:0.126316 166:0.922105 167:0.0778947 169:1 170:1 171:0.0223158 172:1 173:0.691462 174:1 176:1 177:0.4 179:1 180:1 182:1 183:0.355579 184:1 185:0.0444211 186:1 187:0.526316 188:1 190:1 191:0.829263 192:1 193:0.170737 194:1 195:0.526316 196:1 197:0.473684
Cbc0031I 18 added rows had average density of 90.111111
Cbc0013I At root node, 18 cuts changed objective from -8 to -8 in 97 passes
Cbc0014I Cut generator 0 (Probing) - 423 row cuts average 2.3 elements, 0 column cuts (0 active) in 0.080 seconds - new frequency is -100
Cbc0014I Cut generator 1 (Gomory) - 1558 row cuts average 168.8 elements, 0 column cuts (0 active) in 0.396 seconds - new frequency is -100
Cbc0014I Cut generator 2 (Knapsack) - 6 row cuts average 3.3 elements, 0 column cuts (0 active) in 0.040 seconds - new frequency is -100
Cbc0014I Cut generator 3 (Clique) - 0 row cuts average 0.0 elements, 0 column cuts (0 active) in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 4 (MixedIntegerRounding2) - 17 row cuts average 7.5 elements, 0 column cuts (0 active) in 0.024 seconds - new frequency is -100
Cbc0014I Cut generator 5 (FlowCover) - 0 row cuts average 0.0 elements, 0 column cuts (0 active) in 0.036 seconds - new frequency is -100
Cbc0014I Cut generator 6 (TwoMirCuts) - 204 row cuts average 123.1 elements, 0 column cuts (0 active) in 0.036 seconds - new frequency is -100
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: -4 OBJ VAL ORIG(?): 4 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196
Preprocessed sol: 1:6 2:8 3:2 4:1 5:3 6:5 7:7 8:4 9:4 11:1 18:1 20:1 22:1 27:1 40:1 51:1 54:1 62:1 73:1 84:1 95:1 101:1 108:1 123:1 128:1 136:1 139:1 140:1 141:1 143:1 144:1 147:1 149:1 150:1 153:1 154:1 157:1 158:1 161:1 162:1 165:1 166:1 169:1 170:1 171:1 172:1 175:1 177:1 178:1 180:1 181:1 183:1 184:1 187:1 188:1 191:1 193:1 194:1
Postprocessed sol: 0:9 1:10 2:11 3:11 4:12 5:9 6:7 7:8 8:7 9:8 11:1 18:1 19:1 20:1 23:1 24:1 25:1 26:1 28:9 42:1 48:1 56:1 67:1 72:1 88:1 110:1 120:1 121:1 124:1 127:1 132:1 134:1 137:1 138:1 141:1 142:1 143:1 145:1 146:1 149:1 150:1 153:1 155:1 156:1 159:1 160:1 162:1 163:1 164:1 165:1 167:1 168:0.25 169:1 170:1 171:1 173:1 174:1 175:1 176:1 177:1 179:1 180:1 183:1 184:1 186:1 187:1 189:1 190:1 191:1 193:1 195:1 196:1 197:1
Cbc0010I After 0 nodes, 1 on tree, -4 best solution, best possible -8 (1.20 seconds)
Cbc0038I Full problem 247 rows 196 columns, reduced to 59 rows 31 columns
event(heuristicSolution) CbcModel.cpp:13363 event(solution) CbcModel.cpp:4568 Cbc0012I Integer solution of -6 found by RINS after 6647 iterations and 42 nodes (1.44 seconds)
event(heuristicSolution) CbcModel.cpp:13363 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: -6 OBJ VAL ORIG(?): 6 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196
Preprocessed sol: 0:2 1:8 2:5 3:6 4:3 5:7 7:1 8:4 9:6 11:1 12:1 15:1 20:1 24:1 26:1 29:1 42:1 48:1 58:1 64:1 77:1 79:1 89:1 101:1 108:1 111:1 116:1 132:1 136:1 139:1 140:1 141:1 143:1 145:1 146:1 147:1 149:1 150:1 153:1 154:1 156:1 157:1 159:1 161:1 162:1 165:1 166:1 169:1 170:1 172:1 175:1 177:1 178:1 181:1 182:1 184:1 187:1 188:1 189:1 191:1 192:1 195:1
Postprocessed sol: 0:2 1:8 2:5 3:6 4:3 5:7 7:1 8:4 9:8 11:1 12:1 15:1 19:2 20:1 24:1 26:1 29:1 44:1 50:1 60:1 66:1 79:1 81:1 91:1 103:1 110:1 113:1 118:1 134:1 138:1 141:1 142:1 143:1 145:1 147:1 148:1 149:1 151:1 152:1 155:1 156:1 158:1 159:1 161:1 163:1 164:1 167:1 168:1 171:1 172:1 173:1 174:1 175:1 177:1 179:1 180:1 183:1 184:1 186:1 189:1 190:1 191:1 193:1 194:1 197:1
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: -6 OBJ VAL ORIG(?): 6 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196
Preprocessed sol: 0:2 1:8 2:5 3:6 4:3 5:7 7:1 8:4 9:6 11:1 12:1 15:1 20:1 24:1 26:1 29:1 42:1 48:1 58:1 64:1 77:1 79:1 89:1 101:1 108:1 111:1 116:1 132:1 136:1 139:1 140:1 141:1 143:1 145:1 146:1 147:1 149:1 150:1 153:1 154:1 156:1 157:1 159:1 161:1 162:1 165:1 166:1 169:1 170:1 172:1 175:1 177:1 178:1 181:1 182:1 184:1 187:1 188:1 189:1 191:1 192:1 195:1
Postprocessed sol: 0:2 1:8 2:5 3:6 4:3 5:7 7:1 8:4 9:8 11:1 12:1 15:1 19:2 20:1 24:1 26:1 29:1 44:1 50:1 60:1 66:1 79:1 81:1 91:1 103:1 110:1 113:1 118:1 134:1 138:1 141:1 142:1 143:1 145:1 147:1 148:1 149:1 151:1 152:1 155:1 156:1 158:1 159:1 161:1 163:1 164:1 167:1 168:1 171:1 172:1 173:1 174:1 175:1 177:1 179:1 180:1 183:1 184:1 186:1 189:1 190:1 191:1 193:1 194:1 197:1
Cbc0016I Integer solution of -8 found by strong branching after 6843 iterations and 54 nodes (1.47 seconds)
event(solution) CbcModel.cpp:4568 % OBJ VAL RAW: -8 OBJ VAL ORIG(?): 8 % BND RAW: -8 BND ORIG(?): 8 orig NCols: 198 prepro NCols: 196
Preprocessed sol: 0:2 1:8 2:5 3:4 4:3 5:7 7:1 8:6 9:8 11:1 12:1 15:1 18:1 20:1 22:1 24:1 26:1 29:1 42:1 48:1 56:1 64:1 77:1 79:1 89:1 103:1 108:1 111:1 117:1 123:1 129:1 132:1 136:1 139:1 140:1 141:1 143:1 145:1 146:1 147:1 149:1 150:1 153:1 154:1 157:1 158:1 159:1 161:1 162:1 165:1 166:1 169:1 170:1 171:1 172:1 175:1 177:1 178:1 181:1 182:1 183:1 184:1 187:1 188:1 189:1 191:1 192:1 195:1
Postprocessed sol: 0:2 1:8 2:5 3:4 4:3 5:7 7:1 8:6 9:8 11:1 12:1 15:1 18:1 20:1 22:1 24:1 26:1 29:1 44:1 50:1 58:1 66:1 79:1 81:1 91:1 105:1 110:1 113:1 119:1 125:1 131:1 134:1 138:1 141:1 142:1 143:1 145:1 147:1 148:1 149:1 151:1 152:1 155:1 156:1 159:1 160:1 161:1 163:1 164:1 167:1 168:1 171:1 172:1 173:1 174:1 177:1 179:1 180:1 183:1 184:1 185:1 186:1 189:1 190:1 191:1 193:1 194:1 197:1
Cbc0001I Search completed - best objective -8, took 6843 iterations and 54 nodes (1.47 seconds)
Cbc0032I Strong branching done 910 times (9539 iterations), fathomed 14 nodes and fixed 24 variables
Cbc0035I Maximum depth 24, 0 variables fixed on reduced cost
Cuts at root node changed objective from -8 to -8
Probing was tried 97 times and created 423 cuts of which 0 were active after adding rounds of cuts (0.080 seconds)
Gomory was tried 97 times and created 1558 cuts of which 0 were active after adding rounds of cuts (0.396 seconds)
Knapsack was tried 97 times and created 6 cuts of which 0 were active after adding rounds of cuts (0.040 seconds)
Clique was tried 97 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 97 times and created 17 cuts of which 0 were active after adding rounds of cuts (0.024 seconds)
FlowCover was tried 97 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.036 seconds)
TwoMirCuts was tried 97 times and created 204 cuts of which 0 were active after adding rounds of cuts (0.036 seconds)
ImplicationCuts was tried 8 times and created 84 cuts of which 0 were active after adding rounds of cuts (0.004 seconds)
Result - Optimal solution found
Objective value: -8.00000000
Enumerated nodes: 54
Total iterations: 6843
Time (CPU seconds): 1.50
Time (Wallclock seconds): 1.52
Total time (CPU seconds): 1.50 (Wallclock seconds): 1.52
--------------------------------------
0 X_INTRODUCED_0 2.000000
1 X_INTRODUCED_1 8.000000
2 X_INTRODUCED_2 5.000000
3 X_INTRODUCED_3 4.000000
4 X_INTRODUCED_4 3.000000
5 X_INTRODUCED_5 7.000000
7 X_INTRODUCED_7 1.000000
8 X_INTRODUCED_8 6.000000
9 satisfies 8.000000
11 X_INTRODUCED_89 1.000000
12 X_INTRODUCED_90 1.000000
15 X_INTRODUCED_93 1.000000
18 X_INTRODUCED_96 1.000000
20 X_INTRODUCED_98 1.000000
22 X_INTRODUCED_100 1.000000
24 X_INTRODUCED_102 1.000000
26 X_INTRODUCED_104 1.000000
29 X_INTRODUCED_111 1.000000
44 X_INTRODUCED_154 1.000000
50 X_INTRODUCED_179 1.000000
58 X_INTRODUCED_206 1.000000
66 X_INTRODUCED_233 1.000000
79 X_INTRODUCED_265 1.000000
81 X_INTRODUCED_286 1.000000
91 X_INTRODUCED_315 1.000000
105 X_INTRODUCED_348 1.000000
110 X_INTRODUCED_392 1.000000
113 X_INTRODUCED_399 1.000000
119 X_INTRODUCED_417 1.000000
125 X_INTRODUCED_435 1.000000
131 X_INTRODUCED_457 1.000000
134 X_INTRODUCED_468 1.000000
138 X_INTRODUCED_488 1.000000
141 X_INTRODUCED_514 1.000000
142 X_INTRODUCED_529 1.000000
143 X_INTRODUCED_530 1.000000
145 X_INTRODUCED_547 1.000000
147 X_INTRODUCED_563 1.000000
148 X_INTRODUCED_579 1.000000
149 X_INTRODUCED_580 1.000000
151 X_INTRODUCED_597 1.000000
152 X_INTRODUCED_612 1.000000
155 X_INTRODUCED_629 1.000000
156 X_INTRODUCED_645 1.000000
159 X_INTRODUCED_662 1.000000
160 X_INTRODUCED_678 1.000000
161 X_INTRODUCED_679 1.000000
163 X_INTRODUCED_695 1.000000
164 X_INTRODUCED_710 1.000000
167 X_INTRODUCED_727 1.000000
168 X_INTRODUCED_742 1.000000
171 X_INTRODUCED_759 1.000000
172 X_INTRODUCED_774 1.000000
173 X_INTRODUCED_775 1.000000
174 X_INTRODUCED_790 1.000000
177 X_INTRODUCED_808 1.000000
179 X_INTRODUCED_824 1.000000
180 X_INTRODUCED_839 1.000000
183 X_INTRODUCED_856 1.000000
184 X_INTRODUCED_871 1.000000
185 X_INTRODUCED_872 1.000000
186 X_INTRODUCED_888 1.000000
189 X_INTRODUCED_905 1.000000
190 X_INTRODUCED_920 1.000000
191 X_INTRODUCED_921 1.000000
193 X_INTRODUCED_937 1.000000
194 X_INTRODUCED_952 1.000000
197 X_INTRODUCED_969 1.000000
--------------------------------------
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ff_cbc.mps.gz
Type: application/x-gzip
Size: 37184 bytes
Desc: not available
URL: <http://list.coin-or.org/pipermail/cbc/attachments/20160226/c2534099/attachment-0003.bin>
-------------- next part --------------
Coin0008I BLANK read with 0 errors
Welcome to the CBC MILP Solver
Version: 2.9
Build Date: Feb 23 2016
Revision Number: 2274
command line - driver4 -solve -quit (default strategy 1)
Continuous objective value is 0 - 0.01 seconds
Cgl0003I 4 fixed, 144 tightened bounds, 1044 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 44 tightened bounds, 0 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 1118 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 897 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 858 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 712 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 647 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 537 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 493 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 499 strengthened rows, 0 substitutions
Cgl0004I processed model has 1481 rows, 765 columns (765 integer (535 of which binary)) and 10536 elements
Cutoff increment increased from 1e-05 to 0.9999
Cbc0038I Initial state - 500 integers unsatisfied sum - 131.233
Cbc0038I Pass 1: suminf. 69.86191 (349) obj. 5831.64 iterations 564
Cbc0038I Pass 2: suminf. 31.60977 (346) obj. 5952.36 iterations 33
Cbc0038I Pass 3: suminf. 34.89443 (186) obj. 6070.82 iterations 54
Cbc0038I Pass 4: suminf. 46.90079 (224) obj. 6082.6 iterations 10
Cbc0038I Pass 5: suminf. 27.51213 (279) obj. 5897.08 iterations 54
Cbc0038I Pass 6: suminf. 7.78619 (109) obj. 5964.15 iterations 20
Cbc0038I Pass 7: suminf. 8.49306 (116) obj. 5993.13 iterations 79
Cbc0038I Pass 8: suminf. 8.34867 (212) obj. 6011.35 iterations 29
Cbc0038I Pass 9: suminf. 48.53509 (242) obj. 5533.87 iterations 78
Cbc0038I Pass 10: suminf. 25.64976 (224) obj. 5679.49 iterations 30
Cbc0038I Pass 11: suminf. 34.38931 (327) obj. 5873.82 iterations 58
Cbc0038I Pass 12: suminf. 101.99681 (322) obj. 6093.27 iterations 30
Cbc0038I Pass 13: suminf. 48.95345 (349) obj. 6168.94 iterations 42
Cbc0038I Pass 14: suminf. 8.95780 (154) obj. 6229.83 iterations 27
Cbc0038I Pass 15: suminf. 11.86836 (182) obj. 5981.01 iterations 74
Cbc0038I Pass 16: suminf. 37.93520 (258) obj. 6277.36 iterations 32
Cbc0038I Pass 17: suminf. 8.74656 (341) obj. 6157.57 iterations 39
Cbc0038I Pass 18: suminf. 13.06434 (143) obj. 6263.33 iterations 26
Cbc0038I Pass 19: suminf. 9.65279 (164) obj. 5639.3 iterations 82
Cbc0038I Pass 20: suminf. 50.06275 (327) obj. 6219.6 iterations 55
Cbc0038I Pass 21: suminf. 10.09882 (133) obj. 6264.33 iterations 13
Cbc0038I Pass 22: suminf. 9.78189 (136) obj. 6264.29 iterations 4
Cbc0038I Pass 23: suminf. 113.08153 (336) obj. 5680.19 iterations 73
Cbc0038I Pass 24: suminf. 10.38430 (138) obj. 6265.32 iterations 53
Cbc0038I Pass 25: suminf. 9.27923 (141) obj. 6265.28 iterations 4
Cbc0038I Pass 26: suminf. 114.80726 (339) obj. 5631.3 iterations 79
Cbc0038I Pass 27: suminf. 10.82005 (138) obj. 6190.33 iterations 54
Cbc0038I Pass 28: suminf. 10.09845 (133) obj. 6264.33 iterations 14
Cbc0038I Pass 29: suminf. 9.78152 (136) obj. 6264.29 iterations 3
Cbc0038I Pass 30: suminf. 4.91392 (137) obj. 6151.77 iterations 37
Cbc0038I No solution found this major pass
Cbc0038I Before mini branch and bound, 187 integers at bound fixed and 0 continuous
Cbc0038I Full problem 1481 rows 765 columns, reduced to 1404 rows 553 columns - too large
Cbc0038I Mini branch and bound did not improve solution (1.00 seconds)
Cbc0038I After 1.00 seconds - Feasibility pump exiting - took 0.20 seconds
Cbc0031I 98 added rows had average density of 14.571429
Cbc0013I At root node, 98 cuts changed objective from 0 to 0 in 10 passes
Cbc0014I Cut generator 0 (Probing) - 3924 row cuts average 2.3 elements, 0 column cuts (0 active) in 0.124 seconds - new frequency is 1
Cbc0014I Cut generator 1 (Gomory) - 178 row cuts average 150.8 elements, 0 column cuts (0 active) in 0.220 seconds - new frequency is 1
Cbc0014I Cut generator 2 (Knapsack) - 14 row cuts average 2.0 elements, 0 column cuts (0 active) in 0.028 seconds - new frequency is 1
Cbc0014I Cut generator 3 (Clique) - 0 row cuts average 0.0 elements, 0 column cuts (0 active) in 0.008 seconds - new frequency is -100
Cbc0014I Cut generator 4 (MixedIntegerRounding2) - 11 row cuts average 2.5 elements, 0 column cuts (0 active) in 0.008 seconds - new frequency is -100
Cbc0014I Cut generator 5 (FlowCover) - 62 row cuts average 2.0 elements, 0 column cuts (0 active) in 0.000 seconds - new frequency is 1
Cbc0014I Cut generator 6 (TwoMirCuts) - 406 row cuts average 153.7 elements, 0 column cuts (0 active) in 0.192 seconds - new frequency is -100
Cbc0010I After 0 nodes, 1 on tree, 1e+50 best solution, best possible 0 (3.40 seconds)
Cbc0004I Integer solution of 3802 found after 125474 iterations and 433 nodes (31.43 seconds)
event(solution) CbcModel.cpp:4568 % OBJ VAL RAW: 3802 OBJ VAL ORIG(?): -3802 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:30 2:106 3:1 4:108 5:1 6:116 7:1 8:51 10:85 11:1 12:87 13:1 14:95 15:1 16:21 18:115 19:1 20:117 21:1 22:125 23:1 24:50 26:86 27:1 28:88 29:1 30:96 31:1 32:36 34:100 35:1 36:102 37:1 38:110 39:1 40:38 42:98 43:1 44:100 45:1 46:108 47:1 48:28 50:108 51:1 52:110 53:1 54:118 55:1 56:19 58:117 59:1 60:119 61:1 62:127 63:1 64:188 66:52 68:50 70:42 72:10 74:126 75:1 76:128 77:1 78:136 79:1 80:362 82:226 84:224 86:216 88:290 90:154 92:152 94:144 96:87 98:49 99:1 100:51 101:1 102:59 103:1 104:92 106:44 107:1 108:46 109:1 110:54 111:1 112:80 114:56 115:1 116:58 117:1 118:66 119:1 120:12 122:124 123:1 124:126 125:1 126:134 127:1 128:149 130:13 132:11 134:3 136:4 138:132 139:1 140:134 141:1 142:142 143:1 144:142 146:6 148:4 150:4 151:1 152:361 154:225 156:223 158:215 160:55 162:81 163:1 164:83 165:1 166:91 167:1 168:64 170:72 171:1 172:74 173:1 174:82 175:1 176:85 178:51 179:1 180:53 181:1 182:61 183:1 184:7 186:129 187:1 188:131 189:1 190:139 191:1 192:269 194:133 196:131 198:123 200:270 202:134 204:132 206:124 208:75 210:61 211:1 212:63 213:1 214:71 215:1 216:45 218:91 219:1 220:93 221:1 222:101 223:1 224:91 226:45 227:1 228:47 229:1 230:55 231:1 232:129 234:7 235:1 236:9 237:1 238:17 239:1 240:132 242:4 243:1 244:6 245:1 246:14 247:1 248:79 250:57 251:1 252:59 253:1 254:67 255:1 256:375 258:239 260:237 262:229 264:48 266:88 267:1 268:90 269:1 270:98 271:1 272:6 274:130 275:1 276:132 277:1 278:140 279:1 280:2 282:134 283:1 284:136 285:144 286:26 288:110 289:1 290:112 291:1 292:120 293:1 294:24 296:112 297:1 298:114 299:1 300:122 301:1 302:228 304:92 306:90 308:82 310:37 312:99 313:1 314:101 315:1 316:109 317:1 318:425 319:289 320:287 321:279 323:136 324:138 325:146 326:136 329:1 330:2 331:1 332:10 333:1 334:138 336:2 339:1 340:8 341:1 342:146 344:10 346:8 349:1 350:143 352:7 354:5 356:3 357:1 358:30 359:1 363:51 364:1 368:21 369:1 373:50 374:1 378:36 379:1 383:38 384:1 388:28 389:1 393:19 394:1 398:42 402:1 403:10 404:1 408:216 412:1 413:144 417:1 418:49 420:1 423:44 425:1 428:56 430:1 433:12 434:1 438:3 442:1 443:4 444:1 448:4 452:1 453:215 457:1 458:55 459:1 463:64 464:1 468:51 470:1 473:7 474:1 478:123 482:1 483:124 487:1 488:61 490:1 493:45 494:1 498:45 500:1 503:7 505:1 508:4 510:1 513:57 515:1 518:229 522:1 523:48 524:1 528:6 529:1 533:2 534:1 538:26 539:1 543:24 544:1 548:82 552:1 553:37 554:1 558:279 562:1 564:1 570:1 576:1 582:1 583:3 587:1 588:1 663:1 708:1 754:1
Postprocessed sol: 0:6 1:142 2:143 3:152 4:30 6:106 7:1 8:107 9:1 10:116 11:1 12:51 14:85 15:1 16:86 17:1 18:95 19:1 20:21 22:115 23:1 24:116 25:1 26:125 27:1 28:50 30:86 31:1 32:87 33:1 34:96 35:1 36:36 38:100 39:1 40:101 41:1 42:110 43:1 44:38 46:98 47:1 48:99 49:1 50:108 51:1 52:28 54:108 55:1 56:109 57:1 58:118 59:1 60:19 62:117 63:1 64:118 65:1 66:127 67:1 68:188 70:52 72:51 74:42 76:10 78:126 79:1 80:127 81:1 82:136 83:1 84:362 86:226 88:225 90:216 92:290 94:154 96:153 98:144 100:87 102:49 103:1 104:50 105:1 106:59 107:1 108:92 110:44 111:1 112:45 113:1 114:54 115:1 116:80 118:56 119:1 120:57 121:1 122:66 123:1 124:12 126:124 127:1 128:125 129:1 130:134 131:1 132:149 134:13 136:12 138:3 140:4 142:132 143:1 144:133 145:1 146:142 147:1 148:142 150:6 152:5 154:4 155:1 156:361 158:225 160:224 162:215 164:55 166:81 167:1 168:82 169:1 170:91 171:1 172:64 174:72 175:1 176:73 177:1 178:82 179:1 180:85 182:51 183:1 184:52 185:1 186:61 187:1 188:7 190:129 191:1 192:130 193:1 194:139 195:1 196:269 198:133 200:132 202:123 204:270 206:134 208:133 210:124 212:75 214:61 215:1 216:62 217:1 218:71 219:1 220:45 222:91 223:1 224:92 225:1 226:101 227:1 228:91 230:45 231:1 232:46 233:1 234:55 235:1 236:129 238:7 239:1 240:8 241:1 242:17 243:1 244:132 246:4 247:1 248:5 249:1 250:14 251:1 252:79 254:57 255:1 256:58 257:1 258:67 259:1 260:375 262:239 264:238 266:229 268:48 270:88 271:1 272:89 273:1 274:98 275:1 276:6 278:130 279:1 280:131 281:1 282:140 283:1 284:2 286:134 287:1 288:135 289:1 290:144 291:1 292:26 294:110 295:1 296:111 297:1 298:120 299:1 300:24 302:112 303:1 304:113 305:1 306:122 307:1 308:228 310:92 312:91 314:82 316:37 318:99 319:1 320:100 321:1 322:109 323:1 324:425 325:289 326:288 327:279 329:1 330:136 331:1 332:137 333:1 334:146 335:1 336:136 339:1 340:1 341:1 342:10 343:1 344:138 346:2 348:1 350:8 351:1 352:146 354:10 356:9 359:1 360:143 362:7 364:6 366:3 367:1 368:3802 369:30 370:30 371:106 372:107 373:116 374:30 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:51 388:51 389:85 390:86 391:95 392:51 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:21 406:21 407:115 408:116 409:125 410:21 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:50 424:50 425:86 426:87 427:96 428:50 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:36 442:36 443:100 444:101 445:110 446:36 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:38 460:38 461:98 462:99 463:108 464:38 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:28 478:28 479:108 480:109 481:118 482:28 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:19 496:19 497:117 498:118 499:127 500:19 501:1 507:1 508:1 509:1 510:1 511:1 512:1 513:42 514:188 515:52 516:51 517:42 518:42 522:1 523:1 524:1 525:1 526:1 527:1 528:1 531:10 532:10 533:126 534:127 535:136 536:10 537:1 543:1 544:1 545:1 546:1 547:1 548:1 549:216 550:362 551:226 552:225 553:216 554:216 558:1 559:1 560:1 561:1 562:1 563:1 564:1 567:144 568:290 569:154 570:153 571:144 572:144 576:1 577:1 578:1 579:1 580:1 581:1 582:1 585:49 586:87 587:49 588:50 589:59 590:49 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:44 604:92 605:44 606:45 607:54 608:44 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:56 622:80 623:56 624:57 625:66 626:56 628:1 631:1 632:1 635:1 636:1 637:1 638:1 639:12 640:12 641:124 642:125 643:134 644:12 645:1 651:1 652:1 653:1 654:1 655:1 656:1 657:3 658:149 659:13 660:12 661:3 662:3 666:1 667:1 668:1 669:1 670:1 671:1 672:1 675:4 676:4 677:132 678:133 679:142 680:4 681:1 687:1 688:1 689:1 690:1 691:1 692:1 693:4 694:142 695:6 696:5 697:4 698:4 702:1 703:1 704:1 705:1 706:1 707:1 708:1 711:215 712:361 713:225 714:224 715:215 716:215 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:55 730:55 731:81 732:82 733:91 734:55 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:64 748:64 749:72 750:73 751:82 752:64 753:1 759:1 760:1 761:1 762:1 763:1 764:1 765:51 766:85 767:51 768:52 769:61 770:51 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:7 784:7 785:129 786:130 787:139 788:7 789:1 795:1 796:1 797:1 798:1 799:1 800:1 801:123 802:269 803:133 804:132 805:123 806:123 810:1 811:1 812:1 813:1 814:1 815:1 816:1 819:124 820:270 821:134 822:133 823:124 824:124 828:1 829:1 830:1 831:1 832:1 833:1 834:1 837:61 838:75 839:61 840:62 841:71 842:61 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:45 856:45 857:91 858:92 859:101 860:45 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:45 874:91 875:45 876:46 877:55 878:45 880:1 883:1 884:1 887:1 888:1 889:1 890:1 891:7 892:129 893:7 894:8 895:17 896:7 898:1 901:1 902:1 905:1 906:1 907:1 908:1 909:4 910:132 911:4 912:5 913:14 914:4 916:1 919:1 920:1 923:1 924:1 925:1 926:1 927:57 928:79 929:57 930:58 931:67 932:57 934:1 937:1 938:1 941:1 942:1 943:1 944:1 945:229 946:375 947:239 948:238 949:229 950:229 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:48 964:48 965:88 966:89 967:98 968:48 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:6 982:6 983:130 984:131 985:140 986:6 987:1 993:1 994:1 995:1 996:1 997:1 998:1 999:2 1000:2 1001:134 1002:135 1003:144 1004:2 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:26 1018:26 1019:110 1020:111 1021:120 1022:26 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:112 1038:113 1039:122 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1053:82 1054:228 1055:92 1056:91 1057:82 1058:82 1062:1 1063:1 1064:1 1065:1 1066:1 1067:1 1068:1 1071:37 1072:37 1073:99 1074:100 1075:109 1076:37 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:279 1090:425 1091:289 1092:288 1093:279 1094:279 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1109:136 1110:137 1111:146 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:136 1128:1 1129:10 1132:1 1135:1 1136:1 1139:1 1140:1 1141:1 1142:1 1144:138 1145:2 1146:1 1147:8 1150:0.993031 1151:0.00696864 1153:1 1154:1 1155:0.00696864 1156:0.00696864 1157:0.993031 1158:0.993031 1159:1 1160:1 1162:146 1163:10 1164:9 1170:1 1171:1 1172:1 1173:1 1174:1 1175:1 1176:1 1179:3 1180:143 1181:7 1182:6 1183:3 1184:3 1188:1 1189:1 1190:1 1191:1 1192:1 1193:1 1194:1 1197:1 1274:1 1320:0.5 1321:0.5 1370:1
Cbc0038I Full problem 1481 rows 765 columns, reduced to 4 rows 4 columns
Cbc0004I Integer solution of 3744 found after 125491 iterations and 437 nodes (31.49 seconds)
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 3744 OBJ VAL ORIG(?): -3744 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:30 2:102 3:1 4:108 5:1 6:116 7:1 8:51 10:81 11:1 12:87 13:1 14:95 15:1 16:21 18:111 19:1 20:117 21:1 22:125 23:1 24:50 26:82 27:1 28:88 29:1 30:96 31:1 32:36 34:96 35:1 36:102 37:1 38:110 39:1 40:38 42:94 43:1 44:100 45:1 46:108 47:1 48:28 50:104 51:1 52:110 53:1 54:118 55:1 56:19 58:113 59:1 60:119 61:1 62:127 63:1 64:188 66:56 68:50 70:42 72:10 74:122 75:1 76:128 77:1 78:136 79:1 80:362 82:230 84:224 86:216 88:290 90:158 92:152 94:144 96:87 98:45 99:1 100:51 101:1 102:59 103:1 104:92 106:40 107:1 108:46 109:1 110:54 111:1 112:80 114:52 115:1 116:58 117:1 118:66 119:1 120:12 122:120 123:1 124:126 125:1 126:134 127:1 128:149 130:17 132:11 134:3 136:4 138:128 139:1 140:134 141:1 142:142 143:1 144:142 146:10 148:4 150:4 151:1 152:361 154:229 156:223 158:215 160:55 162:77 163:1 164:83 165:1 166:91 167:1 168:64 170:68 171:1 172:74 173:1 174:82 175:1 176:85 178:47 179:1 180:53 181:1 182:61 183:1 184:7 186:125 187:1 188:131 189:1 190:139 191:1 192:269 194:137 196:131 198:123 200:270 202:138 204:132 206:124 208:75 210:57 211:1 212:63 213:1 214:71 215:1 216:45 218:87 219:1 220:93 221:1 222:101 223:1 224:91 226:41 227:1 228:47 229:1 230:55 231:1 232:129 234:3 235:1 236:9 237:1 238:17 239:1 240:132 243:1 244:6 245:1 246:14 247:1 248:79 250:53 251:1 252:59 253:1 254:67 255:1 256:375 258:243 260:237 262:229 264:48 266:84 267:1 268:90 269:1 270:98 271:1 272:6 274:126 275:1 276:132 277:1 278:140 279:1 280:2 282:130 283:1 284:136 285:144 286:26 288:106 289:1 290:112 291:1 292:120 293:1 294:24 296:108 297:1 298:114 299:1 300:122 301:1 302:228 304:96 306:90 308:82 310:37 312:95 313:1 314:101 315:1 316:109 317:1 318:425 319:293 320:287 321:279 323:132 324:138 325:146 326:136 328:4 330:2 331:1 332:10 333:1 334:138 336:6 339:1 340:8 341:1 342:146 344:14 346:8 349:1 350:143 352:11 354:5 356:3 357:1 358:30 359:1 363:51 364:1 368:21 369:1 373:50 374:1 378:36 379:1 383:38 384:1 388:28 389:1 393:19 394:1 398:42 402:1 403:10 404:1 408:216 412:1 413:144 417:1 418:45 420:1 423:40 425:1 428:52 430:1 433:12 434:1 438:3 442:1 443:4 444:1 448:4 452:1 453:215 457:1 458:55 459:1 463:64 464:1 468:47 470:1 473:7 474:1 478:123 482:1 483:124 487:1 488:57 490:1 493:45 494:1 498:41 500:1 503:3 505:1 510:1 513:53 515:1 518:229 522:1 523:48 524:1 528:6 529:1 533:2 534:1 538:26 539:1 543:24 544:1 548:82 552:1 553:37 554:1 558:279 562:1 564:1 568:2 571:1 576:1 582:1 583:3 587:1 588:1 662:1 708:1 754:1
Postprocessed sol: 0:6 1:138 2:142 3:152 4:30 6:102 7:1 8:106 9:1 10:116 11:1 12:51 14:81 15:1 16:85 17:1 18:95 19:1 20:21 22:111 23:1 24:115 25:1 26:125 27:1 28:50 30:82 31:1 32:86 33:1 34:96 35:1 36:36 38:96 39:1 40:100 41:1 42:110 43:1 44:38 46:94 47:1 48:98 49:1 50:108 51:1 52:28 54:104 55:1 56:108 57:1 58:118 59:1 60:19 62:113 63:1 64:117 65:1 66:127 67:1 68:188 70:56 72:52 74:42 76:10 78:122 79:1 80:126 81:1 82:136 83:1 84:362 86:230 88:226 90:216 92:290 94:158 96:154 98:144 100:87 102:45 103:1 104:49 105:1 106:59 107:1 108:92 110:40 111:1 112:44 113:1 114:54 115:1 116:80 118:52 119:1 120:56 121:1 122:66 123:1 124:12 126:120 127:1 128:124 129:1 130:134 131:1 132:149 134:17 136:13 138:3 140:4 142:128 143:1 144:132 145:1 146:142 147:1 148:142 150:10 152:6 154:4 155:1 156:361 158:229 160:225 162:215 164:55 166:77 167:1 168:81 169:1 170:91 171:1 172:64 174:68 175:1 176:72 177:1 178:82 179:1 180:85 182:47 183:1 184:51 185:1 186:61 187:1 188:7 190:125 191:1 192:129 193:1 194:139 195:1 196:269 198:137 200:133 202:123 204:270 206:138 208:134 210:124 212:75 214:57 215:1 216:61 217:1 218:71 219:1 220:45 222:87 223:1 224:91 225:1 226:101 227:1 228:91 230:41 231:1 232:45 233:1 234:55 235:1 236:129 238:3 239:1 240:7 241:1 242:17 243:1 244:132 247:1 248:4 249:1 250:14 251:1 252:79 254:53 255:1 256:57 257:1 258:67 259:1 260:375 262:243 264:239 266:229 268:48 270:84 271:1 272:88 273:1 274:98 275:1 276:6 278:126 279:1 280:130 281:1 282:140 283:1 284:2 286:130 287:1 288:134 289:1 290:144 291:1 292:26 294:106 295:1 296:110 297:1 298:120 299:1 300:24 302:108 303:1 304:112 305:1 306:122 307:1 308:228 310:96 312:92 314:82 316:37 318:95 319:1 320:99 321:1 322:109 323:1 324:425 325:293 326:289 327:279 329:1 330:132 331:1 332:136 333:1 334:146 335:1 336:136 338:4 341:1 342:10 343:1 344:138 346:6 348:2 350:8 351:1 352:146 354:14 356:10 359:1 360:143 362:11 364:7 366:3 367:1 368:3738 369:30 370:30 371:105.9 372:106.9 373:116 374:30 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:51 388:51 389:84.9 390:85.9 391:95 392:51 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:21 406:21 407:114.9 408:115.9 409:125 410:21 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:50 424:50 425:85.9 426:86.9 427:96 428:50 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:36 442:36 443:99.9 444:100.9 445:110 446:36 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:38 460:38 461:97.9 462:98.9 463:108 464:38 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:28 478:28 479:107.9 480:108.9 481:118 482:28 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:19 496:19 497:116.9 498:117.9 499:127 500:19 501:1 507:1 508:1 509:1 510:1 511:1 512:1 513:42 514:188 515:52.1 516:51.1 517:42 518:42 522:1 523:1 524:1 525:1 526:1 527:1 528:1 531:10 532:10 533:125.9 534:126.9 535:136 536:10 537:1 543:1 544:1 545:1 546:1 547:1 548:1 549:216 550:362 551:226.1 552:225.1 553:216 554:216 558:1 559:1 560:1 561:1 562:1 563:1 564:1 567:144 568:290 569:154.1 570:153.1 571:144 572:144 576:1 577:1 578:1 579:1 580:1 581:1 582:1 585:45 586:87 587:48.9 588:49.9 589:59 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:40 604:92 605:43.9 606:44.9 607:54 608:43.9 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:49 622:80 623:55.9 624:56.9 625:66 626:55.9 628:1 631:1 632:1 635:1 636:1 637:1 638:1 639:12 640:12 641:123.9 642:124.9 643:134 644:12 645:1 651:1 652:1 653:1 654:1 655:1 656:1 657:3 658:149 659:13.1 660:12.1 661:3 662:3 666:1 667:1 668:1 669:1 670:1 671:1 672:1 675:4 676:4 677:131.9 678:132.9 679:142 680:4 681:1 687:1 688:1 689:1 690:1 691:1 692:1 693:4 694:142 695:6.1 696:5.1 697:4 698:4 702:1 703:1 704:1 705:1 706:1 707:1 708:1 711:215 712:361 713:225.1 714:224.1 715:215 716:215 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:55 730:55 731:80.9 732:81.9 733:91 734:55 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:64 748:64 749:71.9 750:72.9 751:82 752:64 753:1 759:1 760:1 761:1 762:1 763:1 764:1 765:47 766:85 767:50.9 768:51.9 769:61 770:50.9 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:7 784:7 785:128.9 786:129.9 787:139 788:7 789:1 795:1 796:1 797:1 798:1 799:1 800:1 801:123 802:269 803:133.1 804:132.1 805:123 806:123 810:1 811:1 812:1 813:1 814:1 815:1 816:1 819:124 820:270 821:134.1 822:133.1 823:124 824:124 828:1 829:1 830:1 831:1 832:1 833:1 834:1 837:57 838:75 839:60.9 840:61.9 841:71 842:60.9 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:45 856:45 857:90.9 858:91.9 859:101 860:45 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:41 874:91 875:44.9 876:45.9 877:55 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 891:3 892:129 893:6.9 894:7.9 895:17 896:6.9 898:1 901:1 902:1 905:1 906:1 907:1 908:1 910:132 911:3.9 912:4.9 913:14 914:3.9 916:1 919:1 920:1 923:1 924:1 925:1 926:1 927:53 928:79 929:56.9 930:57.9 931:67 932:56.9 934:1 937:1 938:1 941:1 942:1 943:1 944:1 945:229 946:375 947:239.1 948:238.1 949:229 950:229 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:48 964:48 965:87.9 966:88.9 967:98 968:48 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:6 982:6 983:129.9 984:130.9 985:140 986:6 987:1 993:1 994:1 995:1 996:1 997:1 998:1 999:2 1000:2 1001:133.9 1002:134.9 1003:144 1004:2 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:26 1018:26 1019:109.9 1020:110.9 1021:120 1022:26 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:111.9 1038:112.9 1039:122 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1053:82 1054:228 1055:92.1 1056:91.1 1057:82 1058:82 1062:1 1063:1 1064:1 1065:1 1066:1 1067:1 1068:1 1071:37 1072:37 1073:98.9 1074:99.9 1075:109 1076:37 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:279 1090:425 1091:289.1 1092:288.1 1093:279 1094:279 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1109:135.9 1110:136.9 1111:146 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:136 1127:4 1128:0.9 1129:10 1133:1 1135:1 1136:1 1137:1 1138:0.1 1140:0.9 1141:1 1142:1 1143:2 1144:138 1145:2.1 1146:1.1 1147:8 1148:0.1 1151:1 1153:1 1154:1 1155:1 1156:1 1158:0.00348432 1159:1 1160:1 1162:146 1163:10.1 1164:9.1 1170:1 1171:1 1172:1 1173:1 1174:1 1175:1 1176:1 1179:3 1180:143 1181:7.1 1182:6.1 1183:3 1184:3 1188:1 1189:1 1190:1 1191:1 1192:1 1193:1 1194:1 1197:1 1274:1 1320:1 1370:1
Cbc0016I Integer solution of 2013 found by strong branching after 130255 iterations and 571 nodes (32.38 seconds)
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 2013 OBJ VAL ORIG(?): -2013 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:30 2:99 3:1 4:198 5:1 6:331 7:1 8:51 10:78 11:1 12:177 13:1 14:310 15:1 16:21 18:108 19:1 20:207 21:1 22:340 23:1 24:50 26:79 27:1 28:178 29:1 30:311 31:1 32:36 34:93 35:1 36:192 37:1 38:325 39:1 40:38 42:91 43:1 44:190 45:1 46:323 47:1 48:28 50:101 51:1 52:200 53:1 54:333 55:1 56:19 58:110 59:1 60:209 61:1 62:342 63:1 64:188 66:59 68:40 69:1 70:173 71:1 72:10 74:119 75:1 76:218 77:1 78:351 79:1 80:362 82:233 84:134 86:1 88:290 90:161 92:62 94:71 95:1 96:87 98:42 99:1 100:141 101:1 102:274 103:1 104:92 106:37 107:1 108:136 109:1 110:269 111:1 112:80 114:49 115:1 116:148 117:1 118:281 119:1 120:12 122:117 123:1 124:216 125:1 126:349 127:1 128:149 130:20 132:79 133:1 134:212 135:1 136:4 138:125 139:1 140:224 141:1 142:357 143:1 144:142 146:13 148:86 149:1 150:219 151:1 152:361 154:232 156:133 159:1 160:55 162:74 163:1 164:173 165:1 166:306 167:1 168:64 170:65 171:1 172:164 173:1 174:297 175:1 176:85 178:44 179:1 180:143 181:1 182:276 183:1 184:7 186:122 187:1 188:221 189:1 190:354 191:1 192:269 194:140 196:41 198:92 199:1 200:270 202:141 204:42 206:91 207:1 208:75 210:54 211:1 212:153 213:1 214:286 215:1 216:45 218:84 219:1 220:183 221:1 222:316 223:1 224:91 226:38 227:1 228:137 229:1 230:270 231:1 232:129 235:1 236:99 237:1 238:232 239:1 240:132 242:3 244:96 245:1 246:229 247:1 248:79 250:50 251:1 252:149 253:1 254:282 255:1 256:375 258:246 260:147 262:14 264:48 266:81 267:1 268:180 269:1 270:313 271:1 272:6 274:123 275:1 276:222 277:1 278:355 279:1 280:2 282:127 283:1 284:226 285:359 286:26 288:103 289:1 290:202 291:1 292:335 293:1 294:24 296:105 297:1 298:204 299:1 300:337 301:1 302:228 304:99 307:1 308:133 309:1 310:37 312:92 313:1 314:191 315:1 316:324 317:1 318:425 319:296 320:197 321:64 323:129 324:228 325:361 326:136 328:7 330:92 331:1 332:225 333:1 334:138 336:9 338:90 339:1 340:223 341:1 342:146 344:17 346:82 347:1 348:215 349:1 350:143 352:14 354:85 355:1 356:218 357:1 358:30 359:1 363:51 364:1 368:21 369:1 373:50 374:1 378:36 379:1 383:38 384:1 388:28 389:1 393:19 394:1 398:40 401:1 403:10 404:1 408:1 412:1 413:62 416:1 418:42 420:1 423:37 425:1 428:49 430:1 433:12 434:1 438:20 440:1 443:4 444:1 448:13 450:1 457:1 458:55 459:1 463:64 464:1 468:44 470:1 473:7 474:1 478:41 481:1 483:42 486:1 488:54 490:1 493:45 494:1 498:38 500:1 505:1 508:3 510:1 513:50 515:1 518:14 522:1 523:48 524:1 528:6 529:1 533:2 534:1 538:26 539:1 543:24 544:1 551:1 553:37 554:1 558:64 562:1 564:1 568:7 570:1 573:9 575:1 578:17 580:1 583:14 585:1 588:1 661:1 714:1 761:1
Postprocessed sol: 0:6 1:134 2:234 3:367 4:30 6:98 7:1 8:198 9:1 10:331 11:1 12:51 14:77 15:1 16:177 17:1 18:310 19:1 20:21 22:107 23:1 24:207 25:1 26:340 27:1 28:50 30:78 31:1 32:178 33:1 34:311 35:1 36:36 38:92 39:1 40:192 41:1 42:325 43:1 44:38 46:90 47:1 48:190 49:1 50:323 51:1 52:28 54:100 55:1 56:200 57:1 58:333 59:1 60:19 62:109 63:1 64:209 65:1 66:342 67:1 68:188 70:60 72:40 74:173 75:1 76:10 78:118 79:1 80:218 81:1 82:351 83:1 84:362 86:234 88:134 90:1 92:290 94:162 96:62 98:71 99:1 100:87 102:41 103:1 104:141 105:1 106:274 107:1 108:92 110:36 111:1 112:136 113:1 114:269 115:1 116:80 118:48 119:1 120:148 121:1 122:281 123:1 124:12 126:116 127:1 128:216 129:1 130:349 131:1 132:149 134:21 136:79 137:1 138:212 139:1 140:4 142:124 143:1 144:224 145:1 146:357 147:1 148:142 150:14 152:86 153:1 154:219 155:1 156:361 158:233 160:133 163:1 164:55 166:73 167:1 168:173 169:1 170:306 171:1 172:64 174:64 175:1 176:164 177:1 178:297 179:1 180:85 182:43 183:1 184:143 185:1 186:276 187:1 188:7 190:121 191:1 192:221 193:1 194:354 195:1 196:269 198:141 200:41 202:92 203:1 204:270 206:142 208:42 210:91 211:1 212:75 214:53 215:1 216:153 217:1 218:286 219:1 220:45 222:83 223:1 224:183 225:1 226:316 227:1 228:91 230:37 231:1 232:137 233:1 234:270 235:1 236:129 238:1 240:99 241:1 242:232 243:1 244:132 246:4 248:96 249:1 250:229 251:1 252:79 254:49 255:1 256:149 257:1 258:282 259:1 260:375 262:247 264:147 266:14 268:48 270:80 271:1 272:180 273:1 274:313 275:1 276:6 278:122 279:1 280:222 281:1 282:355 283:1 284:2 286:126 287:1 288:226 289:1 290:359 291:1 292:26 294:102 295:1 296:202 297:1 298:335 299:1 300:24 302:104 303:1 304:204 305:1 306:337 307:1 308:228 310:100 314:133 315:1 316:37 318:91 319:1 320:191 321:1 322:324 323:1 324:425 325:297 326:197 327:64 329:1 330:128 331:1 332:228 333:1 334:361 335:1 336:136 338:8 340:92 341:1 342:225 343:1 344:138 346:10 348:90 349:1 350:223 351:1 352:146 354:18 356:82 357:1 358:215 359:1 360:143 362:15 364:85 365:1 366:218 367:1 368:1950 369:30 370:30 371:105.9 372:107.1 373:116.1 374:30 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:51 388:51 389:84.9 390:86.1 391:95.1 392:51 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:21 406:21 407:114.9 408:116.1 409:125.1 410:21 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:50 424:50 425:85.9 426:87.1 427:96.1 428:50 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:36 442:36 443:99.9 444:101.1 445:110.1 446:36 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:38 460:38 461:97.9 462:99.1 463:108.1 464:38 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:28 478:28 479:107.9 480:109.1 481:118.1 482:28 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:19 496:19 497:116.9 498:118.1 499:127.1 500:19 501:1 507:1 508:1 509:1 510:1 511:1 512:1 513:40 514:188 515:52.1 516:50.9 517:42.1 518:41.9 521:1 523:1 524:1 525:1 526:1 528:0.9 529:1 530:0.1 531:10 532:10 533:125.9 534:127.1 535:136.1 536:10 537:1 543:1 544:1 545:1 546:1 547:1 548:1 549:1 550:362 551:226.1 552:224.9 553:215.9 554:215.9 558:1 559:1 560:1 561:1 562:1 563:1 564:1 567:42 568:290 569:154.1 570:152.9 571:143.9 572:143.9 576:1 577:1 578:1 579:1 580:1 581:1 582:1 585:41 586:87 587:48.9 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:36 604:92 605:43.9 606:45.1 607:54.1 608:43.9 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:48 622:80 623:55.9 624:57.1 625:66.1 626:55.9 628:1 631:1 632:1 635:1 636:1 637:1 638:1 639:12 640:12 641:123.9 642:125.1 643:134.1 644:12 645:1 651:1 652:1 653:1 654:1 655:1 656:1 657:21 658:149 659:13.1 660:12.1 661:212 662:3.1 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:4 676:4 677:131.9 678:133.1 679:142.1 680:4 681:1 687:1 688:1 689:1 690:1 691:1 692:1 693:14 694:142 695:6.1 696:5.1 697:219 698:4.1 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:361 713:225.1 714:223.9 715:214.9 716:214.9 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:55 730:55 731:80.9 732:82.1 733:91.1 734:55 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:64 748:64 749:71.9 750:73.1 751:82.1 752:64 753:1 759:1 760:1 761:1 762:1 763:1 764:1 765:43 766:85 767:50.9 768:52.1 769:61.1 770:50.9 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:7 784:7 785:128.9 786:130.1 787:139.1 788:7 789:1 795:1 796:1 797:1 798:1 799:1 800:1 801:21 802:269 803:133.1 804:131.9 805:122.9 806:122.9 810:1 811:1 812:1 813:1 814:1 815:1 816:1 819:42 820:270 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:53 838:75 839:60.9 840:62.1 841:71.1 842:60.9 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:45 856:45 857:90.9 858:92.1 859:101.1 860:45 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:37 874:91 875:44.9 876:46.1 877:55.1 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 891:1 892:129 893:6.9 894:8.1 895:17.1 896:6.9 898:1 901:1 902:1 905:1 906:1 907:1 908:1 909:4 910:132 911:4 912:5.1 913:14.1 914:4 916:1 919:1 920:1 923:1 924:1 925:1 926:1 927:49 928:79 929:56.9 930:58.1 931:67.1 932:56.9 934:1 937:1 938:1 941:1 942:1 943:1 944:1 945:14 946:375 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:48 964:48 965:87.9 966:89.1 967:98.1 968:48 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:6 982:6 983:129.9 984:131.1 985:140.1 986:6 987:1 993:1 994:1 995:1 996:1 997:1 998:1 999:2 1000:2 1001:133.9 1002:135.1 1003:144.1 1004:2 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:26 1018:26 1019:109.9 1020:111.1 1021:120.1 1022:26 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:111.9 1038:113.1 1039:122.1 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:228 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1061:1 1063:1 1064:1 1065:1 1066:1 1068:0.9 1069:1 1070:0.1 1071:37 1072:37 1073:98.9 1074:100.1 1075:109.1 1076:37 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:64 1090:425 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1109:135.9 1110:137.1 1111:146.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1125:8 1126:136 1127:8 1128:1.1 1129:10.1 1130:0.1 1132:1 1135:1 1136:1 1138:0.0273356 1139:1 1140:1 1141:1 1142:1 1143:10 1144:138 1145:2.1 1146:1.1 1147:8.1 1148:0.1 1150:1 1153:1 1154:1 1156:0.00696864 1157:1 1158:1 1159:1 1160:1 1161:18 1162:146 1163:10.1 1164:9.1 1165:215 1166:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1179:15 1180:143 1181:7.1 1182:6.1 1183:218 1184:3.1 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1197:1 1327:1 1377:1
Cbc0038I Full problem 1481 rows 765 columns, reduced to 209 rows 105 columns
event(heuristicSolution) CbcModel.cpp:13363 Cbc0012I Integer solution of 2009 found by RINS after 132880 iterations and 600 nodes (33.23 seconds)
event(heuristicSolution) CbcModel.cpp:13363 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 2009 OBJ VAL ORIG(?): -2009 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:30 2:99 3:1 4:198 5:1 6:332 7:1 8:51 10:78 11:1 12:177 13:1 14:311 15:1 16:21 18:108 19:1 20:207 21:1 22:341 23:1 24:50 26:79 27:1 28:178 29:1 30:312 31:1 32:36 34:93 35:1 36:192 37:1 38:326 39:1 40:38 42:91 43:1 44:190 45:1 46:324 47:1 48:28 50:101 51:1 52:200 53:1 54:334 55:1 56:19 58:110 59:1 60:209 61:1 62:343 63:1 64:188 66:59 68:40 69:1 70:174 71:1 72:10 74:119 75:1 76:218 77:1 78:352 79:1 80:362 82:233 84:134 87:1 88:290 90:161 92:62 94:72 95:1 96:87 98:42 99:1 100:141 101:1 102:275 103:1 104:92 106:37 107:1 108:136 109:1 110:270 111:1 112:80 114:49 115:1 116:148 117:1 118:282 119:1 120:12 122:117 123:1 124:216 125:1 126:350 127:1 128:149 130:20 132:79 133:1 134:213 135:1 136:4 138:125 139:1 140:224 141:1 142:358 143:1 144:142 146:13 148:86 149:1 150:220 151:1 152:361 154:232 156:133 158:1 159:1 160:55 162:74 163:1 164:173 165:1 166:307 167:1 168:64 170:65 171:1 172:164 173:1 174:298 175:1 176:85 178:44 179:1 180:143 181:1 182:277 183:1 184:7 186:122 187:1 188:221 189:1 190:355 191:1 192:269 194:140 196:41 198:93 199:1 200:270 202:141 204:42 206:92 207:1 208:75 210:54 211:1 212:153 213:1 214:287 215:1 216:45 218:84 219:1 220:183 221:1 222:317 223:1 224:91 226:38 227:1 228:137 229:1 230:271 231:1 232:129 235:1 236:99 237:1 238:233 239:1 240:132 242:3 244:96 245:1 246:230 247:1 248:79 250:50 251:1 252:149 253:1 254:283 255:1 256:375 258:246 260:147 262:13 264:48 266:81 267:1 268:180 269:1 270:314 271:1 272:6 274:123 275:1 276:222 277:1 278:356 279:1 280:2 282:127 283:1 284:226 285:360 286:26 288:103 289:1 290:202 291:1 292:336 293:1 294:24 296:105 297:1 298:204 299:1 300:338 301:1 302:228 304:99 307:1 308:134 309:1 310:37 312:92 313:1 314:191 315:1 316:325 317:1 318:425 319:296 320:197 321:63 323:129 324:228 325:362 326:136 328:7 330:92 331:1 332:226 333:1 334:138 336:9 338:90 339:1 340:224 341:1 342:146 344:17 346:82 347:1 348:216 349:1 350:143 352:14 354:85 355:1 356:219 357:1 358:30 359:1 363:51 364:1 368:21 369:1 373:50 374:1 378:36 379:1 383:38 384:1 388:28 389:1 393:19 394:1 398:40 401:1 403:10 404:1 412:1 413:62 416:1 418:42 420:1 423:37 425:1 428:49 430:1 433:12 434:1 438:20 440:1 443:4 444:1 448:13 450:1 453:1 457:1 458:55 459:1 463:64 464:1 468:44 470:1 473:7 474:1 478:41 481:1 483:42 486:1 488:54 490:1 493:45 494:1 498:38 500:1 505:1 508:3 510:1 513:50 515:1 518:13 522:1 523:48 524:1 528:6 529:1 533:2 534:1 538:26 539:1 543:24 544:1 551:1 553:37 554:1 558:63 562:1 564:1 568:7 570:1 573:9 575:1 578:17 580:1 583:14 585:1 588:1 661:1 714:1 762:1
Postprocessed sol: 0:6 1:135 2:234 3:368 4:30 6:99 7:1 8:198 9:1 10:332 11:1 12:51 14:78 15:1 16:177 17:1 18:311 19:1 20:21 22:108 23:1 24:207 25:1 26:341 27:1 28:50 30:79 31:1 32:178 33:1 34:312 35:1 36:36 38:93 39:1 40:192 41:1 42:326 43:1 44:38 46:91 47:1 48:190 49:1 50:324 51:1 52:28 54:101 55:1 56:200 57:1 58:334 59:1 60:19 62:110 63:1 64:209 65:1 66:343 67:1 68:188 70:59 72:40 74:174 75:1 76:10 78:119 79:1 80:218 81:1 82:352 83:1 84:362 86:233 88:134 92:290 94:161 96:62 98:72 99:1 100:87 102:42 103:1 104:141 105:1 106:275 107:1 108:92 110:37 111:1 112:136 113:1 114:270 115:1 116:80 118:49 119:1 120:148 121:1 122:282 123:1 124:12 126:117 127:1 128:216 129:1 130:350 131:1 132:149 134:20 136:79 137:1 138:213 139:1 140:4 142:125 143:1 144:224 145:1 146:358 147:1 148:142 150:13 152:86 153:1 154:220 155:1 156:361 158:232 160:133 163:1 164:55 166:74 167:1 168:173 169:1 170:307 171:1 172:64 174:65 175:1 176:164 177:1 178:298 179:1 180:85 182:44 183:1 184:143 185:1 186:277 187:1 188:7 190:122 191:1 192:221 193:1 194:355 195:1 196:269 198:140 200:41 202:93 203:1 204:270 206:141 208:42 210:92 211:1 212:75 214:54 215:1 216:153 217:1 218:287 219:1 220:45 222:84 223:1 224:183 225:1 226:317 227:1 228:91 230:38 231:1 232:137 233:1 234:271 235:1 236:129 239:1 240:99 241:1 242:233 243:1 244:132 246:3 248:96 249:1 250:230 251:1 252:79 254:50 255:1 256:149 257:1 258:283 259:1 260:375 262:246 264:147 266:13 268:48 270:81 271:1 272:180 273:1 274:314 275:1 276:6 278:123 279:1 280:222 281:1 282:356 283:1 284:2 286:127 287:1 288:226 289:1 290:360 291:1 292:26 294:103 295:1 296:202 297:1 298:336 299:1 300:24 302:105 303:1 304:204 305:1 306:338 307:1 308:228 310:99 314:134 315:1 316:37 318:92 319:1 320:191 321:1 322:325 323:1 324:425 325:296 326:197 327:63 329:1 330:129 331:1 332:228 333:1 334:362 335:1 336:136 338:7 340:92 341:1 342:226 343:1 344:138 346:9 348:90 349:1 350:224 351:1 352:146 354:17 356:82 357:1 358:216 359:1 360:143 362:14 364:85 365:1 366:219 367:1 368:1702 369:30 370:30 371:105.9 372:107.1 373:116.1 374:30 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:51 388:51 389:84.9 390:86.1 391:95.1 392:51 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:21 406:21 407:114.9 408:116.1 409:125.1 410:21 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:50 424:50 425:85.9 426:87.1 427:96.1 428:50 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:36 442:36 443:99.9 444:101.1 445:110.1 446:36 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:38 460:38 461:97.9 462:99.1 463:108.1 464:38 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:28 478:28 479:107.9 480:109.1 481:118.1 482:28 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:19 496:19 497:116.9 498:118.1 499:127.1 500:19 501:1 507:1 508:1 509:1 510:1 511:1 512:1 514:188 515:52.1 516:50.9 517:42.1 518:41.9 521:1 523:1 524:1 525:1 526:1 528:0.9 529:1 530:0.1 531:10 532:10 533:125.9 534:127.1 535:136.1 536:10 537:1 543:1 544:1 545:1 546:1 547:1 548:1 550:362 551:226.1 552:224.9 553:215.9 554:215.9 558:1 559:1 560:1 561:1 562:1 563:1 564:1 568:290 569:154.1 570:152.9 571:143.9 572:143.9 576:1 577:1 578:1 579:1 580:1 581:1 582:1 585:42 586:87 587:48.9 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:37 604:92 605:43.9 606:45.1 607:54.1 608:43.9 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:49 622:80 623:55.9 624:57.1 625:66.1 626:55.9 628:1 631:1 632:1 635:1 636:1 637:1 638:1 639:12 640:12 641:123.9 642:125.1 643:134.1 644:12 645:1 651:1 652:1 653:1 654:1 655:1 656:1 657:21 658:149 659:13.1 660:12.1 661:213 662:3.1 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:4 676:4 677:131.9 678:133.1 679:142.1 680:4 681:1 687:1 688:1 689:1 690:1 691:1 692:1 693:13 694:142 695:6.1 696:5.1 697:220 698:4.1 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:361 713:225.1 714:223.9 715:214.9 716:214.9 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:55 730:55 731:80.9 732:82.1 733:91.1 734:55 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:64 748:64 749:71.9 750:73.1 751:82.1 752:64 753:1 759:1 760:1 761:1 762:1 763:1 764:1 765:44 766:85 767:50.9 768:52.1 769:61.1 770:50.9 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:7 784:7 785:128.9 786:130.1 787:139.1 788:7 789:1 795:1 796:1 797:1 798:1 799:1 800:1 801:21 802:269 803:133.1 804:131.9 805:122.9 806:122.9 810:1 811:1 812:1 813:1 814:1 815:1 816:1 820:270 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:53 838:75 839:60.9 840:62.1 841:71.1 842:60.9 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:45 856:45 857:90.9 858:92.1 859:101.1 860:45 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:38 874:91 875:44.9 876:46.1 877:55.1 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 892:129 893:6.9 894:8.1 895:17.1 896:6.9 898:1 901:1 902:1 905:1 906:1 907:1 908:1 910:132 911:3.9 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 923:1 924:1 925:1 926:1 927:50 928:79 929:56.9 930:58.1 931:67.1 932:56.9 934:1 937:1 938:1 941:1 942:1 943:1 944:1 945:13 946:375 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:48 964:48 965:87.9 966:89.1 967:98.1 968:48 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:6 982:6 983:129.9 984:131.1 985:140.1 986:6 987:1 993:1 994:1 995:1 996:1 997:1 998:1 999:2 1000:2 1001:133.9 1002:135.1 1003:144.1 1004:2 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:26 1018:26 1019:109.9 1020:111.1 1021:120.1 1022:26 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:111.9 1038:113.1 1039:122.1 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:228 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1061:1 1063:1 1064:1 1065:1 1066:1 1068:0.9 1069:1 1070:0.1 1071:37 1072:37 1073:98.9 1074:100.1 1075:109.1 1076:37 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:63 1090:425 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1109:135.9 1110:137.1 1111:146.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:136 1127:7 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1138:0.0242215 1139:1 1140:1 1141:1 1142:1 1143:10 1144:138 1145:2.1 1146:1.1 1147:8.1 1148:0.1 1150:1 1153:1 1154:1 1156:0.00696864 1157:1 1158:1 1159:1 1160:1 1162:146 1163:10.1 1164:9.1 1165:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1180:143 1181:7.1 1182:6.1 1183:3.1 1184:2.9 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1197:1 1272:1 1327:1 1378:1
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 2009 OBJ VAL ORIG(?): -2009 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:30 2:99 3:1 4:198 5:1 6:332 7:1 8:51 10:78 11:1 12:177 13:1 14:311 15:1 16:21 18:108 19:1 20:207 21:1 22:341 23:1 24:50 26:79 27:1 28:178 29:1 30:312 31:1 32:36 34:93 35:1 36:192 37:1 38:326 39:1 40:38 42:91 43:1 44:190 45:1 46:324 47:1 48:28 50:101 51:1 52:200 53:1 54:334 55:1 56:19 58:110 59:1 60:209 61:1 62:343 63:1 64:188 66:59 68:40 69:1 70:174 71:1 72:10 74:119 75:1 76:218 77:1 78:352 79:1 80:362 82:233 84:134 87:1 88:290 90:161 92:62 94:72 95:1 96:87 98:42 99:1 100:141 101:1 102:275 103:1 104:92 106:37 107:1 108:136 109:1 110:270 111:1 112:80 114:49 115:1 116:148 117:1 118:282 119:1 120:12 122:117 123:1 124:216 125:1 126:350 127:1 128:149 130:20 132:79 133:1 134:213 135:1 136:4 138:125 139:1 140:224 141:1 142:358 143:1 144:142 146:13 148:86 149:1 150:220 151:1 152:361 154:232 156:133 158:1 159:1 160:55 162:74 163:1 164:173 165:1 166:307 167:1 168:64 170:65 171:1 172:164 173:1 174:298 175:1 176:85 178:44 179:1 180:143 181:1 182:277 183:1 184:7 186:122 187:1 188:221 189:1 190:355 191:1 192:269 194:140 196:41 198:93 199:1 200:270 202:141 204:42 206:92 207:1 208:75 210:54 211:1 212:153 213:1 214:287 215:1 216:45 218:84 219:1 220:183 221:1 222:317 223:1 224:91 226:38 227:1 228:137 229:1 230:271 231:1 232:129 235:1 236:99 237:1 238:233 239:1 240:132 242:3 244:96 245:1 246:230 247:1 248:79 250:50 251:1 252:149 253:1 254:283 255:1 256:375 258:246 260:147 262:13 264:48 266:81 267:1 268:180 269:1 270:314 271:1 272:6 274:123 275:1 276:222 277:1 278:356 279:1 280:2 282:127 283:1 284:226 285:360 286:26 288:103 289:1 290:202 291:1 292:336 293:1 294:24 296:105 297:1 298:204 299:1 300:338 301:1 302:228 304:99 307:1 308:134 309:1 310:37 312:92 313:1 314:191 315:1 316:325 317:1 318:425 319:296 320:197 321:63 323:129 324:228 325:362 326:136 328:7 330:92 331:1 332:226 333:1 334:138 336:9 338:90 339:1 340:224 341:1 342:146 344:17 346:82 347:1 348:216 349:1 350:143 352:14 354:85 355:1 356:219 357:1 358:30 359:1 363:51 364:1 368:21 369:1 373:50 374:1 378:36 379:1 383:38 384:1 388:28 389:1 393:19 394:1 398:40 401:1 403:10 404:1 412:1 413:62 416:1 418:42 420:1 423:37 425:1 428:49 430:1 433:12 434:1 438:20 440:1 443:4 444:1 448:13 450:1 453:1 457:1 458:55 459:1 463:64 464:1 468:44 470:1 473:7 474:1 478:41 481:1 483:42 486:1 488:54 490:1 493:45 494:1 498:38 500:1 505:1 508:3 510:1 513:50 515:1 518:13 522:1 523:48 524:1 528:6 529:1 533:2 534:1 538:26 539:1 543:24 544:1 551:1 553:37 554:1 558:63 562:1 564:1 568:7 570:1 573:9 575:1 578:17 580:1 583:14 585:1 588:1 661:1 714:1 762:1
Postprocessed sol: 0:6 1:134 2:234 3:368 4:30 6:98 7:1 8:198 9:1 10:332 11:1 12:51 14:77 15:1 16:177 17:1 18:311 19:1 20:21 22:107 23:1 24:207 25:1 26:341 27:1 28:50 30:78 31:1 32:178 33:1 34:312 35:1 36:36 38:92 39:1 40:192 41:1 42:326 43:1 44:38 46:90 47:1 48:190 49:1 50:324 51:1 52:28 54:100 55:1 56:200 57:1 58:334 59:1 60:19 62:109 63:1 64:209 65:1 66:343 67:1 68:188 70:60 72:40 74:174 75:1 76:10 78:118 79:1 80:218 81:1 82:352 83:1 84:362 86:234 88:134 92:290 94:162 96:62 98:72 99:1 100:87 102:41 103:1 104:141 105:1 106:275 107:1 108:92 110:36 111:1 112:136 113:1 114:270 115:1 116:80 118:48 119:1 120:148 121:1 122:282 123:1 124:12 126:116 127:1 128:216 129:1 130:350 131:1 132:149 134:21 136:79 137:1 138:213 139:1 140:4 142:124 143:1 144:224 145:1 146:358 147:1 148:142 150:14 152:86 153:1 154:220 155:1 156:361 158:233 160:133 162:1 163:1 164:55 166:73 167:1 168:173 169:1 170:307 171:1 172:64 174:64 175:1 176:164 177:1 178:298 179:1 180:85 182:43 183:1 184:143 185:1 186:277 187:1 188:7 190:121 191:1 192:221 193:1 194:355 195:1 196:269 198:141 200:41 202:93 203:1 204:270 206:142 208:42 210:92 211:1 212:75 214:53 215:1 216:153 217:1 218:287 219:1 220:45 222:83 223:1 224:183 225:1 226:317 227:1 228:91 230:37 231:1 232:137 233:1 234:271 235:1 236:129 238:1 240:99 241:1 242:233 243:1 244:132 246:4 248:96 249:1 250:230 251:1 252:79 254:49 255:1 256:149 257:1 258:283 259:1 260:375 262:247 264:147 266:13 268:48 270:80 271:1 272:180 273:1 274:314 275:1 276:6 278:122 279:1 280:222 281:1 282:356 283:1 284:2 286:126 287:1 288:226 289:1 290:360 291:1 292:26 294:102 295:1 296:202 297:1 298:336 299:1 300:24 302:104 303:1 304:204 305:1 306:338 307:1 308:228 310:100 314:134 315:1 316:37 318:91 319:1 320:191 321:1 322:325 323:1 324:425 325:297 326:197 327:63 329:1 330:128 331:1 332:228 333:1 334:362 335:1 336:136 338:8 340:92 341:1 342:226 343:1 344:138 346:10 348:90 349:1 350:224 351:1 352:146 354:18 356:82 357:1 358:216 359:1 360:143 362:15 364:85 365:1 366:219 367:1 368:1556 369:30 370:30 371:105.9 372:107.1 373:116.1 374:30 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:51 388:51 389:84.9 390:86.1 391:95.1 392:51 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:21 406:21 407:114.9 408:116.1 409:125.1 410:21 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:50 424:50 425:85.9 426:87.1 427:96.1 428:50 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:36 442:36 443:99.9 444:101.1 445:110.1 446:36 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:38 460:38 461:97.9 462:99.1 463:108.1 464:38 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:28 478:28 479:107.9 480:109.1 481:118.1 482:28 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:19 496:19 497:116.9 498:118.1 499:127.1 500:19 501:1 507:1 508:1 509:1 510:1 511:1 512:1 514:188 515:52.1 516:50.9 517:42.1 518:41.9 521:1 523:1 524:1 525:1 526:1 528:0.9 529:1 530:0.1 531:10 532:10 533:125.9 534:127.1 535:136.1 536:10 537:1 543:1 544:1 545:1 546:1 547:1 548:1 550:362 551:226.1 552:224.9 553:215.9 554:215.9 558:1 559:1 560:1 561:1 562:1 563:1 564:1 568:290 569:154.1 570:152.9 571:143.9 572:143.9 576:1 577:1 578:1 579:1 580:1 581:1 582:1 585:41 586:87 587:48.9 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:36 604:92 605:43.9 606:45.1 607:54.1 608:43.9 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:48 622:80 623:55.9 624:57.1 625:66.1 626:55.9 628:1 631:1 632:1 635:1 636:1 637:1 638:1 639:12 640:12 641:123.9 642:125.1 643:134.1 644:12 645:1 651:1 652:1 653:1 654:1 655:1 656:1 658:149 659:13.1 660:12.1 661:3.1 662:2.9 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:4 676:4 677:131.9 678:133.1 679:142.1 680:4 681:1 687:1 688:1 689:1 690:1 691:1 692:1 693:14 694:142 695:6.1 696:5.1 697:220 698:4.1 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:361 713:225.1 714:223.9 715:214.9 716:214.9 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:55 730:55 731:80.9 732:82.1 733:91.1 734:55 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:64 748:64 749:71.9 750:73.1 751:82.1 752:64 753:1 759:1 760:1 761:1 762:1 763:1 764:1 765:43 766:85 767:50.9 768:52.1 769:61.1 770:50.9 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:7 784:7 785:128.9 786:130.1 787:139.1 788:7 789:1 795:1 796:1 797:1 798:1 799:1 800:1 802:269 803:133.1 804:131.9 805:122.9 806:122.9 810:1 811:1 812:1 813:1 814:1 815:1 816:1 820:270 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:21 838:75 839:60.9 840:62.1 841:71.1 842:60.9 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:45 856:45 857:90.9 858:92.1 859:101.1 860:45 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:37 874:91 875:44.9 876:46.1 877:55.1 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 892:129 893:6.9 894:8.1 895:17.1 896:6.9 898:1 901:1 902:1 905:1 906:1 907:1 908:1 910:132 911:4 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.000341297 923:1 924:1 925:1 926:1 927:49 928:79 929:56.9 930:58.1 931:67.1 932:56.9 934:1 937:1 938:1 941:1 942:1 943:1 944:1 945:13 946:375 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:48 964:48 965:87.9 966:89.1 967:98.1 968:48 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:6 982:6 983:129.9 984:131.1 985:140.1 986:6 987:1 993:1 994:1 995:1 996:1 997:1 998:1 999:2 1000:2 1001:133.9 1002:135.1 1003:144.1 1004:2 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:26 1018:26 1019:109.9 1020:111.1 1021:120.1 1022:26 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:111.9 1038:113.1 1039:122.1 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:228 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1061:1 1063:1 1064:1 1065:1 1066:1 1068:0.9 1069:1 1070:0.1 1071:37 1072:37 1073:98.9 1074:100.1 1075:109.1 1076:37 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:63 1090:425 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1109:135.9 1110:137.1 1111:146.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:136 1127:8 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1138:0.0276817 1139:1 1140:1 1141:1 1142:1 1144:138 1145:2.1 1146:1.1 1147:8.1 1150:1 1153:1 1154:1 1156:0.00731707 1157:1 1158:1 1159:1 1160:1 1162:146 1163:10.1 1164:9.1 1165:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1180:143 1181:7.1 1182:6.1 1183:3.1 1184:2.9 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1197:1 1327:1 1378:1
Cbc0004I Integer solution of 1983 found after 134853 iterations and 653 nodes (33.64 seconds)
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1983 OBJ VAL ORIG(?): -1983 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:30 2:99 3:1 4:198 5:1 6:345 7:1 8:51 10:78 11:1 12:177 13:1 14:324 15:1 16:21 18:108 19:1 20:207 21:1 22:354 23:1 24:50 26:79 27:1 28:178 29:1 30:325 31:1 32:36 34:93 35:1 36:192 37:1 38:339 39:1 40:38 42:91 43:1 44:190 45:1 46:337 47:1 48:28 50:101 51:1 52:200 53:1 54:347 55:1 56:19 58:110 59:1 60:209 61:1 62:356 63:1 64:188 66:59 68:40 69:1 70:187 71:1 72:10 74:119 75:1 76:218 77:1 78:365 79:1 80:362 82:233 84:134 86:13 87:1 88:290 90:161 92:62 94:85 95:1 96:87 98:42 99:1 100:141 101:1 102:288 103:1 104:92 106:37 107:1 108:136 109:1 110:283 111:1 112:80 114:49 115:1 116:148 117:1 118:295 119:1 120:12 122:117 123:1 124:216 125:1 126:363 127:1 128:149 130:20 132:79 133:1 134:226 135:1 136:4 138:125 139:1 140:224 141:1 142:371 143:1 144:142 146:13 148:86 149:1 150:233 151:1 152:361 154:232 156:133 158:14 159:1 160:55 162:74 163:1 164:173 165:1 166:320 167:1 168:64 170:65 171:1 172:164 173:1 174:311 175:1 176:85 178:44 179:1 180:143 181:1 182:290 183:1 184:7 186:122 187:1 188:221 189:1 190:368 191:1 192:269 194:140 196:41 198:106 199:1 200:270 202:141 204:42 206:105 207:1 208:75 210:54 211:1 212:153 213:1 214:300 215:1 216:45 218:84 219:1 220:183 221:1 222:330 223:1 224:91 226:38 227:1 228:137 229:1 230:284 231:1 232:129 235:1 236:99 237:1 238:246 239:1 240:132 242:3 244:96 245:1 246:243 247:1 248:79 250:50 251:1 252:149 253:1 254:296 255:1 256:375 258:246 260:147 263:1 264:48 266:81 267:1 268:180 269:1 270:327 271:1 272:6 274:123 275:1 276:222 277:1 278:369 279:1 280:2 282:127 283:1 284:226 285:373 286:26 288:103 289:1 290:202 291:1 292:349 293:1 294:24 296:105 297:1 298:204 299:1 300:351 301:1 302:228 304:99 307:1 308:147 309:1 310:37 312:92 313:1 314:191 315:1 316:338 317:1 318:425 319:296 320:197 321:50 323:129 324:228 325:375 326:136 328:7 330:92 331:1 332:239 333:1 334:138 336:9 338:90 339:1 340:237 341:1 342:146 344:17 346:82 347:1 348:229 349:1 350:143 352:14 354:85 355:1 356:232 357:1 358:30 359:1 363:51 364:1 368:21 369:1 373:50 374:1 378:36 379:1 383:38 384:1 388:28 389:1 393:19 394:1 398:40 401:1 403:10 404:1 408:13 412:1 413:62 416:1 418:42 420:1 423:37 425:1 428:49 430:1 433:12 434:1 438:20 440:1 443:4 444:1 448:13 450:1 453:14 457:1 458:55 459:1 463:64 464:1 468:44 470:1 473:7 474:1 478:41 481:1 483:42 486:1 488:54 490:1 493:45 494:1 498:38 500:1 505:1 508:3 510:1 513:50 515:1 522:1 523:48 524:1 528:6 529:1 533:2 534:1 538:26 539:1 543:24 544:1 551:1 553:37 554:1 558:50 562:1 564:1 568:7 570:1 573:9 575:1 578:17 580:1 583:14 585:1 588:1 661:1 714:1 763:1
Postprocessed sol: 0:6 1:134 2:234 3:381 4:30 6:98 7:1 8:198 9:1 10:345 11:1 12:51 14:77 15:1 16:177 17:1 18:324 19:1 20:21 22:107 23:1 24:207 25:1 26:354 27:1 28:50 30:78 31:1 32:178 33:1 34:325 35:1 36:36 38:92 39:1 40:192 41:1 42:339 43:1 44:38 46:90 47:1 48:190 49:1 50:337 51:1 52:28 54:100 55:1 56:200 57:1 58:347 59:1 60:19 62:109 63:1 64:209 65:1 66:356 67:1 68:188 70:60 72:40 73:1 74:187 75:1 76:10 78:118 79:1 80:218 81:1 82:365 83:1 84:362 86:234 88:134 90:13 92:290 94:162 96:62 98:85 99:1 100:87 102:41 103:1 104:141 105:1 106:288 107:1 108:92 110:36 111:1 112:136 113:1 114:283 115:1 116:80 118:48 119:1 120:148 121:1 122:295 123:1 124:12 126:116 127:1 128:216 129:1 130:363 131:1 132:149 134:21 136:79 137:1 138:226 139:1 140:4 142:124 143:1 144:224 145:1 146:371 147:1 148:142 150:14 152:86 153:1 154:233 155:1 156:361 158:233 160:133 162:14 163:1 164:55 166:73 167:1 168:173 169:1 170:320 171:1 172:64 174:64 175:1 176:164 177:1 178:311 179:1 180:85 182:43 183:1 184:143 185:1 186:290 187:1 188:7 190:121 191:1 192:221 193:1 194:368 195:1 196:269 198:141 200:41 202:106 203:1 204:270 206:142 208:42 210:105 211:1 212:75 214:53 215:1 216:153 217:1 218:300 219:1 220:45 222:83 223:1 224:183 225:1 226:330 227:1 228:91 230:37 231:1 232:137 233:1 234:284 235:1 236:129 238:1 240:99 241:1 242:246 243:1 244:132 246:4 248:96 249:1 250:243 251:1 252:79 254:49 255:1 256:149 257:1 258:296 259:1 260:375 262:247 264:147 268:48 270:80 271:1 272:180 273:1 274:327 275:1 276:6 278:122 279:1 280:222 281:1 282:369 283:1 284:2 286:126 287:1 288:226 289:1 290:373 291:1 292:26 294:102 295:1 296:202 297:1 298:349 299:1 300:24 302:104 303:1 304:204 305:1 306:351 307:1 308:228 310:100 313:1 314:147 315:1 316:37 318:91 319:1 320:191 321:1 322:338 323:1 324:425 325:297 326:197 327:50 329:1 330:128 331:1 332:228 333:1 334:375 335:1 336:136 338:8 340:92 341:1 342:239 343:1 344:138 346:10 348:90 349:1 350:237 351:1 352:146 354:18 356:82 357:1 358:229 359:1 360:143 362:15 364:85 365:1 366:232 367:1 368:1900 369:30 370:30 371:105.9 372:107.1 373:116.1 374:30 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:51 388:51 389:84.9 390:86.1 391:95.1 392:51 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:21 406:21 407:114.9 408:116.1 409:125.1 410:21 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:50 424:50 425:85.9 426:87.1 427:96.1 428:50 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:36 442:36 443:99.9 444:101.1 445:110.1 446:36 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:38 460:38 461:97.9 462:99.1 463:108.1 464:38 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:28 478:28 479:107.9 480:109.1 481:118.1 482:28 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:19 496:19 497:116.9 498:118.1 499:127.1 500:19 501:1 507:1 508:1 509:1 510:1 511:1 512:1 513:40 514:188 515:52.1 516:50.9 517:42.1 518:41.9 521:1 523:1 524:1 525:1 526:1 528:0.9 529:1 530:0.1 531:10 532:10 533:125.9 534:127.1 535:136.1 536:10 537:1 543:1 544:1 545:1 546:1 547:1 548:1 549:13 550:362 551:226.1 552:224.9 553:215.9 554:215.9 558:1 559:1 560:1 561:1 562:1 563:1 564:1 567:22 568:290 569:154.1 570:152.9 571:143.9 572:143.9 576:1 577:1 578:1 579:1 580:1 581:1 582:1 585:41 586:87 587:48.9 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:36 604:92 605:43.9 606:45.1 607:54.1 608:43.9 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:48 622:80 623:55.9 624:57.1 625:66.1 626:55.9 628:1 631:1 632:1 635:1 636:1 637:1 638:1 639:12 640:12 641:123.9 642:125.1 643:134.1 644:12 645:1 651:1 652:1 653:1 654:1 655:1 656:1 657:21 658:149 659:13.1 660:12.1 661:226 662:3.1 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:4 676:4 677:131.9 678:133.1 679:142.1 680:4 681:1 687:1 688:1 689:1 690:1 691:1 692:1 693:14 694:142 695:6.1 696:5.1 697:233 698:4.1 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 711:14 712:361 713:225.1 714:223.9 715:214.9 716:214.9 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:55 730:55 731:80.9 732:82.1 733:91.1 734:55 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:64 748:64 749:71.9 750:73.1 751:82.1 752:64 753:1 759:1 760:1 761:1 762:1 763:1 764:1 765:43 766:85 767:50.9 768:52.1 769:61.1 770:50.9 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:7 784:7 785:128.9 786:130.1 787:139.1 788:7 789:1 795:1 796:1 797:1 798:1 799:1 800:1 801:41 802:269 803:133.1 804:131.9 805:122.9 806:122.9 809:1 811:1 812:1 813:1 814:1 816:0.9 817:1 818:0.1 819:42 820:270 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:53 838:75 839:60.9 840:62.1 841:71.1 842:60.9 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:45 856:45 857:90.9 858:92.1 859:101.1 860:45 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:37 874:91 875:44.9 876:46.1 877:55.1 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 891:1 892:129 893:6.9 894:8.1 895:17.1 896:6.9 898:1 901:1 902:1 905:1 906:1 907:1 908:1 909:4 910:132 911:4 912:5.1 913:14.1 914:4 916:1 919:1 920:1 923:1 924:1 925:1 926:1 927:49 928:79 929:56.9 930:58.1 931:67.1 932:56.9 934:1 937:1 938:1 941:1 942:1 943:1 944:1 946:375 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:48 964:48 965:87.9 966:89.1 967:98.1 968:48 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:6 982:6 983:129.9 984:131.1 985:140.1 986:6 987:1 993:1 994:1 995:1 996:1 997:1 998:1 999:2 1000:2 1001:133.9 1002:135.1 1003:144.1 1004:2 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:26 1018:26 1019:109.9 1020:111.1 1021:120.1 1022:26 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:111.9 1038:113.1 1039:122.1 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:228 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1061:1 1063:1 1064:1 1065:1 1066:1 1068:0.9 1069:1 1070:0.1 1071:37 1072:37 1073:98.9 1074:100.1 1075:109.1 1076:37 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:50 1090:425 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1109:135.9 1110:137.1 1111:146.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1125:8 1126:136 1127:8 1128:1.1 1129:10.1 1130:0.1 1132:1 1135:1 1136:1 1138:0.0273356 1139:1 1140:1 1141:1 1142:1 1143:10 1144:138 1145:2.1 1146:1.1 1147:8.1 1148:0.1 1150:1 1153:1 1154:1 1156:0.00696864 1157:1 1158:1 1159:1 1160:1 1161:18 1162:146 1163:10.1 1164:9.1 1165:229 1166:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1179:15 1180:143 1181:7.1 1182:6.1 1183:232 1184:3.1 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1197:1 1327:1 1379:1
Cbc0038I Full problem 1481 rows 765 columns, reduced to 378 rows 159 columns
event(heuristicSolution) CbcModel.cpp:13363 event(solution) CbcModel.cpp:4568 Cbc0012I Integer solution of 1939 found by RINS after 142986 iterations and 802 nodes (35.33 seconds)
event(heuristicSolution) CbcModel.cpp:13363 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1939 OBJ VAL ORIG(?): -1939 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:30 2:99 3:1 4:239 5:1 6:345 7:1 8:51 10:78 11:1 12:218 13:1 14:324 15:1 16:21 18:108 19:1 20:248 21:1 22:354 23:1 24:50 26:79 27:1 28:219 29:1 30:325 31:1 32:36 34:93 35:1 36:233 37:1 38:339 39:1 40:38 42:91 43:1 44:231 45:1 46:337 47:1 48:28 50:101 51:1 52:241 53:1 54:347 55:1 56:19 58:110 59:1 60:250 61:1 62:356 63:1 64:188 66:59 68:81 69:1 70:187 71:1 72:10 74:119 75:1 76:259 77:1 78:365 79:1 80:362 82:233 84:93 86:13 87:1 88:290 90:161 92:21 94:85 95:1 96:87 98:42 99:1 100:182 101:1 102:288 103:1 104:92 106:37 107:1 108:177 109:1 110:283 111:1 112:80 114:49 115:1 116:189 117:1 118:295 119:1 120:12 122:117 123:1 124:257 125:1 126:363 127:1 128:149 130:20 132:120 133:1 134:226 135:1 136:4 138:125 139:1 140:265 141:1 142:371 143:1 144:142 146:13 148:127 149:1 150:233 151:1 152:361 154:232 156:92 158:14 159:1 160:55 162:74 163:1 164:214 165:1 166:320 167:1 168:64 170:65 171:1 172:205 173:1 174:311 175:1 176:85 178:44 179:1 180:184 181:1 182:290 183:1 184:7 186:122 187:1 188:262 189:1 190:368 191:1 192:269 194:140 197:1 198:106 199:1 200:270 202:141 204:1 206:105 207:1 208:75 210:54 211:1 212:194 213:1 214:300 215:1 216:45 218:84 219:1 220:224 221:1 222:330 223:1 224:91 226:38 227:1 228:178 229:1 230:284 231:1 232:129 235:1 236:140 237:1 238:246 239:1 240:132 242:3 244:137 245:1 246:243 247:1 248:79 250:50 251:1 252:190 253:1 254:296 255:1 256:375 258:246 260:106 263:1 264:48 266:81 267:1 268:221 269:1 270:327 271:1 272:6 274:123 275:1 276:263 277:1 278:369 279:1 280:2 282:127 283:1 284:267 285:373 286:26 288:103 289:1 290:243 291:1 292:349 293:1 294:24 296:105 297:1 298:245 299:1 300:351 301:1 302:228 304:99 306:41 307:1 308:147 309:1 310:37 312:92 313:1 314:232 315:1 316:338 317:1 318:425 319:296 320:156 321:50 323:129 324:269 325:375 326:136 328:7 330:133 331:1 332:239 333:1 334:138 336:9 338:131 339:1 340:237 341:1 342:146 344:17 346:123 347:1 348:229 349:1 350:143 352:14 354:126 355:1 356:232 357:1 358:30 359:1 363:51 364:1 368:21 369:1 373:50 374:1 378:36 379:1 383:38 384:1 388:28 389:1 393:19 394:1 398:59 400:1 403:10 404:1 408:13 412:1 413:21 416:1 418:42 420:1 423:37 425:1 428:49 430:1 433:12 434:1 438:20 440:1 443:4 444:1 448:13 450:1 453:14 457:1 458:55 459:1 463:64 464:1 468:44 470:1 473:7 474:1 481:1 483:1 486:1 488:54 490:1 493:45 494:1 498:38 500:1 505:1 508:3 510:1 513:50 515:1 522:1 523:48 524:1 528:6 529:1 533:2 534:1 538:26 539:1 543:24 544:1 548:41 551:1 553:37 554:1 558:50 562:1 564:1 568:7 570:1 573:9 575:1 578:17 580:1 583:14 585:1 588:1 661:1 715:1 763:1
Postprocessed sol: 0:6 1:134 2:234 3:381 4:30 6:98 7:1 8:198 9:1 10:345 11:1 12:51 14:77 15:1 16:177 17:1 18:324 19:1 20:21 22:107 23:1 24:207 25:1 26:354 27:1 28:50 30:78 31:1 32:178 33:1 34:325 35:1 36:36 38:92 39:1 40:192 41:1 42:339 43:1 44:38 46:90 47:1 48:190 49:1 50:337 51:1 52:28 54:100 55:1 56:200 57:1 58:347 59:1 60:19 62:109 63:1 64:209 65:1 66:356 67:1 68:188 70:60 72:40 73:1 74:187 75:1 76:10 78:118 79:1 80:218 81:1 82:365 83:1 84:362 86:234 88:134 90:13 92:290 94:162 96:62 98:85 99:1 100:87 102:41 103:1 104:141 105:1 106:288 107:1 108:92 110:36 111:1 112:136 113:1 114:283 115:1 116:80 118:48 119:1 120:148 121:1 122:295 123:1 124:12 126:116 127:1 128:216 129:1 130:363 131:1 132:149 134:21 136:79 137:1 138:226 139:1 140:4 142:124 143:1 144:224 145:1 146:371 147:1 148:142 150:14 152:86 153:1 154:233 155:1 156:361 158:233 160:133 162:14 163:1 164:55 166:73 167:1 168:173 169:1 170:320 171:1 172:64 174:64 175:1 176:164 177:1 178:311 179:1 180:85 182:43 183:1 184:143 185:1 186:290 187:1 188:7 190:121 191:1 192:221 193:1 194:368 195:1 196:269 198:141 200:41 202:106 203:1 204:270 206:142 208:42 210:105 211:1 212:75 214:53 215:1 216:153 217:1 218:300 219:1 220:45 222:83 223:1 224:183 225:1 226:330 227:1 228:91 230:37 231:1 232:137 233:1 234:284 235:1 236:129 238:1 239:1 240:99 241:1 242:246 243:1 244:132 246:4 248:96 249:1 250:243 251:1 252:79 254:49 255:1 256:149 257:1 258:296 259:1 260:375 262:247 264:147 268:48 270:80 271:1 272:180 273:1 274:327 275:1 276:6 278:122 279:1 280:222 281:1 282:369 283:1 284:2 286:126 287:1 288:226 289:1 290:373 291:1 292:26 294:102 295:1 296:202 297:1 298:349 299:1 300:24 302:104 303:1 304:204 305:1 306:351 307:1 308:228 310:100 313:1 314:147 315:1 316:37 318:91 319:1 320:191 321:1 322:338 323:1 324:425 325:297 326:197 327:50 329:1 330:128 331:1 332:228 333:1 334:375 335:1 336:136 338:8 340:92 341:1 342:239 343:1 344:138 346:10 348:90 349:1 350:237 351:1 352:146 354:18 356:82 357:1 358:229 359:1 360:143 362:15 364:85 365:1 366:232 367:1 368:1666 369:30 370:30 371:105.9 372:107.1 373:116.1 374:30 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:51 388:51 389:84.9 390:86.1 391:95.1 392:51 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:21 406:21 407:114.9 408:116.1 409:125.1 410:21 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:50 424:50 425:85.9 426:87.1 427:96.1 428:50 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:36 442:36 443:99.9 444:101.1 445:110.1 446:36 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:38 460:38 461:97.9 462:99.1 463:108.1 464:38 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:28 478:28 479:107.9 480:109.1 481:118.1 482:28 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:19 496:19 497:116.9 498:118.1 499:127.1 500:19 501:1 507:1 508:1 509:1 510:1 511:1 512:1 513:40 514:188 515:52.1 516:50.9 517:42.1 518:41.9 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 531:10 532:10 533:125.9 534:127.1 535:136.1 536:10 537:1 543:1 544:1 545:1 546:1 547:1 548:1 549:13 550:362 551:226.1 552:224.9 553:215.9 554:215.9 558:1 559:1 560:1 561:1 562:1 563:1 564:1 568:290 569:154.1 570:152.9 571:143.9 572:143.9 576:1 577:1 578:1 579:1 580:1 581:1 582:1 585:41 586:87 587:48.9 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:36 604:92 605:43.9 606:45.1 607:54.1 608:43.9 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:48 622:80 623:55.9 624:57.1 625:66.1 626:55.9 628:1 631:1 632:1 635:1 636:1 637:1 638:1 639:12 640:12 641:123.9 642:125.1 643:134.1 644:12 645:1 651:1 652:1 653:1 654:1 655:1 656:1 658:149 659:13.1 660:12.1 661:3.1 662:2.9 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:4 676:4 677:131.9 678:133.1 679:142.1 680:4 681:1 687:1 688:1 689:1 690:1 691:1 692:1 694:142 695:6.1 696:5.1 697:4.1 698:3.9 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 711:14 712:361 713:225.1 714:223.9 715:214.9 716:214.9 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:55 730:55 731:80.9 732:82.1 733:91.1 734:55 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:53 748:64 749:71.9 750:73.1 751:82.1 752:63.9 753:1 758:0.000277008 759:1 760:1 761:1 762:1 763:1 764:1 765:43 766:85 767:50.9 768:52.1 769:61.1 770:50.9 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:7 784:7 785:128.9 786:130.1 787:139.1 788:7 789:1 795:1 796:1 797:1 798:1 799:1 800:1 801:41 802:269 803:133.1 804:131.9 805:122.9 806:122.9 809:1 811:1 812:1 813:1 814:1 816:0.9 817:1 818:0.1 820:270 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:53 838:75 839:60.9 840:62.1 841:71.1 842:60.9 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:45 856:45 857:90.9 858:92.1 859:101.1 860:45 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:37 874:91 875:44.9 876:46.1 877:55.1 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 892:129 893:6.9 894:8.1 895:17.1 896:6.9 898:1 901:1 902:1 905:1 906:1 907:1 908:1 910:132 911:4 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.000341297 923:1 924:1 925:1 926:1 927:49 928:79 929:56.9 930:58.1 931:67.1 932:56.9 934:1 937:1 938:1 941:1 942:1 943:1 944:1 946:375 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:48 964:48 965:87.9 966:89.1 967:98.1 968:48 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:6 982:6 983:129.9 984:131.1 985:140.1 986:6 987:1 993:1 994:1 995:1 996:1 997:1 998:1 999:2 1000:2 1001:133.9 1002:135.1 1003:144.1 1004:2 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:26 1018:26 1019:109.9 1020:111.1 1021:120.1 1022:26 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:111.9 1038:113.1 1039:122.1 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:228 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1061:1 1063:1 1064:1 1065:1 1066:1 1068:0.9 1069:1 1070:0.1 1071:37 1072:37 1073:98.9 1074:100.1 1075:109.1 1076:37 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:50 1090:425 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1109:135.9 1110:137.1 1111:146.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:136 1127:8 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1138:0.0276817 1139:1 1140:1 1141:1 1142:1 1144:138 1145:2.1 1146:1.1 1147:8.1 1150:1 1153:1 1154:1 1156:0.00731707 1157:1 1158:1 1159:1 1160:1 1162:146 1163:10.1 1164:9.1 1165:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1180:143 1181:7.1 1182:6.1 1183:3.1 1184:2.9 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1197:1 1327:1 1379:1
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1939 OBJ VAL ORIG(?): -1939 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:30 2:99 3:1 4:239 5:1 6:345 7:1 8:51 10:78 11:1 12:218 13:1 14:324 15:1 16:21 18:108 19:1 20:248 21:1 22:354 23:1 24:50 26:79 27:1 28:219 29:1 30:325 31:1 32:36 34:93 35:1 36:233 37:1 38:339 39:1 40:38 42:91 43:1 44:231 45:1 46:337 47:1 48:28 50:101 51:1 52:241 53:1 54:347 55:1 56:19 58:110 59:1 60:250 61:1 62:356 63:1 64:188 66:59 68:81 69:1 70:187 71:1 72:10 74:119 75:1 76:259 77:1 78:365 79:1 80:362 82:233 84:93 86:13 87:1 88:290 90:161 92:21 94:85 95:1 96:87 98:42 99:1 100:182 101:1 102:288 103:1 104:92 106:37 107:1 108:177 109:1 110:283 111:1 112:80 114:49 115:1 116:189 117:1 118:295 119:1 120:12 122:117 123:1 124:257 125:1 126:363 127:1 128:149 130:20 132:120 133:1 134:226 135:1 136:4 138:125 139:1 140:265 141:1 142:371 143:1 144:142 146:13 148:127 149:1 150:233 151:1 152:361 154:232 156:92 158:14 159:1 160:55 162:74 163:1 164:214 165:1 166:320 167:1 168:64 170:65 171:1 172:205 173:1 174:311 175:1 176:85 178:44 179:1 180:184 181:1 182:290 183:1 184:7 186:122 187:1 188:262 189:1 190:368 191:1 192:269 194:140 197:1 198:106 199:1 200:270 202:141 204:1 206:105 207:1 208:75 210:54 211:1 212:194 213:1 214:300 215:1 216:45 218:84 219:1 220:224 221:1 222:330 223:1 224:91 226:38 227:1 228:178 229:1 230:284 231:1 232:129 235:1 236:140 237:1 238:246 239:1 240:132 242:3 244:137 245:1 246:243 247:1 248:79 250:50 251:1 252:190 253:1 254:296 255:1 256:375 258:246 260:106 263:1 264:48 266:81 267:1 268:221 269:1 270:327 271:1 272:6 274:123 275:1 276:263 277:1 278:369 279:1 280:2 282:127 283:1 284:267 285:373 286:26 288:103 289:1 290:243 291:1 292:349 293:1 294:24 296:105 297:1 298:245 299:1 300:351 301:1 302:228 304:99 306:41 307:1 308:147 309:1 310:37 312:92 313:1 314:232 315:1 316:338 317:1 318:425 319:296 320:156 321:50 323:129 324:269 325:375 326:136 328:7 330:133 331:1 332:239 333:1 334:138 336:9 338:131 339:1 340:237 341:1 342:146 344:17 346:123 347:1 348:229 349:1 350:143 352:14 354:126 355:1 356:232 357:1 358:30 359:1 363:51 364:1 368:21 369:1 373:50 374:1 378:36 379:1 383:38 384:1 388:28 389:1 393:19 394:1 398:59 400:1 403:10 404:1 408:13 412:1 413:21 416:1 418:42 420:1 423:37 425:1 428:49 430:1 433:12 434:1 438:20 440:1 443:4 444:1 448:13 450:1 453:14 457:1 458:55 459:1 463:64 464:1 468:44 470:1 473:7 474:1 481:1 483:1 486:1 488:54 490:1 493:45 494:1 498:38 500:1 505:1 508:3 510:1 513:50 515:1 522:1 523:48 524:1 528:6 529:1 533:2 534:1 538:26 539:1 543:24 544:1 548:41 551:1 553:37 554:1 558:50 562:1 564:1 568:7 570:1 573:9 575:1 578:17 580:1 583:14 585:1 588:1 661:1 715:1 763:1
Postprocessed sol: 0:6 1:135 2:234 3:381 4:30 6:99 7:1 8:198 9:1 10:345 11:1 12:51 14:78 15:1 16:177 17:1 18:324 19:1 20:21 22:108 23:1 24:207 25:1 26:354 27:1 28:50 30:79 31:1 32:178 33:1 34:325 35:1 36:36 38:93 39:1 40:192 41:1 42:339 43:1 44:38 46:91 47:1 48:190 49:1 50:337 51:1 52:28 54:101 55:1 56:200 57:1 58:347 59:1 60:19 62:110 63:1 64:209 65:1 66:356 67:1 68:188 70:59 72:59 73:1 74:187 75:1 76:10 78:119 79:1 80:218 81:1 82:365 83:1 84:362 86:233 88:134 90:13 92:290 94:161 96:62 98:85 99:1 100:87 102:42 103:1 104:141 105:1 106:288 107:1 108:92 110:37 111:1 112:136 113:1 114:283 115:1 116:80 118:49 119:1 120:148 121:1 122:295 123:1 124:12 126:117 127:1 128:216 129:1 130:363 131:1 132:149 134:20 136:79 137:1 138:226 139:1 140:4 142:125 143:1 144:224 145:1 146:371 147:1 148:142 150:13 152:86 153:1 154:233 155:1 156:361 158:232 160:133 162:14 163:1 164:55 166:74 167:1 168:173 169:1 170:320 171:1 172:64 174:65 175:1 176:164 177:1 178:311 179:1 180:85 182:44 183:1 184:143 185:1 186:290 187:1 188:7 190:122 191:1 192:221 193:1 194:368 195:1 196:269 198:140 200:41 202:106 203:1 204:270 206:141 208:42 210:105 211:1 212:75 214:54 215:1 216:153 217:1 218:300 219:1 220:45 222:84 223:1 224:183 225:1 226:330 227:1 228:91 230:38 231:1 232:137 233:1 234:284 235:1 236:129 239:1 240:99 241:1 242:246 243:1 244:132 246:3 248:96 249:1 250:243 251:1 252:79 254:50 255:1 256:149 257:1 258:296 259:1 260:375 262:246 264:147 268:48 270:81 271:1 272:180 273:1 274:327 275:1 276:6 278:123 279:1 280:222 281:1 282:369 283:1 284:2 286:127 287:1 288:226 289:1 290:373 291:1 292:26 294:103 295:1 296:202 297:1 298:349 299:1 300:24 302:105 303:1 304:204 305:1 306:351 307:1 308:228 310:99 313:1 314:147 315:1 316:37 318:92 319:1 320:191 321:1 322:338 323:1 324:425 325:296 326:197 327:50 329:1 330:129 331:1 332:228 333:1 334:375 335:1 336:136 338:7 340:92 341:1 342:239 343:1 344:138 346:9 348:90 349:1 350:237 351:1 352:146 354:17 356:82 357:1 358:229 359:1 360:143 362:14 364:85 365:1 366:232 367:1 368:1245 369:30 370:30 371:105.9 372:107.1 373:116.1 374:30 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:42 388:51 389:84.9 390:86.1 391:95.1 392:50.9 393:1 398:0.00026738 399:1 400:1 401:1 402:1 403:1 404:1 405:21 406:21 407:114.9 408:116.1 409:125.1 410:21 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:50 424:50 425:85.9 426:87.1 427:96.1 428:50 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:36 442:36 443:99.9 444:101.1 445:110.1 446:36 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:38 460:38 461:97.9 462:99.1 463:108.1 464:38 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:28 478:28 479:107.9 480:109.1 481:118.1 482:28 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:19 496:19 497:116.9 498:118.1 499:127.1 500:19 501:1 507:1 508:1 509:1 510:1 511:1 512:1 513:59 514:188 515:52.1 516:51.1 517:42.1 518:42.1 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 531:10 532:10 533:125.9 534:127.1 535:136.1 536:10 537:1 543:1 544:1 545:1 546:1 547:1 548:1 550:362 551:226.1 552:224.9 553:215.9 554:215.9 558:1 559:1 560:1 561:1 562:1 563:1 564:1 568:290 569:154.1 570:152.9 571:143.9 572:143.9 576:1 577:1 578:1 579:1 580:1 581:1 582:1 585:42 586:87 587:48.9 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:9 604:92 605:43.9 606:45.1 607:54.1 608:43.9 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:15 622:80 623:55.9 624:57.1 625:66.1 626:55.9 628:1 631:1 632:1 635:1 636:1 637:1 638:1 639:12 640:12 641:123.9 642:125.1 643:134.1 644:12 645:1 651:1 652:1 653:1 654:1 655:1 656:1 658:149 659:13.1 660:12.1 661:3.1 662:2.9 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:4 676:4 677:131.9 678:133.1 679:142.1 680:4 681:1 687:1 688:1 689:1 690:1 691:1 692:1 694:142 695:6.1 696:5.1 697:4.1 698:3.9 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:361 713:225.1 714:223.9 715:214.9 716:214.9 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:55 730:55 731:80.9 732:82.1 733:91.1 734:55 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:53 748:64 749:71.9 750:73.1 751:82.1 752:63.9 753:1 758:0.000277008 759:1 760:1 761:1 762:1 763:1 764:1 765:10 766:85 767:50.9 768:52.1 769:61.1 770:50.9 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:7 784:7 785:128.9 786:130.1 787:139.1 788:7 789:1 795:1 796:1 797:1 798:1 799:1 800:1 802:269 803:133.1 804:131.9 805:122.9 806:122.9 811:1 812:1 813:1 814:1 815:1 816:1 817:1 818:0.1 820:270 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:21 838:75 839:60.9 840:62.1 841:71.1 842:60.9 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:45 856:45 857:90.9 858:92.1 859:101.1 860:45 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:10 874:91 875:44.9 876:46.1 877:55.1 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 892:129 893:6.9 894:8.1 895:17.1 896:6.9 898:1 901:1 902:1 905:1 906:1 907:1 908:1 910:132 911:3.9 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 923:1 924:1 925:1 926:1 928:79 929:56.9 930:58.1 931:67.1 932:56.9 934:1 937:1 938:1 941:1 942:1 943:1 944:1 946:375 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:48 964:48 965:87.9 966:89.1 967:98.1 968:48 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:6 982:6 983:129.9 984:131.1 985:140.1 986:6 987:1 993:1 994:1 995:1 996:1 997:1 998:1 999:2 1000:2 1001:133.9 1002:135.1 1003:144.1 1004:2 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:26 1018:26 1019:109.9 1020:111.1 1021:120.1 1022:26 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:111.9 1038:113.1 1039:122.1 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:228 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1061:1 1063:1 1064:1 1065:1 1066:1 1068:0.9 1069:1 1070:0.1 1071:37 1072:37 1073:98.9 1074:100.1 1075:109.1 1076:37 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:50 1090:425 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1109:135.9 1110:137.1 1111:146.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:136 1127:7 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1138:0.0242215 1139:1 1140:1 1141:1 1142:1 1144:138 1145:2.1 1146:1.1 1147:8.1 1150:1 1153:1 1154:1 1156:0.00731707 1157:1 1158:1 1159:1 1160:1 1162:146 1163:10.1 1164:9.1 1165:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1180:143 1181:7.1 1182:6.1 1183:3.1 1184:2.9 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1197:1 1379:1
Cbc0038I Full problem 1481 rows 765 columns, reduced to 1043 rows 338 columns - 28 fixed gives 788, 249 - ok now
Cbc0038I Full problem 1481 rows 765 columns, reduced to 296 rows 135 columns
Cbc0010I After 1000 nodes, 26 on tree, 1939 best solution, best possible 0 (39.87 seconds)
Cbc0004I Integer solution of 1916 found after 170970 iterations and 1186 nodes (41.61 seconds)
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1916 OBJ VAL ORIG(?): -1916 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:15 1:1 2:108 3:1 4:345 5:1 6:395 7:1 8:6 10:87 11:1 12:324 13:1 14:374 15:1 16:24 17:1 18:117 19:1 20:354 21:1 22:404 23:1 24:5 26:88 27:1 28:325 29:1 30:375 31:1 32:9 33:1 34:102 35:1 36:339 37:1 38:389 39:1 40:7 41:1 42:100 43:1 44:337 45:1 46:387 47:1 48:17 49:1 50:110 51:1 52:347 53:1 54:397 55:1 56:26 57:1 58:119 59:1 60:356 61:1 62:406 63:1 64:143 66:50 68:187 69:1 70:237 71:1 72:35 73:1 74:128 75:1 76:365 77:1 78:415 79:1 80:317 82:224 84:13 85:1 86:63 87:1 88:245 90:152 92:85 93:1 94:135 95:1 96:42 98:51 99:1 100:288 101:1 102:338 103:1 104:47 106:46 107:1 108:283 109:1 110:333 111:1 112:35 114:58 115:1 116:295 117:1 118:345 119:1 120:33 121:1 122:126 123:1 124:363 125:1 126:413 127:1 128:104 130:11 132:226 133:1 134:276 135:1 136:41 137:1 138:134 139:1 140:371 141:1 142:421 143:1 144:97 146:4 148:233 149:1 150:283 151:1 152:316 154:223 156:14 157:1 158:64 159:1 160:10 162:83 163:1 164:320 165:1 166:370 167:1 168:19 170:74 171:1 172:311 173:1 174:361 175:1 176:40 178:53 179:1 180:290 181:1 182:340 183:1 184:38 185:1 186:131 187:1 188:368 189:1 190:418 191:1 192:224 194:131 196:106 197:1 198:156 199:1 200:225 202:132 204:105 205:1 206:155 207:1 208:30 210:63 211:1 212:300 213:1 214:350 215:1 217:1 218:93 219:1 220:330 221:1 222:380 223:1 224:46 226:47 227:1 228:284 229:1 230:334 231:1 232:84 234:9 235:1 236:246 237:1 238:296 239:1 240:87 242:6 243:1 244:243 245:1 246:293 247:1 248:34 250:59 251:1 252:296 253:1 254:346 255:1 256:330 258:237 261:1 262:50 263:1 264:3 266:90 267:1 268:327 269:1 270:377 271:1 272:39 273:1 274:132 275:1 276:369 277:1 278:419 279:1 280:43 281:1 282:136 283:1 284:373 285:423 286:19 287:1 288:112 289:1 290:349 291:1 292:399 293:1 294:21 295:1 296:114 297:1 298:351 299:1 300:401 301:1 302:183 304:90 306:147 307:1 308:197 309:1 310:8 311:1 312:101 313:1 314:338 315:1 316:388 317:1 318:380 319:287 320:50 322:45 323:138 324:375 325:425 326:91 328:2 329:1 330:239 331:1 332:289 333:1 334:93 337:1 338:237 339:1 340:287 341:1 342:101 344:8 346:229 347:1 348:279 349:1 350:98 352:5 354:232 355:1 356:282 357:1 358:15 359:1 363:6 364:1 368:24 369:1 373:5 374:1 378:9 379:1 383:7 384:1 388:17 389:1 393:26 394:1 398:50 400:1 403:35 404:1 408:13 411:1 413:85 416:1 418:42 419:1 423:46 425:1 428:35 429:1 433:33 434:1 438:11 440:1 443:41 444:1 448:4 450:1 453:14 456:1 458:10 459:1 463:19 464:1 468:40 469:1 473:38 474:1 478:106 481:1 483:105 486:1 488:30 489:1 494:1 498:46 499:1 503:9 505:1 508:6 510:1 513:34 514:1 521:1 523:3 524:1 528:39 529:1 533:43 534:1 538:19 539:1 543:21 544:1 548:90 550:1 553:8 554:1 562:1 563:45 564:1 568:2 570:1 575:1 578:8 580:1 583:5 585:1 604:1 664:1 720:1 764:1
Postprocessed sol: 0:51 1:144 2:370 3:431 4:15 5:1 6:108 7:1 8:334 9:1 10:395 11:1 12:6 14:87 15:1 16:313 17:1 18:374 19:1 20:24 21:1 22:117 23:1 24:343 25:1 26:404 27:1 28:5 30:88 31:1 32:314 33:1 34:375 35:1 36:9 37:1 38:102 39:1 40:328 41:1 42:389 43:1 44:7 45:1 46:100 47:1 48:326 49:1 50:387 51:1 52:17 53:1 54:110 55:1 56:336 57:1 58:397 59:1 60:26 61:1 62:119 63:1 64:345 65:1 66:406 67:1 68:143 70:50 72:176 73:1 74:237 75:1 76:35 77:1 78:128 79:1 80:354 81:1 82:415 83:1 84:317 86:224 88:134 90:63 91:1 92:245 94:152 96:74 97:1 98:135 99:1 100:42 102:51 103:1 104:277 105:1 106:338 107:1 108:47 110:46 111:1 112:272 113:1 114:333 115:1 116:35 118:58 119:1 120:284 121:1 122:345 123:1 124:33 125:1 126:126 127:1 128:352 129:1 130:413 131:1 132:104 134:11 136:215 137:1 138:276 139:1 140:41 141:1 142:134 143:1 144:360 145:1 146:421 147:1 148:97 150:4 152:222 153:1 154:283 155:1 156:316 158:223 160:133 162:64 163:1 164:10 166:83 167:1 168:309 169:1 170:370 171:1 172:19 174:74 175:1 176:300 177:1 178:361 179:1 180:40 182:53 183:1 184:279 185:1 186:340 187:1 188:38 189:1 190:131 191:1 192:357 193:1 194:418 195:1 196:224 198:131 200:95 201:1 202:156 203:1 204:225 206:132 208:94 209:1 210:155 211:1 212:30 214:63 215:1 216:289 217:1 218:350 219:1 221:1 222:93 223:1 224:319 225:1 226:380 227:1 228:46 230:47 231:1 232:273 233:1 234:334 235:1 236:84 238:9 239:1 240:235 241:1 242:296 243:1 244:87 246:6 247:1 248:232 249:1 250:293 251:1 252:34 254:59 255:1 256:285 257:1 258:346 259:1 260:330 262:237 264:11 266:50 267:1 268:3 270:90 271:1 272:316 273:1 274:377 275:1 276:39 277:1 278:132 279:1 280:358 281:1 282:419 283:1 284:43 285:1 286:136 287:1 288:362 289:1 290:423 291:1 292:19 293:1 294:112 295:1 296:338 297:1 298:399 299:1 300:21 301:1 302:114 303:1 304:340 305:1 306:401 307:1 308:183 310:90 312:136 313:1 314:197 315:1 316:8 317:1 318:101 319:1 320:327 321:1 322:388 323:1 324:380 325:287 326:61 328:45 329:1 330:138 331:1 332:364 333:1 334:425 335:1 336:91 338:2 339:1 340:228 341:1 342:289 343:1 344:93 348:226 349:1 350:287 351:1 352:101 354:8 356:218 357:1 358:279 359:1 360:98 362:5 364:221 365:1 366:282 367:1 368:1867 369:15 370:29.9 371:106.1 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:6 388:50.9 389:85.1 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:24 406:24 407:115.1 408:116.1 409:125.1 410:21.1 411:1 416:0.00717822 417:1 418:1 419:1 420:1 421:1 422:1 423:5 424:49.9 425:86.1 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:9 442:35.9 443:100.1 444:101.1 445:110.1 446:35.9 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:7 460:37.9 461:98.1 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:17 478:27.9 479:108.1 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:26 496:26 497:117.1 498:118.1 499:127.1 500:19.1 501:1 506:0.0169951 507:1 508:1 509:1 510:1 511:1 512:1 513:50 514:187.9 515:51.9 516:51.1 517:237 518:42.1 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 531:35 532:35 533:126.1 534:127.1 535:136.1 536:10.1 537:1 542:0.06 543:1 544:1 545:1 546:1 547:1 548:1 550:361.9 551:225.9 552:224.9 553:215.9 554:215.9 557:1 559:1 560:1 561:1 562:1 564:0.9 565:1 566:0.1 567:74 568:289.9 569:153.9 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 585:42 586:86.9 587:51 588:50.1 589:59.1 590:48.9 591:1 596:0.9 597:1 598:0.1 599:1 600:1 601:1 602:1 603:46 604:91.9 605:46 606:45.1 607:54.1 608:44.1 610:1 613:1 614:1 616:0.00570571 617:1 618:1 619:1 620:1 621:35 622:79.9 623:58 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 639:33 640:33 641:124.1 642:125.1 643:134.1 644:12.1 645:1 650:0.0506053 651:1 652:1 653:1 654:1 655:1 656:1 657:11 658:148.9 659:12.9 660:12.1 661:276 662:3.1 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:41 676:4.1 677:132.1 678:133.1 679:142.1 680:4.1 681:1 687:1 688:1 689:1 690:1 691:1 692:1 693:4 694:141.9 695:5.9 696:5.1 697:283 698:4 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:360.9 713:224.9 714:223.9 715:214.9 716:214.9 719:1 721:1 722:1 723:1 724:1 726:0.9 727:1 728:0.1 729:10 730:54.9 731:81.1 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:19 748:63.9 749:72.1 750:73.1 751:82.1 752:63.9 753:1 759:1 760:1 761:1 762:1 763:1 764:1 765:40 766:84.9 767:53 768:52.1 769:61.1 770:50.9 771:1 776:0.9 777:1 778:0.1 779:1 780:1 781:1 782:1 783:38 784:7.1 785:129.1 786:130.1 787:139.1 788:7.1 789:1 795:1 796:1 797:1 798:1 799:1 800:1 801:95 802:268.9 803:132.9 804:131.9 805:123.1 806:122.9 809:1 811:1 812:1 813:1 814:1 816:0.9 817:1 818:0.1 819:94 820:269.9 821:133.9 822:132.9 823:124.1 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:30 838:74.9 839:63 840:62.1 841:71.1 842:60.9 843:1 848:0.9 849:1 850:0.1 851:1 852:1 853:1 854:1 856:44.9 857:91.1 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:46 874:90.9 875:47 876:46.1 877:55.1 878:45.1 879:1 884:0.9 885:1 886:0.1 887:1 888:1 889:1 890:1 891:9 892:128.9 893:9 894:8.1 895:17.1 896:7.1 898:1 901:1 902:1 904:0.00641892 905:1 906:1 907:1 908:1 909:6 910:131.9 911:6 912:5.1 913:14.1 914:4.1 916:1 919:1 920:1 922:0.00648464 923:1 924:1 925:1 926:1 927:34 928:78.9 929:59 930:58.1 931:67.1 932:56.9 933:1 938:0.9 939:1 940:0.1 941:1 942:1 943:1 944:1 945:11 946:374.9 947:238.9 948:237.9 949:228.9 950:228.9 953:1 955:1 956:1 957:1 958:1 960:0.9 961:1 962:0.1 963:3 964:47.9 965:88.1 966:89.1 967:98.1 968:47.9 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:39 982:39 983:130.1 984:131.1 985:140.1 986:6.1 987:1 992:0.0785203 993:1 994:1 995:1 996:1 997:1 998:1 999:43 1000:43 1001:134.1 1002:135.1 1003:144.1 1004:2.1 1005:1 1010:0.0966903 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:19 1018:25.9 1019:110.1 1020:111.1 1021:120.1 1022:25.9 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:21 1036:23.9 1037:112.1 1038:113.1 1039:122.1 1040:23.9 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1053:90 1054:227.9 1055:91.9 1056:91.1 1057:197 1058:82.1 1060:1 1063:1 1064:1 1066:0.9 1067:1 1068:1 1069:1 1070:0.1 1071:8 1072:36.9 1073:99.1 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1090:424.9 1091:288.9 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1107:45 1108:45 1109:136.1 1110:137.1 1111:146.1 1112:0.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1125:2 1126:135.9 1127:0.1 1128:1.1 1129:10.1 1130:0.1 1132:1 1135:1 1136:1 1139:1 1140:1 1141:1 1142:1 1144:137.9 1145:1.9 1146:1.1 1147:8.1 1150:1 1153:1 1154:1 1156:0.00662021 1157:1 1158:1 1159:1 1160:1 1161:8 1162:145.9 1163:9.9 1164:9.1 1165:279 1166:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1179:5 1180:142.9 1181:6.9 1182:6.1 1183:282 1184:3.1 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1213:1 1275:1 1380:1
Cbc0038I Full problem 1481 rows 765 columns, reduced to 797 rows 300 columns - 18 fixed gives 777, 282 - ok now
Cbc0038I Full problem 1481 rows 765 columns, reduced to 18 rows 18 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 996 rows 360 columns - 24 fixed gives 935, 307 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 807 rows 300 columns - too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 947 rows 328 columns - 28 fixed gives 905, 296 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 530 rows 227 columns
event(heuristicSolution) CbcModel.cpp:13363 Cbc0012I Integer solution of 1580 found by RINS after 187464 iterations and 1400 nodes (44.52 seconds)
event(heuristicSolution) CbcModel.cpp:13363 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1580 OBJ VAL ORIG(?): -1580 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:15 1:1 2:108 3:1 4:240 5:1 6:345 7:1 8:6 10:87 11:1 12:219 13:1 14:324 15:1 16:24 17:1 18:117 19:1 20:249 21:1 22:354 23:1 24:5 26:88 27:1 28:220 29:1 30:325 31:1 32:9 33:1 34:102 35:1 36:234 37:1 38:339 39:1 40:7 41:1 42:100 43:1 44:232 45:1 46:337 47:1 48:17 49:1 50:110 51:1 52:242 53:1 54:347 55:1 56:26 57:1 58:119 59:1 60:251 61:1 62:356 63:1 64:143 66:50 68:82 69:1 70:187 71:1 72:35 73:1 74:128 75:1 76:260 77:1 78:365 79:1 80:317 82:224 84:92 86:13 87:1 88:245 90:152 92:20 94:85 95:1 96:42 98:51 99:1 100:183 101:1 102:288 103:1 104:47 106:46 107:1 108:178 109:1 110:283 111:1 112:35 114:58 115:1 116:190 117:1 118:295 119:1 120:33 121:1 122:126 123:1 124:258 125:1 126:363 127:1 128:104 130:11 132:121 133:1 134:226 135:1 136:41 137:1 138:134 139:1 140:266 141:1 142:371 143:1 144:97 146:4 148:128 149:1 150:233 151:1 152:316 154:223 156:91 158:14 159:1 160:10 162:83 163:1 164:215 165:1 166:320 167:1 168:19 170:74 171:1 172:206 173:1 174:311 175:1 176:40 178:53 179:1 180:185 181:1 182:290 183:1 184:38 185:1 186:131 187:1 188:263 189:1 190:368 191:1 192:224 194:131 196:1 197:1 198:106 199:1 200:225 202:132 205:1 206:105 207:1 208:30 210:63 211:1 212:195 213:1 214:300 215:1 217:1 218:93 219:1 220:225 221:1 222:330 223:1 224:46 226:47 227:1 228:179 229:1 230:284 231:1 232:84 234:9 235:1 236:141 237:1 238:246 239:1 240:87 242:6 243:1 244:138 245:1 246:243 247:1 248:34 250:59 251:1 252:191 253:1 254:296 255:1 256:330 258:237 260:105 263:1 264:3 266:90 267:1 268:222 269:1 270:327 271:1 272:39 273:1 274:132 275:1 276:264 277:1 278:369 279:1 280:43 281:1 282:136 283:1 284:268 285:373 286:19 287:1 288:112 289:1 290:244 291:1 292:349 293:1 294:21 295:1 296:114 297:1 298:246 299:1 300:351 301:1 302:183 304:90 306:42 307:1 308:147 309:1 310:8 311:1 312:101 313:1 314:233 315:1 316:338 317:1 318:380 319:287 320:155 321:50 322:45 323:138 324:270 325:375 326:91 328:2 329:1 330:134 331:1 332:239 333:1 334:93 337:1 338:132 339:1 340:237 341:1 342:101 344:8 346:124 347:1 348:229 349:1 350:98 352:5 354:127 355:1 356:232 357:1 358:15 359:1 363:6 364:1 368:24 369:1 373:5 374:1 378:9 379:1 383:7 384:1 388:17 389:1 393:26 394:1 398:50 400:1 403:35 404:1 408:13 412:1 413:20 416:1 418:42 419:1 423:46 425:1 428:35 429:1 433:33 434:1 438:11 440:1 443:41 444:1 448:4 450:1 453:14 457:1 458:10 459:1 463:19 464:1 468:40 469:1 473:38 474:1 478:1 481:1 486:1 488:30 489:1 494:1 498:46 499:1 503:9 505:1 508:6 510:1 513:34 514:1 522:1 523:3 524:1 528:39 529:1 533:43 534:1 538:19 539:1 543:21 544:1 548:42 551:1 553:8 554:1 558:50 562:1 563:45 564:1 568:2 570:1 575:1 578:8 580:1 583:5 585:1 604:1 664:1 716:1 763:1
Postprocessed sol: 0:51 1:144 2:276 3:381 4:15 5:1 6:108 7:1 8:240 9:1 10:345 11:1 12:6 14:87 15:1 16:219 17:1 18:324 19:1 20:24 21:1 22:117 23:1 24:249 25:1 26:354 27:1 28:5 30:88 31:1 32:220 33:1 34:325 35:1 36:9 37:1 38:102 39:1 40:234 41:1 42:339 43:1 44:7 45:1 46:100 47:1 48:232 49:1 50:337 51:1 52:17 53:1 54:110 55:1 56:242 57:1 58:347 59:1 60:26 61:1 62:119 63:1 64:251 65:1 66:356 67:1 68:143 70:50 72:82 73:1 74:187 75:1 76:35 77:1 78:128 79:1 80:260 81:1 82:365 83:1 84:317 86:224 88:92 90:13 91:1 92:245 94:152 96:20 98:85 99:1 100:42 102:51 103:1 104:183 105:1 106:288 107:1 108:47 110:46 111:1 112:178 113:1 114:283 115:1 116:35 118:58 119:1 120:190 121:1 122:295 123:1 124:33 125:1 126:126 127:1 128:258 129:1 130:363 131:1 132:104 134:11 136:121 137:1 138:226 139:1 140:41 141:1 142:134 143:1 144:266 145:1 146:371 147:1 148:97 150:4 152:128 153:1 154:233 155:1 156:316 158:223 160:91 162:14 163:1 164:10 166:83 167:1 168:215 169:1 170:320 171:1 172:19 174:74 175:1 176:206 177:1 178:311 179:1 180:40 182:53 183:1 184:185 185:1 186:290 187:1 188:38 189:1 190:131 191:1 192:263 193:1 194:368 195:1 196:224 198:131 200:1 201:1 202:106 203:1 204:225 206:132 209:1 210:105 211:1 212:30 214:63 215:1 216:195 217:1 218:300 219:1 220:15 221:1 222:93 223:1 224:225 225:1 226:330 227:1 228:46 230:47 231:1 232:179 233:1 234:284 235:1 236:109 238:9 239:1 240:141 241:1 242:246 243:1 244:87 246:6 247:1 248:138 249:1 250:243 251:1 252:34 254:59 255:1 256:191 257:1 258:296 259:1 260:330 262:237 264:105 267:1 268:3 270:90 271:1 272:222 273:1 274:327 275:1 276:39 277:1 278:132 279:1 280:264 281:1 282:369 283:1 284:43 285:1 286:136 287:1 288:268 289:1 290:373 291:1 292:19 293:1 294:112 295:1 296:244 297:1 298:349 299:1 300:21 301:1 302:114 303:1 304:246 305:1 306:351 307:1 308:183 310:90 312:42 313:1 314:147 315:1 316:8 317:1 318:101 319:1 320:233 321:1 322:338 323:1 324:380 325:287 326:155 327:50 328:45 329:1 330:138 331:1 332:270 333:1 334:375 335:1 336:91 338:2 339:1 340:134 341:1 342:239 343:1 344:93 348:132 349:1 350:237 351:1 352:101 354:8 356:124 357:1 358:229 359:1 360:98 362:5 364:127 365:1 366:232 367:1 368:913 369:15 370:29.9 371:106.1 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:6 388:50.9 389:85.1 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:24 406:24 407:115.1 408:116.1 409:125.1 410:21.1 411:1 416:0.00717822 417:1 418:1 419:1 420:1 421:1 422:1 423:5 424:49.9 425:86.1 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:9 442:35.9 443:100.1 444:101.1 445:110.1 446:35.9 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:7 460:37.9 461:98.1 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:17 478:27.9 479:108.1 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:26 496:19.1 497:117.1 498:118.1 499:127.1 500:19.1 501:1 507:1 508:1 509:1 510:1 511:1 512:1 514:187.9 515:51.9 516:51.1 517:42.1 518:41.9 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 531:35 532:10.1 533:126.1 534:127.1 535:136.1 536:10.1 537:1 543:1 544:1 545:1 546:1 547:1 548:1 550:361.9 551:225.9 552:224.9 553:215.9 554:215.9 559:1 560:1 561:1 562:1 563:1 564:1 565:1 566:0.1 568:289.9 569:153.9 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 586:86.9 587:51 588:50.1 589:59.1 590:48.9 591:1 596:0.9 597:1 598:0.1 599:1 600:1 601:1 602:1 603:46 604:91.9 605:46 606:45.1 607:54.1 608:44.1 609:1 614:0.9 615:1 616:0.1 617:1 618:1 619:1 620:1 621:35 622:79.9 623:58 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 639:33 640:12.1 641:124.1 642:125.1 643:134.1 644:12.1 645:1 651:1 652:1 653:1 654:1 655:1 656:1 658:148.9 659:12.9 660:12.1 661:3.1 662:2.9 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:41 676:4.1 677:132.1 678:133.1 679:142.1 680:4.1 681:1 687:1 688:1 689:1 690:1 691:1 692:1 694:141.9 695:5.9 696:5.1 697:4.1 698:3.9 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:360.9 713:224.9 714:223.9 715:214.9 716:214.9 721:1 722:1 723:1 724:1 725:1 726:1 727:1 728:0.1 729:10 730:54.9 731:81.1 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 748:63.9 749:72.1 750:73.1 751:82.1 752:63.9 753:1 759:1 760:1 761:1 762:1 763:1 764:1 766:84.9 767:53 768:52.1 769:61.1 770:50.9 771:1 776:0.9 777:1 778:0.1 779:1 780:1 781:1 782:1 783:38 784:38 785:129.1 786:130.1 787:139.1 788:7.1 789:1 794:0.0739234 795:1 796:1 797:1 798:1 799:1 800:1 802:268.9 803:132.9 804:131.9 805:122.9 806:122.9 809:1 811:1 812:1 813:1 814:1 816:0.9 817:1 818:0.1 820:269.9 821:133.9 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 838:74.9 839:63 840:62.1 841:71.1 842:60.9 843:1 848:0.9 849:1 850:0.1 851:1 852:1 853:1 854:1 856:44.9 857:91.1 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:46 874:90.9 875:45.1 876:46.1 877:55.1 878:45.1 879:1 884:0.9 885:1 886:0.1 887:1 888:1 889:1 890:1 891:7 892:128.9 893:9 894:8.1 895:17.1 896:7 898:1 901:1 902:1 904:0.00675676 905:1 906:1 907:1 908:1 910:131.9 911:6 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.00716724 923:1 924:1 925:1 926:1 927:34 928:78.9 929:59 930:58.1 931:67.1 932:56.9 933:1 938:0.9 939:1 940:0.1 941:1 942:1 943:1 944:1 946:374.9 947:238.9 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:3 964:47.9 965:88.1 966:89.1 967:98.1 968:47.9 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:39 982:39 983:130.1 984:131.1 985:140.1 986:6.1 987:1 992:0.0785203 993:1 994:1 995:1 996:1 997:1 998:1 999:43 1000:43 1001:134.1 1002:135.1 1003:144.1 1004:2.1 1005:1 1010:0.0966903 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:19 1018:25.9 1019:110.1 1020:111.1 1021:120.1 1022:25.9 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:21 1036:23.9 1037:112.1 1038:113.1 1039:122.1 1040:23.9 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:227.9 1055:91.9 1056:90.9 1057:82.1 1058:81.9 1060:1 1063:1 1064:1 1066:0.9 1067:1 1068:1 1069:1 1070:0.1 1071:8 1072:36.9 1073:99.1 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1090:424.9 1091:288.9 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1107:45 1108:45 1109:136.1 1110:137.1 1111:146.1 1112:0.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:135.9 1127:2 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1138:0.00692042 1139:1 1140:1 1141:1 1142:1 1144:137.9 1145:1.9 1146:1.1 1147:8.1 1150:1 1153:1 1154:1 1156:0.00662021 1157:1 1158:1 1159:1 1160:1 1162:145.9 1163:9.9 1164:9.1 1165:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1180:142.9 1181:6.9 1182:6.1 1183:3.1 1184:2.9 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1329:1 1379:1
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1580 OBJ VAL ORIG(?): -1580 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:15 1:1 2:108 3:1 4:240 5:1 6:345 7:1 8:6 10:87 11:1 12:219 13:1 14:324 15:1 16:24 17:1 18:117 19:1 20:249 21:1 22:354 23:1 24:5 26:88 27:1 28:220 29:1 30:325 31:1 32:9 33:1 34:102 35:1 36:234 37:1 38:339 39:1 40:7 41:1 42:100 43:1 44:232 45:1 46:337 47:1 48:17 49:1 50:110 51:1 52:242 53:1 54:347 55:1 56:26 57:1 58:119 59:1 60:251 61:1 62:356 63:1 64:143 66:50 68:82 69:1 70:187 71:1 72:35 73:1 74:128 75:1 76:260 77:1 78:365 79:1 80:317 82:224 84:92 86:13 87:1 88:245 90:152 92:20 94:85 95:1 96:42 98:51 99:1 100:183 101:1 102:288 103:1 104:47 106:46 107:1 108:178 109:1 110:283 111:1 112:35 114:58 115:1 116:190 117:1 118:295 119:1 120:33 121:1 122:126 123:1 124:258 125:1 126:363 127:1 128:104 130:11 132:121 133:1 134:226 135:1 136:41 137:1 138:134 139:1 140:266 141:1 142:371 143:1 144:97 146:4 148:128 149:1 150:233 151:1 152:316 154:223 156:91 158:14 159:1 160:10 162:83 163:1 164:215 165:1 166:320 167:1 168:19 170:74 171:1 172:206 173:1 174:311 175:1 176:40 178:53 179:1 180:185 181:1 182:290 183:1 184:38 185:1 186:131 187:1 188:263 189:1 190:368 191:1 192:224 194:131 196:1 197:1 198:106 199:1 200:225 202:132 205:1 206:105 207:1 208:30 210:63 211:1 212:195 213:1 214:300 215:1 217:1 218:93 219:1 220:225 221:1 222:330 223:1 224:46 226:47 227:1 228:179 229:1 230:284 231:1 232:84 234:9 235:1 236:141 237:1 238:246 239:1 240:87 242:6 243:1 244:138 245:1 246:243 247:1 248:34 250:59 251:1 252:191 253:1 254:296 255:1 256:330 258:237 260:105 263:1 264:3 266:90 267:1 268:222 269:1 270:327 271:1 272:39 273:1 274:132 275:1 276:264 277:1 278:369 279:1 280:43 281:1 282:136 283:1 284:268 285:373 286:19 287:1 288:112 289:1 290:244 291:1 292:349 293:1 294:21 295:1 296:114 297:1 298:246 299:1 300:351 301:1 302:183 304:90 306:42 307:1 308:147 309:1 310:8 311:1 312:101 313:1 314:233 315:1 316:338 317:1 318:380 319:287 320:155 321:50 322:45 323:138 324:270 325:375 326:91 328:2 329:1 330:134 331:1 332:239 333:1 334:93 337:1 338:132 339:1 340:237 341:1 342:101 344:8 346:124 347:1 348:229 349:1 350:98 352:5 354:127 355:1 356:232 357:1 358:15 359:1 363:6 364:1 368:24 369:1 373:5 374:1 378:9 379:1 383:7 384:1 388:17 389:1 393:26 394:1 398:50 400:1 403:35 404:1 408:13 412:1 413:20 416:1 418:42 419:1 423:46 425:1 428:35 429:1 433:33 434:1 438:11 440:1 443:41 444:1 448:4 450:1 453:14 457:1 458:10 459:1 463:19 464:1 468:40 469:1 473:38 474:1 478:1 481:1 486:1 488:30 489:1 494:1 498:46 499:1 503:9 505:1 508:6 510:1 513:34 514:1 522:1 523:3 524:1 528:39 529:1 533:43 534:1 538:19 539:1 543:21 544:1 548:42 551:1 553:8 554:1 558:50 562:1 563:45 564:1 568:2 570:1 575:1 578:8 580:1 583:5 585:1 604:1 664:1 716:1 763:1
Postprocessed sol: 0:86 1:87 2:276 3:381 4:50 5:1 6:51 7:1 8:240 9:1 10:345 11:1 12:29 14:30 15:1 16:219 17:1 18:324 19:1 20:59 21:1 22:60 23:1 24:249 25:1 26:354 27:1 28:30 30:31 31:1 32:220 33:1 34:325 35:1 36:44 37:1 38:45 39:1 40:234 41:1 42:339 43:1 44:42 45:1 46:43 47:1 48:232 49:1 50:337 51:1 52:52 53:1 54:53 55:1 56:242 57:1 58:347 59:1 60:61 61:1 62:62 63:1 64:251 65:1 66:356 67:1 68:108 70:107 72:82 73:1 74:187 75:1 76:70 77:1 78:71 79:1 80:260 81:1 82:365 83:1 84:282 86:281 88:92 90:13 91:1 92:210 94:209 96:20 98:85 99:1 100:7 102:6 104:183 105:1 106:288 107:1 108:12 110:12 111:1 112:178 113:1 114:283 115:1 118:1 119:1 120:190 121:1 122:295 123:1 124:68 125:1 126:69 127:1 128:258 129:1 130:363 131:1 132:69 134:68 136:121 137:1 138:226 139:1 140:76 141:1 142:77 143:1 144:266 145:1 146:371 147:1 148:62 150:61 152:128 153:1 154:233 155:1 156:281 158:280 160:91 162:14 163:1 164:25 166:26 167:1 168:215 169:1 170:320 171:1 172:16 174:17 175:1 176:206 177:1 178:311 179:1 180:40 182:4 184:185 185:1 186:290 187:1 188:73 189:1 190:74 191:1 192:263 193:1 194:368 195:1 196:189 198:188 200:1 201:1 202:106 203:1 204:190 206:189 209:1 210:105 211:1 212:5 214:6 215:1 216:195 217:1 218:300 219:1 220:35 221:1 222:36 223:1 224:225 225:1 226:330 227:1 228:11 230:10 232:179 233:1 234:284 235:1 236:109 238:48 240:141 241:1 242:246 243:1 244:52 246:51 248:138 249:1 250:243 251:1 252:50 254:50 255:1 256:191 257:1 258:296 259:1 260:295 262:294 264:105 267:1 268:32 270:33 271:1 272:222 273:1 274:327 275:1 276:74 277:1 278:75 279:1 280:264 281:1 282:369 283:1 284:78 285:1 286:79 287:1 288:268 289:1 290:373 291:1 292:54 293:1 294:55 295:1 296:244 297:1 298:349 299:1 300:56 301:1 302:57 303:1 304:246 305:1 306:351 307:1 308:148 310:147 312:42 313:1 314:147 315:1 316:43 317:1 318:44 319:1 320:233 321:1 322:338 323:1 324:345 325:344 326:155 327:50 328:80 329:1 330:81 331:1 332:270 333:1 334:375 335:1 336:56 338:55 340:134 341:1 342:239 343:1 344:58 346:57 348:132 349:1 350:237 351:1 352:66 354:65 356:124 357:1 358:229 359:1 360:63 362:62 364:127 365:1 366:232 367:1 368:228 370:50 371:105.9 372:107.1 373:116.1 374:29.9 375:1 380:0.0508861 381:1 382:1 383:1 384:1 385:1 386:1 388:50.9 389:84.9 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 406:59 407:114.9 408:116.1 409:125.1 410:20.9 411:1 416:0.0943069 417:1 418:1 419:1 420:1 421:1 422:1 424:49.9 425:85.9 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 442:44 443:99.9 444:101.1 445:110.1 446:35.9 451:1 452:0.1 453:1 454:1 455:1 456:1 457:1 458:1 460:42 461:97.9 462:99.1 463:108.1 464:37.9 465:1 470:0.0105943 471:1 472:1 473:1 474:1 475:1 476:1 478:52 479:107.9 480:109.1 481:118.1 482:27.9 483:1 488:0.0607053 489:1 490:1 491:1 492:1 493:1 494:1 496:19.1 497:116.9 498:118.1 499:127.1 500:18.9 501:1 506:0.000492611 507:1 508:1 509:1 510:1 511:1 512:1 514:187.9 515:52.1 516:51.1 517:42.1 518:41.9 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 532:10.1 533:125.9 534:127.1 535:136.1 536:9.9 537:1 542:0.000481928 543:1 544:1 545:1 546:1 547:1 548:1 550:361.9 551:226.1 552:224.9 553:215.9 554:215.9 559:1 560:1 561:1 562:1 563:1 564:1 565:1 566:0.1 568:289.9 569:154.1 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 586:86.9 587:48.9 588:50.1 589:59.1 590:48.9 591:1 596:0.9 597:1 598:0.1 599:1 600:1 601:1 602:1 603:12 604:91.9 605:43.9 606:45.1 607:54.1 608:43.9 609:1 614:0.9 615:1 616:0.1 617:1 618:1 619:1 620:1 622:79.9 623:55.9 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 640:12.1 641:123.9 642:125.1 643:134.1 644:11.9 645:1 650:0.000484262 651:1 652:1 653:1 654:1 655:1 656:1 658:148.9 659:13.1 660:12.1 661:3.1 662:2.9 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:76 676:76 677:131.9 678:133.1 679:142.1 680:4.1 681:1 687:1 688:1 689:1 690:1 691:1 692:1 694:141.9 695:6.1 696:5.1 697:4.1 698:3.9 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:360.9 713:225.1 714:223.9 715:214.9 716:214.9 721:1 722:1 723:1 724:1 725:1 726:1 727:1 728:0.1 729:25 730:54.9 731:80.9 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 748:63.9 749:71.9 750:73.1 751:82.1 752:63.9 753:1 759:1 760:1 761:1 762:1 763:1 764:1 766:84.9 767:50.9 768:52.1 769:61.1 770:50.9 771:1 776:0.9 777:1 778:0.1 779:1 780:1 781:1 782:1 784:7.1 785:128.9 786:130.1 787:139.1 788:6.9 789:1 794:0.000478469 795:1 796:1 797:1 798:1 799:1 800:1 802:268.9 803:133.1 804:131.9 805:122.9 806:122.9 811:1 812:1 813:1 814:1 815:1 816:1 817:1 818:0.1 820:269.9 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 838:74.9 839:60.9 840:62.1 841:71.1 842:60.9 843:1 848:0.9 849:1 850:0.1 851:1 852:1 853:1 854:1 856:44.9 857:90.9 858:92.1 859:101.1 860:44.9 865:1 866:0.1 867:1 868:1 869:1 870:1 871:1 872:1 874:90.9 875:44.9 876:46.1 877:55.1 878:44.9 879:1 884:0.9 885:1 886:0.1 887:1 888:1 889:1 890:1 891:3 892:128.9 893:7.1 894:8.1 895:17.1 896:6.9 898:1 901:1 902:1 904:0.000675676 905:1 906:1 907:1 908:1 910:131.9 911:4.1 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.000682594 923:1 924:1 925:1 926:1 927:50 928:78.9 929:56.9 930:58.1 931:67.1 932:56.9 933:1 938:0.9 939:1 940:0.1 941:1 942:1 943:1 944:1 946:374.9 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 964:47.9 965:87.9 966:89.1 967:98.1 968:47.9 973:1 974:0.1 975:1 976:1 977:1 978:1 979:1 980:1 982:6.1 983:129.9 984:131.1 985:140.1 986:5.9 987:1 992:0.000477327 993:1 994:1 995:1 996:1 997:1 998:1 1000:2.1 1001:133.9 1002:135.1 1003:144.1 1004:1.9 1009:1 1010:0.1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1018:54 1019:109.9 1020:111.1 1021:120.1 1022:25.9 1023:1 1028:0.0704261 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1036:56 1037:111.9 1038:113.1 1039:122.1 1040:23.9 1041:1 1046:0.0800499 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:227.9 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1060:1 1063:1 1064:1 1066:0.9 1067:1 1068:1 1069:1 1070:0.1 1072:43 1073:98.9 1074:100.1 1075:109.1 1076:36.9 1077:1 1082:0.0157216 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1090:424.9 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1108:0.1 1109:135.9 1110:137.1 1111:146.1 1113:1 1118:0.000235294 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:135.9 1127:0.1 1128:1.1 1129:10.1 1135:1 1136:1 1137:1 1138:0.1 1139:1 1140:1 1141:1 1142:1 1144:137.9 1145:2.1 1146:1.1 1147:8.1 1153:1 1154:1 1155:1 1156:1 1157:1 1158:1 1159:1 1160:1 1162:145.9 1163:10.1 1164:9.1 1165:0.1 1171:1 1172:1 1173:1 1174:1 1175:1 1176:1 1177:1 1178:0.1 1180:142.9 1181:7.1 1182:6.1 1183:3.1 1184:2.9 1189:1 1190:1 1191:1 1192:1 1193:1 1194:1 1195:1 1196:0.1 1379:1
Cbc0038I Full problem 1481 rows 765 columns, reduced to 913 rows 334 columns - 28 fixed gives 862, 302 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 238 rows 119 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 888 rows 315 columns - 25 fixed gives 852, 290 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 339 rows 131 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 804 rows 266 columns - 2 fixed gives 800, 264 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 324 rows 156 columns
event(heuristicSolution) CbcModel.cpp:13363 Cbc0012I Integer solution of 1559 found by RINS after 217498 iterations and 1900 nodes (50.01 seconds)
event(heuristicSolution) CbcModel.cpp:13363 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1559 OBJ VAL ORIG(?): -1559 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:7 1:1 2:108 3:1 4:240 5:1 6:345 7:1 8:14 10:87 11:1 12:219 13:1 14:324 15:1 16:16 17:1 18:117 19:1 20:249 21:1 22:354 23:1 24:13 26:88 27:1 28:220 29:1 30:325 31:1 32:1 33:1 34:102 35:1 36:234 37:1 38:339 39:1 40:1 42:100 43:1 44:232 45:1 46:337 47:1 48:9 49:1 50:110 51:1 52:242 53:1 54:347 55:1 56:18 57:1 58:119 59:1 60:251 61:1 62:356 63:1 64:151 66:50 68:82 69:1 70:187 71:1 72:27 73:1 74:128 75:1 76:260 77:1 78:365 79:1 80:325 82:224 84:92 86:13 87:1 88:253 90:152 92:20 94:85 95:1 96:50 98:51 99:1 100:183 101:1 102:288 103:1 104:55 106:46 107:1 108:178 109:1 110:283 111:1 112:43 114:58 115:1 116:190 117:1 118:295 119:1 120:25 121:1 122:126 123:1 124:258 125:1 126:363 127:1 128:112 130:11 132:121 133:1 134:226 135:1 136:33 137:1 138:134 139:1 140:266 141:1 142:371 143:1 144:105 146:4 148:128 149:1 150:233 151:1 152:324 154:223 156:91 158:14 159:1 160:18 162:83 163:1 164:215 165:1 166:320 167:1 168:27 170:74 171:1 172:206 173:1 174:311 175:1 176:48 178:53 179:1 180:185 181:1 182:290 183:1 184:30 185:1 186:131 187:1 188:263 189:1 190:368 191:1 192:232 194:131 196:1 197:1 198:106 199:1 200:233 202:132 205:1 206:105 207:1 208:38 210:63 211:1 212:195 213:1 214:300 215:1 216:8 218:93 219:1 220:225 221:1 222:330 223:1 224:54 226:47 227:1 228:179 229:1 230:284 231:1 232:92 234:9 235:1 236:141 237:1 238:246 239:1 240:95 242:6 243:1 244:138 245:1 246:243 247:1 248:42 250:59 251:1 252:191 253:1 254:296 255:1 256:338 258:237 260:105 263:1 264:11 266:90 267:1 268:222 269:1 270:327 271:1 272:31 273:1 274:132 275:1 276:264 277:1 278:369 279:1 280:35 281:1 282:136 283:1 284:268 285:373 286:11 287:1 288:112 289:1 290:244 291:1 292:349 293:1 294:13 295:1 296:114 297:1 298:246 299:1 300:351 301:1 302:191 304:90 306:42 307:1 308:147 309:1 311:1 312:101 313:1 314:233 315:1 316:338 317:1 318:388 319:287 320:155 321:50 322:37 323:138 324:270 325:375 326:99 328:2 329:1 330:134 331:1 332:239 333:1 334:101 337:1 338:132 339:1 340:237 341:1 342:109 344:8 346:124 347:1 348:229 349:1 350:106 352:5 354:127 355:1 356:232 357:1 358:7 359:1 363:14 364:1 368:16 369:1 373:13 374:1 378:1 379:1 383:1 384:1 388:9 389:1 393:18 394:1 398:50 400:1 403:27 404:1 408:13 412:1 413:20 416:1 418:50 419:1 423:46 425:1 428:43 429:1 433:25 434:1 438:11 440:1 443:33 444:1 448:4 450:1 453:14 457:1 458:18 459:1 463:27 464:1 468:48 469:1 473:30 474:1 478:1 481:1 486:1 488:38 489:1 493:8 494:1 498:47 500:1 503:9 505:1 508:6 510:1 513:42 514:1 522:1 523:11 524:1 528:31 529:1 533:35 534:1 538:11 539:1 543:13 544:1 548:42 551:1 554:1 558:50 562:1 563:37 564:1 568:2 570:1 575:1 578:8 580:1 583:5 585:1 602:1 664:1 716:1 763:1
Postprocessed sol: 0:43 1:87 2:276 3:381 4:7 5:1 6:51 7:1 8:240 9:1 10:345 11:1 12:14 14:30 15:1 16:219 17:1 18:324 19:1 20:16 21:1 22:60 23:1 24:249 25:1 26:354 27:1 28:13 30:31 31:1 32:220 33:1 34:325 35:1 36:1 37:1 38:45 39:1 40:234 41:1 42:339 43:1 44:1 46:43 47:1 48:232 49:1 50:337 51:1 52:9 53:1 54:53 55:1 56:242 57:1 58:347 59:1 60:18 61:1 62:62 63:1 64:251 65:1 66:356 67:1 68:151 70:107 72:82 73:1 74:187 75:1 76:27 77:1 78:71 79:1 80:260 81:1 82:365 83:1 84:325 86:281 88:92 90:13 91:1 92:253 94:209 96:20 97:1 98:85 99:1 100:50 102:6 103:1 104:183 105:1 106:288 107:1 108:55 110:12 111:1 112:178 113:1 114:283 115:1 116:43 118:1 119:1 120:190 121:1 122:295 123:1 124:25 125:1 126:69 127:1 128:258 129:1 130:363 131:1 132:112 134:68 136:121 137:1 138:226 139:1 140:33 141:1 142:77 143:1 144:266 145:1 146:371 147:1 148:105 150:61 152:128 153:1 154:233 155:1 156:324 158:280 160:91 162:14 163:1 164:18 166:26 167:1 168:215 169:1 170:320 171:1 172:27 174:17 175:1 176:206 177:1 178:311 179:1 180:48 182:4 183:1 184:185 185:1 186:290 187:1 188:30 189:1 190:74 191:1 192:263 193:1 194:368 195:1 196:232 198:188 200:1 201:1 202:106 203:1 204:233 206:189 209:1 210:105 211:1 212:38 214:6 215:1 216:195 217:1 218:300 219:1 220:8 222:36 223:1 224:225 225:1 226:330 227:1 228:54 230:10 231:1 232:179 233:1 234:284 235:1 236:92 238:48 240:141 241:1 242:246 243:1 244:95 246:51 248:138 249:1 250:243 251:1 252:42 254:50 255:1 256:191 257:1 258:296 259:1 260:338 262:294 264:105 268:11 270:33 271:1 272:222 273:1 274:327 275:1 276:31 277:1 278:75 279:1 280:264 281:1 282:369 283:1 284:35 285:1 286:79 287:1 288:268 289:1 290:373 291:1 292:11 293:1 294:55 295:1 296:244 297:1 298:349 299:1 300:13 301:1 302:57 303:1 304:246 305:1 306:351 307:1 308:191 310:147 312:42 313:1 314:147 315:1 317:1 318:44 319:1 320:233 321:1 322:338 323:1 324:388 325:344 326:155 327:50 328:37 329:1 330:81 331:1 332:270 333:1 334:375 335:1 336:99 338:55 340:134 341:1 342:239 343:1 344:101 346:57 348:132 349:1 350:237 351:1 352:109 354:65 356:124 357:1 358:229 359:1 360:106 362:62 364:127 365:1 366:232 367:1 368:839 369:7 370:29.9 371:105.9 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:14 388:50.9 389:84.9 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:16 406:20.9 407:114.9 408:116.1 409:125.1 410:20.9 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:13 424:49.9 425:85.9 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:1 442:35.9 443:99.9 444:101.1 445:110.1 446:35.9 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:1 460:37.9 461:97.9 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:9 478:27.9 479:107.9 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:18 496:18.9 497:116.9 498:118.1 499:127.1 500:18.9 501:1 507:1 508:1 509:1 510:1 511:1 512:1 514:187.9 515:52.1 516:51.1 517:42.1 518:41.9 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 531:27 532:27 533:125.9 534:127.1 535:136.1 536:10.1 537:1 542:0.0407229 543:1 544:1 545:1 546:1 547:1 548:1 550:361.9 551:226.1 552:224.9 553:215.9 554:215.9 557:1 559:1 560:1 561:1 562:1 564:0.9 565:1 566:0.1 568:289.9 569:154.1 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 586:86.9 587:48.9 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:12 604:91.9 605:43.9 606:45.1 607:54.1 608:43.9 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:43 622:79.9 623:55.9 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 639:25 640:25 641:123.9 642:125.1 643:134.1 644:12.1 645:1 650:0.0312349 651:1 652:1 653:1 654:1 655:1 656:1 658:148.9 659:13.1 660:12.1 661:3.1 662:2.9 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:33 676:33 677:131.9 678:133.1 679:142.1 680:4.1 681:1 686:0.0686461 687:1 688:1 689:1 690:1 691:1 692:1 694:141.9 695:6.1 696:5.1 697:4.1 698:3.9 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:360.9 713:225.1 714:223.9 715:214.9 716:214.9 721:1 722:1 723:1 724:1 725:1 726:1 727:1 728:0.1 729:18 730:54.9 731:80.9 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:27 748:63.9 749:71.9 750:73.1 751:82.1 752:63.9 753:1 759:1 760:1 761:1 762:1 763:1 764:1 766:84.9 767:50.9 768:52.1 769:61.1 770:50.9 771:1 776:0.9 777:1 778:0.1 779:1 780:1 781:1 782:1 783:30 784:30 785:128.9 786:130.1 787:139.1 788:7.1 789:1 794:0.0547847 795:1 796:1 797:1 798:1 799:1 800:1 802:268.9 803:133.1 804:131.9 805:122.9 806:122.9 811:1 812:1 813:1 814:1 815:1 816:1 817:1 818:0.1 820:269.9 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:38 838:74.9 839:60.9 840:62.1 841:71.1 842:60.9 843:1 848:0.9 849:1 850:0.1 851:1 852:1 853:1 854:1 855:8 856:44.9 857:90.9 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 874:90.9 875:44.9 876:46.1 877:55.1 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 891:3 892:128.9 893:7.1 894:8.1 895:17.1 896:6.9 898:1 901:1 902:1 904:0.000675676 905:1 906:1 907:1 908:1 910:131.9 911:4.1 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.000682594 923:1 924:1 925:1 926:1 927:42 928:78.9 929:56.9 930:58.1 931:67.1 932:56.9 933:1 938:0.9 939:1 940:0.1 941:1 942:1 943:1 944:1 946:374.9 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:11 964:47.9 965:87.9 966:89.1 967:98.1 968:47.9 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:31 982:31 983:129.9 984:131.1 985:140.1 986:6.1 987:1 992:0.0594272 993:1 994:1 995:1 996:1 997:1 998:1 999:35 1000:35 1001:133.9 1002:135.1 1003:144.1 1004:2.1 1005:1 1010:0.0777778 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:11 1018:25.9 1019:109.9 1020:111.1 1021:120.1 1022:25.9 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:13 1036:23.9 1037:111.9 1038:113.1 1039:122.1 1040:23.9 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:227.9 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1060:1 1063:1 1064:1 1066:0.9 1067:1 1068:1 1069:1 1070:0.1 1072:36.9 1073:98.9 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1090:424.9 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1107:37 1108:37 1109:135.9 1110:137.1 1111:146.1 1112:0.1 1113:1 1118:0.0868235 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:135.9 1127:0.1 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1138:0.000346021 1139:1 1140:1 1141:1 1142:1 1144:137.9 1145:2.1 1146:1.1 1147:8.1 1150:1 1153:1 1154:1 1156:0.00731707 1157:1 1158:1 1159:1 1160:1 1162:145.9 1163:10.1 1164:9.1 1165:0.1 1171:1 1172:1 1173:1 1174:1 1175:1 1176:1 1177:1 1178:0.1 1180:142.9 1181:7.1 1182:6.1 1183:3.1 1184:2.9 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1211:1
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1559 OBJ VAL ORIG(?): -1559 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:7 1:1 2:108 3:1 4:240 5:1 6:345 7:1 8:14 10:87 11:1 12:219 13:1 14:324 15:1 16:16 17:1 18:117 19:1 20:249 21:1 22:354 23:1 24:13 26:88 27:1 28:220 29:1 30:325 31:1 32:1 33:1 34:102 35:1 36:234 37:1 38:339 39:1 40:1 42:100 43:1 44:232 45:1 46:337 47:1 48:9 49:1 50:110 51:1 52:242 53:1 54:347 55:1 56:18 57:1 58:119 59:1 60:251 61:1 62:356 63:1 64:151 66:50 68:82 69:1 70:187 71:1 72:27 73:1 74:128 75:1 76:260 77:1 78:365 79:1 80:325 82:224 84:92 86:13 87:1 88:253 90:152 92:20 94:85 95:1 96:50 98:51 99:1 100:183 101:1 102:288 103:1 104:55 106:46 107:1 108:178 109:1 110:283 111:1 112:43 114:58 115:1 116:190 117:1 118:295 119:1 120:25 121:1 122:126 123:1 124:258 125:1 126:363 127:1 128:112 130:11 132:121 133:1 134:226 135:1 136:33 137:1 138:134 139:1 140:266 141:1 142:371 143:1 144:105 146:4 148:128 149:1 150:233 151:1 152:324 154:223 156:91 158:14 159:1 160:18 162:83 163:1 164:215 165:1 166:320 167:1 168:27 170:74 171:1 172:206 173:1 174:311 175:1 176:48 178:53 179:1 180:185 181:1 182:290 183:1 184:30 185:1 186:131 187:1 188:263 189:1 190:368 191:1 192:232 194:131 196:1 197:1 198:106 199:1 200:233 202:132 205:1 206:105 207:1 208:38 210:63 211:1 212:195 213:1 214:300 215:1 216:8 218:93 219:1 220:225 221:1 222:330 223:1 224:54 226:47 227:1 228:179 229:1 230:284 231:1 232:92 234:9 235:1 236:141 237:1 238:246 239:1 240:95 242:6 243:1 244:138 245:1 246:243 247:1 248:42 250:59 251:1 252:191 253:1 254:296 255:1 256:338 258:237 260:105 263:1 264:11 266:90 267:1 268:222 269:1 270:327 271:1 272:31 273:1 274:132 275:1 276:264 277:1 278:369 279:1 280:35 281:1 282:136 283:1 284:268 285:373 286:11 287:1 288:112 289:1 290:244 291:1 292:349 293:1 294:13 295:1 296:114 297:1 298:246 299:1 300:351 301:1 302:191 304:90 306:42 307:1 308:147 309:1 311:1 312:101 313:1 314:233 315:1 316:338 317:1 318:388 319:287 320:155 321:50 322:37 323:138 324:270 325:375 326:99 328:2 329:1 330:134 331:1 332:239 333:1 334:101 337:1 338:132 339:1 340:237 341:1 342:109 344:8 346:124 347:1 348:229 349:1 350:106 352:5 354:127 355:1 356:232 357:1 358:7 359:1 363:14 364:1 368:16 369:1 373:13 374:1 378:1 379:1 383:1 384:1 388:9 389:1 393:18 394:1 398:50 400:1 403:27 404:1 408:13 412:1 413:20 416:1 418:50 419:1 423:46 425:1 428:43 429:1 433:25 434:1 438:11 440:1 443:33 444:1 448:4 450:1 453:14 457:1 458:18 459:1 463:27 464:1 468:48 469:1 473:30 474:1 478:1 481:1 486:1 488:38 489:1 493:8 494:1 498:47 500:1 503:9 505:1 508:6 510:1 513:42 514:1 522:1 523:11 524:1 528:31 529:1 533:35 534:1 538:11 539:1 543:13 544:1 548:42 551:1 554:1 558:50 562:1 563:37 564:1 568:2 570:1 575:1 578:8 580:1 583:5 585:1 602:1 664:1 716:1 763:1
Postprocessed sol: 0:43 1:142 2:368 3:369 4:7 5:1 6:106 7:1 8:332 9:1 10:333 11:1 12:14 14:85 15:1 16:311 17:1 18:312 19:1 20:16 21:1 22:115 23:1 24:341 25:1 26:342 27:1 28:13 30:86 31:1 32:312 33:1 34:313 35:1 36:1 37:1 38:100 39:1 40:326 41:1 42:327 43:1 44:1 46:98 47:1 48:324 49:1 50:325 51:1 52:9 53:1 54:108 55:1 56:334 57:1 58:335 59:1 60:18 61:1 62:117 63:1 64:343 65:1 66:344 67:1 68:151 70:52 72:174 73:1 74:175 75:1 76:27 77:1 78:126 79:1 80:352 81:1 82:353 83:1 84:325 86:226 90:13 91:1 92:253 94:154 96:72 97:1 98:73 99:1 100:50 102:49 103:1 104:275 105:1 106:276 107:1 108:55 110:44 111:1 112:270 113:1 114:271 115:1 116:43 118:56 119:1 120:282 121:1 122:283 123:1 124:25 125:1 126:124 127:1 128:350 129:1 130:351 131:1 132:112 134:13 136:213 137:1 138:214 139:1 140:33 141:1 142:132 143:1 144:358 145:1 146:359 147:1 148:105 150:6 152:220 153:1 154:221 155:1 156:324 158:225 160:1 162:2 163:1 164:18 166:81 167:1 168:307 169:1 170:308 171:1 172:27 174:72 175:1 176:298 177:1 178:299 179:1 180:48 182:51 183:1 184:277 185:1 186:278 187:1 188:30 189:1 190:129 191:1 192:355 193:1 194:356 195:1 196:232 198:133 200:93 201:1 202:94 203:1 204:233 206:134 208:92 209:1 210:93 211:1 212:38 214:61 215:1 216:287 217:1 218:288 219:1 220:8 222:91 223:1 224:317 225:1 226:318 227:1 228:54 230:45 231:1 232:271 233:1 234:272 235:1 236:92 238:7 240:233 241:1 242:234 243:1 244:95 246:4 248:230 249:1 250:231 251:1 252:42 254:57 255:1 256:283 257:1 258:284 259:1 260:338 262:239 264:13 268:11 270:88 271:1 272:314 273:1 274:315 275:1 276:31 277:1 278:130 279:1 280:356 281:1 282:357 283:1 284:35 285:1 286:134 287:1 288:360 289:1 290:361 291:1 292:11 293:1 294:110 295:1 296:336 297:1 298:337 299:1 300:13 301:1 302:112 303:1 304:338 305:1 306:339 307:1 308:191 310:92 312:134 313:1 314:135 315:1 317:1 318:99 319:1 320:325 321:1 322:326 323:1 324:388 325:289 326:63 327:62 328:37 329:1 330:136 331:1 332:362 333:1 334:363 335:1 336:99 340:226 341:1 342:227 343:1 344:101 346:2 348:224 349:1 350:225 351:1 352:109 354:10 356:216 357:1 358:217 359:1 360:106 362:7 364:219 365:1 366:220 367:1 368:1337 369:7 370:29.9 371:106 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:14 388:50.9 389:85 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:16 406:20.9 407:115 408:116.1 409:125.1 410:20.9 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:13 424:49.9 425:86 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:1 442:35.9 443:100 444:101.1 445:110.1 446:35.9 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:1 460:37.9 461:98 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:9 478:27.9 479:108 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:18 496:18.9 497:117 498:118.1 499:127.1 500:18.9 501:1 507:1 508:1 509:1 510:1 511:1 512:1 514:187.9 515:52 516:51.1 517:42.1 518:41.9 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 531:27 532:27 533:126 534:127.1 535:136.1 536:10.1 537:1 542:0.0407229 543:1 544:1 545:1 546:1 547:1 548:1 550:361.9 551:226 552:224.9 553:215.9 554:215.9 557:1 559:1 560:1 561:1 562:1 564:0.9 565:1 566:0.1 568:289.9 569:154 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 585:49 586:86.9 587:49 588:50.1 589:59.1 590:49 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:44 604:91.9 605:44 606:45.1 607:54.1 608:44 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:43 622:79.9 623:56 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 639:25 640:25 641:124 642:125.1 643:134.1 644:12.1 645:1 650:0.0312349 651:1 652:1 653:1 654:1 655:1 656:1 657:13 658:148.9 659:13 660:12.1 661:214 662:3.1 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:33 676:33 677:132 678:133.1 679:142.1 680:4.1 681:1 686:0.0686461 687:1 688:1 689:1 690:1 691:1 692:1 693:6 694:141.9 695:6 696:5.1 697:4.1 698:4.1 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:360.9 713:225 714:223.9 715:214.9 716:214.9 721:1 722:1 723:1 724:1 725:1 726:1 727:1 728:0.1 729:18 730:54.9 731:81 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:27 748:63.9 749:72 750:73.1 751:82.1 752:63.9 753:1 759:1 760:1 761:1 762:1 763:1 764:1 765:28 766:84.9 767:51 768:52.1 769:61.1 770:50.9 771:1 776:0.9 777:1 778:0.1 779:1 780:1 781:1 782:1 783:30 784:7.1 785:129 786:130.1 787:139.1 788:7.1 789:1 795:1 796:1 797:1 798:1 799:1 800:1 802:268.9 803:133 804:131.9 805:122.9 806:122.9 811:1 812:1 813:1 814:1 815:1 816:1 817:1 818:0.1 820:269.9 821:134 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:38 838:74.9 839:61 840:62.1 841:71.1 842:60.9 843:1 848:0.9 849:1 850:0.1 851:1 852:1 853:1 854:1 855:8 856:44.9 857:91 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:45 874:90.9 875:45 876:46.1 877:55.1 878:45 880:1 883:1 884:1 887:1 888:1 889:1 890:1 891:7 892:128.9 893:7 894:8.1 895:17.1 896:7 898:1 901:1 902:1 905:1 906:1 907:1 908:1 910:131.9 911:4 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.000341297 923:1 924:1 925:1 926:1 927:42 928:78.9 929:57 930:58.1 931:67.1 932:56.9 933:1 938:0.9 939:1 940:0.1 941:1 942:1 943:1 944:1 946:374.9 947:239 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:11 964:47.9 965:88 966:89.1 967:98.1 968:47.9 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:31 982:31 983:130 984:131.1 985:140.1 986:6.1 987:1 992:0.0594272 993:1 994:1 995:1 996:1 997:1 998:1 999:35 1000:35 1001:134 1002:135.1 1003:144.1 1004:2.1 1005:1 1010:0.0777778 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:11 1018:25.9 1019:110 1020:111.1 1021:120.1 1022:25.9 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:13 1036:23.9 1037:112 1038:113.1 1039:122.1 1040:23.9 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1053:92 1054:227.9 1055:92 1056:91.1 1057:135 1058:82.1 1060:1 1063:1 1064:1 1066:0.9 1067:1 1068:1 1069:1 1070:0.1 1072:36.9 1073:99 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1090:424.9 1091:289 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1107:37 1108:37 1109:136 1110:137.1 1111:146.1 1112:0.1 1113:1 1118:0.0868235 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:135.9 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1139:1 1140:1 1141:1 1142:1 1143:2 1144:137.9 1145:2 1146:1.1 1147:8.1 1148:0.1 1150:1 1153:1 1154:1 1156:0.00662021 1157:1 1158:1 1159:1 1160:1 1162:145.9 1163:10 1164:9.1 1165:0.1 1171:1 1172:1 1173:1 1174:1 1175:1 1176:1 1177:1 1178:0.1 1179:7 1180:142.9 1181:7 1182:6.1 1183:220 1184:3.1 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1211:1 1274:1 1332:1
Cbc0010I After 2000 nodes, 125 on tree, 1559 best solution, best possible 0 (51.38 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 36 rows 34 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 333 rows 164 columns
event(heuristicSolution) CbcModel.cpp:13363 Cbc0012I Integer solution of 1558 found by RINS after 242787 iterations and 2301 nodes (54.10 seconds)
event(heuristicSolution) CbcModel.cpp:13363 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1558 OBJ VAL ORIG(?): -1558 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:7 1:1 2:113 3:1 4:240 5:1 6:345 7:1 8:14 10:92 11:1 12:219 13:1 14:324 15:1 16:16 17:1 18:122 19:1 20:249 21:1 22:354 23:1 24:13 26:93 27:1 28:220 29:1 30:325 31:1 32:1 33:1 34:107 35:1 36:234 37:1 38:339 39:1 40:1 42:105 43:1 44:232 45:1 46:337 47:1 48:9 49:1 50:115 51:1 52:242 53:1 54:347 55:1 56:18 57:1 58:124 59:1 60:251 61:1 62:356 63:1 64:151 66:45 68:82 69:1 70:187 71:1 72:27 73:1 74:133 75:1 76:260 77:1 78:365 79:1 80:325 82:219 84:92 86:13 87:1 88:253 90:147 92:20 94:85 95:1 96:50 98:56 99:1 100:183 101:1 102:288 103:1 104:55 106:51 107:1 108:178 109:1 110:283 111:1 112:43 114:63 115:1 116:190 117:1 118:295 119:1 120:25 121:1 122:131 123:1 124:258 125:1 126:363 127:1 128:112 130:6 132:121 133:1 134:226 135:1 136:33 137:1 138:139 139:1 140:266 141:1 142:371 143:1 144:105 146:1 147:1 148:128 149:1 150:233 151:1 152:324 154:218 156:91 158:14 159:1 160:18 162:88 163:1 164:215 165:1 166:320 167:1 168:27 170:79 171:1 172:206 173:1 174:311 175:1 176:48 178:58 179:1 180:185 181:1 182:290 183:1 184:30 185:1 186:136 187:1 188:263 189:1 190:368 191:1 192:232 194:126 196:1 197:1 198:106 199:1 200:233 202:127 205:1 206:105 207:1 208:38 210:68 211:1 212:195 213:1 214:300 215:1 216:8 218:98 219:1 220:225 221:1 222:330 223:1 224:54 226:52 227:1 228:179 229:1 230:284 231:1 232:92 234:14 235:1 236:141 237:1 238:246 239:1 240:95 242:11 243:1 244:138 245:1 246:243 247:1 248:42 250:64 251:1 252:191 253:1 254:296 255:1 256:338 258:232 260:105 263:1 264:11 266:95 267:1 268:222 269:1 270:327 271:1 272:31 273:1 274:137 275:1 276:264 277:1 278:369 279:1 280:35 281:1 282:141 283:1 284:268 285:373 286:11 287:1 288:117 289:1 290:244 291:1 292:349 293:1 294:13 295:1 296:119 297:1 298:246 299:1 300:351 301:1 302:191 304:85 306:42 307:1 308:147 309:1 311:1 312:106 313:1 314:233 315:1 316:338 317:1 318:388 319:282 320:155 321:50 322:37 323:143 324:270 325:375 326:99 328:7 329:1 330:134 331:1 332:239 333:1 334:101 336:5 337:1 338:132 339:1 340:237 341:1 342:109 344:3 346:124 347:1 348:229 349:1 350:106 353:1 354:127 355:1 356:232 357:1 358:7 359:1 363:14 364:1 368:16 369:1 373:13 374:1 378:1 379:1 383:1 384:1 388:9 389:1 393:18 394:1 398:45 400:1 403:27 404:1 408:13 412:1 413:20 416:1 418:50 419:1 423:51 425:1 428:43 429:1 433:25 434:1 438:6 440:1 443:33 444:1 448:1 450:1 453:14 457:1 458:18 459:1 463:27 464:1 468:48 469:1 473:30 474:1 478:1 481:1 486:1 488:38 489:1 493:8 494:1 498:52 500:1 503:14 505:1 508:11 510:1 513:42 514:1 522:1 523:11 524:1 528:31 529:1 533:35 534:1 538:11 539:1 543:13 544:1 548:42 551:1 554:1 558:50 562:1 563:37 564:1 568:7 570:1 573:5 575:1 578:3 580:1 585:1 602:1 666:1 716:1 763:1
Postprocessed sol: 0:54 1:142 2:368 3:381 4:18 5:1 6:106 7:1 8:332 9:1 10:345 11:1 12:3 14:85 15:1 16:311 17:1 18:324 19:1 20:27 21:1 22:115 23:1 24:341 25:1 26:354 27:1 28:2 30:86 31:1 32:312 33:1 34:325 35:1 36:12 37:1 38:100 39:1 40:326 41:1 42:339 43:1 44:10 45:1 46:98 47:1 48:324 49:1 50:337 51:1 52:20 53:1 54:108 55:1 56:334 57:1 58:347 59:1 60:29 61:1 62:117 63:1 64:343 65:1 66:356 67:1 68:140 70:52 72:174 73:1 74:187 75:1 76:38 77:1 78:126 79:1 80:352 81:1 82:365 83:1 84:314 86:226 90:13 91:1 92:242 94:154 96:72 98:85 99:1 100:39 102:49 103:1 104:275 105:1 106:288 107:1 108:44 110:44 111:1 112:270 113:1 114:283 115:1 116:32 118:56 119:1 120:282 121:1 122:295 123:1 124:36 125:1 126:124 127:1 128:350 129:1 130:363 131:1 132:101 134:13 136:213 137:1 138:226 139:1 140:44 141:1 142:132 143:1 144:358 145:1 146:371 147:1 148:94 150:6 152:220 153:1 154:233 155:1 156:313 158:225 160:1 162:14 163:1 164:7 166:81 167:1 168:307 169:1 170:320 171:1 172:16 174:72 175:1 176:298 177:1 178:311 179:1 180:37 182:51 183:1 184:277 185:1 186:290 187:1 188:41 189:1 190:129 191:1 192:355 193:1 194:368 195:1 196:221 198:133 200:93 201:1 202:106 203:1 204:222 206:134 208:92 209:1 210:105 211:1 212:27 214:61 215:1 216:287 217:1 218:300 219:1 220:3 221:1 222:91 223:1 224:317 225:1 226:330 227:1 228:43 230:45 231:1 232:271 233:1 234:284 235:1 236:81 238:7 239:1 240:233 241:1 242:246 243:1 244:84 246:4 247:1 248:230 249:1 250:243 251:1 252:31 254:57 255:1 256:283 257:1 258:296 259:1 260:327 262:239 264:13 267:1 269:1 270:88 271:1 272:314 273:1 274:327 275:1 276:42 277:1 278:130 279:1 280:356 281:1 282:369 283:1 284:46 285:1 286:134 287:1 288:360 289:1 290:373 291:1 292:22 293:1 294:110 295:1 296:336 297:1 298:349 299:1 300:24 301:1 302:112 303:1 304:338 305:1 306:351 307:1 308:180 310:92 312:134 313:1 314:147 315:1 316:11 317:1 318:99 319:1 320:325 321:1 322:338 323:1 324:377 325:289 326:63 327:50 328:48 329:1 330:136 331:1 332:362 333:1 334:375 335:1 336:88 339:1 340:226 341:1 342:239 343:1 344:90 346:2 348:224 349:1 350:237 351:1 352:98 354:10 356:216 357:1 358:229 359:1 360:95 362:7 364:219 365:1 366:232 367:1 368:1535 369:18 370:29.9 371:106 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:3 388:50.9 389:85 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:27 406:27 407:115 408:116.1 409:125.1 410:21.1 411:1 416:0.014604 417:1 418:1 419:1 420:1 421:1 422:1 423:2 424:49.9 425:86 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:12 442:35.9 443:100 444:101.1 445:110.1 446:35.9 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:10 460:37.9 461:98 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:20 478:27.9 479:108 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:29 496:19.1 497:117 498:118.1 499:127.1 500:19.1 501:1 507:1 508:1 509:1 510:1 511:1 512:1 513:7 514:187.9 515:52 516:51.1 517:42.1 518:41.9 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 531:38 532:38 533:126 534:127.1 535:136.1 536:10.1 537:1 542:0.0672289 543:1 544:1 545:1 546:1 547:1 548:1 550:361.9 551:226 552:224.9 553:215.9 554:215.9 557:1 559:1 560:1 561:1 562:1 564:0.9 565:1 566:0.1 568:289.9 569:154 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 585:39 586:86.9 587:49 588:50.1 589:59.1 590:48.9 591:1 596:0.9 597:1 598:0.1 599:1 600:1 601:1 602:1 603:44 604:91.9 605:44 606:45.1 607:54.1 608:44 609:1 614:0.9 615:1 616:0.1 617:1 618:1 619:1 620:1 621:32 622:79.9 623:56 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 639:36 640:36 641:124 642:125.1 643:134.1 644:12.1 645:1 650:0.0578692 651:1 652:1 653:1 654:1 655:1 656:1 657:13 658:148.9 659:13 660:12.1 661:226 662:3.1 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:44 676:44 677:132 678:133.1 679:142.1 680:4.1 681:1 686:0.0947743 687:1 688:1 689:1 690:1 691:1 692:1 693:6 694:141.9 695:6 696:5.1 697:233 698:4.1 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:360.9 713:225 714:223.9 715:214.9 716:214.9 721:1 722:1 723:1 724:1 725:1 726:1 727:1 728:0.1 729:7 730:54.9 731:81 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:16 748:63.9 749:72 750:73.1 751:82.1 752:63.9 753:1 759:1 760:1 761:1 762:1 763:1 764:1 765:37 766:84.9 767:51 768:52.1 769:61.1 770:50.9 771:1 776:0.9 777:1 778:0.1 779:1 780:1 781:1 782:1 783:41 784:41 785:129 786:130.1 787:139.1 788:7.1 789:1 794:0.0811005 795:1 796:1 797:1 798:1 799:1 800:1 802:268.9 803:133 804:131.9 805:122.9 806:122.9 811:1 812:1 813:1 814:1 815:1 816:1 817:1 818:0.1 820:269.9 821:134 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:27 838:74.9 839:61 840:62.1 841:71.1 842:60.9 843:1 848:0.9 849:1 850:0.1 851:1 852:1 853:1 854:1 855:3 856:44.9 857:91 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:43 874:90.9 875:45 876:46.1 877:55.1 878:44.9 879:1 884:0.9 885:1 886:0.1 887:1 888:1 889:1 890:1 891:8 892:128.9 893:7 894:8.1 895:17.1 896:7 898:1 901:1 902:1 905:1 906:1 907:1 908:1 910:131.9 911:4 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.000341297 923:1 924:1 925:1 926:1 927:31 928:78.9 929:57 930:58.1 931:67.1 932:56.9 933:1 938:0.9 939:1 940:0.1 941:1 942:1 943:1 944:1 946:374.9 947:239 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 964:47.9 965:88 966:89.1 967:98.1 968:47.9 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:42 982:42 983:130 984:131.1 985:140.1 986:6.1 987:1 992:0.0856802 993:1 994:1 995:1 996:1 997:1 998:1 999:46 1000:46 1001:134 1002:135.1 1003:144.1 1004:2.1 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:22 1018:25.9 1019:110 1020:111.1 1021:120.1 1022:25.9 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:112 1038:113.1 1039:122.1 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1053:92 1054:227.9 1055:92 1056:91.1 1057:147 1058:82.1 1063:1 1064:1 1065:1 1066:1 1067:1 1068:1 1069:1 1070:0.1 1071:11 1072:36.9 1073:99 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:50 1090:424.9 1091:289 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1107:48 1108:0.1 1109:136 1110:137.1 1111:146.1 1112:0.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:135.9 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1139:1 1140:1 1141:1 1142:1 1143:2 1144:137.9 1145:2 1146:1.1 1147:8.1 1148:0.1 1150:1 1153:1 1154:1 1156:0.00662021 1157:1 1158:1 1159:1 1160:1 1162:145.9 1163:10 1164:9.1 1165:0.1 1171:1 1172:1 1173:1 1174:1 1175:1 1176:1 1177:1 1178:0.1 1179:7 1180:142.9 1181:7 1182:6.1 1183:232 1184:3.1 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1214:1 1379:1
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1558 OBJ VAL ORIG(?): -1558 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:7 1:1 2:113 3:1 4:240 5:1 6:345 7:1 8:14 10:92 11:1 12:219 13:1 14:324 15:1 16:16 17:1 18:122 19:1 20:249 21:1 22:354 23:1 24:13 26:93 27:1 28:220 29:1 30:325 31:1 32:1 33:1 34:107 35:1 36:234 37:1 38:339 39:1 40:1 42:105 43:1 44:232 45:1 46:337 47:1 48:9 49:1 50:115 51:1 52:242 53:1 54:347 55:1 56:18 57:1 58:124 59:1 60:251 61:1 62:356 63:1 64:151 66:45 68:82 69:1 70:187 71:1 72:27 73:1 74:133 75:1 76:260 77:1 78:365 79:1 80:325 82:219 84:92 86:13 87:1 88:253 90:147 92:20 94:85 95:1 96:50 98:56 99:1 100:183 101:1 102:288 103:1 104:55 106:51 107:1 108:178 109:1 110:283 111:1 112:43 114:63 115:1 116:190 117:1 118:295 119:1 120:25 121:1 122:131 123:1 124:258 125:1 126:363 127:1 128:112 130:6 132:121 133:1 134:226 135:1 136:33 137:1 138:139 139:1 140:266 141:1 142:371 143:1 144:105 146:1 147:1 148:128 149:1 150:233 151:1 152:324 154:218 156:91 158:14 159:1 160:18 162:88 163:1 164:215 165:1 166:320 167:1 168:27 170:79 171:1 172:206 173:1 174:311 175:1 176:48 178:58 179:1 180:185 181:1 182:290 183:1 184:30 185:1 186:136 187:1 188:263 189:1 190:368 191:1 192:232 194:126 196:1 197:1 198:106 199:1 200:233 202:127 205:1 206:105 207:1 208:38 210:68 211:1 212:195 213:1 214:300 215:1 216:8 218:98 219:1 220:225 221:1 222:330 223:1 224:54 226:52 227:1 228:179 229:1 230:284 231:1 232:92 234:14 235:1 236:141 237:1 238:246 239:1 240:95 242:11 243:1 244:138 245:1 246:243 247:1 248:42 250:64 251:1 252:191 253:1 254:296 255:1 256:338 258:232 260:105 263:1 264:11 266:95 267:1 268:222 269:1 270:327 271:1 272:31 273:1 274:137 275:1 276:264 277:1 278:369 279:1 280:35 281:1 282:141 283:1 284:268 285:373 286:11 287:1 288:117 289:1 290:244 291:1 292:349 293:1 294:13 295:1 296:119 297:1 298:246 299:1 300:351 301:1 302:191 304:85 306:42 307:1 308:147 309:1 311:1 312:106 313:1 314:233 315:1 316:338 317:1 318:388 319:282 320:155 321:50 322:37 323:143 324:270 325:375 326:99 328:7 329:1 330:134 331:1 332:239 333:1 334:101 336:5 337:1 338:132 339:1 340:237 341:1 342:109 344:3 346:124 347:1 348:229 349:1 350:106 353:1 354:127 355:1 356:232 357:1 358:7 359:1 363:14 364:1 368:16 369:1 373:13 374:1 378:1 379:1 383:1 384:1 388:9 389:1 393:18 394:1 398:45 400:1 403:27 404:1 408:13 412:1 413:20 416:1 418:50 419:1 423:51 425:1 428:43 429:1 433:25 434:1 438:6 440:1 443:33 444:1 448:1 450:1 453:14 457:1 458:18 459:1 463:27 464:1 468:48 469:1 473:30 474:1 478:1 481:1 486:1 488:38 489:1 493:8 494:1 498:52 500:1 503:14 505:1 508:11 510:1 513:42 514:1 522:1 523:11 524:1 528:31 529:1 533:35 534:1 538:11 539:1 543:13 544:1 548:42 551:1 554:1 558:50 562:1 563:37 564:1 568:7 570:1 573:5 575:1 578:3 580:1 585:1 602:1 666:1 716:1 763:1
Postprocessed sol: 0:54 1:149 2:234 3:381 4:18 5:1 6:113 7:1 8:198 9:1 10:345 11:1 12:3 14:92 15:1 16:177 17:1 18:324 19:1 20:27 21:1 22:122 23:1 24:207 25:1 26:354 27:1 28:2 30:93 31:1 32:178 33:1 34:325 35:1 36:12 37:1 38:107 39:1 40:192 41:1 42:339 43:1 44:10 45:1 46:105 47:1 48:190 49:1 50:337 51:1 52:20 53:1 54:115 55:1 56:200 57:1 58:347 59:1 60:29 61:1 62:124 63:1 64:209 65:1 66:356 67:1 68:140 70:45 72:40 73:1 74:187 75:1 76:38 77:1 78:133 79:1 80:218 81:1 82:365 83:1 84:314 86:219 88:134 90:13 91:1 92:242 94:147 96:62 98:85 99:1 100:39 102:56 103:1 104:141 105:1 106:288 107:1 108:44 110:51 111:1 112:136 113:1 114:283 115:1 116:32 118:63 119:1 120:148 121:1 122:295 123:1 124:36 125:1 126:131 127:1 128:216 129:1 130:363 131:1 132:101 134:6 136:79 137:1 138:226 139:1 140:44 141:1 142:139 143:1 144:224 145:1 146:371 147:1 148:94 150:1 152:86 153:1 154:233 155:1 156:313 158:218 160:133 162:14 163:1 164:7 166:88 167:1 168:173 169:1 170:320 171:1 172:16 174:79 175:1 176:164 177:1 178:311 179:1 180:37 182:58 183:1 184:143 185:1 186:290 187:1 188:41 189:1 190:136 191:1 192:221 193:1 194:368 195:1 196:221 198:126 200:41 202:106 203:1 204:222 206:127 208:42 210:105 211:1 212:27 214:68 215:1 216:153 217:1 218:300 219:1 220:3 221:1 222:98 223:1 224:183 225:1 226:330 227:1 228:43 230:52 231:1 232:137 233:1 234:284 235:1 236:81 238:14 239:1 240:99 241:1 242:246 243:1 244:84 246:11 247:1 248:96 249:1 250:243 251:1 252:31 254:64 255:1 256:149 257:1 258:296 259:1 260:327 262:232 264:147 267:1 269:1 270:95 271:1 272:180 273:1 274:327 275:1 276:42 277:1 278:137 279:1 280:222 281:1 282:369 283:1 284:46 285:1 286:141 287:1 288:226 289:1 290:373 291:1 292:22 293:1 294:117 295:1 296:202 297:1 298:349 299:1 300:24 301:1 302:119 303:1 304:204 305:1 306:351 307:1 308:180 310:85 313:1 314:147 315:1 316:11 317:1 318:106 319:1 320:191 321:1 322:338 323:1 324:377 325:282 326:197 327:50 328:48 329:1 330:143 331:1 332:228 333:1 334:375 335:1 336:88 338:7 339:1 340:92 341:1 342:239 343:1 344:90 346:5 348:90 349:1 350:237 351:1 352:98 354:3 356:82 357:1 358:229 359:1 360:95 364:85 365:1 366:232 367:1 368:1293 369:18 370:29.9 371:106.1 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:3 388:50.9 389:85.1 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:27 406:21.1 407:115.1 408:116.1 409:125.1 410:21.1 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:2 424:49.9 425:86.1 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:12 442:35.9 443:100.1 444:101.1 445:110.1 446:35.9 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:10 460:37.9 461:98.1 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:20 478:27.9 479:108.1 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:29 496:19.1 497:117.1 498:118.1 499:127.1 500:19.1 501:1 507:1 508:1 509:1 510:1 511:1 512:1 514:187.9 515:51.9 516:50.9 517:42.1 518:41.9 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 531:38 532:38 533:126.1 534:127.1 535:136.1 536:10.1 537:1 542:0.0672289 543:1 544:1 545:1 546:1 547:1 548:1 550:361.9 551:225.9 552:224.9 553:215.9 554:215.9 559:1 560:1 561:1 562:1 563:1 564:1 565:1 566:0.1 568:289.9 569:153.9 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 585:39 586:86.9 587:56 588:50.1 589:59.1 590:48.9 591:1 596:0.9 597:1 598:0.1 599:1 600:1 601:1 602:1 603:44 604:91.9 605:51 606:45.1 607:54.1 608:44 609:1 614:0.9 615:1 616:0.1 617:1 618:1 619:1 620:1 621:32 622:79.9 623:63 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 639:36 640:12.1 641:124.1 642:125.1 643:134.1 644:12.1 645:1 651:1 652:1 653:1 654:1 655:1 656:1 658:148.9 659:12.9 660:12.1 661:3.1 662:2.9 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:44 676:44 677:132.1 678:133.1 679:142.1 680:4.1 681:1 686:0.0947743 687:1 688:1 689:1 690:1 691:1 692:1 694:141.9 695:5.9 696:5.1 697:4.1 698:3.9 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:360.9 713:224.9 714:223.9 715:214.9 716:214.9 721:1 722:1 723:1 724:1 725:1 726:1 727:1 728:0.1 729:7 730:54.9 731:81.1 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:16 748:63.9 749:72.1 750:73.1 751:82.1 752:63.9 753:1 759:1 760:1 761:1 762:1 763:1 764:1 765:37 766:84.9 767:58 768:52.1 769:61.1 770:50.9 771:1 776:0.9 777:1 778:0.1 779:1 780:1 781:1 782:1 783:41 784:41 785:129.1 786:130.1 787:139.1 788:7.1 789:1 794:0.0811005 795:1 796:1 797:1 798:1 799:1 800:1 802:268.9 803:132.9 804:131.9 805:122.9 806:122.9 811:1 812:1 813:1 814:1 815:1 816:1 817:1 818:0.1 820:269.9 821:133.9 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:27 838:74.9 839:68 840:62.1 841:71.1 842:60.9 843:1 848:0.9 849:1 850:0.1 851:1 852:1 853:1 854:1 855:3 856:44.9 857:91.1 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 873:43 874:90.9 875:52 876:46.1 877:55.1 878:44.9 879:1 884:0.9 885:1 886:0.1 887:1 888:1 889:1 890:1 891:7 892:128.9 893:14 894:8.1 895:17.1 896:7 898:1 901:1 902:1 904:0.0236486 905:1 906:1 907:1 908:1 909:4 910:131.9 911:11 912:5.1 913:14.1 914:4 916:1 919:1 920:1 922:0.0238908 923:1 924:1 925:1 926:1 927:31 928:78.9 929:64 930:58.1 931:67.1 932:56.9 933:1 938:0.9 939:1 940:0.1 941:1 942:1 943:1 944:1 946:374.9 947:238.9 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 964:47.9 965:88.1 966:89.1 967:98.1 968:47.9 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:42 982:42 983:130.1 984:131.1 985:140.1 986:6.1 987:1 992:0.0856802 993:1 994:1 995:1 996:1 997:1 998:1 999:46 1000:46 1001:134.1 1002:135.1 1003:144.1 1004:2.1 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:22 1018:25.9 1019:110.1 1020:111.1 1021:120.1 1022:25.9 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:112.1 1038:113.1 1039:122.1 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:227.9 1055:91.9 1056:90.9 1057:82.1 1058:81.9 1063:1 1064:1 1065:1 1066:1 1067:1 1068:1 1069:1 1070:0.1 1071:11 1072:36.9 1073:99.1 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:50 1090:424.9 1091:288.9 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1107:48 1108:0.1 1109:136.1 1110:137.1 1111:146.1 1112:0.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:135.9 1127:7 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1138:0.0242215 1139:1 1140:1 1141:1 1142:1 1144:137.9 1145:2.1 1146:1.1 1147:8.1 1150:1 1153:1 1154:1 1156:0.00731707 1157:1 1158:1 1159:1 1160:1 1162:145.9 1163:9.9 1164:9.1 1165:0.1 1171:1 1172:1 1173:1 1174:1 1175:1 1176:1 1177:1 1178:0.1 1180:142.9 1181:6.9 1182:6.1 1183:3.1 1184:2.9 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1214:1 1277:1 1327:1 1379:1
Cbc0038I Full problem 1481 rows 765 columns, reduced to 964 rows 356 columns - 30 fixed gives 891, 302 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 434 rows 187 columns
event(heuristicSolution) CbcModel.cpp:13363 Cbc0012I Integer solution of 1555 found by RINS after 247945 iterations and 2400 nodes (55.07 seconds)
event(heuristicSolution) CbcModel.cpp:13363 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1555 OBJ VAL ORIG(?): -1555 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:7 1:1 2:112 3:1 4:240 5:1 6:345 7:1 8:14 10:91 11:1 12:219 13:1 14:324 15:1 16:16 17:1 18:121 19:1 20:249 21:1 22:354 23:1 24:13 26:92 27:1 28:220 29:1 30:325 31:1 32:1 33:1 34:106 35:1 36:234 37:1 38:339 39:1 40:1 42:104 43:1 44:232 45:1 46:337 47:1 48:9 49:1 50:114 51:1 52:242 53:1 54:347 55:1 56:18 57:1 58:123 59:1 60:251 61:1 62:356 63:1 64:151 66:46 68:82 69:1 70:187 71:1 72:27 73:1 74:132 75:1 76:260 77:1 78:365 79:1 80:325 82:220 84:92 86:13 87:1 88:253 90:148 92:20 94:85 95:1 96:50 98:55 99:1 100:183 101:1 102:288 103:1 104:55 106:50 107:1 108:178 109:1 110:283 111:1 112:43 114:62 115:1 116:190 117:1 118:295 119:1 120:25 121:1 122:130 123:1 124:258 125:1 126:363 127:1 128:112 130:7 132:121 133:1 134:226 135:1 136:33 137:1 138:138 139:1 140:266 141:1 142:371 143:1 144:105 147:1 148:128 149:1 150:233 151:1 152:324 154:219 156:91 158:14 159:1 160:18 162:87 163:1 164:215 165:1 166:320 167:1 168:27 170:78 171:1 172:206 173:1 174:311 175:1 176:48 178:57 179:1 180:185 181:1 182:290 183:1 184:30 185:1 186:135 187:1 188:263 189:1 190:368 191:1 192:232 194:127 196:1 197:1 198:106 199:1 200:233 202:128 205:1 206:105 207:1 208:38 210:67 211:1 212:195 213:1 214:300 215:1 216:8 218:97 219:1 220:225 221:1 222:330 223:1 224:54 226:51 227:1 228:179 229:1 230:284 231:1 232:92 234:13 235:1 236:141 237:1 238:246 239:1 240:95 242:10 243:1 244:138 245:1 246:243 247:1 248:42 250:63 251:1 252:191 253:1 254:296 255:1 256:338 258:233 260:105 263:1 264:11 266:94 267:1 268:222 269:1 270:327 271:1 272:31 273:1 274:136 275:1 276:264 277:1 278:369 279:1 280:35 281:1 282:140 283:1 284:268 285:373 286:11 287:1 288:116 289:1 290:244 291:1 292:349 293:1 294:13 295:1 296:118 297:1 298:246 299:1 300:351 301:1 302:191 304:86 306:42 307:1 308:147 309:1 311:1 312:105 313:1 314:233 315:1 316:338 317:1 318:388 319:283 320:155 321:50 322:37 323:142 324:270 325:375 326:99 328:6 329:1 330:134 331:1 332:239 333:1 334:101 336:4 337:1 338:132 339:1 340:237 341:1 342:109 344:4 346:124 347:1 348:229 349:1 350:106 352:1 354:127 355:1 356:232 357:1 358:7 359:1 363:14 364:1 368:16 369:1 373:13 374:1 378:1 379:1 383:1 384:1 388:9 389:1 393:18 394:1 398:46 400:1 403:27 404:1 408:13 412:1 413:20 416:1 418:50 419:1 423:50 425:1 428:43 429:1 433:25 434:1 438:7 440:1 443:33 444:1 450:1 453:14 457:1 458:18 459:1 463:27 464:1 468:48 469:1 473:30 474:1 478:1 481:1 486:1 488:38 489:1 493:8 494:1 498:51 500:1 503:13 505:1 508:10 510:1 513:42 514:1 522:1 523:11 524:1 528:31 529:1 533:35 534:1 538:11 539:1 543:13 544:1 548:42 551:1 554:1 558:50 562:1 563:37 564:1 568:6 570:1 573:4 575:1 578:4 580:1 583:1 585:1 602:1 665:1 716:1 763:1
Postprocessed sol: 0:54 1:149 2:354 3:381 4:18 5:1 6:113 7:1 8:318 9:1 10:345 11:1 12:3 14:92 15:1 16:297 17:1 18:324 19:1 20:27 21:1 22:122 23:1 24:327 25:1 26:354 27:1 28:2 30:93 31:1 32:298 33:1 34:325 35:1 36:12 37:1 38:107 39:1 40:312 41:1 42:339 43:1 44:10 45:1 46:105 47:1 48:310 49:1 50:337 51:1 52:20 53:1 54:115 55:1 56:320 57:1 58:347 59:1 60:29 61:1 62:124 63:1 64:329 65:1 66:356 67:1 68:140 70:45 72:160 73:1 74:187 75:1 76:38 77:1 78:133 79:1 80:338 81:1 82:365 83:1 84:314 86:219 88:14 90:13 91:1 92:242 94:147 96:58 98:85 99:1 100:39 102:56 103:1 104:261 105:1 106:288 107:1 108:44 110:51 111:1 112:256 113:1 114:283 115:1 116:32 118:63 119:1 120:268 121:1 122:295 123:1 124:36 125:1 126:131 127:1 128:336 129:1 130:363 131:1 132:101 134:6 136:199 137:1 138:226 139:1 140:44 141:1 142:139 143:1 144:344 145:1 146:371 147:1 148:94 150:1 152:206 153:1 154:233 155:1 156:313 158:218 160:13 162:14 163:1 164:7 166:88 167:1 168:293 169:1 170:320 171:1 172:16 174:79 175:1 176:284 177:1 178:311 179:1 180:37 182:58 183:1 184:263 185:1 186:290 187:1 188:41 189:1 190:136 191:1 192:341 193:1 194:368 195:1 196:221 198:126 200:79 202:106 203:1 204:222 206:127 208:78 210:105 211:1 212:27 214:68 215:1 216:273 217:1 218:300 219:1 220:3 221:1 222:98 223:1 224:303 225:1 226:330 227:1 228:43 230:52 231:1 232:257 233:1 234:284 235:1 236:108 238:14 239:1 240:219 241:1 242:246 243:1 244:84 246:11 248:216 249:1 250:243 251:1 252:31 254:64 255:1 256:269 257:1 258:296 259:1 260:327 262:232 264:27 267:1 269:1 270:95 271:1 272:300 273:1 274:327 275:1 276:42 277:1 278:137 279:1 280:342 281:1 282:369 283:1 284:46 285:1 286:141 287:1 288:346 289:1 290:373 291:1 292:22 293:1 294:117 295:1 296:322 297:1 298:349 299:1 300:24 301:1 302:119 303:1 304:324 305:1 306:351 307:1 308:180 310:85 312:120 313:1 314:147 315:1 316:11 317:1 318:106 319:1 320:311 321:1 322:338 323:1 324:377 325:282 326:77 327:50 328:48 329:1 330:143 331:1 332:348 333:1 334:375 335:1 336:88 338:7 340:212 341:1 342:239 343:1 344:90 346:5 348:210 349:1 350:237 351:1 352:98 354:3 356:202 357:1 358:229 359:1 360:95 364:205 365:1 366:232 367:1 368:923 369:18 370:29.9 371:106.1 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:3 388:50.9 389:85.1 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:27 406:21.1 407:115.1 408:116.1 409:125.1 410:21.1 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:2 424:49.9 425:86.1 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:12 442:35.9 443:100.1 444:101.1 445:110.1 446:35.9 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:10 460:37.9 461:98.1 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 477:20 478:27.9 479:108.1 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:29 496:29 497:117.1 498:118.1 499:127.1 500:19.1 501:1 506:0.0243842 507:1 508:1 509:1 510:1 511:1 512:1 514:187.9 515:51.9 516:51.1 517:42.1 518:41.9 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 531:38 532:38 533:126.1 534:127.1 535:136.1 536:10.1 537:1 542:0.0672289 543:1 544:1 545:1 546:1 547:1 548:1 549:14 550:361.9 551:225.9 552:224.9 553:215.9 554:215.9 557:1 559:1 560:1 561:1 562:1 564:0.9 565:1 566:0.1 568:289.9 569:153.9 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 585:39 586:86.9 587:56 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 598:0.0210059 599:1 600:1 601:1 602:1 604:91.9 605:51 606:45.1 607:54.1 608:43.9 613:1 614:1 615:1 616:0.1 617:1 618:1 619:1 620:1 621:32 622:79.9 623:63 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 639:36 640:36 641:124.1 642:125.1 643:134.1 644:12.1 645:1 650:0.0578692 651:1 652:1 653:1 654:1 655:1 656:1 658:148.9 659:12.9 660:12.1 661:3.1 662:2.9 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:44 676:4.1 677:132.1 678:133.1 679:142.1 680:4.1 681:1 687:1 688:1 689:1 690:1 691:1 692:1 694:141.9 695:5.9 696:5.1 697:4.1 698:3.9 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:360.9 713:224.9 714:223.9 715:214.9 716:214.9 721:1 722:1 723:1 724:1 725:1 726:1 727:1 728:0.1 729:7 730:54.9 731:81.1 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 748:63.9 749:72.1 750:73.1 751:82.1 752:63.9 753:1 759:1 760:1 761:1 762:1 763:1 764:1 766:84.9 767:58 768:52.1 769:61.1 770:50.9 771:1 776:0.9 777:1 778:0.1 779:1 780:1 781:1 782:1 783:41 784:41 785:129.1 786:130.1 787:139.1 788:7.1 789:1 794:0.0811005 795:1 796:1 797:1 798:1 799:1 800:1 802:268.9 803:132.9 804:131.9 805:122.9 806:122.9 811:1 812:1 813:1 814:1 815:1 816:1 817:1 818:0.1 820:269.9 821:133.9 822:132.9 823:123.9 824:123.9 829:1 830:1 831:1 832:1 833:1 834:1 835:1 836:0.1 838:74.9 839:68 840:62.1 841:71.1 842:60.9 843:1 848:0.9 849:1 850:0.1 851:1 852:1 853:1 854:1 855:3 856:44.9 857:91.1 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 874:90.9 875:52 876:46.1 877:55.1 878:44.9 883:1 884:1 885:1 886:0.1 887:1 888:1 889:1 890:1 892:128.9 893:14 894:8.1 895:17.1 896:6.9 898:1 901:1 902:1 904:0.0239865 905:1 906:1 907:1 908:1 910:131.9 911:11 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.0242321 923:1 924:1 925:1 926:1 928:78.9 929:64 930:58.1 931:67.1 932:56.9 933:1 938:0.9 939:1 940:0.1 941:1 942:1 943:1 944:1 946:374.9 947:238.9 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 964:47.9 965:88.1 966:89.1 967:98.1 968:47.9 973:1 974:0.1 975:1 976:1 977:1 978:1 979:1 980:1 981:42 982:42 983:130.1 984:131.1 985:140.1 986:6.1 987:1 992:0.0856802 993:1 994:1 995:1 996:1 997:1 998:1 999:46 1000:2.1 1001:134.1 1002:135.1 1003:144.1 1004:2.1 1005:1 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:2 1018:25.9 1019:110.1 1020:111.1 1021:120.1 1022:25.9 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:24 1036:24 1037:112.1 1038:113.1 1039:122.1 1040:24 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:227.9 1055:91.9 1056:91.1 1057:82.1 1058:81.9 1060:1 1063:1 1064:1 1066:0.9 1067:1 1068:1 1069:1 1070:0.1 1071:11 1072:36.9 1073:99.1 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:50 1090:424.9 1091:288.9 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1107:48 1108:48 1109:136.1 1110:137.1 1111:146.1 1112:0.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:135.9 1127:7 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1138:0.0242215 1139:1 1140:1 1141:1 1142:1 1144:137.9 1145:2.1 1146:1.1 1147:8.1 1150:1 1153:1 1154:1 1156:0.00731707 1157:1 1158:1 1159:1 1160:1 1162:145.9 1163:9.9 1164:9.1 1165:0.1 1171:1 1172:1 1173:1 1174:1 1175:1 1176:1 1177:1 1178:0.1 1180:142.9 1181:6.9 1182:6.1 1183:3.1 1184:2.9 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1277:1 1327:1 1379:1
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1555 OBJ VAL ORIG(?): -1555 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:7 1:1 2:112 3:1 4:240 5:1 6:345 7:1 8:14 10:91 11:1 12:219 13:1 14:324 15:1 16:16 17:1 18:121 19:1 20:249 21:1 22:354 23:1 24:13 26:92 27:1 28:220 29:1 30:325 31:1 32:1 33:1 34:106 35:1 36:234 37:1 38:339 39:1 40:1 42:104 43:1 44:232 45:1 46:337 47:1 48:9 49:1 50:114 51:1 52:242 53:1 54:347 55:1 56:18 57:1 58:123 59:1 60:251 61:1 62:356 63:1 64:151 66:46 68:82 69:1 70:187 71:1 72:27 73:1 74:132 75:1 76:260 77:1 78:365 79:1 80:325 82:220 84:92 86:13 87:1 88:253 90:148 92:20 94:85 95:1 96:50 98:55 99:1 100:183 101:1 102:288 103:1 104:55 106:50 107:1 108:178 109:1 110:283 111:1 112:43 114:62 115:1 116:190 117:1 118:295 119:1 120:25 121:1 122:130 123:1 124:258 125:1 126:363 127:1 128:112 130:7 132:121 133:1 134:226 135:1 136:33 137:1 138:138 139:1 140:266 141:1 142:371 143:1 144:105 147:1 148:128 149:1 150:233 151:1 152:324 154:219 156:91 158:14 159:1 160:18 162:87 163:1 164:215 165:1 166:320 167:1 168:27 170:78 171:1 172:206 173:1 174:311 175:1 176:48 178:57 179:1 180:185 181:1 182:290 183:1 184:30 185:1 186:135 187:1 188:263 189:1 190:368 191:1 192:232 194:127 196:1 197:1 198:106 199:1 200:233 202:128 205:1 206:105 207:1 208:38 210:67 211:1 212:195 213:1 214:300 215:1 216:8 218:97 219:1 220:225 221:1 222:330 223:1 224:54 226:51 227:1 228:179 229:1 230:284 231:1 232:92 234:13 235:1 236:141 237:1 238:246 239:1 240:95 242:10 243:1 244:138 245:1 246:243 247:1 248:42 250:63 251:1 252:191 253:1 254:296 255:1 256:338 258:233 260:105 263:1 264:11 266:94 267:1 268:222 269:1 270:327 271:1 272:31 273:1 274:136 275:1 276:264 277:1 278:369 279:1 280:35 281:1 282:140 283:1 284:268 285:373 286:11 287:1 288:116 289:1 290:244 291:1 292:349 293:1 294:13 295:1 296:118 297:1 298:246 299:1 300:351 301:1 302:191 304:86 306:42 307:1 308:147 309:1 311:1 312:105 313:1 314:233 315:1 316:338 317:1 318:388 319:283 320:155 321:50 322:37 323:142 324:270 325:375 326:99 328:6 329:1 330:134 331:1 332:239 333:1 334:101 336:4 337:1 338:132 339:1 340:237 341:1 342:109 344:4 346:124 347:1 348:229 349:1 350:106 352:1 354:127 355:1 356:232 357:1 358:7 359:1 363:14 364:1 368:16 369:1 373:13 374:1 378:1 379:1 383:1 384:1 388:9 389:1 393:18 394:1 398:46 400:1 403:27 404:1 408:13 412:1 413:20 416:1 418:50 419:1 423:50 425:1 428:43 429:1 433:25 434:1 438:7 440:1 443:33 444:1 450:1 453:14 457:1 458:18 459:1 463:27 464:1 468:48 469:1 473:30 474:1 478:1 481:1 486:1 488:38 489:1 493:8 494:1 498:51 500:1 503:13 505:1 508:10 510:1 513:42 514:1 522:1 523:11 524:1 528:31 529:1 533:35 534:1 538:11 539:1 543:13 544:1 548:42 551:1 554:1 558:50 562:1 563:37 564:1 568:6 570:1 573:4 575:1 578:4 580:1 583:1 585:1 602:1 665:1 716:1 763:1
Postprocessed sol: 0:61 1:149 2:354 3:381 4:25 5:1 6:113 7:1 8:318 9:1 10:345 11:1 12:4 14:92 15:1 16:297 17:1 18:324 19:1 20:34 21:1 22:122 23:1 24:327 25:1 26:354 27:1 28:5 30:93 31:1 32:298 33:1 34:325 35:1 36:19 37:1 38:107 39:1 40:312 41:1 42:339 43:1 44:17 45:1 46:105 47:1 48:310 49:1 50:337 51:1 52:27 53:1 54:115 55:1 56:320 57:1 58:347 59:1 60:36 61:1 62:124 63:1 64:329 65:1 66:356 67:1 68:133 70:45 72:160 73:1 74:187 75:1 76:45 77:1 78:133 79:1 80:338 81:1 82:365 83:1 84:307 86:219 88:14 90:13 92:235 94:147 96:58 98:85 99:1 100:39 102:56 103:1 104:261 105:1 106:288 107:1 108:37 110:51 111:1 112:256 113:1 114:283 115:1 116:25 118:63 119:1 120:268 121:1 122:295 123:1 124:43 125:1 126:131 127:1 128:336 129:1 130:363 131:1 132:94 134:6 136:199 137:1 138:226 139:1 140:51 141:1 142:139 143:1 144:344 145:1 146:371 147:1 148:87 150:1 152:206 153:1 154:233 155:1 156:306 158:218 160:13 162:14 166:88 167:1 168:293 169:1 170:320 171:1 172:9 174:79 175:1 176:284 177:1 178:311 179:1 180:37 182:58 183:1 184:263 185:1 186:290 187:1 188:48 189:1 190:136 191:1 192:341 193:1 194:368 195:1 196:214 198:126 200:79 202:106 203:1 204:215 206:127 208:78 210:105 212:20 214:68 215:1 216:273 217:1 218:300 219:1 220:10 221:1 222:98 223:1 224:303 225:1 226:330 227:1 228:36 230:52 231:1 232:257 233:1 234:284 235:1 236:108 238:14 239:1 240:219 241:1 242:246 243:1 244:77 246:11 248:216 249:1 250:243 251:1 252:24 254:64 255:1 256:269 257:1 258:296 259:1 260:320 262:232 264:27 268:7 269:1 270:95 271:1 272:300 273:1 274:327 275:1 276:49 277:1 278:137 279:1 280:342 281:1 282:369 283:1 284:53 285:1 286:141 287:1 288:346 289:1 290:373 291:1 292:29 293:1 294:117 295:1 296:322 297:1 298:349 299:1 300:31 301:1 302:119 303:1 304:324 305:1 306:351 307:1 308:173 310:85 312:120 313:1 314:147 315:1 316:18 317:1 318:106 319:1 320:311 321:1 322:338 323:1 324:370 325:282 326:77 327:50 328:55 329:1 330:143 331:1 332:348 333:1 334:375 335:1 336:81 338:7 340:212 341:1 342:239 343:1 344:83 346:5 348:210 349:1 350:237 351:1 352:91 354:3 356:202 357:1 358:229 359:1 360:88 364:205 365:1 366:232 367:1 368:195 370:29.9 371:106.1 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 388:50.9 389:85.1 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 406:34 407:115.1 408:116.1 409:125.1 410:20.9 411:1 416:0.0324257 417:1 418:1 419:1 420:1 421:1 422:1 424:49.9 425:86.1 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 442:35.9 443:100.1 444:101.1 445:110.1 446:35.9 451:1 452:0.1 453:1 454:1 455:1 456:1 457:1 458:1 460:37.9 461:98.1 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 478:27.9 479:108.1 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 496:36 497:117.1 498:118.1 499:127.1 500:18.9 501:1 506:0.0421182 507:1 508:1 509:1 510:1 511:1 512:1 514:187.9 515:51.9 516:51.1 517:42.1 518:41.9 520:1 523:1 524:1 526:0.9 527:1 528:1 529:1 530:0.1 532:45 533:126.1 534:127.1 535:136.1 536:9.9 537:1 542:0.0845783 543:1 544:1 545:1 546:1 547:1 548:1 549:14 550:361.9 551:225.9 552:224.9 553:215.9 554:215.9 557:1 559:1 560:1 561:1 562:1 564:0.9 565:1 566:0.1 568:289.9 569:153.9 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 585:39 586:86.9 587:56 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 598:0.0210059 599:1 600:1 601:1 602:1 604:91.9 605:51 606:45.1 607:54.1 608:43.9 613:1 614:1 615:1 616:0.1 617:1 618:1 619:1 620:1 621:25 622:79.9 623:63 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 640:43 641:124.1 642:125.1 643:134.1 644:11.9 645:1 650:0.0753027 651:1 652:1 653:1 654:1 655:1 656:1 658:148.9 659:12.9 660:12.1 661:3.1 662:2.9 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:51 676:4.1 677:132.1 678:133.1 679:142.1 680:4.1 681:1 687:1 688:1 689:1 690:1 691:1 692:1 694:141.9 695:5.9 696:5.1 697:4.1 698:3.9 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 712:360.9 713:224.9 714:223.9 715:214.9 716:214.9 721:1 722:1 723:1 724:1 725:1 726:1 727:1 728:0.1 730:54.9 731:81.1 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 748:63.9 749:72.1 750:73.1 751:82.1 752:63.9 753:1 759:1 760:1 761:1 762:1 763:1 764:1 766:84.9 767:58 768:52.1 769:61.1 770:50.9 771:1 776:0.9 777:1 778:0.1 779:1 780:1 781:1 782:1 784:48 785:129.1 786:130.1 787:139.1 788:6.9 789:1 794:0.0983254 795:1 796:1 797:1 798:1 799:1 800:1 802:268.9 803:132.9 804:131.9 805:122.9 806:122.9 811:1 812:1 813:1 814:1 815:1 816:1 817:1 818:0.1 820:269.9 821:133.9 822:132.9 823:123.9 824:123.9 829:1 830:1 831:1 832:1 833:1 834:1 835:1 836:0.1 838:74.9 839:68 840:62.1 841:71.1 842:60.9 843:1 848:0.9 849:1 850:0.1 851:1 852:1 853:1 854:1 856:44.9 857:91.1 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 874:90.9 875:52 876:46.1 877:55.1 878:44.9 883:1 884:1 885:1 886:0.1 887:1 888:1 889:1 890:1 892:128.9 893:14 894:8.1 895:17.1 896:6.9 898:1 901:1 902:1 904:0.0239865 905:1 906:1 907:1 908:1 910:131.9 911:11 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.0242321 923:1 924:1 925:1 926:1 928:78.9 929:64 930:58.1 931:67.1 932:56.9 937:1 938:1 939:1 940:0.1 941:1 942:1 943:1 944:1 946:374.9 947:238.9 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 964:47.9 965:88.1 966:89.1 967:98.1 968:47.9 973:1 974:0.1 975:1 976:1 977:1 978:1 979:1 980:1 982:6.1 983:130.1 984:131.1 985:140.1 986:5.9 987:1 992:0.000477327 993:1 994:1 995:1 996:1 997:1 998:1 1000:2.1 1001:134.1 1002:135.1 1003:144.1 1004:1.9 1005:1 1010:0.000472813 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:2 1018:29 1019:110.1 1020:111.1 1021:120.1 1022:25.9 1023:1 1028:0.00776942 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1036:31 1037:112.1 1038:113.1 1039:122.1 1040:23.9 1041:1 1046:0.0177057 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:227.9 1055:91.9 1056:91.1 1057:82.1 1058:81.9 1060:1 1063:1 1064:1 1066:0.9 1067:1 1068:1 1069:1 1070:0.1 1072:36.9 1073:99.1 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1090:424.9 1091:288.9 1092:287.9 1093:278.9 1094:278.9 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1105:1 1106:0.1 1108:0.1 1109:136.1 1110:137.1 1111:146.1 1113:1 1118:0.000235294 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:135.9 1127:7 1128:1.1 1129:10.1 1135:1 1136:1 1137:1 1138:0.1 1139:1 1140:1 1141:1 1142:1 1144:137.9 1145:2.1 1146:1.1 1147:8.1 1153:1 1154:1 1155:1 1156:1 1157:1 1158:1 1159:1 1160:1 1162:145.9 1163:9.9 1164:9.1 1165:0.1 1171:1 1172:1 1173:1 1174:1 1175:1 1176:1 1177:1 1178:0.1 1180:142.9 1181:6.9 1182:6.1 1183:3.1 1184:2.9 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1327:1
Cbc0038I Full problem 1481 rows 765 columns, reduced to 420 rows 197 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 979 rows 346 columns - 25 fixed gives 936, 309 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 252 rows 127 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 196 rows 83 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 365 rows 151 columns
Cbc0010I After 3000 nodes, 175 on tree, 1555 best solution, best possible 0 (60.44 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 905 rows 323 columns - 29 fixed gives 854, 292 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 245 rows 120 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 969 rows 360 columns - 27 fixed gives 879, 320 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 347 rows 151 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 809 rows 291 columns - 21 fixed gives 784, 270 - ok now
Cbc0038I Full problem 1481 rows 765 columns, reduced to 18 rows 16 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 340 rows 164 columns
Cbc0016I Integer solution of 1505 found by strong branching after 319242 iterations and 3738 nodes (66.15 seconds)
Cbc0016I Integer solution of 1501 found by strong branching after 319244 iterations and 3738 nodes (66.15 seconds)
event(solution) CbcModel.cpp:4568 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1501 OBJ VAL ORIG(?): -1501 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:2 2:61 3:1 4:198 5:1 6:345 7:1 8:23 10:40 11:1 12:177 13:1 14:324 15:1 16:7 17:1 18:70 19:1 20:207 21:1 22:354 23:1 24:22 26:41 27:1 28:178 29:1 30:325 31:1 32:8 34:55 35:1 36:192 37:1 38:339 39:1 40:10 42:53 43:1 44:190 45:1 46:337 47:1 49:1 50:63 51:1 52:200 53:1 54:347 55:1 56:9 57:1 58:72 59:1 60:209 61:1 62:356 63:1 64:160 66:97 68:40 69:1 70:187 71:1 72:18 73:1 74:81 75:1 76:218 77:1 78:365 79:1 80:334 82:271 84:134 86:13 87:1 88:262 90:199 92:62 94:85 95:1 96:59 98:4 99:1 100:141 101:1 102:288 103:1 104:64 106:1 108:136 109:1 110:283 111:1 112:52 114:11 115:1 116:148 117:1 118:295 119:1 120:16 121:1 122:79 123:1 124:216 125:1 126:363 127:1 128:121 130:58 132:79 133:1 134:226 135:1 136:24 137:1 138:87 139:1 140:224 141:1 142:371 143:1 144:114 146:51 148:86 149:1 150:233 151:1 152:333 154:270 156:133 158:14 159:1 160:27 162:36 163:1 164:173 165:1 166:320 167:1 168:36 170:27 171:1 172:164 173:1 174:311 175:1 176:57 178:6 179:1 180:143 181:1 182:290 183:1 184:21 185:1 186:84 187:1 188:221 189:1 190:368 191:1 192:241 194:178 196:41 198:106 199:1 200:242 202:179 204:42 206:105 207:1 208:47 210:16 211:1 212:153 213:1 214:300 215:1 216:17 218:46 219:1 220:183 221:1 222:330 223:1 224:63 227:1 228:137 229:1 230:284 231:1 232:101 234:38 236:99 237:1 238:246 239:1 240:104 242:41 244:96 245:1 246:243 247:1 248:51 250:12 251:1 252:149 253:1 254:296 255:1 256:347 258:284 260:147 263:1 264:20 266:43 267:1 268:180 269:1 270:327 271:1 272:22 273:1 274:85 275:1 276:222 277:1 278:369 279:1 280:26 281:1 282:89 283:1 284:226 285:373 286:2 287:1 288:65 289:1 290:202 291:1 292:349 293:1 294:4 295:1 296:67 297:1 298:204 299:1 300:351 301:1 302:200 304:137 307:1 308:147 309:1 310:9 312:54 313:1 314:191 315:1 316:338 317:1 318:397 319:334 320:197 321:50 322:28 323:91 324:228 325:375 326:108 328:45 330:92 331:1 332:239 333:1 334:110 336:47 338:90 339:1 340:237 341:1 342:118 344:55 346:82 347:1 348:229 349:1 350:115 352:52 354:85 355:1 356:232 357:1 358:2 359:1 363:23 364:1 368:7 369:1 373:22 374:1 378:8 379:1 383:10 384:1 389:1 393:9 394:1 398:40 401:1 403:18 404:1 408:13 412:1 413:62 416:1 418:4 420:1 423:1 425:1 428:11 430:1 433:16 434:1 438:58 440:1 443:24 444:1 448:51 450:1 453:14 457:1 458:27 459:1 463:27 465:1 468:6 470:1 473:21 474:1 478:41 481:1 483:42 486:1 488:16 490:1 493:17 494:1 500:1 503:38 505:1 508:41 510:1 513:12 515:1 522:1 523:20 524:1 528:22 529:1 533:26 534:1 538:2 539:1 543:4 544:1 551:1 553:9 554:1 558:50 562:1 563:28 564:1 568:45 570:1 573:47 575:1 578:55 580:1 583:52 585:1 599:1 659:1 714:1 763:1
Postprocessed sol: 0:34 1:97 2:234 3:381 4:2 6:61 7:1 8:198 9:1 10:345 11:1 12:23 14:40 15:1 16:177 17:1 18:324 19:1 20:7 21:1 22:70 23:1 24:207 25:1 26:354 27:1 28:22 30:41 31:1 32:178 33:1 34:325 35:1 36:8 38:55 39:1 40:192 41:1 42:339 43:1 44:10 46:53 47:1 48:190 49:1 50:337 51:1 53:1 54:63 55:1 56:200 57:1 58:347 59:1 60:9 61:1 62:72 63:1 64:209 65:1 66:356 67:1 68:160 70:97 72:40 73:1 74:187 75:1 76:18 77:1 78:81 79:1 80:218 81:1 82:365 83:1 84:334 86:271 88:134 90:13 92:262 94:199 96:62 98:85 99:1 100:59 102:4 103:1 104:141 105:1 106:288 107:1 108:64 110:1 112:136 113:1 114:283 115:1 116:52 118:11 119:1 120:148 121:1 122:295 123:1 124:16 125:1 126:79 127:1 128:216 129:1 130:363 131:1 132:121 134:58 136:79 137:1 138:226 139:1 140:24 141:1 142:87 143:1 144:224 145:1 146:371 147:1 148:114 150:51 152:86 153:1 154:233 155:1 156:333 158:270 160:133 162:14 164:27 166:36 167:1 168:173 169:1 170:320 171:1 172:36 174:27 175:1 176:164 177:1 178:311 179:1 180:57 182:6 183:1 184:143 185:1 186:290 187:1 188:21 189:1 190:84 191:1 192:221 193:1 194:368 195:1 196:241 198:178 200:41 202:106 203:1 204:242 206:179 208:42 210:105 211:1 212:47 214:16 215:1 216:153 217:1 218:300 219:1 220:17 222:46 223:1 224:183 225:1 226:330 227:1 228:63 231:1 232:137 233:1 234:284 235:1 236:101 238:38 240:99 241:1 242:246 243:1 244:104 246:41 248:96 249:1 250:243 251:1 252:51 254:12 255:1 256:149 257:1 258:296 259:1 260:347 262:284 264:147 268:20 270:43 271:1 272:180 273:1 274:327 275:1 276:22 277:1 278:85 279:1 280:222 281:1 282:369 283:1 284:26 285:1 286:89 287:1 288:226 289:1 290:373 291:1 292:2 293:1 294:65 295:1 296:202 297:1 298:349 299:1 300:4 301:1 302:67 303:1 304:204 305:1 306:351 307:1 308:200 310:137 313:1 314:147 315:1 316:9 318:54 319:1 320:191 321:1 322:338 323:1 324:397 325:334 326:197 327:50 328:28 329:1 330:91 331:1 332:228 333:1 334:375 335:1 336:108 338:45 340:92 341:1 342:239 343:1 344:110 346:47 348:90 349:1 350:237 351:1 352:118 354:55 356:82 357:1 358:229 359:1 360:115 362:52 364:85 365:1 366:232 367:1 368:1501 369:2 370:29.9 371:105.9 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:23 388:50.9 389:84.9 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:7 406:20.9 407:114.9 408:116.1 409:125.1 410:20.9 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:22 424:49.9 425:85.9 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:8 442:35.9 443:99.9 444:101.1 445:110.1 446:35.9 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:10 460:37.9 461:97.9 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 478:27.9 479:107.9 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:9 496:18.9 497:116.9 498:118.1 499:127.1 500:18.9 501:1 507:1 508:1 509:1 510:1 511:1 512:1 513:40 514:187.9 515:52.1 516:50.9 517:42.1 518:41.9 521:1 523:1 524:1 525:1 526:1 528:0.9 529:1 530:0.1 531:18 532:18 533:125.9 534:127.1 535:136.1 536:10.1 537:1 542:0.0190361 543:1 544:1 545:1 546:1 547:1 548:1 549:13 550:361.9 551:226.1 552:224.9 553:215.9 554:215.9 558:1 559:1 560:1 561:1 562:1 563:1 564:1 567:62 568:289.9 569:154.1 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 585:4 586:86.9 587:48.9 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:1 604:91.9 605:43.9 606:45.1 607:54.1 608:43.9 610:1 613:1 614:1 617:1 618:1 619:1 620:1 621:11 622:79.9 623:55.9 624:57.1 625:66.1 626:55.9 628:1 631:1 632:1 635:1 636:1 637:1 638:1 639:16 640:16 641:123.9 642:125.1 643:134.1 644:12.1 645:1 650:0.0094431 651:1 652:1 653:1 654:1 655:1 656:1 657:58 658:148.9 659:13.1 660:12.1 661:226 662:3.1 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:24 676:24 677:131.9 678:133.1 679:142.1 680:4.1 681:1 686:0.0472684 687:1 688:1 689:1 690:1 691:1 692:1 693:51 694:141.9 695:6.1 696:5.1 697:233 698:4.1 700:1 703:1 704:1 706:0.9 707:1 708:1 709:1 710:0.1 711:14 712:360.9 713:225.1 714:223.9 715:214.9 716:214.9 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:27 730:54.9 731:80.9 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 747:27 748:63.9 749:71.9 750:73.1 751:82.1 752:63.9 754:1 757:1 758:0.1 760:0.9 761:1 762:1 763:1 764:1 765:6 766:84.9 767:50.9 768:52.1 769:61.1 770:50.9 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:21 784:21 785:128.9 786:130.1 787:139.1 788:7.1 789:1 794:0.0332536 795:1 796:1 797:1 798:1 799:1 800:1 801:41 802:268.9 803:133.1 804:131.9 805:122.9 806:122.9 809:1 811:1 812:1 813:1 814:1 816:0.9 817:1 818:0.1 819:42 820:269.9 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 837:16 838:74.9 839:60.9 840:62.1 841:71.1 842:60.9 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:17 856:44.9 857:90.9 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 874:90.9 875:44.9 876:46.1 877:55.1 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 891:38 892:128.9 893:38 894:8.1 895:17.1 896:7.1 898:1 901:1 902:1 905:1 906:1 907:1 908:1 909:41 910:131.9 911:41 912:5.1 913:14.1 914:4.1 916:1 919:1 920:1 923:1 924:1 925:1 926:1 927:12 928:78.9 929:56.9 930:58.1 931:67.1 932:56.9 934:1 937:1 938:1 941:1 942:1 943:1 944:1 946:374.9 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:20 964:47.9 965:87.9 966:89.1 967:98.1 968:47.9 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:22 982:6.1 983:129.9 984:131.1 985:140.1 986:6.1 987:1 993:1 994:1 995:1 996:1 997:1 998:1 999:26 1000:26 1001:133.9 1002:135.1 1003:144.1 1004:2.1 1005:1 1010:0.0565012 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1017:2 1018:25.9 1019:109.9 1020:111.1 1021:120.1 1022:25.9 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:4 1036:23.9 1037:111.9 1038:113.1 1039:122.1 1040:23.9 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:227.9 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1061:1 1063:1 1064:1 1065:1 1066:1 1068:0.9 1069:1 1070:0.1 1071:9 1072:36.9 1073:98.9 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:50 1090:424.9 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1107:28 1108:28 1109:135.9 1110:137.1 1111:146.1 1112:0.1 1113:1 1118:0.0656471 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1125:45 1126:135.9 1127:0.1 1128:1.1 1129:10.1 1130:0.1 1132:1 1135:1 1136:1 1139:1 1140:1 1141:1 1142:1 1143:47 1144:137.9 1145:2.1 1146:1.1 1147:8.1 1148:0.1 1150:1 1153:1 1154:1 1156:0.00696864 1157:1 1158:1 1159:1 1160:1 1161:55 1162:145.9 1163:10.1 1164:9.1 1165:229 1166:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1179:52 1180:142.9 1181:7.1 1182:6.1 1183:232 1184:3.1 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1208:1 1379:1
Cbc0010I After 4000 nodes, 257 on tree, 1501 best solution, best possible 0 (68.08 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 274 rows 129 columns
Cbc0010I After 5000 nodes, 260 on tree, 1501 best solution, best possible 0 (77.10 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 140 rows 81 columns
Cbc0010I After 6000 nodes, 174 on tree, 1501 best solution, best possible 0 (86.68 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 1077 rows 352 columns - 22 fixed gives 1043, 323 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 679 rows 256 columns
Cbc0010I After 7000 nodes, 100 on tree, 1501 best solution, best possible 0 (95.00 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 1018 rows 332 columns - 25 fixed gives 979, 301 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 363 rows 170 columns
event(heuristicSolution) CbcModel.cpp:13363 Cbc0012I Integer solution of 1499 found by RINS after 503535 iterations and 7810 nodes (100.72 seconds)
event(heuristicSolution) CbcModel.cpp:13363 Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Coin0505I Presolved problem not optimal, resolve after postsolve
Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1499 OBJ VAL ORIG(?): -1499 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:4 2:61 3:1 4:198 5:1 6:345 7:1 8:25 10:40 11:1 12:177 13:1 14:324 15:1 16:5 17:1 18:70 19:1 20:207 21:1 22:354 23:1 24:24 26:41 27:1 28:178 29:1 30:325 31:1 32:10 34:55 35:1 36:192 37:1 38:339 39:1 40:12 42:53 43:1 44:190 45:1 46:337 47:1 48:2 50:63 51:1 52:200 53:1 54:347 55:1 56:7 57:1 58:72 59:1 60:209 61:1 62:356 63:1 64:162 66:97 68:40 69:1 70:187 71:1 72:16 73:1 74:81 75:1 76:218 77:1 78:365 79:1 80:336 82:271 84:134 86:13 87:1 88:264 90:199 92:62 94:85 95:1 96:61 98:4 99:1 100:141 101:1 102:288 103:1 104:66 106:1 108:136 109:1 110:283 111:1 112:54 114:11 115:1 116:148 117:1 118:295 119:1 120:14 121:1 122:79 123:1 124:216 125:1 126:363 127:1 128:123 130:58 132:79 133:1 134:226 135:1 136:22 137:1 138:87 139:1 140:224 141:1 142:371 143:1 144:116 146:51 148:86 149:1 150:233 151:1 152:335 154:270 156:133 158:14 159:1 160:29 162:36 163:1 164:173 165:1 166:320 167:1 168:38 170:27 171:1 172:164 173:1 174:311 175:1 176:59 178:6 179:1 180:143 181:1 182:290 183:1 184:19 185:1 186:84 187:1 188:221 189:1 190:368 191:1 192:243 194:178 196:41 198:106 199:1 200:244 202:179 204:42 206:105 207:1 208:49 210:16 211:1 212:153 213:1 214:300 215:1 216:19 218:46 219:1 220:183 221:1 222:330 223:1 224:65 227:1 228:137 229:1 230:284 231:1 232:103 234:38 236:99 237:1 238:246 239:1 240:106 242:41 244:96 245:1 246:243 247:1 248:53 250:12 251:1 252:149 253:1 254:296 255:1 256:349 258:284 260:147 263:1 264:22 266:43 267:1 268:180 269:1 270:327 271:1 272:20 273:1 274:85 275:1 276:222 277:1 278:369 279:1 280:24 281:1 282:89 283:1 284:226 285:373 287:1 288:65 289:1 290:202 291:1 292:349 293:1 294:2 295:1 296:67 297:1 298:204 299:1 300:351 301:1 302:202 304:137 307:1 308:147 309:1 310:11 312:54 313:1 314:191 315:1 316:338 317:1 318:399 319:334 320:197 321:50 322:26 323:91 324:228 325:375 326:110 328:45 330:92 331:1 332:239 333:1 334:112 336:47 338:90 339:1 340:237 341:1 342:120 344:55 346:82 347:1 348:229 349:1 350:117 352:52 354:85 355:1 356:232 357:1 358:4 359:1 363:25 364:1 368:5 369:1 373:24 374:1 378:10 379:1 383:12 384:1 388:2 389:1 393:7 394:1 398:40 401:1 403:16 404:1 408:13 412:1 413:62 416:1 418:4 420:1 423:1 425:1 428:11 430:1 433:14 434:1 438:58 440:1 443:22 444:1 448:51 450:1 453:14 457:1 458:29 459:1 463:27 465:1 468:6 470:1 473:19 474:1 478:41 481:1 483:42 486:1 488:16 490:1 493:19 494:1 500:1 503:38 505:1 508:41 510:1 513:12 515:1 522:1 523:22 524:1 528:20 529:1 533:24 534:1 539:1 543:2 544:1 551:1 553:11 554:1 558:50 562:1 563:26 564:1 568:45 570:1 573:47 575:1 578:55 580:1 583:52 585:1 598:1 659:1 714:1 763:1
Postprocessed sol: 0:32 1:97 2:234 3:381 4:4 6:61 7:1 8:198 9:1 10:345 11:1 12:23 14:40 15:1 16:177 17:1 18:324 19:1 20:5 21:1 22:70 23:1 24:207 25:1 26:354 27:1 28:24 30:41 31:1 32:178 33:1 34:325 35:1 36:10 38:55 39:1 40:192 41:1 42:339 43:1 44:12 46:53 47:1 48:190 49:1 50:337 51:1 52:2 54:63 55:1 56:200 57:1 58:347 59:1 60:7 61:1 62:72 63:1 64:209 65:1 66:356 67:1 68:162 70:97 72:40 73:1 74:187 75:1 76:16 77:1 78:81 79:1 80:218 81:1 82:365 83:1 84:336 86:271 88:134 90:13 92:264 94:199 96:62 98:85 99:1 100:61 102:4 103:1 104:141 105:1 106:288 107:1 108:66 110:66 112:136 113:1 114:283 115:1 116:54 118:54 119:1 120:148 121:1 122:295 123:1 124:14 125:1 126:79 127:1 128:216 129:1 130:363 131:1 132:123 134:58 136:79 137:1 138:226 139:1 140:22 141:1 142:87 143:1 144:224 145:1 146:371 147:1 148:116 150:51 152:86 153:1 154:233 155:1 156:335 158:270 160:133 162:14 163:1 164:42 166:36 167:1 168:173 169:1 170:320 171:1 172:38 174:27 175:1 176:164 177:1 178:311 179:1 180:59 182:6 183:1 184:143 185:1 186:290 187:1 188:19 189:1 190:84 191:1 192:221 193:1 194:368 195:1 196:243 198:178 200:41 201:1 202:106 203:1 204:244 206:179 208:42 209:1 210:105 211:1 212:49 214:16 215:1 216:153 217:1 218:300 219:1 220:19 222:46 223:1 224:183 225:1 226:330 227:1 228:65 231:1 232:137 233:1 234:284 235:1 236:103 238:38 240:99 241:1 242:246 243:1 244:106 246:41 248:96 249:1 250:243 251:1 252:53 254:12 255:1 256:149 257:1 258:296 259:1 260:349 262:284 264:147 268:22 270:43 271:1 272:180 273:1 274:327 275:1 276:20 277:1 278:85 279:1 280:222 281:1 282:369 283:1 284:24 285:1 286:89 287:1 288:226 289:1 290:373 291:1 293:1 294:65 295:1 296:202 297:1 298:349 299:1 300:2 301:1 302:67 303:1 304:204 305:1 306:351 307:1 308:202 310:137 313:1 314:147 315:1 316:11 318:54 319:1 320:191 321:1 322:338 323:1 324:399 325:334 326:197 327:50 328:26 329:1 330:91 331:1 332:228 333:1 334:375 335:1 336:110 338:45 340:92 341:1 342:239 343:1 344:112 346:47 348:90 349:1 350:237 351:1 352:120 354:55 356:82 357:1 358:229 359:1 360:117 362:52 364:85 365:1 366:232 367:1 368:1027 369:2 370:29.9 371:105.9 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:23 388:50.9 389:84.9 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:7 406:20.9 407:114.9 408:116.1 409:125.1 410:20.9 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:22 424:49.9 425:85.9 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:8 442:35.9 443:99.9 444:101.1 445:110.1 446:35.9 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:10 460:37.9 461:97.9 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 478:27.9 479:107.9 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:9 496:18.9 497:116.9 498:118.1 499:127.1 500:18.9 501:1 507:1 508:1 509:1 510:1 511:1 512:1 513:40 514:187.9 515:52.1 516:50.9 517:42.1 518:41.9 521:1 523:1 524:1 525:1 526:1 528:0.9 529:1 530:0.1 531:18 532:16 533:125.9 534:127.1 535:136.1 536:10.1 537:1 542:0.0142169 543:1 544:1 545:1 546:1 547:1 548:1 550:361.9 551:226.1 552:224.9 553:215.9 554:215.9 559:1 560:1 561:1 562:1 563:1 564:1 565:1 566:0.1 568:289.9 569:154.1 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 585:4 586:86.9 587:48.9 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:66 604:91.9 605:66 606:45.1 607:54.1 608:44.1 609:1 614:0.9 615:1 616:0.1 617:1 618:1 619:1 620:1 621:54 622:79.9 623:55.9 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 639:16 640:14 641:123.9 642:125.1 643:134.1 644:12.1 645:1 650:0.00460048 651:1 652:1 653:1 654:1 655:1 656:1 657:58 658:148.9 659:13.1 660:12.1 661:226 662:3.1 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:22 676:22 677:131.9 678:133.1 679:142.1 680:4.1 681:1 686:0.0425178 687:1 688:1 689:1 690:1 691:1 692:1 694:141.9 695:6.1 696:5.1 697:4.1 698:3.9 703:1 704:1 705:1 706:1 707:1 708:1 709:1 710:0.1 712:360.9 713:225.1 714:223.9 715:214.9 716:214.9 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:42 730:54.9 731:80.9 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 748:63.9 749:71.9 750:73.1 751:82.1 752:63.9 754:1 757:1 758:0.1 760:0.9 761:1 762:1 763:1 764:1 766:84.9 767:50.9 768:52.1 769:61.1 770:50.9 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:21 784:7.1 785:128.9 786:130.1 787:139.1 788:7.1 789:1 795:1 796:1 797:1 798:1 799:1 800:1 802:268.9 803:133.1 804:131.9 805:122.9 806:122.9 809:1 811:1 812:1 813:1 814:1 816:0.9 817:1 818:0.1 820:269.9 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 838:74.9 839:60.9 840:62.1 841:71.1 842:60.9 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:1 856:44.9 857:90.9 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 874:90.9 875:44.9 876:46.1 877:55.1 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 891:19 892:128.9 893:38 894:8.1 895:17.1 896:7.1 898:1 901:1 902:1 905:1 906:1 907:1 908:1 910:131.9 911:4.1 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.000682594 923:1 924:1 925:1 926:1 928:78.9 929:56.9 930:58.1 931:67.1 932:56.9 934:1 937:1 938:1 941:1 942:1 943:1 944:1 946:374.9 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:20 964:47.9 965:87.9 966:89.1 967:98.1 968:47.9 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:22 982:20 983:129.9 984:131.1 985:140.1 986:6.1 987:1 992:0.0331742 993:1 994:1 995:1 996:1 997:1 998:1 999:26 1000:24 1001:133.9 1002:135.1 1003:144.1 1004:2.1 1005:1 1010:0.051773 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1018:25.9 1019:109.9 1020:111.1 1021:120.1 1022:25.9 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:4 1036:23.9 1037:111.9 1038:113.1 1039:122.1 1040:23.9 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:227.9 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1060:1 1063:1 1064:1 1066:0.9 1067:1 1068:1 1069:1 1070:0.1 1071:9 1072:36.9 1073:98.9 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:50 1090:424.9 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1107:26 1108:0.1 1109:135.9 1110:137.1 1111:146.1 1112:0.1 1113:1 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:135.9 1127:0.1 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1138:0.000346021 1139:1 1140:1 1141:1 1142:1 1144:137.9 1145:2.1 1146:1.1 1147:8.1 1150:1 1153:1 1154:1 1156:0.00731707 1157:1 1158:1 1159:1 1160:1 1162:145.9 1163:10.1 1164:9.1 1165:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1179:52 1180:142.9 1181:7.1 1182:6.1 1183:232 1184:3.1 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1207:1
event(solution) CbcModel.cpp:4568 Cgl0013I Postprocessed model is infeasible - possible tolerance issue - try without preprocessing
% OBJ VAL RAW: 1499 OBJ VAL ORIG(?): -1499 % BND RAW: 0 BND ORIG(?): -0 orig NCols: 1381 prepro NCols: 765
Preprocessed sol: 0:4 2:61 3:1 4:198 5:1 6:345 7:1 8:25 10:40 11:1 12:177 13:1 14:324 15:1 16:5 17:1 18:70 19:1 20:207 21:1 22:354 23:1 24:24 26:41 27:1 28:178 29:1 30:325 31:1 32:10 34:55 35:1 36:192 37:1 38:339 39:1 40:12 42:53 43:1 44:190 45:1 46:337 47:1 48:2 50:63 51:1 52:200 53:1 54:347 55:1 56:7 57:1 58:72 59:1 60:209 61:1 62:356 63:1 64:162 66:97 68:40 69:1 70:187 71:1 72:16 73:1 74:81 75:1 76:218 77:1 78:365 79:1 80:336 82:271 84:134 86:13 87:1 88:264 90:199 92:62 94:85 95:1 96:61 98:4 99:1 100:141 101:1 102:288 103:1 104:66 106:1 108:136 109:1 110:283 111:1 112:54 114:11 115:1 116:148 117:1 118:295 119:1 120:14 121:1 122:79 123:1 124:216 125:1 126:363 127:1 128:123 130:58 132:79 133:1 134:226 135:1 136:22 137:1 138:87 139:1 140:224 141:1 142:371 143:1 144:116 146:51 148:86 149:1 150:233 151:1 152:335 154:270 156:133 158:14 159:1 160:29 162:36 163:1 164:173 165:1 166:320 167:1 168:38 170:27 171:1 172:164 173:1 174:311 175:1 176:59 178:6 179:1 180:143 181:1 182:290 183:1 184:19 185:1 186:84 187:1 188:221 189:1 190:368 191:1 192:243 194:178 196:41 198:106 199:1 200:244 202:179 204:42 206:105 207:1 208:49 210:16 211:1 212:153 213:1 214:300 215:1 216:19 218:46 219:1 220:183 221:1 222:330 223:1 224:65 227:1 228:137 229:1 230:284 231:1 232:103 234:38 236:99 237:1 238:246 239:1 240:106 242:41 244:96 245:1 246:243 247:1 248:53 250:12 251:1 252:149 253:1 254:296 255:1 256:349 258:284 260:147 263:1 264:22 266:43 267:1 268:180 269:1 270:327 271:1 272:20 273:1 274:85 275:1 276:222 277:1 278:369 279:1 280:24 281:1 282:89 283:1 284:226 285:373 287:1 288:65 289:1 290:202 291:1 292:349 293:1 294:2 295:1 296:67 297:1 298:204 299:1 300:351 301:1 302:202 304:137 307:1 308:147 309:1 310:11 312:54 313:1 314:191 315:1 316:338 317:1 318:399 319:334 320:197 321:50 322:26 323:91 324:228 325:375 326:110 328:45 330:92 331:1 332:239 333:1 334:112 336:47 338:90 339:1 340:237 341:1 342:120 344:55 346:82 347:1 348:229 349:1 350:117 352:52 354:85 355:1 356:232 357:1 358:4 359:1 363:25 364:1 368:5 369:1 373:24 374:1 378:10 379:1 383:12 384:1 388:2 389:1 393:7 394:1 398:40 401:1 403:16 404:1 408:13 412:1 413:62 416:1 418:4 420:1 423:1 425:1 428:11 430:1 433:14 434:1 438:58 440:1 443:22 444:1 448:51 450:1 453:14 457:1 458:29 459:1 463:27 465:1 468:6 470:1 473:19 474:1 478:41 481:1 483:42 486:1 488:16 490:1 493:19 494:1 500:1 503:38 505:1 508:41 510:1 513:12 515:1 522:1 523:22 524:1 528:20 529:1 533:24 534:1 539:1 543:2 544:1 551:1 553:11 554:1 558:50 562:1 563:26 564:1 568:45 570:1 573:47 575:1 578:55 580:1 583:52 585:1 598:1 659:1 714:1 763:1
Postprocessed sol: 0:32 1:97 2:234 3:381 4:4 6:61 7:1 8:198 9:1 10:345 11:1 12:23 14:40 15:1 16:177 17:1 18:324 19:1 20:5 21:1 22:70 23:1 24:207 25:1 26:354 27:1 28:24 30:41 31:1 32:178 33:1 34:325 35:1 36:10 38:55 39:1 40:192 41:1 42:339 43:1 44:12 46:53 47:1 48:190 49:1 50:337 51:1 52:2 54:63 55:1 56:200 57:1 58:347 59:1 60:7 61:1 62:72 63:1 64:209 65:1 66:356 67:1 68:162 70:97 72:40 73:1 74:187 75:1 76:16 77:1 78:81 79:1 80:218 81:1 82:365 83:1 84:336 86:271 88:134 90:13 92:264 94:199 96:62 98:85 99:1 100:61 102:4 103:1 104:141 105:1 106:288 107:1 108:66 110:66 112:136 113:1 114:283 115:1 116:54 118:54 119:1 120:148 121:1 122:295 123:1 124:14 125:1 126:79 127:1 128:216 129:1 130:363 131:1 132:123 134:58 136:79 137:1 138:226 139:1 140:22 141:1 142:87 143:1 144:224 145:1 146:371 147:1 148:116 150:51 152:86 153:1 154:233 155:1 156:335 158:270 160:133 162:14 163:1 164:42 166:36 167:1 168:173 169:1 170:320 171:1 172:38 174:27 175:1 176:164 177:1 178:311 179:1 180:59 182:6 183:1 184:143 185:1 186:290 187:1 188:19 189:1 190:84 191:1 192:221 193:1 194:368 195:1 196:243 198:178 200:41 201:1 202:106 203:1 204:244 206:179 208:42 209:1 210:105 211:1 212:49 214:16 215:1 216:153 217:1 218:300 219:1 220:19 222:46 223:1 224:183 225:1 226:330 227:1 228:65 231:1 232:137 233:1 234:284 235:1 236:103 238:38 240:99 241:1 242:246 243:1 244:106 246:41 248:96 249:1 250:243 251:1 252:53 254:12 255:1 256:149 257:1 258:296 259:1 260:349 262:284 264:147 268:22 270:43 271:1 272:180 273:1 274:327 275:1 276:20 277:1 278:85 279:1 280:222 281:1 282:369 283:1 284:24 285:1 286:89 287:1 288:226 289:1 290:373 291:1 293:1 294:65 295:1 296:202 297:1 298:349 299:1 300:2 301:1 302:67 303:1 304:204 305:1 306:351 307:1 308:202 310:137 313:1 314:147 315:1 316:11 318:54 319:1 320:191 321:1 322:338 323:1 324:399 325:334 326:197 327:50 328:26 329:1 330:91 331:1 332:228 333:1 334:375 335:1 336:110 338:45 340:92 341:1 342:239 343:1 344:112 346:47 348:90 349:1 350:237 351:1 352:120 354:55 356:82 357:1 358:229 359:1 360:117 362:52 364:85 365:1 366:232 367:1 368:1027 369:2 370:29.9 371:105.9 372:107.1 373:116.1 374:29.9 375:1 381:1 382:1 383:1 384:1 385:1 386:1 387:23 388:50.9 389:84.9 390:86.1 391:95.1 392:50.9 393:1 399:1 400:1 401:1 402:1 403:1 404:1 405:7 406:20.9 407:114.9 408:116.1 409:125.1 410:20.9 411:1 417:1 418:1 419:1 420:1 421:1 422:1 423:22 424:49.9 425:85.9 426:87.1 427:96.1 428:49.9 429:1 435:1 436:1 437:1 438:1 439:1 440:1 441:8 442:35.9 443:99.9 444:101.1 445:110.1 446:35.9 447:1 453:1 454:1 455:1 456:1 457:1 458:1 459:10 460:37.9 461:97.9 462:99.1 463:108.1 464:37.9 465:1 471:1 472:1 473:1 474:1 475:1 476:1 478:27.9 479:107.9 480:109.1 481:118.1 482:27.9 483:1 489:1 490:1 491:1 492:1 493:1 494:1 495:9 496:18.9 497:116.9 498:118.1 499:127.1 500:18.9 501:1 507:1 508:1 509:1 510:1 511:1 512:1 513:40 514:187.9 515:52.1 516:50.9 517:42.1 518:41.9 521:1 523:1 524:1 525:1 526:1 528:0.9 529:1 530:0.1 531:18 532:16 533:125.9 534:127.1 535:136.1 536:10.1 537:1 542:0.0142169 543:1 544:1 545:1 546:1 547:1 548:1 550:361.9 551:226.1 552:224.9 553:215.9 554:215.9 559:1 560:1 561:1 562:1 563:1 564:1 565:1 566:0.1 568:289.9 569:154.1 570:152.9 571:143.9 572:143.9 575:1 577:1 578:1 579:1 580:1 582:0.9 583:1 584:0.1 585:4 586:86.9 587:48.9 588:50.1 589:59.1 590:48.9 592:1 595:1 596:1 599:1 600:1 601:1 602:1 603:66 604:91.9 605:66 606:45.1 607:54.1 608:44.1 609:1 614:0.9 615:1 616:0.1 617:1 618:1 619:1 620:1 621:54 622:79.9 623:55.9 624:57.1 625:66.1 626:55.9 627:1 632:0.9 633:1 634:0.1 635:1 636:1 637:1 638:1 639:16 640:14 641:123.9 642:125.1 643:134.1 644:12.1 645:1 650:0.00460048 651:1 652:1 653:1 654:1 655:1 656:1 657:58 658:148.9 659:13.1 660:12.1 661:3.1 662:3.1 664:1 667:1 668:1 670:0.9 671:1 672:1 673:1 674:0.1 675:22 676:4.1 677:131.9 678:133.1 679:142.1 680:4.1 681:1 687:1 688:1 689:1 690:1 691:1 692:1 694:141.9 695:6.1 696:5.1 697:4.1 698:3.9 703:1 704:1 705:1 706:1 707:1 708:1 709:1 710:0.1 712:360.9 713:225.1 714:223.9 715:214.9 716:214.9 720:1 721:1 722:1 723:1 724:1 725:1 726:1 729:42 730:54.9 731:80.9 732:82.1 733:91.1 734:54.9 735:1 741:1 742:1 743:1 744:1 745:1 746:1 748:63.9 749:71.9 750:73.1 751:82.1 752:63.9 754:1 757:1 758:0.1 760:0.9 761:1 762:1 763:1 764:1 766:84.9 767:50.9 768:52.1 769:61.1 770:50.9 772:1 775:1 776:1 779:1 780:1 781:1 782:1 783:21 784:19 785:128.9 786:130.1 787:139.1 788:7.1 789:1 794:0.0284689 795:1 796:1 797:1 798:1 799:1 800:1 802:268.9 803:133.1 804:131.9 805:122.9 806:122.9 809:1 811:1 812:1 813:1 814:1 816:0.9 817:1 818:0.1 820:269.9 821:134.1 822:132.9 823:123.9 824:123.9 827:1 829:1 830:1 831:1 832:1 834:0.9 835:1 836:0.1 838:74.9 839:60.9 840:62.1 841:71.1 842:60.9 844:1 847:1 848:1 851:1 852:1 853:1 854:1 855:1 856:44.9 857:90.9 858:92.1 859:101.1 860:44.9 861:1 867:1 868:1 869:1 870:1 871:1 872:1 874:90.9 875:44.9 876:46.1 877:55.1 878:44.9 880:1 883:1 884:1 887:1 888:1 889:1 890:1 891:19 892:128.9 893:38 894:8.1 895:17.1 896:7.1 898:1 901:1 902:1 905:1 906:1 907:1 908:1 910:131.9 911:4.1 912:5.1 913:14.1 914:3.9 916:1 919:1 920:1 922:0.000682594 923:1 924:1 925:1 926:1 928:78.9 929:56.9 930:58.1 931:67.1 932:56.9 934:1 937:1 938:1 941:1 942:1 943:1 944:1 946:374.9 947:239.1 948:237.9 949:228.9 950:228.9 954:1 955:1 956:1 957:1 958:1 959:1 960:1 963:20 964:47.9 965:87.9 966:89.1 967:98.1 968:47.9 969:1 975:1 976:1 977:1 978:1 979:1 980:1 981:22 982:6.1 983:129.9 984:131.1 985:140.1 986:6.1 987:1 993:1 994:1 995:1 996:1 997:1 998:1 999:26 1000:24 1001:133.9 1002:135.1 1003:144.1 1004:2.1 1005:1 1010:0.051773 1011:1 1012:1 1013:1 1014:1 1015:1 1016:1 1018:25.9 1019:109.9 1020:111.1 1021:120.1 1022:25.9 1023:1 1029:1 1030:1 1031:1 1032:1 1033:1 1034:1 1035:4 1036:23.9 1037:111.9 1038:113.1 1039:122.1 1040:23.9 1041:1 1047:1 1048:1 1049:1 1050:1 1051:1 1052:1 1054:227.9 1055:92.1 1056:90.9 1057:82.1 1058:81.9 1060:1 1063:1 1064:1 1066:0.9 1067:1 1068:1 1069:1 1070:0.1 1071:9 1072:36.9 1073:98.9 1074:100.1 1075:109.1 1076:36.9 1077:1 1083:1 1084:1 1085:1 1086:1 1087:1 1088:1 1089:50 1090:424.9 1091:289.1 1092:287.9 1093:278.9 1094:278.9 1098:1 1099:1 1100:1 1101:1 1102:1 1103:1 1104:1 1107:26 1108:26 1109:135.9 1110:137.1 1111:146.1 1112:0.1 1113:1 1118:0.0609412 1119:1 1120:1 1121:1 1122:1 1123:1 1124:1 1126:135.9 1127:0.1 1128:1.1 1129:10.1 1132:1 1135:1 1136:1 1138:0.000346021 1139:1 1140:1 1141:1 1142:1 1144:137.9 1145:2.1 1146:1.1 1147:8.1 1150:1 1153:1 1154:1 1156:0.00731707 1157:1 1158:1 1159:1 1160:1 1162:145.9 1163:10.1 1164:9.1 1165:0.1 1168:1 1171:1 1172:1 1174:0.9 1175:1 1176:1 1177:1 1178:0.1 1179:52 1180:142.9 1181:7.1 1182:6.1 1183:232 1184:3.1 1186:1 1189:1 1190:1 1192:0.9 1193:1 1194:1 1195:1 1196:0.1 1207:1
Cbc0010I After 8000 nodes, 69 on tree, 1499 best solution, best possible 0 (104.74 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 346 rows 157 columns
Cbc0010I After 9000 nodes, 80 on tree, 1499 best solution, best possible 0 (113.07 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 985 rows 320 columns - 25 fixed gives 902, 294 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 372 rows 142 columns
Cbc0010I After 10000 nodes, 19 on tree, 1499 best solution, best possible 0 (119.68 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 846 rows 288 columns - 9 fixed gives 820, 279 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 455 rows 212 columns
Cbc0010I After 11000 nodes, 21 on tree, 1499 best solution, best possible 0 (126.98 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 1060 rows 356 columns - 29 fixed gives 974, 309 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 549 rows 242 columns
Cbc0038I Full problem 1481 rows 765 columns, reduced to 1040 rows 350 columns - 21 fixed gives 1001, 322 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 192 rows 108 columns
Cbc0010I After 12000 nodes, 311 on tree, 1499 best solution, best possible 166.16777 (145.89 seconds)
Cbc0010I After 13000 nodes, 593 on tree, 1499 best solution, best possible 216.18246 (155.53 seconds)
Cbc0010I After 14000 nodes, 591 on tree, 1499 best solution, best possible 216.18246 (162.12 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 837 rows 324 columns - 59 fixed gives 631, 244 - ok now
Cbc0038I Full problem 1481 rows 765 columns, reduced to 14 rows 15 columns
Cbc0010I After 15000 nodes, 860 on tree, 1499 best solution, best possible 253.27932 (173.35 seconds)
Cbc0010I After 16000 nodes, 1093 on tree, 1499 best solution, best possible 286.19305 (184.40 seconds)
Cbc0010I After 17000 nodes, 1285 on tree, 1499 best solution, best possible 317.6446 (198.08 seconds)
Cbc0010I After 18000 nodes, 1279 on tree, 1499 best solution, best possible 317.6446 (205.10 seconds)
Cbc0010I After 19000 nodes, 1423 on tree, 1499 best solution, best possible 344.99529 (221.26 seconds)
Cbc0010I After 20000 nodes, 1538 on tree, 1499 best solution, best possible 383.55586 (238.58 seconds)
Cbc0010I After 21000 nodes, 1668 on tree, 1499 best solution, best possible 420.91112 (254.96 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 1075 rows 364 columns - 42 fixed gives 944, 305 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 499 rows 221 columns
Cbc0010I After 22000 nodes, 1607 on tree, 1499 best solution, best possible 420.91112 (263.50 seconds)
Cbc0010I After 23000 nodes, 1696 on tree, 1499 best solution, best possible 455.7251 (280.44 seconds)
Cbc0010I After 24000 nodes, 1740 on tree, 1499 best solution, best possible 496.47506 (295.77 seconds)
Cbc0010I After 25000 nodes, 1756 on tree, 1499 best solution, best possible 534.79018 (311.28 seconds)
Cbc0010I After 26000 nodes, 1744 on tree, 1499 best solution, best possible 534.79018 (317.14 seconds)
Cbc0010I After 27000 nodes, 1762 on tree, 1499 best solution, best possible 567.92073 (330.93 seconds)
Cbc0010I After 28000 nodes, 1767 on tree, 1499 best solution, best possible 602.00086 (345.60 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 979 rows 347 columns - 36 fixed gives 833, 291 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 196 rows 82 columns
Cbc0010I After 29000 nodes, 1822 on tree, 1499 best solution, best possible 635.65129 (358.73 seconds)
Cbc0010I After 30000 nodes, 1815 on tree, 1499 best solution, best possible 635.65129 (366.19 seconds)
Cbc0010I After 31000 nodes, 1816 on tree, 1499 best solution, best possible 671.0556 (381.17 seconds)
Cbc0010I After 32000 nodes, 1780 on tree, 1499 best solution, best possible 708.82215 (395.94 seconds)
Cbc0010I After 33000 nodes, 1806 on tree, 1499 best solution, best possible 742.03546 (408.70 seconds)
Cbc0010I After 34000 nodes, 1798 on tree, 1499 best solution, best possible 742.03546 (413.99 seconds)
Cbc0010I After 35000 nodes, 1900 on tree, 1499 best solution, best possible 773.04295 (425.68 seconds)
Cbc0038I Full problem 1481 rows 765 columns, reduced to 1075 rows 348 columns - 30 fixed gives 951, 304 - still too large
Cbc0038I Full problem 1481 rows 765 columns, reduced to 587 rows 234 columns
Cbc0010I After 36000 nodes, 2020 on tree, 1499 best solution, best possible 802.14105 (436.16 seconds)
Cbc0010I After 37000 nodes, 2123 on tree, 1499 best solution, best possible 822.47608 (446.68 seconds)
Cbc0004I Integer solution of 1368 found after 2839702 iterations and 37426 nodes (449.42 seconds)
event(solution) CbcModel.cpp:4568
More information about the Cbc
mailing list