예제 #1
0
파일: profiler.cpp 프로젝트: fritzo/pomagma
void ProgramProfiler::log_stats(const std::map<const void *, size_t> &linenos) {
    std::unique_lock<std::mutex> lock(s_mutex);
    for (ProgramProfiler *instance : s_instances) {
        instance->unsafe_report();
    }

    std::vector<LogLine> log_lines;
    double total_sec = 0;
    for (auto &pair : s_stats) {
        size_t lineno = map_find(linenos, pair.first);
        Stat &stat = pair.second;
        log_lines.push_back({stat, lineno});
        total_sec += stat.time * 1e-6;
        stat.count = 0;
        stat.time = 0;
    }
    std::sort(log_lines.begin(), log_lines.end());

    POMAGMA_INFO("Profile of VirtualMachine programs:");
    POMAGMA_INFO(" Line       Calls Percent   Total sec Per call sec");
    POMAGMA_INFO("----- ----------- ------- ----------- ------------");
    for (const auto &line : log_lines) {
        double time_sec = line.stat.time * 1e-6;
        double percent = 100 * time_sec / total_sec;
        POMAGMA_INFO(std::fixed << std::setprecision(2) << std::setw(5)
                                << std::right << line.lineno << std::setw(12)
                                << std::right << line.stat.count << std::setw(8)
                                << std::right << percent << std::setw(12)
                                << time_sec << std::setw(10)
                                << (time_sec / line.stat.count));
    }
}
예제 #2
0
파일: theory.hpp 프로젝트: imclab/pomagma
 // FIXME HACK this depends on link order, dying if log has been destroyed
 ~CleanupProfiler ()
 {
     unsigned long task_count = s_counts.size();
     POMAGMA_INFO("Task Id\tCount\tElapsed sec");
     for (unsigned long i = 0; i < task_count; ++i) {
         POMAGMA_INFO(
             std::setw(4) << i <<
             std::setw(8) << s_counts[i].load() <<
             std::setw(16) << (s_elapsed[i].load() * 1e-6));
     }
 }
