Algebraic Kernel ( Arithmetic and Algebra) CGAL 4.13 -User Manual

时间:2023-03-08 21:57:51
Algebraic Kernel ( Arithmetic and Algebra) CGAL 4.13 -User Manual

1 Introduction

Real solving of polynomials is a fundamental problem with a wide application range. This package is targeted at providing black-box implementations of state-of-the-art algorithms to determine, compare, and approximate real roots of univariate polynomials and bivariate polynomial systems. Such a black-box is called an Algebraic Kernel. Since this package is aimed at providing more than one implementation, the interface of the algebraic kernels is expressed in concepts. The main concepts provided by this package are the AlgebraicKernel_d_1 for univariate polynomial systems and AlgebraicKernel_d_2 for bivariate polynomial systems, the latter being a refinement of the first.

解多项式是广泛应用的基本问题。本包的目标是对单变量多项式和2变量多项式提供“黑盒”式的艺术性算法实现,支持对这类多项式提供判定、比较和近似根。这个“黑盒”被称为Algebraic Kernel因为本包的目标是提供不只一个实现,所以algebraic kernel接口被表达成概念。本包提供的主概念是用于单变量多项式系统的 AlgebraicKernel_d_1和2变量多项式系统的 AlgebraicKernel_d_2,后者是前者的精炼。

2 Algebraic Kernel Concepts

2.1 Univariate Algebraic Kernel

2.2 Major Types

First of all, the univariate algebraic kernel provides construction, comparison and approximation of real roots of univariate polynomials. Thus, the major public types the AlgebraicKernel_d_1 provides are:

AlgebraicKernel_d_1::Polynomial_1 - the type representing univariate polynomials,

AlgebraicKernel_d_1::Coefficient - the coefficient type of these polynomials,

AlgebraicKernel_d_1::Algebraic_real_1 - the type representing real roots,

AlgebraicKernel_d_1::Bound - the type which is used to approximate these algebraic reals, in particular, it is used to represent the boundaries of isolating intervals.

首先,单变量代数内核(univariate algebraic kernel )提供了对单变量多项式实数根的构造、比较和近似。AlgebraicKernel_d_1提供的公共类型有:

AlgebraicKernel_d_1::Polynomial_1:表示单变量多项式的类型

AlgebraicKernel_d_1::Coefficient:这些多项式的系数类型

AlgebraicKernel_d_1::Algebraic_real_1:表示实数根(解)的类型

AlgebraicKernel_d_1::Bound :用于近似这些代数实数,特别地用于表示隔离的区间(isolating interval)。

2.3 Construction of Algebraic Real Numbers

The kernel provides two different function objects to construct an AlgebraicKernel_d_1::Algebraic_real_1. The most general way is to use AlgebraicKernel_d_1::Isolate_1; The function object takes a univariate polynomial and writes all real roots into a given output iterator. It is also possible to retrieve the multiplicity of each root. The second option is to construct one particular algebraic real using AlgebraicKernel_d_1::Construct_algebraic_real_1. This function object provides construction from the native int type, the coefficient type as well as the bound type. Moreover, it is possible to construct an algebraic real by giving a polynomial and either an isolating interval or the index of the root. A related function object is AlgebraicKernel_d_1::Number_of_solutions_1 computing the number of real roots of a polynomial.

该内核提供了2个对象用于构造AlgebraicKernel_d_1::Algebraic_real_1,最通用的方法是使用AlgebraicKernel_d_1::Isolate_1这个函数对象操作一个单变量多项式并将所有实数根写入一个给定的输出迭代器中。也可以提取每个根的重根。第二个选项是用AlgebraicKernel_d_1::Construct_algebraic_real_1创建一个特定的代数实数。这个对函数对象提供了从本地int类型、系数类型和边界类型(bound type)的创建方法。另外,可以通过给出一个多项式、一个隔离区间或根的序号来生成一个代数实数。计算实数根数量的函数对象是AlgebraicKernel_d_1::Number_of_solutions_1

2.4 Comparison and Approximation of Algebraic Real Numbers

An AlgebraicKernel_d_1::Algebraic_real_1 is model of RealEmbeddable, for instance, it is possible to compare two algebraic reals, to determine the sign of an algebraic real or to ask for its double approximation, see also section secRealEmbeddable. Moreover, AlgebraicKernel_d_1::Compare_1 provides comparison with int, the coefficient type and the bound type.

There are several ways to approximate an AlgebraicKernel_d_1::Algebraic_real_1:

AlgebraicKernel_d_1::Approximate_absolute_1 - provides an approximation that is better than the passed absolute error bound,

