/** * @file SparseMatrixHelper.tpp * @author Giulio Romualdi * @copyright Released under the terms of the BSD 3-Clause License * @date 2018 */ #include #include template bool OsqpEigen::SparseMatrixHelper::createOsqpSparseMatrix( const Eigen::SparseCompressedBase& eigenSparseMatrix, csc*& osqpSparseMatrix) { // Copying into a new sparse matrix to be sure to use a CSC matrix Eigen::SparseMatrix 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(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::InnerIterator it(colMajorCopy, k); it; ++it) { osqpSparseMatrix->i[innerOsqpPosition] = static_cast(it.row()); osqpSparseMatrix->x[innerOsqpPosition] = static_cast(it.value()); innerOsqpPosition++; } } osqpSparseMatrix->p[static_cast(cols)] = static_cast(innerOsqpPosition); assert(innerOsqpPosition == numberOfNonZeroCoeff); return true; } template bool OsqpEigen::SparseMatrixHelper::osqpSparseMatrixToTriplets( const csc* const& osqpSparseMatrix, std::vector>& 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(row, column, static_cast(value)); } tripletList.erase(tripletList.begin() + numberOfNonZeroCoeff, tripletList.end()); return true; } template bool OsqpEigen::SparseMatrixHelper::osqpSparseMatrixToEigenSparseMatrix( const csc* const& osqpSparseMatrix, Eigen::SparseMatrix& 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> 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 bool OsqpEigen::SparseMatrixHelper::eigenSparseMatrixToTriplets( const Eigen::SparseCompressedBase& eigenSparseMatrix, std::vector>& 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::InnerIterator it(eigenSparseMatrix, k); it; ++it) { tripletList[nonZero] = Eigen::Triplet(it.row(), it.col(), static_cast(it.value())); nonZero++; } } tripletList.erase(tripletList.begin() + eigenSparseMatrix.nonZeros(), tripletList.end()); return true; }