示例#1
0
void contractor_throw_if_empty::prune(contractor_status & cs) {
    DREAL_LOG_DEBUG << "contractor_throw_if_empty::prune";
    m_c.prune(cs);
    if (cs.m_box.is_empty()) {
        throw contractor_exception("throw if empty");
    }
}
示例#2
0
void contractor_cache::prune(contractor_status & cs) {
    // extract i-th interval where `m_input[i] == 1`
    vector<ibex::Interval> const in = extract_from_box_using_bitset(cs.m_box, m_input);
    auto const it = m_cache.find(in);
    if (it == m_cache.end()) {
        // not found in cache, run m_ctc
        ++m_num_nohit;
        {
            contractor_status_guard csg(cs);
            assert(cs.m_output.empty());
            assert(cs.m_used_constraints.empty());
            try {
                // run contractor
                m_ctc.prune(cs);
                // extract out from box.
                vector<ibex::Interval> const out = extract_from_box_using_bitset(cs.m_box, cs.m_output);
                // save the result to the cache
                m_cache.emplace(in, make_tuple(out, cs.m_output, cs.m_used_constraints, false));
            } catch (exception & e) {
                m_cache.emplace(in, make_tuple(vector<ibex::Interval>(), cs.m_output, cs.m_used_constraints, true));
                throw contractor_exception(e.what());
            }
        }
    } else {
        ++m_num_hit;
        // found in cache, use it
        auto const & m_cached_content = it->second;
        vector<ibex::Interval> const & out = get<0>(m_cached_content);
        auto const & output_bitset = get<1>(m_cached_content);
        auto const & used_constraints = get<2>(m_cached_content);
        bool const was_exception_thrown = get<3>(m_cached_content);
        cs.m_used_constraints.insert(used_constraints.begin(), used_constraints.end());
        if (was_exception_thrown) {
            cs.m_output.union_with(output_bitset);
            throw contractor_exception("previously there was an exception in the cached computation");
        } else {
            // project out to box;
            update_box_using_bitset(cs.m_box, out, output_bitset);
            cs.m_output.union_with(output_bitset);
        }
    }
}
示例#3
0
void contractor_parallel_all::prune(box & b, SMTConfig & config) {
    DREAL_LOG_DEBUG << "contractor_parallel_all::prune";
    DREAL_LOG_FATAL << "-------------------------------------------------------------";
    // TODO(soonhok): implement this
    if (m_vec.size() == 0) {
        // Do nothing for empty vec
        return;
    }

    // 1. Make n copies of box b
    vector<box> boxes(m_vec.size(), b);
    vector<pruning_thread_status> statuses(m_vec.size(), pruning_thread_status::READY);
    m_index = -1;

    // DREAL_LOG_FATAL << "parallel: Boxes are copied";

    // 2. Trigger execution with each contractor and a copied box
    vector<interruptible_thread> threads;
    atomic_int tasks_to_run(m_vec.size());
    // DREAL_LOG_FATAL << "parallel: tasks to run = " << tasks_to_run.load();
    for (unsigned i = 0; i < m_vec.size(); ++i) {
        DREAL_LOG_FATAL << "parallel : thread " << i << " / " << (tasks_to_run.load() - 1)
                        << " spawning...";
        threads.emplace_back(parallel_helper_fn,
                             i,
                             m_vec[i],
                             boxes[i],
                             config,
                             statuses[i],
                             m_mutex,
                             m_cv,
                             m_index,
                             tasks_to_run);
        DREAL_LOG_FATAL << "parallel : thread " << i << " / " << (tasks_to_run.load() - 1)
                        << " spawned...";
    }
    DREAL_LOG_FATAL << "parallel : " << m_vec.size() << " thread(s) got created";

    while (true) {
        DREAL_LOG_FATAL << "parallel: waiting for the lock";
        unique_lock<mutex> lk(m_mutex);
        DREAL_LOG_FATAL << "parallel: get a lock. " << tasks_to_run.load() << " tasks to go";
        if (tasks_to_run.load() == 0) {
            break;
        }
        DREAL_LOG_FATAL << "parallel: WAIT for CV." << tasks_to_run.load() << " tasks to go";;
        m_index = -1;
        m_cv.wait(lk, [&]() { return m_index != -1; });
        DREAL_LOG_FATAL << "parallel: wake up" << tasks_to_run.load();
        pruning_thread_status const & s = statuses[m_index];
        // DREAL_LOG_FATAL << "parallel: thread " << m_index << " " << s;
        if (s == pruning_thread_status::UNSAT || s == pruning_thread_status::EXCEPTION) {
            // Interrupt all the rest threads
            for (unsigned i = 0; i < statuses.size(); i++) {
                if (i - m_index != 0 && (statuses[i] == pruning_thread_status::READY || statuses[i] == pruning_thread_status::RUNNING)) {
                    threads[i].interrupt();
                }
            }

            if (s == pruning_thread_status::UNSAT) {
                DREAL_LOG_FATAL << "parallel: " << m_index << " got UNSAT";
                b.set_empty();
                m_input.union_with(m_vec[m_index].input());
                m_output.union_with(m_vec[m_index].output());
                unordered_set<shared_ptr<constraint>> const & used_ctrs = m_vec[m_index].used_constraints();
                m_used_constraints.insert(used_ctrs.begin(), used_ctrs.end());
                lk.unlock();
                for (unsigned i = 0; i < m_vec.size(); i++) {
                    threads[i].join();
                }
                DREAL_LOG_FATAL << "parallel: return UNSAT";
                return;
            }
            if (s == pruning_thread_status::EXCEPTION) {
                DREAL_LOG_FATAL << "parallel: " << m_index << " got EXCEPTION";
                lk.unlock();
                for (unsigned i = 0; i < m_vec.size(); i++) {
                    threads[i].join();
                }
                DREAL_LOG_FATAL << "parallel: throw exception";
                throw contractor_exception("exception during parallel contraction");
            }

        } else {
            // if (s != pruning_thread_status::SAT) {
            //     // DREAL_LOG_FATAL << "parallel: " << m_index << " got " << s;
            //     // DREAL_LOG_FATAL << "parallel: " << m_index << " got " << statuses[m_index];
            assert(s == pruning_thread_status::SAT);
            // }
            // if (threads[m_index].joinable()) {
            // threads[m_index].join();
            // }
            // DREAL_LOG_FATAL << "parallel: " << m_index << " got SAT";
            // Why?
            //  - Not READY/RUNNING: It's a job already done.
            //  - Not UNSAT/EXCEPTION: already handled above.
            //  - Not KILLED: There must be one which kill the killed
            //                job, and this loop stops after handling
            //                the first one
        }
    }

    // Assertion: All of them got SAT
    // for (pruning_thread_status const & s : statuses) {
    //     assert(s == pruning_thread_status::SAT);
    // }

    // DREAL_LOG_FATAL << "All of them are SAT";
    b = boxes[0];
    for (unsigned i = 0; i < m_vec.size(); i++) {
        contractor const & c = m_vec[i];
        b.intersect(boxes[i]);
        m_input.union_with(c.input());
        m_output.union_with(c.output());
        unordered_set<shared_ptr<constraint>> const & used_ctrs = c.used_constraints();
        m_used_constraints.insert(used_ctrs.begin(), used_ctrs.end());
        if (b.is_empty()) {
            // DREAL_LOG_FATAL << "Found an empty while intersecting...";
            for (unsigned i = 0; i < m_vec.size(); i++) {
                // if (threads[i].joinable()) {
                // DREAL_LOG_FATAL << "Try to join " << i << "...";
                threads[i].join();
                // DREAL_LOG_FATAL << "Try to join " << i << "... done";
                // }
            }
            // DREAL_LOG_FATAL << "parallel: return UNSAT";
            return;
        }
    }
    // DREAL_LOG_FATAL << "Intersection is nonempty exiting...";
    for (unsigned i = 0; i < m_vec.size(); i++) {
        // if (threads[i].joinable()) {
        threads[i].join();
        // }
    }
    // DREAL_LOG_FATAL << "parallel: return SAT";
    return;
}
示例#4
0
void contractor_gsl::prune(box & b, SMTConfig & config) {
    // TODO(soonhok): add timeout
    fesetround(FE_TONEAREST);  // Without this, GSL might cause a segmentation fault due to problems in floating point lib
    gsl_odeiv2_step_reset(m_step);
    gsl_odeiv2_evolve_reset(m_evolve);

    double const T_lb = b[m_time_t].lb();
    double const T_ub = b[m_time_t].ub();
    double t = 0.0, old_t = 0.0;                  /* initialize t */
    double T_next = 0.0;
    double h = 1e-10;              /* starting step size for ode solver */
    DREAL_LOG_INFO << "GSL: prune begin "
                   << m_time_t << " = ["
                   << T_lb << ", " << T_ub << "]"
                   << "\t" << b.max_diam();
    DREAL_LOG_INFO << m_ctr->get_ic();

    if (b.max_diam() < config.nra_precision) {
        return;
    }
    bool need_to_run = false;
    for (Enode * e : m_vars_0) {
        if (b[e].diam() > config.nra_precision) {
            need_to_run = true;
            break;
        }
    }
    if (b[m_time_t].diam() > config.nra_precision) {
        need_to_run = true;
    }
    if (!need_to_run) { return; }

    extract_sample_point(b, m_vars_0, m_values);
    extract_sample_point(b, m_pars_0, m_params);
    for (unsigned i = 0; i < m_vars_0.size(); i++) {
        b[m_vars_0[i]] = m_values[i];
    }
    for (unsigned i = 0; i < m_pars_0.size(); i++) {
        b[m_pars_0[i]] = m_params[i];
    }

    // First move to T_lb without checking m_values
    while (t < T_lb) {
        interruption_point();
        T_next = T_lb;
        // T_next = min(t + config.nra_precision, T_lb);
        int status = gsl_odeiv2_evolve_apply(m_evolve, m_control, m_step,
                                             &m_system,
                                             &t, T_next,
                                             &h, m_values);
        if (status != GSL_SUCCESS) {
            DREAL_LOG_INFO << "GSL: error, return value " << status;
            throw contractor_exception("GSL FAILED");
        }
    }

    // Now we're in the range in [T_lb, T_ub], need to check m_values.
    while (t < T_ub) {
        interruption_point();
        T_next = min(t + config.nra_precision, T_ub);
        // T_next = T_ub;

        // Copy m_values to m_old_values, and t to old_t
        for (unsigned i = 0; i < m_dim; i++) {
            m_old_values[i] = m_values[i];
        }
        old_t = t;
        int status = gsl_odeiv2_evolve_apply(m_evolve, m_control, m_step,
                                             &m_system,
                                             &t, T_next,
                                             &h, m_values);
        if (status != GSL_SUCCESS) {
            DREAL_LOG_INFO << "GSL: error, return value " << status;
            throw contractor_exception("GSL FAILED");
        }

        // print_values(t, m_values, m_dim);         /* print at t */
        bool values_good = true;
        unsigned i = 0;
        for (Enode * e : m_vars_t) {
            double const old_v_i = m_old_values[i];
            double const v_i = m_values[i];
            auto iv = (old_v_i < v_i) ? ibex::Interval(old_v_i, v_i) : ibex::Interval(v_i, old_v_i);
            auto const & iv_X_t = b[e];
            iv &= iv_X_t;
            if (iv.is_empty()) {
                values_good = false;
                DREAL_LOG_INFO << "GSL Not in Range: " << e
                                << " : " << m_values[i] << " not in " << b[e] << " at t = " << t;
                break;
            }
            i++;
        }
        if (values_good) {
            thread_local static box old_box(b);
            old_box = b;
            // Update X_t with m_values
            i = 0;
            for (Enode * e : m_vars_t) {
                double const old_v_i = m_old_values[i];
                double const v_i = m_values[i];
                auto iv = (old_v_i < v_i) ? ibex::Interval(old_v_i, v_i) : ibex::Interval(v_i, old_v_i);
                auto const & iv_X_t = b[e];
                iv &= iv_X_t;
                DREAL_LOG_INFO << "GSL Update: " << e
                                << " : " << b[e] << " ==> " << iv;
                b[e] = iv;
                i++;
            }
            // Update Time with T
            double const new_t = t/2.0 + old_t/2.0;
            DREAL_LOG_INFO << "GSL Update: time: " << b[m_time_t] << " ==> " << new_t;
            b[m_time_t] = new_t;
            m_eval_ctc.prune(b, config);
            if (!b.is_empty()) {
                DREAL_LOG_INFO << "This box satisfies other non-linear constraints";
                return;
            } else {
                DREAL_LOG_INFO << "This box failed to satisfy other non-linear constraints";
                b = old_box;
            }
        }
    }
    DREAL_LOG_INFO << "GSL failed in the end";
    throw contractor_exception("GSL failed");
}