Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/build_wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ on:
env:
ARTIFACT_RETENTION: ${{ github.ref == 'refs/heads/main' && '30' || '7' }}

# Merges queue up fast; a newer main supersedes an older smoke build. Release
# builds must never cancel each other, so only non-release runs are cancelled.
concurrency:
group: build-wheels-${{ github.ref }}
cancel-in-progress: ${{ github.event_name != 'release' }}

jobs:
cpython-linux-x86_64:
name: 'Linux CPython (${{ matrix.cibw_archs }}, ${{ matrix.manylinux_image }})'
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/ci-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ permissions:
contents: read
actions: read

# PR updates supersede each other; pushes to main and manual runs never cancel.
concurrency:
group: ci-matrix-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
OMP_NUM_THREADS: 2
CXX_STANDARD: 20
Expand All @@ -25,6 +30,10 @@ env:
jobs:
build:
name: "${{ matrix.os }} (${{ matrix.arch }}, ${{ matrix.compiler }})"
# Pushes to main were already validated as PRs; post-merge coverage comes
# from release-build below (plus the wheel smoke build), so don't redo the
# PR checks on every merge.
if: github.event_name != 'push'
runs-on: ${{ matrix.runner }}
# The gcc-13 builds run in manylinux_2_28 containers (glibc 2.28
# compatible release binaries); macos/windows/llvm-20 run on their runners.
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ add_subdirectory(networkit/cpp)
set(NETWORKIT_LIBRARIES networkit)
install(DIRECTORY include/networkit
DESTINATION ${NETWORKIT_INSTALL_INCLUDE_DIR}
FILES_MATCHING PATTERN "*.hpp")
FILES_MATCHING PATTERN "*.hpp" PATTERN "*.tpp")

# Install ttmath header files
install(DIRECTORY extlibs/ttmath/ttmath
Expand Down
37 changes: 24 additions & 13 deletions include/networkit/graph/InducedSubgraphView.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,14 +541,14 @@ class InducedSubgraphView : public std::conditional_t<std::is_same_v<BaseGraph,
/// O(1). Requires hasNode(u); @a u is a view id.
count degreeOut(node u) const {
assert(hasNode(u));
return compact_ ? outDegreeC_.values()[u] : outDegree_[u];
return compact_ ? degreesC_.values()[u].out : outDegree_[u];
}

/// O(1). Requires hasNode(u); @a u is a view id. On an undirected base the in-degree is
/// the out-degree.
count degreeIn(node u) const {
assert(hasNode(u));
return directed_ ? (compact_ ? inDegreeC_.values()[u] : inDegree_[u]) : degreeOut(u);
return directed_ ? (compact_ ? degreesC_.values()[u].in : inDegree_[u]) : degreeOut(u);
}

bool isIsolated(node u) const {
Expand Down Expand Up @@ -749,10 +749,15 @@ class InducedSubgraphView : public std::conditional_t<std::is_same_v<BaseGraph,
/// Compact-mode degree storage: keyed by base id (so the incremental updates during
/// membership edits find their entries), with keys() sorted ascending. keys() is therefore
/// the member set -- a compact id indexes keys()/values() directly -- and the flat_map is
/// updated in place by every edit, so readers never observe a stale mapping.
Aux::flat_map<node, count> outDegreeC_;
/// Only populated on a directed base.
Aux::flat_map<node, count> inDegreeC_;
/// updated in place by every edit, so readers never observe a stale mapping. In- and
/// out-degrees share one map because they have identical key sets; a second map would
/// duplicate the keys (n * sizeof(node) bytes) and double the sorted-insertion work.
/// The `in` field is unused on an undirected base.
struct CompactDegrees {
count out = 0;
count in = 0;
};
Aux::flat_map<node, CompactDegrees> degreesC_;
count n_ = 0, m_ = 0, selfLoops_ = 0;
bool directed_;
/// When true, the GraphLike primitives present dense ids @c [0, n) while the membership
Expand Down Expand Up @@ -788,7 +793,7 @@ class InducedSubgraphView : public std::conditional_t<std::is_same_v<BaseGraph,
}
return sortedMembers_;
}
return outDegreeC_.keys();
return degreesC_.keys();
}

/// View id @a u to base id. Precondition: hasNode(u); callers establish that (outNeighbors
Expand All @@ -814,10 +819,18 @@ class InducedSubgraphView : public std::conditional_t<std::is_same_v<BaseGraph,
/// A member's stored out-degree, for the incremental updates during edits. On a compact
/// view flat_map::operator[] finds the member's entry (inserting a zero for a node that
/// is joining, which the caller then overwrites).
count &outDegreeAt(node b) { return compact_ ? outDegreeC_[b] : outDegree_[b]; }
count &outDegreeAt(node b) {
if (compact_)
return degreesC_[b].out;
return outDegree_[b];
}

/// As outDegreeAt, over the in-degrees. Only called on a directed base.
count &inDegreeAt(node b) { return compact_ ? inDegreeC_[b] : inDegree_[b]; }
count &inDegreeAt(node b) {
if (compact_)
return degreesC_[b].in;
return inDegree_[b];
}

template <typename NodeRange>
void addNodesImpl(const NodeRange &nodes) {
Expand Down Expand Up @@ -924,10 +937,8 @@ class InducedSubgraphView : public std::conditional_t<std::is_same_v<BaseGraph,
}

if (compact_) {
// the flat_maps' keys must equal the membership: drop @a v's entries
outDegreeC_.erase(v);
if (directed_)
inDegreeC_.erase(v);
// the flat_map's keys must equal the membership: drop @a v's entry
degreesC_.erase(v);
} else {
if (directed_)
inDegree_[v] = 0;
Expand Down
Loading