7 #include "CoinHelperFunctions.hpp"
9 #include <OsiVolSolverInterface.hpp>
10 #include <OsiClpSolverInterface.hpp>
44 const std::pair<BCP_cut*, BCP_row*>& p1)
56 const size_t cutnum = new_cuts.
size();
57 if (cutnum != new_rows.
size())
58 throw BCP_fatal_error(
"Uneven vector sizes in MC_lp_unique_cycle_cuts.\n");
63 std::pair<BCP_cut*, BCP_row*>* cut_row_pairs =
64 new std::pair<BCP_cut*, BCP_row*>[cutnum];
65 for (i = 0; i < cutnum; ++i) {
66 cut_row_pairs[i].first = new_cuts[i];
67 cut_row_pairs[i].second = new_rows[i];
72 new_cuts[0] = cut_row_pairs[0].first;
73 new_rows[0] = cut_row_pairs[0].second;
74 for (i = 1; i < cutnum; ++i) {
76 delete cut_row_pairs[i].first;
77 delete cut_row_pairs[i].second;
79 new_cuts[++
k] = cut_row_pairs[i].first;
80 new_rows[
k] = cut_row_pairs[i].second;
85 delete[] cut_row_pairs;
127 return new OsiVolSolverInterface;
131 return new OsiClpSolverInterface;
142 bool in_strong_branching)
150 OsiVolSolverInterface* vollp =
dynamic_cast<OsiVolSolverInterface*
>(
lp);
152 VOL_parms& vpar = vollp->volprob()->parm;
172 if (in_strong_branching) {
190 for (k =
x.size(), i =
x.size() - 1; i >= 0; --i) {
191 const double xx =
x[i];
195 }
else if (xx < etol) {
215 improve_round, edge_switch, struct_switch,
216 .9, 0, new_cuts, new_rows);
218 if (new_cuts.
size() == 0) {
255 double*
w =
new double[
m];
256 double * xx =
new double[
m];
267 for (i = 0; i < heurnum; ++i) {
268 for (j = 0; j <
m; ++
j)
269 w[j] = CoinDrand48();
272 improve_round, do_edge_switch, struct_switch);
276 for (i = 0; i < heurnum; ++i) {
278 for (j = 0; j <
m; ++
j)
279 w[j] = CoinDrand48();
282 improve_round, do_edge_switch, struct_switch);
285 for (i = 0; i < heurnum; ++i) {
287 for (j = 0; j <
m; ++
j)
288 w[j] = CoinDrand48();
291 improve_round, do_edge_switch, struct_switch);
297 for (i = 0; i < heurnum; ++i) {
298 for (j = 0; j <
m; ++
j) {
299 w[
j] = CoinDrand48();
300 xx[
j] = x[
j] * (.95 + .1 * CoinDrand48());
305 par.
entry(MC_lp_par::DoIsingSquareSwitchHeur));
312 const double * lhs = lpres.lhs();
313 const int numcuts = cuts.
size();
315 for (i = 0; i < numcuts; ++i) {
316 const double ub = cuts[i]->ub();
320 ratio = CoinMin(ratio, ub/lhs[i]);
323 for (i = 0; i <
m; ++i)
325 for (i = 0; i < heurnum; ++i) {
326 for (j = 0; j <
m; ++
j) {
327 w[
j] = CoinDrand48();
332 par.
entry(MC_lp_par::DoIsingSquareSwitchHeur));
364 const int cutnum = cuts.
size();
370 const int varnum = vars.
size();
371 double* coefs =
new double[varnum];
372 int* inds =
new int[varnum];
373 int* iotainds =
new int[varnum];
374 CoinIotaN(iotainds, varnum, 0);
376 for (
int i = 0; i < cutnum; ++i) {
382 CoinDisjointCopyN(cycle_cut->
edges, len, inds);
383 CoinFillN(coefs, pos, 1.0);
384 CoinFillN(coefs + pos, len - pos, -1.0);
385 CoinSort_2(inds, inds + len, coefs);
398 lb, dense_cut->
rhs));
405 for (
int i = 0; i < cutnum; ++i) {
407 if (cuts[i]->lb() != rows[i]->LowerBound() ||
408 cuts[i]->ub() != rows[i]->UpperBound()) {
409 printf(
"*** What! *** : cut bounds are not the same: %i %f %f %f %f\n",
410 i, cuts[i]->lb(), rows[i]->LowerBound(),
411 cuts[i]->ub(), rows[i]->UpperBound());
413 if (lhs < cuts[i]->lb() || lhs > cuts[i]->ub()) {
414 printf(
"*** Violation *** : index: %i lhs: %f lb: %f ub: %f\n",
415 i, lhs, cuts[i]->lb(), cuts[i]->ub());
446 const double minviol =
455 const int numvars = vars.
size();
456 double*
w =
new double[numvars];
457 double* xx =
new double[numvars];
463 for (i = 0; i < heurnum; ++i) {
465 for (j = 0; j < numvars; ++
j)
466 w[j] = CoinDrand48();
469 heurswitchround, edge_switch, struct_switch,
470 minviol, new_cuts.
size() + max_cycle_num,
475 for (i = 0; i < heurnum; ++i) {
477 for (j = 0; j < numvars; ++
j)
478 w[j] = CoinDrand48();
481 heurswitchround, edge_switch, struct_switch,
482 minviol, new_cuts.
size() + max_cycle_num,
486 for (i = 0; i < heurnum; ++i) {
488 for (j = 0; j < numvars; ++
j)
489 w[j] = CoinDrand48();
492 heurswitchround, edge_switch, struct_switch,
493 minviol, new_cuts.
size() + max_cycle_num,
497 const int cutnum_add = new_cuts.
size() - cutnum;
498 printf(
"MC: cycle cuts (add): %i\n", cutnum_add);
502 for (i = 0; i < numvars; ++i)
503 xx[i] = x[i]*(.95 + .1 * CoinDrand48());
504 for (i = 0; i < heurnum; ++i) {
506 for (j = 0; j < numvars; ++
j)
507 w[j] = CoinDrand48();
510 heurswitchround, new_cuts.
size() + max_cycle_num,
516 const int cutnum_mult_add = new_cuts.
size() - cutnum - cutnum_add;
517 printf(
"MC: cycle cuts (mult & add): %i\n", cutnum_mult_add);
524 const double * lhs = lpres.lhs();
525 const int numcuts = cuts.
size();
528 double maxviol = 0.0;
529 for (i = 0; i < numcuts; ++i) {
530 const double ub = cuts[i]->ub();
535 maxviol = CoinMax(maxviol, lhs[i] - ub);
537 ratio = CoinMin(ratio, ub/lhs[i]);
540 printf(
"MC: primal shrinking: %.6f , %i cuts left violated (%.6f)\n",
541 ratio, cnt, maxviol);
542 for (i = 0; i < numvars; ++i)
544 for (i = 0; i < heurnum; ++i) {
546 for (j = 0; j < numvars; ++
j)
547 w[j] = CoinDrand48();
550 heurswitchround, new_cuts.
size() + max_cycle_num,
555 const int cutnum_shrink_add =
556 new_cuts.
size() - cutnum - cutnum_add - cutnum_mult_add;
557 printf(
"MC: cycle cuts (shrink & add): %i\n", cutnum_shrink_add);
574 const double minviol =
588 const double*
x = lpres.
x();
589 double* xx =
new double[vars.
size()];
590 for (
int i = vars.
size() - 1; i >= 0; --i) {
599 vars, cuts, new_cuts, new_rows);
603 vars, cuts, new_cuts, new_rows);
610 double max_lp_viol = 0.0;
614 OsiVolSolverInterface* vollp =
618 const double * rhs = vollp->getRightHandSide();
619 for (
int k = vollp->getNumRows() - 1;
k >= 0; --
k)
620 max_lp_viol = CoinMax(max_lp_viol, lhs[
k] - rhs[
k]);
622 max_lp_viol += 0.001;
634 bool tailoff_gap_rel, tailoff_lb_abs, tailoff_lb_rel;
635 tailoff_test(tailoff_gap_rel, tailoff_lb_abs, tailoff_lb_rel, objval);
639 int i, cutnum = new_cuts.
size();
642 const int grid =
static_cast<int>(sqrt(
mc.
num_nodes + 1.0));
643 const int grid_nodes = grid*grid;
644 const double minviol =
649 x, minviol, new_cuts, new_rows);
650 const int ising_four_cycle_num = new_cuts.
size() - cutnum;
651 printf(
"MC: ising four cycles: %i \n", ising_four_cycle_num);
652 cutnum = new_cuts.
size();
657 x, 0.9, new_cuts, new_rows);
658 const int ising_triangle_num = new_cuts.
size() - cutnum;
659 printf(
"MC: ising triangles: %i \n", ising_triangle_num);
660 cutnum = new_cuts.
size();
671 (cutnum < 50 || tailoff_gap_rel || tailoff_lb_abs || tailoff_lb_rel));
676 const int cycle_num = new_cuts.
size() - cutnum;
678 printf(
"MC: cycle cuts: %i (%i before removing duplicates)\n",
679 static_cast<int>(new_cuts.
size()) - cutnum, cycle_num);
680 cutnum = new_cuts.
size();
691 (cutnum < 50 || tailoff_gap_rel || tailoff_lb_abs || tailoff_lb_rel));
696 const int sp_cycle_num = new_cuts.
size() - cutnum;
698 printf(
"MC: SP based cycle cuts: %i (%i before removing duplicates)\n",
699 static_cast<int>(new_cuts.
size()) - cutnum, sp_cycle_num);
700 cutnum = new_cuts.
size();
704 for (i = 0; i < cutnum; ++i) {
706 if (new_cuts[i]->lb() != new_rows[i]->LowerBound() ||
707 new_cuts[i]->ub() != new_rows[i]->UpperBound()) {
708 printf(
"*** What! *** : cut bounds are not the same: %i %f %f %f %f\n",
709 i, new_cuts[i]->lb(), new_rows[i]->LowerBound(),
710 new_cuts[i]->ub(), new_rows[i]->UpperBound());
712 if (lhs < new_cuts[i]->lb() || lhs > new_cuts[i]->ub()) {
713 printf(
"*** Violation *** : index: %i lhs: %f lb: %f ub: %f\n",
714 i, lhs, new_cuts[i]->lb(), new_cuts[i]->ub());
728 const int var_bound_changes_since_logical_fixing,
734 if (var_bound_changes_since_logical_fixing == 0)
741 int * first_on_chain =
new int[
n];
742 int * last_on_chain =
new int[
n];
743 int * next_on_chain =
new int[
n];
744 int * size_of_chain =
new int[
n];
745 int * sig =
new int[
n];
747 CoinIotaN(first_on_chain, n, 0);
748 CoinIotaN(last_on_chain, n, 0);
749 CoinFillN(next_on_chain, n, -1);
750 CoinFillN(size_of_chain, n, 1);
751 CoinFillN(sig, n, 1);
757 for (
int k = 0;
k <
m; ++
k) {
758 if (vars[
k]->lb() != vars[
k]->ub())
760 const int i = edges[
k].
tail;
761 const int j = edges[
k].
head;
762 const int label_i = first_on_chain[i];
763 const int label_j = first_on_chain[
j];
764 if (label_i == label_j)
766 if (size_of_chain[label_i] > size_of_chain[label_j]) {
774 for (
int l = label_s; l != -1; l = next_on_chain[l]) {
775 first_on_chain[l] = label_l;
777 if ((vars[
k]->lb() == 0.0 && sig[i] != sig[j]) ||
778 (vars[
k]->lb() == 1.0 && sig[i] == sig[j])) {
780 for (
int l = label_s; l != -1; l = next_on_chain[l]) {
784 next_on_chain[last_on_chain[label_l]] = label_s;
785 last_on_chain[label_l] = last_on_chain[label_s];
786 size_of_chain[label_l] += size_of_chain[label_s];
789 delete[] last_on_chain;
790 delete[] next_on_chain;
791 delete[] size_of_chain;
797 const int * component = first_on_chain;
798 for (
int k = 0;
k <
m; ++
k) {
799 if (vars[
k]->lb() == vars[
k]->ub())
801 const int i = edges[
k].
tail;
802 const int j = edges[
k].
head;
803 if (component[i] == component[j]) {
806 if (sig[i] == sig[j]) {
815 printf(
"MC: logical fixing: # of components: %i, fixed %i variables.\n",
816 n - tree_size, static_cast<int>(changed_pos.
size()));
817 delete[] first_on_chain;
BCP_object_origin
This enumerative constant describes the origin (originating process) of an object (variable or cut)...
static bool MC_cycle_row_pair_comp(const std::pair< BCP_cut *, BCP_row * > &p0, const std::pair< BCP_cut *, BCP_row * > &p1)
MC_solution * MC_mst_cutgen(const MC_problem &mc, const double *x, const double *w, const double alpha, const double beta, const MC_EdgeOrdering edge_ordering, const int heurswitchround, const bool do_edge_switch_heur, const int struct_switch_heur, const double minviol, const int maxnewcuts, BCP_vec< BCP_cut * > &new_cuts, BCP_vec< BCP_row * > &new_rows)
bool MC_cycle_cut_equal(const BCP_cut *bc0, const BCP_cut *bc1)
Upper limit on the number of iterations performed in each of the children of the search tree node whe...
pos
position where the operator should be printed when printing the expression
void clear()
Delete every entry.
Abstract base class that defines members common to all types of cuts.
virtual void unpack_module_data(BCP_buffer &buf)
Unpack the initial information sent to the LP process by the Tree Manager.
virtual BCP_solution * test_feasibility(const BCP_lp_result &lp_result, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts)
Evaluate and return MIP feasibility of the current solution.
char entry(const chr_params key) const
void MC_generate_shortest_path_cycles(const MC_problem &mc, const double *x, const bool generate_all_cuts, const double minviol, BCP_vec< BCP_cut * > &new_cuts, BCP_vec< BCP_row * > &new_rows)
void set_param(const BCP_lp_par::chr_params key, const bool val)
The two objects are the same.
const double * lhs() const
BCP_buffer & unpack(BCP_buffer &buf)
virtual BCP_object_compare_result compare_cuts(const BCP_cut *c0, const BCP_cut *c1)
Compare two generated cuts.
void reserve(const size_t n)
Reallocate the object to make space for n entries.
int current_iteration() const
Return the iteration count within the search tree node being processed.
void push_back(const_reference x)
Append x to the end of the vector.
virtual void modify_lp_parameters(OsiSolverInterface *lp, const int changeType, bool in_strong_branching)
Modify parameters of the LP solver before optimization.
static void MC_update_solution(MC_solution *&sol_old, MC_solution *&sol_new)
BCP_parameter_set< MC_lp_par > par
virtual void cuts_to_rows(const BCP_vec< BCP_var * > &vars, BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_row * > &rows, const BCP_lp_result &lpres, BCP_object_origin origin, bool allow_multiple)
Convert (and possibly lift) a set of cuts into corresponding rows for the current LP relaxation...
static const int cycle_cut
static double ratio(Bigint *a, Bigint *b)
virtual void logical_fixing(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const BCP_vec< BCP_obj_status > &var_status, const BCP_vec< BCP_obj_status > &cut_status, const int var_bound_changes_since_logical_fixing, BCP_vec< int > &changed_pos, BCP_vec< double > &new_bd)
This method provides an opportunity for the user to tighten the bounds of variables.
void erase(iterator pos)
Erase the entry pointed to by pos.
void fint fint fint real fint real real real real real real real real real fint real fint * lp
BCP_lp_prob * getLpProblemPointer()
Get the pointer.
MC_solution * MC_mst_heur(const MC_problem &mc, const double *x, const double *w, const double alpha, const double beta, const MC_EdgeOrdering edge_ordering, const int heurswitchround, const bool do_edge_switch_heur, const int struct_switch_heur)
OsiSolverInterface * lp_solver
A class that holds the methods about how to pack things.
void generate_mst_cuts(const double *x, const double *lhs, const double objval, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_cut * > &new_cuts, BCP_vec< BCP_row * > &new_rows)
BCP_lp_result * lp_result
void unique_cycle_cuts(BCP_vec< BCP_cut * > &new_cuts, BCP_vec< BCP_row * > &new_rows)
void tailoff_test(bool &tailoff_gap_rel, bool &tailoff_lb_abs, bool &tailoff_lb_rel, const double objval) const
virtual double objective_value() const
The method returning the objective value of the solution.
virtual BCP_solution * generate_heuristic_solution(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts)
Try to generate a heuristic solution (or return one generated during cut/variable generation...
Currently there isn't any error handling in BCP.
size_t size() const
Return the current number of entries.
iterator end()
Return an iterator to the end of the object.
This class describes the message buffer used for all processes of BCP.
MC_solution * mc_generate_heuristic_solution(const double *x, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts)
A local helper function.
virtual void pack_feasible_solution(BCP_buffer &buf, const BCP_solution *sol)
Pack a MIP feasible solution into a buffer.
The two objects are not comparable or neither is better than the other.
void unchecked_push_back(const_reference x)
Append x to the end of the vector.
void generate_sp_cuts(const double *x, const double *lhs, const double objval, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_cut * > &new_cuts, BCP_vec< BCP_row * > &new_rows)
virtual OsiSolverInterface * initialize_solver_interface()
Create LP solver environment.
void purge_ptr_vector(BCP_vec< T * > &pvec, typename BCP_vec< T * >::iterator first, typename BCP_vec< T * >::iterator last)
This function purges the entries [first,last) from the vector of pointers pvec.
void unpack(BCP_buffer &buf)
Unpack the parameter set from the buffer.
This class holds the results after solving an LP relaxation.
void MC_test_ising_triangles(const int n, const int *cycles, const double *x, const double minviol, BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_row * > &rows)
iterator entry(const int i)
Return an iterator to the i-th entry.
void fint fint fint real fint real real real real real real real real * w
void MC_test_ising_four_cycles(const int n, const int *cycles, const double *x, const double minviol, BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_row * > &rows)
bool MC_cycle_cut_less(const BCP_cut *bc0, const BCP_cut *bc1)
BCP_object_compare_result
This enumerative constant describes the possible outcomes when comparing two objects (variables or cu...
The maximum number of violated valid inequalities that can be added per iteration.
BCP_buffer & pack(BCP_buffer &buf) const
void fint fint fint real fint real * x
This class holds a row in a compressed form.
This is the abstract base class for a solution to a Mixed Integer Programming problem.
virtual void generate_cuts_in_lp(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_cut * > &new_cuts, BCP_vec< BCP_row * > &new_rows)
Generate cuts within the LP process.