Polynomial ( Arithmetic and Algebra) CGAL 4.13 -User Manual

Fundamentals

polynomial is either zero, or can be written as the sum of one or more non-zero terms. The number of terms is finite. A term consist of a constant coefficient and a monomial, that is, the product of zero or more variables. Each variable may have an exponent that is a non-negative integer. The exponent on a variable in a term is equal to the degree of that variable in that term. A term with no variables is called a constant term. The degree of a constant term is 0.

For example, 7x^3*y is a term. The coefficient is 7, the monomial is x^3y, comprised of the variables x and y, the degree of x is three, and the degree of y is one. The total degree of the entire term is the sum of the degrees in each variable. In the example above, the degree is 3+1=4.

 

多项式可以是0或有限多个非0项(term)。一个项包含一个常系数和一个单项式。单项式是一个0个或多个变量的乘积,每个变量有一个非负整数指数。这个指数的值等于这项内该变量的“度”(degree)。常数的度是0.

如,−7x^3*y是一个项,其系数是-7,单项式是x^3y,,由两个变量x和y组成,x的度是3,y的度是1.该项的总度数是3+1=4。

 

A one-variable (univariate) polynomial f of degree n has the following form:

f=anx^n+(an1)x^(n1)+...+a2x^2+a1x+a0

The coefficient a0 is called the constant coefficientan is called the leading coefficient. If f is not the zero polynomial the leading coefficient is not zero. The polynomial is called monic if an=1. In case the coefficient domain of f possess a greatest common divisor (gcd) the content of f is the gcd of all coefficients of f. For instance, the content of 12x3+6 is 6.

 

一个n度的单个变量(univariate)多项式是:f=anx^n+(an1)x^(n1)+...+a2x^2+a1x+a0

a0被称为常系数。如果f不是0多项式,则其leading coefficient则非0。如果an=1,则该多项式被称为“首一多项式”。如果f多项式中的系数集中的元素存在GCD,我们称该GCD为Content

A multivariate polynomial is a polynomial in more than one variable. According to the number of variables it is possible to further classify multivariate polynomials as bivariate, trivariate etc. In contrast to univariate polynomials the terms of a multivariate polynomial are not completely ordered by their total degree. However, given a certain order on the variables it is possible to define a lexicographic order on the terms. Given this order the leading coefficient of a multivariate polynomial is defined as the coefficient of the highest term. For instance the leading coefficient of the multivariate polynomial p=5x3y+7xy2 is 7, given that y has an higher order than x.

一个多变量(multivariate)多项式可以分为2变量多项式、3变量多项式等。一个多变量多项式没有完全按其总度数排序。但给定一定的变量排序规则,则可能定义一个项的词典序。给定排序规则的多项式中,其leading系数被定义为度数最高的项系数。如:p=5x^3y+7xy^2中,如果定义y比x排序优先,则其leading系数为7。

 

However, it is also possible to interpret a multivariate polynomial as a univariate polynomial in that variable. For instance the trivariate polynomial

q=x5+7x2y1z2+13x1y2z2Z[x,y,z]

may be interpreted as a univariate polynomial in z, that is, q is interpreted as an element of R[z], with R=Z[x,y].

q=(13x1y2+7x2y1)z2+x5z0R[z]

 

In this case the leading coefficient of q with respect to z is 13x1y2+7x2y1 and x5 becomes the 'constant' term.

多变量多项式也可以看作其中一个变量的是单变量多项式。

homogeneous polynomial is a polynomial whose terms do all have the same total degree. For example, h=x5+7x2y1z2+13x1y2z2 is a homogeneous polynomial of degree 5, in three variables.

一个齐次多项式每个单项的总度数相等。

General Design

The package introduces a concept Polynomial_d, a concept for multivariate polynomials in d variables. Though the concept is written for an arbitrary number of variables, the number of variables is considered as fixed for a particular model of Polynomial_d. The concept also allows univariate polynomials.

First of all a model of Polynomial_d is considered as an algebraic structure, that is, the ring operations {+,,} are provided due to the fact that Polynomial_d refines at least the concept IntegralDomainWithoutDivision. However, a model of Polynomial_d has to be accompanied by a traits class Polynomial_traits_d<Polynomial_d> being a model of PolynomialTraits_d. This traits class provides all further functionalities on polynomials.