예제 #3
0
파일: simplify.cpp 프로젝트: imclab/pomagma
size_t batch_simplify(
        Structure & structure,
        const std::vector<std::string> & routes,
        const char * source_file,
        const char * destin_file)
{
    POMAGMA_INFO("simplifying expressions");
    POMAGMA_ASSERT(
        std::string(source_file) != std::string(destin_file),
        "source and destin cannot be the same");
    SimplifyParser parser(structure.signature(), routes);

    std::ofstream destin(destin_file);
    POMAGMA_ASSERT(destin, "failed to open " << destin_file);
    destin << "# expressions simplifed by pomagma\n";

    size_t line_count = 0;
    for (LineParser iter(source_file); iter.ok(); iter.next()) {
        const std::string & expression = * iter;
        POMAGMA_DEBUG("simplifying " << expression);

        // simplify relations like EQUAL I APP APP S K K
        parser.begin(expression);
        std::string type = parser.parse_token();
        SimplifyTerm lhs = parser.parse_term();
        SimplifyTerm rhs = parser.parse_term();
        parser.end();
        destin << type << " " << lhs.route << " " << rhs.route << "\n";

        ++line_count;
    }

    return line_count;
}
예제 #4
0
파일: carrier.cpp 프로젝트: pomagma/pomagma
void Carrier::validate () const
{
    UniqueLock lock(m_mutex);

    POMAGMA_INFO("Validating Carrier");

    m_support.validate();

    size_t actual_item_count = 0;
    size_t actual_rep_count = 0;
    for (Ob i = 1; i <= item_dim(); ++i) {
        Ob rep = m_reps[i].load();
        if (contains(i)) {
            POMAGMA_ASSERT(rep, "supported object has no rep: " << i);
            POMAGMA_ASSERT(rep <= i, "rep out of order: " << rep << "," << i);
            ++actual_item_count;
            if (rep == i) {
                ++actual_rep_count;
            }
        } else {
            POMAGMA_ASSERT(rep == 0, "unsupported object has rep: " << i);
        }
    }
    POMAGMA_ASSERT_EQ(item_count(), actual_item_count);
    POMAGMA_ASSERT_EQ(rep_count(), actual_rep_count);
}
예제 #5
0
파일: router.cpp 프로젝트: fritzo/pomagma
DenseSet Router::find_defined() const {
    POMAGMA_INFO("Finding defined obs");
    DenseSet defined(m_carrier.item_dim());
    DenseSet undefined(m_carrier.item_dim());
    undefined = m_carrier.support();

    bool changed = true;
    while (changed) {
        changed = false;

        POMAGMA_DEBUG("accumulating route probabilities");

        undefined -= defined;
        for (auto iter = undefined.iter(); iter.ok(); iter.next()) {
            Ob ob = *iter;
            if (defines(defined, ob)) {
                defined.insert(ob);
                changed = true;
                break;
            }
        }
    }

    return defined;
}
예제 #6
0
파일: server.cpp 프로젝트: imclab/pomagma
void Server::serve (const char * address)
{
    POMAGMA_INFO("Starting server");
    zmq::context_t context(1);
    zmq::socket_t socket(context, ZMQ_REP);
    socket.bind(address);

    while (true) {
        POMAGMA_DEBUG("waiting for request");
        zmq::message_t raw_request;
        socket.recv(& raw_request);

        POMAGMA_DEBUG("parsing request");
        messaging::AnalystRequest request;
        request.ParseFromArray(raw_request.data(), raw_request.size());

        messaging::AnalystResponse response = handle(* this, request);

        POMAGMA_DEBUG("serializing response");
        std::string response_str;
        response.SerializeToString(& response_str);
        const size_t size = response_str.length();
        zmq::message_t raw_response(size);
        memcpy(raw_response.data(), response_str.c_str(), size);

        POMAGMA_DEBUG("sending response");
        socket.send(raw_response);
    }
}
예제 #7
0
size_t Approximator::test_less() {
    POMAGMA_INFO("Testing LESS closure");

    size_t fail_count = 0;

    const size_t item_dim = m_item_dim;
#pragma omp parallel
    {
        Approximation actual(item_dim, m_top, m_bot);
        DenseSet temp_set(m_item_dim);

#pragma omp for schedule(dynamic, 1)
        for (Ob x = 1; x <= item_dim; ++x) {
            Approximation expected(x, m_less);
            actual = expected;
            close(actual, temp_set);

            if (actual != expected) {
#pragma omp atomic
                fail_count += 1;
            }
        }
    }

    if (fail_count) {
        POMAGMA_WARN("LESS failed " << fail_count << " cases");
    }

    return fail_count;
}
예제 #8
0
void SymmetricFunction::validate() const {
    POMAGMA_INFO("Validating SymmetricFunction");

    m_lines.validate();

    POMAGMA_DEBUG("validating line-value consistency");
    for (size_t i = 1; i <= item_dim(); ++i)
        for (size_t j = i; j <= item_dim(); ++j) {
            auto val_iter = m_values.find(assert_sorted_pair(i, j));

            if (not(support().contains(i) and support().contains(j))) {
                POMAGMA_ASSERT(val_iter == m_values.end(),
                               "found unsupported lhs, rhs: " << i << ',' << j);
            } else if (val_iter != m_values.end()) {
                POMAGMA_ASSERT(defined(i, j),
                               "found undefined value: " << i << ',' << j);
                Ob val = val_iter->second;
                POMAGMA_ASSERT(val, "found zero value: " << i << ',' << j);
                POMAGMA_ASSERT(support().contains(val),
                               "found unsupported value: " << i << ',' << j);
            } else {
                POMAGMA_ASSERT(not defined(i, j),
                               "found defined null value: " << i << ',' << j);
            }
        }
}
예제 #9
0
파일: router.cpp 프로젝트: fritzo/pomagma
std::vector<float> Router::measure_probs(float reltol) const {
    POMAGMA_INFO("Measuring ob probs");
    const size_t item_count = m_carrier.item_count();
    std::vector<float> probs(1 + item_count, 0);
    const float max_increase = 1.0 + reltol;

    bool changed = true;
    while (changed) {
        changed = false;

        POMAGMA_DEBUG("accumulating route probabilities");

        // The following three cannot be mixed: openmp, gcc, fork.
        // see http://bisqwit.iki.fi/story/howto/openmp/#OpenmpAndFork
        //# pragma omp parallel for schedule(dynamic, 1)
        for (size_t i = 0; i < item_count; ++i) {
            Ob ob = 1 + i;

            float prob = 0;
            for (const Segment& segment : iter_val(ob)) {
                prob += get_prob(segment, probs);
            }

            if (prob > probs[ob] * max_increase) {
                //#pragma omp atomic
                changed = true;
            }
            probs[ob] = prob;  // relaxed memory order
        }
    }

    return probs;
}
예제 #10
0
파일: router.cpp 프로젝트: fritzo/pomagma
void Router::update_probs(std::vector<float>& probs, float reltol) const {
    POMAGMA_INFO("Updating ob probs");
    const size_t item_count = m_carrier.item_count();
    POMAGMA_ASSERT_EQ(probs.size(), 1 + item_count);
    const float max_increase = 1.0 + reltol;

    bool changed = true;
    while (changed) {
        changed = false;

        POMAGMA_DEBUG("accumulating route probabilities");

#pragma omp parallel for schedule(dynamic, 1)
        for (size_t i = 0; i < item_count; ++i) {
            Ob ob = 1 + i;
            float& prob = probs[ob];

            float temp_prob = 0;
            for (const Segment& segment : iter_val(ob)) {
                temp_prob += get_prob(segment, probs);
            }

            if (temp_prob > prob * max_increase) {
                changed = true;
            }

            prob = temp_prob;
        }
    }
}
예제 #11
0
파일: syntax.cpp 프로젝트: fritzo/pomagma
void Structure::assert_valid() {
    POMAGMA_INFO("Validating solver::Structure");

    // Check atoms.
    POMAGMA_ASSERT(term_arity(TermAtom::TOP) == TermArity::TOP, "Missing TOP");
    POMAGMA_ASSERT(term_arity(TermAtom::BOT) == TermArity::BOT, "Missing BOT");
    POMAGMA_ASSERT(term_arity(TermAtom::I) == TermArity::I, "Missing I");
    POMAGMA_ASSERT(term_arity(TermAtom::K) == TermArity::K, "Missing K");
    POMAGMA_ASSERT(term_arity(TermAtom::B) == TermArity::B, "Missing B");
    POMAGMA_ASSERT(term_arity(TermAtom::C) == TermArity::C, "Missing C");
    POMAGMA_ASSERT(term_arity(TermAtom::S) == TermArity::S, "Missing S");

    // Check terms.
    const Term max_term = term_arity_.size() - 1;
    for (Term term = 1; term <= max_term; ++term) {
        const TermArity arity = term_arity(term);
        switch (arity) {
            case TermArity::IVAR: {
                const unsigned rank = ivar_arg(term);
                POMAGMA_ASSERT_EQ(term, ivar(rank));
                break;
            }
            case TermArity::NVAR: {
                const std::string& name = nvar_arg(term);
                POMAGMA_ASSERT_EQ(term, nvar(name));
                break;
            }
            case TermArity::APP: {
                Term lhs;
                Term rhs;
                std::tie(lhs, rhs) = app_arg(term);
                POMAGMA_ASSERT_EQ(term, app(lhs, rhs));
                break;
            }
            case TermArity::JOIN: {
                Term lhs;
                Term rhs;
                std::tie(lhs, rhs) = join_arg(term);
                POMAGMA_ASSERT_EQ(term, join(lhs, rhs));
                break;
            }
            default:
                break;
        }
    }

    // Check literals.
    const Literal max_lit = less_arg_.size() - 1;
    for (Literal lit = 1; lit <= max_lit; ++lit) {
        Term lhs;
        Term rhs;

        std::tie(lhs, rhs) = literal_arg(lit);
        POMAGMA_ASSERT_EQ(lit, less(lhs, rhs));

        std::tie(lhs, rhs) = literal_arg(-lit);
        POMAGMA_ASSERT_EQ(-lit, nless(lhs, rhs));
    }
}
예제 #12
0
파일: router.cpp 프로젝트: fritzo/pomagma
void Router::update_weights(
    const std::vector<float>& probs,
    const std::unordered_map<std::string, size_t>& symbol_counts,
    const std::unordered_map<Ob, size_t>& ob_counts,
    std::vector<float>& symbol_weights, std::vector<float>& ob_weights,
    float reltol) const {
    POMAGMA_INFO("Updating weights");
    const size_t symbol_count = m_types.size();
    const size_t ob_count = m_carrier.item_count();
    POMAGMA_ASSERT_EQ(probs.size(), 1 + ob_count);
    POMAGMA_ASSERT_EQ(symbol_weights.size(), symbol_count);
    POMAGMA_ASSERT_EQ(ob_weights.size(), 1 + ob_count);
    const float max_increase = 1.0 + reltol;

    std::vector<float> temp_symbol_weights(symbol_weights.size());
    std::vector<float> temp_ob_weights(ob_weights.size());

update_weights_loop : {
    POMAGMA_DEBUG("distributing route weight");

    std::fill(temp_symbol_weights.begin(), temp_symbol_weights.end(), 0);
    for (size_t i = 0; i < symbol_count; ++i) {
        temp_symbol_weights[i] = map_get(symbol_counts, m_types[i].name, 0);
    }

    std::fill(temp_ob_weights.begin(), temp_ob_weights.end(), 0);
    for (const auto& pair : ob_counts) {
        temp_ob_weights[pair.first] = pair.second;
    }

#pragma omp parallel for schedule(dynamic, 1)
    for (size_t i = 0; i < ob_count; ++i) {
        Ob ob = 1 + i;

        const float weight = ob_weights[ob] / probs[ob];
        for (const Segment& segment : iter_val(ob)) {
            float part = weight * get_prob(segment, probs);
            add_weight(part, segment, temp_symbol_weights, temp_ob_weights);
        }
    }

    std::swap(symbol_weights, temp_symbol_weights);
    std::swap(ob_weights, temp_ob_weights);

    for (size_t i = 0; i < symbol_count; ++i) {
        if (symbol_weights[i] > temp_symbol_weights[i] * max_increase) {
            goto update_weights_loop;
        }
    }

    for (size_t i = 0; i < ob_count; ++i) {
        Ob ob = 1 + i;
        if (ob_weights[ob] > temp_ob_weights[ob] * max_increase) {
            goto update_weights_loop;
        }
    }
}
}
예제 #13
0
파일: server.cpp 프로젝트: fritzo/pomagma
void Server::serve(const char* address) {
    void* context;
    void* socket;
    zmq_msg_t message;

    POMAGMA_INFO("Starting server");
    POMAGMA_ASSERT_C((context = zmq_ctx_new()));
    POMAGMA_ASSERT_C((socket = zmq_socket(context, ZMQ_REP)));
    POMAGMA_ASSERT_C(0 == zmq_bind(socket, address));

    for (m_serving = true; m_serving;) {
        POMAGMA_DEBUG("waiting for request");
        POMAGMA_ASSERT_C(0 == zmq_msg_init(&message));
        POMAGMA_ASSERT_C(-1 != zmq_msg_recv(&message, socket, 0));

        POMAGMA_DEBUG("parsing request");
        protobuf::CartographerRequest request;
        bool parsed = request.ParseFromArray(zmq_msg_data(&message),
                                             zmq_msg_size(&message));
        POMAGMA_ASSERT(parsed, "Failed to parse request");
        POMAGMA_ASSERT_C(0 == zmq_msg_close(&message));

        protobuf::CartographerResponse response = handle(*this, request);

        POMAGMA_DEBUG("serializing response");
        std::string response_str;
        response.SerializeToString(&response_str);
        const int size = response_str.length();
        POMAGMA_ASSERT_C(0 == zmq_msg_init(&message));
        POMAGMA_ASSERT_C(0 == zmq_msg_init_size(&message, size));
        memcpy(zmq_msg_data(&message), response_str.c_str(), size);

        POMAGMA_DEBUG("sending response");
        POMAGMA_ASSERT_C(size == zmq_msg_send(&message, socket, 0));
        POMAGMA_ASSERT_C(0 == zmq_msg_close(&message));
    }

    POMAGMA_INFO("stopping server");
    int linger_ms = 0;
    POMAGMA_ASSERT_C(
        0 == zmq_setsockopt(socket, ZMQ_LINGER, &linger_ms, sizeof(linger_ms)));
    POMAGMA_ASSERT_C(0 == zmq_close(socket));
    POMAGMA_ASSERT_C(0 == zmq_ctx_destroy(context));
}
예제 #14
0
void NullaryFunction::validate () const
{
    SharedLock lock(m_mutex);

    POMAGMA_INFO("Validating NullaryFunction");

    Ob value = m_value;
    if (value) {
        POMAGMA_ASSERT(support().contains(value),
                "unsupported value: " << value);
    }
}
예제 #15
0
size_t Approximator::test() {
    POMAGMA_INFO("Testing approximator");

    size_t fail_count = 0;

    fail_count += test_less();
    for (auto pair : m_structure.signature().binary_functions()) {
        fail_count += test_function(pair.first, *pair.second);
    }
    for (auto pair : m_structure.signature().symmetric_functions()) {
        fail_count += test_function(pair.first, *pair.second);
    }

    if (fail_count) {
        POMAGMA_WARN("Failed approximator test");
    } else {
        POMAGMA_INFO("Passed approximator test");
    }

    return fail_count;
}
예제 #16
0
파일: theory.hpp 프로젝트: imclab/pomagma
void insert_nullary_functions ()
{
    const auto & functions = signature.nullary_functions();
    POMAGMA_INFO("Inserting " << functions.size() << " nullary functions");

    for (auto pair : functions) {
        NullaryFunction * fun = pair.second;
        if (not fun->find()) {
            Ob val = carrier.try_insert();
            POMAGMA_ASSERT(val, "no space to insert nullary functions");
            fun->insert(val);
        }
    }
}
예제 #17
0
void BinaryRelation::validate_disjoint(const BinaryRelation& other) const {
    POMAGMA_INFO("Validating disjoint pair of BinaryRelations");

    // validate supports agree
    POMAGMA_ASSERT_EQ(support().item_dim(), other.support().item_dim());
    POMAGMA_ASSERT_EQ(support().count_items(), other.support().count_items());
    POMAGMA_ASSERT(support() == other.support(),
                   "BinaryRelation supports differ");

    // validate disjointness
    DenseSet this_set(item_dim(), nullptr);
    DenseSet other_set(item_dim(), nullptr);
    for (auto i = support().iter(); i.ok(); i.next()) {
        this_set.init(m_lines.Lx(*i));
        other_set.init(other.m_lines.Lx(*i));
        POMAGMA_ASSERT(this_set.disjoint(other_set),
                       "BinaryRelations intersect at row " << *i);
    }
}
예제 #18
0
void test_merge (Carrier & carrier, rng_t & rng)
{
    POMAGMA_INFO("Checking unsafe_merge");
    const DenseSet & support = carrier.support();
    size_t merge_count = 0;
    g_merge_count = 0;
    std::bernoulli_distribution randomly_merge(0.1);
    for (auto rep_iter = support.iter(); rep_iter.ok(); rep_iter.next())
    for (auto dep_iter = support.iter(); dep_iter.ok(); dep_iter.next()) {
        Ob dep = carrier.find(*dep_iter);
        Ob rep = carrier.find(*rep_iter);
        if ((rep < dep) and randomly_merge(rng)) {
            carrier.merge(dep, rep);
            ++merge_count;
            break;
        }
    }
    POMAGMA_ASSERT_EQ(merge_count, g_merge_count);
}
예제 #19
0
void remove_deps (Carrier & carrier, Function & fun)
{
    POMAGMA_INFO("Merging deps");
    const DenseSet & support = carrier.support();
    bool merged;
    do {
        merged = false;
        for (auto iter = support.iter(); iter.ok(); iter.next()) {
            Ob dep = *iter;
            if (carrier.find(dep) != dep) {
                fun.unsafe_merge(dep);
                carrier.unsafe_remove(dep);
                merged = true;
            }
        }
    } while (merged);
    fun.update_values();
    POMAGMA_ASSERT_EQ(carrier.rep_count(), carrier.item_count());
    fun.validate();
}
예제 #20
0
파일: syntax.cpp 프로젝트: fritzo/pomagma
Structure::Structure() {
    POMAGMA_INFO("Initializing solver::Structure");

    // Initialize vectors for 1-based indexing.
    term_arity_.resize(1);
    less_arg_.resize(1);

    // Initialize atoms.
    new_term(TermArity::TOP);
    new_term(TermArity::BOT);
    new_term(TermArity::I);
    new_term(TermArity::K);
    new_term(TermArity::B);
    new_term(TermArity::C);
    new_term(TermArity::S);

    if (POMAGMA_DEBUG_LEVEL) {
        assert_valid();
    }
}
예제 #21
0
void BinaryRelation::validate () const
{
    POMAGMA_INFO("Validating BinaryRelation");

    m_lines.validate();

    size_t num_pairs = 0;

    DenseSet Lx(round_item_dim(), nullptr);
    DenseSet Rx(round_item_dim(), nullptr);
    for (Ob i = 1; i <= item_dim(); ++i) {
        bool sup_i = supports(i);
        Lx.init(m_lines.Lx(i));

        for (Ob j = 1; j <= item_dim(); ++j) {
            bool sup_ij = sup_i and supports(j);
            Rx.init(m_lines.Rx(j));

            bool Lx_ij = Lx.contains(j);
            bool Rx_ij = Rx.contains(i);
            num_pairs += Rx_ij;

            POMAGMA_ASSERT(Lx_ij == Rx_ij,
                    "Lx,Rx disagree at " << i << "," << j
                    << ", Lx is " << Lx_ij << ", Rx is " << Rx_ij  );

            POMAGMA_ASSERT(sup_ij or not Lx_ij,
                    "Lx unsupported at " << i << "," << j );

            POMAGMA_ASSERT(sup_ij or not Rx_ij,
                    "Rx unsupported at " << i << "," << j );
        }
    }

    size_t true_size = count_pairs();
    POMAGMA_ASSERT(num_pairs == true_size,
            "incorrect number of pairs: "
            << num_pairs << " should be " << true_size);
}
예제 #22
0
파일: router.cpp 프로젝트: fritzo/pomagma
void Router::fit_language(
    const std::unordered_map<std::string, size_t>& symbol_counts,
    const std::unordered_map<Ob, size_t>& ob_counts, float reltol) {
    POMAGMA_INFO("Fitting language");
    const size_t item_count = m_carrier.item_count();
    std::vector<float> ob_probs(1 + item_count, 0);
    std::vector<float> ob_weights(1 + item_count, 0);
    std::vector<float> symbol_weights(m_types.size(), 0);
    POMAGMA_ASSERT_EQ(m_types.size(), m_language.size());
    const float max_increase = 1.0 + reltol;

    bool changed = true;
    while (changed) {
        changed = false;

        update_probs(ob_probs, reltol);

        update_weights(ob_probs, symbol_counts, ob_counts, symbol_weights,
                       ob_weights, reltol);

        POMAGMA_DEBUG("optimizing language");
        float total_weight = 0;
        for (float weight : symbol_weights) {
            total_weight += weight;
        }
        for (size_t i = 0; i < m_types.size(); ++i) {
            SegmentType& type = m_types[i];
            float new_prob = symbol_weights[i] / total_weight;
            float old_prob = type.prob;
            type.prob = new_prob;
            m_language[type.name] = new_prob;

            if (new_prob > old_prob * max_increase) {
                changed = true;
            }
        }
    }
}
예제 #23
0
파일: server.cpp 프로젝트: fritzo/pomagma
void Server::serve(const char* address) {
    void* context;
    void* socket;
    zmq_msg_t message;

    POMAGMA_INFO("Starting server");
    POMAGMA_ASSERT_C((context = zmq_ctx_new()));
    POMAGMA_ASSERT_C((socket = zmq_socket(context, ZMQ_REP)));
    POMAGMA_ASSERT_C(0 == zmq_bind(socket, address));

    while (true) {
        POMAGMA_DEBUG("waiting for request");
        POMAGMA_ASSERT_C(0 == zmq_msg_init(&message));
        POMAGMA_ASSERT_C(-1 != zmq_msg_recv(&message, socket, 0));

        POMAGMA_DEBUG("parsing request");
        protobuf::AnalystRequest request;
        bool parsed = request.ParseFromArray(zmq_msg_data(&message),
                                             zmq_msg_size(&message));
        POMAGMA_ASSERT(parsed, "Failed to parse request");
        POMAGMA_ASSERT_C(0 == zmq_msg_close(&message));

        protobuf::AnalystResponse response = handle(*this, request);

        POMAGMA_DEBUG("serializing response");
        std::string response_str;
        response.SerializeToString(&response_str);
        const int size = response_str.length();
        POMAGMA_ASSERT_C(0 == zmq_msg_init(&message));
        POMAGMA_ASSERT_C(0 == zmq_msg_init_size(&message, size));
        memcpy(zmq_msg_data(&message), response_str.c_str(), size);

        POMAGMA_DEBUG("sending response");
        POMAGMA_ASSERT_C(size == zmq_msg_send(&message, socket, 0));
        POMAGMA_ASSERT_C(0 == zmq_msg_close(&message));
    }
}
예제 #24
0
std::vector<Ob> conjecture_diverge(Structure& structure,
                                   const std::vector<float>& probs,
                                   const std::vector<std::string>& routes,
                                   const char* conjectures_file) {
    POMAGMA_INFO("Conjecturing divergent terms");
    const Carrier& carrier = structure.carrier();
    const BinaryRelation& NLESS = structure.binary_relation("NLESS");
    const Ob BOT = structure.nullary_function("BOT").find();
    const Ob TOP = structure.nullary_function("TOP").find();

    POMAGMA_DEBUG("collecting conjectures");
    DenseSet conjecture_set(carrier.item_count());
    conjecture_set.set_diff(carrier.support(), NLESS.get_Rx_set(BOT));
    POMAGMA_ASSERT(conjecture_set.contains(BOT), "BOT not conjectured");
    POMAGMA_ASSERT(not conjecture_set.contains(TOP), "TOP conjectured");
    conjecture_set.remove(BOT);
    std::vector<Ob> conjectures;
    for (auto iter = conjecture_set.iter(); iter.ok(); iter.next()) {
        Ob ob = *iter;
        conjectures.push_back(ob);
    }

    POMAGMA_DEBUG("sorting " << conjectures.size() << " conjectures");
    std::sort(conjectures.begin(), conjectures.end(),
              [&](const Ob& x, const Ob& y) { return probs[x] > probs[y]; });

    POMAGMA_DEBUG("writing conjectures to " << conjectures_file);
    std::ofstream file(conjectures_file, std::ios::out | std::ios::trunc);
    POMAGMA_ASSERT(file, "failed to open " << conjectures_file);
    file << "# divergence conjectures generated by pomagma";
    for (auto ob : conjectures) {
        file << "\nEQUAL BOT " << routes[ob];
    }

    return conjectures;
}
예제 #25
0
void NullaryFunction::log_stats (const std::string & prefix) const
{
    if (not m_value.load()) {
        POMAGMA_INFO(prefix << " undefined");
    }
}
예제 #26
0
size_t Approximator::test_function(const std::string& name,
                                   const Function& fun) {
    POMAGMA_INFO("Testing " << name << " approximation");

    size_t ob_fail_count = 0;
    size_t upper_fail_count = 0;
    size_t upper_extra_count = 0;
    size_t upper_missing_count = 0;
    size_t lower_fail_count = 0;
    size_t lower_extra_count = 0;
    size_t lower_missing_count = 0;

    const size_t item_dim = m_item_dim;
#pragma omp parallel
    {
        DenseSet temp_set(item_dim);

#pragma omp for schedule(dynamic, 1)
        for (Ob x = 1; x <= item_dim; ++x) {
            Approximation approx_x(x, m_less);
            approx_x.ob = 0;

            for (auto iter = fun.iter_lhs(x); iter.ok(); iter.next()) {
                Ob y = *iter;
                Approximation approx_y(y, m_less);
                approx_y.ob = 0;

                Ob xy = fun.find(x, y);
                Approximation expected(xy, m_less);
                Approximation actual = find(fun, approx_x, approx_y);

                if (actual.ob != expected.ob) {
#pragma omp atomic
                    ob_fail_count += 1;
                }
                if (actual.upper != expected.upper) {
#pragma omp atomic
                    upper_fail_count += 1;
                    temp_set.set_diff(actual.upper, expected.upper);
                    if (size_t count = temp_set.count_items()) {
#pragma omp atomic
                        upper_extra_count += count;
                    }
                    temp_set.set_diff(expected.upper, actual.upper);
                    if (size_t count = temp_set.count_items()) {
#pragma omp atomic
                        upper_missing_count += count;
                    }
                }
                if (actual.lower != expected.lower) {
#pragma omp atomic
                    lower_fail_count += 1;
                    temp_set.set_diff(actual.lower, expected.lower);
                    if (size_t count = temp_set.count_items()) {
#pragma omp atomic
                        lower_extra_count += count;
                    }
                    temp_set.set_diff(expected.lower, actual.lower);
                    if (size_t count = temp_set.count_items()) {
#pragma omp atomic
                        lower_missing_count += count;
                    }
                }
            }
        }
    }

    if (ob_fail_count) {
        POMAGMA_WARN(name << " ob failed " << ob_fail_count << " cases");
    }
    if (upper_missing_count or upper_extra_count) {
        POMAGMA_WARN(name << " upper has " << upper_missing_count
                          << " missing and " << upper_extra_count
                          << " extra obs in " << upper_fail_count << " cases");
    }
    if (lower_missing_count or lower_extra_count) {
        POMAGMA_WARN(name << " lower has " << lower_missing_count
                          << " missing and " << lower_extra_count
                          << " extra obs in " << lower_fail_count << " cases");
    }

    return ob_fail_count + upper_fail_count + lower_fail_count;
}
예제 #27
0
파일: server.cpp 프로젝트: fritzo/pomagma
static protobuf::CartographerResponse handle(
    Server& server, protobuf::CartographerRequest& request) {
    POMAGMA_INFO("Handling request");
    Timer timer;
    protobuf::CartographerResponse response;

    if (request.has_crop()) {
        server.crop(request.crop().headroom());
        response.mutable_crop();
    }

    if (request.has_declare()) {
        for (const auto& name : request.declare().nullary_functions()) {
            server.declare(name);
        }
        response.mutable_declare();
    }

    if (request.has_assume()) {
        const std::string& facts_in = request.assume().facts_in();
        auto counts = server.assume(facts_in);
        response.mutable_assume()->set_pos_count(counts["pos"]);
        response.mutable_assume()->set_neg_count(counts["neg"]);
        response.mutable_assume()->set_merge_count(counts["merge"]);
        response.mutable_assume()->set_ignored_count(counts["ignored"]);
    }

    if (request.has_infer()) {
        const size_t priority = request.infer().priority();
        const size_t theorem_count = server.infer(priority);
        response.mutable_infer()->set_theorem_count(theorem_count);
    }

    if (request.has_execute()) {
        server.execute(request.execute().program());
        response.mutable_execute();
    }

    if (request.has_aggregate()) {
        server.aggregate(request.aggregate().survey_in());
        response.mutable_aggregate();
    }

    if (request.has_validate()) {
        server.validate();
        response.mutable_validate();
    }

    if (request.has_info()) {
        const auto info = server.info();
        response.mutable_info()->set_item_count(info.item_count);
    }

    if (request.has_dump()) {
        server.dump(request.dump().world_out());
        response.mutable_dump();
    }

    if (request.trim_size() > 0) {
        std::vector<Server::TrimTask> tasks(request.trim_size());
        for (int i = 0; i < request.trim_size(); ++i) {
            const auto& task = request.trim(i);
            tasks[i].size = task.size();
            tasks[i].temperature = task.temperature();
            tasks[i].filename = task.filename();
            response.add_trim();
        }
        server.trim(tasks);
    }

    if (request.has_conjecture()) {
        const std::string& diverge_out = request.conjecture().diverge_out();
        const std::string& equal_out = request.conjecture().equal_out();
        const size_t max_count = request.conjecture().max_count();
        auto counts = server.conjecture(diverge_out, equal_out, max_count);
        response.mutable_conjecture()->set_diverge_count(counts["diverge"]);
        response.mutable_conjecture()->set_equal_count(counts["equal"]);
    }

    if (request.has_stop()) {
        server.stop();
        response.mutable_stop();
    }

    POMAGMA_INFO("Handled request in " << timer.elapsed() << " sec");
    return response;
}
예제 #28
0
파일: server.cpp 프로젝트: fritzo/pomagma
static protobuf::AnalystResponse handle(Server& server,
                                        protobuf::AnalystRequest& request) {
    POMAGMA_INFO("Handling request");
    protobuf::AnalystResponse response;
    typedef protobuf::AnalystResponse::Trool Trool;

    if (request.has_id()) {
        response.set_id(request.id());
    }

    if (request.has_test_inference()) {
        size_t fail_count = server.test_inference();
        response.mutable_test_inference()->set_fail_count(fail_count);
    }

    if (request.has_simplify()) {
        size_t code_count = request.simplify().codes_size();
        for (size_t i = 0; i < code_count; ++i) {
            const std::string& code = request.simplify().codes(i);
            std::string result = server.simplify(code);
            response.mutable_simplify()->add_codes(result);
        }
    }

    if (request.has_validate()) {
        size_t code_count = request.validate().codes_size();
        for (size_t i = 0; i < code_count; ++i) {
            const std::string& code = request.validate().codes(i);
            auto validity = server.validate(code);
            auto& result = *response.mutable_validate()->add_results();
            result.set_is_top(static_cast<Trool>(validity.is_top));
            result.set_is_bot(static_cast<Trool>(validity.is_bot));
            result.set_pending(false);
        }
    }

    if (request.has_validate_corpus()) {
        size_t line_count = request.validate_corpus().lines_size();
        std::vector<Corpus::LineOf<std::string>> lines(line_count);
        for (size_t i = 0; i < line_count; ++i) {
            const auto& line = request.validate_corpus().lines(i);
            if (line.has_name()) {
                lines[i].maybe_name = line.name();
            }
            lines[i].body = line.code();
        }
        const auto validities = server.validate_corpus(lines);
        auto& responses = *response.mutable_validate_corpus();
        for (const auto& pair : validities) {
            auto& result = *responses.add_results();
            result.set_is_top(static_cast<Trool>(pair.validity.is_top));
            result.set_is_bot(static_cast<Trool>(pair.validity.is_bot));
            result.set_pending(pair.pending);
        }
    }

    if (request.has_get_histogram()) {
        const Corpus::Histogram& histogram = server.get_histogram();
        auto& response_histogram =
            *response.mutable_get_histogram()->mutable_histogram();
        for (const auto& pair : histogram.obs) {
            auto& term = *response_histogram.add_terms();
            term.set_ob(pair.first);
            term.set_count(pair.second);
        }
        for (const auto& pair : histogram.symbols) {
            auto& term = *response_histogram.add_terms();
            term.set_name(pair.first);
            term.set_count(pair.second);
        }
    }

    if (request.has_fit_language()) {
        std::unordered_map<std::string, float> language;
        if (request.fit_language().has_histogram()) {
            Corpus::Histogram histogram;
            const auto& request_histogram = request.fit_language().histogram();
            size_t terms_size = request_histogram.terms_size();
            for (size_t i = 0; i < terms_size; ++i) {
                const auto& term = request_histogram.terms(i);
                if (term.has_ob()) {
                    histogram.obs[term.ob()] = term.count();
                } else {
                    histogram.symbols[term.name()] = term.count();
                }
            }
            language = server.fit_language(histogram);
        } else {
            language = server.fit_language(server.get_histogram());
        }
        auto& response_fit_language = *response.mutable_fit_language();
        for (const auto& pair : language) {
            auto& symbol = *response_fit_language.add_symbols();
            symbol.set_name(pair.first);
            symbol.set_prob(pair.second);
        }
    }

    if (request.has_solve()) {
        size_t max_solutions = std::numeric_limits<size_t>::max();
        if (request.solve().has_max_solutions()) {
            max_solutions = request.solve().max_solutions();
        }
        if (max_solutions > 0) {
            Server::SolutionSet solutions =
                server.solve(request.solve().program(), max_solutions);
            auto& response_solve = *response.mutable_solve();
            for (const auto& solution : solutions.necessary) {
                response_solve.add_necessary(solution);
            }
            for (const auto& solution : solutions.possible) {
                response_solve.add_possible(solution);
            }
        } else {
            response.add_error_log(
                "expected request.solve.max_solutions > 0; actual 0");
        }
    }

    if (request.has_validate_facts()) {
        const auto& facts = request.validate_facts().facts();
        const std::vector<std::string> polish_facts(facts.begin(), facts.end());
        const auto result = server.validate_facts(polish_facts);
        response.mutable_validate_facts()->set_result(
            static_cast<Trool>(result));
    }

    for (const std::string& message : server.flush_errors()) {
        response.add_error_log(message);
    }

    return response;
}
예제 #29
0
파일: router.cpp 프로젝트: fritzo/pomagma
std::vector<std::string> Router::find_routes() const {
    POMAGMA_INFO("Routing all obs");

    const size_t item_count = m_carrier.item_count();
    std::vector<float> best_probs(1 + item_count, 0);
    std::vector<Segment> best_segments(1 + item_count);

    bool changed = true;
    while (changed) {
        changed = false;

        POMAGMA_DEBUG("finding best local routes");

        //#pragma omp parallel for schedule(dynamic, 1)
        for (size_t i = 0; i < item_count; ++i) {
            Ob ob = 1 + i;

            float& best_prob = best_probs[ob];
            Segment& best_segment = best_segments[ob];
            bool best_changed = false;
            for (const Segment& segment : iter_val(ob)) {
                float prob = get_prob(segment, best_probs);
                if (unlikely(std::make_pair(-prob, segment) <
                             std::make_pair(-best_prob, best_segment))) {
                    best_prob = prob;        // relaxed memory order
                    best_segment = segment;  // relaxed memory order
                    best_changed = true;
                }
            }

            if (best_changed) {
                //#pragma omp atomic
                changed = true;
            }
        }
    }

    POMAGMA_DEBUG("scheduling route building");
    std::vector<Ob> schedule;
    schedule.reserve(item_count);
    for (auto iter = m_carrier.iter(); iter.ok(); iter.next()) {
        Ob ob = *iter;
        POMAGMA_ASSERT_LT(0, best_probs[ob]);
        schedule.push_back(ob);
    }
    std::sort(schedule.begin(), schedule.end(), [&](const Ob& x, const Ob& y) {
        return best_probs[x] > best_probs[y];
    });

    POMAGMA_DEBUG("building full routes");
    std::vector<std::string> routes(1 + item_count);
    for (Ob ob : schedule) {
        const Segment& segment = best_segments[ob];
        const SegmentType& type = m_types[segment.type];
        switch (type.arity) {
            case NULLARY: {
                routes[ob] = type.name;
            } break;

            case UNARY: {
                const auto& arg = routes[segment.arg1];
                POMAGMA_ASSERT(not arg.empty(), "unknown arg route");
                routes[ob] = type.name + " " + arg;
            } break;

            case BINARY: {
                const auto& lhs = routes[segment.arg1];
                const auto& rhs = routes[segment.arg2];
                POMAGMA_ASSERT(not lhs.empty(), "unknown lhs route");
                POMAGMA_ASSERT(not rhs.empty(), "unknown rhs route");
                routes[ob] = type.name + " " + lhs + " " + rhs;
            } break;
        }
    }

    return routes;
}
예제 #30
0
파일: router.cpp 프로젝트: fritzo/pomagma
Router::Router(const Signature& signature,
               const std::unordered_map<std::string, float>& language)
    : m_carrier(*signature.carrier()),
      m_language(language),
      m_value_index(signature.carrier()->item_count()) {
    POMAGMA_INFO("Building router indices");

    for (auto pair : signature.nullary_functions()) {
        const auto& name = pair.first;
        const auto& fun = *pair.second;
        if (m_language.find(name) != m_language.end()) {
            const TypeId type = new_type(NULLARY, name);
            if (Ob val = fun.find()) {
                m_segments.push_back(Segment(type, val));
            }
        }
    }

    for (auto pair : signature.injective_functions()) {
        const auto& name = pair.first;
        const auto& fun = *pair.second;
        if (m_language.find(name) != m_language.end()) {
            const TypeId type = new_type(UNARY, name);
            for (auto iter = fun.iter(); iter.ok(); iter.next()) {
                Ob arg = *iter;
                Ob val = fun.find(arg);
                m_segments.push_back(Segment(type, val, arg));
            }
        }
    }

    for (auto pair : signature.binary_functions()) {
        const auto& name = pair.first;
        const auto& fun = *pair.second;
        if (m_language.find(name) != m_language.end()) {
            const TypeId type = new_type(BINARY, name);
            for (auto iter = m_carrier.iter(); iter.ok(); iter.next()) {
                Ob lhs = *iter;
                for (auto iter = fun.iter_lhs(lhs); iter.ok(); iter.next()) {
                    Ob rhs = *iter;
                    Ob val = fun.find(lhs, rhs);
                    m_segments.push_back(Segment(type, val, lhs, rhs));
                }
            }
        }
    }

    for (auto pair : signature.symmetric_functions()) {
        const auto& name = pair.first;
        const auto& fun = *pair.second;
        if (m_language.find(name) != m_language.end()) {
            const TypeId type = new_type(BINARY, name);
            for (auto iter = m_carrier.iter(); iter.ok(); iter.next()) {
                Ob lhs = *iter;
                for (auto iter = fun.iter_lhs(lhs); iter.ok(); iter.next()) {
                    Ob rhs = *iter;
                    Ob val = fun.find(lhs, rhs);
                    m_segments.push_back(Segment(type, val, lhs, rhs));
                }
            }
        }
    }

    std::sort(m_segments.begin(), m_segments.end());

    // assume all values are reached by at least one segment
    m_value_index.resize(1 + m_carrier.item_count(), 0);
    for (size_t i = 0; i < m_segments.size(); ++i) {
        m_value_index[m_segments[i].val] = i;
    }
}