Skip to content

feat(ruvector-mincut): exact Stoer-Wagner partition backend for RuVectorGraphAnalyzer #33

feat(ruvector-mincut): exact Stoer-Wagner partition backend for RuVectorGraphAnalyzer

feat(ruvector-mincut): exact Stoer-Wagner partition backend for RuVectorGraphAnalyzer #33

name: MinCut regression
on:
pull_request:
paths:
- 'crates/ruvector-mincut/**'
- 'crates/ruvector-mincut-node/**'
- 'crates/ruvector-mincut-wasm/**'
- 'npm/packages/mincut-wasm/**'
- '.github/workflows/mincut-regression.yml'
workflow_dispatch:
permissions:
contents: read
jobs:
kernel:
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4
with:
toolchain: stable
components: rustfmt
- name: Exhaustive kernel oracle (32768 graph topologies)
run: |
rustc --edition=2021 -O --test crates/ruvector-mincut/tests/exact_kernel.rs -o /tmp/mincut-kernel-tests
/tmp/mincut-kernel-tests
- name: Check formatting of changed Rust files
run: |
rustfmt --edition=2021 --config skip_children=true crates/ruvector-mincut/src/algorithm/exact.rs crates/ruvector-mincut/src/algorithm/mod.rs crates/ruvector-mincut/src/routing/mod.rs crates/ruvector-mincut/src/routing/rufield.rs crates/ruvector-mincut/src/routing/spatial.rs crates/ruvector-mincut/src/graph/mod.rs crates/ruvector-mincut/src/canonical/dynamic/mod.rs crates/ruvector-mincut/src/canonical/dynamic/tests.rs crates/ruvector-mincut/tests/exact_kernel.rs crates/ruvector-mincut/tests/exact_regression.rs crates/ruvector-mincut/examples/dynamic_bench.rs crates/ruvector-mincut-node/src/lib.rs crates/ruvector-mincut-wasm/src/lib.rs
git diff --exit-code -- crates/ruvector-mincut crates/ruvector-mincut-node crates/ruvector-mincut-wasm
public-api:
runs-on: ubuntu-22.04
timeout-minutes: 25
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
submodules: recursive
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4
with:
toolchain: stable
components: rustfmt
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32
- name: Compile public API and library regressions
timeout-minutes: 15
run: cargo test -p ruvector-mincut --features canonical --test exact_regression --lib --no-run
- name: Public API exhaustive oracle
timeout-minutes: 3
run: cargo test -p ruvector-mincut --features canonical --test exact_regression
- name: Changed modules and canonical consumers
timeout-minutes: 5
run: |
cargo test -p ruvector-mincut --features canonical --lib algorithm::tests::
cargo test -p ruvector-mincut --features canonical --lib graph::tests::
cargo test -p ruvector-mincut --features canonical --lib canonical::
- name: Compare public API timings against prior verified revision
if: github.event_name == 'pull_request'
env:
BASE_SHA: c92142ba90b08f9b56c1e7b66364c4dcc8c85e69
run: |
cargo run -p ruvector-mincut --release --example dynamic_bench
cp crates/ruvector-mincut/src/algorithm/mod.rs /tmp/mincut-current.rs
trap 'cp /tmp/mincut-current.rs crates/ruvector-mincut/src/algorithm/mod.rs' EXIT
git fetch --depth=1 origin "$BASE_SHA"
git show "$BASE_SHA:crates/ruvector-mincut/src/algorithm/mod.rs" > crates/ruvector-mincut/src/algorithm/mod.rs
cargo run -p ruvector-mincut --release --example dynamic_bench
javascript:
runs-on: ubuntu-22.04
timeout-minutes: 30
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4
with:
toolchain: stable
targets: wasm32-unknown-unknown
- uses: actions/setup-node@v4
with:
node-version: '22'
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32
with:
key: mincut-javascript
- name: Build and test native addon
run: |
cargo build -p ruvector-mincut-node --release
cp target/release/libruvector_mincut_node.so /tmp/mincut.node
MINCUT_ADDON=/tmp/mincut.node node --test crates/ruvector-mincut-node/tests/runtime.cjs crates/ruvector-mincut-node/tests/routing.cjs
MINCUT_ADDON=/tmp/mincut.node node npm/packages/mincut-wasm/bench/batch.cjs
- name: Build WASM and matching JavaScript glue
run: |
cargo build -p ruvector-mincut-wasm --release --target wasm32-unknown-unknown
VERSION=$(awk '/^name = "wasm-bindgen"$/ {getline; gsub(/"/, "", $3); print $3; exit}' Cargo.lock)
cargo install wasm-bindgen-cli --version "$VERSION" --locked
wasm-bindgen target/wasm32-unknown-unknown/release/ruvector_mincut_wasm.wasm --target nodejs --out-dir npm/packages/mincut-wasm/node
wasm-bindgen target/wasm32-unknown-unknown/release/ruvector_mincut_wasm.wasm --target web --out-dir npm/packages/mincut-wasm/web
echo '{"type":"commonjs"}' > npm/packages/mincut-wasm/node/package.json
- name: Test package exports and installed tarball
run: |
cd npm/packages/mincut-wasm
npm test
node bench/batch.cjs
wc -c web/ruvector_mincut_wasm_bg.wasm
npm pack --pack-destination /tmp
mkdir /tmp/mincut-consumer
cd /tmp/mincut-consumer
npm init -y
npm install /tmp/ruvector-mincut-wasm-*.tgz --ignore-scripts
cp "$GITHUB_WORKSPACE/npm/packages/mincut-wasm/test/"*.test.cjs .
node --test *.test.cjs
- name: Complete native, WASM and worker road benchmarks
run: |
set -euo pipefail
python -m pip install igraph==0.11.9 texttable==1.7.0
python crates/ruvector-mincut/benchmarks/prepare_roads.py --output /tmp/roads
ROADS_DIR=/tmp/roads MINCUT_ADDON=/tmp/mincut.node node crates/ruvector-mincut/benchmarks/routing_runtime.cjs native | tee /tmp/roads/native-runtime.jsonl
ROADS_DIR=/tmp/roads node crates/ruvector-mincut/benchmarks/routing_runtime.cjs wasm | tee /tmp/roads/wasm-runtime.jsonl
ROADS_DIR=/tmp/roads node crates/ruvector-mincut/benchmarks/routing_runtime.cjs worker | tee /tmp/roads/worker-runtime.jsonl
- name: Real browser module worker
run: |
npm install --prefix /tmp/mincut-browser --ignore-scripts playwright@1.62.1
/tmp/mincut-browser/node_modules/.bin/playwright install --with-deps chromium
NODE_PATH=/tmp/mincut-browser/node_modules node npm/packages/mincut-wasm/test/browser-routing.cjs
- uses: actions/upload-artifact@v4
with:
name: mincut-road-runtime-evidence
path: /tmp/roads/*runtime.jsonl