Класс разреженных матриц с параметризуемым "нулем" - PullRequest
12 голосов
/ 31 августа 2011

Я делаю некоторые вычисления на разреженной матрице с плавающей точкой в ​​домене журнала, поэтому «пустые» записи на самом деле -Inf (используя -FLT_MAX). Я сейчас использую пользовательский класс разреженной матрицы, но мне не терпится поменять местами готовую замену.

Это на C ++. Я хотел взглянуть на сжатые матрицы столбцов в Eigen и Boost uBlas. Однако не ясно, поддерживает ли пользовательское значение «ноль» (возможно, предоставленное параметром шаблона). У кого-нибудь есть предложение?

Разъяснение

Что я хочу, так это: для любой ячейки (i, j), которая не была «задана» ранее, я бы хотел, чтобы mat [i, j] возвращал -Inf ... так что это, возможно, лучше описать как значение «по умолчанию» для «пустых» записей разреженной матрицы.

Я использую это для выполнения HMM-рекурсий (Витерби, сумма-произведение) с вероятностями, которые хранятся в домене журнала, чтобы избежать потери ресурсов.

Я не делаю никаких матричных операций ... По сути, я просто заполняю таблицу динамического программирования. Я хочу использовать класс разреженной матрицы, потому что я только заполняю полосу матрицы и хотел бы эффективно использовать память. Матрицы сжатых полос дадут хорошую производительность, так как я заполняю матрицу «по порядку».

Ответы [ 2 ]

2 голосов
/ 01 сентября 2011

Как насчет этого?

class compressed_matrix_nonzero_default : public boost::numeric::ublas::compressed_matrix<double>
{
    double def;
public:
    compressed_matrix_nonzero_default( int s1, int s2 )
        : boost::numeric::ublas::compressed_matrix<double>(s1,s2)
        , def(0)
    {

    }
    void setDefault( double d ) { def = d; }
    double value( int i, int j )
    {
        typedef boost::numeric::ublas::compressed_matrix<double>::iterator1 it1_t;
        typedef boost::numeric::ublas::compressed_matrix<double>::iterator2 it2_t;
        for (it1_t it1 = begin1(); it1 != end1(); it1++)
        {
            if( it1.index1() <  i )
                continue;
            if( it1.index1() > i ) {
                return def;
            }
            for (it2_t it2 = it1.begin(); it2 != it1.end(); it2++)
            {
                if( it2.index2() < j )
                    continue;
                if( it2.index2() == j )
                    return *it2;
                if( it2.index2() > j )
                    return def;
            }


        }
        return def;
    }

};

Использование

compressed_matrix_nonzero_default MNZ(3,3);
MNZ.setDefault(-100);
MNZ (1,1) = 45;

for( int i = 0; i < 3; i++ ) {
    for( int j = 0; j < 3; j++ ) {
        std::cout << MNZ.value(i,j) << ",";
    }
    std::cout << "\n";
}
1 голос
/ 01 сентября 2011

Решение, которое я сейчас приготовил, заключается в следующем.Определите класс lfloat:

class lfloat {
  float value;
public:
  lfloat(float f=-FLT_MAX)
  {
    value = f;
  }

  lfloat& operator=(float f)
  {
    value = f;
    return *this;
  }

  operator float()   { return value; }
};

и используйте его следующим образом:

compressed_matrix<lfloat> M1(3,3);

Таким образом, мы не переписываем какие-либо функциональные возможности в классах матрицы повышения, но мы должныполучить желаемый результат.

...