Given a d-variate polynomial over some base ring R there are at least two different possible views on such a polynomial.

  • The recursive or univariate view: In this view, a polynomial is considered as an element of R[x0,,xd2][xd1]. That is, the polynomial is treated as a univariate polynomial over the ring R[x0,,xd2].
  • The symmetric or multivariate view: This view is almost symmetric with respect to all variables. It considers the polynomial as an element of R[x0,,xd1].

According to these two different views the traits class is required to provide two different coefficient types:

  • Polynomial_traits_d::Coefficient_type representing R[x0,,xd2].
  • Polynomial_traits_d::Innermost_coefficient_type representing the base ring R.

Another important type which is introduced by this package is Exponent_vector. It is derived from std::vector<int> and used to identify multivariate monomials. For instance the exponent vector containing the sequence [3,2,4] corresponds to the trivariate monomial x30x21x42. Note that a vector with negative exponents is considered as invalid. However, we allow negative exponents as they may appear as intermediate results, in particular we did not derive from std::vector<unsigned int>.

此包引入了一个Polynomial_d概念,它表示一个具有d个变量元多多项式。虽然本概念为任意数量的变量所创建,但对于每个特定的d其变量的数量是固定的。这个概念也允许单变量多项式。

首先,Polynomial_d被认为是一个代数结构,于是f需要提供环操作(Ring operation){+,-, *},因为本概念至少精炼于IntegralDomainWithoutDivision.概念。一个Polynomial_d概念必须与一个traits类 Polynomial_traits_d<Polynomial_d>相伴随,这个trait类是概念PolynomialTraits_d.的模型。这个类提供了多项式的所有进一步操作。

给定在基本环(base ring)R上一个d变量的多项式,至少有两种视角来解释该多项式:

  • 回归的或单变量视角。一个多项式被看作是一个单变量多项式,其他变量被看作系数。即其term可表示为R[x0,,xd2][xd1],即一个环R[x0,,xd2]上的单变量多项式。
  • 对称的或多变量视角。这个视角对所有的变量几乎是对称的。它将多项式看作环R[x0,,xd1]的一个元素。

按照此观点,traits类必须提供两种不同的系数类型:

  • Polynomial_traits_d::Coefficient_type 表示 R[x0,,xd2].
  • Polynomial_traits_d::Innermost_coefficient_type 表示 base ring R.

另一个引入的重要的类型Exponent_vector。它是由std::vector<int> 扩展而来,用来识别多元单项式。如一个指数向量(exponent vector )包含序列[3,2,4]对应的3变量单项式为x03 *x12*x24。要注意的是向量中如果出现负的指数,将被认为是非法的。但是,我们仍然在中间结果中出现负的指数,特别是当这个向量不是从std::vector<unsigned int>.扩展来的。

Constructing a Multivariate Polynomial

First of all the concept Polynomial_d requires that the model is constructible from int. This is due to the fact that Polynomial_d refines IntegralDomainWithoutDivision which in turn refines FromIntConstructible. Of course this allows only the construction of constant polynomials.

In general a polynomial is constructed using the functor Polynomial_traits_d::Construct_polynomial a model of PolynomialTraits_d::ConstructPolynomial. Basically there are two options:

  • The polynomial is constructed from an iterator range with value type Polynomial_traits_d::Coefficient_type, where the begin iterator refers to the constant term (constant with respect to the outermost variable).
  • The polynomial is constructed from an iterator range with value type std::pair<Exponent_vector, Polynomial_traits_d::Innermost_coefficient_type>, where each pair defines the coefficient for the monomial defined by the exponent vector.

However, in some cases it might be more convenient to just construct the polynomials representing the different variables and to obtain the final polynomial using algebraic expressions. The most elegant way to construct a certain variable is Polynomial_traits_d::Shift being a model of PolynomialTraits_d::Shift.

Polynomial_d概念首先要求模型由int创建。这是由于Polynomial_d是精炼自IntegralDomainWithoutDivision,而IntegralDomainWithoutDivision又是精炼自FromIntConstructible.。这当然允许构造常数多项式。

