1 | /*
|
2 | * Souffle - A Datalog Compiler
|
3 | * Copyright (c) 2022, The Souffle Developers. All rights reserved
|
4 | * Licensed under the Universal Permissive License v 1.0 as shown at:
|
5 | * - https://opensource.org/licenses/UPL
|
6 | * - <souffle root>/licenses/SOUFFLE-UPL.txt
|
7 | */
|
8 |
|
9 | /************************************************************************
|
10 | *
|
11 | * @file SubsetCache.h
|
12 | *
|
13 | * Data structure for efficiently generating subsets without recomputation
|
14 | *
|
15 | ***********************************************************************/
|
16 |
|
17 | #pragma once
|
18 |
|
19 | namespace souffle {
|
20 |
|
21 | class SubsetCache {
|
22 | public:
|
23 | using PowerSet = std::set<std::vector<std::size_t>>;
|
24 |
|
25 | const PowerSet& getSubsets(std::size_t N, std::size_t K) const {
|
26 | if (cache.count({N, K})) {
|
27 | return cache.at({N, K});
|
28 | }
|
29 |
|
30 | PowerSet res;
|
31 |
|
32 | // generate the next permutation of the bitmask
|
33 | std::vector<std::size_t> cur;
|
34 | cur.reserve(K);
|
35 |
|
36 | // use bitmask for subset generation
|
37 | std::string bitmask(K, 1); // K leading 1's
|
38 | bitmask.resize(N, 0); // N-K trailing 0's
|
39 |
|
40 | // generate the combination while there are combinations to go
|
41 | do {
|
42 | cur.clear();
|
43 |
|
44 | // construct the subset using the set bits in the bitmask
|
45 | for (std::size_t i = 0; i < N; ++i) // [0..N-1] integers
|
46 | {
|
47 | if (bitmask[i]) {
|
48 | cur.push_back(i);
|
49 | }
|
50 | }
|
51 | res.insert(cur);
|
52 | } while (std::prev_permutation(bitmask.begin(), bitmask.end()));
|
53 | cache[std::make_pair(N, K)] = res;
|
54 | return cache.at({N, K});
|
55 | }
|
56 |
|
57 | private:
|
58 | mutable std::map<std::pair<std::size_t, std::size_t>, PowerSet> cache;
|
59 | };
|
60 |
|
61 | } // namespace souffle
|