2016-06-22 2 views
1

Я хочу решить большие разреженные линейные уравнения с коэффициентами в Z_2, используя Eigen. Сначала мы попробовали булевский тип, который не работает, потому что 1 + 1 = 1 в булевом, но я ожидаю 1 + 1 = 0. Следовательно, решение может быть новым настроенным скалярным типом. Но как это работает? Также приветствуются некоторые предложения других пакетов или программного обеспечения.Как решить разреженную линейную систему с коэффициентами в Z_2?

+1

Использование оператора^вместо оператора +? – lorro

+0

@lorro почему? 1^1 = 1. –

+0

'^' бит XOR .. – kangshiyin

ответ

0

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

http://eigen.tuxfamily.org/dox/TopicCustomizingEigen.html#CustomScalarType

В основном вам нужно сделать 3 вещи.

  1. убедитесь, что общий оператор (+, -., *,/И т.д.), которые поддерживаются типа T
  2. добавить специализацию STRUCT Эйген :: NumTraits
  3. определяют математические функции это имеет смысл для вашего типа. Это включает стандартные, такие как sqrt, pow, sin, tan, conj, real, imag и т. Д., А также abs2, который является Eigen специфическим. (См файл Эйген/SRC/CORE/MathFunctions.h)

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

Приведенная выше ссылка представляет собой простой пример для типа adtl::adouble. Код очень короткий, потому что большая часть операций уже определена. В исходном источнике unsupported/ есть еще одна сторонняя форма поддержки mpfr::mpreal. Вы можете начать с этой ссылки.

https://eigen.tuxfamily.org/dox/unsupported/group__MPRealSupport__Module.html

В исходной директории Эйгена эти файлы связаны с поддержкой mpfr::mpreal. Они могут быть полезными.

./unsupported/Eigen/MPRealSupport ./unsupported/test/mpreal/mpreal.h ./unsupported/test/mpreal_support.cpp


Это минимальный рабочий пример с поддержкой матричного умножения в z_2:

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

namespace Z2 { 

struct Scalar { 
    Scalar() : 
     data(0) { 
    } 
    Scalar(bool x) : 
     data(x) { 
    } 
    bool data; 

    inline Scalar operator+=(const Scalar& a) { 
    return data ^= a.data; 
    } 
}; 

inline Scalar abs(const Scalar& a) { 
    return a; 
} 

inline Scalar operator+(const Scalar& a, const Scalar& b) { 
    return a.data^b.data; 
} 

inline Scalar operator*(const Scalar& a, const Scalar& b) { 
    return a.data & b.data; 
} 

template<class E, class CT> 
std::basic_ostream<E, CT> &operator <<(std::basic_ostream<E, CT> &os, 
             const Z2::Scalar &m) { 
    return os << m.data; 
} 

} 

namespace Eigen { 
// follow all other traits of bool 
template<> struct NumTraits<Z2::Scalar> : NumTraits<bool> { 
    typedef Z2::Scalar Real; 
    typedef typename internal::conditional<sizeof(Z2::Scalar) <= 2, float, double>::type NonInteger; 
    typedef Z2::Scalar Nested; 
}; 
} 

int main(void) { 
    using namespace Eigen; 
    Matrix<Z2::Scalar, Dynamic, Dynamic> x(2, 2), y(2, 2), i(2, 2), j(2, 2); 
    x.row(0) << 1, 1; 
    y.col(0) << 1, 1; 
    i.setIdentity(); 
    j = i.array() + 1; 
    std::cout << "x=\n" << x << std::endl; 
    std::cout << "y=\n" << y << std::endl; 
    std::cout << "i=\n" << i << std::endl; 
    std::cout << "j=\n" << j << std::endl; 
    std::cout << "x+y=\n" << x + y << std::endl; 
    std::cout << "x.*y=\n" << x.array() * y.array() << std::endl; 
    std::cout << "y*j=\n" << y * j << std::endl; 
    std::cout << "abs(x)=\n" << x.array().abs() << std::endl; 
    return 0; 
} 

Результат:

x= 
1 1 
0 0 
y= 
1 0 
1 0 
i= 
1 0 
0 1 
j= 
0 1 
1 0 
x+y= 
0 1 
1 0 
x.*y= 
1 0 
0 0 
y*j= 
0 1 
0 1 
abs(x)= 
1 1 
0 0 
+0

Да, теперь я знаю, что^- правильный оператор. Однако, как я уже говорил, я хочу решить разреженную линейную систему, используя пакет Eigen. Поэтому на самом деле я хочу сначала определить bool -значную матрицу, такую ​​как Eigen :: Matrix (m, n, BOOL), этот BOOL - это тип bool с модифицированным оператором, как вы сказали. Я не знаю, как это реализовать. –

+0

@ Misery я вижу. Вот почему вам нужна перегрузка. – kangshiyin

+0

это потрясающе. Я очень благодарен. Но для того, чтобы решить линейную систему, мне все равно придется перегружать много операторов, таких как -,>, ... Большинство из них работают хорошо, за исключением того, что: 1. Мне нужно перегрузить некоторые функции, такие как sqrt, abs, я сделал это выглядит так: 'namespace std {Z2 :: Scalar abs (Z2 :: Scalar & a) {return a.data; } Z2 :: Scalar sqrt (Z2 :: Scalar & a) {return a.данные; }} «Но он все еще не работал и сказал, что никакой подходящей функции. Есть ли у вас какие-либо идеи? –

Смежные вопросы