AlgebraicKernel_d_1::Approximate_relative_1 - provides an approximation that is better than the passed relative error bound,

AlgebraicKernel_d_1::Isolate_1 - returns an isolating interval with respect to a given univariate polynomial,

A related function object is AlgebraicKernel_d_1::Bound_between_1, which computes a number that isolates two algebraic real numbers.

一个AlgebraicKernel_d_1::Algebraic_real_1类是 RealEmbeddable的模型,它可以对两个代数实数进行比较,判定代数实数的类型或求它的近似值(见secRealEmbeddable节)。另外,提供了int,系数类型和边界类型的比较。

有几种方法可以对一个AlgebraicKernel_d_1::Algebraic_real_1进行近似:

AlgebraicKernel_d_1::Approximate_absolute_1:提供比传入的绝对误差界(passed absolute error bound)更好的近似值;

AlgebraicKernel_d_1::Approximate_relative_1:提供比传入的相对误差界(passed relative error bound)更好的近似值;

AlgebraicKernel_d_1::Isolate_1:对给定的单变量多项式返回一个隔离的区间。

2.5 Interplay with Polynomials

It is also possible to retrieve a representing polynomial from an algebraic real using AlgebraicKernel_d_1::Compute_polynomial_1, which guarantees that the algebraic real is a root of the returned polynomial. As the name already indicates, this operation may be very costly since the polynomial may not be computed yet. Moreover, it is not guaranteed that the returned polynomial is the minimal polynomial of the number. Together with AlgebraicKernel_d_1::Isolate_1, it is possible to retrieve the traditional representation of an algebraic real as a square free polynomial and an isolating interval.

Though the AlgebraicKernel_d_1 does not provide arithmetic operations on AlgebraicKernel_d_1::Algebraic_real_1, it is possible to compute the sign of a polynomial at a given algebraic real using AlgebraicKernel_d_1::Sign_at_1. Or alternatively, just compute whether the polynomial is zero at an algebraic real number using AlgebraicKernel_d_1::Is_zero_at_1. Note that this operation can be significantly less expensive, in particular if the polynomial is not zero at the given algebraic real.

可以用类AlgebraicKernel_d_1::Compute_polynomial_1从给定的代数实数来还原一个多项式,并保证返回的多项式的一个根就是这个代数实数。正如其名称所示,其操作消耗可能非常大(因为这个多项式可能不能计算)。另外,这一操作返回的多项式不保证是该数的最小多项式。与AlgebraicKernel_d_1::Isolate_1一起使用,可能能够以一个无平方多项式和一个隔离区间的方式还原一个传统表达的代数实数(as a square free polynomial and an isolating interval)。

虽然 AlgebraicKernel_d_1不提供对AlgebraicKernel_d_1::Compute_polynomial_1的算术操作,但使用AlgebraicKernel_d_1::Sign_at_1可以计算一个多项式在给定代数实数点的符号。或者可以使用AlgebraicKernel_d_1::Is_zero_at_1只计算多项式在一个代数实数点是否为0。注意,这些操作能够显著低耗,特别是当给定代数实数点此多项式不为0时

2.6 Auxiliary Functionality for Polynomials

First of all the type AlgebraicKernel_d_1::Polynomial_1 is required to be a model of the concept Polynomial_1, which is defined in the Polynomial package (see chapter Chapter_Polynomial). This implies that all essential functionality is provided via Polynomial_traits_d. However, the algebraic kernel also provides several function objects to handle polynomials:

AlgebraicKernel_d_1::Is_square_free_1 - determines whether a polynomial is square free,

AlgebraicKernel_d_1::Make_square_free_1 - computes the square free part of a polynomial,

AlgebraicKernel_d_1::Square_free_factorize_1 - computes a square free factorization of a polynomial,

AlgebraicKernel_d_1::Is_coprime_1 - computes whether a pair of polynomials is square free,

AlgebraicKernel_d_1::Make_coprime_1 - decomposes two polynomials into the coprime factors and their common factor.

Though the polynomial package provides similar functionality we suggest to use the function objects provided by the kernel, since the design of the algebraic kernel allows for instance internal caching by the kernel.

Also note that AlgebraicKernel_d_1::Square_free_factorize_1 only computes the square free factorization up to a constant factor. This is a slight modification with respect to its counterpart in Polynomial_traits_d. In this way it was possible that the concepts just require the coefficient type to be a model of IntegralDomain, instead of Field or UniqueFactorizationDomain. For more details see also:

首先, AlgebraicKernel_d_1::Polynomial_1类型要求是 Polynomial_1概念的一个模型。 Polynomial_1在Polynomial包中定义(见 Polynomial章)。这意味着所有的功能通过Polynomial_traits_d提供。但 AlgebraicKernel_d_1也提供了几个函数对象来操纵多项式:

