2197 | | |
| 2197 | |
| 2198 | @require_field |
| 2199 | def _normal_basis_libsingular(self): |
| 2200 | r""" |
| 2201 | Returns the normal basis for a given groebner basis. It will use |
| 2202 | the Groebner Basis as computed by |
| 2203 | ``MPolynomialIdeal._groebner_basis_libsingular()``. |
| 2204 | |
| 2205 | EXAMPLES:: |
| 2206 | |
| 2207 | sage: R.<x,y,z> = PolynomialRing(QQ) |
| 2208 | sage: I = R.ideal(x^2-2*x*z+5, x*y^2+y*z+1, 3*y^2-8*x*z) |
| 2209 | sage: I.normal_basis() |
| 2210 | [z^2, y*z, x*z, z, x*y, y, x, 1] |
| 2211 | """ |
| 2212 | from sage.rings.polynomial.multi_polynomial_ideal_libsingular import kbase_libsingular |
| 2213 | gb = self._groebner_basis_libsingular() |
| 2214 | |
| 2215 | return kbase_libsingular(self.ring().ideal(gb)) |
| 2216 | |
| 2217 | @require_field |
| 2218 | def normal_basis(self, algorithm='libsingular', singular=singular_default): |
| 2219 | """ |
| 2220 | Returns a vector space basis (consisting of monomials) of the |
| 2221 | quotient ring by the ideal, resp. of a free module by the module, |
| 2222 | in case it is finite dimensional and if the input is a standard |
| 2223 | basis with respect to the ring ordering. |
| 2224 | |
| 2225 | INPUT: algorithm - defaults to use libsingular, if it is anything |
| 2226 | else we will use the kbase() command |
| 2227 | |
| 2228 | EXAMPLES:: |
| 2229 | |
| 2230 | sage: R.<x,y,z> = PolynomialRing(QQ) |
| 2231 | sage: I = R.ideal(x^2+y^2+z^2-4, x^2+2*y^2-5, x*z-1) |
| 2232 | sage: I.normal_basis() |
| 2233 | [y*z^2, z^2, y*z, z, x*y, y, x, 1] |
| 2234 | sage: I.normal_basis(algorithm='singular') |
| 2235 | [y*z^2, z^2, y*z, z, x*y, y, x, 1] |
| 2236 | """ |
| 2237 | |
| 2238 | if algorithm == 'libsingular': |
| 2239 | return self._normal_basis_libsingular() |
| 2240 | else: |
| 2241 | gb = self.groebner_basis() |
| 2242 | return list(singular.kbase(self.ring().ideal(gb))) |
| 2243 | |
2915 | | from sage.rings.polynomial.multi_polynomial_ideal_libsingular import kbase_libsingular |
2916 | | gb = self._groebner_basis_libsingular() |
2917 | | |
2918 | | return kbase_libsingular(self.ring().ideal(gb)) |
2919 | | |
2920 | | @require_field |
2921 | | def normal_basis(self, algorithm='libsingular', singular=singular_default): |
| 2949 | Return the degree of semi-regularity of this ideal under the |
| 2950 | assumption that it is semi-regular. |
| 2951 | |
| 2952 | Let `\{f_1, ... , f_m\} \subset K[x_1 , ... , x_n]` be |
| 2953 | homogeneous polynomials of degrees `d_1,... ,d_m` |
| 2954 | respectively. This sequence is semi-regular if: |
| 2955 | |
| 2956 | * `\{f_1, ... , f_m\} \neq K[x_1 , ... , x_n]` |
| 2957 | |
| 2958 | * for all `1 \leq i \leq m` and `g \in K[x_1,\dots,x_n]`: |
| 2959 | `deg(g \cdot pi ) < D` and |
| 2960 | `g \cdot f_i \in <f_1 , \dots , f_{i−1>` implies that |
| 2961 | `g \in <f_1, ..., f_{i−1}>` where `D` is the degree of regularity. |
| 2962 | |
| 2963 | This notion can be extended to afﬁne polynomials by |
| 2964 | considering their homogeneous components of highest degree. |
| 2965 | |
| 2966 | The degree of regularity of a semi-regular sequence |
| 2967 | `f_1, ...,f_m` of respective degrees `d_1,...,d_m` is given by the |
| 2968 | index of the ﬁrst non-positive coefficient of: |
| 2969 | |
| 2970 | `\sum c_k z^k = \frac{\prod (1 − z^{d_i})}{(1-z)^n}` |
| 2971 | |
| 2972 | EXAMPLE: |
| 2973 | |
| 2974 | We consider a homogeneous example:: |
| 2975 | |
| 2976 | sage: n = 8 |
| 2977 | sage: K = GF(127) |
| 2978 | sage: P = PolynomialRing(K,n,'x') |
| 2979 | sage: s = [K.random_element() for _ in range(n)] |
| 2980 | sage: L = [] |
| 2981 | sage: for i in range(2*n): |
| 2982 | ... f = P.random_element(degree=2, terms=binomial(n,2)) |
| 2983 | ... f -= f(*s) |
| 2984 | ... L.append(f.homogenize()) |
| 2985 | sage: I = Ideal(L) |
| 2986 | sage: I.degree_of_semi_regularity() |
| 2987 | 4 |
| 2988 | |
| 2989 | From this, we expect a Groebner basis computation to reach at |
| 2990 | most degree 4. For homogeneous systems this is equivalent to |
| 2991 | the largest degree in the Groebner basis:: |
| 2992 | |
| 2993 | sage: max(f.degree() for f in I.groebner_basis()) |
| 2994 | 4 |
| 2995 | |
| 2996 | We increase the number of polynomials and observe a decrease |
| 2997 | the degree of regularity:: |
| 2998 | |
| 2999 | sage: for i in range(2*n): |
| 3000 | ... f = P.random_element(degree=2, terms=binomial(n,2)) |
| 3001 | ... f -= f(*s) |
| 3002 | ... L.append(f.homogenize()) |
| 3003 | sage: I = Ideal(L) |
| 3004 | sage: I.degree_of_semi_regularity() |
| 3005 | 3 |
| 3006 | |
| 3007 | sage: max(f.degree() for f in I.groebner_basis()) |
| 3008 | 3 |
| 3009 | |
| 3010 | The degree of regularity approaches 2 for quadratic systems as |
| 3011 | the number of polynomials approaches `n^2`:: |
| 3012 | |
| 3013 | sage: for i in range((n-4)*n): |
| 3014 | ... f = P.random_element(degree=2, terms=binomial(n,2)) |
| 3015 | ... f -= f(*s) |
| 3016 | ... L.append(f.homogenize()) |
| 3017 | sage: I = Ideal(L) |
| 3018 | sage: I.degree_of_semi_regularity() |
| 3019 | 2 |
| 3020 | |
| 3021 | sage: max(f.degree() for f in I.groebner_basis()) |
| 3022 | 2 |
| 3023 | |
| 3024 | .. note:: |
| 3025 | |
| 3026 | It is unknown whether semi-regular sequences |
| 3027 | exist. However, it is expected that random systems are |
| 3028 | semi-regular sequences. For more details about |
| 3029 | semi-regular sequences see [BFS04]_. |
| 3030 | |
| 3031 | REFERENCES: |
| 3032 | |
| 3033 | .. [BFS04] Magali Bardet, Jean-Charles Faugère, and Bruno |
| 3034 | Salvy, On the complexity of Groebner basis computation of |
| 3035 | semi-regular overdetermined algebraic equations. |
| 3036 | Proc. International Conference on Polynomial System Solving |
| 3037 | (ICPSS), pp. 71–75, 2004. |
| 3038 | |
2923 | | Returns a vector space basis (consisting of monomials) of the |
2924 | | quotient ring by the ideal, resp. of a free module by the module, |
2925 | | in case it is finite dimensional and if the input is a standard |
2926 | | basis with respect to the ring ordering. |
2927 | | |
2928 | | INPUT: algorithm - defaults to use libsingular, if it is anything |
2929 | | else we will use the kbase() command |
2930 | | |
2931 | | EXAMPLES:: |
2932 | | |
2933 | | sage: R.<x,y,z> = PolynomialRing(QQ) |
2934 | | sage: I = R.ideal(x^2+y^2+z^2-4, x^2+2*y^2-5, x*z-1) |
2935 | | sage: I.normal_basis() |
2936 | | [y*z^2, z^2, y*z, z, x*y, y, x, 1] |
2937 | | sage: I.normal_basis(algorithm='singular') |
2938 | | [y*z^2, z^2, y*z, z, x*y, y, x, 1] |
2939 | | """ |
2940 | | |
2941 | | if algorithm == 'libsingular': |
2942 | | return self._normal_basis_libsingular() |
| 3040 | degs = [f.degree() for f in self.gens() if f!=0] # we ignore zeroes |
| 3041 | m, n = self.ngens(), len(set(sum([f.variables() for f in self.gens()],()))) |
| 3042 | if m <= n: |
| 3043 | raise ValueError("This function requires an overdefined system of polynomials.") |
| 3044 | |
| 3045 | from sage.rings.all import QQ |
| 3046 | from sage.misc.misc_c import prod |
| 3047 | from sage.rings.power_series_ring import PowerSeriesRing |
| 3048 | |
| 3049 | R,z = PowerSeriesRing(QQ,'z', default_prec=sum(degs)).objgen() |
| 3050 | dreg = 0 |
| 3051 | s = prod([1-z**d for d in degs]) / (1-z)**n |
| 3052 | for dreg in xrange(0,sum(degs)): |
| 3053 | if s[dreg] < 0: |
| 3054 | return ZZ(dreg) |