Exact symbolic growth, unified reduction size contracts, and deterministic solver backends #1824
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| # Cancel superseded runs on the same ref (e.g. rapid pushes to a PR). | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| # Least privilege: jobs only read the repo; codecov auth is via token secret. | |
| permissions: | |
| contents: read | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| # Incremental compilation hurts cold CI builds and bloats the cache; disable it | |
| # (recommended by Swatinem/rust-cache). | |
| CARGO_INCREMENTAL: 0 | |
| # Tolerate transient registry/network blips. | |
| CARGO_NET_RETRY: 10 | |
| RUSTUP_MAX_RETRIES: 10 | |
| jobs: | |
| # Formatting — cheap, fails fast, no build/cache needed. | |
| fmt: | |
| name: Rustfmt | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt | |
| - name: Check formatting | |
| run: cargo fmt --all --check | |
| # Lints. | |
| clippy: | |
| name: Clippy | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Run clippy | |
| run: cargo clippy --all-targets --features example-db -- -D warnings | |
| # Build and exercise the HiGHS-backed CLI natively on Apple Silicon. | |
| macos-arm64: | |
| name: macOS ARM64 build & run | |
| runs-on: macos-15 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Verify ARM64 host | |
| run: "rustc -vV | grep 'host: aarch64-apple-darwin'" | |
| - name: Build workspace | |
| run: cargo build --workspace | |
| - name: Run CLI and ILP smoke test | |
| run: | | |
| target/debug/pred list | head -5 | |
| target/debug/pred create MaximumIndependentSet --graph 0-1,1-2,2-3,3-4,4-0 -o mis.json | |
| target/debug/pred solve mis.json --solver ilp | tee solve.out | |
| grep -q '"kind": "ilp"' solve.out | |
| grep -q '"evaluation": "Max(2)"' solve.out | |
| # Build and exercise the HiGHS-backed CLI natively on 64-bit Windows. | |
| windows-x86_64: | |
| name: Windows x86_64 build & run | |
| runs-on: windows-2025 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Verify x86_64 host | |
| shell: pwsh | |
| run: | | |
| $hostInfo = rustc -vV | Out-String | |
| if ($hostInfo -notmatch 'host: x86_64-pc-windows-msvc') { | |
| throw "Unexpected Rust host:`n$hostInfo" | |
| } | |
| - name: Build workspace | |
| run: cargo build --workspace | |
| - name: Run CLI and ILP smoke test | |
| shell: pwsh | |
| run: | | |
| $pred = 'target/debug/pred.exe' | |
| & $pred list | Select-Object -First 5 | |
| & $pred create MaximumIndependentSet --graph 0-1,1-2,2-3,3-4,4-0 -o mis.json | |
| & $pred solve mis.json --solver ilp | Tee-Object -FilePath solve.out | |
| $solveOutput = Get-Content solve.out -Raw | |
| if ($solveOutput -notmatch '"kind": "ilp"') { | |
| throw 'Expected the ILP solver to run' | |
| } | |
| if ($solveOutput -notmatch '"evaluation": "Max\(2\)"') { | |
| throw 'Expected the maximum independent set value to be 2' | |
| } | |
| # Cross-compile the full HiGHS-backed CLI to RISC-V Linux, then execute an | |
| # ILP solve under QEMU user-mode emulation (not just a link check). | |
| riscv: | |
| name: RISC-V build & run | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: riscv64gc-unknown-linux-gnu | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Install RISC-V cross tools and QEMU | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y gcc-riscv64-linux-gnu g++-riscv64-linux-gnu binutils-riscv64-linux-gnu qemu-user | |
| - name: Build workspace for RISC-V | |
| env: | |
| CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc | |
| CC_riscv64gc_unknown_linux_gnu: riscv64-linux-gnu-gcc | |
| CXX_riscv64gc_unknown_linux_gnu: riscv64-linux-gnu-g++ | |
| run: cargo build --workspace --target riscv64gc-unknown-linux-gnu | |
| - name: Verify RISC-V executable | |
| run: | | |
| riscv64-linux-gnu-readelf -h target/riscv64gc-unknown-linux-gnu/debug/pred \ | |
| | grep 'Machine:.*RISC-V' | |
| - name: Run CLI smoke test under QEMU | |
| env: | |
| PRED: qemu-riscv64 -L /usr/riscv64-linux-gnu target/riscv64gc-unknown-linux-gnu/debug/pred | |
| run: | | |
| # Registry loads and the catalog renders on RISC-V. | |
| $PRED list | head -5 | |
| # End-to-end reduction and HiGHS solve: MIS of a 5-cycle is 2. | |
| $PRED create MaximumIndependentSet --graph 0-1,1-2,2-3,3-4,4-0 -o mis.json | |
| $PRED solve mis.json --solver ilp | tee solve.out | |
| grep -q '"kind": "ilp"' solve.out | |
| grep -q '"evaluation": "Max(2)"' solve.out | |
| # Build, test (nextest), doc tests, and paper. | |
| test: | |
| name: Test | |
| runs-on: ubuntu-latest | |
| # Single feature set across compile + test + doctest so artifacts are reused | |
| # (no redundant full recompile between steps). | |
| env: | |
| FEATURES: "example-db" | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: taiki-e/install-action@v2 | |
| with: | |
| tool: nextest | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Install typst | |
| uses: typst-community/setup-typst@v5 | |
| - name: Compile tests | |
| run: cargo nextest run --no-run --workspace --features "$FEATURES" | |
| - name: Run tests | |
| run: cargo nextest run --workspace --features "$FEATURES" | |
| # nextest does not run doc tests; run them separately (reuses the build). | |
| - name: Run doc tests | |
| run: cargo test --doc --features "$FEATURES" --verbose | |
| - name: Build paper | |
| run: make paper | |
| # Coverage intentionally excludes the optional example database to keep the | |
| # historical codecov baseline stable. | |
| coverage: | |
| name: Code Coverage | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: llvm-tools-preview | |
| - uses: taiki-e/install-action@v2 | |
| with: | |
| tool: cargo-llvm-cov,nextest | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Generate coverage | |
| run: cargo llvm-cov nextest --workspace --lcov --output-path lcov.info | |
| - name: Upload to codecov.io | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| files: lcov.info | |
| fail_ci_if_error: false # Don't fail CI if upload fails | |
| token: ${{ secrets.CODECOV_TOKEN }} |