AlgebraicKernel_d_1::Is_square_free_1 :判定多项式是否是一个无平方的多项式(square free polynomial)。

AlgebraicKernel_d_1::Make_square_free_1:计算一个多项式的无平方部分(square free part)。

AlgebraicKernel_d_1::Square_free_factorize_1 :计算一个多项式的square free因式分解

AlgebraicKernel_d_1::Is_coprime_1:计算是否一对多项式为square free。

AlgebraicKernel_d_1::Make_coprime_1:将两个多项式分解为互质的因子产并求出其公因子。

虽然在多项式包(polynomial package)中提供了相似的功能,我们建议使用本包提供了函数对象,因为代数核心(algebraic kernel)允许实例被内核控制(allows for instance internal caching by the kernel)

需要注意的是:AlgebraicKernel_d_1::Square_free_factorize_1对无平方因式分解只计算到常数因子(Also note that AlgebraicKernel_d_1::Square_free_factorize_1 only computes the square free factorization up to a constant factor.)。这与Polynomial_traits_d.中的相应功能是一种轻微的修改,这样的话,可能会允许系数类型为的IntegralDomain模型,而不需要它是 Field 的或 UniqueFactorizationDomain的模型( In this way it was possible that the concepts just require the coefficient type to be a model of IntegralDomain, instead of Field or UniqueFactorizationDomain.)。更多细节见:

2.7 Design Rationale

Most implementations of an AlgebraicKernel_d_1 will represent an algebraic real number by the root of a square free polynomial and an isolating interval, that is, the number is defined as the only root of the polynomial within the interval. Usually, one will refrain from computing the minimal polynomial since the computation of the minimal polynomial is much more expensive and does not pay of. However, besides the representation by a polynomial and an isolating interval one can also imagine the representation by a polynomial and the index of the root, e.g., as the ith real root when enumerated from minus to plus infinity. Moreover, it may very well be that the kernel just computes an approximation of the number, whereas the representing polynomial is not computed yet. This is in particular relevant in relation to the AlgebraicKernel_d_2, where AlgebraicKernel_d_1::Algebraic_real_1 is used to represent coordinates of solutions of bivariate systems. Hence, the design does not allow a direct access to any, seemingly obvious, members of an AlgebraicKernel_d_1::Algebraic_real_1. Instead there is, e.g., AlgebraicKernel_d_1::Compute_polynomial_1 which emphasizes that the requested polynomial may not be computed yet. Similarly, there is no way to directly ask for the refinement of the current isolating interval since this would impose a state to every object of an AlgebraicKernel_d_1::Algebraic_real_1.

AlgebraicKernel_d_1 的大多数实现一个由无平方多项式和一个隔离区间表示的代数实数值,即这个数被定义为多项式在这一区间内的唯一根。通常,计算一个最小多项式(minimal polynomial)的操作是受限的,主要原因是这种操作如此昂贵又不可行。但是,除了由一个多项式和一个隔离区间表示外,我们也可以想象由一个多项式和根的序号(index of root)表示,即由负无穷向正无穷排序中的第i个根。另外,在不计算表示的多项式(representation polynomial)的情况下,kernel仅计算一个数的近似值也是十分好的,即其多项式不进行计算。这在AlgebraicKernel_d_2中是特别相关的,即当  AlgebraicKernel_d_1::Algebraic_real_1用于表示2变量系统的解的坐标时。由此,这个设计不允许对任何一个AlgebraicKernel_d_1::Algebraic_real_1的成员进行直接操作。因为AlgebraicKernel_d_1::Compute_polynomial_1意味着强调需要的多项式可能没有被计算。相似地,不可能直接要求对当前隔离区间进行精炼,因为这将对所有的AlgebraicKernel_d_1::Algebraic_real_1类型对象赋予了状态。

2.8 Bivariate Algebraic Kernel

The concept AlgebraicKernel_d_2 is a refinement of AlgebraicKernel_d_1, that is, a model of AlgebraicKernel_d_2 is also a model of AlgebraicKernel_d_1. Hence, the AlgebraicKernel_d_2 concept is designed such that occurring names and functionalities are as similar as possible to those in the AlgebraicKernel_d_1 concept. The following are a direct generalization of their univariate counterparts:

AlgebraicKernel_d_2概念是的AlgebraicKernel_d_1精炼,即一个AlgebraicKernel_d_2的模型也是一个AlgebraicKernel_d_1的模型。因此,AlgebraicKernel_d_2概念被设计为与AlgebraicKernel_d_1概念的相应操功能名称 尽量相似。下面的部分直接由单变量相应功能演化而来:

