181 lines
5.8 KiB
C++
181 lines
5.8 KiB
C++
/**
|
|
* @file SparseMatrixHelper.tpp
|
|
* @author Giulio Romualdi
|
|
* @copyright Released under the terms of the BSD 3-Clause License
|
|
* @date 2018
|
|
*/
|
|
|
|
#include <OsqpEigen/Debug.hpp>
|
|
#include <cassert>
|
|
|
|
template <typename Derived>
|
|
bool OsqpEigen::SparseMatrixHelper::createOsqpSparseMatrix(
|
|
const Eigen::SparseCompressedBase<Derived>& eigenSparseMatrix, csc*& osqpSparseMatrix)
|
|
|
|
{
|
|
// Copying into a new sparse matrix to be sure to use a CSC matrix
|
|
Eigen::SparseMatrix<typename Derived::value_type, Eigen::ColMajor> colMajorCopy;
|
|
|
|
// This may perform memory allocation, but this is already the case for allocating the
|
|
// osqpSparseMatrix
|
|
colMajorCopy = eigenSparseMatrix;
|
|
|
|
// get number of row, columns and nonZeros from Eigen SparseMatrix
|
|
c_int rows = colMajorCopy.rows();
|
|
c_int cols = colMajorCopy.cols();
|
|
c_int numberOfNonZeroCoeff = colMajorCopy.nonZeros();
|
|
|
|
// get innerr and outer index
|
|
const int* outerIndexPtr = colMajorCopy.outerIndexPtr();
|
|
const int* innerNonZerosPtr = colMajorCopy.innerNonZeroPtr();
|
|
|
|
// instantiate csc matrix
|
|
// MEMORY ALLOCATION!!
|
|
if (osqpSparseMatrix != nullptr)
|
|
{
|
|
debugStream() << "[OsqpEigen::SparseMatrixHelper::createOsqpSparseMatrix] osqpSparseMatrix "
|
|
"pointer is not a null pointer! "
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
|
|
osqpSparseMatrix = OsqpEigen::spalloc(rows, cols, numberOfNonZeroCoeff);
|
|
|
|
int innerOsqpPosition = 0;
|
|
for (int k = 0; k < cols; k++)
|
|
{
|
|
if (colMajorCopy.isCompressed())
|
|
{
|
|
osqpSparseMatrix->p[k] = static_cast<c_int>(outerIndexPtr[k]);
|
|
} else
|
|
{
|
|
if (k == 0)
|
|
{
|
|
osqpSparseMatrix->p[k] = 0;
|
|
} else
|
|
{
|
|
osqpSparseMatrix->p[k] = osqpSparseMatrix->p[k - 1] + innerNonZerosPtr[k - 1];
|
|
}
|
|
}
|
|
for (typename Eigen::SparseMatrix<typename Derived::value_type,
|
|
Eigen::ColMajor>::InnerIterator it(colMajorCopy, k);
|
|
it;
|
|
++it)
|
|
{
|
|
osqpSparseMatrix->i[innerOsqpPosition] = static_cast<c_int>(it.row());
|
|
osqpSparseMatrix->x[innerOsqpPosition] = static_cast<c_float>(it.value());
|
|
innerOsqpPosition++;
|
|
}
|
|
}
|
|
osqpSparseMatrix->p[static_cast<int>(cols)] = static_cast<c_int>(innerOsqpPosition);
|
|
|
|
assert(innerOsqpPosition == numberOfNonZeroCoeff);
|
|
|
|
return true;
|
|
}
|
|
|
|
template <typename T>
|
|
bool OsqpEigen::SparseMatrixHelper::osqpSparseMatrixToTriplets(
|
|
const csc* const& osqpSparseMatrix, std::vector<Eigen::Triplet<T>>& tripletList)
|
|
{
|
|
// if the matrix is not instantiate the triplets vector is empty
|
|
if (osqpSparseMatrix == nullptr)
|
|
{
|
|
debugStream() << "[OsqpEigen::SparseMatrixHelper::osqpSparseMatrixToTriplets] the "
|
|
"osqpSparseMatrix is not initialized."
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
|
|
// get row and column data
|
|
c_int* innerIndexPtr = osqpSparseMatrix->i;
|
|
c_int* outerIndexPtr = osqpSparseMatrix->p;
|
|
|
|
// get values data
|
|
c_float* valuePtr = osqpSparseMatrix->x;
|
|
c_int numberOfNonZeroCoeff = osqpSparseMatrix->p[osqpSparseMatrix->n];
|
|
|
|
// populate the tripletes vector
|
|
int column = 0;
|
|
int row;
|
|
c_float value;
|
|
|
|
tripletList.resize(numberOfNonZeroCoeff);
|
|
for (int i = 0; i < numberOfNonZeroCoeff; i++)
|
|
{
|
|
row = innerIndexPtr[i];
|
|
value = valuePtr[i];
|
|
|
|
while (i >= outerIndexPtr[column + 1])
|
|
column++;
|
|
|
|
tripletList[i] = Eigen::Triplet<T>(row, column, static_cast<T>(value));
|
|
}
|
|
|
|
tripletList.erase(tripletList.begin() + numberOfNonZeroCoeff, tripletList.end());
|
|
|
|
return true;
|
|
}
|
|
|
|
template <typename T>
|
|
bool OsqpEigen::SparseMatrixHelper::osqpSparseMatrixToEigenSparseMatrix(
|
|
const csc* const& osqpSparseMatrix, Eigen::SparseMatrix<T>& eigenSparseMatrix)
|
|
{
|
|
// if the matrix is not instantiate the eigen matrix is empty
|
|
if (osqpSparseMatrix == nullptr)
|
|
{
|
|
debugStream() << "[OsqpEigen::SparseMatrixHelper::osqpSparseMatrixToEigenSparseMatrix] the "
|
|
"osqpSparseMatrix is not initialized."
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
|
|
// get the number of rows and columns
|
|
int rows = osqpSparseMatrix->m;
|
|
int cols = osqpSparseMatrix->n;
|
|
|
|
// get the triplets from the csc matrix
|
|
std::vector<Eigen::Triplet<T>> tripletList;
|
|
|
|
OsqpEigen::SparseMatrixHelper::osqpSparseMatrixToTriplets(osqpSparseMatrix, tripletList);
|
|
|
|
// resize the eigen matrix
|
|
eigenSparseMatrix.resize(rows, cols);
|
|
|
|
// set the eigen matrix from triplets
|
|
eigenSparseMatrix.setFromTriplets(tripletList.begin(), tripletList.end());
|
|
return true;
|
|
}
|
|
|
|
template <typename Derived, typename T>
|
|
bool OsqpEigen::SparseMatrixHelper::eigenSparseMatrixToTriplets(
|
|
const Eigen::SparseCompressedBase<Derived>& eigenSparseMatrix,
|
|
std::vector<Eigen::Triplet<T>>& tripletList)
|
|
{
|
|
if (eigenSparseMatrix.nonZeros() == 0)
|
|
{
|
|
debugStream() << "[OsqpEigen::SparseMatrixHelper::eigenSparseMatrixToTriplets] The "
|
|
"eigenSparseMatrix is empty."
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
|
|
tripletList.resize(eigenSparseMatrix.nonZeros());
|
|
// populate the triplet list
|
|
int nonZero = 0;
|
|
for (int k = 0; k < eigenSparseMatrix.outerSize(); ++k)
|
|
{
|
|
for (typename Eigen::SparseCompressedBase<Derived>::InnerIterator it(eigenSparseMatrix, k);
|
|
it;
|
|
++it)
|
|
{
|
|
tripletList[nonZero]
|
|
= Eigen::Triplet<T>(it.row(), it.col(), static_cast<T>(it.value()));
|
|
nonZero++;
|
|
}
|
|
}
|
|
tripletList.erase(tripletList.begin() + eigenSparseMatrix.nonZeros(), tripletList.end());
|
|
|
|
return true;
|
|
}
|