通常,一个多项式使用PolynomialTraits_d::ConstructPolynomial概念的模型——函子Polynomial_traits_d::Construct_polynomial构造。一般有两种选择:

  • 使用类型由一个类型为Polynomial_traits_d::Coefficient_type的迭代器(terator range)构造,此时begin迭代器指向常数项(这一常数是相对于最外侧变量)。
  • 使用类型由一个类型为 std::pair<Exponent_vector, Polynomial_traits_d::Innermost_coefficient_type>的迭代器(terator range)构造,此时每个对(pair)定义由指数向量(exponent vector)定义的单项的系数。

在一些情况下,构造表示不同变量数的多项式最方便的方法是直接创建并通过代数表达式得到最后的多项式。创建一个变量最优雅的方法是通过Polynomial_traits_d::Shift,它是 PolynomialTraits_d::Shift一个模型。

3.1 Example

下面的例子是展示不同的2变量多项式的创建方法:

The following example illustrates different ways to construct a bivariate polynomial: 
File Polynomial/construction.cpp

#include <CGAL/Polynomial.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Polynomial_type_generator.h>
 
int main(){
 
typedef PT_2::Coefficient_type Poly_1;
typedef PT_2::Innermost_coefficient_type Integer;
 
PT_2::Construct_polynomial construct_polynomial;
Poly_2 dc;
 
 
// constructing a constant polynomial from int
Poly_2 two(2); // = 2
std::cout << "A constant polynomial: " << two << std::endl;
 
 
// construction from an iterator range of univariate polynomials
 
std::list<Poly_1> univariate_coeffs;
univariate_coeffs.push_back(Poly_1(3));
univariate_coeffs.push_back(Poly_1(0));
univariate_coeffs.push_back(Poly_1(5));
Poly_2 F = // 5*y^2 + 3
construct_polynomial(univariate_coeffs.begin(),univariate_coeffs.end());
std::cout << "The bivariate polynomial F: " << F << std::endl;
 
 
// construction from an iterator range over monomials
 
std::list<std::pair<CGAL::Exponent_vector, Integer> > innermost_coeffs;
innermost_coeffs.push_back(std::make_pair(CGAL::Exponent_vector(0,0),-2));
innermost_coeffs.push_back(std::make_pair(CGAL::Exponent_vector(3,5),2));
Poly_2 G = // (2*x^3)*y^5 + (-2)
construct_polynomial(innermost_coeffs.begin(),innermost_coeffs.end());
std::cout << "The bivariate polynomial G: " << G << std::endl;
 
//construction using shift
PT_2::Shift shift;
Poly_2 x = shift(Poly_2(1),1,0); // 'multiply' 1 by x_0^1  Poly_2(1)是系数,第2项1是指数,第3项0表示变量下标,这里是x0
Poly_2 y = shift(Poly_2(1),1,1); // 'multiply' 1 by x_1^1  Poly_2(1)是系数,第2项1是指数,第3项0表示变量下标,这里是x1
 
Poly_2 H = 5 * x * y + 3 * y * y; // = 3*y^2 + (5*x)*y
std::cout << "The bivariate polynomial H: " << H << std::endl;
}

 

Coefficient Access

In order to obtain a certain coefficient the traits class provides several functors. Note that the functors do not allow a write access to the coefficients.

traits类提供了多种方法来取得系数。注意:functor是不可写入系数的。

 

4.1 Example

The following example illustrates the application of the functors discussed above: 
File Polynomial/coefficient_access.cpp

#include <CGAL/Polynomial.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Polynomial_type_generator.h>
 
int main(){
 
//construction using shift
Poly_2 x = PT_2::Shift()(Poly_2(1),1,0); // = x^1
Poly_2 y = PT_2::Shift()(Poly_2(1),1,1); // = y^1
 
Poly_2 F // = (11*x^2 + 5*x)*y^4 + (7*x^2)*y^3
= 11 * CGAL::ipower(y,4) * CGAL::ipower(x,2)
+ 5 * CGAL::ipower(y,4) * CGAL::ipower(x,1)
+ 7 * CGAL::ipower(y,3) * CGAL::ipower(x,2);
std::cout << "The bivariate polynomial F: " << F <<"\n"<< std::endl;
 
PT_2::Get_coefficient get_coefficient;
std::cout << "Coefficient of y^0: "<< get_coefficient(F,0) << std::endl;
std::cout << "Coefficient of y^1: "<< get_coefficient(F,1) << std::endl;
std::cout << "Coefficient of y^2: "<< get_coefficient(F,2) << std::endl;
std::cout << "Coefficient of y^3: "<< get_coefficient(F,3) << std::endl;
std::cout << "Coefficient of y^4: "<< get_coefficient(F,4) << std::endl;
std::cout << "Coefficient of y^5: "<< get_coefficient(F,5) << std::endl;
std::cout << std::endl;
 
PT_2::Leading_coefficient lcoeff;
std::cout << "Leading coefficient with respect to y: "
<< lcoeff(F) // = 11*x^2 + 5*x
<< std::endl;
 
PT_2::Get_innermost_coefficient get_icoeff;
std::cout << "Innermost coefficient of monomial x^1y^4: "
<< get_icoeff(F,CGAL::Exponent_vector(1,4)) // = 5
<< std::endl;
 
PT_2::Innermost_leading_coefficient ilcoeff;
std::cout << "Innermost leading coefficient with respect to y: "
<< ilcoeff(F) // = 11
<< std::endl;
}
 

Degree, Total Degree and Degree Vector

There are three functors in PolynomialTraits_d related to the degree of a polynomial.

  • PolynomialTraits_d::Degree: a model of this concept returns the degree of the polynomial in the univariate view. By default this is the degree with respect to the outermost variable, but it is also possible to select another variable.
  • PolynomialTraits_d::TotalDegree: a model of this concept returns the total degree of a polynomial. The polynomial is considered as a multivariate polynomial. The total degree is the maximum over the sums of the exponents of each multivariate monomial.
  • PolynomialTraits_d::DegreeVector: a model of this concept returns the exponent vector of the leading monomial, where the monomial order is lexicographic and starts with the outermost variable. See also PolynomialTraits_d::InnermostLeadingCoefficient.
有三个PolynomialTraits_d 的函子与多项式的度有关:

5.1 Example

The following example illustrates the application of the functors discussed above: 
File Polynomial/degree.cpp

#include <CGAL/Polynomial.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Polynomial_type_generator.h>
 
int main(){
 
//construction using shift
Poly_2 x = PT_2::Shift()(Poly_2(1),1,0); // x_0^1
Poly_2 y = PT_2::Shift()(Poly_2(1),1,1); // x_1^1
 
Poly_2 F // = (11*x^2 + 5*x)*y^4 + (7*x^2)*y^3
= 11 * CGAL::ipower(y,4) * CGAL::ipower(x,2)
+ 5 * CGAL::ipower(y,4) * CGAL::ipower(x,1)
+ 7 * CGAL::ipower(y,3) * CGAL::ipower(x,2);
std::cout << "The bivariate polynomial F: " << F <<"\n"<< std::endl;
 
PT_2::Degree degree;
PT_2::Total_degree total_degree;
PT_2::Degree_vector degree_vector;
 
std::cout << "The degree of F with respect to y: "<< degree(F) // = 4
<< std::endl;
std::cout << "The degree of F with respect to x: "<< degree(F,0) // = 2
<< std::endl;
std::cout << "The total degree of F : "<< total_degree(F) // = 6
<< std::endl;
std::cout << "The degree vector of F : "<< degree_vector(F)// = (2,4)
<< std::endl;
}
 

Changing the Order of Variables

Given for instance a bivariate polynomial it is conceivable that one wants to interchange the role of x and y. That is one wants to interpret the x as y and vice versa. For such a case the polynomial traits provides PolynomialTraits_d::Swap:

Given a polynomial p and to two indices i and j, the functor returns the polynomial in which xi is substituted by xj and vice versa, that is, the variables swap their positions. The order of the other variables remains untouched.

Another scenario is, that a particular variable should be moved to another position, for instance, it should become the outermost variable while the relative order of the other variables remains unchanged. For such a case the polynomial traits provides PolynomialTraits_d::Move.

Of course there is also a general method to interchange the order of variables, namely PolynomialTraits_d::Permute.

给定一个2变量多项式,如果作者想交换其中x和y的角色,polynomial traits提供了PolynomialTraits_d::Swap来实现这一功能。
给定一个多项式p和两个序号i和j,此函子返回一个多项式,其中将p的xi和xj进行了互换,而其他变量没有变化。
另一个场景是:一个特定的变量需要被移动到另一个位置,如它将变为最外侧的(outmost)变量,其他变量位置不变。polynomial traits提供了 PolynomialTraits_d::Move来实现此功能。
 