AlgebraicKernel_d_2::Polynomial_2,

AlgebraicKernel_d_2::Algebraic_real_2,

AlgebraicKernel_d_2::Construct_algebraic_real_2,

AlgebraicKernel_d_2::Isolate_2,

AlgebraicKernel_d_2::Is_square_free_2,

AlgebraicKernel_d_2::Make_square_free_2,

AlgebraicKernel_d_2::Square_free_factorize_2,

AlgebraicKernel_d_2::Is_coprime_2,

AlgebraicKernel_d_2::Make_coprime_2,

AlgebraicKernel_d_2::Solve_2,

AlgebraicKernel_d_2::Number_of_solutions_2,

AlgebraicKernel_d_2::Compare_xy_2,

AlgebraicKernel_d_2::Sign_at_2,

AlgebraicKernel_d_2::Is_zero_at_2.

For instance, AlgebraicKernel_d_2::Solve_2 provides the solution for a bivariate polynomial system. However, it is also possible to obtain the coordinates of these solutions with the additional functors:

AlgebraicKernel_d_2::Compute_x_2,

AlgebraicKernel_d_2::Compute_y_2.

例如:AlgebraicKernel_d_2::Solve_2 为2变量多项式系统提供了解。当然,还可能通过下面函子得到这些解的坐标:

AlgebraicKernel_d_2::Compute_x_2,

AlgebraicKernel_d_2::Compute_y_2.

In principal this would be sufficient generalization, since functions such as isolating, approximating algebraic real numbers could be implemented using these access functions ant the corresponding functionalities in the univariate algebraic kernel. However, one should be aware that an AlgebraicKernel_d_2::Algebraic_real_2 is not necessarily represented as a pair of univariate solutions, that is, using AlgebraicKernel_d_2::Compute_y_2 may entail considerable computations. Therefore, the concept also requires the following additional functors that may allow a model to bypass this issue:

原则上,这个generalization已经足够,因为对代数实数的isolating、approximating 函数能够使用单变量代数内核的相应功能的access function 来实现。然而,需要清楚的是AlgebraicKernel_d_2::Algebraic_real_2不必须表达了一对单变量解,即使用AlgebraicKernel_d_2::Compute_y_2可能造成相当大的计算量,所以这个概念也要求下面的附加函子来使模型绕过这一问题:

AlgebraicKernel_d_2::Compute_polynomial_x_2,

AlgebraicKernel_d_2::Compute_polynomial_y_2,

AlgebraicKernel_d_2::Isolate_x_2,

AlgebraicKernel_d_2::Isolate_y_2,

AlgebraicKernel_d_2::Compare_x_2,

AlgebraicKernel_d_2::Compare_y_2,

AlgebraicKernel_d_2::Approximate_absolute_x_2,

AlgebraicKernel_d_2::Approximate_relative_x_2,

AlgebraicKernel_d_2::Approximate_absolute_y_2,

AlgebraicKernel_d_2::Approximate_relative_y_2,

AlgebraicKernel_d_2::Bound_between_x_2,

AlgebraicKernel_d_2::Bound_between_y_2.

3 Models

3.1 Generic Algebraic Kernels

The package provides generic models of the univariate and bivariate algebraic kernel, namely Algebraic_kernel_d_1<Coeff> and Algebraic_kernel_d_2<Coeff>, respectively. Both kernels support a large set of number types as their template argument, which defines the supported coefficient type. The supported types are, for instance, Gmpz and Gmpq as well as the corresponding types of LEDA and CORE.

The Algebraic_kernel_d_1<Coeff> represents an algebraic real root by a square free polynomial and an isolating interval that uniquely defines the root. The current method to isolate roots is the Bitstream Descartes method [6]. The used method to refine the approximation of an algebraic real root is a slightly modified (filtered) version of the one presented in [1]. The method has quadratic convergence.

Algebraic_kernel_d_2<Coeff> is based on an algorithm computing a geometric-topological analysis of a single curve [5] and of a pair of curves [4]. The main idea behind both analyses is to compute the critical x-coordinates of curves and curve pairs by projection (resultants), and compute additional information about the critical fibers using subresultants and Sturm-Habicht sequences [7]. With that information, the fiber at critical x-coordinates is computed by a variant of the Bitstream Descartes method. See also [8] for a comprehensive description of these techniques. Almost all functors in the class that take a Polynomial_2 object as argument trigger such an analysis as a main computation step. For efficiency, these analyses (of single curves and curve pairs) are therefore cached internally for efficiency. For instance, computing the pairwise solutions of 10 Polynomial_2 objects requires 10 curve analyses and 45 curve pair analyses to be computed internally.

