Optimizer::Status Optimizer::optimize(const IntervalVector& init_box, double obj_init_bound) { loup=obj_init_bound; pseudo_loup=obj_init_bound; buffer.contract(loup); uplo=NEG_INFINITY; uplo_of_epsboxes=POS_INFINITY; nb_cells=0; nb_simplex=0; diam_simplex=0; nb_rand=0; diam_rand=0; buffer.flush(); Cell* root=new Cell(IntervalVector(n+1)); write_ext_box(init_box,root->box); // add data required by the bisector bsc.add_backtrackable(*root); // add data "pu" and "pf" (if required) buffer.cost2().add_backtrackable(*root); // add data required by optimizer + Fritz John contractor root->add<EntailedCtr>(); //root->add<Multipliers>(); entailed=&root->get<EntailedCtr>(); entailed->init_root(user_sys,sys); loup_changed=false; initial_loup=obj_init_bound; loup_point=init_box.mid(); time=0; Timer::start(); handle_cell(*root,init_box); update_uplo(); try { while (!buffer.empty()) { // if (trace >= 2) cout << " buffer " << buffer << endl; if (trace >= 2) buffer.print(cout); // cout << "buffer size " << buffer.size() << " " << buffer2.size() << endl; // removes from the heap buffer, the cells already chosen in the other buffer if (buffer.empty()) { //cout << " buffer empty " << buffer.empty() << " " << buffer2.empty() << endl; // this update is only necessary when buffer was not // initially empty update_uplo(); break; } loup_changed=false; Cell *c; // random choice between the 2 buffers corresponding to two criteria implemented in two heaps) // critpr chances over 100 to choose the second heap (see CellDoubleHeap) c=buffer.top(); try { pair<IntervalVector,IntervalVector> boxes=bsc.bisect(*c); pair<Cell*,Cell*> new_cells=c->bisect(boxes.first,boxes.second); buffer.pop(); delete c; // deletes the cell. handle_cell(*new_cells.first, init_box); handle_cell(*new_cells.second, init_box); if (uplo_of_epsboxes == NEG_INFINITY) { cout << " possible infinite minimum " << endl; break; } if (loup_changed) { // In case of a new upper bound (loup_changed == true), all the boxes // with a lower bound greater than (loup - goal_prec) are removed and deleted. // Note: if contraction was before bisection, we could have the problem // that the current cell is removed by contractHeap. See comments in // older version of the code (before revision 284). double ymax=compute_ymax(); buffer.contract(ymax); //cout << " now buffer is contracted and min=" << buffer.minimum() << endl; if (ymax <= NEG_INFINITY) { if (trace) cout << " infinite value for the minimum " << endl; break; } if (trace) cout << setprecision(12) << "ymax=" << ymax << " uplo= " << uplo<< endl; } update_uplo(); time_limit_check(); } catch (NoBisectableVariableException& ) { update_uplo_of_epsboxes((c->box)[ext_sys.goal_var()].lb()); buffer.pop(); delete c; // deletes the cell. update_uplo(); // the heap has changed -> recalculate the uplo } } } catch (TimeOutException& ) { return TIME_OUT; } Timer::stop(); time+= Timer::VIRTUAL_TIMELAPSE(); if (uplo_of_epsboxes == POS_INFINITY && (loup==POS_INFINITY || (loup==initial_loup && goal_abs_prec==0 && goal_rel_prec==0))) return INFEASIBLE; else if (loup==initial_loup) return NO_FEASIBLE_FOUND; else if (uplo_of_epsboxes == NEG_INFINITY) return UNBOUNDED_OBJ; else return SUCCESS; }
void Optimizer::optimize(const IntervalVector& init_box) { buffer.flush(); Cell* root=new Cell(IntervalVector(n+1)); write_ext_box(init_box,root->box); // add data required by the bisector bsc.add_backtrackable(*root); // add data required by optimizer + Fritz John contractor root->add<EntailedCtr>(); //root->add<Multipliers>(); entailed=&root->get<EntailedCtr>(); entailed->init_root(user_sys,sys); loup_changed=false; loup_point=init_box.mid(); time=0; Timer::start(); handle_cell(*root,init_box); try { while (!buffer.empty()) { loup_changed=false; if (trace >= 2) cout << ((CellBuffer&) buffer) << endl; Cell* c=buffer.top(); // cout << " box before bisection " << c->box << endl; try { pair<IntervalVector,IntervalVector> boxes=bsc.bisect(*c); pair<Cell*,Cell*> new_cells=c->bisect(boxes.first,boxes.second); delete buffer.pop(); handle_cell(*new_cells.first, init_box); handle_cell(*new_cells.second, init_box); if (uplo_of_epsboxes == NEG_INFINITY) { cout << " possible infinite minimum " << endl; break; } if (loup_changed ) { // In case of a new upper bound (loup_changed == true), all the boxes // with a lower bound greater than (loup - goal_prec) are removed and deleted. // Note: if contraction was before bisection, we could have the problem // that the current cell is removed by contract_heap. See comments in // older version of the code (before revision 284). double ymax= compute_ymax(); buffer.contract_heap(ymax); if (ymax <=NEG_INFINITY) { if (trace) cout << " infinite value for the minimum " << endl; break; } if (trace) cout << setprecision(12) << "ymax=" << ymax << " uplo= " << uplo<< endl; } update_uplo(); time_limit_check(); } catch (NoBisectableVariableException& ) { bool bb=false; for (int i=0;(!bb)&&( i<(c->box).size()); i++) { if (i!=ext_sys.goal_var()) // skip goal variable bb=bb||(c->box)[i].is_unbounded(); } if (!bb) { // rem4: this case can append if the interval [1.79769e+308,inf] is in c.box. // It is only numerical degenerated case update_uplo_of_epsboxes ((c->box)[ext_sys.goal_var()].lb()); } delete buffer.pop(); } } } catch (TimeOutException& ) { return; } Timer::stop(); time+= Timer::VIRTUAL_TIMELAPSE(); }
void Optimizer::contract_and_bound(Cell& c, const IntervalVector& init_box) { /*======================== contract y with y<=loup ========================*/ Interval& y=c.box[ext_sys.goal_var()]; // IntervalVector tmp_box(n); // read_ext_box(c.box,tmp_box); double ymax; if (loup==POS_INFINITY) ymax=POS_INFINITY; else ymax= compute_ymax()+1.e-15; // else ymax= compute_ymax(); /* if (!(y.ub() == ymax)) y &= Interval(NEG_INFINITY,ymax+1.e-15); else if (y.ub()==ymax && !(tmp_box.contains(loup_point))) y = Interval(y.lb(), ymax+1.e-15); */ y &= Interval(NEG_INFINITY,ymax); if (y.is_empty()) { c.box.set_empty(); return; } /*================ contract x with f(x)=y and g(x)<=0 ================*/ //cout << " [contract] x before=" << c.box << endl; //cout << " [contract] y before=" << y << endl; ctc.contract(c.box); if (c.box.is_empty()) return; //cout << " [contract] x after=" << c.box << endl; //cout << " [contract] y after=" << y << endl; // TODO: no more cell in argument here (just a box). Does it matter? /*====================================================================*/ /*========================= update loup =============================*/ IntervalVector tmp_box(n); read_ext_box(c.box,tmp_box); entailed = &c.get<EntailedCtr>(); if (!update_entailed_ctr(tmp_box)) { c.box.set_empty(); return; } bool loup_ch=update_loup(tmp_box); // update of the upper bound of y in case of a new loup found if (loup_ch) y &= Interval(NEG_INFINITY,compute_ymax()); loup_changed |= loup_ch; if (y.is_empty()) { // fix issue #44 c.box.set_empty(); return; } /*====================================================================*/ // [gch] The case (!c.box.is_bisectable()) seems redundant // with the case of a NoBisectableVariableException in // optimize(). Is update_uplo_of_epsboxes called twice in this case? // (bn] NO , the NoBisectableVariableException is raised by the bisector, there are 2 different cases of a non bisected box that may cause an update of uplo_of_epsboxes if ((tmp_box.max_diam()<=prec && y.diam() <=goal_abs_prec) || !c.box.is_bisectable()) { // rem1: tmp_box and not c.box because y is handled with goal_rel_prec and goal_abs_prec // rem2: do not use a precision contractor here since it would make the box empty (and y==(-inf,-inf)!!) // rem 3 : the extended boxes with no bisectable domains should be caught for avoiding infinite bisections update_uplo_of_epsboxes(y.lb()); c.box.set_empty(); return; } //gradient=0 contraction for unconstrained optimization ; //first order test for constrained optimization (useful only when there are no equations replaced by inequalities) //works with the box without the objective (tmp_box) firstorder_contract(tmp_box,init_box); if (tmp_box.is_empty()) { c.box.set_empty(); } else { // the current extended box in the cell is updated write_ext_box(tmp_box,c.box); } }
void Optimizer::contract_and_bound(Cell& c, const IntervalVector& init_box) { // cout << "box " <<c.box << endl; /*======================== contract y with y<=loup ========================*/ Interval& y=c.box[ext_sys.goal_var()]; double ymax; if (loup==POS_INFINITY) ymax=POS_INFINITY; else ymax= compute_ymax(); y &= Interval(NEG_INFINITY,ymax); if (y.is_empty()) { c.box.set_empty(); throw EmptyBoxException(); } /*================ contract x with f(x)=y and g(x)<=0 ================*/ // cout << "y=f(x) and g(x)<=0 " << endl; // cout << " x before=" << c.box << endl; // cout << " y before=" << y << endl; contract(c.box, init_box); // cout << " x after=" << c.box << endl; // cout << " y after=" << y << endl; // TODO: no more cell in argument here (just a box). Does it matter? /*====================================================================*/ /*========================= update loup =============================*/ IntervalVector tmp_box(n); read_ext_box(c.box,tmp_box); entailed = &c.get<EntailedCtr>(); update_entailed_ctr(tmp_box); update_loup(tmp_box); /*====================================================================*/ // [gch] TODO: the case (!c.box.is_bisectable()) seems redundant // with the case of a NoBisectableVariableException in // optimize(). Is update_uplo_of_epsboxes called twice in this case? // (bn] NO , the NoBisectableVariableException is raised by the bisector, // there are actually 2 different cases of a non bisected box that may cause an update // of uplo_of_epsboxes double tmp_diam =tmp_box.max_diam(); if ((tmp_diam<=prec && y.diam() <=goal_abs_prec) || !c.box.is_bisectable()) { // rem1: tmp_box and not c.box because y is handled with goal_rel_prec and goal_abs_prec // rem2: do not use a precision contractor here since it would make the box empty (and y==(-inf,-inf)!!) // rem 3 : the extended boxes with no bisectable domains should be catched for avoiding infinite bisections if (!(tmp_box.is_unbounded())) { // rem4: this case can append if the interval [1.79769e+308,inf] is in c.box. // It is only numerical degenerated case update_uplo_of_epsboxes(y.lb()); } throw EmptyBoxException(); } //gradient=0 contraction for unconstrained optimization ; //first order test for constrained optimization (useful only when there are no equations replaced by inequalities) //works with the box without the objective (tmp_box) firstorder_contract(tmp_box,init_box); // the current extended box in the cell is updated write_ext_box(tmp_box,c.box); }