
org.ejml.sparse.csc.RandomMatrices_FSCC Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ejml-fsparse Show documentation
Show all versions of ejml-fsparse Show documentation
A fast and easy to use dense and sparse matrix linear algebra library written in Java.
The newest version!
/*
* Copyright (c) 2022, Peter Abeles. All Rights Reserved.
*
* This file is part of Efficient Java Matrix Library (EJML).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ejml.sparse.csc;
import javax.annotation.Generated;
import org.ejml.UtilEjml;
import org.ejml.data.FMatrixRMaj;
import org.ejml.data.FMatrixSparseCSC;
import org.ejml.data.FMatrixSparseTriplet;
import org.ejml.dense.row.CommonOps_FDRM;
import org.ejml.ops.FConvertMatrixStruct;
import java.util.Arrays;
import java.util.Random;
/**
* Functions for creating randomly generated sparse matrices.
*
* @author Peter Abeles
*/
@Generated("org.ejml.sparse.csc.RandomMatrices_DSCC")
public class RandomMatrices_FSCC {
private RandomMatrices_FSCC(){}
/**
* Randomly generates matrix with the specified number of non-zero elements filled with values from min to max.
*
* @param numRows Number of rows
* @param numCols Number of columns
* @param nz_total Total number of non-zero elements in the matrix
* @param min Minimum element value, inclusive
* @param max Maximum element value, inclusive
* @param rand Random number generator
* @return Randomly generated matrix
*/
public static FMatrixSparseCSC rectangle( int numRows, int numCols, int nz_total,
float min, float max, Random rand ) {
if (UtilEjml.exceedsMaxMatrixSize(numRows, numCols))
throw new IllegalArgumentException("Due to how a random matrix is created, rows*cols < Integer.MAX_VALUE");
nz_total = Math.min(numRows*numCols, nz_total);
int[] selected = UtilEjml.shuffled(numRows*numCols, nz_total, rand);
Arrays.sort(selected, 0, nz_total);
FMatrixSparseCSC ret = new FMatrixSparseCSC(numRows, numCols, nz_total);
ret.indicesSorted = true;
// compute the number of elements in each column
int[] hist = new int[numCols];
for (int i = 0; i < nz_total; i++) {
hist[selected[i]/numRows]++;
}
// define col_idx
ret.histogramToStructure(hist);
for (int i = 0; i < nz_total; i++) {
int row = selected[i]%numRows;
ret.nz_rows[i] = row;
ret.nz_values[i] = rand.nextFloat()*(max - min) + min;
}
return ret;
}
public static FMatrixSparseCSC rectangle( int numRows, int numCols, int nz_total, Random rand ) {
return rectangle(numRows, numCols, nz_total, -1, 1, rand);
}
/**
* Creates a random symmetric matrix. The entire matrix will be filled in, not just a triangular
* portion.
*
* @param N Number of rows and columns
* @param nz_total Number of nonzero elements in the triangular portion of the matrix
* @param min Minimum element value, inclusive
* @param max Maximum element value, inclusive
* @param rand Random number generator
* @return Randomly generated matrix
*/
public static FMatrixSparseCSC symmetric( int N, int nz_total,
float min, float max, Random rand ) {
if (UtilEjml.exceedsMaxMatrixSize(N, N))
throw new IllegalArgumentException("Due to how a random matrix is created, N*N < Integer.MAX_VALUE");
if (N < 0)
throw new IllegalArgumentException("Matrix must have a positive size. N=" + N);
// compute the number of elements in the triangle, including diagonal
int Ntriagle = (N*N + N)/2;
// create a list of open elements
int[] open = new int[Ntriagle];
for (int row = 0, index = 0; row < N; row++) {
for (int col = row; col < N; col++, index++) {
open[index] = row*N + col;
}
}
// perform a random draw
UtilEjml.shuffle(open, open.length, 0, nz_total, rand);
Arrays.sort(open, 0, nz_total);
// construct the matrix
FMatrixSparseTriplet A = new FMatrixSparseTriplet(N, N, nz_total*2);
for (int i = 0; i < nz_total; i++) {
int index = open[i];
int row = index/N;
int col = index%N;
float value = rand.nextFloat()*(max - min) + min;
if (row == col) {
A.addItem(row, col, value);
} else {
A.addItem(row, col, value);
A.addItem(col, row, value);
}
}
FMatrixSparseCSC B = new FMatrixSparseCSC(N, N, A.nz_length);
FConvertMatrixStruct.convert(A, B);
return B;
}
/**
* Randomly generates lower triangular (or hessenberg) matrix with the specified number of of non-zero
* elements. The diagonal elements must be non-zero.
*
* @param dimen Number of rows and columns
* @param hessenberg Hessenberg degree. 0 is triangular and 1 or more is Hessenberg.
* @param nz_total Total number of non-zero elements in the matrix. Adjust to meet matrix size constraints.
* @param min Minimum element value, inclusive
* @param max Maximum element value, inclusive
* @param rand Random number generator
* @return Randomly generated matrix
*/
public static FMatrixSparseCSC triangleLower( int dimen, int hessenberg, int nz_total,
float min, float max, Random rand ) {
// number of elements which are along the diagonal
int diag_total = dimen - hessenberg;
// pre compute element count in each row
int[] rowStart = new int[dimen];
int[] rowEnd = new int[dimen];
// diagonal is mandatory and these indexes refer to a triangle -1 dimension
int N = 0;
for (int i = 0; i < dimen; i++) {
if (i < dimen - 1 + hessenberg) rowStart[i] = N;
N += i < hessenberg ? dimen : dimen - 1 - i + hessenberg;
if (i < dimen - 1 + hessenberg) rowEnd[i] = N;
}
N += dimen - hessenberg;
// constrain the total number of non-zero elements
nz_total = Math.min(N, nz_total);
nz_total = Math.max(diag_total, nz_total);
// number of elements which are not the diagonal elements
int off_total = nz_total - diag_total;
int[] selected = UtilEjml.shuffled(N - diag_total, off_total, rand);
Arrays.sort(selected, 0, off_total);
FMatrixSparseCSC L = new FMatrixSparseCSC(dimen, dimen, nz_total);
// compute the number of elements in each column
int[] hist = new int[dimen];
int s_index = 0;
for (int col = 0; col < dimen; col++) {
if (col >= hessenberg)
hist[col]++;
while (s_index < off_total && selected[s_index] < rowEnd[col]) {
hist[col]++;
s_index++;
}
}
// define col_idx
L.histogramToStructure(hist);
int nz_index = 0;
s_index = 0;
for (int col = 0; col < dimen; col++) {
int offset = col >= hessenberg ? col - hessenberg + 1 : 0;
// assign the diagonal element a value
if (col >= hessenberg) {
L.nz_rows[nz_index] = col - hessenberg;
L.nz_values[nz_index++] = rand.nextFloat()*(max - min) + min;
}
// assign the other elements values
while (s_index < off_total && selected[s_index] < rowEnd[col]) {
// the extra + 1 is because random elements were not allowed along the diagonal
int row = selected[s_index++] - rowStart[col] + offset;
L.nz_rows[nz_index] = row;
L.nz_values[nz_index++] = rand.nextFloat()*(max - min) + min;
}
}
return L;
}
public static FMatrixSparseCSC triangleUpper( int dimen, int hessenberg, int nz_total,
float min, float max, Random rand ) {
FMatrixSparseCSC L = triangleLower(dimen, hessenberg, nz_total, min, max, rand);
FMatrixSparseCSC U = L.createLike();
CommonOps_FSCC.transpose(L, U, null);
return U;
}
public static int nonzero( int numRows, int numCols, float minFill, float maxFill, Random rand ) {
int N = numRows*numCols;
return (int)(N*(rand.nextFloat()*(maxFill - minFill) + minFill) + 0.5f);
}
/**
* Creates a triangular matrix where the amount of fill is randomly selected too.
*
* @param upper true for upper triangular and false for lower
* @param N number of rows and columns
* @param minFill minimum fill fraction
* @param maxFill maximum fill fraction
* @param rand random number generator
* @return Random matrix
*/
public static FMatrixSparseCSC triangle( boolean upper, int N, float minFill, float maxFill, Random rand ) {
int nz = (int)(((N - 1)*(N - 1)/2)*(rand.nextFloat()*(maxFill - minFill) + minFill)) + N;
if (upper) {
return triangleUpper(N, 0, nz, -1, 1, rand);
} else {
return triangleLower(N, 0, nz, -1, 1, rand);
}
}
/**
* Creates a random symmetric positive definite matrix with zero values.
*
* @param width number of columns and rows
* @param probabilityZero How likely a value is of being zero. 0 = no zeros. 1.0f = all zeros
* @param rand random number generator
* @return Random matrix
*/
public static FMatrixSparseCSC symmetricPosDef( int width, float probabilityZero, Random rand ) {
if (UtilEjml.exceedsMaxMatrixSize(width, width))
throw new IllegalArgumentException("Due to how a random matrix is created, width*width < Integer.MAX_VALUE");
if (probabilityZero < 0 || probabilityZero > 1.0f)
throw new IllegalArgumentException("Invalid value for probabilityZero");
// This is not formally proven to work. It just seems to work.
FMatrixRMaj a = new FMatrixRMaj(width, 1);
FMatrixRMaj b = new FMatrixRMaj(width, width);
for (int i = 1; i < width; i++) {
if (rand.nextFloat() >= probabilityZero)
a.set(i, 0, rand.nextFloat()*2 - 1.0f);
}
CommonOps_FDRM.multTransB(a, a, b);
for (int i = 0; i < width; i++) {
b.add(i, i, 1.0f + (float)(rand.nextFloat()*0.1f));
}
FMatrixSparseCSC out = new FMatrixSparseCSC(width, width, width);
FConvertMatrixStruct.convert(b, out, UtilEjml.TEST_F32);
return out;
}
/**
* Creates a random matrix where each column has exactly `nzEntriesPerColumn` non-zero entries.
* Compared to {@link #rectangle} this method can generate larger sparse matrices.
*
* @param numRows Number of rows
* @param numCols Number of columns
* @param nzEntriesPerColumn Amount of nz-entries per column
* @param min Minimum element value, inclusive
* @param max Maximum element value, inclusive
* @param rand Random number generator
* @return Randomly generated matrix
*/
public static FMatrixSparseCSC generateUniform( int numRows, int numCols, int nzEntriesPerColumn,
float min, float max, Random rand ) {
if (nzEntriesPerColumn > numRows) {
throw new IllegalArgumentException("numRows must be greater than nzEntriesPerColumn");
}
int nz_total = Math.toIntExact(nzEntriesPerColumn*numCols);
FMatrixSparseCSC matrix = new FMatrixSparseCSC(numRows, numCols, nz_total);
matrix.indicesSorted = true;
if (nzEntriesPerColumn == 0) {
return matrix;
}
int[] nz_hist = new int[numCols];
Arrays.fill(nz_hist, nzEntriesPerColumn);
matrix.histogramToStructure(nz_hist);
boolean[] selectedRows = new boolean[numRows];
// if the density is high enough, picking random rows will be very slow
// in this case we unselect (numRows-nzEntriesPerColumn) rows
boolean dropRows = ((float)nzEntriesPerColumn/numRows) > 0.5f;
for (int col = 0; col < numCols; col++) {
if (dropRows) {
// select all rows at first
Arrays.fill(selectedRows, true);
} else {
Arrays.fill(selectedRows, false);
}
int nz_index = col*nzEntriesPerColumn;
// selecting rows
if (dropRows) {
for (int colEntry = 0; colEntry < (numRows - nzEntriesPerColumn); colEntry++) {
int row = rand.nextInt(numRows);
while (!selectedRows[row]) {
row = rand.nextInt(numRows);
}
selectedRows[row] = false;
}
for (int row = 0; row < selectedRows.length; row++) {
if (selectedRows[row]) {
matrix.nz_rows[nz_index] = row;
matrix.nz_values[nz_index] = rand.nextFloat()*(max - min) + min;
nz_index++;
}
}
} else {
for (int colEntry = 0; colEntry < nzEntriesPerColumn; colEntry++) {
int row = rand.nextInt(numRows);
// avoid duplicate entries
while (selectedRows[row]) {
row = rand.nextInt(numRows);
}
selectedRows[row] = true;
matrix.nz_rows[nz_index] = row;
matrix.nz_values[nz_index] = rand.nextFloat()*(max - min) + min;
nz_index++;
}
Arrays.sort(matrix.nz_rows, nz_index - nzEntriesPerColumn, nz_index);
}
}
return matrix;
}
/**
* Modies the matrix to make sure that at least one element in each column has a value
*/
public static void ensureNotSingular( FMatrixSparseCSC A, Random rand ) {
// if( A.numRows < A.numCols ) {
// throw new IllegalArgumentException("Fewer equations than variables");
// }
int[] s = UtilEjml.shuffled(A.numRows, rand);
Arrays.sort(s);
int N = Math.min(A.numCols, A.numRows);
for (int col = 0; col < N; col++) {
A.set(s[col], col, rand.nextFloat() + 0.5f);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy