如何用Z_2中的系数求解稀疏线性系统?

时间:2016-06-22 14:23:18

标签: c++ linear-algebra eigen finite-field

我想用Eigen求解Z_2系数的大型稀疏线性方程组。首先我们尝试了布尔类型,它不起作用,因为1 + 1 = 1布尔值,但我希望1 + 1 = 0。因此,解决方案可能是新的自定义标量类型。但它究竟如何运作?其他软件包或软件的一些建议也是受欢迎的。

1 个答案:

答案 0 :(得分:0)

由于基本类型的运算符不能超载。您需要自定义标量类型。这是告诉你如何做到这一点的基本文件。

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

基本上你需要做3件事。

  
      
  1. 确保T类型支持公共运算符(+, - ,*,/等)
  2.   
  3. 添加struct Eigen :: NumTraits
  4. 的特化   
  5. 定义对您的类型有意义的数学函数。这包括像sqrt,pow,sin,tan,conj,real,imag等标准的,以及特定于特定的abs2。 (参见文件Eigen / src / Core / MathFunctions.h)
  6.   

实际上,您只能定义方程求解所需的运算符和数学函数。

以上链接提供了类型adtl::adouble的简单示例。代码非常短,因为大多数操作已经很好地定义了。在特征源目录unsupported/中,还有另一个第三方类型mpfr::mpreal支持。你可以从这个链接开始。

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

在Eigen源目录中,这些文件与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