6.1 Example

The following example illustrates the application of the functors discussed above: 
File Polynomial/swap_move.cpp

#include <CGAL/Polynomial.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Polynomial_type_generator.h>
 
int main(){
 
//construction using shift
Poly_3 x = PT_3::Shift()(Poly_3(1),1,0); // x_0^1
Poly_3 y = PT_3::Shift()(Poly_3(1),1,1); // x_1^1
Poly_3 z = PT_3::Shift()(Poly_3(1),1,2); // x_2^1
 
 
Poly_3 F = x*y*y*z*z*z;
std::cout << "The trivariate polynomial F: " << F << std::endl;
std::cout << std::endl;
 
PT_3::Swap swap;
PT_3::Move move;
PT_3::Permute permute;
 
std::cout << "x and z swapped: "<< swap(F,0,2) // = x^3*y^2*z
<< std::endl;
std::cout << "x and y swapped: "<< swap(F,0,1) // = x^2*y*z^3
<< std::endl << std::endl;
 
std::cout << "x moved to outermost position : "
<< move(F,0,2) // = x^2*y^3*z
<< std::endl;
std::cout << "Same as swap(swap(F,0,1),1,2) : "
<< swap(swap(F,0,1),1,2) // = x^2*y^3*z
<< std::endl;
 
std::cout << "Same as the permutation (0,1,2)->(2,0,1): ";
std::vector<int> perm;
perm.push_back(2);perm.push_back(0);perm.push_back(1);
std::cout << permute(F,perm.begin(),perm.end())// = x^2*y^3*z
<< std::endl;
 
}
 

GCD and More

Since the concept PolynomialTraits_d refines the concept AlgebraicStructureTraits the polynomial traits provides functors for integral division, division with remainder, greatest common divisor, etc. But note that the algebraic structure of a polynomial depends on the algebraic structure of the innermost coefficient, for instance, a gcd is available if and only if the innermost coefficient is a Field or a UniqueFactorizationDomain. Hence, we can not provide a gcd if the innermost coefficient is just an IntegralDomain since it is simply not well defined[1]. However, if we would consider the polynomial over the quotient field of the integral domain the gcd would be well defined. The only problem is that the result can not be represented over the ring since it contains denominators. Therefore, the PolynomialTraits_d requires functors such as PolynomialTraits_d::GcdUpToConstantFactor. This functor computes the gcd of two polynomials up to a constant factor (utcf). That is, it returns the correct gcd for polynomials over the quotient field, but multiplied by some constant such that the result is representable with coefficients in the ring.

However, note that these 'utcf' functions are usually a bit faster than their strict counterparts. This is due to the fact that the 'utcf' functions are allowed to skip the computation of the correct constant factor. Note that in many cases the constant factor is in fact not needed. In particular if the polynomials are supposed to represent some zero set, that is, an algebraic curve or surface.

 PolynomialTraits_d 概念精炼自 AlgebraicStructureTraits 概念,所以它提供了整数除法、带余数的除法和GCD等函子。请注意,多项式的代数结构依赖innermost coefficient(最内侧系数,即常数系数)的代数结构,如:当且仅当innermost coefficient 是一个Field(域) 或一个 UniqueFactorizationDomain时,才存在GCD所以,当innermost coefficient仅仅是 IntegralDomain时,我们不能提供GCD,因为它没有被很好地定义但是如果我们考虑在 IntegralDomain中的quotient域的多项式时,则GCD则是很好的定义的。仅有的问题是:结果可能不会在环上,因为它包含了一个分母。所以,PolynomialTraits_d 要求如PolynomialTraits_d::GcdUpToConstantFactor的函子。这个函子计算两个多项式的GCD向上到一个常数因子(This functor computes the gcd of two polynomials up to a constant factor (utcf))即,这个函子返回多项式在Quotient field(域)的正确的GCD,但这个GCD被乘以某个常数使其结果能够被环中的系数所表达(but multiplied by some constant such that the result is representable with coefficients in the ring.)。

但是,这些utcf函数通常会比他们严格的counterpart快一点。这是由于utcf函数允许跳过计算正确的常数因子。在很多情况下,因子实际上不需要,特别是当多项式用于表达0集合(zero set)时,如一个代数曲线或表面。

