Skip to content

Commit e92c3a7

Browse files
committed
Documentation updates and minor changes.
1 parent ec1a95c commit e92c3a7

File tree

4 files changed

+77
-17
lines changed

4 files changed

+77
-17
lines changed

CSparse.Tests/Ordering/TestDulmageMendelsohn.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
namespace CSparse.Tests.Ordering
22
{
3+
using CSparse.Double;
34
using CSparse.Ordering;
5+
using CSparse.Storage;
46
using NUnit.Framework;
57
using System;
68

@@ -33,5 +35,46 @@ public void TestGenerate2()
3335

3436
Assert.That(dm.StructuralRank == n, Is.True);
3537
}
38+
39+
[Test]
40+
public void TestGenerate3()
41+
{
42+
var A = SparseMatrix.OfRowMajor(8, 8,
43+
[
44+
11, 12, 0, 0, 0, 0, 0, 0,
45+
0, 22, 23, 0, 25, 26, 0, 0,
46+
0, 0, 33, 34, 0, 0, 37, 0,
47+
0, 0, 43, 44, 0, 0, 0, 48,
48+
51, 0, 0, 0, 55, 56, 0, 0,
49+
0, 0, 0, 0, 0, 66, 67, 0,
50+
0, 0, 0, 0, 0, 76, 77, 0,
51+
0, 0, 0, 84, 0, 0, 87, 88
52+
]);
53+
54+
var S = SymbolicColumnStorage.Create(A);
55+
56+
var dm = DulmageMendelsohn.Generate(S, 1);
57+
58+
Assert.That(dm.StructuralRank, Is.EqualTo(8));
59+
Assert.That(dm.Blocks, Is.EqualTo(3));
60+
61+
int[] expected = [0, 1, 4, 2, 3, 7, 5, 6];
62+
63+
Assert.That(dm.RowPermutation, Is.EqualTo(expected).AsCollection);
64+
Assert.That(dm.ColumnPermutation, Is.EqualTo(expected).AsCollection);
65+
66+
expected = [0, 3, 6, 8];
67+
68+
Assert.That(dm.BlockRowPointers, Is.EqualTo(expected).AsCollection);
69+
Assert.That(dm.BlockColumnPointers, Is.EqualTo(expected).AsCollection);
70+
71+
expected = [0, 0, 8, 8, 8];
72+
73+
Assert.That(dm.CoarseRowDecomposition, Is.EqualTo(expected).AsCollection);
74+
75+
expected = [0, 0, 0, 8, 8];
76+
77+
Assert.That(dm.CoarseColumnDecomposition, Is.EqualTo(expected).AsCollection);
78+
}
3679
}
3780
}

