⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 colamd.c

📁 LU矩阵分解单机版最新版本
💻 C
📖 第 1 页 / 共 5 页
字号:
	Col [0].start = 0 ;	p [0] = Col [0].start ;	for (col = 1 ; col < n_col ; col++)	{	    /* note that the lengths here are for pruned columns, i.e. */	    /* no duplicate row indices will exist for these columns */	    Col [col].start = Col [col-1].start + Col [col-1].length ;	    p [col] = Col [col].start ;	}	/* === Re-create col form =========================================== */	for (row = 0 ; row < n_row ; row++)	{	    rp = &A [Row [row].start] ;	    rp_end = rp + Row [row].length ;	    while (rp < rp_end)	    {		A [(p [*rp++])++] = row ;	    }	}    }    /* === Done.  Matrix is not (or no longer) jumbled ====================== */    return (TRUE) ;}/* ========================================================================== *//* === init_scoring ========================================================= *//* ========================================================================== *//*    Kills dense or empty columns and rows, calculates an initial score for    each column, and places all columns in the degree lists.  Not user-callable.*/PRIVATE void init_scoring(    /* === Parameters ======================================================= */    int n_row,			/* number of rows of A */    int n_col,			/* number of columns of A */    Colamd_Row Row [],		/* of size n_row+1 */    Colamd_Col Col [],		/* of size n_col+1 */    int A [],			/* column form and row form of A */    int head [],		/* of size n_col+1 */    double knobs [COLAMD_KNOBS],/* parameters */    int *p_n_row2,		/* number of non-dense, non-empty rows */    int *p_n_col2,		/* number of non-dense, non-empty columns */    int *p_max_deg		/* maximum row degree */){    /* === Local variables ================================================== */    int c ;			/* a column index */    int r, row ;		/* a row index */    int *cp ;			/* a column pointer */    int deg ;			/* degree of a row or column */    int *cp_end ;		/* a pointer to the end of a column */    int *new_cp ;		/* new column pointer */    int col_length ;		/* length of pruned column */    int score ;			/* current column score */    int n_col2 ;		/* number of non-dense, non-empty columns */    int n_row2 ;		/* number of non-dense, non-empty rows */    int dense_row_count ;	/* remove rows with more entries than this */    int dense_col_count ;	/* remove cols with more entries than this */    int min_score ;		/* smallest column score */    int max_deg ;		/* maximum row degree */    int next_col ;		/* Used to add to degree list.*/#ifndef NDEBUG    int debug_count ;		/* debug only. */#endif /* NDEBUG */    /* === Extract knobs ==================================================== */    dense_row_count = MAX (0, MIN (knobs [COLAMD_DENSE_ROW] * n_col, n_col)) ;    dense_col_count = MAX (0, MIN (knobs [COLAMD_DENSE_COL] * n_row, n_row)) ;    DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;    max_deg = 0 ;    n_col2 = n_col ;    n_row2 = n_row ;    /* === Kill empty columns =============================================== */    /* Put the empty columns at the end in their natural order, so that LU */    /* factorization can proceed as far as possible. */    for (c = n_col-1 ; c >= 0 ; c--)    {	deg = Col [c].length ;	if (deg == 0)	{	    /* this is a empty column, kill and order it last */	    Col [c].shared2.order = --n_col2 ;	    KILL_PRINCIPAL_COL (c) ;	}    }    DEBUG1 (("colamd: null columns killed: %d\n", n_col - n_col2)) ;    /* === Kill dense columns =============================================== */    /* Put the dense columns at the end, in their natural order */    for (c = n_col-1 ; c >= 0 ; c--)    {	/* skip any dead columns */	if (COL_IS_DEAD (c))	{	    continue ;	}	deg = Col [c].length ;	if (deg > dense_col_count)	{	    /* this is a dense column, kill and order it last */	    Col [c].shared2.order = --n_col2 ;	    /* decrement the row degrees */	    cp = &A [Col [c].start] ;	    cp_end = cp + Col [c].length ;	    while (cp < cp_end)	    {		Row [*cp++].shared1.degree-- ;	    }	    KILL_PRINCIPAL_COL (c) ;	}    }    DEBUG1 (("colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ;    /* === Kill dense and empty rows ======================================== */    for (r = 0 ; r < n_row ; r++)    {	deg = Row [r].shared1.degree ;	ASSERT (deg >= 0 && deg <= n_col) ;	if (deg > dense_row_count || deg == 0)	{	    /* kill a dense or empty row */	    KILL_ROW (r) ;	    --n_row2 ;	}	else	{	    /* keep track of max degree of remaining rows */	    max_deg = MAX (max_deg, deg) ;	}    }    DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;    /* === Compute initial column scores ==================================== */    /* At this point the row degrees are accurate.  They reflect the number */    /* of "live" (non-dense) columns in each row.  No empty rows exist. */    /* Some "live" columns may contain only dead rows, however.  These are */    /* pruned in the code below. */    /* now find the initial matlab score for each column */    for (c = n_col-1 ; c >= 0 ; c--)    {	/* skip dead column */	if (COL_IS_DEAD (c))	{	    continue ;	}	score = 0 ;	cp = &A [Col [c].start] ;	new_cp = cp ;	cp_end = cp + Col [c].length ;	while (cp < cp_end)	{	    /* get a row */	    row = *cp++ ;	    /* skip if dead */	    if (ROW_IS_DEAD (row))	    {		continue ;	    }	    /* compact the column */	    *new_cp++ = row ;	    /* add row's external degree */	    score += Row [row].shared1.degree - 1 ;	    /* guard against integer overflow */	    score = MIN (score, n_col) ;	}	/* determine pruned column length */	col_length = (int) (new_cp - &A [Col [c].start]) ;	if (col_length == 0)	{	    /* a newly-made null column (all rows in this col are "dense" */	    /* and have already been killed) */	    DEBUG2 (("Newly null killed: %d\n", c)) ;	    Col [c].shared2.order = --n_col2 ;	    KILL_PRINCIPAL_COL (c) ;	}	else	{	    /* set column length and set score */	    ASSERT (score >= 0) ;	    ASSERT (score <= n_col) ;	    Col [c].length = col_length ;	    Col [c].shared2.score = score ;	}    }    DEBUG1 (("colamd: Dense, null, and newly-null columns killed: %d\n",    	n_col-n_col2)) ;    /* At this point, all empty rows and columns are dead.  All live columns */    /* are "clean" (containing no dead rows) and simplicial (no supercolumns */    /* yet).  Rows may contain dead columns, but all live rows contain at */    /* least one live column. */#ifndef NDEBUG    debug_structures (n_row, n_col, Row, Col, A, n_col2) ;#endif /* NDEBUG */    /* === Initialize degree lists ========================================== */#ifndef NDEBUG    debug_count = 0 ;#endif /* NDEBUG */    /* clear the hash buckets */    for (c = 0 ; c <= n_col ; c++)    {	head [c] = EMPTY ;    }    min_score = n_col ;    /* place in reverse order, so low column indices are at the front */    /* of the lists.  This is to encourage natural tie-breaking */    for (c = n_col-1 ; c >= 0 ; c--)    {	/* only add principal columns to degree lists */	if (COL_IS_ALIVE (c))	{	    DEBUG4 (("place %d score %d minscore %d ncol %d\n",		c, Col [c].shared2.score, min_score, n_col)) ;	    /* === Add columns score to DList =============================== */	    score = Col [c].shared2.score ;	    ASSERT (min_score >= 0) ;	    ASSERT (min_score <= n_col) ;	    ASSERT (score >= 0) ;	    ASSERT (score <= n_col) ;	    ASSERT (head [score] >= EMPTY) ;	    /* now add this column to dList at proper score location */	    next_col = head [score] ;	    Col [c].shared3.prev = EMPTY ;	    Col [c].shared4.degree_next = next_col ;	    /* if there already was a column with the same score, set its */	    /* previous pointer to this new column */	    if (next_col != EMPTY)	    {		Col [next_col].shared3.prev = c ;	    }	    head [score] = c ;	    /* see if this score is less than current min */	    min_score = MIN (min_score, score) ;#ifndef NDEBUG	    debug_count++ ;#endif /* NDEBUG */	}    }#ifndef NDEBUG    DEBUG1 (("colamd: Live cols %d out of %d, non-princ: %d\n",	debug_count, n_col, n_col-debug_count)) ;    ASSERT (debug_count == n_col2) ;    debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2, max_deg) ;#endif /* NDEBUG */    /* === Return number of remaining columns, and max row degree =========== */    *p_n_col2 = n_col2 ;    *p_n_row2 = n_row2 ;    *p_max_deg = max_deg ;}/* ========================================================================== *//* === find_ordering ======================================================== *//* ========================================================================== *//*    Order the principal columns of the supercolumn form of the matrix    (no supercolumns on input).  Uses a minimum approximate column minimum    degree ordering method.  Not user-callable.*/PRIVATE int find_ordering	/* return the number of garbage collections */(    /* === Parameters ======================================================= */    int n_row,			/* number of rows of A */    int n_col,			/* number of columns of A */    int Alen,			/* size of A, 2*nnz + n_col or larger */    Colamd_Row Row [],		/* of size n_row+1 */    Colamd_Col Col [],		/* of size n_col+1 */    int A [],			/* column form and row form of A */    int head [],		/* of size n_col+1 */    int n_col2,			/* Remaining columns to order */    int max_deg,		/* Maximum row degree */    int pfree			/* index of first free slot (2*nnz on entry) */){    /* === Local variables ================================================== */    int k ;			/* current pivot ordering step */    int pivot_col ;		/* current pivot column */    int *cp ;			/* a column pointer */    int *rp ;			/* a row pointer */    int pivot_row ;		/* current pivot row */    int *new_cp ;		/* modified column pointer */    int *new_rp ;		/* modified row pointer */    int pivot_row_start ;	/* pointer to start of pivot row */    int pivot_row_degree ;	/* number of columns in pivot row */    int pivot_row_length ;	/* number of supercolumns in pivot row */    int pivot_col_score ;	/* score of pivot column */    int needed_memory ;		/* free space needed for pivot row */    int *cp_end ;		/* pointer to the end of a column */    int *rp_end ;		/* pointer to the end of a row */    int row ;			/* a row index */    int col ;			/* a column index */    int max_score ;		/* maximum possible score */    int cur_score ;		/* score of current column */    unsigned int hash ;		/* hash value for supernode detection */    int head_column ;		/* head of hash bucket */    int first_col ;		/* first column in hash bucket */    int tag_mark ;		/* marker value for mark array */    int row_mark ;		/* Row [row].shared2.mark */    int set_difference ;	/* set difference size of row with pivot row */    int min_score ;		/* smallest column score */    int col_thickness ;		/* "thickness" (no. of columns in a supercol) */    int max_mark ;		/* maximum value of tag_mark */    int pivot_col_thickness ;	/* number of columns represented by pivot col */    int prev_col ;		/* Used by Dlist operations. */    int next_col ;		/* Used by Dlist operations. */    int ngarbage ;		/* number of garbage collections performed */#ifndef NDEBUG    int debug_d ;		/* debug loop counter */    int debug_step = 0 ;	/* debug loop counter */#endif /* NDEBUG */    /* === Initialization and clear mark ==================================== */    max_mark = INT_MAX - n_col ;	/* INT_MAX defined in <limits.h> */    tag_mark = clear_mark (n_row, Row) ;    min_score = 0 ;    ngarbage = 0 ;    DEBUG1 (("colamd: Ordering, n_col2=%d\n", n_col2)) ;    /* === Order the columns ================================================ */    for (k = 0 ; k < n_col2 ; /* 'k' is incremented below */)    {#ifndef NDEBUG	if (debug_step % 100 == 0)	{	    DEBUG2 (("\n...       Step k: %d out of n_col2: %d\n", k, n_col2)) ;	}	else	{	    DEBUG3 (("\n----------Step k: %d out of n_col2: %d\n", k, n_col2)) ;	}	debug_step++ ;	debug_deg_lists (n_row, n_col, Row, Col, head,		min_score, n_col2-k, max_deg) ;	debug_matrix (n_row, n_col, Row, Col, A) ;#endif /* NDEBUG */	/* === Select pivot column, and order it ============================ */	/* make sure degree list isn't empty */	ASSERT (min_score >= 0) ;	ASSERT (min_score <= n_col) ;	ASSERT (head [min_score] >= EMPTY) ;#ifndef NDEBUG	for (debug_d = 0 ; debug_d < min_score ; debug_d++)	{	    ASSERT (head [debug_d] == EMPTY) ;	}#endif /* NDEBUG */	/* get pivot column from head of minimum degree list */	while (head [min_score] == EMPTY && min_score < n_col)	{	    min_score++ ;	}	pivot_col = head [min_score] ;	ASSERT (pivot_col >= 0 && pivot_col <= n_col) ;	next_col = Col [pivot_col].shared4.degree_next ;	head [min_score] = next_col ;	if (next_col != EMPTY)	{	    Col [next_col].shared3.prev = EMPTY ;	}	ASSERT (COL_IS_ALIVE (pivot_col)) ;	DEBUG3 (("Pivot col: %d\n", pivot_col)) ;	/* remember score for defrag check */	pivot_col_score = Col [pivot_col].shared2.score ;	/* the pivot column is the kth column in the pivot order */	Col [pivot_col].shared2.order = k ;	/* increment order count by column thickness */	pivot_col_thickness = Col [pivot_col].shared1.thickness ;	k += pivot_col_thickness ;	ASSERT (pivot_col_thickness > 0) ;	/* === Garbage_collection, if necessary ============================= */	needed_memory = MIN (pivot_col_score, n_col - k) ;	if (pfree + needed_memory >= Alen)	{	    pfree = garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -