Вычисления на алгебраических числах

0

Я хотел бы делать точные вычисления на регулярных многоугольниках. Для этого я написал код, который вы найдете ниже. Но выражение cos*cos не будет компилироваться. По-видимому, умножение не определено для используемого нами типа алгебраического числа. Думаю, мне придется попробовать другой подход. В настоящее время, похоже, есть два кандидата:

  1. RS, по- видимому, предоставляет некоторые более совершенные алгебраические функции, и CGAL поддерживает его. Но я не вижу операторов умножения в связанных заголовках, поэтому я сомневаюсь, что он будет делать умножение так, как я бы хотел.
  2. leda :: real - это тип для алгебраических действительных чисел. Мне, вероятно, придется переписать мой код, но добиться подобных результатов можно. Возможно, я мог бы даже преобразовать cos I, вычисленный в CGAL, к такой leda::real. Похоже, что заголовок LEDA имеет operator*. LEDA бесплатно для моего использования, но все еще закрытого источника. И leda_real.h для CGAL 4.3 выглядит странно: он относится к leda_real not leda::real, поэтому, возможно, он написан для устаревшей версии LEDA. И это, по-видимому, включает в себя себя, что выглядит довольно бессмысленно.

Какой из этих альтернатив лучше всего подходит для построения точного ядра CGAL, способного описывать регулярные n -gons для любого n? Все это работает? Есть ли другая альтернатива, которую я пропускаю?

Поскольку на моем компьютере нет RS или LEDA, я бы предпочел образованное мнение, прежде чем приступить к их созданию, и, возможно, даже написать инструкции по установке ("ebuilds") для моего Linux Gentoo.

#include <string>
#include <iostream>
#include <sstream>
#include <vector>

//define CGAL_USE_RS
#include <CGAL/Gmpz.h>
#include <CGAL/Algebraic_kernel_d_1.h>
#include <CGAL/Algebraic_kernel_rs_gmpz_d_1.h>
#include <CGAL/Homogeneous.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>

#define DBG(x) std::cerr << x << std::endl

typedef CGAL::Gmpz ZZ;
// typedef CGAL::Algebraic_kernel_rs_gmpz_d_1 AK;
typedef CGAL::Algebraic_kernel_d_1<ZZ> AK;
typedef AK::Polynomial_1 Polynomial;
typedef AK::Algebraic_real_1 AA;
typedef AK::Coefficient Coeff;
typedef AK::Bound Bound;
typedef AK::Multiplicity_type Multiplicity;
typedef CGAL::Homogeneous<AK> Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits;
typedef Kernel::Point_2 Point;
typedef Kernel::Segment_2 Segment;
typedef CGAL::Arrangement_2<Traits> Arrangement;

static unsigned run(unsigned short n) {
  AK ak;
  AK::Construct_algebraic_real_1 to_AA = ak.construct_algebraic_real_1_object();
  AK::Solve_1 solve = ak.solve_1_object();
  Polynomial x{CGAL::shift(Polynomial(1), 1)}, twox{2*x};
  Polynomial a{1}, b{x};
  for (unsigned short i = 2; i <= n; ++i) {
    Polynomial c = twox*b - a;
    a = b;
    b = c;
  }
  std::vector<std::pair<AA, Multiplicity>> roots;
  solve(b - 1, std::back_inserter(roots));
  AA one{1}, cos{-2};
  for (auto i = roots.begin(), e = roots.end(); i != e; ++i) {
    AA cur = i->first;
    if (cur < one && cur > cos)
      cos = cur;
  }
  AA sin = CGAL::sqrt(to_AA(1) - cos*cos);
  //DBG("sin="<<CGAL::to_double(sin)<<", cos="<<CGAL::to_double(cos));
  return 0;
}

int main(int argc, char** argv) {
  for (int i = 1; i < argc; ++i) {
    unsigned short n;
    std::istringstream(argv[i]) >> n;
    std::cout << n << ": " << run(n) << std::endl;
  }
  return 0;
}
  • 0
    Вы уверены, что проблема в умножении, а не в функции cos ()? Напомним, что cos (pi) = -1, а число pi является довольно иррациональным числом.
  • 0
    @Cheers: cos что в моем случае это просто имя переменной. Предполагается, что я вычислю cos(2*pi/n) , решив уравнение Tn(x)=1 где Tn - n-й полином Чебышева .
Показать ещё 4 комментария
Теги:
cgal
leda
rs
algebraic-number

1 ответ

1
Лучший ответ

CGAL также поставляется с библиотекой CORE, которая обеспечивает необходимые операции.

Вот некоторый код (предоставленный самим OP), чтобы вычислить, что sin и cos точно:

#include <utility>
#include <CGAL/CORE_Expr.h>
#include <CGAL/Polynomial.h>
#include <CGAL/number_utils.h>

typedef CORE::Expr AA;
typedef CGAL::Polynomial<AA> Polynomial;

// return sin(θ) and cos(θ) for θ = 2π/n
static std::pair<AA, AA> sin_cos(unsigned short n) {
  // We actually use -x instead of x since root_of will give the k-th
  // smallest root but we want the second largest one without counting.
  Polynomial x{CGAL::shift(Polynomial(-1), 1)}, twox{2*x};
  Polynomial a{1}, b{x};
  for (unsigned short i = 2; i <= n; ++i) {
    Polynomial c = twox*b - a;
    a = b;
    b = c;
  }
  a = b - 1;
  AA cos = -CGAL::root_of(2, a.begin(), a.end());
  AA sin = CGAL::sqrt(AA(1) - cos*cos);
  return std::make_pair(sin, cos);
}
  • 0
    Где на самом деле находится документация библиотеки CORE? Интересно, существует ли для него функция solve .
  • 0
    Я не искал документ, но MvG указал на учебник, в котором есть информация. Expr имеет конструктор, который принимает полином и индекс корня (или изолирующего интервала). Также есть функция rootOf.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню