Esempio n. 1
0
void LDLSolve(scs_float *x, scs_float b[], cs * L, scs_float D[], scs_int P[], scs_float * bp) {
	/* solves PLDL'P' x = b for x */
	scs_int n = L->n;
	if (P == NULL) {
		if (x != b) /* if they're different addresses */
			memcpy(x, b, n * sizeof(scs_float));
		LDL_lsolve(n, x, L->p, L->i, L->x);
		LDL_dsolve(n, x, D);
		LDL_ltsolve(n, x, L->p, L->i, L->x);
	} else {
		LDL_perm(n, bp, b, P);
		LDL_lsolve(n, bp, L->p, L->i, L->x);
		LDL_dsolve(n, bp, D);
		LDL_ltsolve(n, bp, L->p, L->i, L->x);
		LDL_permt(n, x, bp, P);
	}
}
Esempio n. 2
0
int main (void)
#endif
{

    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

#ifdef USE_AMD
    double Info [AMD_INFO] ;
#endif
    double r, rnorm, flops, maxrnorm = 0. ;
    double *Ax, *Lx, *B, *D, *X, *Y ;
    LDL_int matrix, *Ai, *Ap, *Li, *Lp, *P, *Pinv, *Perm, *PermInv, n, i, j, p,
	nz, *Flag, *Pattern, *Lnz, *Parent, trial, lnz, d, jumbled ;
    FILE *f ;
    char s [LEN] ;

    /* ---------------------------------------------------------------------- */
    /* check the error-checking routines with null matrices */
    /* ---------------------------------------------------------------------- */

    i = 1 ;
    n = -1 ;
    if (LDL_valid_perm (n, (LDL_int *) NULL, &i)
	|| !LDL_valid_perm (0, (LDL_int *) NULL, &i)
	|| LDL_valid_matrix (n, (LDL_int *) NULL, (LDL_int *) NULL)
	|| LDL_valid_matrix (0, &i, &i))
    {
	printf (PROGRAM ": ldl error-checking routine failed\n") ;
	EXIT_ERROR ;
    }

    /* ---------------------------------------------------------------------- */
    /* read in a factorize a set of matrices */
    /* ---------------------------------------------------------------------- */

    for (matrix = 1 ; matrix <= NMATRICES ; matrix++)
    {

	/* ------------------------------------------------------------------ */
	/* read in the matrix and the permutation */
	/* ------------------------------------------------------------------ */

	sprintf (s, "../Matrix/A%02d", (int) matrix) ;
	if ((f = fopen (s, "r")) == (FILE *) NULL)
	{
	    printf (PROGRAM ": could not open file: %s\n", s) ;
	    EXIT_ERROR ;
	}
	fgets (s, LEN, f) ;
	printf ("\n\n--------------------------------------------------------");
	printf ("\nInput matrix: %s", s) ;
	printf ("--------------------------------------------------------\n\n");
	fscanf (f, LDL_ID " " LDL_ID, &n, &jumbled) ;
	n = (n < 0) ? (0) : (n) ;
	ALLOC_MEMORY (P, LDL_int, n) ;
	ALLOC_MEMORY (Ap, LDL_int, n+1) ;
	for (j = 0 ; j <= n ; j++)
	{
	    fscanf (f, LDL_ID, &Ap [j]) ;
	}
	nz = Ap [n] ;
	ALLOC_MEMORY (Ai, LDL_int, nz) ;
	ALLOC_MEMORY (Ax, double, nz) ;
	for (p = 0 ; p < nz ; p++)
	{
	    fscanf (f, LDL_ID , &Ai [p]) ;
	}
	for (p = 0 ; p < nz ; p++)
	{
	    fscanf (f, "%lg", &Ax [p]) ;
	}
	for (j = 0 ; j < n  ; j++)
	{
	    fscanf (f, LDL_ID , &P  [j]) ;
	}
	fclose (f) ;

	/* ------------------------------------------------------------------ */
	/* check the matrix A and the permutation P */
	/* ------------------------------------------------------------------ */

	ALLOC_MEMORY (Flag, LDL_int, n) ;

	/* To test the error-checking routines, some of the input matrices
	 * are not valid.  So this error is expected to occur. */
	if (!LDL_valid_matrix (n, Ap, Ai) || !LDL_valid_perm (n, P, Flag))
	{
	    printf (PROGRAM ": invalid matrix and/or permutation\n") ;
	    FREE_MEMORY (P, LDL_int) ;
	    FREE_MEMORY (Ap, LDL_int) ;
	    FREE_MEMORY (Ai, LDL_int) ;
	    FREE_MEMORY (Ax, double) ;
	    FREE_MEMORY (Flag, LDL_int) ;
	    continue ;
	}

	/* ------------------------------------------------------------------ */
	/* get the AMD permutation, if available */
	/* ------------------------------------------------------------------ */

#ifdef USE_AMD

	/* recompute the permutation with AMD */
	/* Assume that AMD produces a valid permutation P. */

#ifdef LDL_LONG

	if (amd_l_order (n, Ap, Ai, P, (double *) NULL, Info) < AMD_OK)
	{
	    printf (PROGRAM ": call to AMD failed\n") ;
	    EXIT_ERROR ;
	}
	amd_l_control ((double *) NULL) ;
	amd_l_info (Info) ;

#else

	if (amd_order (n, Ap, Ai, P, (double *) NULL, Info) < AMD_OK)
	{
	    printf (PROGRAM ": call to AMD failed\n") ;
	    EXIT_ERROR ;
	}
	amd_control ((double *) NULL) ;
	amd_info (Info) ;

#endif
#endif

	/* ------------------------------------------------------------------ */
	/* allocate workspace and the first part of LDL factorization */
	/* ------------------------------------------------------------------ */

	ALLOC_MEMORY (Pinv, LDL_int, n) ;
	ALLOC_MEMORY (Y, double, n) ;
	ALLOC_MEMORY (Pattern, LDL_int, n) ;
	ALLOC_MEMORY (Lnz, LDL_int, n) ;
	ALLOC_MEMORY (Lp, LDL_int, n+1) ;
	ALLOC_MEMORY (Parent, LDL_int, n) ;
	ALLOC_MEMORY (D, double, n) ;
	ALLOC_MEMORY (B, double, n) ;
	ALLOC_MEMORY (X, double, n) ;

	/* ------------------------------------------------------------------ */
	/* factorize twice, with and without permutation */
	/* ------------------------------------------------------------------ */

	for (trial = 1 ; trial <= 2 ; trial++)
	{

	    if (trial == 1)
	    {
		printf ("Factorize PAP'=LDL' and solve Ax=b\n") ;
		Perm = P ;
		PermInv = Pinv ;
	    }
	    else
	    {
		printf ("Factorize A=LDL' and solve Ax=b\n") ;
		Perm = (LDL_int *) NULL ;
		PermInv = (LDL_int *) NULL ;
	    }

	    /* -------------------------------------------------------------- */
	    /* symbolic factorization to get Lp, Parent, Lnz, and Pinv */
	    /* -------------------------------------------------------------- */

	    LDL_symbolic (n, Ap, Ai, Lp, Parent, Lnz, Flag, Perm, PermInv) ;
	    lnz = Lp [n] ;

	    /* find # of nonzeros in L, and flop count for LDL_numeric */
	    flops = 0 ;
	    for (j = 0 ; j < n ; j++)
	    {
		flops += ((double) Lnz [j]) * (Lnz [j] + 2) ;
	    }
	    printf ("Nz in L: "LDL_ID"  Flop count: %g\n", lnz, flops) ;

	    /* -------------------------------------------------------------- */
	    /* allocate remainder of L, of size lnz */
	    /* -------------------------------------------------------------- */

	    ALLOC_MEMORY (Li, LDL_int, lnz) ;
	    ALLOC_MEMORY (Lx, double, lnz) ;

	    /* -------------------------------------------------------------- */
	    /* numeric factorization to get Li, Lx, and D */
	    /* -------------------------------------------------------------- */

	    d = LDL_numeric (n, Ap, Ai, Ax, Lp, Parent, Lnz, Li, Lx, D,
		Y, Flag, Pattern, Perm, PermInv) ;

	    /* -------------------------------------------------------------- */
	    /* solve, or report singular case */
	    /* -------------------------------------------------------------- */

	    if (d != n)
	    {
		printf ("Ax=b not solved since D("LDL_ID","LDL_ID") is zero.\n", d, d) ;
	    }
	    else
	    {
		/* construct the right-hand-side, B */
		for (i = 0 ; i < n ; i++)
		{
		    B [i] = 1 + ((double) i) / 100 ;
		}

		/* solve Ax=b */
		if (trial == 1)
		{
		    /* the factorization is LDL' = PAP' */
		    LDL_perm (n, Y, B, P) ;			/* y = Pb */
		    LDL_lsolve (n, Y, Lp, Li, Lx) ;		/* y = L\y */
		    LDL_dsolve (n, Y, D) ;			/* y = D\y */
		    LDL_ltsolve (n, Y, Lp, Li, Lx) ;		/* y = L'\y */
		    LDL_permt (n, X, Y, P) ;			/* x = P'y */
		}
		else
		{
		    /* the factorization is LDL' = A */
		    for (i = 0 ; i < n ; i++)			/* x = b */
		    {
			X [i] = B [i] ;
		    }
		    LDL_lsolve (n, X, Lp, Li, Lx) ;		/* x = L\x */
		    LDL_dsolve (n, X, D) ;			/* x = D\x */
		    LDL_ltsolve (n, X, Lp, Li, Lx) ;		/* x = L'\x */
		}

		/* compute the residual y = Ax-b */
		/* note that this code can tolerate a jumbled matrix */
		for (i = 0 ; i < n ; i++)
		{
		    Y [i] = -B [i] ;
		}
		for (j = 0 ; j < n ; j++)
		{
		    for (p = Ap [j] ; p < Ap [j+1] ; p++)
		    {
			Y [Ai [p]] += Ax [p] * X [j] ;
		    }
		}
		/* rnorm = norm (y, inf) */
		rnorm = 0 ;
		for (i = 0 ; i < n ; i++)
		{
		    r = (Y [i] > 0) ? (Y [i]) : (-Y [i]) ;
		    rnorm = (r > rnorm) ? (r) : (rnorm) ;
		}
		maxrnorm = (rnorm > maxrnorm) ? (rnorm) : (maxrnorm) ;
		printf ("relative maxnorm of residual: %g\n", rnorm) ;
	    }

	    /* -------------------------------------------------------------- */
	    /* free the size-lnz part of L */
	    /* -------------------------------------------------------------- */

	    FREE_MEMORY (Li, LDL_int) ;
	    FREE_MEMORY (Lx, double) ;

	}

	/* free everything */
	FREE_MEMORY (P, LDL_int) ;
	FREE_MEMORY (Ap, LDL_int) ;
	FREE_MEMORY (Ai, LDL_int) ;
	FREE_MEMORY (Ax, double) ;
	FREE_MEMORY (Pinv, LDL_int) ;
	FREE_MEMORY (Y, double) ;
	FREE_MEMORY (Flag, LDL_int) ;
	FREE_MEMORY (Pattern, LDL_int) ;
	FREE_MEMORY (Lnz, LDL_int) ;
	FREE_MEMORY (Lp, LDL_int) ;
	FREE_MEMORY (Parent, LDL_int) ;
	FREE_MEMORY (D, double) ;
	FREE_MEMORY (B, double) ;
	FREE_MEMORY (X, double) ;
    }

    printf ("\nLargest residual during all tests: %g\n", maxrnorm) ;
    if (maxrnorm < 1e-8)
    {
	printf ("\n" PROGRAM ": all tests passed\n") ;
	EXIT_OK ;
    }
    else
    {
	printf ("\n" PROGRAM ": one more tests failed (residual too high)\n") ;
	EXIT_ERROR ;
    }
}
Esempio n. 3
0
/**
 * Solves the permuted KKT system and returns the unpermuted search directions.
 *
 * On entry, the factorization of the permuted KKT matrix, PKPt,
 * is assumed to be up to date (call kkt_factor beforehand to achieve this).
 * The right hand side, Pb, is assumed to be already permuted.
 *
 * On exit, the resulting search directions are written into dx, dy and dz,
 * where these variables are permuted back to the original ordering.
 *
 * KKT->nitref iterative refinement steps are applied to solve the linear system.
 *
 * Returns the number of iterative refinement steps really taken.
 */
