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"); }
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; }
Approximator::Approximator(Structure& structure, DenseSetStore& sets, WorkerPool& worker_pool) : // 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_less(structure.binary_relation("LESS")), m_nless(structure.binary_relation("NLESS")), // dense set stores m_sets(sets), m_empty_set(sets.store(std::move(DenseSet(m_item_dim)))), m_known(1 + m_item_dim), m_unknown(), // lazy map caches m_disjoint_cache(worker_pool, [this](const std::pair<SetId, SetId>& pair) { return m_sets.load(pair.first).disjoint(m_sets.load(pair.second)) ? Trool::TRUE : Trool::FALSE; }), m_union_cache(worker_pool, [this](const std::vector<SetId>& sets) { const size_t count = sets.size(); POMAGMA_ASSERT1(count >= 2, "too few sets: " << count); DenseSet val(m_item_dim); val.set_union(m_sets.load(sets[0]), m_sets.load(sets[1])); for (size_t i = 2; i < count; ++i) { val += m_sets.load(sets[i]); } return m_sets.store(std::move(val)); }), m_nullary_cache(), m_binary_cache() { POMAGMA_ASSERT(m_top, "TOP is not defined"); POMAGMA_ASSERT(m_bot, "BOT is not defined"); POMAGMA_INFO("Inserting LESS and NLESS in DenseSetStore"); for (auto iter = m_structure.carrier().iter(); iter.ok(); iter.next()) { const Ob ob = *iter; m_known[ob][ABOVE] = m_sets.store(m_less.get_Lx_set(ob)); m_known[ob][BELOW] = m_sets.store(m_less.get_Rx_set(ob)); m_known[ob][NABOVE] = m_sets.store(m_nless.get_Lx_set(ob)); m_known[ob][NBELOW] = m_sets.store(m_nless.get_Rx_set(ob)); } m_unknown[ABOVE] = m_known[m_top][ABOVE]; m_unknown[BELOW] = m_known[m_bot][BELOW]; m_unknown[NABOVE] = m_empty_set; m_unknown[NBELOW] = m_empty_set; POMAGMA_INFO("Initializing nullary_function cache"); for (const auto& i : signature().nullary_functions()) { const std::string& name = i.first; Ob ob = i.second->find(); Approximation approx = ob ? known(ob) : unknown(); POMAGMA_INSERT(m_nullary_cache, name, approx); } POMAGMA_INFO("Initializing binary_function cache"); for (const auto& i : signature().binary_functions()) { const auto& fun = *i.second; const uint64_t hash = hash_name(i.first); typedef SetPairToSetCache Cache; for (Parity p : {ABOVE, BELOW}) { POMAGMA_INSERT( m_binary_cache, CacheKey(hash, VAL, p), new Cache(worker_pool, [this, &fun, p](const std::pair<SetId, SetId>& x) { return function_lhs_rhs(fun, x.first, x.second, p); })); } for (Parity p : {NABOVE, NBELOW}) { POMAGMA_INSERT( m_binary_cache, CacheKey(hash, RHS, p), new Cache(worker_pool, [this, &fun, p](const std::pair<SetId, SetId>& x) { return function_lhs_val(fun, x.first, x.second, p); })); POMAGMA_INSERT( m_binary_cache, CacheKey(hash, LHS, p), new Cache(worker_pool, [this, &fun, p](const std::pair<SetId, SetId>& x) { return function_rhs_val(fun, x.first, x.second, p); })); } } POMAGMA_INFO("Initializing symmetric_function cache"); for (const auto& i : signature().symmetric_functions()) { const auto& fun = *i.second; const uint64_t hash = hash_name(i.first); typedef SetPairToSetCache Cache; for (Parity p : {ABOVE, BELOW}) { POMAGMA_INSERT( m_binary_cache, CacheKey(hash, VAL, p), new Cache(worker_pool, [this, &fun, p](const std::pair<SetId, SetId>& x) { return function_lhs_rhs(fun, x.first, x.second, p); })); } for (Parity p : {NABOVE, NBELOW}) { auto* cache = new Cache( worker_pool, [this, &fun, p](const std::pair<SetId, SetId>& x) { return function_lhs_val(fun, x.first, x.second, p); }); POMAGMA_INSERT(m_binary_cache, CacheKey(hash, RHS, p), cache); POMAGMA_INSERT(m_binary_cache, CacheKey(hash, LHS, p), cache); } } }