void tilingInterpolation::integer_pruning(box const & old_box, box const & new_box, int i) { Enode * it; //TODO what about shared ? should we rather take the projections if (is_a_var(i)) { it = make_false(); } else { assert(is_b_var(i)); it = make_true(); } if (new_box.get_values()[i].is_empty()) { //if the new box is empty then we have a leaf push_partial_interpolant(it); proof_size += 1; } else { //we need to figure out what parts are pruned auto const fst_value = old_box.get_value(i); auto const snd_value = new_box.get_value(i); //pruning on the lower end if (fst_value.lb() < snd_value.lb()) { std::tuple<bool,int,double,bool> pivot(false, i, snd_value.lb(), false); split_stack.push(pivot); push_partial_interpolant(it); proof_size += 1; } //pruning on the upper end if (fst_value.ub() > snd_value.ub()) { std::tuple<bool,int,double,bool> pivot(true, i, snd_value.ub(), false); split_stack.push(pivot); push_partial_interpolant(it); proof_size += 1; } } }
void tilingInterpolation::pruning(box const & old_box, box const & new_box, std::shared_ptr<constraint> cstr) { Enode * it; if (is_a_constraint(cstr)) { it = make_false(); } else if (is_b_constraint(cstr)) { it = make_true(); } else { assert(is_bound(cstr)); DREAL_LOG_DEBUG << "pruning, ignoring bound: " << cstr.get(); return; } if (new_box.is_empty()) { //if the new box is empty then we have a leaf push_partial_interpolant(it); proof_size += 1; } else { //we need to figure out what parts are pruned int max_var = domain.get_vars().size(); for (int i = 0; i < max_var; i++) { auto const fst_value = old_box.get_value(i); auto const snd_value = new_box.get_value(i); //pruning on the lower end if (fst_value.lb() < snd_value.lb()) { std::tuple<bool,int,double,bool> pivot(false, i, snd_value.lb(), false); split_stack.push(pivot); push_partial_interpolant(it); proof_size += 1; } //pruning on the upper end if (fst_value.ub() > snd_value.ub()) { std::tuple<bool,int,double,bool> pivot(true, i, snd_value.ub(), false); split_stack.push(pivot); push_partial_interpolant(it); proof_size += 1; } } } }
bool optimizer::improve_naive(box& p) { //note that p is a point not a nontrivial box Enode * target = NULL; //will pick one target error function double delta = config.nra_precision; double max_error = delta; for (auto f : error_funcs) { //evaluate f on p double c = std::fabs(eval_enode_term(f,p)); cerr << "for f = " << f << ", the error evaluates to " << c << endl; if (c > max_error) { max_error = c; target = f; } } if (max_error<=delta) { cerr << "error already minimized" << endl; return false; } cerr << "max_error is: " << max_error << ", happening on function " << target << endl; //otherwise, move on each dimension based on the gradient of f Enode * ptarget = plainf[target]; //use the simplified form for computing gradients map<Enode*, double> new_values; unordered_set<Enode*> vars = ptarget->get_vars(); for (auto v : vars) { Enode * gradient_v = egraph.mkDeriv(ptarget,v); double p_v = p.get_value(v).lb(); double grad = eval_enode_term(gradient_v,p); //take a newton step on the dimention cerr << "exploring the domain:\n" << domain << endl; double length = domain.get_value(v).ub() - domain.get_value(v).lb(); double step = ((p_v-domain.get_value(v).lb())/(length+delta))*(domain.get_value(v).ub()-p_v); cerr << "taking a step of size: " << step << endl; cerr << "at gradient " << grad << endl; double newv = p_v - step*grad; cerr << "making a move on " << v << " by " << newv << endl; new_values.emplace(v,newv); } //TODO: collect the box that it has been through //if value interval has no zero, push to the learned boxes; the new point is the improved point //if value interval has zero, push that box to the top! for (auto v : vars) { //change the value in p using the new point p.set_value(v,new_values[v],new_values[v]); //lower and upper bounds are the same } cerr << "the new point is:\n" << p << endl; return true; }
double eval_enode_term(Enode * const e, box const & b) { if (e->isVar()) { return b.get_value(e).lb(); } else if (e->isConstant()) { double const v = e->getValue(); return v; } else if (e->isSymb()) { throw runtime_error("eval_enode: Symb"); } else if (e->isNumb()) { throw runtime_error("eval_enode: Numb"); } else if (e->isTerm()) { assert(e->getArity() >= 1); enodeid_t id = e->getCar()->getId(); double ret = 0.0; Enode * tmp = e; switch (id) { case ENODE_ID_PLUS: ret = eval_enode_term(tmp->get1st(), b); tmp = tmp->getCdr()->getCdr(); // e is pointing to the 2nd arg while (!tmp->isEnil()) { ret = ret + eval_enode_term(tmp->getCar(), b); tmp = tmp->getCdr(); } return ret; case ENODE_ID_MINUS: ret = eval_enode_term(tmp->get1st(), b); tmp = tmp->getCdr()->getCdr(); // e is pointing to the 2nd arg while (!tmp->isEnil()) { ret = ret - eval_enode_term(tmp->getCar(), b); tmp = tmp->getCdr(); } return ret; case ENODE_ID_UMINUS: ret = eval_enode_term(tmp->get1st(), b); assert(tmp->getArity() == 1); return (- ret); case ENODE_ID_TIMES: ret = eval_enode_term(tmp->get1st(), b); tmp = tmp->getCdr()->getCdr(); // e is pointing to the 2nd arg while (!tmp->isEnil()) { ret = ret * eval_enode_term(tmp->getCar(), b); tmp = tmp->getCdr(); } return ret; case ENODE_ID_DIV: ret = eval_enode_term(tmp->get1st(), b); tmp = tmp->getCdr()->getCdr(); // e is pointing to the 2nd arg while (!tmp->isEnil()) { ret = ret / eval_enode_term(tmp->getCar(), b); tmp = tmp->getCdr(); } return ret; case ENODE_ID_ACOS: assert(e->getArity() == 1); return acos(eval_enode_term(e->get1st(), b)); case ENODE_ID_ASIN: assert(e->getArity() == 1); return asin(eval_enode_term(e->get1st(), b)); case ENODE_ID_ATAN: assert(e->getArity() == 1); return atan(eval_enode_term(e->get1st(), b)); case ENODE_ID_ATAN2: assert(e->getArity() == 2); return atan2(eval_enode_term(e->get1st(), b), eval_enode_term(e->get2nd(), b)); case ENODE_ID_MIN: assert(e->getArity() == 2); return fmin(eval_enode_term(e->get1st(), b), eval_enode_term(e->get2nd(), b)); case ENODE_ID_MAX: assert(e->getArity() == 2); return fmax(eval_enode_term(e->get1st(), b), eval_enode_term(e->get2nd(), b)); case ENODE_ID_MATAN: assert(e->getArity() == 1); throw runtime_error("eval_enode: MATAN"); case ENODE_ID_SAFESQRT: assert(e->getArity() == 1); throw runtime_error("eval_enode: SAFESQRT"); case ENODE_ID_SQRT: assert(e->getArity() == 1); return sqrt(eval_enode_term(e->get1st(), b)); case ENODE_ID_EXP: assert(e->getArity() == 1); return exp(eval_enode_term(e->get1st(), b)); case ENODE_ID_LOG: assert(e->getArity() == 1); return log(eval_enode_term(e->get1st(), b)); case ENODE_ID_POW: assert(e->getArity() == 2); return pow(eval_enode_term(e->get1st(), b), eval_enode_term(e->get2nd(), b)); case ENODE_ID_ABS: assert(e->getArity() == 1); return fabs(eval_enode_term(e->get1st(), b)); case ENODE_ID_SIN: assert(e->getArity() == 1); return sin(eval_enode_term(e->get1st(), b)); case ENODE_ID_COS: assert(e->getArity() == 1); return cos(eval_enode_term(e->get1st(), b)); case ENODE_ID_TAN: assert(e->getArity() == 1); return tan(eval_enode_term(e->get1st(), b)); case ENODE_ID_SINH: assert(e->getArity() == 1); return sinh(eval_enode_term(e->get1st(), b)); case ENODE_ID_COSH: assert(e->getArity() == 1); return cosh(eval_enode_term(e->get1st(), b)); case ENODE_ID_TANH: assert(e->getArity() == 1); return tanh(eval_enode_term(e->get1st(), b)); default: throw runtime_error("eval_enode: Unknown Term"); } } else if (e->isList()) { throw runtime_error("eval_enode: List"); } else if (e->isDef()) { throw runtime_error("eval_enode: Def"); } else if (e->isEnil()) { throw runtime_error("eval_enode: Nil"); } else { throw runtime_error("eval_enode: unknown case"); } throw runtime_error("Not implemented yet: eval_enode"); }