CSparse/Ordering/AMD.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@ public static class AMD
2525
/// </remarks>
2626
public static int[] Generate<T>(CompressedColumnStorage<T> A, ColumnOrdering order)
2727
where T : struct, IEquatable<T>, IFormattable
28+
{
29+
return Generate(SymbolicColumnStorage.Create(A), order);
30+
}
31+
32+
/// <summary>
33+
/// Generate minimum degree ordering of A+A' (if A is symmetric) or A'A.
34+
/// </summary>
35+
/// <param name="A">Column-compressed matrix</param>
36+
/// <param name="order">Column ordering method</param>
37+
/// <returns>amd(A+A') if A is symmetric, or amd(A'A) otherwise, null on
38+
/// error or for natural ordering</returns>
39+
/// <remarks>
40+
/// See Chapter 7.1 (Fill-reducing orderings: Minimum degree ordering) in
41+
/// "Direct Methods for Sparse Linear Systems" by Tim Davis.
42+
/// </remarks>
43+
public static int[] Generate(SymbolicColumnStorage A, ColumnOrdering order)
2844
{
2945
int[] Cp, Ci, P, W, nv, next, head, elen, degree, w, hhead;
3046

@@ -42,7 +58,7 @@ public static int[] Generate<T>(CompressedColumnStorage<T> A, ColumnOrdering ord
4258
return Permutation.Create(n);
4359
}
4460

45-
var C = ConstructMatrix(SymbolicColumnStorage.Create(A), order);
61+
var C = ConstructMatrix(A, order);
4662

4763
Cp = C.ColumnPointers;
4864
cnz = Cp[n];
@@ -139,7 +155,7 @@ public static int[] Generate<T>(CompressedColumnStorage<T> A, ColumnOrdering ord
139155
Ci[p] = -(j + 2); // first entry is now CS_FLIP(j)
140156
}
141157
}
142-
for (q = 0, p = 0; p < cnz; ) // scan all of memory
158+
for (q = 0, p = 0; p < cnz;) // scan all of memory
143159
{
144160
if ((j = FLIP(Ci[p++])) >= 0) // found object j
145161
{
@@ -303,7 +319,7 @@ public static int[] Generate<T>(CompressedColumnStorage<T> A, ColumnOrdering ord
303319
eln = elen[i];
304320
for (p = Cp[i] + 1; p <= Cp[i] + ln - 1; p++) w[Ci[p]] = mark;
305321
jlast = i;
306-
for (j = next[i]; j != -1; ) // compare i with all j
322+
for (j = next[i]; j != -1;) // compare i with all j
307323
{
308324
ok = (W[j] == ln) && (elen[j] == eln);
309325
for (p = Cp[j] + 1; ok && p <= Cp[j] + ln - 1; p++)
@@ -411,13 +427,13 @@ private static bool KeepOffDiag(int i, int j)
411427
private static SymbolicColumnStorage ConstructMatrix(SymbolicColumnStorage A, ColumnOrdering order)
412428
{
413429
SymbolicColumnStorage result = null;
414-
430+
415431
// Compute A'
416432
var AT = A.Transpose();
417433

418434
int m = A.RowCount;
419435
int n = A.ColumnCount;
420-
436+
421437
if (order == ColumnOrdering.MinimumDegreeAtPlusA)
422438
{
423439
if (n != m)
@@ -444,7 +460,7 @@ private static SymbolicColumnStorage ConstructMatrix(SymbolicColumnStorage A, Co
444460
{
445461
// Column j of AT starts here.
446462
p = colptr[j];
447-
463+
448464
// New column j starts here.
449465
colptr[j] = p2;
450466

CSparse/Ordering/DulmageMendelsohn.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public sealed class DulmageMendelsohn
2222
private int nb; // number of blocks in fine dmperm decomposition
2323

2424
/// <summary>
25-
/// Create a new Decomposition instance.
25+
/// Create a new decomposition instance.
2626
/// </summary>
2727
private DulmageMendelsohn(int m, int n)
2828
{
@@ -97,11 +97,10 @@ public int Singletons
9797
public int[] CoarseColumnDecomposition => cc;
9898

9999
/// <summary>
100-
/// Compute coarse and then fine Dulmage-Mendelsohn decomposition. seed
101-
/// optionally selects a randomized algorithm.
100+
/// Compute coarse and fine Dulmage-Mendelsohn decomposition.
102101
/// </summary>
103102
/// <param name="matrix">column-compressed matrix</param>
104-
/// <param name="seed">0: natural, -1: reverse, random order otherwise</param>
103+
/// <param name="seed"> The seed optionally selects a randomized algorithm (0 = default (natural), -1 = reverse, random order otherwise).</param>
105104
/// <returns>Dulmage-Mendelsohn analysis</returns>
106105
public static DulmageMendelsohn Generate<T>(CompressedColumnStorage<T> matrix, int seed = 0)
107106
where T : struct, IEquatable<T>, IFormattable
@@ -110,11 +109,10 @@ public static DulmageMendelsohn Generate<T>(CompressedColumnStorage<T> matrix, i
110109
}
111110

112111
/// <summary>
113-
/// Compute coarse and then fine Dulmage-Mendelsohn decomposition. seed
114-
/// optionally selects a randomized algorithm.
112+
/// Compute coarse and fine Dulmage-Mendelsohn decomposition.
115113
/// </summary>
116114
/// <param name="A">The matrix represented by <see cref="SymbolicColumnStorage"/>.</param>
117-
/// <param name="seed">0: natural, -1: reverse, random order otherwise</param>
115+
/// <param name="seed"> The seed optionally selects a randomized algorithm (0 = default (natural), -1 = reverse, random order otherwise).</param>
118116
/// <returns>Dulmage-Mendelsohn analysis</returns>
119117
public static DulmageMendelsohn Generate(SymbolicColumnStorage A, int seed = 0)
120118
{

CSparse/Storage/SymbolicColumnStorage.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ public SymbolicColumnStorage(int rowCount, int columnCount, int[] columnPointers
9494

9595
if (columnPointers.Length < columnCount + 1)
9696
{
97-
throw new ArgumentOutOfRangeException("Column pointers array size don't match given column count argument.");
97+
throw new ArgumentOutOfRangeException(nameof(columnPointers), "Column pointers array size doesn't match given column count argument.");
9898
}
9999

100100
if (rowIndices.Length < columnPointers[columnCount])
101101
{
102-
throw new ArgumentOutOfRangeException("Row indices array size don't match non-zeros count.");
102+
throw new ArgumentOutOfRangeException(nameof(rowIndices), "Row indices array size doesn't match non-zeros count.");
103103
}
104104

105105
this.rowCount = rowCount;
@@ -187,13 +187,16 @@ public void Sort()
187187
}
188188
}
189189

190+
/// <summary>
191+
/// Returns a copy of the <see cref="SymbolicColumnStorage"/>.
192+
/// </summary>
193+
/// <returns></returns>
190194
public SymbolicColumnStorage Clone()
191195
{
192-
int m = RowCount;
193196
int n = ColumnCount;
194197
int nnz = NonZerosCount;
195198

196-
var result = new SymbolicColumnStorage(m, n, nnz, true);
199+
var result = new SymbolicColumnStorage(RowCount, n, nnz, true);
197200

198201
Buffer.BlockCopy(ColumnPointers, 0, result.ColumnPointers, 0, (n + 1) * Constants.SizeOfInt);
199202
Buffer.BlockCopy(RowIndices, 0, result.RowIndices, 0, nnz * Constants.SizeOfInt);

0 commit comments

Comments
 (0)