Creating Sparse array with C++ Matlab Data API

5 visualizzazioni (ultimi 30 giorni)
I have followed the instructions here to create a sparse double array. Instead of returning as it should in the debugger I get the following message from the debugger
Thread 40 "MATLAB" received signal SIGINT, Interrupt.
[Switching to Thread 0x7fffdfe48700 (LWP 14917)]
0x00007ffff68c2cb9 in __GI___poll (fds=0x7fffda7c6e40, nfds=2, timeout=1000) at ../sysdeps/unix/sysv/linux/poll.c:29
29 ../sysdeps/unix/sysv/linux/poll.c: No such file or directory.
Looking at other answers, it seems that this should happen when a pointer is unitialized, but I cannot find what pointer that could be, since I copied the official documentation.
Here is the code. Its goal is to read a graph. First number in each line is the weight of the node, the rest are edges from this node and their weights.
/* C MATLAB FUNCTION: loadmetisgraph
PURPOSE: Reads in a METIS file as described in the manual
(http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/manual.pdf)
and return the graph and the node weights as specified in the file
USAGE: function [G, weights] = loadmetsgraph(graphFilename);
INPUTS:
-graphFilename (char): Path to the graph file
Outputs:
-G (sparse matrix): A sparse representation of the graph read
TODO: Be able to read all METIS formats
*/
#include <iostream>
#include <fstream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
#include "mex.hpp"
#include "mexAdapter.hpp"
#include "MatlabDataArray.hpp"
void loadMetisGraph(std::string graphFilename, size_t &n, size_t &m, std::vector<size_t> &heads, std::vector<size_t> &tails, std::vector<double> &weights, std::vector<double> &nodeWeights) {
int64_t flag = 0;
std::ifstream graphFile(graphFilename);
if (!graphFile.is_open()) {
std::cerr << "Failed to open graphFilename " << graphFilename <<". Check path and permissions.\n";
return;
}
n = 0;
m = 0;
std::string line;
int64_t node = 0;
while (std::getline(graphFile, line)) {
std::istringstream iss{line};
// Define variable 'data'. Use range constructor and stream iterator
std::vector<int64_t> data{std::istream_iterator<double>(iss), std::istream_iterator<double>()};
if (n == 0) {
n = data[0];
m = data[1];
if (data.size() > 2)
flag = data[2];
continue;
}
nodeWeights.push_back(data[0]);
for (size_t j = 1; j < data.size(); j += 2) {
heads.push_back(data[j] - 1);
tails.push_back(node);
weights.push_back(data[j + 1]);
}
}
}
class MexFunction : public matlab::mex::Function
{
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
matlab::data::ArrayFactory factory;
public:
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs)
{
size_t n;
size_t m;
std::vector<size_t> heads;
std::vector<size_t> tails;
std::vector<double> weights;
std::vector<double> nodeWeights;
std::string graphFilename(matlab::data::CharArray(inputs[0]).toAscii());
loadMetisGraph(graphFilename, n, m, heads, tails, weights, nodeWeights);
auto nodeWeightsArr = factory.createArray({1, n}, nodeWeights.begin(), nodeWeights.end());
matlab::data::buffer_ptr_t<size_t> heads_p = factory.createBuffer<size_t>(2 * m);
matlab::data::buffer_ptr_t<size_t> tails_p = factory.createBuffer<size_t>(2 * m);
matlab::data::buffer_ptr_t<double> weights_p = factory.createBuffer<double>(2 * m);
size_t *headsPtr = heads_p.get();
size_t *tailsPtr = tails_p.get();
double *weightsPtr = weights_p.get();
std::cerr << headsPtr << std::endl;
std::cerr << "n = " << n << " m = " << m << " 2m = " << 2 * m << " weights.size = " << weights.size() << std::endl;
std::for_each(heads.begin(), heads.end(), [&](const size_t& e) { *(headsPtr++) = e; });
std::for_each(tails.begin(), tails.end(), [&](const size_t& e) { *(tailsPtr++) = e; });
std::for_each(weights.begin(), weights.end(), [&](const double& e) { *(weightsPtr++) = e; });
// Use the buffers to create the sparse array
matlab::data::SparseArray<double> G =
factory.createSparseArray<double>({n, n}, 2 * m,
std::move(weights_p), std::move(tails_p), std::move(heads_p));
outputs[0] = G;
outputs[1] = nodeWeightsArr;
}
};
The top function is reading the file and putting the triads in heads, tails and weights and after that in the operator function it sends the results back to Matlab. Here is a small sample file that it should be able to read:
34 78 011
16 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1 11 1 12 1 13 1 14 1 18 1 20 1 22 1 32 1
9 1 1 3 1 4 1 8 1 14 1 18 1 20 1 22 1 31 1
10 1 1 2 1 4 1 8 1 9 1 10 1 14 1 28 1 29 1 33 1
6 1 1 2 1 3 1 8 1 13 1 14 1
3 1 1 7 1 11 1
4 1 1 7 1 11 1 17 1
4 1 1 5 1 6 1 17 1
4 1 1 2 1 3 1 4 1
5 1 1 3 1 31 1 33 1 34 1
2 3 1 34 1
3 1 1 5 1 6 1
1 1 1
2 1 1 4 1
5 1 1 2 1 3 1 4 1 34 1
2 33 1 34 1
2 33 1 34 1
2 6 1 7 1
2 1 1 2 1
2 33 1 34 1
3 1 1 2 1 34 1
2 33 1 34 1
2 1 1 2 1
2 33 1 34 1
5 28 1 33 1 34 1 26 1 30 1
3 32 1 28 1 26 1
3 32 1 24 1 25 1
2 34 1 30 1
4 3 1 24 1 25 1 34 1
3 3 1 32 1 34 1
4 33 1 34 1 24 1 27 1
4 2 1 9 1 33 1 34 1
6 1 1 25 1 26 1 29 1 33 1 34 1
12 3 1 9 1 32 1 31 1 15 1 16 1 19 1 21 1 23 1 24 1 30 1 34 1
17 9 1 14 1 20 1 32 1 31 1 10 1 28 1 29 1 33 1 15 1 16 1 19 1 21 1 23 1 24 1 27 1 30 1
Compilation:
mex COPTIMFLAGS="-Wall -Wextra" loadMetisGraph.cpp -g
Call command:
[G, weights] = loadMetisGraph('karate.metis');
If someone could point me to the correct direction, I would appreciate it.

Risposta accettata

kameranis
kameranis il 28 Giu 2021
Found what was wrong.
a) node should be size_t.
b) Reading in size_t and converting what is needed to double is better than the other way around.
c) Because I didn't increment node there were many entries in the same position which was taking a lot of time to aggregate and instead I thought it was hanging.

Più risposte (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by