Class Hierarchies and Method Organization For Matrices
Class Hierarchies and Method Organization For Matrices
Martin Maechler
ETH Zurich
Switzerland
[email protected]
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 1 / 30
Outline
1 Preliminaries
5 Conclusions
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 2 / 30
Acknowledgements
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 3 / 30
Preliminaries
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 4 / 30
Goals of Matrix package
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 5 / 30
many Matrix classes . . .
> length(allCl <- getClasses("package:Matrix"))
[1] 89
[1] 70
i.e., many . . . , each inheriting from root class ”Matrix”
> str(subs <- showExtends(getClassDef("Matrix")@subclasses,
+ printTo=FALSE))
List of 2
$ what: chr [1:76] "compMatrix" "triangularMatrix" "dMatrix" "iMatr
$ how : chr [1:76] "directly" "directly" "directly" "directly" ...
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 7 / 30
3-way Partitioning of Matrix space — 2
First two schemes: a slight generalization from lapack for dense matrices.
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 8 / 30
3D space of Matrix classes
three-way partitioning of Matrix classes visualized in 3D space, dropping
the final Matrix, e.g., "d" instead of "dMatrix":
> d1 <- c("d", "l", "n")
> d2 <- c("general", "symmetric", "triangular", "diagonal")
> d3 <- c("dense", c("Csparse", "Tsparse", "Rsparse"))
> clGrid <- expand.grid(dim1 = d1, dim2 = d2, dim3 = d3,
+ KEEP.OUT.ATTRS = FALSE)
> clGr <- data.matrix(clGrid)
> library(scatterplot3d)
used for visualization:
● ● ●
● ● ●
● ● ●
● ● ●
Rsparse ● ●
●
●
● ●
● ● ●
● ● ●
Tsparse ● ●
●
●
● ●
dim3
dim2
diagonal
● ● ●
● ● ●
Csparse ● ●
●
●
triangular
●
● ● ●
symmetric
dense ● ● ●
general
d l n
dim1
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 9 / 30
3D space of Matrix classes
● ● ●
● ● ●
● ● ●
● ● ●
Rsparse ● ●
●
●
● ●
● ● ●
● ● ●
Tsparse ● ●
●
●
● ●
dim3
dim2
diagonal
● ● ●
● ● ●
Csparse ● ●
●
●
triangular
●
● ●
symmetric
●
dense ● ● ●
general
d l n
dim1
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 10 / 30
3-fold classification — Matrix naming scheme
1 “Factual” classes: Matrix objects are of those; the above “points in
3D space”
2 Virtual classes: e.g. the above coordinate axes categories.
● ● ●
● ● ●
● ● ●
● ● ●
Rsparse ● ●
●
●
● ●
● ● ●
● ● ●
Tsparse ● ●
●
●
● ●
dim3
dim2
diagonal
● ● ●
● ● ●
Csparse ● ●
●
●
triangular
●
● ●
symmetric
●
dense ● ● ●
general
d l n
dim1
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 12 / 30
Matrix 3d space: filled (2)
● ● ●
dtR ● ● ●
dsR
● ●
●
●
● ●
Rsparse dgR
●
dtT
●
●
●
● ●
dsT
● ●
●
●
● ●
Tsparse dgT
●
dtC
●
●
●
● ●
dim3
dim2
dsC
●
ddi
●
●
●
diagonal
●
Csparse dgC
●
dtp
dtr
●
●
●
triangular
●
dsy
dpo
dpp
dsp
● ●
symmetric
●
dense dge
● ● ●
general
d l n
dim1
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 13 / 30
Matrix 3d space: filled (3)
● ● ●
dtR ●
ltR ● ●
dsR
●
lsR
●
●
●
● ●
Rsparse dgR
●
lgR
●
dtT●
●
ltT
● ●
dsT
●
lsT
●
●
●
● ●
Tsparse dgT
●
lgT
●
dtC●
ltC
●
● ●
dim3
dim2
dsC
●
lsC
ddi
●
●
●
ldi
●
diagonal
●
Csparse dgC
●
lgC
●
dtp
dtr●
●
ltp
ltr
●
triangular
●
dsy
dpo
dpp
dsp
●
lsy
lsp
● ●
symmetric
dense dge
●
lge
● ●
general
d l n
dim1
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 14 / 30
Matrix 3d space: filled (4)
● ● ●
dtR ●
ltR ●
ntR
●
dsR
●
lsR
●
● nsR
●
● ●
Rsparse dgR
●
lgR
●
dtT● ngR
ltT
●
ntT
●
dsT
●
lsT
●
● nsT
●
● ●
Tsparse dgT
●
lgT
●
dtC● ngT
ltC
●
ntC
●
dim3
dim2
dsC
●
lsC
ddi
●
● nsC
ldi
●
diagonal
● ●
Csparse dgC
●
lgC
●
dtp
dtr● ngC
ltp
ltr
●
triangular ntp
ntr
●
dsy
dpo
dpp
dsp
●
lsy
lsp
●
nsy symmetric
nsp ●
dense dge
●
lge
●
nge general
●
d l n
dim1
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 15 / 30
Matrix classes – 3 fold inheritance tree
Matrix
diagonal* ddense* ldense* ndense* triangular* symmetric* dsparse* Csparse* lsparse* Tsparse* general* Rsparse* nsparse*
ddi* ldi* dtp* dtr* dsy* dsp* ltr* dge* ltp* ntr* lsy* lsp* ntp* nsy* nsp* dtC* dsC* lge* nge* ltC* dtT* dtR* lsC* dsT* ltT* dsR* ntC* lsT* dgC* ltR* nsC* lsR* lgC* ntT* nsT* dgT* lgT* dgR* ngC* lgR* ngT* ntR* nsR* ngR* p*
cor*
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 16 / 30
Subgraph of Full inheritence graph
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 17 / 30
Subgraph of Full inheritence graph
Matrix
dense* d* l* n* sparse* i* z*
dge* dsy* dsp* dtr* dtp* ddi* lge* lsy* lsp* ltr* ltp* ldi* ntp* nge* nsy* nsp* ntr* dgT* dtT* dsT* dtR* dsR* dgR* lsT* ltT* lgT* dtC* dsC* dgC* nsT* lsR* ltR* lgR* ngT* ntT* ntR* nsR* ngR* lgC* lsC* ltC* nsC* ngC* ntC*
cor*
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 18 / 30
Top 2 levels of hierarchy — distance-wise
> defMatrix <- getClassDef("Matrix")
> ## Distances of subclasses:
> table(subDist <- sapply(defMatrix@subclasses, slot, "distance"))
1 2 3 4 5
9 16 44 6 1
> sub12 <- defMatrix@subclasses[subDist <= 2] # but not unique!
Matrix
> trM_top12 <- subGraph(c("Matrix", unique(names(sub12))), trMatrix)
> plotRag(mRagraph(trM_top12)) ## first and second level virtual cla
Rsparse* Tsparse* Csparse* dsparse* lsparse* nsparse* general* ddense* symmetric* ldense* ndense* diagonal*
Matrix
Rsparse* Tsparse* Csparse* dsparse* lsparse* nsparse* general* ddense* symmetric* ldense* ndense* diagonal*
p*
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 20 / 30
Top 2 levels of sparse sub-hierarchy:
'sparseMatrix' classes −− sub graph
35 nodes with 61 edges
sparse*
dgT* dtT* dsT* dgC* dtC* dsC* dgR* dtR* dsR* lgT* ltT* lsT* ngT* ntT* nsT* lgC* ltC* lsC* lgR* ltR* lsR* ngC* ntC* nsC* ngR* ntR* nsR*
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 21 / 30
Top 2 levels of hierarchy:
'sparseMatrix' classes −− in "neato" layout
35 nodes with 61 edges
ltR* lsR*
lgR*
lsC*
lgC* ltC* lsparse*
dgR* Rsparse*
dtR*
dsR* ntR*
lsT* ngR*
dgC* Csparse* lgT* nsR*
sparse* ltT*
dsC* dsparse* ntC*
dtC* nsparse*
nsC* ngC* Tsparse*
dgT* ngT*
dsT*dtT* p* nsT*
ntT*
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 22 / 30
Methods for Matrix classes
generic for n matrix classes, namely for each possible pair of matrix
classes, but define methods for “high-level virtual super classes”
3 the higher the better (less pairwise combinations)
4 the higher the worse (the less specific, the less OO)
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 23 / 30
Methods for “high-level” super classes
Typically want methods defined for high-level (i.e. high-up) super classes
one “bail-out” method for the mother class "Matrix", e.g., for the
expand() generic:
expand( Cholesky(crossprod(A)) )
Error: not-yet-implemented method for expand(<dCHMsimpl>).
->> Ask the package authors to implement the missing feature.
implementation - often “via”
method for one or a few specific classes, e.g., "dgeMatrix",
general method then may be as simple as
function(x) { x <- as(x, "dgeMatrix"); callGeneric() }
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 24 / 30
Methods for super classes
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 25 / 30
Methods for super classes – dispatch ambiguities
Have multiple inheritance, every object inheriting one “branch” from the
3-fold hierarchy.
> (lmat <- 1 == crossprod(Matrix(c(0,2,0,0:1,0), 4,3)))
3 x 3 sparse Matrix of class "lsCMatrix"
[1,] . . .
[2,] . . .
[3,] . . |
Warning messages:
1: Ambiguous method selection for "==", target "numeric#dsCMatrix" (
numeric#dMatrix
numeric#sparseMatrix
in: .findInheritedMethods(classes, fdef, mtable)
2: Ambiguous method selection for "==", target "dsCMatrix#numeric" (
dMatrix#numeric
sparseMatrix#numeric
in: .findInheritedMethods(classes, fdef, mtable)
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 26 / 30
Methods for super classes – dispatch ambiguities
sparse* d* comp*
dsC*
Hence often more than one path “up” the inheritance graph. JMC’s “How
S4 Methods Work” introduces (integer) distances by counting the total
number of edges needed to go backwards, and thus neatly disambiguates
method dispatch – in some cases only:
Here, sparse* (= sparseMatrix) and d* (= dMatrix)
both have distance 2 from dsC* −→ unnecessary warning.
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 27 / 30
Propsal: Customizable method dispatch
RFC: Instead of counting edges, i.e., adding edges with weights 1, allow
to edge weights to be specified, e.g., in the setClass(*, contains=
...) statements.
Your idea on this ?
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 28 / 30
Propsal: Customizable method dispatch
RFC: Instead of counting edges, i.e., adding edges with weights 1, allow
to edge weights to be specified, e.g., in the setClass(*, contains=
...) statements.
Your idea on this ?
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 28 / 30
Propsal: Customizable method dispatch
RFC: Instead of counting edges, i.e., adding edges with weights 1, allow
to edge weights to be specified, e.g., in the setClass(*, contains=
...) statements.
Your idea on this ?
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 28 / 30
Systematic Testing of multi-argument Methods
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 29 / 30
Messages to take home
Martin Maechler (ETH Zurich) Class Hierarchies etc. . . for Matrices DSC 2007 30 / 30