Skip to content

Commit

Permalink
A few more minor improvements before merging this
Browse files Browse the repository at this point in the history
  • Loading branch information
Hannah Bast committed Oct 10, 2024
1 parent 15df99b commit 943c3e9
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 27 deletions.
46 changes: 24 additions & 22 deletions src/engine/CountConnectedSubgraphs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,35 @@ namespace countConnectedSubgraphs {

// _____________________________________________________________________________
size_t countSubgraphs(const Graph& graph, size_t budget) {
size_t c = 0;
size_t count = 0;
// For each node `i`, recursively count all subgraphs that contain `i`, but no
// node `k < i` (because these have already been counted previously, when we
// ran the loop for `k`.
// ran the loop for `k`).
for (size_t i = 0; i < graph.size(); ++i) {
++c;
if (c > budget) {
++count;
if (count > budget) {
return budget + 1;
}
// The subgraph that only consists of `i` is encoded by a single `1` bit.
// The ignored set has `1`s in all `i` bits that have a lower index than `i`
// (e.g. if `i` is 3, then the subgraph is `[0 x 56] 0000 1000` and the
// ignored set is `[0 x 56] 0000 0111`.
uint64_t subgraph = 1ULL << i;
// The set of nodes that only consists of node `i` is encoded by a single
// `1` bit. The ignored set has `1`s in all `i` bits that have a lower index
// than `i` (e.g. if `i` is 3, then `nodes` is `[0 x 56] 0000 1000` and
// `ignored` is `[0 x 56] 0000 0111`.
uint64_t nodes = 1ULL << i;
uint64_t ignored = ad_utility::bitMaskForLowerBits(i);
c = countSubgraphsRecursively(graph, subgraph, ignored, c, budget);
count = countSubgraphsRecursively(graph, nodes, ignored, count, budget);
}
return c;
return count;
}

// Return the set of nodes in `graph` that are adjacent to at least one of the
// nodes in `nodes`. Nodes that are `ignored` are excluded from the result. Note
// that the result may contain nodes from the `nodes` itself. The result is
// returned using the same encoding as `nodes` and `ignored`.
static uint64_t computeNeighbors(const Graph& graph, uint64_t subgraph,
static uint64_t computeNeighbors(const Graph& graph, uint64_t nodes,
uint64_t ignored) {
uint64_t neighbors{};
for (size_t i = 0; i < 64; ++i) {
bool set = subgraph & (1ULL << i);
bool set = nodes & (1ULL << i);
if (set) {
neighbors |= graph[i].neighbors_;
}
Expand All @@ -48,8 +48,8 @@ static uint64_t computeNeighbors(const Graph& graph, uint64_t subgraph,
}

// For a number `i` from 0 .. 2^`neighbors.size()` - 1, return the `i`th
// subset of the elements of `neighborVec`. All elements in `neighbors` have
// to be `< 64`, so that the final result can be expressed as a bitmap.
// subset of the elements of `neighbors`. All elements in `neighbors` have
// to be from 0..63 so that the final result can be expressed as a bitmap.
static uint64_t subsetIndexToBitmap(size_t i,
const std::vector<uint8_t>& neighbors) {
// Note: This can probably be done more efficiently using bit fiddling, but it
Expand All @@ -63,8 +63,8 @@ static uint64_t subsetIndexToBitmap(size_t i,
return subset;
}

// Convert a bitset to a vector of the indices of the bits that are set, e.g
// `13` (`1101` as bits) will be converted to `[0, 2, 3]`;
// Convert a bitset to a vector of the indices of the bits that are set. For
// example, `13` (`1101` as bits) will be converted to `[0, 2, 3]`;
static std::vector<uint8_t> bitsetToVector(uint64_t bitset) {
std::vector<uint8_t> result;
for (uint8_t i = 0; i < 64; ++i) {
Expand All @@ -87,7 +87,8 @@ std::string toBitsetString(uint64_t x) {

// _____________________________________________________________________________
size_t countSubgraphsRecursively(const Graph& graph, uint64_t nodes,
uint64_t ignored, size_t c, size_t budget) {
uint64_t ignored, size_t count,
size_t budget) {
// Compute the set of direct neighbors of the `nodes` that is not
// ignored
uint64_t neighbors = computeNeighbors(graph, nodes, ignored);
Expand All @@ -102,13 +103,14 @@ size_t countSubgraphsRecursively(const Graph& graph, uint64_t nodes,
// Iterate over all Subsets of the neighbors
size_t upperBound = 1ULL << neighborsAsVector.size();
for (size_t i = 1; i < upperBound; ++i) {
++c;
if (c > budget) {
++count;
if (count > budget) {
return budget + 1;
}
auto subset = subsetIndexToBitmap(i, neighborsAsVector);
c = countSubgraphsRecursively(graph, nodes | subset, newIgnored, c, budget);
count = countSubgraphsRecursively(graph, nodes | subset, newIgnored, count,
budget);
}
return c;
return count;
}
} // namespace countConnectedSubgraphs
10 changes: 5 additions & 5 deletions src/engine/CountConnectedSubgraphs.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ using Graph = std::vector<Node>;
size_t countSubgraphs(const Graph& graph, size_t budget);

// Recursive implementation of `countSubgraphs`. Compute the number of connected
// subgraphs in the `graph` that contains all the nodes in `nodes`, but none
// of the nodes in `ignored`. Assume that `c` subgraphs have been previously
// found and therefore count towards the `budget`. The `nodes` and `ignored`
// are 1-hot encoded bitsets (see above).
// subgraphs in `graph` that contains all the nodes in `nodes`, but none of the
// nodes in `ignored`. Assume that `count` subgraphs have been previously found
// and therefore count towards the `budget`. The `nodes` and `ignored` are 1-hot
// encoded bitsets (see above).
size_t countSubgraphsRecursively(const Graph& graph, uint64_t nodes,
uint64_t ignored, size_t c, size_t budget);
uint64_t ignored, size_t count, size_t budget);

// Convert `x` to a string of bits, with the leading zeros removed, e.g.,
// `3` will become "11". This is useful for debugging the functions above.
Expand Down

0 comments on commit 943c3e9

Please sign in to comment.