Я хочу решить большие разреженные системы линейных уравнений с коэффициентами в Z_2, используя Eigen. Сначала мы попробовали логический тип, который не работает, потому что 1 + 1 = 1 в логическом, но я ожидаю 1 + 1 = 0. Следовательно, решение может быть новым настроенным скалярным типом. Но как именно это работает? Некоторые предложения других пакетов или программного обеспечения также приветствуются.
Так как операторы для фундаментальных типов не могут быть перегружены. Вам нужен индивидуальный скалярный тип. Вот основной документ, рассказывающий вам, как это сделать.
http://eigen.tuxfamily.org/dox/TopicCustomizingEigen.html#CustomScalarType
В основном вам нужно сделать 3 вещи.
- убедитесь, что общий оператор (+, -, *, / и т. д.) поддерживается типом T
- добавить специализацию структуры Eigen :: NumTraits
- определить математические функции, которые имеют смысл для вашего типа. Это включает в себя стандартные, такие как sqrt, pow, sin, tan, coni, real, imag и т. Д., А также abs2, который является специфическим для Eigen. (см. файл Eigen / src / Core / MathFunctions.h)
На самом деле вы можете определить только те операторы и математические функции, которые необходимы для решения уравнений.
Приведенная выше ссылка предоставляет простой пример для типа adtl::adouble
, Код очень короткий, потому что большинство операций уже четко определены. В собственном каталоге dir unsupported/
есть еще один сторонний тип mpfr::mpreal
служба поддержки. Вы можете начать с этой ссылки.
https://eigen.tuxfamily.org/dox/unsupported/group__MPRealSupport__Module.html
В директории Eigen source эти файлы связаны с mpfr::mpreal
служба поддержки. Они могут быть полезны.
./ Неподдерживаемый / Эйген / 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
Других решений пока нет …