📄 mod2sparse.c
字号:
)
{
mod2entry *f1, *f2, *ft;
if (mod2sparse_rows(m1)<mod2sparse_rows(m2))
{ fprintf (stderr,
"mod2sparse_add_col: Column added to is shorter than column added from\n");
exit(1);
}
if (col1<0 || col1>=mod2sparse_cols(m1)
|| col2<0 || col2>=mod2sparse_cols(m2))
{ fprintf (stderr,"mod2sparse_add_col: Column index out of range\n");
exit(1);
}
f1 = mod2sparse_first_in_col(m1,col1);
f2 = mod2sparse_first_in_col(m2,col2);
while (!mod2sparse_at_end(f1) && !mod2sparse_at_end(f2))
{ if (mod2sparse_row(f1)>mod2sparse_row(f2))
{ mod2sparse_insert(m1,mod2sparse_row(f2),col1);
f2 = mod2sparse_next_in_col(f2);
}
else
{ ft = mod2sparse_next_in_col(f1);
if (mod2sparse_row(f1)==mod2sparse_row(f2))
{ mod2sparse_delete(m1,f1);
f2 = mod2sparse_next_in_col(f2);
}
f1 = ft;
}
}
while (!mod2sparse_at_end(f2))
{ mod2sparse_insert(m1,mod2sparse_row(f2),col1);
f2 = mod2sparse_next_in_col(f2);
}
}
/* FIND AN LU DECOMPOSITION OF A SPARSE MATRIX. */
int mod2sparse_decomp
( mod2sparse *A, /* Input matrix, M by N */
int K, /* Size of sub-matrix to find LU decomposition of */
int *rows, /* Array where row indexes are stored, M long */
int *cols, /* Array where column indexes are stored, N long */
mod2sparse_strategy strategy, /* Strategy to follow in picking rows/columns */
int abandon_number, /* Number of columns to abandon at some point */
int abandon_when /* When to abandon these columns */
)
{
int *rinv, *cinv, *acnt, *rcnt;
mod2sparse *B;
int M, N;
mod2entry *e, *f, *fn, *e2;
int i, j, k, cc, cc2, cc3, cr2, pr;
int found, nnf;
M = mod2sparse_rows(A);
N = mod2sparse_cols(A);
if (mod2sparse_cols(L)!=K || mod2sparse_rows(L)!=M
|| mod2sparse_cols(U)!=N || mod2sparse_rows(U)!=K)
{ fprintf (stderr,
"mod2sparse_decomp: Matrices have incompatible dimensions\n");
exit(1);
}
if (abandon_number>N-K)
{ fprintf(stderr,"Trying to abandon more columns than allowed\n");
exit(1);
}
rinv = chk_alloc (M, sizeof *rinv);
cinv = chk_alloc (N, sizeof *cinv);
if (abandon_number>0)
{ acnt = chk_alloc (M+1, sizeof *acnt);
}
if (strategy==Mod2sparse_minprod)
{ rcnt = chk_alloc (M, sizeof *rcnt);
}
mod2sparse_clear(L);
mod2sparse_clear(U);
/* Copy A to B. B will be modified, then discarded. */
B = mod2sparse_allocate(M,N);
mod2sparse_copy(A,B);
/* Count 1s in rows of B, if using minprod strategy. */
if (strategy==Mod2sparse_minprod)
{ for (i = 0; i<M; i++)
{ rcnt[i] = mod2sparse_count_row(B,i);
}
}
/* Set up initial row and column choices. */
for (i = 0; i<M; i++) rows[i] = rinv[i] = i;
for (j = 0; j<N; j++) cols[j] = cinv[j] = j;
/* Find L and U one column at a time. */
nnf = 0;
for (i = 0; i<K; i++)
{
/* Choose the next row and column of B. */
switch (strategy)
{
case Mod2sparse_first:
{
found = 0;
for (k = i; k<N; k++)
{ e = mod2sparse_first_in_col(B,cols[k]);
while (!mod2sparse_at_end(e))
{ if (rinv[mod2sparse_row(e)]>=i)
{ found = 1;
goto out_first;
}
e = mod2sparse_next_in_col(e);
}
}
out_first:
break;
}
case Mod2sparse_mincol:
{
found = 0;
for (j = i; j<N; j++)
{ cc2 = mod2sparse_count_col(B,cols[j]);
if (!found || cc2<cc)
{ e2 = mod2sparse_first_in_col(B,cols[j]);
while (!mod2sparse_at_end(e2))
{ if (rinv[mod2sparse_row(e2)]>=i)
{ found = 1;
cc = cc2;
e = e2;
k = j;
break;
}
e2 = mod2sparse_next_in_col(e2);
}
}
}
break;
}
case Mod2sparse_minprod:
{
found = 0;
for (j = i; j<N; j++)
{ cc2 = mod2sparse_count_col(B,cols[j]);
e2 = mod2sparse_first_in_col(B,cols[j]);
while (!mod2sparse_at_end(e2))
{ if (rinv[mod2sparse_row(e2)]>=i)
{ cr2 = rcnt[mod2sparse_row(e2)];
if (!found || cc2==1 || (cc2-1)*(cr2-1)<pr)
{ found = 1;
pr = cc2==1 ? 0 : (cc2-1)*(cr2-1);
e = e2;
k = j;
}
}
e2 = mod2sparse_next_in_col(e2);
}
}
break;
}
default:
{ fprintf(stderr,"mod2sparse_decomp: Unknown stategy\n");
exit(1);
}
}
if (!found)
{ nnf += 1;
}
/* Update 'rows' and 'cols'. Looks at 'k' and 'e' found above. */
if (found)
{
if (cinv[mod2sparse_col(e)]!=k) abort();
cols[k] = cols[i];
cols[i] = mod2sparse_col(e);
cinv[cols[k]] = k;
cinv[cols[i]] = i;
k = rinv[mod2sparse_row(e)];
if (k<i) abort();
rows[k] = rows[i];
rows[i] = mod2sparse_row(e);
rinv[rows[k]] = k;
rinv[rows[i]] = i;
}
/* Update L, U, and B. */
f = mod2sparse_first_in_col(B,cols[i]);
while (!mod2sparse_at_end(f))
{
fn = mod2sparse_next_in_col(f);
k = mod2sparse_row(f);
if (rinv[k]>i)
{ mod2sparse_add_row(B,k,B,mod2sparse_row(e));
if (strategy==Mod2sparse_minprod)
{ rcnt[k] = mod2sparse_count_row(B,k);
}
mod2sparse_insert(L,k,i);
}
else if (rinv[k]<i)
{ mod2sparse_insert(U,rinv[k],cols[i]);
}
else
{ mod2sparse_insert(L,k,i);
mod2sparse_insert(U,i,cols[i]);
}
f = fn;
}
/* Get rid of all entries in the current column of B, just to save space. */
for (;;)
{ f = mod2sparse_first_in_col(B,cols[i]);
if (mod2sparse_at_end(f)) break;
mod2sparse_delete(B,f);
}
/* Abandon columns of B with lots of entries if it's time for that. */
if (abandon_number>0 && i==abandon_when)
{
for (k = 0; k<M+1; k++)
{ acnt[k] = 0;
}
for (j = 0; j<N; j++)
{ k = mod2sparse_count_col(B,j);
acnt[k] += 1;
}
cc = abandon_number;
k = M;
while (acnt[k]<cc)
{ cc -= acnt[k];
k -= 1;
if (k<0) abort();
}
cc2 = 0;
for (j = 0; j<N; j++)
{ cc3 = mod2sparse_count_col(B,j);
if (cc3>k || cc3==k && cc>0)
{ if (cc3==k) cc -= 1;
for (;;)
{ f = mod2sparse_first_in_col(B,j);
if (mod2sparse_at_end(f)) break;
mod2sparse_delete(B,f);
}
cc2 += 1;
}
}
if (cc2!=abandon_number) abort();
if (strategy==Mod2sparse_minprod)
{ for (j = 0; j<M; j++)
{ rcnt[j] = mod2sparse_count_row(B,j);
}
}
}
}
/* Get rid of all entries in the rows of L past row K, after reordering. */
for (i = K; i<M; i++)
{ for (;;)
{ f = mod2sparse_first_in_row(L,rows[i]);
if (mod2sparse_at_end(f)) break;
mod2sparse_delete(L,f);
}
}
mod2sparse_free(B);
free(rinv);
free(cinv);
if (strategy==Mod2sparse_minprod) free(rcnt);
if (abandon_number>0) free(acnt);
return nnf;
}
/* SOLVE A LOWER-TRIANGULAR SYSTEM BY FORWARD SUBSTITUTION. */
int mod2sparse_forward_sub
( mod2sparse *L, /* Matrix that is lower triangular after reordering */
int *rows, /* Array of indexes (from 0) of rows for new order */
int *x, /* Vector on right of equation, also reordered */
int *y /* Place to store solution */
)
{
int K, i, j, ii, b, d;
mod2entry *e;
K = mod2sparse_cols(L);
/* Make sure that L is lower-triangular, after row re-ordering. */
for (i = 0; i<K; i++)
{ ii = rows ? rows[i] : i;
e = mod2sparse_last_in_row(L,ii);
if (!mod2sparse_at_end(e) && mod2sparse_col(e)>i)
{ fprintf(stderr,
"mod2sparse_forward_sub: Matrix is not lower-triangular\n");
exit(1);
}
}
/* Solve system by forward substitution. */
for (i = 0; i<K; i++)
{
ii = rows ? rows[i] : i;
/* Look at bits in this row, forming inner product with partial
solution, and seeing if the diagonal is 1. */
d = 0;
b = 0;
for (e = mod2sparse_first_in_row(L,ii);
!mod2sparse_at_end(e);
e = mod2sparse_next_in_row(e))
{
j = mod2sparse_col(e);
if (j==i)
{ d = 1;
}
else
{ b ^= y[j];
}
}
/* Check for no solution if the diagonal isn't 1. */
if (!d && b!=x[ii])
{ return 0;
}
/* Set bit of solution, zero if arbitrary. */
y[i] = b^x[ii];
}
return 1;
}
/* SOLVE AN UPPER-TRIANGULAR SYSTEM BY BACKWARD SUBSTITUTION. */
int mod2sparse_backward_sub
( mod2spars e *U, /* Matrix that is upper triangular after reordering */
int *cols, /* Array of indexes (from 0) of columns for new order */
int *y, /* Vector on right of equation */
int *z /* Place to store solution, also reordered */
)
{
int K, i, j, ii, b, d;
mod2entry *e;
K = mod2sparse_rows(U);
/* Make sure that U is upper-triangular, after column re-ordering. */
for (i = 0; i<K; i++)
{ ii = cols ? cols[i] : i;
e = mod2sparse_last_in_col(U,ii);
if (!mod2sparse_at_end(e) && mod2sparse_row(e)>i)
{ fprintf(stderr,
"mod2sparse_backward_sub: Matrix is not upper-triangular\n");
exit(1);
}
}
/* Solve system by backward substitution. */
for (i = K-1; i>=0; i--)
{
ii = cols ? cols[i] : i;
/* Look at bits in this row, forming inner product with partial
solution, and seeing if the diagonal is 1. */
d = 0;
b = 0;
for (e = mod2sparse_first_in_row(U,i);
!mod2sparse_at_end(e);
e = mod2sparse_next_in_row(e))
{
j = mod2sparse_col(e);
if (j==ii)
{ d = 1;
}
else
{ b ^= z[j];
}
}
/* Check for no solution if the diagonal isn't 1. */
if (!d && b!=y[i])
{ return 0;
}
/* Set bit of solution, zero if arbitrary. */
z[ii] = b^y[i];
}
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -