Example #1
0
def qrp(A, rank = None, extra_prec = 16):
    m = A.nrows()
    n = A.ncols()
    s = min(m,n)
    if rank is not None:
        #s = min(s, rank + 1);
        pass;
    base_prec = A.base_ring().precision();
    base_field = A.base_ring()
    if is_ComplexField(base_field):
        field = ComplexField(base_prec + extra_prec + m);
    else:
        field = RealField(base_prec + extra_prec + m);
#    field = base_field; 
    R = copy(A);
    A = A.change_ring(field);
    P = [ j for j in xrange(n) ];
    Q = identity_matrix(field,m)
#    print A.base_ring()
#    print Q.base_ring()
    
    normbound = field(2)**(-0.5*field.precision());

    colnorms2 = [ float_sum([ R[k,j].norm() for k in range(m)]) for j in range(n) ];
    for j in xrange(s):
        # find column with max norm
        maxnorm2 = colnorms2[j];
        p = j;
        for k in xrange(j, n):
            if colnorms2[k] > maxnorm2:
                p = k;
                maxnorm2 = colnorms2[k];     
        #it is worth it to recompute the maxnorm                
        xnorm2 = float_sum([ R[i,p].norm() for i in range(j, m)])                
        xnorm = sqrt(xnorm2);
        # swap j and p in A, P and colnorms
        if j != p:
            P[j], P[p] = P[p], P[j]
            colnorms2[j], colnorms2[p] = colnorms2[p], colnorms2[j]
            for i in xrange(0, m):
                R[i, j], R[i, p] = R[i, p], R[i, j];
        
        # compute householder vector
        u = [ R[k,j] for k in xrange(j, m) ];
        alpha = R[j,j];
        # alphanorm = alpha.abs();
        if alpha.real() < 0:
            u[0] -= xnorm
            z = -1
        else:
            u[0] += xnorm
            z = 1
            

        
        beta = xnorm*(xnorm + alpha * z); 
        if beta.abs() < normbound:
            beta = float_sum( [u[i].conjugate() * R[i+j,j] for i in range(m - j)]) 
        if beta == field(0):
            break;
        beta = 1/beta;
        
        # H = I - beta * u * u^*
        # Apply householder matrix
        #update R
        R[j,j] = -z * xnorm;
        for i in xrange(j+1,m):
            R[i,j] = 0
        for k in xrange(j+1, n):
            lambdR = beta * float_sum( [u[l - j].conjugate() * R[l, k] for l in xrange(j, m)] );
            for i in xrange(j, m):
                R[i, k] -= lambdR * u[i - j];
        
        #update Q
        for k in xrange(m):
            lambdQ = float_sum( [u[l - j].conjugate() * Q[l, k] for l in xrange(j, m)] );
            lambdQ *= beta
            for i in xrange(j,m):
                Q[i, k] -= lambdQ * u[i - j];
        
        for k in xrange(j + 1, n):
            square = R[j,k].norm();
            colnorms2[k] -= square;
            # sometimes is better to just recompute the norm
            if True: #colnorms2[k] < normbound or colnorms2[k] < square*normbound:
                colnorms2[k] = float_sum([ R[i,k].norm() for i in range(j + 1, m)])                
    # compute P matrix
    Pmatrix = Matrix(ZZ, n);
    for i in xrange(n):
        Pmatrix[ P[i], i] = 1;

    return Q.conjugate_transpose().change_ring(base_field), R.change_ring(base_field), Pmatrix;