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); }
//validation template<class X> void splay_forest<X>::test_find (Pos eqn) { //test find_pair Pos pos = find_pair(get_root(eqn), get_key(eqn), get_val(eqn)); POMAGMA_ASSERT(pos, "invalid: eqn not found in own " << nameof<X>() << " tree"); POMAGMA_ASSERT(pos == eqn, "invalid: wrong eqn found in own " << nameof<X>() << " tree"); //test find_key pos = find_key(get_root(eqn), get_key(eqn)); POMAGMA_ASSERT(pos, "invalid: key not found in own " << nameof<X>() << " tree"); POMAGMA_ASSERT(get_key(pos) == get_key(eqn), "invalid: wrong key found in own " << nameof<X>() << " tree"); }
Approximator::Approximator(Structure& structure) : m_structure(structure), m_item_dim(structure.carrier().item_dim()), m_top(structure.nullary_function("TOP").find()), m_bot(structure.nullary_function("BOT").find()), m_identity(structure.nullary_function("I").find()), m_less(structure.binary_relation("LESS")), m_nless(structure.binary_relation("NLESS")), m_join(structure.signature().symmetric_function("JOIN")), m_rand(structure.signature().symmetric_function("RAND")), m_quote(structure.signature().injective_function("QUOTE")) { POMAGMA_ASSERT(m_top, "TOP is not defined"); POMAGMA_ASSERT(m_bot, "BOT is not defined"); POMAGMA_ASSERT(m_identity, "I is not defined"); }
inline T * replace (T * & pointer, T * new_value) { POMAGMA_ASSERT(pointer != nullptr, "nothing to replace"); T * old_value = pointer; pointer = new_value; return old_value; }
void unlock () { bool expected = true; POMAGMA_ASSERT(m_flag.compare_exchange_strong(expected, false), "unlock contention"); store_barrier(); }
Server::SolutionSet Server::solve(const std::string& program, size_t max_solutions) { std::istringstream infile(program); auto listings = m_parser.parse(infile); POMAGMA_ASSERT_LE(1, listings.size()); m_return.clear(); m_nreturn.clear(); for (const auto& listing : listings) { vm::Program program = m_parser.find_program(listing); m_virtual_machine.execute(program); } POMAGMA_ASSERT(m_return.get_set().disjoint(m_nreturn.get_set()), "inconsistent query result; check programs:\n" << program); SolutionSet solutions; print_ob_set(m_return.get_set(), solutions.necessary, max_solutions); POMAGMA_ASSERT_LE(solutions.necessary.size(), max_solutions); max_solutions -= solutions.necessary.size(); if (max_solutions > 0) { // TODO only execute NRETURN programs if needed DenseSet possible(m_structure.carrier().item_dim()); possible.set_pnn(m_structure.carrier().support(), m_return.get_set(), m_nreturn.get_set()); print_ob_set(possible, solutions.possible, max_solutions); } return solutions; }
inline void tempfile_dump (pid_t pid, const T & t) { std::string filename = tempfile_name(pid); std::ofstream file(filename.c_str(), std::ios::out | std::ios::trunc); POMAGMA_ASSERT(file, "failed to open tempfile " << filename); file << t << std::endl; }
void lock () { load_barrier(); bool expected = false; POMAGMA_ASSERT(m_flag.compare_exchange_strong(expected, true), "lock contention"); }
inline Router::TypeId Router::new_type(Router::Arity arity, const std::string& name) { auto i = m_language.find(name); POMAGMA_ASSERT(i != m_language.end(), name << " not found"); float prob = i->second; m_types.push_back(SegmentType(arity, name, prob)); return m_types.size() - 1; }
template<class X> void splay_forest<X>::validate_forest () { POMAGMA_DEBUG("Validating " << nameof<X>() << " forest"); for (typename Pos::sparse_iterator iter=Pos::sbegin(); iter!=Pos::send(); ++iter) { Pos eqn = *iter; //make sure eqn is inserted test_find(eqn); //check L-U agreement if (Pos l = L(eqn)) { POMAGMA_ASSERT(rank(l) < rank(eqn), "L-U out of order"); POMAGMA_ASSERT(U(l) == eqn, "invalid: runaway L-child"); } //check R-U agreement if (Pos r = R(eqn)) { POMAGMA_ASSERT(rank(eqn) < rank(r), "R-U out of order"); POMAGMA_ASSERT(U(r) == eqn, "invalid: runaway R-child"); } //check U-_ agreement if (Pos u = U(eqn)) { if (rank(eqn) < rank(u)) { POMAGMA_ASSERT(L(u) == eqn, "invalid: neglected L-child"); } else { POMAGMA_ASSERT(R(u) == eqn, "invalid: neglected R-child"); } } else { POMAGMA_ASSERT(root(eqn) == eqn, "invalid: root mismatch"); } } }
InFile (const std::string & filename) : id(H5Fopen( filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)) { POMAGMA_ASSERT(id >= 0, "failed to open file " << filename << "\n" << get_error()); }
inline T * replace ( std::unordered_map<std::string, T *> & map, const std::string & name, T * new_value) { auto i = map.find(name); POMAGMA_ASSERT(i != map.end(), "nothing to replace"); return replace(i->second, new_value); }
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)); } }
OutFile (const std::string & filename) : id(H5Fcreate( filename.c_str(), H5F_ACC_TRUNC, // creation mode H5P_DEFAULT, // creation property list H5P_DEFAULT)) // access property list { POMAGMA_ASSERT(id >= 0, "failed to create file " << filename << "\n" << get_error()); }
inline void tempfile_load (pid_t pid, T & t) { std::string filename = tempfile_name(pid); { std::ifstream file(filename.c_str(), std::ios::in); POMAGMA_ASSERT(file, "failed to open tempfile " << filename); file >> t; } remove(filename.c_str()); }
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); } }
void in_temp_dir(std::function<void()> body) { const auto old_path = fs::current_path(); const auto temp_path = fs::unique_path("/tmp/pomagma.temp.%%%%-%%%%-%%%%-%%%%"); POMAGMA_ASSERT(fs::create_directories(temp_path), "failed to create temp directory"); fs::current_path(temp_path); body(); fs::current_path(old_path); fs::remove_all(temp_path); }
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); } }
void assume_core_facts (const char * theory_file) { std::ifstream file(theory_file); POMAGMA_ASSERT(file, "failed to open " << theory_file); std::string expression; while (getline(file, expression)) { if (not expression.empty() and expression[0] != '#') { schedule(AssumeTask(expression)); } } }
// for growing void base_bin_rel::move_from (const base_bin_rel & other) { POMAGMA_DEBUG("Copying base_bin_rel"); size_t min_item_dim = min(item_dim(), other.item_dim()); size_t min_word_dim = min(word_dim(), other.word_dim()); m_support.move_from(other.m_support); if (_symmetric()) { POMAGMA_ASSERT(other._symmetric(), "symmetry mismatch"); for (size_t i = 1; i <= min_item_dim; ++i) { memcpy(Lx(i), other.Lx(i), sizeof(Word) * min_word_dim); } } else { POMAGMA_ASSERT(not other._symmetric(), "symmetry mismatch"); for (size_t i = 1; i <= min_item_dim; ++i) { memcpy(Lx(i), other.Lx(i), sizeof(Word) * min_word_dim); memcpy(Rx(i), other.Rx(i), sizeof(Word) * min_word_dim); } } }
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); }
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); } } }
inline void random_init (Carrier & carrier, rng_t & rng) { POMAGMA_ASSERT_EQ(carrier.item_count(), 0); const size_t size = carrier.item_dim(); for (Ob i = 1; i <= size; ++i) { POMAGMA_ASSERT(carrier.unsafe_insert(), "insertion failed"); } POMAGMA_ASSERT_EQ(carrier.item_count(), size); std::bernoulli_distribution randomly_remove(0.5); for (Ob i = 1; i <= size; ++i) { if (randomly_remove(rng)) { carrier.unsafe_remove(i); } } }
Server::Server(const char* structure_file, const char* language_file) : m_language(load_language(language_file)), m_structure(structure_file), m_return(m_structure.carrier()), m_nreturn(m_structure.carrier()), m_dense_set_store(m_structure.carrier().item_dim()), m_worker_pool(), m_intervals_approximator(m_structure, m_dense_set_store, m_worker_pool), m_approximator(m_structure), m_approximate_parser(m_approximator), m_probs(), m_routes(), m_simplifier(m_structure.signature(), m_routes, m_error_log), m_corpus(m_structure.signature()), m_validator(m_approximator), m_parser(), m_virtual_machine() { // parser and virtual_machine must be loaded after RETURN is delclared. Signature& signature = m_structure.signature(); POMAGMA_ASSERT(not signature.unary_relation("RETURN"), "reserved name RETURN is defined in loaded structure"); POMAGMA_ASSERT(not signature.unary_relation("NRETURN"), "reserved name NRETURN is defined in loaded structure"); signature.declare("RETURN", m_return); signature.declare("NRETURN", m_nreturn); m_parser.load(signature); m_virtual_machine.load(signature); if (POMAGMA_DEBUG_LEVEL > 1) { m_structure.validate(); } Router router(m_structure.signature(), m_language); m_probs = router.measure_probs(); m_routes = router.find_routes(); }
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; }
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)); }
base_bin_rel::base_bin_rel (size_t item_dim, bool symmetric) : m_support(item_dim), m_round_item_dim(dense_set::round_item_dim(item_dim)), m_round_word_dim(dense_set::round_word_dim(item_dim)), m_data_size_words((1 + m_round_item_dim) * m_round_word_dim), m_Lx_lines(pomagma::alloc_blocks<Word>(m_data_size_words)), m_Rx_lines(symmetric ? m_Lx_lines : pomagma::alloc_blocks<Word>(m_data_size_words)) { POMAGMA_DEBUG("creating base_bin_rel with " << m_data_size_words << " words"); POMAGMA_ASSERT(m_round_item_dim <= MAX_ITEM_DIM, "base_bin_rel is too large"); // initialize to zeros bzero(m_Lx_lines, sizeof(Word) * m_data_size_words); if (not symmetric) { bzero(m_Rx_lines, sizeof(Word) * m_data_size_words); } }
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)); } }
void base_bin_rel::validate() const { m_support.validate(); // TODO validate Lx, Rx agree with support // (move code over from dense_bin_rel::validate() if (_symmetric()) { // check emptiness outside of support dense_set set(item_dim(), NULL); dense_set round_set(m_round_item_dim, NULL); for (oid_t i = 0; i < m_round_item_dim; ++i) { if (1 <= i and i <= item_dim()) { set.init(Lx(i)); set.validate(); } else { round_set.init(m_Lx_lines + m_round_word_dim * i); round_set.validate(); POMAGMA_ASSERT(round_set.empty(), "unsupported Lx(" << i << ") has " << round_set.count_items() << " items"); } } // check for Lx/Rx agreement for (oid_t i = 1; i <= item_dim(); ++i) { for (oid_t j = i; j <= item_dim(); ++j) { POMAGMA_ASSERT(Lx(i, j) == Rx(i, j), "Lx, Rx disagree at " << i << ',' << j); }} } else { // check emptiness outside of support dense_set set(item_dim(), NULL); dense_set round_set(m_round_item_dim, NULL); for (oid_t i = 0; i < m_round_item_dim; ++i) { if (1 <= i and i <= item_dim()) { set.init(Lx(i)); set.validate(); set.init(Rx(i)); set.validate(); } else { round_set.init(m_Lx_lines + m_round_word_dim * i); round_set.validate(); POMAGMA_ASSERT(round_set.empty(), "unsupported Lx(" << i << ") has " << round_set.count_items() << " items"); round_set.init(m_Rx_lines + m_round_word_dim * i); round_set.validate(); POMAGMA_ASSERT(round_set.empty(), "unsupported Rx(" << i << ") has " << round_set.count_items() << " items"); } } // check for Lx/Rx agreement for (oid_t i = 1; i <= item_dim(); ++i) { for (oid_t j = 1; j <= item_dim(); ++j) { POMAGMA_ASSERT(Lx(i, j) == Rx(i, j), "Lx, Rx disagree at " << i << ',' << j); }} } }
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; }