[R] Re : Generate a random bistochastic matrix

Martin Maechler maechler at stat.math.ethz.ch
Tue Oct 17 21:30:47 CEST 2006


Thank you, Ravi,

>>>>> "Ravi" == Ravi Varadhan <rvaradhan at jhmi.edu>
>>>>>     on Mon, 16 Oct 2006 18:54:16 -0400 writes:

    Ravi> Martin, I don't think that a doubly stochastic matrix
    Ravi> can be obtained from an arbitrary positive rectangular
    Ravi> matrix.  There is a theorem by Sinkhorn (Am Math Month
    Ravi> 1967) on the diagonal equivalence of matrices with
    Ravi> prescribed row and column sums.  It shows that given a
    Ravi> positive matrix A(m x n), there is a unique matrix DAE
    Ravi> (where D and E are m x m and n x n diagonal matrices)
    Ravi> with rows, k*r_i (i = 1, ..., m), and column sums, c_j
    Ravi> (j=1,...,n) such that k = \sum_j c_j / \sum_i r_i.
    Ravi> Therefore, the alternative row and column
    Ravi> normalization algorithm (same as the iterative
    Ravi> proportional fitting algorithm for contingency tables)
    Ravi> will alternate between row and column sums being
    Ravi> unity, while the other sum alternates between k and
    Ravi> 1/k.

    Ravi> Here is a slight modification of your algorithm for
    Ravi> the rectangular case:


    Ravi> bistochMat.rect <- function(m,n, tol = 1e-7, maxit = 1000) {
    Ravi> ## Purpose: Random bistochastic *square* matrix (M_{ij}):
    Ravi> ##	        M_{ij} >= 0;  sum_i M_{ij} = sum_j M_{ij} = 1   (for all i,
    Ravi> j)
    Ravi> ##
    Ravi> ----------------------------------------------------------------------
    Ravi> ## Arguments: n: (n * n) matrix dimension;
    Ravi> ##
    Ravi> ----------------------------------------------------------------------
    Ravi> ## Author: Martin Maechler, Date: 16 Oct 2006, 14:47
    Ravi> stopifnot(maxit >= 1, tol >= 0)
    Ravi> M <- matrix(runif(m*n), m,n)
    Ravi> for(i in 1:maxit) {
    Ravi> rM <- rowSum(M)
    Ravi> M <- M / rep((rM),n)
    Ravi> cM <- colSum(M)
    Ravi> M <- M / rep((cM),each=m)
    Ravi> if(all(abs(c(rM,cM) - 1) < tol))
    Ravi> break
    Ravi> }
    Ravi> ## cat("needed", i, "iterations\n")
    Ravi> ## or rather
    Ravi> attr(M, "iter") <- i
    Ravi> M
    Ravi> }

    Ravi> Using this algorithm we get for an 8 x 4 matrix, for example, we get:

    >> M <- bistochMat.rect(8,4)
    >> apply(M,1,sum)
    Ravi> [1] 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5
    >> apply(M,2,sum)
    Ravi> [1] 1 1 1 1

"Of course" I had tried that too, before I posted and limited
the problem to square matrices.

    Ravi> Clearly the algorithm didn't converge according to
    Ravi> your convergence criterion, but the row sums oscillate
    Ravi> between 1 and 0.5, and the column sums oscillate
    Ravi> between 2 and 1, respectively.

indeed, and I had tried similar examples.

The interesting thing is really the theorem you mention
a consequence of which seems to be that indeed, simple row and
column scaling iterations would not converge.

Intuitively, I'd still expect that relatively simple
modification of the algorithm should lead to convergence.

Your following statement seems to indicate so,
or do I misunderstand its consequences?

    Ravi> It is interesting to note that the above algorithm
    Ravi> converges if we use the infinity norm, instead of the
    Ravi> 1-norm, to scale the rows and columns, i.e. we divide
    Ravi> rows and columns by their maxima.



More information about the R-help mailing list