#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "basiclu.h"
#include "mmio.h"
#define IO_ERROR 102
int main(int argc, const char *argv[])
{
lu_int *Ap = NULL;
lu_int *Ai = NULL;
double *Ax = NULL;
lu_int *basis = NULL;
lu_int *isbasic = NULL;
lu_int *count = NULL;
int *mm_I = NULL;
int *mm_J = NULL;
double *mm_val = NULL;
int mm_M, mm_N, mm_nz;
lu_int m, n, nz, i, j, l, put, err = 0;
struct basiclu_object factor;
double volumetol = 1.1;
long maxpass = 2;
basiclu_obj_initialize(&factor, 0);
if (argc < 2 || argc > 4) {
printf(" usage: maxvolume <matrix.mtx> [volumetol [maxpass]]\n");
return 101;
}
if (argc >= 3)
volumetol = atof(argv[2]);
if (argc >= 4)
maxpass = atol(argv[3]);
volumetol = fmax(volumetol, 1.0);
err = mm_read_unsymmetric_sparse(argv[1], &mm_M, &mm_N, &mm_nz,
&mm_val, &mm_I, &mm_J);
if (err) {
err = IO_ERROR;
goto cleanup;
}
printf(" matrix: %d rows, %d columns, %d nonzeros\n", mm_M, mm_N, mm_nz);
printf(" parameters: volumetol = %.2f, maxpass = %ld\n",
volumetol, maxpass);
m = mm_M;
n = mm_N;
nz = mm_nz;
Ap = malloc((m+n+1)*sizeof(lu_int));
Ai = malloc((nz+m)*sizeof(lu_int));
Ax = malloc((nz+m)*sizeof(double));
count = calloc(n, sizeof(lu_int));
if (!Ap || !Ai || !Ax || !count) {
err = BASICLU_ERROR_out_of_memory;
goto cleanup;
}
for (l = 0; l < nz; l++)
count[mm_J[l]]++;
put = 0;
for (j = 0; j < n; j++)
{
Ap[j] = put;
put += count[j];
count[j] = Ap[j];
}
Ap[n] = put;
for (l = 0; l < nz; l++)
{
j = mm_J[l];
put = count[j]++;
Ai[put] = mm_I[l];
Ax[put] = mm_val[l];
}
for (i = 0; i < m; i++)
{
Ai[Ap[n+i]] = i;
Ax[Ap[n+i]] = 1e-8;
Ap[n+i+1] = Ap[n+i] + 1;
}
free(mm_I);
free(mm_J);
free(mm_val);
free(count);
mm_I = NULL;
mm_J = NULL;
mm_val = NULL;
count = NULL;
err = basiclu_obj_initialize(&factor, m);
if (err != BASICLU_OK)
goto cleanup;
basis = malloc(m*sizeof(lu_int));
isbasic = calloc(m+n, sizeof(lu_int));
if (!basis || !isbasic) {
err = BASICLU_ERROR_out_of_memory;
goto cleanup;
}
for (i = 0; i < m; i++)
basis[i] = n+i;
for (j = n; j < m+n; j++)
isbasic[j] = 1;
long pass, changed = 1;
for (pass = 0; pass < maxpass && changed; pass++)
{
lu_int nupdate;
err = basiclu_obj_maxvolume(&factor, m+n, Ap, Ai, Ax, basis, isbasic,
volumetol, &nupdate);
if (err != BASICLU_OK)
goto cleanup;
changed = nupdate > 0;
printf(" pass %d: %d updates\n", pass+1, nupdate);
}
long rankdef = 0;
for (j = n; j < m+n; j++)
rankdef += isbasic[j] != 0;
long nupdate = factor.xstore[BASICLU_NUPDATE_TOTAL];
long nforrest = factor.xstore[BASICLU_NFORREST_TOTAL];
long nperm = nupdate-nforrest;
long nfactorize = factor.xstore[BASICLU_NFACTORIZE];
double time_factorize = factor.xstore[BASICLU_TIME_FACTORIZE_TOTAL];
double time_solve = factor.xstore[BASICLU_TIME_SOLVE_TOTAL];
double time_update = factor.xstore[BASICLU_TIME_UPDATE_TOTAL];
printf(" status: %s\n",
changed ? "max # passes done" : "optimal basis");
printf(" # passes: %ld\n", pass);
printf(" row rank deficiency: %ld\n", rankdef);
printf(" updates [perm + FT]: %ld [%ld + %ld]\n",
nupdate, nperm, nforrest);
printf(" # factorizations: %ld\n", nfactorize);
printf(" time factorize: %.2f sec\n", time_factorize);
printf(" time solve: %.2f sec\n", time_solve);
printf(" time update: %.2f sec\n", time_update);
cleanup:
if (Ap) free(Ap);
if (Ai) free(Ai);
if (Ax) free(Ax);
if (basis) free(basis);
if (isbasic) free(isbasic);
if (count) free(count);
if (mm_I) free(mm_I);
if (mm_J) free(mm_J);
if (mm_val) free(mm_val);
basiclu_obj_free(&factor);
if (err != BASICLU_OK)
printf(" error (%ld)\n", (long) err);
return err;
}