0
votes


Basically I wrote code to simulate one encoded data vector over a AWGN channel. The simulation but only works once. So I would like to create multiple objects or find a way to run the code multiple times depending on int N (for example int N = 1000000; in my case), so that I can calculate the BER (bit error rate). I haven't found an elegant way to do that yet though... I hope you understand my question.
Do you need more information?
Thank you!!

#include <iostream>
#include "encode.h"
#include "awgn.h"
#include "decode.h"

using namespace Eigen;

int main()
{
    std::string code = "Hamming";
    int dim_u, dim_mat_col, dim_mat_row, dim_mat_col_H, dim_mat_row_H;
    MatrixXi P;
    if (code == "Hamming")
    {
        dim_u = 4;       // can also call it "k"
        dim_mat_col = 7; // also serves as dim of x and y, or simply n
        dim_mat_row = 4;
        dim_mat_col_H = dim_mat_col;
        dim_mat_row_H = dim_mat_col - dim_mat_row;
        P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
        P << 1, 1, 0,
            0, 1, 1,
            1, 1, 1,
            1, 0, 1;
    }

    if (code == "BCH")
    {
        dim_u = 7;
        dim_mat_col = 15; // also serves as dim of x and y, or simply n
        dim_mat_row = 7;
        dim_mat_col_H = dim_mat_col;
        dim_mat_row_H = dim_mat_col - dim_mat_row;
        P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
        P << 1, 1, 1, 0, 1, 0, 0, 0,
            0, 1, 1, 1, 0, 1, 0, 0,
            0, 0, 1, 1, 1, 0, 1, 0,
            0, 0, 0, 1, 1, 1, 0, 1,
            1, 1, 1, 0, 0, 1, 1, 0,
            0, 1, 1, 1, 0, 0, 1, 1,
            1, 1, 0, 1, 0, 0, 0, 1;
    }

    if (code == "Golay")
    {
        dim_u = 12;
        dim_mat_col = 24; // also serves as dim of x and y, or simply n
        dim_mat_row = 12;
        dim_mat_col_H = dim_mat_col;
        dim_mat_row_H = dim_mat_col - dim_mat_row;
        P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
        P << 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1,
            0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0,
            0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1,
            1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0,
            1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1,
            1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
            1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1,
            1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0,
            0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1,
            0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0,
            0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1,
            1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1;
    }

    int N = 1000000; // number of simulations
    bool c_hat_minus_c = 0;
    int val = 0;

    Encode vec(dim_u, dim_mat_row, dim_mat_col);
    awgn channel(dim_mat_col);
    Decode dec(dim_mat_col, dim_mat_row_H, dim_mat_col_H, P);

    vec.encodeDataVector(dim_u, dim_mat_col, P);
    // std::cout << "modulated x: " << vec.x << std::endl;
    channel.addGausian(vec.x);
    // std::cout << channel.y << std::endl;

    c_hat_minus_c = dec.decodingalg(6000, channel.y, P, vec.x); // check if codeword is received correctly
                                                                //   std::cout << channel.y << std::endl;

    // std::cout << "val: " << val << std::endl;
}

If I wrap the stack allocated objects in a for loop like this:

for (int i = 0; i < N; i++)
    {
        Encode vec(dim_u, dim_mat_row, dim_mat_col);
        awgn channel(dim_mat_col);
        Decode dec(dim_mat_col, dim_mat_row_H, dim_mat_col_H, P);

        vec.encodeDataVector(dim_u, dim_mat_col, P);
        // std::cout << "modulated x: " << vec.x << std::endl;
        channel.addGausian(vec.x);
        // std::cout << channel.y << std::endl;

        c_hat_minus_c = dec.decodingalg(6000, channel.y, P, vec.x); // check if codeword is received correctly
                                                                    //   std::cout << channel.y << std::endl;

        // std::cout << "val: " << val << std::endl;
    }

The program breaks and says:

/usr/include/eigen3/Eigen/src/Core/CommaInitializer.h:97: Eigen::CommaInitializer& Eigen::CommaInitializer::operator,(const Eigen::DenseBase&) [with OtherDerived = Eigen::Matrix<int, -1, -1>; XprType = Eigen::Matrix<int, -1, -1>]: Assertion `(m_col + other.cols() <= m_xpr.cols()) && "Too many coefficients passed to comma initializer (operator<<)"' failed.

Edit: so I basically found out that it braks in encode.cpp the second time it tries to initialize the Matrix G_

#include <iostream>
#include "encode.h"
#include "awgn.h"
#include <cstdlib> // rand and srand
#include <ctime>   // For the time function
using namespace std;
using namespace Eigen;

Encode::Encode(int dim_u, int dim_mat_row, int dim_mat_col) //(7,4) Hamming code only up to now
{
    // if (code == "Hamming")
    //     dim_u = 4;
    // dim_mat_col = 7;
    // dim_mat_row = 4;

    u_ = RowVectorXi::Zero(dim_u);
    G_ = MatrixXi::Zero(dim_mat_row, dim_mat_col);
}

void Encode::encodeDataVector(int dim_u, int dim_mat_col, MatrixXi &P)
{

    // Get the system time.
    unsigned seed = time(0);

    // Seed the random number generator.
    srand(seed);

    for (int i = 0; i < dim_u; i++)
    {
        u_(i) = rand() % 2; // only zeros and ones
    }
    // cout << u_ << endl << endl;

    MatrixXi I;

    //  I = MatrixXi::Zero(7, 7);
    I = MatrixXi::Identity(dim_u, dim_u);
    G_ << I, P; **<----- here**

    // cout << G_ << endl << endl;

    x = u_ * G_;

    for (int i = 0; i < dim_mat_col; i++)
    {
        x(i) = x(i) % 2;
    }

    // std::cout << "correct codeword: " << x << std::endl;

    // mapping for BPSK
    for (int i = 0; i < dim_mat_col; i++)
    {
        if (x(i) == 0)
            x(i) = 1;
        else
            x(i) = -1;
    }

    // awgn::awgn channel(dim_mat_col);
    // channel.addGausian(this->x);
}
1
At a guess I would say wrap everything below int N = ... inside a for loop and somehow accumulate the result. - Botje
I already tried that. But I'm not familiar with the lifetime of objects. Basically for every simulation I would need 3 new objects of Encode awgn and Decode as far as I understand it - johnny_b_good
By defining these variables inside the body of the for loop, every iteration gets a fresh set of objects that is cleaned up when the loop ends. Which is what you wanted, no? - Botje
Yes that's what I tried but I'm working with Eigen and after the first iteration it already breaks. It says "too many coefficients passed to comma initializer" ...I not sure where this happens and why - johnny_b_good
Now run your program in a debugger and wait until it catches the assertion; then move up the call stack until you find which of your lines of code triggers it. From the structure of the code, it looks like the shape of P is being modified; in which case you can fix that by simply taking a copy of P at the top of the loop and passing that around. - Botje

1 Answers

0
votes

P is being passed by non-const reference, which means it may be modified by the functions you call. Passing a copy of P in each iteration makes sure that the modifications to P stay local to that iteration:

for (int i = 0; i < N; i++) {
    MatrixXi P_copy = P;
    ...
}