与这些函子相关的概念包括:

The concepts for the related functors are:

 

Another analog functionality is the pseudo division. The related functors replace the usual division with remainder in case the Polynomial is not a EuclideanRing.

The concepts for the related functors are:

另一个模拟的功能是“伪除法”。当 Polynomial 不是一个EuclideanRing(欧几里德环)时,相关的函子用remainder (余数)代替了通常的除法。

与这些函子相关的概念有:

7.1 Example

The following example illustrates the application of some functors discussed above: 
File Polynomial/gcd_up_to_constant_factor.cpp

#include <CGAL/Polynomial.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Polynomial_type_generator.h>
 
int main(){
 
PT_1::Shift shift;    //***!!!用于 生成单变量式
PT_1::Gcd gcd;     //GCD
PT_1::Gcd_up_to_constant_factor gcd_utcf;  //***!!!生成一个GCD的整倍数
PT_1::Multivariate_content mcontent;     //***!!!如果f多项式中的系数集的所有元素存在GCD,我们称该GCD为Content
PT_1::Canonicalize canonicalize;  //***!!!规范化(不知道是什么意思)可能是将其按照其度数从高到低或从低到高排列的形式
 
//construction using shift
Poly_1 x = shift(Poly_1(1),1,0); // x^1
 
// common factor 7 * (x^2-2)
Poly_1 F = 21*(x-5)*(x*x-2); // = 21*x^3 + (-105)*x^2 + (-42)*x + 210
Poly_1 G = 14*(x-3)*(x*x-2); // = 14*x^3 + (-42)*x^2 + (-28)*x + 84
 
std::cout << "The univariate polynomial F: " << F << std::endl;
std::cout << "The univariate polynomial G: " << G << std::endl;
std::cout << "Common multivariate content: "
<< CGAL::gcd(mcontent(F),mcontent(G)) // = 7
<< std::endl;
std::cout << "The gcd of F and G: "
<< gcd(F,G)          // = 7*x^2 + (-14)
<< std::endl;
std::cout << "The gcd up to constant factor of F and G: "
<< gcd_utcf(F,G) // = x^2 + (-2)
<< std::endl;
std::cout << "Same as canonicalized gcd of F and G: "
<< canonicalize(gcd_utcf(F,G)) // = x^2 + (-2)
<< std::endl;
 
}

 

Evaluation and Substitution

Of course, it should also be possible to evaluate a polynomial or substitute its variables. We also require a special functor to determine whether a polynomial is zero at a given point. In case the inner most coefficient is RealEmbeddable the traits also must provide a function to compute the sign at a given point.

The concepts for the related functors are:

The traits is also required to provide variants of these functors that interpret the polynomial as a homogeneous polynomial by adding a virtual homogeneous variable such that each term has the same degree, namely the degree of the polynomial. Of course there is a difference between the univariate and multivariate view. For instance the polynomial

5x^3+7x3

has degree 3, hence it is interpreted as the homogeneous polynomial

5x^3+7xw^23w^3

by adding the homogeneous variable w. In case of the multivariate view each term is filled up by the homogeneous variable such that the degree of each term is equal to the total degree of the polynomial.

Note that these functors may significantly improve efficiency. For instance, it is possible to determine the sign of a polynomial over integer coefficients at a rational point without changing the coefficient domain of the polynomial. For more details have a look at the following concepts:

评估一个多项式或替换其中的变量也是需要考虑的。我们也要求提供一个特别的函子要判断一个多项式在给定的点是否为0值。当最内侧的系数值是RealEmbeddable 时,traits必须能够提供一个函子来确定一个给定点的符号。

与这些函子相关的概念有:

 

traits也要求提供这些函子的变种,通过增加一个虚拟的齐次变量,使每一项具有相同的度(这个度成为多项式的度),这样将多项式转换为齐次多项式。当然,单变量多项式和多变量视角存在一个不同点。 一个多项式:

5x^3+7x3,具有3度。加入了一个齐次变量w将其转换为齐次多项式:5x^3+7xw^23w^3。