idxint kkt_solve(kkt* KKT, spmat* A, spmat* G, pfloat* Pb, pfloat* dx, pfloat* dy, pfloat* dz, idxint n, idxint p, idxint m, cone* C, idxint isinit, idxint nitref)
{
	
#if CONEMODE == 0
#define MTILDE (m+2*C->nsoc)
#else
#define MTILDE (m)
#endif
    
    idxint i, k, l, j, kk, kItRef;
#if (defined STATICREG) && (STATICREG > 0)
	idxint dzoffset;
#endif
	idxint*  Pinv = KKT->Pinv;
	pfloat*    Px = KKT->work1;
	pfloat*   dPx = KKT->work2;
	pfloat*     e = KKT->work3;
    pfloat*    Pe = KKT->work4;
    pfloat* truez = KKT->work5;
    pfloat*   Gdx = KKT->work6;
    pfloat* ex = e;
    pfloat* ey = e + n;
    pfloat* ez = e + n+p;
    pfloat bnorm = 1.0 + norminf(Pb, n+p+MTILDE);
    pfloat nex = 0;
    pfloat ney = 0;
    pfloat nez = 0;
    pfloat nerr;
    pfloat nerr_prev;
    pfloat error_threshold = bnorm*LINSYSACC;
    idxint nK = KKT->PKPt->n;

	/* forward - diagonal - backward solves: Px holds solution */
	LDL_lsolve2(nK, Pb, KKT->L->jc, KKT->L->ir, KKT->L->pr, Px );		
	LDL_dsolve(nK, Px, KKT->D);
	LDL_ltsolve(nK, Px, KKT->L->jc, KKT->L->ir, KKT->L->pr);
    
#if PRINTLEVEL > 2
    if( p > 0 ){
        PRINTTEXT("\nIR: it  ||ex||   ||ey||   ||ez|| (threshold: %4.2e)\n", error_threshold);
        PRINTTEXT("    --------------------------------------------------\n");
    } else {
        PRINTTEXT("\nIR: it  ||ex||   ||ez|| (threshold: %4.2e)\n", error_threshold);
        PRINTTEXT("    -----------------------------------------\n");
    }
#endif
    
	/* iterative refinement */
	for( kItRef=0; kItRef <= nitref; kItRef++ ){
        
        /* unpermute x & copy into arrays */
        unstretch(n, p, C, Pinv, Px, dx, dy, dz);
        
		/* compute error term */
        k=0; j=0;
        
		/* 1. error on dx*/
#if (defined STATICREG) && (STATICREG > 0)
		/* ex = bx - A'*dy - G'*dz - DELTASTAT*dx */
        for( i=0; i<n; i++ ){ ex[i] = Pb[Pinv[k++]] - DELTASTAT*dx[i]; }
#else
		/* ex = bx - A'*dy - G'*dz */
		for( i=0; i<n; i++ ){ ex[i] = Pb[Pinv[k++]]; }
#endif
        if(A) sparseMtVm(A, dy, ex, 0, 0);
        sparseMtVm(G, dz, ex, 0, 0);
        nex = norminf(ex,n);
        	
        /* error on dy */
        if( p > 0 ){
#if (defined STATICREG) && (STATICREG > 0)
			/* ey = by - A*dx + DELTASTAT*dy */
            for( i=0; i<p; i++ ){ ey[i] = Pb[Pinv[k++]] + DELTASTAT*dy[i]; }
#else
			/* ey = by - A*dx */
			for( i=0; i<p; i++ ){ ey[i] = Pb[Pinv[k++]]; }
#endif
            sparseMV(A, dx, ey, -1, 0);
            ney = norminf(ey,p);            
        }
        
        
		/* --> 3. ez = bz - G*dx + V*dz_true */
        kk = 0; j=0; 
#if (defined STATICREG) && (STATICREG > 0)		
		dzoffset=0;
#endif
        sparseMV(G, dx, Gdx, 1, 1);
        for( i=0; i<C->lpc->p; i++ ){
#if (defined STATICREG) && (STATICREG > 0)
            ez[kk++] = Pb[Pinv[k++]] - Gdx[j++] + DELTASTAT*dz[dzoffset++];
#else
			ez[kk++] = Pb[Pinv[k++]] - Gdx[j++];
#endif
        }
        for( l=0; l<C->nsoc; l++ ){
            for( i=0; i<C->soc[l].p; i++ ){
#if (defined STATICREG) && (STATICREG > 0) 				
                ez[kk++] = i<(C->soc[l].p-1) ? Pb[Pinv[k++]] - Gdx[j++] + DELTASTAT*dz[dzoffset++] : Pb[Pinv[k++]] - Gdx[j++] - DELTASTAT*dz[dzoffset++];
#else
				ez[kk++] = Pb[Pinv[k++]] - Gdx[j++];
#endif
            }
#if CONEMODE == 0
            ez[kk] = 0;
            ez[kk+1] = 0;
            k += 2;
            kk += 2;
#endif
        }
        for( i=0; i<MTILDE; i++) { truez[i] = Px[Pinv[n+p+i]]; }
        if( isinit == 0 ){
            scale2add(truez, ez, C);
        } else {
            vadd(MTILDE, truez, ez);
        }
        nez = norminf(ez,MTILDE);
        
        
#if PRINTLEVEL > 2
        if( p > 0 ){
            PRINTTEXT("    %2d  %3.1e  %3.1e  %3.1e\n", (int)kItRef, nex, ney, nez);
        } else {
            PRINTTEXT("    %2d  %3.1e  %3.1e\n", (int)kItRef, nex, nez);
        }
#endif
        
        /* maximum error (infinity norm of e) */
        nerr = MAX( nex, nez);
        if( p > 0 ){ nerr = MAX( nerr, ney ); }
        
        /* CHECK WHETHER REFINEMENT BROUGHT DECREASE - if not undo and quit! */
        if( kItRef > 0 && nerr > nerr_prev ){
            /* undo refinement */
            for( i=0; i<nK; i++ ){ Px[i] -= dPx[i]; }
            kItRef--;
            break;
        }
        
        /* CHECK WHETHER TO REFINE AGAIN */
        if( kItRef == nitref || ( nerr < error_threshold ) || ( kItRef > 0 && nerr_prev < IRERRFACT*nerr ) ){
            break;
        }
        nerr_prev = nerr;
        
        /* permute */
        for( i=0; i<nK; i++) { Pe[Pinv[i]] = e[i]; }
        
        /* forward - diagonal - backward solves: dPx holds solution */
        LDL_lsolve2(nK, Pe, KKT->L->jc, KKT->L->ir, KKT->L->pr, dPx);
        LDL_dsolve(nK, dPx, KKT->D);
        LDL_ltsolve(nK, dPx, KKT->L->jc, KKT->L->ir, KKT->L->pr);
        
        /* add refinement to Px */
        for( i=0; i<nK; i++ ){ Px[i] += dPx[i]; }
	}

#if PRINTLEVEL > 2
    PRINTTEXT("\n");
#endif
    
	/* copy solution out into the different arrays, permutation included */
	unstretch(n, p, C, Pinv, Px, dx, dy, dz);
    
    return kItRef;
}