MCPcopy Create free account
hub / github.com/VectorDB-NTU/RaBitQ-Library / SymqgIndex

Class SymqgIndex

python_bindings/symqg_bindings.cpp:17–110  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

15namespace rabitqlib::python_bindings {
16
17class SymqgIndex {
18 public:
19 SymqgIndex(size_t dim, size_t max_degree, const std::string& metric = "l2")
20 : dim_(dim)
21 , max_degree_(max_degree)
22 , metric_(metric_from_string(metric)) {}
23
24 void build(py::handle data, size_t ef_construction, size_t num_threads = 1) {
25 auto data_array = ensure_2d_array<float>(data, "data");
26 if (static_cast<size_t>(data_array.shape(1)) != dim_) {
27 throw std::invalid_argument("data dimension does not match index dim");
28 }
29
30 num_points_ = static_cast<size_t>(data_array.shape(0));
31 index_ = std::make_unique<rabitqlib::symqg::QuantizedGraph<float>>(
32 num_points_, dim_, max_degree_, metric_, rabitqlib::RotatorType::FhtKacRotator
33 );
34
35 rabitqlib::symqg::QGBuilder builder(*index_, ef_construction, data_array.data(), num_threads);
36 builder.build();
37 built_ = true;
38 }
39
40 py::tuple search(py::handle queries, size_t k, size_t ef, size_t num_threads = 1) {
41 auto query_array = ensure_2d_array<float>(queries, "queries");
42 if (!built_) {
43 throw std::runtime_error("SymqgIndex must be built or loaded before search");
44 }
45 if (static_cast<size_t>(query_array.shape(1)) != dim_) {
46 throw std::invalid_argument("query dimension does not match index dim");
47 }
48
49 index_->set_ef(ef);
50
51 const size_t nq = static_cast<size_t>(query_array.shape(0));
52 const auto shape = std::vector<ssize_t>{static_cast<ssize_t>(nq), static_cast<ssize_t>(k)};
53 auto ids = py::array_t<rabitqlib::PID>(shape);
54 auto dists = py::array_t<float>(shape);
55 auto ids_buf = ids.mutable_unchecked<2>();
56 auto dists_buf = dists.mutable_unchecked<2>();
57
58 rabitqlib::ivf::parallel_for(
59 0,
60 nq,
61 num_threads,
62 [&](size_t idx, size_t /*threadId*/) {
63 std::vector<rabitqlib::PID> row_ids(k, 0);
64 std::vector<float> row_dists(k, 0.0F);
65 index_->search(query_array.data() + (idx * dim_), static_cast<uint32_t>(k), row_ids.data(), row_dists.data());
66 for (size_t j = 0; j < k; ++j) {
67 ids_buf(static_cast<ssize_t>(idx), static_cast<ssize_t>(j)) = row_ids[j];
68 dists_buf(static_cast<ssize_t>(idx), static_cast<ssize_t>(j)) = row_dists[j];
69 }
70 }
71 );
72
73 return py::make_tuple(ids, dists);
74 }

Callers 1

mainFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected