remove empty rows of an Eigen::SparseMatrix - sparse-matrix

I have built a sparse matrix mat from a list of triplets
Eigen::SparseMatrix<double, Eigen::RowMajor> mat(Nbins,Ndata);
mat.setFromTriplets(tripletList.begin(), tripletList.end());
Now I would like to create a new matrix ret, which only contains the rows of the previous matrix which are not empty. I do it as follows
Eigen::SparseMatrix<double, Eigen::RowMajor> ret(Nbins,Ndata);
unsigned Nrow=0;
for (unsigned i=0; i<Nbins; ++i) {
auto mrow = mat.row(i);
if (mrow.sum()>0) {
ret.row(Nrow++) = mrow;
}
}
ret.conservativeResize(Nrow,Ndata);
However, doing it this way is slow and inefficient. Slow because quick profiling suggests it spends most of its time on ret.row(Nrow++) = mrow;. Inefficient because we are also copying all the data twice.
Is there a better solution? I feel one has to fiddle with the inner vectors but I get confused by them and I don't know how user-proof it is to play with them.
EDIT: In my application, matrices are row major, and I want to remove empty rows. mat is not needed, just ret. All coefficients are positive hence the way I check for nonzero rows. The triplets are sorted but column-major. There are no duplicate triplets.

Found it! Instead of writing a hand-made setFromTriplets, I went with a modification of the tripletList. The interface of Eigen::Triplet makes it very easy.
//get which rows are empty
std::vector<bool> has_value(Nbins,false);
for (auto tr : tripletList) has_value[tr.row()] = true;
//create map from old to new indices
std::map<unsigned,unsigned> row_map;
unsigned new_idx=0;
for (unsigned old_idx=0; old_idx<Nbins; old_idx++)
if(has_value[old_idx])
row_map[old_idx]=new_idx++;
//make new triplet list, dropping empty rows
std::vector<Eigen::Triplet<double> > newTripletList;
newTripletList.reserve(Ndata);
for (auto tr : tripletList)
newTripletList.push_back(
Eigen::Triplet<double>(row_map[tr.row()],tr.col(),tr.value()));
//form new matrix and return
Eigen::SparseMatrix<double, Eigen::RowMajor> ret(new_idx,Ndata);
ret.setFromTriplets(newTripletList.begin(), newTripletList.end());

Related

looping multiple vectors in a for loop

I'm programming an objloader and this is a small part of its code.I want to be able to loop through different vectors in a single for loop.The for loop doesn't work here but is it possible to implement this concept somehow? make the (for ((GLdouble* val : container)&&(GLdouble* val2:NContainer)) condition work somehow?
aclass e;
std::vector<GLdouble*> container = e.function();
Nclass n;
std::vector<GLdouble*> Ncontainer = n.function();
for ((GLdouble* val : container)&&(GLdouble* val2:NContainer))
{
glVertex3dv(val);
glNormal3dv(val2);
}

Using C functions to select array values of index positions [3], [4] and [5]

I haven’t posted to a forum like this before, so I’ve tried to explain as clearly as possible, in as much detail as possible, to try to help anyone understand the problem I’m stuck on. I should add I’ve tried to dig for ages for a suitable function to help me in C but without resorting to parsing by looping on iterations of arrays, it seems no function(s) exist in C to get the job done more elegantly?
Anyway, I have a script which, when complete, will allow me to send specific integer value data, via a serial signal, to a dot matrix display.
I’m able to send the raw HEX data from an array/buffer to a dot matrix display using the script as it is. I also have the dot matrix script working well too so it displays the whole array of HEX data well. However, I want to refine the data by not only changing the data types in an array or buffer (named tempBuffer) from HEX to INT (or whatever is appropriate) but to also specifically select three items of data from their respective index positions in that eight item array/buffer (tempBuffer).
The problem looks like this:-
tempBuffer {0x4 0x41 0xC 0xB 0x90 0x0 0x0 0x0} // Raw hex data in array (buffer) - index positions 0 through 7.
I would like to select index positions [2], [3] and [4] in the above tempBuffer array and then place them consecutively into another array pending further processing (i.e. eventually adding item [3] and [4] together to produce one INT value representing a temperature, for example).
For example:
tempBuffer index item [2] would then be placed as Index item [0] in a new array, newArray . tempBuffer Items [3] & [4] would obviously become items [1] & [2] in newArray.
I plan to use newArray index item [0] as a condition check, for example, an if or case statement etc. The outcome of the clause would determine what happens next to the subsequent index items in [1] & [2]. It won’t always be necessary to use item [2] for data checking of a certain condition if item [0] is not met.
I could use a messy C loop/parsing iteration to extract the values I need from tempBuffer and place them in newArray. However, I wondered if there is a more elegant or existing function set existing in C which will allow me to get the job done more efficiently?
My query also applies I guess to possible function solutions in C to add the index values [1] and [2] together in newArray but if anyone can point me to a pre-existing function or an efficient means to iterate the arrays from above I should be grateful for any guidance, advice or pointers to further reading. Else, (excuse the pun) its back to using unwieldy looping and iteration in C statements to achieve the same outcome.
In the unlikely event anyone is following my original posting . . .
Thank you to those who tried to help.
Please excuse my syntax below, I'm 20 years out of practice with any coding. However, I don't care - it works!
I've managed to resolve my query and now have an adapted script (see section relating to my original stackoverflow query) running the way I want it to.
My adapted and integrated script now achieves the following:-
Read and *display (static, scroll, reverse & invert) Ford **ECU PID data (500Kb/11bit) relating to Vehicle Speed and RPM to a 10 x (8x8) LED Matrix display strip.
***Parse NEMA sentences to display on said matrix altitude and time-of-day data.
• I plan to change to Mikal Hart's TinyGPS++ libraries soon and adapt the script further to make it more efficient.
• I also plan to present a YouTube tutorial about my project.
*Thank you to Marco Colli (MajicDesigns) Parola libraries.
****Thank you to Seeed Studio's example script, OBDII_PIDs, as a base starting point.**
*** Thank you to "ludektalian" for further inspiration.
Thank you,
**# Define this_that_and_the_other;
String = "Only fraction of script";
blah - - -
blah - - -
blah . . .
unsigned char newArray[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char serialOutArray[3] = {0,0,0};
if(CAN_MSGAVAIL == CAN.checkReceive()) // check data acquisition
{
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
for(int i = 0; i<len; i++) // print the data
{
newArray [i] = buf[i], HEX;
}
serialOutArray [0] = newArray [2]; // create 3 item array (new array)
serialOutArray [1] = newArray [3]; // from original 8 item array (buf) which
serialOutArray [2] = newArray [4]; // assign 'new array' to
delay(100); //'serialOutArray'
for (int y = 0; y<13; y++)
{
if (int(serialOutArray [0]) == 5) // Coolant in Celsius
{
delay(100);
colSub = int(serialOutArray[1]);
colTot = (colSub-40);
P.print(colTot + "C");
delay(500);
colSub = 0;
colTot = 0;
break;
}
if (int(serialOutArray [0]) == 12) // RPM
{
rpmA = int(serialOutArray [1])*256;
rpmB = int(serialOutArray [2]);
subRPM = (rpmA + rpmB);
rpmTot = subRPM/4;
P.print(rpmTot + "RPM");
break;
}
if (int(serialOutArray [0]) == 13) // MPH
{
mphA = serialOutArray[1];
mphTot = mphA*0.621371192;
P.print(mphTot + "MPH");
break;
}

How to create a world map using C language?

How to create a world map using C language?
Here, I want to generate a 1000*1000 two dimensional array of world map. Within the array, the land part is marked with value 1 and the sea part is marked with value 0. Is there any simple way to create?
Obviously, there's no algorithm which describes the shape of the coastline of the continents ;)
But you could use e.g. Smrender (http://www.abenteuerland.at/smrender/), feed it with the coastline of e.g. OpenStreetMap or Naturalearthdata and a single rule. Let it create a PNG image with 1000x1000 pixels.
EDIT:
With ImageMagick (convert) you can directly convert a PNG into a C header file as an array.
Go to Openstreetmap.org (or Googlemaps), zoom out until you see the whole world, make a screenshot, open it in your favorite image manipulation program and cut and resize it to 1000x1000, then run convert input.png output.h.
Bernhard
I wrote a answer in game development some hours ago that can help you, heres the topic, it's written in javascript, but it won't be hard to translate to c.
In the example you fill the whole map of 0's and then you trace a path randomly, if you want to smooth the map later you can make a snippet that loops all the watter tiles and converts them to land if there are 3 or more land tiles adjacent to it, do it 40-60 times and you will get a smoother shore and no "holes" in the continent.
EDIT
Updating the answer with a demo in C.
I've not tested it, but if you include the headers and checks the code, this is the answer.
//Create and populate the map
int mapsize = 100;
int map[mapsize*mapsize];
for(int t = 0; t < mapsize*mapsize; t++) map[t] = 0;
//make the path
int currPos[2] = {0,50};
map[currPos[0]+(currPos[1]*mapSize)] = 1;
int landTiles = 20000;
for(var l = 0; l < landTiles; l++){
int dir[2] = {RANDOM_BETWEEN_-1_AND_1, RANDOM_BETWEEN_-1_AND_1};
int next[2] = {currPos[0]+dir[0], currPos[1]+dir[1]};
map[next[0]+(next[1]*mapSize)] = 1;
currPos = next;
}
//Draw the map
for(var row = 0; row < mapSize; row++){
for(var col = 0; col < mapSize; col++){
cout << map[col+(row*mapSize)];
}
cout << endl;
}
You could have some program or script (taking as input some representation of some image of the Earth) which generates a long C file like
const char map[1000][1000] = {
{'0', '1', //.... etc for the first fow
},
{'0', '0', '0', '1', //... etc
}
/// etc for other rows
};
See also XBM for an example.

Checking arrays in AS3

I'm collecting rows of answers from a database which are made in to arrays. Something like:
for (var i:int = 0; i < event.result.length; i++) {
var data = event.result[i];
var answer:Array = new Array(data["question_id"], data["focus_id"], data["attempts"], data["category"], data["answer"], data["correct"], data["score"]);
trace("answer: " + answer);
restoreAnswer(answer, i);
}
Now, if I trace answer, I typically get something like:
answer: 5,0,2,IK,1.a,3.1,0
answer: 5,0,1,IK,2.a,3.1,0
answer: 4,1,1,AK,3,3,2
From this we see that focus_id 0 (second array item) in question_id 5 (first array item) has been attempted twice (third array item), and I only want to use the last attempt in my restoreAnswer function.
My problem is that first attempt answers override the second attempts since the first are parsed last it seems. How do I go about only calling my restoreAnswer only when appropriate?
The options are:
1 attempts, correct score (2 points)
2 attempts, correct score (1 points)
1 attempt, wrong score (0 points)
2 attemps, wrong score (0 points)
There can be multiple focus_id in each question_id.
Thank you very much! :)
I would consider having the DB query return only the most recent attempt, or if that doesn't work efficiently, return the data in attempt order. You may score question 5 twice, but at least it'll score correctly on the last pass.
You can also filter or sort the data you get back from the server.
Michael Brewer-Davis suggested using the database query to resolve this; normally speaking, this would be the right solution.
If you wait until you get it back from the web method call or whatever in AS3, then consider creating an additional Vector variable:
var vAttempts:Vector.<Vector.<int>> = new Vector.<Vector.<int>>(this.m_iNumQuestions);
You mentioned that it seems that everything is sorted so that earlier attempts come last. First you want to make sure that's true. If so, then before you do any call to restoreAnswer(), you'll want to check vAttempts to make sure that you have not already called restoreAnswer() for that question_id and focus_id:
if (!vAttempts[data["question_id"]])
{
vAttempts[data["question_id"]] = new Vector.<int>(); // ensuring a second dimension
}
if (vAttempts[data["question_id"]].indexOf(data["focus_id"]) == -1)
{
restoreAnswer(answer, i);
vAttempts[data["question_id"]].push(data["focus_id"]);
}
So optimizing this just a little bit, what you'll have is as follows:
private final function resultHandler(event:ResultEvent):void {
var vAttempts:Vector.<Vector.<int>> = new Vector.<Vector.<int>>(this.m_iNumQuestions);
var result:Object = event.result;
var iLength:int = result.length;
for (var i:int = 0; i < iLength; i++) {
var data = result[i];
var iQuestionID:int = data["question_id"];
var iFocusID:int = data["focus_id"];
var answer:Array = [iQuestionID, iFocusID, data["attempts"],
data["category"], data["answer"], data["correct"], data["score"]];
trace("answer: " + answer);
var vFocusIDs:Vector.<int> = vAttempts[iQuestionID];
if (!vFocusIDs) {
vAttempts[iQuestionID] = new <int>[iFocusID];
restoreAnswer(answer, i);
} else if (vFocusIDs.indexOf(iFocusID) == -1) {
restoreAnswer(answer, i);
vFocusIDs.push(iFocusID);
}
}
}
Note: In AS3, Arrays can skip over certain indexes, but Vectors can't. So if your program doesn't already have some sort of foreknowledge as to the number of questions, you'll need to change vAttempts from a Vector to an Array. Also account for whether question IDs are 0-indexed (as this question assumes) or 1-indexed.

R - Loop in matrix

I have two variables, the first is 1D flow vector containing 230 data and the second is 2D temperature matrix (230*44219).
I am trying to find the correlation matrix between each flow value and corresponding 44219 temperature. This is my code below.
Houlgrave_flow_1981_2000 = window(Houlgrave_flow_average, start = as.Date("1981-11-15"),end = as.Date("2000-12-15"))
> str(Houlgrave_flow_1981_2000)
‘zoo’ series from 1981-11-15 to 2000-12-15
Data: num [1:230] 0.085689 0.021437 0.000705 0 0.006969 ...
Index: Date[1:230], format: "1981-11-15" "1981-12-15" "1982-01-15" "1982-02-15" ...
Hulgrave_SST_1981_2000=X_sst[1:230,]
> str(Hulgrave_SST_1981_2000)
num [1:230, 1:44219] -0.0733 0.432 0.2783 -0.1989 0.1028 ...
sf_Houlgrave_SF_SST = NULL
sst_Houlgrave_SF_SST = NULL
cor_Houlgrave_SF_SST = NULL
for (i in 1:230) {
for(j in 1:44219){
sf_Houlgrave_SF_SST[i] = Houlgrave_flow_1981_2000[i]
sst_Houlgrave_SF_SST[i,j] = Hulgrave_SST_1981_2000[i,j]
cor_Houlgrave_SF_SST[i,j] = cor(sf_Houlgrave_SF_SST[i],Hulgrave_SST_1981_2000[i,j])
}
}
The error message always says:
Error in sst_Houlgrave_SF_SST[i, j] = Hulgrave_SST_1981_2000[i, j] :
incorrect number of subscripts on matrix
Thank you for your help.
try this:
# prepare empty matrix of correct size
cor_Houlgrave_SF_SST <- matrix(nrow=dim(Hulgrave_SST_1981_2000)[1],
ncol=dim(Hulgrave_SST_1981_2000)[2])
# Good practice to not specify "230" or "44219" directly, instead
for (i in 1:dim(Hulgrave_SST_1981_2000)[1]) {
for(j in 1:dim(Hulgrave_SST_1981_2000)[2]){
cor_Houlgrave_SF_SST[i,j] <- cor(sf_Houlgrave_SF_SST[i],Hulgrave_SST_1981_2000[i,j])
}
}
The two redefinitions inside your loop were superfluous I believe. The main problem with your code was not defining the matrix - i.e. the cor variable did not have 2 dimensions, hence the error.
It is apparently also good practice to define empty matrices for results in for-loops by explicitly giving them correct dimensions in advance - is meant to make the code more efficient.

Resources