在多变量视角情况下,每项加入齐次变量使它的度等于多项式的总度。值得注意的是:这些函子可能会大大提高效率。如:在一个有理数点计算一个整数系数多项式的符号时,可以不改变系数的定义域(domain)(it is possible to determine the sign of a polynomial over integer coefficients at a rational point without changing the coefficient domain of the polynomial. For more details have a look at the following concepts:)。下面的概念提供了更多细节:

Note that substitute allows the substitution of the variables by any type that is ExplicitInteroperable with the innermost coefficient type. This is a very powerful tool since it allows the substitution of the variables by polynomials. However, for some standard manipulations such as translation or scaling we require special functors since they are expected to be faster than their equivalent implementation using substitution:

注意:这样的替换操作允许使用与最内侧系数( innermost coefficient ,即常系数)类型可实现显示互操作的所有类型进行变量的替换。这是非常强大的工具,因为它允许用多项式来替换变量。

但是,我们需要一些特殊的函子来执行一些标准的操作,如转换或缩放。这样我们希望这些函子要快于基于替换的同样操作的实现。它们有:

8.1 Example

The following example illustrates the application of some functors discussed above: 
File Polynomial/substitute.cpp

#include <CGAL/Polynomial.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Polynomial_type_generator.h>
 
int main(){
 
//construction using shift
Poly_2 x = PT_2::Shift()(Poly_2(1),1,0); // x^1
Poly_2 y = PT_2::Shift()(Poly_2(1),1,1); // y^1
 
 
Poly_2 F = 2*x*y + 3*CGAL::ipower(y,3);
std::cout << "The bivariate polynomial F: " << F // = 3*y^3 + (2*x)*y
<< std::endl << std::endl;
 
PT_2::Evaluate evaluate;
PT_2::Evaluate_homogeneous hevaluate;
 
// Evaluation considers a polynomials as univariate:
std::cout << "F(5): " << evaluate(F,5) // = 10*x + 375
<< std::endl;
// Evaluate_homogeneous considers F as a homogeneous polynomial in
// the outermost variable only, that is, F is interpreted as
// F(u,v) = 2*x*u*v^2 + 3 * u^3
std::cout << "F(5,7): " << hevaluate(F,5,7) // = 490*x + 375
<< std::endl << std::endl;
 
 
PT_2::Substitute substitute;
PT_2::Substitute_homogeneous hsubstitute;
 
// Substitute considers a polynomials as multivariate, that is, the
// new values for the variables are given by an iterator range
// Note that the value type only has to be interoperable with the innermost
// coefficient
std::list<Poly_2> replacements;
replacements.push_back(x-1); // replace x by x-1
replacements.push_back(y); // replace y by y, i.e., do nothing
 
std::cout << "The bivariate polynomial F: " << F // = 3*y^3 + (2*x)*y
<< std::endl;
std::cout << "F(x-1,y): " // = 3*y^3 + (2*x + (-2))*y
<< substitute(F,replacements.begin(),replacements.end())    //***!!!用x-1替换x
<< std::endl;
// Substitute_homogeneous considers F as a homogeneous polynomial in
// all variable, that is, F is interpreted as
// F(x,y,w) = 2*x*y*w + 3 * y^3
replacements.push_back(y); // replace z by y
 
std::cout << "F(x-1,y,y): " // = 3*y^3 + (2*x + (-2))*y^2
<< hsubstitute(F,replacements.begin(),replacements.end())
<< std::endl;
}
 

Resultants, Subresultants and Sturm-Habicht Sequences(结式,子结式及Sturm-Habicht序列)

结式(eliminant或resultant)是代数学术语,指由两个多项式的系数所构成的一种行列式,或称Sylvester行列式,结式可判断两个多项式是否有公根、是否互素,以及判断多项式是否有重根

The PolynomialTraits_d concept also provides more sophisticated functors for computations with polynomials - computing the resultant of two polynomials, their polynomial subresultant sequence, with or without cofactors, and their principal subresultant coefficients.

PolynomialTraits_d概念提供了多项式的更多的复杂的函子。计算两个多项式的结式、计算其多项式子结式序列、代数余子式和他们的基本子结式的系数。

Moreover, functors to compute the Sturm-Habicht sequence, with or without cofactors, and for the principal Sturm-Habicht coefficients exist.

For a formal definition of all used terms, we refer to the corresponding reference pages.

