block and expression must have a const value error - c++

I would like to create a matrix B from a block of matrix A. The size of A changes, so I'm trying to achieve the following
Eigen::MatrixXd B(A.block<3,N>(0,0));
where N is columns number of A. I get this error the expression must have constant value. How can I solve this problem? I've tried to use const_cast<> but I still get the same problem.

I think this would work:
Eigen::MatrixXd B = A.block(0, 0, 3, N);
The API documentation of eigen is here.
If N is a variable, it can't be used as a template function argument (<3,N>) because those must be compile-time constants (the compiler generates/instanciates a version of the function block for each combination or template arguments.)

Related

A vector of polynomials each defined as a function

I'm trying to get a vector of polynomials, but within the vector have each polynomial defined by a function in Pari.
For example, I want to be able to output a vector of this form:
[f(x) = x-1 , f(x) = x^2 - 1, f(x) = x^3 - 1, f(x) = x^4 - 1, f(x) = x^5 - 1]
A simple vector construction of vector( 5, n, f(x) = x^n-1) doesn't work, outputting [(x)->my(i=1);x^i-1, (x)->my(i=2);x^i-1, (x)->my(i=3);x^i-1, (x)->my(i=4);x^i-1, (x)->my(i=5);x^i-1].
Is there a way of doing this quite neatly?
Update:
I have a function which takes a polynomial in two variables (say x and y), replaces one of those variables (say y) with exp(I*t), and then integrates this between t=0 and t=1, giving a single variable polynomial in x: int(T)=intnum(t=0,1,T(x,exp(I*t)))
Because of the way this is defined, I have to explicitly define a polynomial T(x,y)=..., and then calculate int(T). Simply putting in a polynomial, say int(x*y)-1, returns:
*** at top-level: int(x*y-1)
*** ^----------
*** in function int: intnum(t=0,1,T(x,exp(I*t)))
*** ^--------------
*** not a function in function call
*** Break loop: type 'break' to go back to GP prompt
I want to be able to do this for many polynomials, without having to manually type T(x,y)=... for every single one. My plan is to try and do this using the apply feature (so, putting all the polynomials in a vector - for a simple example, vector(5, n, x^n*y-1)). However, because of the way I've defined int, I would need to have each entry in the vector defined as T(x,y)=..., which is where my original question spawned from.
Defining T(x,y)=vector(5, n, x^n*y-1) doesn't seem to help with what I want to calculate. And because of how int is defined, I can't think of any other way to go about trying to tackle this.
Any ideas?
The PARI inbuilt intnum function takes as its third argument an expression rather than a function. This expression can make use of the variable t. (Several inbuilt functions behave like this - they are not real functions).
Your int function can be defined as follows:
int(p)=intnum(t=0, 1, subst(p, y, exp(I*t)))
It takes as an argument a polynomial p and then it substitutes for y when required to do so.
You can then use int(x*y) which returns (0.84147098480789650665250232163029899962 + 0.45969769413186028259906339255702339627*I)*x'.
Similarly you can use apply with a vector of polynomials. For example:
apply(int, vector(5, n, x^n*y-1))
Coming back to your original proposal - it's not technically wrong and will work. I just wouldn't recommend it over the subst method, but perhaps if you are were wanting to perform numerical integration over a class of functions that were not representable as polynomials. Let's suppose int is defined as:
int(T)=intnum(t=0,1,T(x,exp(I*t)))
You can invoke it using the syntax int((x,y) -> x*y). The arrow is the PARI syntax for creating an anonymous function. (This is the difference between an expression and a function - you cannot create your own functions that work like PARI inbuilt functions)
You may even use it with a vector of functions:
apply(int, vector(5, n, (x,y)->x^n*y-1))
I am using the syntax (x,y)->x^n*y-1 here which is preferable to the f(x,y)=x^n*y-1 you had in your question, but they are essentially the same. (the latter form also defines f as a side effect which is not wanted so it is better to use anonymous functions.

Arguments for custom unary/binaryExpr() eigen3

I'm trying to eliminate nested for loops by making use of coefficient-wise operations on eigen3 objects. In order to achieve this I have to generalize an already existing function such that I can make us of custom coefficient-wise operations.
I found that eigen provides two functions, unaryExpr() and binaryExpr() (documentation), that allow to implement a custom coefficient-wise operation on eigen Arrays. However, as far as I understand, you can only give one or two arguments to these functions which represent the coefficients from the array itself. I would like to pass other arguments as well to this function since I need these other arguments to complete the calculation.
I would like to generalize the following function
inline Complex expValue(int twoMS, int twoMSPrime, const Matrix2cd& mat)
{
const Vector2cd& bra = getSpinBasisState(twoMSPrime);
const Vector2cd& ket = getSpinBasisState(twoMS);
return bra.adjoint()*mat*ket;
}
All the possible combinations of values for twoMS and twoMSPrime I have stored in an array like this
Eigen::ArrayXXd spinCGPart(16, 2);
So, 16 different combinations and two columns, one for twoMS and one for twoMSPrime.
Instead of looping over all the different combinations, I would like to implement a coefficient-wise operation like so
Eigen::ArrayXXcd result(16, 1);
result = spinCGPart.col(0).binaryExpr(spinCGPart.col(1), generalExpVal);
Where generalExpVal should be something like
complex generalExpVal(int a, int b, const Matrix2cd& mat) const
{
const Vector2cd& bra = getSpinBasisState(b);
const Vector2cd& ket = getSpinBasisState(a);
return bra.adjoint()*mat*ket;
}
I'm stuck with implementing this last function. The documentation for the binaryExpr() looks like it doesn't allow extra parameters to be given to the function. Is this the case? I need to pass mat as an argument since it changes constantly throughout the calculation. Any suggestion regarding eigen or another way of thinking about the problem would be very helpful and appreciated!
Still not sure what you are actually trying to achieve here, but the easiest way (with C++11 or later) to refer to additional objects in your binary functor is to use a lambda expression:
result = spinCGPart.col(0).binaryExpr(spinCGPart.col(1),
[&](int a, int b){return generalExpVal(a,b,mat);});
Fully compiling example: https://godbolt.org/z/PBJJRW
With C++03 you can manually do that using a helper struct, or using e.g., boost::bind.

Assigning elements to Eigen::Vector2d within std vector throws error

I went through few StackOverflow posts but didn't find such error. I am trying to write a simple class which does a few operations on Eigen vectors and matrices. I created a class called MyClass and it has a method by the name MyMethod. It's code is as follows
void MyClass::MyMethod(Eigen::Vector4f X,
std::vector<Eigen::Vector2i> &pixelIndices,
std::vector<Eigen::Vector4f> vertices)
{
// Do some preprocessing
//Deleacring the std vector
std::vector<Eigen::Vector2i> currTriangle(3);
currTriangle[0] = Eigen::Vector2i(0); //Error occurs here
// Do some more processing
}
Upon executing method from a main function error occurs at the said statement. The error output is given below.
$: ./test1
test1: /usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:285: void Eigen::PlainObjectBase<Derived>::resize(Eigen::Index) [with Derived = Eigen::Matrix<int, 2, 1>; Eigen::Index = long int]: Assertion `((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime==Dynamic || size<=MaxSizeAtCompileTime)) || SizeAtCompileTime == size) && size>=0' failed.
Aborted (core dumped)
I know that using STL containers with Eigen is problematic, but as mentioned in the documentation the problems seems to be only with fixed size vectorizable Eigen types (that is they should be of 16 byte size), but Vector2i is not such a Eigen type. The assert statement is called in resize() method of PlainObjectBase, which is also weird because I haven't used it anywhere in the code.
Has anyone else faced this error? Any help will be really appreciated.
Update:
The error seems to be not because I used std::vector. I made this small changes to the code.
void MyClass::MyMethod(Eigen::Vector4f X,
std::vector<Eigen::Vector2i> &pixelIndices,
std::vector<Eigen::Vector4f> vertices)
{
// Do some preprocessing
Eigen::Vector2i temp(0); //Same Error occures here also
//Deleacring the std vector
std::vector<Eigen::Vector2i> currTriangle(3);
currTriangle[0] = Eigen::Vector2i(0);
// Do some more processing
}
So it seems like the error occurs when initializing the Vector2i.
As #MarcGlisse pointed out, Vector2i(0) tells to construct a Vector2i with 0 elements, which will fail at runtime. The reason why fixed sized matrices/vectors constructed with a single scalar interpret this as size rather than value is to allow generic functions, where it is not clear whether the size dynamic or fixed:
template<int SizeAtCompileTime>
void foo(){
Eigen::Matrix<int, SizeAtCompileTime, 1> v(actualSize);
// ...
}
There are two border-cases: Passing two integers to a vector with two elements or passing one integer to a vector with one element, will cause the vector to be initialized with that value(s) if the scalar type of the vector can implicitly constructed from the passed integer type -- otherwise, it will be interpreted as size.
To solve your original problem, there are several alternatives:
Eigen::Vector2i temp1(Eigen::Vector2i::Zero());
Eigen::Vector2i temp2(0,0);
// initialize all elements with a Zero vector:
std::vector<Eigen::Vector2i> currTriangle(3, Eigen::Vector2i::Zero());
currTriangle[0].setZero(); // set 0th element to Zero vector
currTriangle[0].setConstant(0); // equivalent to setZero, but works for arbitrary constants
currTriangle[0].array() = 0; // .array() lets you do element-wise operations

How do I compute the absolute value of a vector in Eigen?

How do I compute the absolute value of a vector in Eigen? Since the obvious way
Eigen::VectorXf v(-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0);
v.abs(); // Compute abs value.
does not work.
For Eigen 3.2.1 using p.abs(); in the same way as you would use p.normalize results in a compiler error along the lines of
error: no member named 'abs' in 'Eigen::Matrix' p.abs();
~ ^
so a vector in Eigen is nothing but a Matrix type. To compute the absolute values of a matrix in Eigen one can use p.cwiseAbs() or array conversion p.array().abs();. Both these absolute functions returns a value rather than modifying the variable itself.
So a correct way of doing it would be to do
p = p.cwiseAbs();
or
p = p.array().abs();

Dividing each element in a container between a given number C++

I was multiplying each container against another number so I did the following:
local_it begin = magnitudesBegin;
std::advance(begin , 2);
local_it end = magnitudesBegin;
std::advance(end, 14);
std::transform(begin, end, firstHalf.begin(),
std::bind1st(std::multiplies<double>(),100));
It worked wonders, problem is when doing the same to divide between another container. Here is a working example of my problem:
const std::size_t stabilitySize = 13;
boost::array<double,stabilitySize> secondHalf;
double fundamental = 707;
boost::array<double, stabilitySize> indexes = {{3,4,5,6,7,8,9,10,11,12,13,14,15}};
std::transform(indexes.begin(), indexes.end(), secondHalf.begin(),
std::bind1st(std::divides<double>(),fundamental));
It does divide the container. But instead of dividing each element in the array against 707 it divides 707 between each element in the array.
std::bind1st(std::divides<double>(),fundamental)
The code above takes a functor std::divides<double> that takes two arguments and fixes the value of the first argument to be fundamental. That is it fixes the numerator of the operation and you get the expected result. If you want to bind fundamental to be the denominator, use std::bind2nd.
you can try the following , divide has a completely different operation than multiply, it just divides a constant number by all your elements
std::bind1st(std::multiplies<double>(),1.0/707.0));
If the number 707.0 is something like a fundamental constant, and a division can be seen as a "conversion", let's call it "x to y" (I don't know what your numbers are representing, so replace this by meaningful words). It would be nice to wrap this "x to y" conversion in a free-standing function for re-usability. Then, use this function on std::transform.
double x_to_y(double x) {
return x / 707.0;
}
...
std::transform(..., x_to_y);
If you had C++11 available, or want to use another lambda-library, another option is to write this in-line where being used. You might find this syntax more readable like parameter binding using bind2nd:
std::transform(..., _1 / 707.0); // when using boost::lambda