In Matlab, this function blkdiag construct block diagonal matrix. For example, if I have
a = [ 2, 2;
2, 2]
Then blkdiag(a,a) will return this output
>> blkdiag(a,a)
ans =
2 2 0 0
2 2 0 0
0 0 2 2
0 0 2 2
Is there an alternative in Eigen Library for blkdiag? The size of the big matrix varies which means classical approaches won't work. I mean to directly construct a matrix like the aforementioned output.
A simple function like
MatrixXd blkdiag(const MatrixXd& a, int count)
{
MatrixXd bdm = MatrixXd::Zero(a.rows() * count, a.cols() * count);
for (int i = 0; i < count; ++i)
{
bdm.block(i * a.rows(), i * a.cols(), a.rows(), a.cols()) = a;
}
return bdm;
}
does the job.
If the argument sub-matrix a can be fixed-size or dynamic-size or an expression then the following is a better choice
template <typename Derived>
MatrixXd blkdiag(const MatrixBase<Derived>& a, int count)
{
MatrixXd bdm = MatrixXd::Zero(a.rows() * count, a.cols() * count);
for (int i = 0; i < count; ++i)
{
bdm.block(i * a.rows(), i * a.cols(), a.rows(), a.cols()) = a;
}
return bdm;
}
Your problem is already solved! Just see the eigen documentation for topleftcorner and bottomrightcorner in http://eigen.tuxfamily.org/dox/classEigen_1_1DenseBase.html#a6f5fc5fe9d3fb70e62d4a9b1795704a8 and http://eigen.tuxfamily.org/dox/classEigen_1_1DenseBase.html#a2b9618f3c9eb4d4c9813ae8f6a8e70c5 respectively.
All you have to do is assign a matrix to those places, more or less like this:
//Assuming A is the result and has the right size allocated with zeroes, and a is the matrix you have.
A.topLeftCorner(a.rows(),a.cols())=a;
same for bottom right corner, unless you want to flip matrix (try methods .reverse() and .transpose() to get the desired flip effect) a before copying it there.
You can also try the .block() function for better handling of the matrices.
Related
The problem I'm having is that I'm unsure how I can multiply matrices together by the same matrices over and over. What I'm trying to achieve is that I want to be able to update the matrices. Here is my code:
int fib3(int a, int b, int n) {
int num[2][2] = { {0,1}, {1,1} };
const int num2[2][2] = { {0,1}, {1,1} };
int factArray[2][1] = { {0}, {1} };
if (n == 0) {
return a;
}
else if (n == 1) {
return b;
}
else {
for (int i = 0; i <= n; i++) {
num[0][0] = ((num2[0][0] * 0) + num2[0][1] * 1);
num[0][1] = ((num2[0][0] * 1) + num2[0][1] * 1);
num[1][0] = ((num2[1][0] * 0) + num2[1][1] * 1);
num[1][1] = ((num2[1][0] * 1) + num2[1][1] * 1);
}
factArray[0][0] = ((num[0][0] * factArray[0][0]) + num[0][1] * factArray[1][0]);
factArray[1][0] = ((num[1][0] * factArray[0][0]) + num[1][1] * factArray[1][0]);
return factArray[0][0];
}
Here I would take the previous matrices and multiply it by a constant matrices, but I am unsure how to update the matrices as I do.
So the matrices is raised to some power.
So for example, I want to find f(5) the 5th Fibonacci sequence , which should be 5, and I am getting 1 as the result in the programming.
The formula in matrix representation is mainly of interest for theoretical analysis. The trick is that you can have always two elements of the sequence in the vector instead of having to refer to earlier elements of the sequence. However, to implement it I dont see the benefit compared to using the recursive formula. Condsider that
| 1 1 | | a | | a+b |
| 1 0 | * | b | = | a |
Hence the matrix multiplication effectively does exactly the same: add the last two elements, remeber current one (a).
That being said, your code has some problems:
you pass a and b but you only ever use them for the first and second element of the sequence. You dont need a and b. The initial values are already in the starting value of the matrix.
you have a loop, but in each iteration you calculate the same values and write them into the same array elements.
I cannot really follow the logic of your code. Why is there another multiplication after the loop? The matrix formula says, in a nutshell, "take some starting vector, apply a matrix n times, done". To be honest I cannot find that anywhere in your code ;)
If you insist on using matrix multiplications, I would suggest to stay away from c-style arrays. They don't like to be passed around. Use std::array instead. I have a slight aversion against nesting, hence I'd suggest to use
constexpr size_t N = 2;
using matrix = std::array<int,N*N>;
using vector = std::array<int,N>;
std::arrays can be returned with no pain:
vector multiply(const matrix& a,const vector& b) {
vector result;
auto ma = [&a](size_t row,size_t col) { return a[row*N+col];};
result[0] = ma(0,0)*b[0] + ma(0,1)*b[1];
result[1] = ma(1,0)*b[0] + ma(1,1)*b[1];
return result;
}
Now it should be straight-forward to implement the fibonacci sequence.
Spoiler Alert
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
The community reviewed whether to reopen this question 7 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I'm trying to implement a 1-dimensional convolution in "valid" mode (Matlab definition) in C++.
It seems pretty simple, but I haven't been able to find a code doing that in C++ (or any other language that I could adapt to as a matter of fact). If my vector size is a power, I can use a 2D convolution, but I would like to find something that would work for any input and kernel.
So how to perform a 1-dimensional convolution in "valid" mode, given an input vector of size I and a kernel of size K (the output should normally be a vector of size I - K + 1).
Pseudocode is also accepted.
You could use the one of the following implementations:
Full convolution:
template<typename T>
std::vector<T>
conv(std::vector<T> const &f, std::vector<T> const &g) {
int const nf = f.size();
int const ng = g.size();
int const n = nf + ng - 1;
std::vector<T> out(n, T());
for(auto i(0); i < n; ++i) {
int const jmn = (i >= ng - 1)? i - (ng - 1) : 0;
int const jmx = (i < nf - 1)? i : nf - 1;
for(auto j(jmn); j <= jmx; ++j) {
out[i] += (f[j] * g[i - j]);
}
}
return out;
}
f : First sequence (1D signal).
g : Second sequence (1D signal).
returns a std::vector of size f.size() + g.size() - 1, which is the result of the discrete convolution aka. Cauchy product (f * g) = (g * f).
LIVE DEMO
Valid convolution:
template<typename T>
std::vector<T>
conv_valid(std::vector<T> const &f, std::vector<T> const &g) {
int const nf = f.size();
int const ng = g.size();
std::vector<T> const &min_v = (nf < ng)? f : g;
std::vector<T> const &max_v = (nf < ng)? g : f;
int const n = std::max(nf, ng) - std::min(nf, ng) + 1;
std::vector<T> out(n, T());
for(auto i(0); i < n; ++i) {
for(int j(min_v.size() - 1), k(i); j >= 0; --j) {
out[i] += min_v[j] * max_v[k];
++k;
}
}
return out;
}
f : First sequence (1D signal).
g : Second sequence (1D signal).
returns a std::vector of size std::max(f.size(), g.size()) - std::min(f.size(), g.size()) + 1, which is the result of the valid (i.e., with out the paddings) discrete convolution aka. Cauchy product (f * g) = (g * f).
LIVE DEMO
In order to perform a 1-D valid convolution on an std::vector (let's call it vec for the sake of the example, and the output vector would be outvec) of the size l it is enough to create the right boundaries by setting loop parameters correctly, and then perform the convolution as usual, i.e.:
for(size_t i = K/2; i < l - K/2; ++i)
{
outvec[i] = 0.0;
for(size_t j = 0; j < K+1; j++)
{
outvec[i - K/2] += invec[i - K/2 + j] * kernel[j];
}
}
Note the starting and the final value of i.
Works for any 1-D kernel of any size - provided that the kernel is not of bigger size than vector ;)
Note that I've used the variable K as you've described it, but personally I would've understand the 'size' different - a matter of taste I guess. In this example, the total length of the kernel vector is K+1. I've also assumed that the outvec already has l - K elements (BTW: output vector has l - K elements, not l - K + 1 as you have written), so no push_back() is needed.
I don't understand why you need to implement a convolution function. Doesn't Matlab have a built-in 1D convolution function?
Putting that aside, you can implement convolution given a Fourier transform function. You need to be careful about the length of the input and output vectors. The length of the result is I + K - 1 (not I - K + 1, right?). Extend each input vector with zeros to length N where N is the power of 2 greater than or equal to I + K - 1. Take the Fourier transform of the inputs, then multiple the results element by element. Take the inverse Fourier transform of that product, and return the first I + K - 1 elements (throw the rest away). That's your convolution.
You may need to throw in a scaling factor of 1/N somewhere since there is no universally-agreed scaling for Fourier transforms, and I don't remember what Matlab assumes for that.
I am trying to find the indefinite integral of a polynomial, however neither my maths nor my coding is great. My code compiles but I believe I have the wrong formula:
Polynomial Polynomial :: indefiniteIntegral() const
{
Polynomial Result;
Result.fDegree = fDegree + 1;
for ( int i = fDegree; i > 0 ; i--){
Result.fCoeffs[i] = pow(fCoeffs[i], (Result.fDegree)) / (Result.fDegree);
}
return Result;
}
Looks like what you want is
for ( int i = fDegree; i > 0; --i ) {
Result.fCoeffs[i] = fCoeffs[i-1] / static_cast<float>(i);
}
I don't know the underlying implementation of your class, so I don't know how you're implementing fCoeffs (if its doubles or floats) and if you need to worry about i being out of bounds. If its a vector then it definitely needs to be initialized to the right size; if its a map, then you may not need to.
Try something like
Polynomial Polynomial::indefiniteIntegral() const
{
Polynomial Result;
Result.fDegree = fDegree + 1;
for (int i = fDegree; i > 0 ; i--) {
Result.fCoeffs[i] = fCoeffs[i-1] / i;
}
Result.rCoeffs[0] = 0;
return Result;
}
Each monomial a x^i is stored as value a in fCoeffs[i], after integration it should be moved to fCoeffs[i+1], multiplied with 1/(i+1). The lowest coefficient is set to 0.
And yes, you better make sure there is room for the highest coefficient.
Example: [1 1] is 1 + x and should become C + x + 1/2 x^2 which is represented by [0 1 0.5], keeping in mind that we introduced an arbitrary constant.
Ive been recently reading Matrix Tutorials with openGL and stumbled upon an optimized method for Matrix Multiplication that I cannot understand.
//Create an allias type for a Matrix Type
typedef struct Matrix
{
float m[16];
} Matrix;
//default matrix
static const Matrix IDENTITY_MATRIX = { {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
} };
Matrix MultiplyMatrices(const Matrix* m1, const Matrix* m2)
{
Matrix out = IDENTITY_MATRIX;
unsigned int row, column, row_offset;
for (row = 0, row_offset = row * 4; row < 4; ++row, row_offset = row * 4)
for (column = 0; column < 4; ++column)
out.m[row_offset + column] =
(m1->m[row_offset + 0] * m2->m[column + 0]) +
(m1->m[row_offset + 1] * m2->m[column + 4]) +
(m1->m[row_offset + 2] * m2->m[column + 8]) +
(m1->m[row_offset + 3] * m2->m[column + 12]);
return out;
}
These are the questions I have:
In the method MultiplyMatrices why is there a pointer to params m1 and m2? If your just copying their values and returning a new matrix why use a pointer?
Why is the for loop condition identical to its increment?
for (row = 0, row_offset = row * 4; row < 4; ++row, row_offset = row *
4)
The MultiplyMatrices function calculates the product of two matrices. So that's why you need two matrices as the input arguments of this function. Note that the definition of the matrix
typedef struct Matrix
{
float m[16];
} Matrix;
defines a 4 by 4 matrix with a 1-D array. So the offset is 4 for each row. This is just to simulate a 2-D matrix with 1-D array. You need to pass in pointers to two input matrices so that you can get their element values inside the function.
The reason why you see two identical statements in the for loop is:
for (row = 0, row_offset = row * 4; row < 4; ++row, row_offset = row * 4)
Initially the row_offset is set to 0. When the loop is going through each row in the matrix, the row_offset is increasing with row. This is because in the 1-D array representation of 2-D matrix, the a[i][j] element can be written as:
a[i][j] = a[i*num_col+j]
And here num_col is 4. So these two statements are not the same. The first is to initialize. The second is to reset the row_offset when the row index increases by 1.
In the method MultiplyMatrices why is there a pointer to m1 and m2? If your just copying their values why use a pointer?
Maybe I don't understand your question, but how would you propose to do it differently? You're outputting the product into a third memory location out which is the product of m1 and m2. This is the most efficient way..
Why is the for loop condition identical to its increment?
It's not - the ++row increments row before the assignment on each loop. The "condition" is row < 4 which you did not bold - maybe that's the confusion.
In C++ I need to calculate the determinant of a 6x6 matrix really fast.
This is how I would do this for a 2x2 matrix:
double det2(double A[2][2]) {
return A[0][0]*A[1][1] - A[0][1]*A[1][0];
}
I want a similar function for the determinant of a 6x6 matrix but I do not want to write it by hand since it contains 6! = 720 terms where each term is the product of 6 elements in the matrix.
Therefore I want to use Leibniz formula:
static int perms6[720][6];
static int signs6[720];
double det6(double A[6][6]) {
double sum = 0.0;
for(int i = 0; i < 720; i++) {
int j0 = perms6[i][0];
int j1 = perms6[i][1];
int j2 = perms6[i][2];
int j3 = perms6[i][3];
int j4 = perms6[i][4];
int j5 = perms6[i][5];
sum += signs6[i]*A[0]*A[j0]*A[1]*A[j1]*A[2]*A[j2]*A[3]*A[j3]*A[4]*A[j4]*A[5]*A[j5];
}
return sum;
}
How do I find the permutations and the signs?
Is there some way I could get the compiler to do more of the work (e.g. C macros or template metaprogramming) so that the function would be even faster?
EDIT:
I just timed the following code (Eigen):
Matrix<double,6,6> A;
// ... fill A
for(long i = 0; i < 1e6; i++) {
PartialPivLU< Matrix<double,6,6> > LU(A);
double d = LU.determinant();
}
to 1.25 s. So using LU or Gauss decomposition is definitely fast enough for my use!
Use Gauss method to make the matrix upper-triangular. For every operation you know how determinant is changed (not changed of multiplied by constant d) and it works in O(n^3). After that just multiply numbers on main diagonal and delete to product of all d's
Use Eigen, An example can be found here.