另外,计算Sturm-Habicht序列的函子(或仿函数),带或不带余子式时,以及主Sturm-Habicht因子存在时的方法如下:

上面所有术语的形式化定义在相应的参考页给出。

The principal Sturm-Habicht sequence allows to count the number of real roots of a polynomial using the function

As input, this function requires an iterator range that represents the principal Sturm-Habicht coefficients. This might look complicated at a first sight, as one has to store the principal Sturm-Habicht sequence temporarily. However, we remark an important property of the (principal) Sturm-Habicht sequence. Having a polynomial ft(x) that depends on a parameter t, and its (principal) Sturm-Habicht coefficients stha0(ft),,sthan(ft), evaluating stha0(ft) for t=t0 yields a valid (principal) Sturm-Habicht sequence for ft0. The same holds for (principal) subresultants. Thus, it is enough in such situations to compute the sequence once for the parameter t, and call number_of_real_roots() for each specialized parameter value.

We finally remark that computing subresultants and Sturm-Habicht sequences introduces an enormous coefficient blow-up. An application of the functors therefore does not make sense for built-in integers except for toy examples. To avoid overflows, one should use arbitrary size integer types in real applications.

主Sturm-Habicht序列可以用下面的函数来计算一个多项式的实数根的个数:

这个函数要求一个表示Sturm-Habicht系数序列的迭代器作为输入。最初看上去有点复杂,因为要将主Sturm-Habicht 序列进行暂存。但我们注意到Sturm-Habicht序列的一个重要的性质。考虑一个依赖参数t的多项式ft(x),它的(主)Sturm-Habicht系数为 stha0(ft),,sthan(ft),  当t=t0时对stha0(ft) 求值生成一个ft0 的合法的Sturm-Habicht 序列。这对于  (principal) subresultants同样成立。这种条件对于计算参数t的序列和对每个特定参数值调用number_of_real_roots() 是足够的(Thus, it is enough in such situations to compute the sequence once for the parameter t, and call number_of_real_roots() for each specialized parameter value)。

最后需要注意的是:对subresultants和 Sturm-Habicht sequences的计算可能引入很多的系数放大(blow-up)。于是使用这些函数的应用除了toy examples就没法搞清内置整数( An application of the functors therefore does not make sense for built-in integers except for toy examples.),为解决这一问题,我们在实际应用中应当使用任意精度整数(arbitrary size integer)类型

9.1 Example

The following example illustrates how two compute resultants of two polynomials, and how to count the number of distinct real roots of a polynomial using its principal Sturm-Habicht coefficients.


File Polynomial/subresultants.cpp

#include <CGAL/Polynomial.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Polynomial_type_generator.h>
 
#include <CGAL/Exact_integer.h>
 
int main(){
 
typedef CGAL::Exact_integer Int;
 
 
//construction using shift
Poly_1 x = PT_1::Shift()(Poly_1(1),1); // x^1
 
Poly_1 F // = (x+1)^2*(x-1)*(2x-1)=2x^4+x^3-3x^2-x+1
= 2 * CGAL::ipower(x,4) + 1 * CGAL::ipower(x,3)
- 3 * CGAL::ipower(x,2) - 1 * CGAL::ipower(x,1)
+ 1 * CGAL::ipower(x,0);
std::cout << "F=" << F << std::endl;
 
Poly_1 G // = (x+1)*(x+3)=x^2+4*x+3
= 1 * CGAL::ipower(x,2) + 4 * CGAL::ipower(x,1) + 3 * CGAL::ipower(x,0);
std::cout << "G=" << G << std::endl;
 
// Resultant computation:
PT_1::Resultant resultant;
 
std::cout << "The resultant of F and G is: " << resultant(F,G) << std::endl;
// It is zero, because F and G have a common factor
 
// Real root counting:
PT_1::Principal_sturm_habicht_sequence stha;
std::vector<Int> psc;
 
stha(F,std::back_inserter(psc));
 
int roots = CGAL::number_of_real_roots(psc.begin(),psc.end());
 
std::cout << "The number of real roots of F is: " << roots << std::endl; // 3
 
 
std::cout << "The number of real roots of G is: " << roots << std::endl; // 2
 
return 0;
 
}
resultant
posted @ 2018-11-18 12:02  小船1968  阅读(675)  评论(0编辑  收藏  举报