A point p of type Algebraic_real_2 is represented by its x-coordinate x0 (as described in the Algebraic_kernel_d_1 paragraph above), an algebraic curve where p lies on, and an integer i, denoting that p is the ith point in the fiber at x0, counted from the bottom (ignoring a possible vertical line at x0). Note that this determines the point uniquely, but the y-coordinate is not stored internally in terms of an Algebraic_real_1 object. Querying such a representation by calling Compute_y_2 is a time-consuming step, and should be avoided for efficiency reasons if possible.

本包提供了单变量和2变量的代数内核的通用模型,即 Algebraic_kernel_d_1<Coeff> 和 Algebraic_kernel_d_2<Coeff>,两个内核各自支持一个用于定义其系数类型的大集合的数据类型作为它们的模板参数。支持的类型为Gmpz和Gmpq及LEDA和CORE的相应类型。

Algebraic_kernel_d_1<Coeff> 表示一个由一个square free多项式和一个isolating 区间表达的代数实数的实数根。当前isloate根的方法是Bitstream Descartes法。本包使用的精炼一个代数实数根的近似值的方法是由文献【1】中的方法稍作修改而来。这个方法是二次收敛的(quadratic convergence)。

Algebraic_kernel_d_2<Coeff>基于一个计算一个曲线和一对曲线的几何拓扑分析算法【5】【4】。其主要思路是通过投射(projection,即resultant)计算曲线或曲线对的临界点的x坐标,并利用子结式(subresultant)和Sturm-Habicht序列计算附加的关于临界fiber的信息。使用这些信息,一个 Bistream Descartes算法的变种计算在临界x坐标处的fiber。了解这些技术请参考文献【8】。本类中几乎所有以polymonial_2对象为参数的函子都会将触发本分析作为其中的主要步骤。为了效率,这些分析(单曲线或曲线对)被cached internally。例如,计算10个polymonial_2的成对的解需要在内部对10条曲线分析和45对曲线分析进行计算。

Algebraic_real_2类型的一个点p由它的x坐标x0表示(正如Algebraic_kernel_d_1上面段描述的),p所在的一个代数曲线和一个序号i(指出p在fiber中x0的序号,从底部开始计数,不考虑通过x0的垂线)。注意,这样将保证点是唯一的,但y坐标并没有以Algebraic_real_1 对象的形式保存在其内部。通过Compute_y_2来求这样的表示是一个耗时的步骤,为了提高效率应当避免。

3.2 Algebraic Kernels Based on RS

The package offers two univariate algebraic kernels that are based on the library RS [13], namely Algebraic_kernel_rs_gmpz_d_1 and Algebraic_kernel_rs_gmpq_d_1. As the names indicate, the kernels are based on the library RS [13] and support univariate polynomials over Gmpz or Gmpq, respectively.

In general we encourage to use Algebraic_kernel_rs_gmpz_d_1 instead of Algebraic_kernel_rs_gmpq_d_1. This is caused by the fact that the most efficient way to compute operations (such as gcd) on polynomials with rational coefficients is to use the corresponding implementation for polynomials with integer coefficients. That is, the Algebraic_kernel_rs_gmpq_d_1 is slightly slower due to overhead caused by the necessary conversions. However, since this may not always be a major issue, the Algebraic_kernel_rs_gmpq_d_1 is provided for convenience.

The core of both kernels is the implementation of the interval Descartes algorithm [12] of the library RS [13], which is used to isolate the roots of the polynomial. The RS library restricts its attention to univariate integer polynomials and some substantial gain of efficiency can be made by using a kernel that does not follow the generic programming paradigm, by avoiding interfaces between layers. Specifically, working with only one number type allows to optimize some polynomial operations as well as memory handling. The implementation of these kernels make heavy use of the Mpfr [11] and Mpfi [10] libraries, and of their CGAL interfaces, Gmpfr and Gmpfi. The algebraic numbers (roots of the polynomials) are represented in the two RS kernels by a Gmpfi interval and a pointer to the polynomial of which they are roots. See [9] for more details on the implementation, tests of these kernels, comparisons with other algebraic kernels and discussions about the efficiency.

本包提供了两个基于RS库的单变量代数内核,即Algebraic_kernel_rs_gmpz_d_1Algebraic_kernel_rs_gmpq_d_1。它是基于RS并通过Gmpz或Gmpq支持单变量多项式。

