Как я могу решить разреженную линейную систему с коэффициентами в Z_2?

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

1

Решение

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

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

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

  1. убедитесь, что общий оператор (+, -, *, / и т. д.) поддерживается типом T
  2. добавить специализацию структуры Eigen :: NumTraits
  3. определить математические функции, которые имеют смысл для вашего типа. Это включает в себя стандартные, такие как 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
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]