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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

### Changed

- Switched back from `@repl` blocks to `jldoctest` blocks in the docstrings, since *Documenter.jl* stopped executing `@repl` blocks in the generated documentation (#217).
- Switched from recomputing Del Corso–Manzini placement deadlines from scratch each step to maintaining them incrementally as nodes are placed, incorporating the last missing optimization from the paper (#216).
- Changed the default recognition decider from Del Corso–Manzini to Caprara–Salazar-González, which is now considerably faster after the performance fixes (#214).
- Updated the `_blb_connected` helper (used in `bandwidth_lower_bound`) to avoid unnecessary allocations, now requiring only `O(n)` auxiliary space instead of `O(n^2)` (#213).
Expand Down
25 changes: 18 additions & 7 deletions src/Minimization/Exact/solvers/brute_force_search.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,24 @@ is not *exactly* ``Θ(n²)``, although it is close.)
The algorithm always iterates over all possible permutations, so it is infeasible to go
above ``9×9`` or ``10×10`` without incurring multiple-hour runtimes. Nevertheless, we see
that it is quite effective for, say, ``8×8``:
```@repl
using Random, SparseArrays
Random.seed!(628318);
(n, p) = (8, 0.2);
A = sprand(n, n, p);
A = A + A' # Ensure structural symmetry;
minimize_bandwidth(A, Minimization.BruteForceSearch())
```jldoctest
julia> using Random, SparseArrays

julia> Random.seed!(628318);

julia> (n, p) = (8, 0.2);

julia> A = sprand(n, n, p);

julia> A = A + A' # Ensure structural symmetry;

julia> minimize_bandwidth(A, Minimization.BruteForceSearch())
Results of Bandwidth Minimization Algorithm
* Algorithm: Brute-force search
* Approach: exact
* Minimum Bandwidth: 3
* Original Bandwidth: 6
* Matrix Size: 8×8
```

# Notes
Expand Down
34 changes: 26 additions & 8 deletions src/Minimization/Exact/solvers/caprara_salazar_gonzalez.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,32 @@ exponential growth in time complexity with respect to ``n``.
# Examples
We verify the optimality of the ordering found by Caprara–Salazar-González for a random
``8×8`` matrix via a brute-force search over all possible permutations up to reversal:
```@repl
using Random, SparseArrays
Random.seed!(5883);
(n, p) = (8, 0.25);
A = sprand(n, n, p);
A = A + A' # Ensure structural symmetry;
res_bf = minimize_bandwidth(A, Minimization.BruteForceSearch())
res_csg = minimize_bandwidth(A, Minimization.CapraraSalazarGonzalez())
```jldoctest
julia> using Random, SparseArrays

julia> Random.seed!(5883);

julia> (n, p) = (8, 0.25);

julia> A = sprand(n, n, p);

julia> A = A + A' # Ensure structural symmetry;

julia> res_bf = minimize_bandwidth(A, Minimization.BruteForceSearch())
Results of Bandwidth Minimization Algorithm
* Algorithm: Brute-force search
* Approach: exact
* Minimum Bandwidth: 4
* Original Bandwidth: 7
* Matrix Size: 8×8

julia> res_csg = minimize_bandwidth(A, Minimization.CapraraSalazarGonzalez())
Results of Bandwidth Minimization Algorithm
* Algorithm: Caprara–Salazar-González
* Approach: exact
* Minimum Bandwidth: 4
* Original Bandwidth: 7
* Matrix Size: 8×8
```

# Notes
Expand Down
144 changes: 106 additions & 38 deletions src/Minimization/Exact/solvers/del_corso_manzini.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,32 @@ Based on experimental results, the algorithm is feasible for ``n×n`` matrices u
# Examples
We verify the optimality of the ordering found by Del Corso–Manzini for a random ``9×9``
matrix via a brute-force search over all possible permutations up to reversal:
```@repl
using Random, SparseArrays
Random.seed!(0117);
(n, p) = (9, 0.5);
A = sprand(n, n, p);
A = A + A' # Ensure structural symmetry;
res_bf = minimize_bandwidth(A, Minimization.BruteForceSearch())
res_dcm = minimize_bandwidth(A, Minimization.DelCorsoManzini())
```jldoctest
julia> using Random, SparseArrays

julia> Random.seed!(0117);

julia> (n, p) = (9, 0.5);

julia> A = sprand(n, n, p);

julia> A = A + A' # Ensure structural symmetry;

julia> res_bf = minimize_bandwidth(A, Minimization.BruteForceSearch())
Results of Bandwidth Minimization Algorithm
* Algorithm: Brute-force search
* Approach: exact
* Minimum Bandwidth: 5
* Original Bandwidth: 8
* Matrix Size: 9×9

julia> res_dcm = minimize_bandwidth(A, Minimization.DelCorsoManzini())
Results of Bandwidth Minimization Algorithm
* Algorithm: Del Corso–Manzini
* Approach: exact
* Minimum Bandwidth: 5
* Original Bandwidth: 8
* Matrix Size: 9×9
```

We now generate (and shuffle) a random ``40×40`` matrix with minimum bandwidth ``10`` using
Expand All @@ -71,16 +89,32 @@ cases, `random_banded_matrix(n, k)` *does* generate matrices with minimum bandwi
Nevertheless, this example demonstrates that Del Corso–Manzini at the very least finds a
quite good ordering, even though exact optimality—which *is* guaranteed by the original
paper [DM99]—is not explicitly verified.)
```@repl
using Random
Random.seed!(0201);
(n, k) = (40, 10);
A = MatrixBandwidth.random_banded_matrix(n, k);
perm = randperm(n);
A_shuffled = A[perm, perm];
bandwidth(A)
bandwidth(A_shuffled) # Much larger after shuffling
minimize_bandwidth(A_shuffled, Minimization.DelCorsoManzini())
```jldoctest
julia> using Random

julia> Random.seed!(0201);

julia> (n, k) = (40, 10);

julia> A = MatrixBandwidth.random_banded_matrix(n, k);

julia> perm = randperm(n);

julia> A_shuffled = A[perm, perm];

julia> bandwidth(A)
10

julia> bandwidth(A_shuffled) # Much larger after shuffling
36

julia> minimize_bandwidth(A_shuffled, Minimization.DelCorsoManzini())
Results of Bandwidth Minimization Algorithm
* Algorithm: Del Corso–Manzini
* Approach: exact
* Minimum Bandwidth: 10
* Original Bandwidth: 36
* Matrix Size: 40×40
```

# Notes
Expand Down Expand Up @@ -184,14 +218,32 @@ for a random ``9×9`` matrix via a brute-force search over all possible permutat
reversal. The depth parameter is not explicitly set; instead, some near-optimal value is
automatically computed upon the first
[`MatrixBandwidth.Minimization.minimize_bandwidth`](@ref) function call.
```@repl
using Random, SparseArrays
Random.seed!(548836);
(n, p) = (9, 0.2);
A = sprand(n, n, p);
A = A + A' # Ensure structural symmetry;
res_bf = minimize_bandwidth(A, Minimization.BruteForceSearch())
res_dcm_ps = minimize_bandwidth(A, Minimization.DelCorsoManziniWithPS())
```jldoctest
julia> using Random, SparseArrays

julia> Random.seed!(548836);

julia> (n, p) = (9, 0.2);

julia> A = sprand(n, n, p);

julia> A = A + A' # Ensure structural symmetry;

julia> res_bf = minimize_bandwidth(A, Minimization.BruteForceSearch())
Results of Bandwidth Minimization Algorithm
* Algorithm: Brute-force search
* Approach: exact
* Minimum Bandwidth: 3
* Original Bandwidth: 8
* Matrix Size: 9×9

julia> res_dcm_ps = minimize_bandwidth(A, Minimization.DelCorsoManziniWithPS())
Results of Bandwidth Minimization Algorithm
* Algorithm: Del Corso–Manzini with perimeter search
* Approach: exact
* Minimum Bandwidth: 3
* Original Bandwidth: 8
* Matrix Size: 9×9
```

We now generate (and shuffle) a random ``30×30`` matrix with minimum bandwidth ``8`` using
Expand All @@ -201,18 +253,34 @@ finds a bandwidth-``8`` ordering, which is (we claim) optimal up to symmetric pe
`< k`. Nevertheless, this example demonstrates that Del Corso–Manzini at the very least
finds a quite good ordering, even though exact optimality—which *is* guaranteed by the
original paper [DM99]—is not explicitly verified.) In this case, we set the depth parameter
to ``4`` beforehand instead of relying on [`Recognition.dcm_ps_optimal_depth`](@ref).

```@repl
using Random
Random.seed!(78779);
(n, k, depth) = (30, 8, 4);
A = MatrixBandwidth.random_banded_matrix(n, k);
perm = randperm(n);
A_shuffled = A[perm, perm];
bandwidth(A)
bandwidth(A_shuffled) # Much larger after shuffling
minimize_bandwidth(A_shuffled, Minimization.DelCorsoManziniWithPS(depth))
to ``3`` beforehand instead of relying on [`Recognition.dcm_ps_optimal_depth`](@ref).

```jldoctest
julia> using Random

julia> Random.seed!(78779);

julia> (n, k, depth) = (30, 8, 3);

julia> A = MatrixBandwidth.random_banded_matrix(n, k);

julia> perm = randperm(n);

julia> A_shuffled = A[perm, perm];

julia> bandwidth(A)
8

julia> bandwidth(A_shuffled) # Much larger after shuffling
25

julia> minimize_bandwidth(A_shuffled, Minimization.DelCorsoManziniWithPS(depth))
Results of Bandwidth Minimization Algorithm
* Algorithm: Del Corso–Manzini with perimeter search
* Approach: exact
* Minimum Bandwidth: 8
* Original Bandwidth: 25
* Matrix Size: 30×30
```

# Notes
Expand Down
70 changes: 52 additions & 18 deletions src/Minimization/Exact/solvers/saxe_gurari_sudborough.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,32 @@ aggressive pruning strategies keep their effective search space very small in pr
# Examples
We verify the optimality of the ordering found by Saxe–Gurari–Sudborough for a random
``9×9`` matrix via a brute-force search over all possible permutations up to reversal:
```@repl
using Random, SparseArrays
Random.seed!(52452);
(n, p) = (9, 0.5);
A = sprand(n, n, p);
A = A + A' # Ensure structural symmetry;
res_bf = minimize_bandwidth(A, Minimization.BruteForceSearch())
res_sgs = minimize_bandwidth(A, Minimization.SaxeGurariSudborough())
```jldoctest
julia> using Random, SparseArrays

julia> Random.seed!(52452);

julia> (n, p) = (9, 0.5);

julia> A = sprand(n, n, p);

julia> A = A + A' # Ensure structural symmetry;

julia> res_bf = minimize_bandwidth(A, Minimization.BruteForceSearch())
Results of Bandwidth Minimization Algorithm
* Algorithm: Brute-force search
* Approach: exact
* Minimum Bandwidth: 5
* Original Bandwidth: 8
* Matrix Size: 9×9

julia> res_sgs = minimize_bandwidth(A, Minimization.SaxeGurariSudborough())
Results of Bandwidth Minimization Algorithm
* Algorithm: Saxe–Gurari–Sudborough
* Approach: exact
* Minimum Bandwidth: 5
* Original Bandwidth: 8
* Matrix Size: 9×9
```

We now generate (and shuffle) a random ``25×25`` matrix with minimum bandwidth ``5`` using
Expand All @@ -73,16 +91,32 @@ cases, `random_banded_matrix(n, k)` generates matrices with minimum bandwidth `<
appears to be one such case. Although we do not explicitly verify exact optimality—which
*is* guaranteed by the original paper [GS84]—here via brute-force search, this example
demonstrates that Saxe–Gurari–Sudborough at the very least finds a quite good ordering.)
```@repl
using Random
Random.seed!(937497);
(n, k, p) = (25, 5, 0.25);
A = MatrixBandwidth.random_banded_matrix(n, k; p=p);
perm = randperm(n);
A_shuffled = A[perm, perm];
bandwidth(A)
bandwidth(A_shuffled) # Much larger after shuffling
minimize_bandwidth(A_shuffled, Minimization.SaxeGurariSudborough())
```jldoctest
julia> using Random

julia> Random.seed!(937497);

julia> (n, k, p) = (25, 5, 0.25);

julia> A = MatrixBandwidth.random_banded_matrix(n, k; p=p);

julia> perm = randperm(n);

julia> A_shuffled = A[perm, perm];

julia> bandwidth(A)
5

julia> bandwidth(A_shuffled) # Much larger after shuffling
19

julia> minimize_bandwidth(A_shuffled, Minimization.SaxeGurariSudborough())
Results of Bandwidth Minimization Algorithm
* Algorithm: Saxe–Gurari–Sudborough
* Approach: exact
* Minimum Bandwidth: 4
* Original Bandwidth: 19
* Matrix Size: 25×25
```

# Notes
Expand Down
Loading
Loading