通常,我们鼓励使用 Algebraic_kernel_rs_gmpz_d_1 ,主要原因是有理系数多项式计算操作(如GCD)大部分都使用相应的整系数多项式的实现来进行。而由于需要进行数据转换所以Algebraic_kernel_rs_gmpq_d_1运行较慢。但是,因为这种情况不会总是我们关心的问题,所以为了方便我们提供了 Algebraic_kernel_rs_gmpq_d_1

两个内核都实现了RS库的区间笛卡尔算法(interval Descartes algorithm),算法用于隔离出多项式的根。

4 Examples

4.1 Construction of Algebraic Real Numbers

The following example illustrates the construction of AlgebraicKernel_d_1::Algebraic_real_1 using AlgebraicKernel_d_1::Construct_algebraic_real_1
File Algebraic_kernel_d/Construct_algebraic_real_1.cpp

// $URL$
// $Id$
#include <CGAL/basic.h>
#ifdef CGAL_USE_MPFI
#include <CGAL/Algebraic_kernel_d_1.h>
#include <CGAL/Gmpz.h>
#include <vector>
#include <iostream>
typedef AK::Polynomial_1 Polynomial_1;
typedef AK::Algebraic_real_1 Algebraic_real_1;
typedef AK::Coefficient Coefficient;
typedef AK::Bound Bound;
typedef AK::Multiplicity_type Multiplicity_type;
int main(){
AK ak; // an object of
AK::Construct_algebraic_real_1 construct_algreal_1 = ak.construct_algebraic_real_1_object();
std::cout << "Construct from int : " << construct_algreal_1(int(2)) << "\n";
std::cout << "Construct from Coefficient : " << construct_algreal_1(Coefficient(2)) << "\n";
std::cout << "Construct from Bound : " << construct_algreal_1(Bound(2)) << "\n\n";
Polynomial_1 x = CGAL::shift(AK::Polynomial_1(1),1); // the monomial x
std::cout << "Construct by index : "
<< construct_algreal_1(x*x-2,1) << "\n"
<< to_double(construct_algreal_1(x*x-2,1)) << "\n";
std::cout << "Construct by isolating interval : "
<< construct_algreal_1(x*x-2,Bound(0),Bound(2)) << "\n"
<< to_double(construct_algreal_1(x*x-2,Bound(0),Bound(2))) << "\n\n";
return 0;
}
#else
int main(){
std::cout << "This example requires CGAL to be configured with library MPFI." << std::endl;
return 0;
}
#endif

4.2 Solving Univariate Polynomials

The following example illustrates the construction of AlgebraicKernel_d_1::Algebraic_real_1 using AlgebraicKernel_d_1::Solve_1
File Algebraic_kernel_d/Solve_1.cpp

// $URL$
// $Id$
#include <CGAL/basic.h>
#ifdef CGAL_USE_MPFI
#include <CGAL/Algebraic_kernel_d_1.h>
#include <CGAL/Gmpz.h>
#include <vector>
typedef AK::Polynomial_1 Polynomial_1;
typedef AK::Algebraic_real_1 Algebraic_real_1;
typedef AK::Bound Bound;
typedef AK::Multiplicity_type Multiplicity_type;
int main(){
AK ak; // an object of
AK::Solve_1 solve_1 = ak.solve_1_object();
Polynomial_1 x = CGAL::shift(AK::Polynomial_1(1),1); // the monomial x
// variant using a bool indicating a square free polynomial
// multiplicities are not computed
std::vector<Algebraic_real_1> roots;
solve_1(x*x-2,true, std::back_inserter(roots));
std::cout << "Number of roots is : " << roots.size() << "\n";
std::cout << "First root should be -sqrt(2): " << CGAL::to_double(roots[0]) << "\n";
std::cout << "Second root should be sqrt(2): " << CGAL::to_double(roots[1]) << "\n\n";
roots.clear();
// variant for roots in a given range of a square free polynomial
solve_1((x*x-2)*(x*x-3),true, Bound(0),Bound(10),std::back_inserter(roots));
std::cout << "Number of roots is : " << roots.size() << "\n";
std::cout << "First root should be sqrt(2): " << CGAL::to_double(roots[0]) << "\n";
std::cout << "Second root should be sqrt(3): " << CGAL::to_double(roots[1]) << "\n\n";
roots.clear();
// variant computing all roots with multiplicities
std::vector<std::pair<Algebraic_real_1,Multiplicity_type> > mroots;
solve_1((x*x-2), std::back_inserter(mroots));
std::cout << "Number of roots is : " << mroots.size() << "\n";
std::cout << "First root should be -sqrt(2): " << CGAL::to_double(mroots[0].first) << ""
<< " with multiplicity " << mroots[0].second << "\n";
std::cout << "Second root should be sqrt(2): " << CGAL::to_double(mroots[1].first) << ""
<< " with multiplicity " << mroots[1].second << "\n\n";
mroots.clear();
// variant computing roots with multiplicities for a range
solve_1((x*x-2)*(x*x-3),Bound(0),Bound(10),std::back_inserter(mroots));
std::cout << "Number of roots is : " << mroots.size() << "\n";
std::cout << "First root should be sqrt(2): " << CGAL::to_double(mroots[0].first) << ""
<< " with multiplicity " << mroots[0].second << "\n";
std::cout << "Second root should be sqrt(3): " << CGAL::to_double(mroots[1].first) << ""
<< " with multiplicity " << mroots[1].second << "\n\n";
return 0;
}
#else
int main(){
std::cout << "This example requires CGAL to be configured with library MPFI." << std::endl;
return 0;
}
#endif

