-1

I'm trying my hand at doing some simple convex programming with Armadillo, but I might be getting lost in the syntax (or installation).

I have the following:

int M, N; // these are initialised to > 0 values.
vec X;
vec B = ones<vec>(M); // some vector. It's not actually this, but I include this for clarity

X = join_cols<vec>(zeros<vec>(2*N),join_cols<vec>((abs<vec>(B)+B)*0.5,(abs<vec>(B)-B)*0.5));

And it gives me the compile error:

../L1ConvexSolver.cpp:326:94: error: no matching function for call to ‘join_cols(arma::enable_if2<true, const arma::eOp<arma::eGlue<arma::eOp<arma::Col<double>, arma::eop_abs>, arma::Col<double>, arma::eglue_plus>, arma::eop_scalar_times> >::result, arma::enable_if2<true, const arma::eOp<arma::eGlue<arma::eOp<arma::Col<double>, arma::eop_abs>, arma::Col<double>, arma::eglue_minus>, arma::eop_scalar_times> >::result)’
../L1ConvexSolver.cpp:326:94: note: candidate is:
../../Libraries/armadillo-3.910.1/include/armadillo_bits/fn_join.hpp:17:1: note: template<class T1, class T2> const arma::Glue<T1, T2, arma::glue_join> arma::join_cols(const arma::Base<typename T1::elem_type, T1>&, const arma::Base<typename T1::elem_type, T2>&)

I am getting similar errors elsewhere. I'm also trying to use sp_mat (or SpMat) with inv() or solve() with no dice. In fact, nothing seems to work apart from element acces and basic arithmetic. Do I have an installation issue or is my syntax just wrong?

I'm running it all on Ubuntu 12.04.

EDIT:

Building on Rudolfs' answer, it seems that I was ignoring some of the errors that were given!

It seems that the following works:

X = join_cols<mat>(vec(zeros<vec>(2*N)),join_cols<mat>(vec((abs(B)+B)*0.5),vec((abs(B)-B)*0.5)));

But this doesn't:

X = join_cols<mat>(zeros<vec>(2*N),join_cols<mat>((abs<vec>(B)+B)*0.5,(abs<vec>(B)-B)*0.5));

And the reason is that Armadillo does internal optimisations that can rearrange expressions in a pre-compilation step, but because of that and the fact that join_cols() did not have enough prototypes to cope with all of the glue statements (scalar mult, vector addition, etc) it was failing before Armadillo could preprocess. At least, that's my over-simplified view.

lsdavies
  • 317
  • 2
  • 13
  • The code is wrong. There is no join_cols < mat > () or join_cols < vec > () functions in Armadillo. There is simply join_cols(), without the template specification. Similar for abs(). See my answer below for more details. – mtall Sep 13 '13 at 12:47
  • It compiles with and without the template specifiers, but you're probably right, they aren't necessary. However, what IS necessary is the encapsulation of the inner arguments in constructors, which I see in your answer you have omitted. – lsdavies Sep 13 '13 at 15:21
  • Umm? The code in my answer compiles. What do you mean by "encapsulation of the inner arguments in constructors" ? – mtall Sep 15 '13 at 14:38

2 Answers2

3

Are you sure you can call the join on vectors? At least looking at the documentation and given a fast look at the function definition it seems that it works on mat objects, since this code compiles fine:

mat m1, m2;
mat m3 = join_cols<mat>(m1, m2);

also

vec v1, v2;
vec v3 = join_cols<mat>(v1, v2);

works. I'd suggest you try the second example to see if the results are correct, maybe the library is not sure how to interpret a vector in a column join operation. But since vec is just a subclass of mat (logically a matrix with one row) i'd guess it works.

Rudolfs Bundulis
  • 11,636
  • 6
  • 33
  • 71
  • Thanks for the reply, and you're right it seems that join_cols does not work for vec. My next question would be is there an alternative e.g. an append() method? I can't find much about it in the documentation except the Matlab/Octave conversion table at http://arma.sourceforge.net/docs.html#syntax . I could just use 1D mats and be done with it. Second question is, do I have to write my own inv() function for sp_mat? – lsdavies Sep 13 '13 at 11:46
  • I'd suggest accepting and making a new thread with the nex questions since that is the convention here - we can't do an explicitly large thread with comments. That's for one. Second - did you try the second code example i provided to see what results it returns? – Rudolfs Bundulis Sep 13 '13 at 12:08
  • vec v3 = join_cols < mat > (v1, v2) is not right. As soon as your inputs to join_cols() are matrix expressions, the code is not going to work. Use join_cols(v1,v2) instead. – mtall Sep 15 '13 at 14:39
0

You don't need to have the template specification when using join_cols(). For example, you don't need to do join_cols< vec >(X). Simply do join_cols(X) without the < vec >. Similar for abs< vec >(X): use abs(X) instead.

The reason the ones< vec > and zeros< vec > functions need the template specification is to tell the compiler what type of object is being generated, as it can't work it out simply from the input argument (which is just an integer specifying the length). In contrast, join_cols() and abs() already know the input type (ie. vectors and matrices).

In summary, instead of

X = join_cols<vec>(zeros<vec>(2*N),join_cols<vec>((abs<vec>(B)+B)*0.5,(abs<vec>(B)-B)*0.5));

do this:

X = join_cols(zeros<vec>(2*N),join_cols((abs(B)+B)*0.5,(abs(B)-B)*0.5));
mtall
  • 3,574
  • 15
  • 23