2013-09-16 1 views
3

Я пытаюсь реализовать коды исправления ошибок, и для этого мне нужно взять вектор bool (данные) и умножить его на bool Матрица (матрица генератора помех), выполняющая операции XOR (вместо того, что выглядит как OR по умолчанию по умолчанию BIG). Пример того, что я делаю, можно найти в этом простом учебнике: http://michael.dipperstein.com/hamming/умножение bool с эксклюзивным или не или (с помощью библиотеки собственных матриц)

Мне не обязательно использовать Eigen, поэтому, пожалуйста, не стесняйтесь предлагать что-то другое, кроме Eigen, если у вас есть решение.

Так, например, немного C++ кода, который компилирует, но не совсем работать правильный путь:

#include <Eigen/Dense> 
#include <iostream> 

using namespace std; 
using namespace Eigen; 

typedef Eigen::Matrix<bool, 4, 7> Matrix4by7Bool; 
typedef Eigen::Matrix<bool, 1, 4> Vector4Bool; 
int main() 
{ 
Matrix4by7Bool gm; 
gm << 0,1,1,1,0,0,0, 
     1,0,1,0,1,0,0, 
     1,1,0,0,0,1,0, 
     1,1,1,0,0,0,1; 

Vector4Bool dm; 
dm << 1,0,1,0; 

cout << dm * gm; 
} 

в настоящее время приводит к: 1 1 1 1 0 1 0
но мне нужно: 1 0 1 1 0 1 0

Разница в том, что поведение по умолчанию заключается в умножении, а затем в OR каждое умножение. Поскольку мне нужен XOR вместо OR, интересно, какой лучший способ сделать это с Eigen?

С удовольствием попробуем разобраться, если это не имеет смысла.

BTW, не уверен, если это имеет значение, но я работаю над MacBook Air, используя G ++. Просто скачал Айген так его вероит новейший доступные (eigen3)

Спасибо,
Кита

UPDATE: Учитывая принятым решением ниже, я хотел перепечатывать правильный код в качестве ссылки для людей:

#include <Eigen/Dense> 
#include <iostream> 

using namespace std; 
using namespace Eigen; 

typedef Eigen::Array<bool, 4, 7> Array4by7Bool; 
typedef Eigen::Array<bool, 4, 1> Array1by4Bool; 

struct logical_xor { 
    bool operator() (bool a, bool b) const 
    { 
    return a != b; 
    } 
}; 

int main() 
{ 
    Array4by7Bool gm; 
    gm << 0,1,1,1,0,0,0, 
     1,0,1,0,1,0,0, 
     1,1,0,0,0,1,0, 
     1,1,1,0,0,0,1; 

    Array1by4Bool dm; 
    dm << 1,0,1,0; 

    cout << "result: " << (gm.colwise() * dm).colwise().redux(logical_xor()) << endl; 
} 
+0

Возможно, вы сможете написать свою собственную функцию, используя цикл 'for' и оператор XOR ^(). –

ответ

4

Вы можете имитировать matrix_vector продукт с помощью вещания и частичного сокращения:

struct logical_xor { bool operator(bool a, bool b) { return a != b; } 
result = (gm.array().colwise() * dm.transpose().array()).colwise().redux(logical_xor()); 

Если вы объявляете переменные, как массив и ая уже массив столбца, то это упрощается:

result = (gm.colwise() * dm).colwise().redux(logical_xor()); 
+0

Это краткий. Интересно, хотя, если есть удар производительности, потому что операция умножения происходит, а затем операция трансляции. В то время как в ответе us202 это похоже на его просто переопределение операции? Не ясно, достаточно ли для внутренних функций Eigen, чтобы узнать, действительно ли это так, или насколько это происходит ... –

+0

+1 от меня для этого решения, потому что, в отличие от моего ответа, этот подход дает понять, что XOR на самом деле (математически) тип добавления.Я не думаю, что вы столкнетесь с огромным успехом - у моего решения могут быть проблемы, если компилятор не встраивает операторов или что-то в этом роде. Если это критически важно для производительности, сравните оба решения и сравните их с другим подходом, который не использует Eigen. – us2012

3

Вы может сделать это. Ниже приведено доказательство концепции. Он содержит минимум, необходимый для компиляции вашего примера и предоставления желаемого результата.

Это, вероятно, довольно хрупкий, и это c & p'ed из другого кода, в котором я лежал, поэтому он не заработает никаких очков за то, что он красив или идиоматичен.

Основная идея заключается в том, что вы создаете свой собственный тип bool, где добавление XOR, и предоставить соответствующие операторы и NumTraits вам нужно.

#include <Eigen/Dense> 
#include <iostream> 

using namespace std; 
using namespace Eigen; 

class mybool { 
public: 
    bool b; 
    mybool() { b = false; } 
    mybool(bool b) : b(b) {} 
    mybool(int a) : b(a!=0) {} 
    mybool operator* (const mybool m) const {return m.b & b;} 
    mybool operator+ (const mybool m) const {return m.b^b;} 
    mybool operator+= (const mybool m) {b ^= m.b; return b;} 
    friend ostream& operator<<(ostream& os, const mybool& m); 
}; 

ostream& operator<<(ostream& os, const mybool& m) { os << m.b; return os; } 

namespace Eigen { 
template<> struct NumTraits<mybool> 
{ 
    typedef int Real; 
    typedef mybool Nested; 
    enum { 
    IsComplex = 0, 
    IsInteger = 1, 
    IsSigned = 0, 
    RequireInitialization = 0, 
    ReadCost = 1, 
    AddCost = 2, 
    MulCost = 2 
    }; 
    static Real epsilon() { return 1; } 
}; 
} 


typedef Matrix<mybool, 4, 7> Matrix4by7Bool; 
typedef Matrix<mybool, 1, 4> Vector4Bool; 
int main() 
{ 
    Matrix4by7Bool gm; 
    gm << 0,1,1,1,0,0,0, 
     1,0,1,0,1,0,0, 
     1,1,0,0,0,1,0, 
     1,1,1,0,0,0,1; 

    Vector4Bool dm; 
    dm << 1,0,1,0; 

    cout << dm * gm; 
} 
Смежные вопросы