Beispiel #1
0
contractor default_strategy::build_contractor(box const & box,
                                              scoped_vec<shared_ptr<constraint>> const & ctrs,
                                              bool const complete,
                                              SMTConfig const & config) const {
    bool const use_cache = true;

    // 1. Categorize constraints
    vector<shared_ptr<nonlinear_constraint>> nl_ctrs;
    vector<shared_ptr<ode_constraint>> ode_ctrs_rev;
    vector<shared_ptr<generic_forall_constraint>> generic_forall_ctrs;
    for (shared_ptr<constraint> const ctr : ctrs.get_reverse()) {
        switch (ctr->get_type()) {
        case constraint_type::Nonlinear: {
            auto nl_ctr = dynamic_pointer_cast<nonlinear_constraint>(ctr);
            nl_ctrs.push_back(nl_ctr);
            break;
        }
        case constraint_type::ODE: {
            auto ode_ctr = dynamic_pointer_cast<ode_constraint>(ctr);
            ode_ctrs_rev.push_back(ode_ctr);
            break;
        }
        case constraint_type::GenericForall: {
            auto gf_ctr = dynamic_pointer_cast<generic_forall_constraint>(ctr);
            generic_forall_ctrs.push_back(gf_ctr);
            break;
        }
        case constraint_type::ForallT: {
            // Do nothing
            break;
        }
        default:
            DREAL_LOG_FATAL << "Unknown Constraint Type: " << ctr->get_type() << " " <<  *ctr << endl;
        }
    }
    vector<shared_ptr<ode_constraint>> ode_ctrs(ode_ctrs_rev);
    reverse(ode_ctrs.begin(), ode_ctrs.end());

    vector<contractor> ctcs;
    ctcs.reserve(ctrs.size());
    // 2.0 Build Sample Contractor
    if (config.nra_sample > 0 && complete) {
        ctcs.push_back(mk_contractor_sample(box, config.nra_sample, ctrs.get_vec()));
    }
    // 2.1 Build nonlinear contractors
    vector<contractor> nl_ctcs;
    for (auto const & nl_ctr : nl_ctrs) {
        if (!nl_ctr->is_neq()) {
            nl_ctcs.push_back(mk_contractor_ibex_fwdbwd(nl_ctr, use_cache));
        } else {
            // Case: != (not equal), do nothing
        }
    }
    contractor nl_ctc = mk_contractor_seq(nl_ctcs);
    ctcs.insert(ctcs.end(), nl_ctcs.begin(), nl_ctcs.end());

    // 2.2. Build Polytope Contractor
    if (config.nra_polytope) {
        ctcs.push_back(mk_contractor_ibex_polytope(config.nra_precision, box.get_vars(), nl_ctrs));
    }
    // 2.3. Int Contractor
    ctcs.push_back(mk_contractor_int(box));
    // 2.4. Build generic forall contractors
    for (auto const & generic_forall_ctr : generic_forall_ctrs) {
        ctcs.push_back(mk_contractor_generic_forall(box, generic_forall_ctr));
    }

    if (complete && ode_ctrs.size() > 0) {
        // Add ODE Contractors only for complete check
        // 2.5. Build GSL Contractors (using CAPD4)
        vector<contractor> ode_gsl_ctcs;
        if (config.nra_ODE_sampling) {
            // 2.5.1 Build Eval contractors
            vector<contractor> eval_ctcs;
            for (auto const & nl_ctr : nl_ctrs) {
                eval_ctcs.push_back(mk_contractor_eval(nl_ctr, false));
            }
            contractor eval_ctc = mk_contractor_seq(eval_ctcs);
            if (config.nra_parallel) {
                vector<contractor> nl_ctcs2;
                for (auto const & nl_ctr : nl_ctrs) {
                    if (!nl_ctr->is_neq()) {
                        nl_ctcs2.push_back(mk_contractor_ibex_fwdbwd(nl_ctr, false));
                    } else {
                        // Case: != (not equal), do nothing
                    }
                }
                contractor nl_ctc2 = mk_contractor_seq(nl_ctcs2);
                for (auto const & ode_ctr : ode_ctrs) {
                    // Add Forward ODE Pruning (Underapproximation, using GNU GSL)
                    ode_gsl_ctcs.push_back(mk_contractor_gsl(box, ode_ctr, eval_ctc, ode_direction::FWD, false, config.nra_ODE_fwd_timeout));
                    ode_gsl_ctcs.push_back(nl_ctc2);
                }
            } else {
                for (auto const & ode_ctr : ode_ctrs) {
                    // Add Forward ODE Pruning (Underapproximation, using GNU GSL)
                    ode_gsl_ctcs.push_back(mk_contractor_gsl(box, ode_ctr, eval_ctc, ode_direction::FWD, use_cache, config.nra_ODE_fwd_timeout));
                    ode_gsl_ctcs.push_back(nl_ctc);
                }
            }
        }
        // 2.6. Build ODE Contractors (using CAPD4)
        vector<contractor> ode_capd4_fwd_ctcs;
        vector<contractor> ode_capd4_bwd_ctcs;
        for (auto const & ode_ctr : ode_ctrs) {
            // 2.6.1. Add Forward ODE Pruning (Overapproximation, using CAPD4)
            if (config.nra_ODE_cache) {
                ode_capd4_fwd_ctcs.emplace_back(
                    mk_contractor_cache(
                        mk_contractor_try(
                            mk_contractor_seq(mk_contractor_capd_full(box, ode_ctr, ode_direction::FWD, config.nra_ODE_taylor_order, config.nra_ODE_grid_size, use_cache, config.nra_ODE_fwd_timeout),
                                              nl_ctc))));
            } else {
                ode_capd4_fwd_ctcs.emplace_back(
                    mk_contractor_try(
                        mk_contractor_seq(
                            mk_contractor_capd_full(box, ode_ctr, ode_direction::FWD, config.nra_ODE_taylor_order, config.nra_ODE_grid_size, use_cache, config.nra_ODE_fwd_timeout),
                            nl_ctc)));
            }
        }
        if (!config.nra_ODE_forward_only) {
            // 2.6.2. Add Backward ODE Pruning (Overapproximation, using CAPD4)
            for (auto const & ode_ctr : ode_ctrs_rev) {
                if (config.nra_ODE_cache) {
                    ode_capd4_bwd_ctcs.emplace_back(
                        mk_contractor_cache(
                            mk_contractor_try(
                                mk_contractor_seq(
                                    mk_contractor_capd_full(box, ode_ctr, ode_direction::BWD, config.nra_ODE_taylor_order, config.nra_ODE_grid_size, use_cache, config.nra_ODE_bwd_timeout),
                                    nl_ctc))));
                } else {
                    ode_capd4_bwd_ctcs.emplace_back(
                        mk_contractor_try(
                            mk_contractor_seq(
                                mk_contractor_capd_full(box, ode_ctr, ode_direction::BWD, config.nra_ODE_taylor_order, config.nra_ODE_grid_size, use_cache, config.nra_ODE_bwd_timeout),
                                nl_ctc)));
                }
            }
        }
        if (config.nra_ODE_sampling) {
            if (config.nra_parallel) {
                ctcs.push_back(mk_contractor_parallel_any(
                                   mk_contractor_try_or(mk_contractor_throw_if_empty(mk_contractor_seq(ode_gsl_ctcs)),
                                                        mk_contractor_empty()),
                                   mk_contractor_seq(mk_contractor_seq(ode_capd4_fwd_ctcs),
                                                     mk_contractor_seq(ode_capd4_bwd_ctcs))));
            } else {
                ctcs.push_back(
                    mk_contractor_try_or(
                        // Try Underapproximation(GSL) if it fails try Overapproximation(CAPD4)
                        mk_contractor_throw_if_empty(mk_contractor_seq(ode_gsl_ctcs)),
                        mk_contractor_seq(mk_contractor_seq(ode_capd4_fwd_ctcs),
                                          mk_contractor_seq(ode_capd4_bwd_ctcs))));
            }
        } else {
            ctcs.insert(ctcs.end(), ode_capd4_fwd_ctcs.begin(), ode_capd4_fwd_ctcs.end());
            ctcs.insert(ctcs.end(), ode_capd4_bwd_ctcs.begin(), ode_capd4_bwd_ctcs.end());
        }
    }
    if (complete) {
        // 2.7 Build Eval contractors
        vector<contractor> eval_ctcs;
        for (auto const & nl_ctr : nl_ctrs) {
            eval_ctcs.push_back(mk_contractor_eval(nl_ctr, use_cache));
        }
        return mk_contractor_seq(mk_contractor_fixpoint(default_strategy::term_cond, ctcs),
                                 mk_contractor_seq(eval_ctcs));
    } else {
        return mk_contractor_fixpoint(default_strategy::term_cond, ctcs);
    }
}
Beispiel #2
0
contractor nra_solver::build_contractor(box const & box, scoped_vec<constraint *> const &ctrs, bool const complete) {
    vector<nonlinear_constraint const *> nl_ctrs;
    vector<contractor> nl_ctcs;
    nl_ctcs.reserve(ctrs.size());
    vector<contractor> nl_eval_ctcs;
    nl_eval_ctcs.reserve(ctrs.size());
    vector<contractor> ode_ctcs;
    ode_ctcs.reserve(ctrs.size());
    // Add contractor_sample if --sample option is used
    if (config.nra_sample > 0 && complete) {
        nl_ctcs.push_back(mk_contractor_sample(config.nra_sample, ctrs.get_vec()));
    }
    for (constraint * const ctr : ctrs) {
        if (ctr->get_type() == constraint_type::Nonlinear) {
            nonlinear_constraint const * const nl_ctr = dynamic_cast<nonlinear_constraint *>(ctr);
            if (nl_ctr->get_numctr()) {
                nl_ctcs.push_back(mk_contractor_ibex_fwdbwd(box, nl_ctr));
                nl_ctrs.push_back(nl_ctr);
            } else {
                // This is identity, do nothing
            }
            nl_eval_ctcs.push_back(mk_contractor_eval(box, nl_ctr));
#ifdef SUPPORT_ODE
        } else if (ctr->get_type() == constraint_type::ODE) {
            // TODO(soonhok): add heuristics to choose fwd/bwd
            // TODO(soonhok): perform ODE only for complete check
            ode_ctcs.emplace_back(
                mk_contractor_try(
                    mk_contractor_capd_fwd_full(box, dynamic_cast<ode_constraint *>(ctr), config.nra_ODE_taylor_order, config.nra_ODE_grid_size)));
            ode_ctcs.emplace_back(
                mk_contractor_try(
                    mk_contractor_capd_bwd_full(box, dynamic_cast<ode_constraint *>(ctr), config.nra_ODE_taylor_order, config.nra_ODE_grid_size)));
#endif
        }
    }
    if (config.nra_polytope) {
        nl_ctcs.push_back(mk_contractor_ibex_polytope(config.nra_precision, nl_ctrs));
    }
    nl_ctcs.push_back(mk_contractor_int());
    // Add contractor_sample if --sample option is used
    if (config.nra_aggressive > 0 && complete) {
        nl_ctcs.push_back(mk_contractor_sample(config.nra_aggressive, ctrs.get_vec()));
    }

    auto term_cond = [this](dreal::box const & old_box, dreal::box const & new_box) {
        if (new_box.max_diam() < config.nra_precision) {
            return true;
        }
        double const threshold = 0.01;
        // If there is a dimension which is improved more than
        // threshold, we stop the current fixed-point computation.
        bool is_corner_case = true;
        for (unsigned i = 0; i < old_box.size(); i++) {
            double const new_box_i = new_box[i].diam();
            double const old_box_i = old_box[i].diam();
            if (new_box_i == numeric_limits<double>::infinity()) {
                continue;
            }
            if (old_box_i == 0) {
                // The i-th dimension was already a point, nothing to improve.
                continue;
            }
            double const improvement = 1 - new_box_i / old_box_i;
            assert(!std::isnan(improvement));
            if (improvement >= threshold) {
                return false;
            } else {
                is_corner_case = false;
            }
        }

        if (is_corner_case && new_box == old_box) {
            // We only do the equality check if it's a corner case
            // where every dimension has either [ENTIRE] or a point
            // value.
            return false;
        }
        return true;
    };
    return mk_contractor_fixpoint(term_cond, nl_ctcs, ode_ctcs, nl_eval_ctcs);
}