Alien-XGBoost
view release on metacpan or search on metacpan
xgboost/cub/experimental/sparse_matrix.h view on Meta::CPAN
return false;
}
};
//---------------------------------------------------------------------
// Data members
//---------------------------------------------------------------------
// Fields
int num_rows;
int num_cols;
int num_nonzeros;
CooTuple* coo_tuples;
//---------------------------------------------------------------------
// Methods
//---------------------------------------------------------------------
// Constructor
CooMatrix() : num_rows(0), num_cols(0), num_nonzeros(0), coo_tuples(NULL) {}
/**
* Clear
*/
void Clear()
{
if (coo_tuples) delete[] coo_tuples;
coo_tuples = NULL;
}
// Destructor
~CooMatrix()
{
Clear();
}
// Display matrix to stdout
void Display()
{
cout << "COO Matrix (" << num_rows << " rows, " << num_cols << " columns, " << num_nonzeros << " non-zeros):\n";
cout << "Ordinal, Row, Column, Value\n";
for (int i = 0; i < num_nonzeros; i++)
{
cout << '\t' << i << ',' << coo_tuples[i].row << ',' << coo_tuples[i].col << ',' << coo_tuples[i].val << "\n";
}
}
/**
* Builds a symmetric COO sparse from an asymmetric CSR matrix.
*/
template <typename CsrMatrixT>
void InitCsrSymmetric(CsrMatrixT &csr_matrix)
{
if (coo_tuples)
{
fprintf(stderr, "Matrix already constructed\n");
exit(1);
}
num_rows = csr_matrix.num_cols;
num_cols = csr_matrix.num_rows;
num_nonzeros = csr_matrix.num_nonzeros * 2;
coo_tuples = new CooTuple[num_nonzeros];
for (OffsetT row = 0; row < csr_matrix.num_rows; ++row)
{
for (OffsetT nonzero = csr_matrix.row_offsets[row]; nonzero < csr_matrix.row_offsets[row + 1]; ++nonzero)
{
coo_tuples[nonzero].row = row;
coo_tuples[nonzero].col = csr_matrix.column_indices[nonzero];
coo_tuples[nonzero].val = csr_matrix.values[nonzero];
coo_tuples[csr_matrix.num_nonzeros + nonzero].row = coo_tuples[nonzero].col;
coo_tuples[csr_matrix.num_nonzeros + nonzero].col = coo_tuples[nonzero].row;
coo_tuples[csr_matrix.num_nonzeros + nonzero].val = csr_matrix.values[nonzero];
}
}
// Sort by rows, then columns
std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);
}
/**
* Builds a COO sparse from a relabeled CSR matrix.
*/
template <typename CsrMatrixT>
void InitCsrRelabel(CsrMatrixT &csr_matrix, OffsetT* relabel_indices)
{
if (coo_tuples)
{
fprintf(stderr, "Matrix already constructed\n");
exit(1);
}
num_rows = csr_matrix.num_rows;
num_cols = csr_matrix.num_cols;
num_nonzeros = csr_matrix.num_nonzeros;
coo_tuples = new CooTuple[num_nonzeros];
for (OffsetT row = 0; row < num_rows; ++row)
{
for (OffsetT nonzero = csr_matrix.row_offsets[row]; nonzero < csr_matrix.row_offsets[row + 1]; ++nonzero)
{
coo_tuples[nonzero].row = relabel_indices[row];
coo_tuples[nonzero].col = relabel_indices[csr_matrix.column_indices[nonzero]];
coo_tuples[nonzero].val = csr_matrix.values[nonzero];
}
}
// Sort by rows, then columns
std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);
}
/**
* Builds a METIS COO sparse from the given file.
*/
void InitMetis(const string &metis_filename)
{
if (coo_tuples)
{
fprintf(stderr, "Matrix already constructed\n");
exit(1);
}
// TODO
}
/**
* Builds a MARKET COO sparse from the given file.
*/
void InitMarket(
const string& market_filename,
ValueT default_value = 1.0,
bool verbose = false)
{
if (verbose) {
printf("Reading... "); fflush(stdout);
}
if (coo_tuples)
{
fprintf(stderr, "Matrix already constructed\n");
exit(1);
}
std::ifstream ifs;
ifs.open(market_filename.c_str(), std::ifstream::in);
if (!ifs.good())
{
fprintf(stderr, "Error opening file\n");
exit(1);
}
bool array = false;
bool symmetric = false;
bool skew = false;
int current_edge = -1;
char line[1024];
if (verbose) {
printf("Parsing... "); fflush(stdout);
}
while (true)
{
ifs.getline(line, 1024);
if (!ifs.good())
{
// Done
break;
}
if (line[0] == '%')
{
// Comment
if (line[1] == '%')
{
// Banner
symmetric = (strstr(line, "symmetric") != NULL);
skew = (strstr(line, "skew") != NULL);
array = (strstr(line, "array") != NULL);
if (verbose) {
printf("(symmetric: %d, skew: %d, array: %d) ", symmetric, skew, array); fflush(stdout);
}
}
}
else if (current_edge == -1)
{
// Problem description
int nparsed = sscanf(line, "%d %d %d", &num_rows, &num_cols, &num_nonzeros);
if ((!array) && (nparsed == 3))
{
if (symmetric)
num_nonzeros *= 2;
// Allocate coo matrix
coo_tuples = new CooTuple[num_nonzeros];
current_edge = 0;
}
else if (array && (nparsed == 2))
{
// Allocate coo matrix
num_nonzeros = num_rows * num_cols;
coo_tuples = new CooTuple[num_nonzeros];
current_edge = 0;
}
else
{
fprintf(stderr, "Error parsing MARKET matrix: invalid problem description: %s\n", line);
exit(1);
}
}
else
{
// Edge
if (current_edge >= num_nonzeros)
{
fprintf(stderr, "Error parsing MARKET matrix: encountered more than %d num_nonzeros\n", num_nonzeros);
exit(1);
}
int row, col;
double val;
if (array)
{
if (sscanf(line, "%lf", &val) != 1)
{
fprintf(stderr, "Error parsing MARKET matrix: badly formed current_edge: '%s' at edge %d\n", line, current_edge);
exit(1);
}
col = (current_edge / num_rows);
row = (current_edge - (num_rows * col));
coo_tuples[current_edge] = CooTuple(row, col, val); // Convert indices to zero-based
}
else
{
// Parse nonzero (note: using strtol and strtod is 2x faster than sscanf or istream parsing)
char *l = line;
char *t = NULL;
// parse row
row = strtol(l, &t, 0);
if (t == l)
{
fprintf(stderr, "Error parsing MARKET matrix: badly formed row at edge %d\n", current_edge);
exit(1);
}
l = t;
// parse col
col = strtol(l, &t, 0);
if (t == l)
{
fprintf(stderr, "Error parsing MARKET matrix: badly formed col at edge %d\n", current_edge);
exit(1);
}
l = t;
// parse val
val = strtod(l, &t);
if (t == l)
{
val = default_value;
}
/*
int nparsed = sscanf(line, "%d %d %lf", &row, &col, &val);
if (nparsed == 2)
{
// No value specified
val = default_value;
}
else if (nparsed != 3)
{
fprintf(stderr, "Error parsing MARKET matrix 1: badly formed current_edge: %d parsed at edge %d\n", nparsed, current_edge);
exit(1);
}
*/
coo_tuples[current_edge] = CooTuple(row - 1, col - 1, val); // Convert indices to zero-based
}
current_edge++;
if (symmetric && (row != col))
{
coo_tuples[current_edge].row = coo_tuples[current_edge - 1].col;
coo_tuples[current_edge].col = coo_tuples[current_edge - 1].row;
coo_tuples[current_edge].val = coo_tuples[current_edge - 1].val * (skew ? -1 : 1);
current_edge++;
}
}
}
// Adjust nonzero count (nonzeros along the diagonal aren't reversed)
num_nonzeros = current_edge;
if (verbose) {
printf("done. Ordering..."); fflush(stdout);
}
// Sort by rows, then columns
std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);
if (verbose) {
printf("done. "); fflush(stdout);
}
ifs.close();
}
/**
* Builds a dense matrix
*/
int InitDense(
OffsetT num_rows,
OffsetT num_cols,
ValueT default_value = 1.0,
bool verbose = false)
{
if (coo_tuples)
{
fprintf(stderr, "Matrix already constructed\n");
exit(1);
}
this->num_rows = num_rows;
this->num_cols = num_cols;
num_nonzeros = num_rows * num_cols;
coo_tuples = new CooTuple[num_nonzeros];
for (OffsetT row = 0; row < num_rows; ++row)
{
for (OffsetT col = 0; col < num_cols; ++col)
{
coo_tuples[(row * num_cols) + col] = CooTuple(row, col, default_value);
}
}
// Sort by rows, then columns
std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);
return 0;
}
/**
* Builds a wheel COO sparse matrix having spokes spokes.
*/
int InitWheel(
OffsetT spokes,
ValueT default_value = 1.0,
bool verbose = false)
{
if (coo_tuples)
{
fprintf(stderr, "Matrix already constructed\n");
exit(1);
}
num_rows = spokes + 1;
num_cols = num_rows;
num_nonzeros = spokes * 2;
coo_tuples = new CooTuple[num_nonzeros];
// Add spoke num_nonzeros
int current_edge = 0;
for (OffsetT i = 0; i < spokes; i++)
{
coo_tuples[current_edge] = CooTuple(0, i + 1, default_value);
current_edge++;
}
// Add rim
for (OffsetT i = 0; i < spokes; i++)
{
OffsetT dest = (i + 1) % spokes;
coo_tuples[current_edge] = CooTuple(i + 1, dest + 1, default_value);
current_edge++;
}
// Sort by rows, then columns
std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);
return 0;
}
/**
* Builds a square 2D grid CSR matrix. Interior num_vertices have degree 5 when including
* a self-loop.
*
* Returns 0 on success, 1 on failure.
*/
int InitGrid2d(OffsetT width, bool self_loop, ValueT default_value = 1.0)
{
if (coo_tuples)
{
fprintf(stderr, "Matrix already constructed\n");
exit(1);
}
int interior_nodes = (width - 2) * (width - 2);
int edge_nodes = (width - 2) * 4;
int corner_nodes = 4;
num_rows = width * width;
num_cols = num_rows;
num_nonzeros = (interior_nodes * 4) + (edge_nodes * 3) + (corner_nodes * 2);
if (self_loop)
num_nonzeros += num_rows;
coo_tuples = new CooTuple[num_nonzeros];
int current_edge = 0;
for (OffsetT j = 0; j < width; j++)
{
for (OffsetT k = 0; k < width; k++)
{
OffsetT me = (j * width) + k;
// West
OffsetT neighbor = (j * width) + (k - 1);
if (k - 1 >= 0) {
coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);
current_edge++;
}
// East
neighbor = (j * width) + (k + 1);
if (k + 1 < width) {
coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);
current_edge++;
}
// North
neighbor = ((j - 1) * width) + k;
if (j - 1 >= 0) {
coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);
current_edge++;
}
// South
neighbor = ((j + 1) * width) + k;
if (j + 1 < width) {
coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);
current_edge++;
}
if (self_loop)
{
neighbor = me;
coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);
current_edge++;
}
}
}
// Sort by rows, then columns, update dims
std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);
return 0;
}
/**
* Builds a square 3D grid COO sparse matrix. Interior num_vertices have degree 7 when including
* a self-loop. Values are unintialized, coo_tuples are sorted.
*/
int InitGrid3d(OffsetT width, bool self_loop, ValueT default_value = 1.0)
{
if (coo_tuples)
{
fprintf(stderr, "Matrix already constructed\n");
return -1;
}
OffsetT interior_nodes = (width - 2) * (width - 2) * (width - 2);
OffsetT face_nodes = (width - 2) * (width - 2) * 6;
OffsetT edge_nodes = (width - 2) * 12;
OffsetT corner_nodes = 8;
num_cols = width * width * width;
num_rows = num_cols;
num_nonzeros = (interior_nodes * 6) + (face_nodes * 5) + (edge_nodes * 4) + (corner_nodes * 3);
if (self_loop)
num_nonzeros += num_rows;
coo_tuples = new CooTuple[num_nonzeros];
int current_edge = 0;
for (OffsetT i = 0; i < width; i++)
{
for (OffsetT j = 0; j < width; j++)
{
for (OffsetT k = 0; k < width; k++)
{
OffsetT me = (i * width * width) + (j * width) + k;
// Up
OffsetT neighbor = (i * width * width) + (j * width) + (k - 1);
if (k - 1 >= 0) {
coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);
current_edge++;
}
// Down
neighbor = (i * width * width) + (j * width) + (k + 1);
if (k + 1 < width) {
coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);
current_edge++;
}
// West
neighbor = (i * width * width) + ((j - 1) * width) + k;
if (j - 1 >= 0) {
coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);
current_edge++;
}
// East
neighbor = (i * width * width) + ((j + 1) * width) + k;
if (j + 1 < width) {
coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);
current_edge++;
}
// North
neighbor = ((i - 1) * width * width) + (j * width) + k;
if (i - 1 >= 0) {
coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);
current_edge++;
}
( run in 0.699 second using v1.01-cache-2.11-cpan-e1769b4cff6 )