4.3 Comparison and Approximation of Algebraic Real Numbers

The following example illustrates the comparison of AlgebraicKernel_d_1::Algebraic_real_1 numbers: 
File Algebraic_kernel_d/Compare_1.cpp

// $URL$
// $Id$
#include <CGAL/basic.h>
#ifdef CGAL_USE_MPFI
#include <CGAL/Algebraic_kernel_d_1.h>
#include <CGAL/Gmpz.h>
#include <vector>
typedef AK::Coefficient Coefficient;
typedef AK::Polynomial_1 Polynomial_1;
typedef AK::Algebraic_real_1 Algebraic_real_1;
typedef AK::Bound Bound;
typedef std::pair<Bound,Bound> Interval;
int main(){
AK ak;
AK::Construct_algebraic_real_1 construct_algebraic_real_1 = ak.construct_algebraic_real_1_object();
Polynomial_1 x = CGAL::shift(AK::Polynomial_1(1),1); // the monomial x
Algebraic_real_1 a = construct_algebraic_real_1(x*x-2,1); // sqrt(2)
Algebraic_real_1 b = construct_algebraic_real_1(x*x-3,1); // sqrt(3)
// Algebraic_real_1 is RealEmbeddable (just some functions:)
std::cout << "sign of a is : " << CGAL::sign(a) << "\n";
std::cout << "double approximation of a is : " << CGAL::to_double(a) << "\n";
std::cout << "double approximation of b is : " << CGAL::to_double(b) << "\n";
std::cout << "double lower bound of a : " << CGAL::to_interval(a).first << "\n";
std::cout << "double upper bound of a : " << CGAL::to_interval(a).second << "\n";
std::cout << "LessThanComparable (a<b) : " << (a<b) << "\n\n";
// use compare_1 with int, Bound, Coefficient, Algebraic_real_1
AK::Compare_1 compare_1 = ak.compare_1_object();
std::cout << " compare with an int : " << compare_1(a ,int(2)) << "\n";
std::cout << " compare with an Coefficient : " << compare_1(a ,Coefficient(2)) << "\n";
std::cout << " compare with an Bound : " << compare_1(a ,Bound(2)) << "\n";
std::cout << " compare with another Algebraic_real_1: " << compare_1(a ,b) << "\n\n";
// get a value between two roots
AK::Bound_between_1 bound_between_1 = ak.bound_between_1_object();
std::cout << " value between sqrt(2) and sqrt(3) " << bound_between_1(a,b) << "\n";
std::cout << " is larger than sqrt(2) " << compare_1(bound_between_1(a,b),a) << "\n";
std::cout << " is less than sqrt(3) " << compare_1(bound_between_1(a,b),b) << "\n\n";
// approximate with relative precision
AK::Approximate_relative_1 approx_r = ak.approximate_relative_1_object();
std::cout << " lower bound of a with at least 100 bits: "<< approx_r(a,100).first << "\n";
std::cout << " upper bound of a with at least 100 bits: "<< approx_r(a,100).second << "\n\n";
// approximate with absolute error
AK::Approximate_absolute_1 approx_a = ak.approximate_absolute_1_object();
std::cout << " lower bound of b with error less than 2^-100: "<< approx_a(b,100).first << "\n";
std::cout << " upper bound of b with error less than 2^-100: "<< approx_a(b,100).second << "\n\n";
return 0;
}
#else
int main(){
std::cout << "This example requires CGAL to be configured with library MPFI." << std::endl;
return 0;
}
#endif

4.4 Isolation of Algebraic Real Numbers with respect to roots of other polynomials

The following example illustrates the isolation of AlgebraicKernel_d_1::Algebraic_real_1 numbers: 
File Algebraic_kernel_d/Isolate_1.cpp

