I have an Eigen Vector. I would want to cat it recursively. For example
Eigen::Vector3d vec;
vec << 5, 6, 7;
Eigen::VectorXd vecCat;
for(int i=0;i<3;i++)
vecCat << vec(i),0,0;
cout<<vecCat<<endl;
so that the final output would be
vecCat= 5 0 0 6 0 0 7 0 0
I am getting an error if I do the above way. Can anyone help me?
As I said in the comment, I will not explain how one could use the CommaInitializer iteratively. But here is a solution using Eigen::Map:
Eigen::Vector3d vec;
vec << 5,6,7;
Eigen::VectorXd vecCat = Eigen::VectorXd::Zero(9); // result vector
{
// map vector to 3x3 matrix:
Eigen::Map<Eigen::MatrixXd> map(vecCat.data(), 3,3);
map.row(0) = vec.transpose(); // set top elements to elements of vec
}
std::cout << vecCat.transpose() << '\n';
If row(0) is everything you need to modify in map you can alternatively (instead of the { } block) write:
Eigen::MatrixXd::Map(vecCat.data(), 3, 3).row(0) = vec.transpose();
Related
//this approach is based on finding all the subsets of a set having n elements by finding subsets of n-1 elements. and so on through recursion..
int sum_subset(int set[], vector<int>& subset, int sum, int n, int l=0)
{
//for edge case of sum=0
if (sum = 0) return 1;
int s = 0;
//base condition of recursion
if (l == n) {
for (int x:subset) {
s += x;
}
return (s==sum)? 1: 0;
}
//calling the recursion for ->not including the nth element of the set of n elements in the subset of n-1 elements
int a = sum_subset(set, subset, sum, n, l+1);
//including nth element in the subset
subset.push_back(set[l]);
//calling the recursion for -> including the nth element of the set of n elements in the subset of n-1 elements
int b = sum_subset(set, subset, sum, n, l+1);
return a + b;
}
int main() {
int n;
cout << "enter the size of set" << endl;
cin >> n;
int set[n];
cout << "enter the set elements" << endl;
for(int i = 0; i < n; i++) {
cin >> set[i];
}
cout << "enter the sum " << endl;
int sum;
cin >> sum;
vector<int> subset{0};
int ans = sum_subset(set, subset, sum, n);
cout << "subsets having sum =" << sum << "are->" << ans << endl;
}
//output
enter the size of set
5
enter the set elements
1
2
2
1
3
enter the sum
3
subsets having sum =3are->1
You are assigning your sum variable the value 0 instead of comparing the values:
//for edge case of sum=0
if (sum = 0) return 1;
int s = 0;
This itself hides another problem: you never remove the values from the subset vector. For example, the first time you push the value into your subset, you leave your subset equal to {3}. Then you just add more and more values, and this "subset" will never give you the sum equal 3.
One more problem that doesn't affect your program, but is important. In the line below you don't create an empty vector, but you create a vector with one zero element in it, the the vector is equal to {0}:
vector<int> subset{0};
I'm trying to implement some draws using a polya urn scheme using Rcpp. Basically, I have a matrix I'm drawing from, and a 2nd matrix with weights proportional to the probabilities. After each draw, I need to increase the weight of whichever cell I drew.
I was running into some indexing errors which lead me to examine the sampling more generally, and I found that my weight matrix was getting modified by RcppArmadillo::sample. Two questions (1) is this behavior that I should have expected or is this a bug which I should report somewhere? (2) Any ideas on current work-around? Here's a reproducible example:
#include <RcppArmadilloExtensions/sample.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp ;
// [[Rcpp::export]]
void sampler(int N, int inc, NumericMatrix& weight_matrix, int reps) {
IntegerVector wm_tmp = seq_along(weight_matrix);
Rcout << "Initial weight_matrix:\n" << weight_matrix << "\n";
int x_ind;
for(int i = 0; i < reps; ++i) {
x_ind = RcppArmadillo::sample(wm_tmp, 1, true, weight_matrix)(0) - 1;
Rcout << "Weight matrix after sample: (rep = " << i << ")\n" << weight_matrix << "\n";
Rcout << "x_ind: " << x_ind << "\n";
// get indices
weight_matrix[x_ind] = weight_matrix[x_ind] + inc;
Rcout << "Add increment of " << inc << " to weight_matrix:\n" << weight_matrix << "\n";
}
}
//
// // [[Rcpp::export]]
// IntegerVector seq_cpp(IntegerMatrix x) {
// IntegerVector tmp = seq_along(x);
// IntegerVector ret = RcppArmadillo::sample(tmp, 2, true);
// return ret;
// }
/*** R
weight_matrix <- matrix(1, 5, 2)
sampler(5, 1, weight_matrix, 3)
weight_matrix <- matrix(1, 5, 2)
sampler(5, 0, weight_matrix, 3)
*/
Thanks!
That is known and documented behaviour.
You could do
i) Use Rcpp::clone() to create a distinct copy of your SEXP (ie NumericMatrix).
ii) Use an Armadillo matrix instead and pass as const arma::mat & m.
There are architectural reasons having to do with the way R organizes its data structure which mean that we cannot give you fast access (no copies!) and also protect against writes.
This question already has an answer here:
Assigning Rcpp objects into an Rcpp List yields duplicates of the last element
(1 answer)
Closed 4 years ago.
I want to create a list of matrices that I am updating in a loop and return it to R. I have
std::vector<IntegerMatrix> zb_list;
and
IntegerMatrix tb(J,nmax), zb(J,nmax);
before the loop. Inside the loop, I update zb and then have
zb_list.push_back(zb);
I also have
Rcout << (zb_list[itr]) << "\n";
Rcout << (zb) << "\n\n";
where itr counts the iterations. These both confirm that zb is changing inside the loop and zb_list keeps track of it.
Then I return zb_list after the loop. When accessing the result in R, the list contains copies of the same zb, the last one computed in the loop. I suspect there is some pass by reference going on... but can't figure it out. I don't have a good understanding of what is going on (tried to use return(wrap(zb_list))without luck) but clearly something is wrong. Also used List zb_list; for defining it which doesn't help. Any suggestions?
EDiT: Here is the minimal working example:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
List test_weird(int ITRmax=2) {
IntegerMatrix zb(2,2);
std::vector<IntegerMatrix> zb_list;
int itr = 0;
while (itr < ITRmax) {
zb( (1+itr)%2 ,(1+itr)%2 ) ++ ;
zb_list.push_back(zb);
Rcout << (zb) << (zb_list[itr]) << "\n\n";
++itr;
}
return List::create(_["zb"] = zb,
_["zb_list"] = zb_list);
}
/*** R
res <- test_weird()
res$zb_list
*/
This the output when the look is running:
0 0
0 1
0 0
0 1
1 0
0 1
1 0
0 1
... and this is the output from R:
> res$zb_list
[[1]]
[,1] [,2]
[1,] 1 0
[2,] 0 1
[[2]]
[,1] [,2]
[1,] 1 0
[2,] 0 1
As you can see both items in the list are the last zb in the loop.
The problem is that push_back(something) makes a copy of something. But if something is a pointer, than subsequent changes will effect all copies of that pointer. In plain C++:
#include <vector>
#include <iostream>
int main() {
std::vector<int*> v;
int* p = new int;
for (int i = 0; i < 2; ++i) {
*p = i;
v.push_back(p);
std::cout << *p << " " << *v[i] << std::endl;
}
std::cout << *v[0] << " " << *v[1] << std::endl;
return 0;
}
produces
$ ./pointer_fun
0 0
1 1
1 1
So if the something is a pointer (like object), which is the case for all Rcpp objects, then you need a deep copy/clone of the object, i.e.
zb_list.push_back(clone(zb));
I am looking for a good way to round an int in Qt to the nearest 5.
e.g:
8 -> 10
12 -> 10
13 -> 15
15 -> 15
17 -> 15
and so on
Rounding in C++ to the nearest integer number usually is done via:
static_cast<int>(number + 0.5);
Now, to round it to the next 5, I would bring it into the system where we can apply this rounding rule (i.e. 5 -> 1, 6 -> 1.2) and then bring it back into the system where 5 really is 5:
int roundToNearestFive(int number)
{
return static_cast<int>(number / 5. + .5) * 5;
}
I find this formulation easiest.
Here a possible solution:
#include<iostream>
int toNearest5(int i) {
int r = i%5, o = 0;
if(r) {
o = r/5. >= .5 ? 5 : 0;
}
return (i-r+o);
}
int main() {
using namespace std;
cout << toNearest5(8) << endl;
cout << toNearest5(12) << endl;
cout << toNearest5(13) << endl;
cout << toNearest5(15) << endl;
cout << toNearest5(17) << endl;
}
The idea is to get the number and round it to the lowest multiple of 5 (you can do that by removing the remainder), that is:
int remainder = i%5;
int rounded = i - remainder;
Now, you can check the remainder and add 5 to the rounded number if the remainder is greater than 2.5, otherwise add 0.
In order to check it, I've divided the remainder by 5 (its upper bound), so that to get a number in [0,1[ and check it with 0.5 to know how to round the original number.
It follows a more compact version of the same function:
int toNearest5(int i) {
int j = i%5;
return (i - j + (j/5. >= .5 ? 5 : 0));
}
I don't know if the Qt framework offers something similar out of the box, but it's a matter of an one line function, you can easily write it for yourself.
Ok, this may seem trivial to some, but I'm stuck.
Here's the algorithm I'm supposed to use:
Here’s a recursive algorithm. Suppose we have n integers in a non-increasing sequence, of which the first is the number k. Subtract one from each of the first k numbers after the first. (If there are fewer than k such number, the sequence is not graphical.) If necessary, sort the resulting sequence of n-1 numbers (ignoring the first one) into a non-increasing sequence. The original sequence is graphical if and only if the second one is. For the stopping conditions, note that a sequence of all zeroes is graphical, and a sequence containing a negative number is not. (The proof of this is not difficult, but we won’t deal with it here.)
Example:
Original sequence: 5, 4, 3, 3, 2, 1, 1
Subtract 1 five times: 3, 2, 2, 1, 0, 1
Sort: 3, 2, 2, 1, 1, 0
Subtract 1 three times: 1, 1, 0, 1, 0
Sort: 1, 1, 1, 0, 0
Subtract 1 once: 0, 1, 0, 0
Sort: 1, 0, 0, 0
Subtract 1 once: -1, 0, 0
We have a negative number, so the original sequence is not graphical.
This seems simple enough to me, but when I try to execute the algorithm I get stuck.
Here's the function I've written so far:
//main
int main ()
{
//local variables
const int MAX = 30;
ifstream in;
ofstream out;
int graph[MAX], size;
bool isGraph;
//open and test file
in.open("input3.txt");
if (!in) {
cout << "Error reading file. Exiting program." << endl;
exit(1);
}
out.open("output3.txt");
while (in >> size) {
for (int i = 0; i < size; i++) {
in >> graph[i];
}
isGraph = isGraphical(graph, 0, size);
if (isGraph) {
out << "Yes\n";
}else
out << "No\n";
}
//close all files
in.close();
out.close();
cin.get();
return 0;
}//end main
bool isGraphical(int degrees[], int start, int end){
bool isIt = false;
int ender;
inSort(degrees, end);
ender = degrees[start] + start + 1;
for(int i = 0; i < end; i++)
cout << degrees[i];
cout << endl;
if (degrees[start] == 0){
if(degrees[end-1] < 0)
return false;
else
return true;
}
else{
for(int i = start + 1; i < ender; i++) {
degrees[i]--;
}
isIt = isGraphical(degrees, start+1, end);
}
return isIt;
}
void inSort(int x[],int length)
{
for(int i = 0; i < length; ++i)
{
int current = x[i];
int j;
for(j = i-1; j >= 0 && current > x[j]; --j)
{
x[j+1] = x[j];
}
x[j+1] = current;
}
}
I seem to get what that sort function is doing, but when I debug, the values keep jumping around. Which I assume is coming from my recursive function.
Any help?
EDIT:
Code is functional. Please see the history if needed.
With help from #RMartinhoFernandes I updated my code. Includes working insertion sort.
I updated the inSort funcion boundaries
I added an additional ending condition from the comments. But the algorithm still isn't working. Which makes me thing my base statements are off. Would anyone be able to help further? What am I missing here?
Ok, I helped you out in chat, and I'll post a summary of the issues you had here.
The insertion sort inner loop should go backwards, not forwards. Make it for(i = (j - 1); (i >= 0) && (key > x[i]); i--);
There's an out-of-bounds access in the recursion base case: degrees[end] should be degrees[end-1];
while (!in.eof()) will not read until the end-of-file. while(in >> size) is a superior alternative.
Are you sure you ender do not go beyond end? Value of ender is degrees[start] which could go beyond the value of end.
Then you are using ender in for loop
for(int i = start+1; i < ender; i++){ //i guess it should be end here
I think your insertion sort algorithm isn't right. Try this one (note that this sorts it in the opposite order from what you want though). Also, you want
for(int i = start + 1; i < ender + start + 1; i++) {
instead of
for(int i = start+1; i < ender; i++)
Also, as mentioned in the comments, you want to check if degrees[end - 1] < 0 instead of degrees[end].