// $URL$
// $Id$
#include <CGAL/basic.h>
#ifdef CGAL_USE_MPFI
#include <CGAL/Algebraic_kernel_d_1.h>
#include <CGAL/Gmpz.h>
#include <vector>
typedef AK::Polynomial_1 Polynomial_1;
typedef AK::Algebraic_real_1 Algebraic_real_1;
typedef AK::Coefficient Coefficient;
typedef AK::Bound Bound;
typedef AK::Multiplicity_type Multiplicity_type;
int main(){
AK ak; // an object of
AK::Construct_algebraic_real_1 construct_algreal_1 = ak.construct_algebraic_real_1_object();
AK::Isolate_1 isolate_1 = ak.isolate_1_object();
AK::Compute_polynomial_1 compute_polynomial_1 = ak.compute_polynomial_1_object();
// construct an algebraic number from an integer
Algebraic_real_1 frominteger=construct_algreal_1(int(2));
std::cout << "Construct from int: " << frominteger << "\n";
// the constructed algebraic number is root of a polynomial
Polynomial_1 pol=compute_polynomial_1(frominteger);
std::cout << "The constructed number is root of: " << pol << "\n";
// construct an algebraic number from a polynomial and an isolating interval
Polynomial_1 x = CGAL::shift(AK::Polynomial_1(1),1); // the monomial x
Algebraic_real_1 frominterval=construct_algreal_1(x*x-2,Bound(0),Bound(2));
std::cout << "Construct from isolating interval: " << frominterval << "\n";
// isolate the second algebraic number from the first: this is to say,
// isolating the second algebraic number with respect to the polynomial
// of which the first constructed number is root
std::pair<Bound,Bound> isolation1 = isolate_1(frominterval,pol);
std::cout << "Isolating the second algebraic number gives: ["
<< isolation1.first << "," << isolation1.second << "]\n";
// isolate again the same algebraic number, this time with respect to
// the polynomial 10*x-14 (which has root 1.4, close to this algebraic
// number)
std::pair<Bound,Bound> isolation2 = isolate_1(frominterval,10*x-14);
std::cout << "Isolating again the second algebraic number gives: ["
<< isolation2.first << "," << isolation2.second << "]\n";
return 0;
}
#else
int main(){
std::cout << "This example requires CGAL to be configured with library MPFI." << std::endl;
return 0;
}
#endif

4.5 Interplay with Polynomials

The following example illustrates the sign evaluation of AlgebraicKernel_d_1::Algebraic_real_1 numbers in polynomials: 
File Algebraic_kernel_d/Sign_at_1.cpp

// $URL$
// $Id$
#include <CGAL/basic.h>
#ifdef CGAL_USE_MPFI
#include <CGAL/Algebraic_kernel_d_1.h>
#include <CGAL/Gmpz.h>
#include <vector>
typedef AK::Polynomial_1 Polynomial_1;
typedef AK::Algebraic_real_1 Algebraic_real_1;
typedef AK::Coefficient Coefficient;
typedef AK::Bound Bound;
typedef AK::Multiplicity_type Multiplicity_type;
int main(){
AK ak;
AK::Solve_1 solve_1 = ak.solve_1_object();
AK::Sign_at_1 sign_at_1 = ak.sign_at_1_object();
AK::Is_zero_at_1 is_zero_at_1 = ak.is_zero_at_1_object();
// construct the polynomials p=x^2-5 and q=x-2
Polynomial_1 x = CGAL::shift(AK::Polynomial_1(1),1); // the monomial x
Polynomial_1 p = x*x-5;
std::cout << "Polynomial p: " << p << "\n";
Polynomial_1 q = x-2;
std::cout << "Polynomial q: " << q << "\n";
// find the roots of p (it has two roots) and q (one root)
std::vector<Algebraic_real_1> roots_p,roots_q;
solve_1(p,true, std::back_inserter(roots_p));
solve_1(q,true, std::back_inserter(roots_q));
// evaluate the second root of p in q
std::cout << "Sign of the evaluation of root 2 of p in q: "
<< sign_at_1(q,roots_p[1]) << "\n";
// evaluate the root of q in p
std::cout << "Sign of the evaluation of root 1 of q in p: "
<< sign_at_1(p,roots_q[0]) << "\n";
// check whether the evaluation of the first root of p in p is zero
std::cout << "Is zero the evaluation of root 1 of p in p? "
<< is_zero_at_1(p,roots_p[0]) << "\n";
return 0;
}
#else
int main(){
std::cout << "This example requires CGAL to be configured with library MPFI." << std::endl;
return 0;
}
#endif